From ab1393a4788d753a9ceceaa4a0a9809a5c560100 Mon Sep 17 00:00:00 2001 From: Julian Gilbey Date: Mon, 5 Sep 2022 21:56:24 +0100 Subject: [PATCH 1/1] Import pydevd_2.8.0+git20220826.8ee4065+ds.orig.tar.xz [dgit import orig pydevd_2.8.0+git20220826.8ee4065+ds.orig.tar.xz] --- .github/install_and_run_debug_py.sh | 35 + .github/workflows/pydevd-tests-python.yml | 117 + .gitignore | 39 + .project | 17 + .pydevproject | 34 + .settings/org.eclipse.core.resources.prefs | 45 + .settings/org.python.pydev.yaml | 47 + LICENSE | 203 + MANIFEST.in | 8 + README.rst | 37 + _pydev_bundle/__init__.py | 0 _pydev_bundle/_pydev_calltip_util.py | 155 + _pydev_bundle/_pydev_completer.py | 267 + _pydev_bundle/_pydev_execfile.py | 14 + _pydev_bundle/_pydev_filesystem_encoding.py | 41 + _pydev_bundle/_pydev_getopt.py | 130 + _pydev_bundle/_pydev_imports_tipper.py | 373 + _pydev_bundle/_pydev_jy_imports_tipper.py | 492 + _pydev_bundle/_pydev_log.py | 24 + _pydev_bundle/_pydev_saved_modules.py | 110 + _pydev_bundle/_pydev_sys_patch.py | 73 + _pydev_bundle/_pydev_tipper_common.py | 52 + _pydev_bundle/fsnotify/__init__.py | 353 + _pydev_bundle/pydev_console_utils.py | 639 + _pydev_bundle/pydev_import_hook.py | 40 + _pydev_bundle/pydev_imports.py | 13 + _pydev_bundle/pydev_ipython_console.py | 97 + _pydev_bundle/pydev_ipython_console_011.py | 516 + _pydev_bundle/pydev_is_thread_alive.py | 23 + _pydev_bundle/pydev_localhost.py | 67 + _pydev_bundle/pydev_log.py | 276 + _pydev_bundle/pydev_monkey.py | 1190 + _pydev_bundle/pydev_monkey_qt.py | 216 + _pydev_bundle/pydev_override.py | 35 + _pydev_bundle/pydev_umd.py | 180 + _pydev_bundle/pydev_versioncheck.py | 16 + _pydev_runfiles/__init__.py | 0 _pydev_runfiles/pydev_runfiles.py | 857 + _pydev_runfiles/pydev_runfiles_coverage.py | 76 + _pydev_runfiles/pydev_runfiles_nose.py | 207 + _pydev_runfiles/pydev_runfiles_parallel.py | 267 + .../pydev_runfiles_parallel_client.py | 214 + _pydev_runfiles/pydev_runfiles_pytest2.py | 306 + _pydev_runfiles/pydev_runfiles_unittest.py | 150 + _pydev_runfiles/pydev_runfiles_xml_rpc.py | 257 + _pydevd_bundle/__init__.py | 0 _pydevd_bundle/_debug_adapter/__init__.py | 0 ...main__pydevd_gen_debug_adapter_protocol.py | 592 + .../_debug_adapter/debugProtocol.json | 4084 ++ .../_debug_adapter/debugProtocolCustom.json | 325 + .../_debug_adapter/pydevd_base_schema.py | 147 + .../_debug_adapter/pydevd_schema.py | 19514 +++++++ .../_debug_adapter/pydevd_schema_log.py | 46 + _pydevd_bundle/pydevconsole_code.py | 554 + .../pydevd_additional_thread_info.py | 19 + .../pydevd_additional_thread_info_regular.py | 153 + _pydevd_bundle/pydevd_api.py | 1140 + _pydevd_bundle/pydevd_breakpoints.py | 184 + _pydevd_bundle/pydevd_bytecode_utils.py | 843 + _pydevd_bundle/pydevd_code_to_source.py | 611 + .../pydevd_collect_bytecode_info.py | 925 + _pydevd_bundle/pydevd_comm.py | 1823 + _pydevd_bundle/pydevd_comm_constants.py | 208 + .../pydevd_command_line_handling.py | 183 + .../pydevd_concurrency_analyser/__init__.py | 0 .../pydevd_concurrency_logger.py | 346 + .../pydevd_thread_wrappers.py | 83 + _pydevd_bundle/pydevd_console.py | 270 + _pydevd_bundle/pydevd_constants.py | 787 + _pydevd_bundle/pydevd_custom_frames.py | 116 + _pydevd_bundle/pydevd_cython.c | 43164 ++++++++++++++++ _pydevd_bundle/pydevd_cython.pxd | 27 + _pydevd_bundle/pydevd_cython.pyx | 1870 + _pydevd_bundle/pydevd_cython_wrapper.py | 52 + _pydevd_bundle/pydevd_daemon_thread.py | 193 + _pydevd_bundle/pydevd_defaults.py | 8 + _pydevd_bundle/pydevd_dont_trace.py | 123 + _pydevd_bundle/pydevd_dont_trace_files.py | 153 + _pydevd_bundle/pydevd_exec2.py | 5 + _pydevd_bundle/pydevd_extension_api.py | 87 + _pydevd_bundle/pydevd_extension_utils.py | 67 + _pydevd_bundle/pydevd_filtering.py | 331 + _pydevd_bundle/pydevd_frame.py | 1239 + _pydevd_bundle/pydevd_frame_utils.py | 302 + _pydevd_bundle/pydevd_gevent_integration.py | 93 + _pydevd_bundle/pydevd_import_class.py | 68 + _pydevd_bundle/pydevd_io.py | 258 + _pydevd_bundle/pydevd_json_debug_options.py | 196 + _pydevd_bundle/pydevd_net_command.py | 146 + .../pydevd_net_command_factory_json.py | 474 + .../pydevd_net_command_factory_xml.py | 493 + _pydevd_bundle/pydevd_plugin_utils.py | 91 + _pydevd_bundle/pydevd_process_net_command.py | 757 + .../pydevd_process_net_command_json.py | 1311 + _pydevd_bundle/pydevd_referrers.py | 257 + _pydevd_bundle/pydevd_reload.py | 433 + _pydevd_bundle/pydevd_resolver.py | 723 + _pydevd_bundle/pydevd_safe_repr.py | 399 + _pydevd_bundle/pydevd_save_locals.py | 96 + _pydevd_bundle/pydevd_signature.py | 201 + _pydevd_bundle/pydevd_source_mapping.py | 153 + _pydevd_bundle/pydevd_stackless.py | 416 + _pydevd_bundle/pydevd_suspended_frames.py | 533 + _pydevd_bundle/pydevd_thread_lifecycle.py | 96 + _pydevd_bundle/pydevd_timeout.py | 239 + _pydevd_bundle/pydevd_trace_api.py | 62 + _pydevd_bundle/pydevd_trace_dispatch.py | 62 + .../pydevd_trace_dispatch_regular.py | 490 + _pydevd_bundle/pydevd_traceproperty.py | 92 + _pydevd_bundle/pydevd_utils.py | 511 + _pydevd_bundle/pydevd_vars.py | 839 + _pydevd_bundle/pydevd_vm_type.py | 41 + _pydevd_bundle/pydevd_xml.py | 399 + _pydevd_frame_eval/.gitignore | 3 + _pydevd_frame_eval/__init__.py | 0 .../pydevd_frame_eval_cython_wrapper.py | 43 + _pydevd_frame_eval/pydevd_frame_eval_main.py | 48 + _pydevd_frame_eval/pydevd_frame_evaluator.c | 20595 ++++++++ _pydevd_frame_eval/pydevd_frame_evaluator.pxd | 131 + .../pydevd_frame_evaluator.template.pyx | 613 + _pydevd_frame_eval/pydevd_frame_tracing.py | 122 + _pydevd_frame_eval/pydevd_modify_bytecode.py | 365 + _pydevd_frame_eval/release_mem.h | 5 + build_tools/build.py | 175 + build_tools/build_binaries_osx.py | 60 + build_tools/build_binaries_windows.py | 91 + build_tools/check_no_git_modifications.py | 32 + build_tools/generate_code.py | 228 + build_tools/names_to_rename.py | 318 + build_tools/pydevd_release_process.txt | 216 + build_tools/rename_pep8.py | 131 + conftest.py | 369 + gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 160 + gradlew.bat | 90 + interpreterInfo.py | 255 + pycompletionserver.py | 372 + pydev_app_engine_debug_startup.py | 21 + pydev_coverage.py | 94 + pydev_ipython/README | 8 + pydev_ipython/__init__.py | 0 pydev_ipython/inputhook.py | 592 + pydev_ipython/inputhookglut.py | 154 + pydev_ipython/inputhookgtk.py | 36 + pydev_ipython/inputhookgtk3.py | 35 + pydev_ipython/inputhookpyglet.py | 92 + pydev_ipython/inputhookqt4.py | 196 + pydev_ipython/inputhookqt5.py | 199 + pydev_ipython/inputhooktk.py | 23 + pydev_ipython/inputhookwx.py | 169 + pydev_ipython/matplotlibtools.py | 149 + pydev_ipython/qt.py | 23 + pydev_ipython/qt_for_kernel.py | 119 + pydev_ipython/qt_loaders.py | 301 + pydev_ipython/version.py | 36 + pydev_pysrc.py | 1 + pydev_run_in_console.py | 153 + .../__not_in_default_pythonpath.txt | 1 + pydev_sitecustomize/sitecustomize.py | 237 + pydevconsole.py | 603 + pydevd.py | 3461 ++ pydevd_attach_to_process/README.txt | 27 + .../_always_live_program.py | 32 + pydevd_attach_to_process/_check.py | 2 + .../_test_attach_to_process.py | 9 + .../_test_attach_to_process_linux.py | 74 + .../add_code_to_python_process.py | 606 + pydevd_attach_to_process/attach_pydevd.py | 73 + pydevd_attach_to_process/attach_script.py | 184 + .../common/py_custom_pyeval_settrace.hpp | 193 + .../common/py_custom_pyeval_settrace_310.hpp | 113 + .../common/py_custom_pyeval_settrace_311.hpp | 120 + .../py_custom_pyeval_settrace_common.hpp | 62 + .../common/py_settrace.hpp | 193 + pydevd_attach_to_process/common/py_utils.hpp | 84 + .../common/py_version.hpp | 90 + pydevd_attach_to_process/common/python.h | 704 + pydevd_attach_to_process/common/ref_utils.hpp | 63 + .../linux_and_mac/.gitignore | 4 + .../linux_and_mac/attach.cpp | 111 + .../linux_and_mac/compile_linux.sh | 9 + .../linux_and_mac/compile_mac.sh | 5 + .../linux_and_mac/compile_manylinux.cmd | 10 + .../linux_and_mac/lldb_prepare.py | 54 + .../winappdbg/__init__.py | 263 + .../winappdbg/breakpoint.py | 4822 ++ pydevd_attach_to_process/winappdbg/compat.py | 183 + pydevd_attach_to_process/winappdbg/crash.py | 1853 + pydevd_attach_to_process/winappdbg/debug.py | 1543 + pydevd_attach_to_process/winappdbg/disasm.py | 722 + pydevd_attach_to_process/winappdbg/event.py | 1869 + .../winappdbg/interactive.py | 2242 + pydevd_attach_to_process/winappdbg/module.py | 2016 + pydevd_attach_to_process/winappdbg/process.py | 5021 ++ .../winappdbg/registry.py | 695 + pydevd_attach_to_process/winappdbg/search.py | 665 + pydevd_attach_to_process/winappdbg/sql.py | 993 + pydevd_attach_to_process/winappdbg/system.py | 1297 + pydevd_attach_to_process/winappdbg/textio.py | 1879 + pydevd_attach_to_process/winappdbg/thread.py | 2127 + pydevd_attach_to_process/winappdbg/util.py | 1038 + .../winappdbg/win32/__init__.py | 72 + .../winappdbg/win32/advapi32.py | 3209 ++ .../winappdbg/win32/context_amd64.py | 762 + .../winappdbg/win32/context_i386.py | 449 + .../winappdbg/win32/dbghelp.py | 1277 + .../winappdbg/win32/defines.py | 718 + .../winappdbg/win32/gdi32.py | 507 + .../winappdbg/win32/kernel32.py | 4716 ++ .../winappdbg/win32/ntdll.py | 539 + .../winappdbg/win32/peb_teb.py | 3435 ++ .../winappdbg/win32/psapi.py | 387 + .../winappdbg/win32/shell32.py | 382 + .../winappdbg/win32/shlwapi.py | 756 + .../winappdbg/win32/user32.py | 1727 + .../winappdbg/win32/version.py | 1038 + .../winappdbg/win32/wtsapi32.py | 337 + pydevd_attach_to_process/winappdbg/window.py | 759 + pydevd_attach_to_process/windows/attach.cpp | 634 + pydevd_attach_to_process/windows/attach.h | 57 + .../windows/compile_windows.bat | 39 + .../windows/inject_dll.cpp | 134 + .../windows/py_win_helpers.hpp | 77 + .../windows/run_code_in_memory.hpp | 116 + .../windows/run_code_on_dllmain.cpp | 78 + pydevd_attach_to_process/windows/stdafx.cpp | 22 + pydevd_attach_to_process/windows/stdafx.h | 36 + pydevd_attach_to_process/windows/targetver.h | 22 + pydevd_file_utils.py | 911 + pydevd_plugins/__init__.py | 8 + pydevd_plugins/django_debug.py | 613 + pydevd_plugins/extensions/README.md | 30 + pydevd_plugins/extensions/__init__.py | 7 + pydevd_plugins/extensions/types/__init__.py | 7 + .../extensions/types/pydevd_helpers.py | 26 + .../types/pydevd_plugin_numpy_types.py | 86 + .../types/pydevd_plugin_pandas_types.py | 160 + .../types/pydevd_plugins_django_form_str.py | 16 + pydevd_plugins/jinja2_debug.py | 506 + pydevd_plugins/pydevd_line_validation.py | 107 + pydevd_tracing.py | 375 + pytest.ini | 4 + runfiles.py | 317 + setup.py | 181 + setup_pydevd_cython.py | 250 + stubs/_django_manager_body.py | 414 + test_pydevd_reload/__init__.py | 0 test_pydevd_reload/test_pydevd_reload.py | 573 + tests/__init__.py | 0 tests/test_check_pydevconsole.py | 113 + tests/test_get_referrers.py | 125 + tests/test_jyserver.py | 140 + tests/test_jysimpleTipper.py | 242 + tests/test_pydev_ipython_011.py | 308 + tests/test_pydevconsole.py | 277 + tests/test_pyserver.py | 155 + tests/test_simpleTipper.py | 243 + tests_mainloop/README | 4 + tests_mainloop/__init__.py | 0 tests_mainloop/gui-glut.py | 52 + tests_mainloop/gui-gtk.py | 35 + tests_mainloop/gui-gtk3.py | 33 + tests_mainloop/gui-pyglet.py | 28 + tests_mainloop/gui-qt.py | 36 + tests_mainloop/gui-tk.py | 33 + tests_mainloop/gui-wx.py | 103 + tests_python/__init__.py | 0 tests_python/check_debug_python.py | 38 + tests_python/debug_constants.py | 45 + tests_python/debugger_fixtures.py | 524 + tests_python/debugger_unittest.py | 1446 + tests_python/flask1/.project | 17 + tests_python/flask1/.pydevproject | 8 + tests_python/flask1/app.py | 60 + tests_python/flask1/templates/bad.html | 10 + tests_python/flask1/templates/hello.html | 10 + tests_python/my_django_proj_17/.project | 18 + tests_python/my_django_proj_17/.pydevproject | 12 + tests_python/my_django_proj_17/manage.py | 10 + .../my_django_proj_17/my_app/__init__.py | 0 .../my_django_proj_17/my_app/admin.py | 3 + .../my_django_proj_17/my_app/forms.py | 4 + .../my_django_proj_17/my_app/models.py | 3 + .../my_app/templates/my_app/index.html | 13 + .../my_app/templates/my_app/inherited.html | 5 + .../my_app/templates/my_app/inherits.html | 2 + .../my_app/templates/my_app/name.html | 7 + .../my_app/templates/my_app/no_var_error.html | 5 + .../templates/my_app/template_error.html | 13 + .../templates/my_app/template_error2.html | 6 + .../my_django_proj_17/my_app/tests.py | 3 + tests_python/my_django_proj_17/my_app/urls.py | 12 + .../my_django_proj_17/my_app/views.py | 73 + .../my_django_proj_17/__init__.py | 0 .../my_django_proj_17/settings.py | 86 + .../my_django_proj_17/urls.py | 11 + .../my_django_proj_17/wsgi.py | 14 + tests_python/my_django_proj_21/.project | 18 + tests_python/my_django_proj_21/.pydevproject | 14 + .../org.eclipse.core.resources.prefs | 27 + .../.settings/org.python.pydev.yaml | 47 + tests_python/my_django_proj_21/manage.py | 15 + .../my_django_proj_21/my_app/__init__.py | 0 .../my_django_proj_21/my_app/admin.py | 3 + tests_python/my_django_proj_21/my_app/apps.py | 5 + .../my_django_proj_21/my_app/forms.py | 4 + .../my_app/migrations/__init__.py | 0 .../my_django_proj_21/my_app/models.py | 3 + .../my_app/templates/my_app/index.html | 13 + .../my_app/templates/my_app/inherited.html | 5 + .../my_app/templates/my_app/inherits.html | 2 + .../my_app/templates/my_app/name.html | 7 + .../my_app/templates/my_app/no_var_error.html | 5 + .../templates/my_app/template_error.html | 13 + .../templates/my_app/template_error2.html | 6 + .../my_django_proj_21/my_app/tests.py | 72 + tests_python/my_django_proj_21/my_app/urls.py | 15 + .../my_django_proj_21/my_app/views.py | 80 + .../my_django_proj_21/__init__.py | 0 .../my_django_proj_21/settings.py | 120 + .../my_django_proj_21/urls.py | 23 + .../my_django_proj_21/wsgi.py | 16 + .../my_extensions/pydevd_plugins/__init__.py | 7 + .../pydevd_plugins/extensions/__init__.py | 7 + .../extensions/pydevd_plugin_test_events.py | 18 + .../extensions/pydevd_plugin_test_exttype.py | 20 + tests_python/performance_check.py | 245 + tests_python/regression_check.py | 240 + .../resource_path_translation/__init__.py | 0 .../resource_path_translation/other.py | 6 + tests_python/resources/__init__.py | 0 .../resources/_bytecode_big_method.py | 331 + .../resources/_bytecode_constructs.py | 126 + .../resources/_bytecode_many_names_example.py | 268 + .../resources/_bytecode_overflow_example.py | 89 + tests_python/resources/_bytecode_super.py | 22 + tests_python/resources/_debugger_case1.py | 61 + tests_python/resources/_debugger_case13.py | 43 + tests_python/resources/_debugger_case14.py | 29 + tests_python/resources/_debugger_case15.py | 29 + .../resources/_debugger_case15_execfile.py | 1 + tests_python/resources/_debugger_case16.py | 12 + tests_python/resources/_debugger_case17.py | 44 + tests_python/resources/_debugger_case17a.py | 18 + tests_python/resources/_debugger_case18.py | 23 + tests_python/resources/_debugger_case19.py | 10 + tests_python/resources/_debugger_case2.py | 24 + tests_python/resources/_debugger_case20.py | 38 + tests_python/resources/_debugger_case3.py | 8 + tests_python/resources/_debugger_case4.py | 22 + tests_python/resources/_debugger_case56.py | 9 + tests_python/resources/_debugger_case89.py | 16 + .../_debugger_case_adjust_breakpoint.py | 11 + .../resources/_debugger_case_async.py | 21 + .../resources/_debugger_case_asyncio.py | 37 + ...ger_case_attach_to_pid_multiple_threads.py | 47 + .../_debugger_case_attach_to_pid_simple.py | 17 + .../resources/_debugger_case_breakpoint.py | 7 + .../resources/_debugger_case_breakpoint2.py | 7 + ..._debugger_case_breakpoint_condition_exc.py | 8 + .../_debugger_case_breakpoint_remote.py | 15 + ...bugger_case_breakpoint_remote_no_import.py | 14 + .../resources/_debugger_case_change_breaks.py | 12 + .../resources/_debugger_case_check_tracer.py | 100 + .../resources/_debugger_case_completions.py | 23 + .../resources/_debugger_case_custom_frames.py | 23 + .../_debugger_case_custom_message.py | 14 + .../_debugger_case_deadlock_thread_eval.py | 72 + .../resources/_debugger_case_debug_options.py | 11 + .../resources/_debugger_case_deep_stacks.py | 16 + .../resources/_debugger_case_dir_exception.py | 13 + .../resources/_debugger_case_dont_trace.py | 3 + .../_debugger_case_dont_trace_test.py | 18 + .../resources/_debugger_case_evaluate.py | 8 + .../resources/_debugger_case_event_ext.py | 1 + .../resources/_debugger_case_exceptions.py | 22 + .../resources/_debugger_case_frame_eval.py | 70 + .../resources/_debugger_case_generator.py | 18 + .../resources/_debugger_case_generator2.py | 17 + .../resources/_debugger_case_generator3.py | 13 + .../resources/_debugger_case_generator_py2.py | 16 + .../resources/_debugger_case_generator_py3.py | 14 + .../_debugger_case_generator_step_in.py | 13 + ...ebugger_case_get_next_statement_targets.py | 26 + .../_debugger_case_get_thread_stack.py | 21 + .../resources/_debugger_case_gevent.py | 57 + .../resources/_debugger_case_gevent_simple.py | 21 + .../_debugger_case_gevent_subprocess.py | 16 + .../resources/_debugger_case_globals.py | 12 + .../_debugger_case_gui_event_loop.py | 26 + .../_debugger_case_gui_event_loop_qt5.py | 51 + .../resources/_debugger_case_hasattr_crash.py | 10 + .../resources/_debugger_case_hit_count.py | 6 + .../_debugger_case_ignore_exceptions.py | 25 + .../_debugger_case_import_imported.py | 2 + .../resources/_debugger_case_import_main.py | 3 + .../_debugger_case_lambda_multiline.py | 8 + .../resources/_debugger_case_lamda.py | 5 + .../_debugger_case_large_exception_stack.py | 16 + .../resources/_debugger_case_linecache.py | 26 + .../_debugger_case_linecache_existing_file.py | 12 + .../_debugger_case_listen_dap_messages.py | 59 + .../_debugger_case_local_variables.py | 14 + .../_debugger_case_local_variables2.py | 12 + .../_debugger_case_local_variables3.py | 82 + .../_debugger_case_local_variables_hex.py | 12 + .../resources/_debugger_case_logging.py | 63 + .../resources/_debugger_case_m_switch.py | 3 + .../resources/_debugger_case_m_switch_2.py | 2 + .../resources/_debugger_case_matplotlib.py | 23 + .../_debugger_case_method_single_line.py | 5 + .../resources/_debugger_case_module.py | 17 + .../_debugger_case_module_entry_point.py | 2 + .../_debugger_case_multi_threads_stepping.py | 55 + .../_debugger_case_multiple_threads.py | 32 + .../_debugger_case_multiprocessing.py | 15 + .../_debugger_case_multiprocessing_2.py | 20 + .../_debugger_case_multiprocessing_pool.py | 17 + ...er_case_multiprocessing_stopped_threads.py | 32 + .../resources/_debugger_case_namedtuple.py | 6 + .../_debugger_case_no_subprocess_patching.py | 35 + .../resources/_debugger_case_odict.py | 14 + .../_debugger_case_path_translation.py | 14 + .../_debugger_case_pause_continue.py | 13 + .../resources/_debugger_case_print.py | 1 + .../_debugger_case_pydevd_customization.py | 63 + .../resources/_debugger_case_python_c.py | 21 + .../resources/_debugger_case_qthread1.py | 31 + .../resources/_debugger_case_qthread2.py | 40 + .../resources/_debugger_case_qthread3.py | 35 + .../resources/_debugger_case_qthread4.py | 47 + .../resources/_debugger_case_quoting.py | 26 + .../_debugger_case_raise_with_cause.py | 23 + .../resources/_debugger_case_redirect.py | 26 + .../resources/_debugger_case_remote.py | 16 + .../resources/_debugger_case_remote_1.py | 47 + .../resources/_debugger_case_remote_2.py | 11 + .../_debugger_case_remote_threads.py | 31 + ...bugger_case_remote_unhandled_exceptions.py | 15 + ...ugger_case_remote_unhandled_exceptions2.py | 21 + .../_debugger_case_remove_breakpoint.py | 14 + .../_debugger_case_replace_process.py | 18 + .../resources/_debugger_case_return_value.py | 16 + .../_debugger_case_return_value_asyncio.py | 26 + .../resources/_debugger_case_scapy.py | 2 + .../_debugger_case_scoped_stepping.py | 145 + .../_debugger_case_scoped_stepping_target.py | 3 + .../_debugger_case_scoped_stepping_target2.py | 9 + ...ugger_case_scoped_stepping_target_async.py | 9 + .../_debugger_case_set_next_statement.py | 10 + .../resources/_debugger_case_settrace.py | 26 + .../resources/_debugger_case_show_bytecode.py | 25 + .../resources/_debugger_case_simple_calls.py | 18 + ...gger_case_skip_breakpoint_in_exceptions.py | 8 + .../_debugger_case_smart_step_into.py | 20 + .../_debugger_case_smart_step_into2.py | 17 + .../_debugger_case_smart_step_into3.py | 21 + .../_debugger_case_source_map_goto_target.py | 24 + .../_debugger_case_source_mapping.py | 31 + ...ugger_case_source_mapping_and_reference.py | 57 + .../_debugger_case_source_mapping_jmc.py | 35 + .../_debugger_case_source_reference.py | 32 + .../resources/_debugger_case_stepping.py | 19 + .../_debugger_case_stop_async_iteration.py | 14 + .../_debugger_case_subprocess_and_fork.py | 47 + .../_debugger_case_subprocess_target.zip | Bin 0 -> 177 bytes .../_debugger_case_subprocess_zip.py | 34 + .../resources/_debugger_case_suspend_all.py | 33 + .../_debugger_case_suspend_policy.py | 29 + .../resources/_debugger_case_sysexit.py | 9 + .../resources/_debugger_case_sysexit_0.py | 9 + .../resources/_debugger_case_sysexit_none.py | 9 + .../resources/_debugger_case_terminate.py | 37 + ..._debugger_case_thread_creation_deadlock.py | 26 + .../_debugger_case_thread_started_exited.py | 18 + .../_debugger_case_trace_dispatch.py | 18 + .../resources/_debugger_case_tracing.py | 14 + tests_python/resources/_debugger_case_trio.py | 30 + .../resources/_debugger_case_type_ext.py | 8 + ...gger_case_unhandled_exception_get_stack.py | 12 + .../_debugger_case_unhandled_exceptions.py | 47 + ...bugger_case_unhandled_exceptions_custom.py | 53 + ...ger_case_unhandled_exceptions_generator.py | 19 + ...gger_case_unhandled_exceptions_listcomp.py | 19 + ..._case_unhandled_exceptions_on_top_level.py | 1 + ...case_unhandled_exceptions_on_top_level2.py | 6 + .../_debugger_case_unhandled_just_my_code.py | 13 + .../_debugger_case_user_unhandled.py | 14 + .../_debugger_case_user_unhandled2.py | 5 + ..._debugger_case_variables_with_same_name.py | 15 + .../_debugger_case_wait_for_attach.py | 3 + .../_debugger_case_wait_for_attach_impl.py | 49 + .../resources/_debugger_case_warnings.py | 22 + .../resources/_debugger_case_yield_from.py | 12 + .../resources/_debugger_case_zip_files.py | 17 + tests_python/resources/_performance_1.py | 34 + tests_python/resources/_performance_2.py | 25 + tests_python/resources/_performance_3.py | 15 + .../_pydev_coverage_cyrillic_encoding_py2.py | 8 + .../_pydev_coverage_cyrillic_encoding_py3.py | 8 + .../resources/_pydev_coverage_syntax_error.py | 8 + .../_pydevd_test_find_main_thread_id.py | 159 + tests_python/resources/launch/foo/__main__.py | 6 + tests_python/resources/launch/foo/bar.py | 0 tests_python/resources/launch_py2/__init__.py | 0 .../resources/launch_py2/foo/__init__.py | 0 .../resources/launch_py2/foo/__main__.py | 6 + tests_python/resources/launch_py2/foo/bar.py | 0 tests_python/resources/my_code/__init__.py | 0 tests_python/resources/my_code/my_code.py | 15 + .../resources/my_code/my_code_coroutine.py | 27 + .../my_code_coroutine_user_unhandled.py | 34 + ...y_code_coroutine_user_unhandled_no_stop.py | 34 + .../resources/my_code/my_code_double_step.py | 8 + .../resources/my_code/my_code_exception.py | 14 + .../my_code/my_code_exception_on_other.py | 14 + .../my_code_exception_user_unhandled.py | 22 + .../resources/my_code/my_code_on_entry.py | 1 + .../resources/not_my_code/__init__.py | 0 .../resources/not_my_code/empty_file.py | 0 .../resources/not_my_code/main_on_entry.py | 7 + .../resources/not_my_code/main_on_entry2.py | 24 + .../resources/not_my_code/not_my_coroutine.py | 5 + tests_python/resources/not_my_code/other.py | 15 + .../resources/not_my_code/other_noop.py | 2 + .../_debugger_case_wrong_bytecode.py | 47 + .../wrong_bytecode/helper/__init__.py | 58 + .../wrong_bytecode/helper/helper/__init__.py | 56 + .../helper/helper/helper/__init__.py | 56 + tests_python/test_additional_thread_info.py | 82 + tests_python/test_bytecode_manipulation.py | 279 + tests_python/test_code_obj_to_source_code.py | 95 + tests_python/test_collect_bytecode_info.py | 698 + .../test_collect_try_except_info.json | 30 + .../test_iter_bytecode.py26.json | 210 + .../test_iter_bytecode.py27.json | 200 + .../test_iter_bytecode.py36.json | 235 + .../test_iter_bytecode.py37.json | 235 + tests_python/test_console.py | 201 + tests_python/test_convert_utilities.py | 528 + tests_python/test_debugger.py | 4405 ++ tests_python/test_debugger_json.py | 6375 +++ tests_python/test_dump_threads.py | 8 + tests_python/test_evaluate_expression.py | 280 + tests_python/test_extract_token.py | 49 + tests_python/test_fixtures.py | 113 + tests_python/test_frame_eval_and_tracing.py | 278 + tests_python/test_frame_evaluator.py | 131 + tests_python/test_null.py | 8 + tests_python/test_process_command_line.py | 28 + tests_python/test_pydev_monkey.py | 526 + tests_python/test_pydevcoverage.py | 68 + tests_python/test_pydevd_api.py | 43 + tests_python/test_pydevd_filtering.py | 258 + tests_python/test_pydevd_io.py | 225 + tests_python/test_resolvers.py | 323 + tests_python/test_run.py | 115 + tests_python/test_safe_repr.py | 690 + tests_python/test_save_locals.py | 101 + tests_python/test_schema.py | 142 + tests_python/test_smart_step_into_bytecode.py | 1132 + tests_python/test_suspended_frames_manager.py | 142 + tests_python/test_timeout_tracker.py | 128 + tests_python/test_tracing_gotchas.py | 101 + tests_python/test_tracing_on_top_level.py | 485 + tests_python/test_utilities.py | 550 + tests_python/tests_single_notification.py | 293 + tests_runfiles/not_in_default_pythonpath.txt | 1 + tests_runfiles/samples/.cvsignore | 2 + tests_runfiles/samples/nested_dir/.cvsignore | 2 + tests_runfiles/samples/nested_dir/__init__.py | 1 + .../samples/nested_dir/nested2/.cvsignore | 2 + .../samples/nested_dir/nested2/__init__.py | 1 + .../nested_dir/nested2/deep_nest_test.py | 22 + .../nested_dir/nested2/non_test_file.py | 3 + .../samples/nested_dir/nested3/.cvsignore | 2 + .../samples/nested_dir/nested3/__init__.py | 1 + .../samples/nested_dir/nested3/junk.txt | 1 + .../nested_dir/nested3/non_test_file.py | 3 + .../samples/nested_dir/non_test_file.py | 3 + .../samples/nested_dir/simple4_test.py | 16 + tests_runfiles/samples/non_test_file.py | 3 + .../samples/not_in_default_pythonpath.txt | 1 + tests_runfiles/samples/simple2_test.py | 16 + tests_runfiles/samples/simple3_test.py | 16 + tests_runfiles/samples/simpleClass_test.py | 14 + tests_runfiles/samples/simpleModule_test.py | 16 + tests_runfiles/samples/simple_test.py | 45 + tests_runfiles/test_pydevd_property.py | 124 + tests_runfiles/test_pydevdio.py | 36 + tests_runfiles/test_runfiles.py | 437 + 591 files changed, 220050 insertions(+) create mode 100644 .github/install_and_run_debug_py.sh create mode 100644 .github/workflows/pydevd-tests-python.yml create mode 100644 .gitignore create mode 100644 .project create mode 100644 .pydevproject create mode 100644 .settings/org.eclipse.core.resources.prefs create mode 100644 .settings/org.python.pydev.yaml create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README.rst create mode 100644 _pydev_bundle/__init__.py create mode 100644 _pydev_bundle/_pydev_calltip_util.py create mode 100644 _pydev_bundle/_pydev_completer.py create mode 100644 _pydev_bundle/_pydev_execfile.py create mode 100644 _pydev_bundle/_pydev_filesystem_encoding.py create mode 100644 _pydev_bundle/_pydev_getopt.py create mode 100644 _pydev_bundle/_pydev_imports_tipper.py create mode 100644 _pydev_bundle/_pydev_jy_imports_tipper.py create mode 100644 _pydev_bundle/_pydev_log.py create mode 100644 _pydev_bundle/_pydev_saved_modules.py create mode 100644 _pydev_bundle/_pydev_sys_patch.py create mode 100644 _pydev_bundle/_pydev_tipper_common.py create mode 100644 _pydev_bundle/fsnotify/__init__.py create mode 100644 _pydev_bundle/pydev_console_utils.py create mode 100644 _pydev_bundle/pydev_import_hook.py create mode 100644 _pydev_bundle/pydev_imports.py create mode 100644 _pydev_bundle/pydev_ipython_console.py create mode 100644 _pydev_bundle/pydev_ipython_console_011.py create mode 100644 _pydev_bundle/pydev_is_thread_alive.py create mode 100644 _pydev_bundle/pydev_localhost.py create mode 100644 _pydev_bundle/pydev_log.py create mode 100644 _pydev_bundle/pydev_monkey.py create mode 100644 _pydev_bundle/pydev_monkey_qt.py create mode 100644 _pydev_bundle/pydev_override.py create mode 100644 _pydev_bundle/pydev_umd.py create mode 100644 _pydev_bundle/pydev_versioncheck.py create mode 100644 _pydev_runfiles/__init__.py create mode 100644 _pydev_runfiles/pydev_runfiles.py create mode 100644 _pydev_runfiles/pydev_runfiles_coverage.py create mode 100644 _pydev_runfiles/pydev_runfiles_nose.py create mode 100644 _pydev_runfiles/pydev_runfiles_parallel.py create mode 100644 _pydev_runfiles/pydev_runfiles_parallel_client.py create mode 100644 _pydev_runfiles/pydev_runfiles_pytest2.py create mode 100644 _pydev_runfiles/pydev_runfiles_unittest.py create mode 100644 _pydev_runfiles/pydev_runfiles_xml_rpc.py create mode 100644 _pydevd_bundle/__init__.py create mode 100644 _pydevd_bundle/_debug_adapter/__init__.py create mode 100644 _pydevd_bundle/_debug_adapter/__main__pydevd_gen_debug_adapter_protocol.py create mode 100644 _pydevd_bundle/_debug_adapter/debugProtocol.json create mode 100644 _pydevd_bundle/_debug_adapter/debugProtocolCustom.json create mode 100644 _pydevd_bundle/_debug_adapter/pydevd_base_schema.py create mode 100644 _pydevd_bundle/_debug_adapter/pydevd_schema.py create mode 100644 _pydevd_bundle/_debug_adapter/pydevd_schema_log.py create mode 100644 _pydevd_bundle/pydevconsole_code.py create mode 100644 _pydevd_bundle/pydevd_additional_thread_info.py create mode 100644 _pydevd_bundle/pydevd_additional_thread_info_regular.py create mode 100644 _pydevd_bundle/pydevd_api.py create mode 100644 _pydevd_bundle/pydevd_breakpoints.py create mode 100644 _pydevd_bundle/pydevd_bytecode_utils.py create mode 100644 _pydevd_bundle/pydevd_code_to_source.py create mode 100644 _pydevd_bundle/pydevd_collect_bytecode_info.py create mode 100644 _pydevd_bundle/pydevd_comm.py create mode 100644 _pydevd_bundle/pydevd_comm_constants.py create mode 100644 _pydevd_bundle/pydevd_command_line_handling.py create mode 100644 _pydevd_bundle/pydevd_concurrency_analyser/__init__.py create mode 100644 _pydevd_bundle/pydevd_concurrency_analyser/pydevd_concurrency_logger.py create mode 100644 _pydevd_bundle/pydevd_concurrency_analyser/pydevd_thread_wrappers.py create mode 100644 _pydevd_bundle/pydevd_console.py create mode 100644 _pydevd_bundle/pydevd_constants.py create mode 100644 _pydevd_bundle/pydevd_custom_frames.py create mode 100644 _pydevd_bundle/pydevd_cython.c create mode 100644 _pydevd_bundle/pydevd_cython.pxd create mode 100644 _pydevd_bundle/pydevd_cython.pyx create mode 100644 _pydevd_bundle/pydevd_cython_wrapper.py create mode 100644 _pydevd_bundle/pydevd_daemon_thread.py create mode 100644 _pydevd_bundle/pydevd_defaults.py create mode 100644 _pydevd_bundle/pydevd_dont_trace.py create mode 100644 _pydevd_bundle/pydevd_dont_trace_files.py create mode 100644 _pydevd_bundle/pydevd_exec2.py create mode 100644 _pydevd_bundle/pydevd_extension_api.py create mode 100644 _pydevd_bundle/pydevd_extension_utils.py create mode 100644 _pydevd_bundle/pydevd_filtering.py create mode 100644 _pydevd_bundle/pydevd_frame.py create mode 100644 _pydevd_bundle/pydevd_frame_utils.py create mode 100644 _pydevd_bundle/pydevd_gevent_integration.py create mode 100644 _pydevd_bundle/pydevd_import_class.py create mode 100644 _pydevd_bundle/pydevd_io.py create mode 100644 _pydevd_bundle/pydevd_json_debug_options.py create mode 100644 _pydevd_bundle/pydevd_net_command.py create mode 100644 _pydevd_bundle/pydevd_net_command_factory_json.py create mode 100644 _pydevd_bundle/pydevd_net_command_factory_xml.py create mode 100644 _pydevd_bundle/pydevd_plugin_utils.py create mode 100644 _pydevd_bundle/pydevd_process_net_command.py create mode 100644 _pydevd_bundle/pydevd_process_net_command_json.py create mode 100644 _pydevd_bundle/pydevd_referrers.py create mode 100644 _pydevd_bundle/pydevd_reload.py create mode 100644 _pydevd_bundle/pydevd_resolver.py create mode 100644 _pydevd_bundle/pydevd_safe_repr.py create mode 100644 _pydevd_bundle/pydevd_save_locals.py create mode 100644 _pydevd_bundle/pydevd_signature.py create mode 100644 _pydevd_bundle/pydevd_source_mapping.py create mode 100644 _pydevd_bundle/pydevd_stackless.py create mode 100644 _pydevd_bundle/pydevd_suspended_frames.py create mode 100644 _pydevd_bundle/pydevd_thread_lifecycle.py create mode 100644 _pydevd_bundle/pydevd_timeout.py create mode 100644 _pydevd_bundle/pydevd_trace_api.py create mode 100644 _pydevd_bundle/pydevd_trace_dispatch.py create mode 100644 _pydevd_bundle/pydevd_trace_dispatch_regular.py create mode 100644 _pydevd_bundle/pydevd_traceproperty.py create mode 100644 _pydevd_bundle/pydevd_utils.py create mode 100644 _pydevd_bundle/pydevd_vars.py create mode 100644 _pydevd_bundle/pydevd_vm_type.py create mode 100644 _pydevd_bundle/pydevd_xml.py create mode 100644 _pydevd_frame_eval/.gitignore create mode 100644 _pydevd_frame_eval/__init__.py create mode 100644 _pydevd_frame_eval/pydevd_frame_eval_cython_wrapper.py create mode 100644 _pydevd_frame_eval/pydevd_frame_eval_main.py create mode 100644 _pydevd_frame_eval/pydevd_frame_evaluator.c create mode 100644 _pydevd_frame_eval/pydevd_frame_evaluator.pxd create mode 100644 _pydevd_frame_eval/pydevd_frame_evaluator.template.pyx create mode 100644 _pydevd_frame_eval/pydevd_frame_tracing.py create mode 100644 _pydevd_frame_eval/pydevd_modify_bytecode.py create mode 100644 _pydevd_frame_eval/release_mem.h create mode 100644 build_tools/build.py create mode 100644 build_tools/build_binaries_osx.py create mode 100644 build_tools/build_binaries_windows.py create mode 100644 build_tools/check_no_git_modifications.py create mode 100644 build_tools/generate_code.py create mode 100644 build_tools/names_to_rename.py create mode 100644 build_tools/pydevd_release_process.txt create mode 100644 build_tools/rename_pep8.py create mode 100644 conftest.py create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 interpreterInfo.py create mode 100644 pycompletionserver.py create mode 100644 pydev_app_engine_debug_startup.py create mode 100644 pydev_coverage.py create mode 100644 pydev_ipython/README create mode 100644 pydev_ipython/__init__.py create mode 100644 pydev_ipython/inputhook.py create mode 100644 pydev_ipython/inputhookglut.py create mode 100644 pydev_ipython/inputhookgtk.py create mode 100644 pydev_ipython/inputhookgtk3.py create mode 100644 pydev_ipython/inputhookpyglet.py create mode 100644 pydev_ipython/inputhookqt4.py create mode 100644 pydev_ipython/inputhookqt5.py create mode 100644 pydev_ipython/inputhooktk.py create mode 100644 pydev_ipython/inputhookwx.py create mode 100644 pydev_ipython/matplotlibtools.py create mode 100644 pydev_ipython/qt.py create mode 100644 pydev_ipython/qt_for_kernel.py create mode 100644 pydev_ipython/qt_loaders.py create mode 100644 pydev_ipython/version.py create mode 100644 pydev_pysrc.py create mode 100644 pydev_run_in_console.py create mode 100644 pydev_sitecustomize/__not_in_default_pythonpath.txt create mode 100644 pydev_sitecustomize/sitecustomize.py create mode 100644 pydevconsole.py create mode 100644 pydevd.py create mode 100644 pydevd_attach_to_process/README.txt create mode 100644 pydevd_attach_to_process/_always_live_program.py create mode 100644 pydevd_attach_to_process/_check.py create mode 100644 pydevd_attach_to_process/_test_attach_to_process.py create mode 100644 pydevd_attach_to_process/_test_attach_to_process_linux.py create mode 100644 pydevd_attach_to_process/add_code_to_python_process.py create mode 100644 pydevd_attach_to_process/attach_pydevd.py create mode 100644 pydevd_attach_to_process/attach_script.py create mode 100644 pydevd_attach_to_process/common/py_custom_pyeval_settrace.hpp create mode 100644 pydevd_attach_to_process/common/py_custom_pyeval_settrace_310.hpp create mode 100644 pydevd_attach_to_process/common/py_custom_pyeval_settrace_311.hpp create mode 100644 pydevd_attach_to_process/common/py_custom_pyeval_settrace_common.hpp create mode 100644 pydevd_attach_to_process/common/py_settrace.hpp create mode 100644 pydevd_attach_to_process/common/py_utils.hpp create mode 100644 pydevd_attach_to_process/common/py_version.hpp create mode 100644 pydevd_attach_to_process/common/python.h create mode 100644 pydevd_attach_to_process/common/ref_utils.hpp create mode 100644 pydevd_attach_to_process/linux_and_mac/.gitignore create mode 100644 pydevd_attach_to_process/linux_and_mac/attach.cpp create mode 100755 pydevd_attach_to_process/linux_and_mac/compile_linux.sh create mode 100755 pydevd_attach_to_process/linux_and_mac/compile_mac.sh create mode 100644 pydevd_attach_to_process/linux_and_mac/compile_manylinux.cmd create mode 100644 pydevd_attach_to_process/linux_and_mac/lldb_prepare.py create mode 100644 pydevd_attach_to_process/winappdbg/__init__.py create mode 100644 pydevd_attach_to_process/winappdbg/breakpoint.py create mode 100644 pydevd_attach_to_process/winappdbg/compat.py create mode 100644 pydevd_attach_to_process/winappdbg/crash.py create mode 100644 pydevd_attach_to_process/winappdbg/debug.py create mode 100644 pydevd_attach_to_process/winappdbg/disasm.py create mode 100644 pydevd_attach_to_process/winappdbg/event.py create mode 100644 pydevd_attach_to_process/winappdbg/interactive.py create mode 100644 pydevd_attach_to_process/winappdbg/module.py create mode 100644 pydevd_attach_to_process/winappdbg/process.py create mode 100644 pydevd_attach_to_process/winappdbg/registry.py create mode 100644 pydevd_attach_to_process/winappdbg/search.py create mode 100644 pydevd_attach_to_process/winappdbg/sql.py create mode 100644 pydevd_attach_to_process/winappdbg/system.py create mode 100644 pydevd_attach_to_process/winappdbg/textio.py create mode 100644 pydevd_attach_to_process/winappdbg/thread.py create mode 100644 pydevd_attach_to_process/winappdbg/util.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/__init__.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/advapi32.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/context_amd64.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/context_i386.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/dbghelp.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/defines.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/gdi32.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/kernel32.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/ntdll.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/peb_teb.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/psapi.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/shell32.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/shlwapi.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/user32.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/version.py create mode 100644 pydevd_attach_to_process/winappdbg/win32/wtsapi32.py create mode 100644 pydevd_attach_to_process/winappdbg/window.py create mode 100644 pydevd_attach_to_process/windows/attach.cpp create mode 100644 pydevd_attach_to_process/windows/attach.h create mode 100644 pydevd_attach_to_process/windows/compile_windows.bat create mode 100644 pydevd_attach_to_process/windows/inject_dll.cpp create mode 100644 pydevd_attach_to_process/windows/py_win_helpers.hpp create mode 100644 pydevd_attach_to_process/windows/run_code_in_memory.hpp create mode 100644 pydevd_attach_to_process/windows/run_code_on_dllmain.cpp create mode 100644 pydevd_attach_to_process/windows/stdafx.cpp create mode 100644 pydevd_attach_to_process/windows/stdafx.h create mode 100644 pydevd_attach_to_process/windows/targetver.h create mode 100644 pydevd_file_utils.py create mode 100644 pydevd_plugins/__init__.py create mode 100644 pydevd_plugins/django_debug.py create mode 100644 pydevd_plugins/extensions/README.md create mode 100644 pydevd_plugins/extensions/__init__.py create mode 100644 pydevd_plugins/extensions/types/__init__.py create mode 100644 pydevd_plugins/extensions/types/pydevd_helpers.py create mode 100644 pydevd_plugins/extensions/types/pydevd_plugin_numpy_types.py create mode 100644 pydevd_plugins/extensions/types/pydevd_plugin_pandas_types.py create mode 100644 pydevd_plugins/extensions/types/pydevd_plugins_django_form_str.py create mode 100644 pydevd_plugins/jinja2_debug.py create mode 100644 pydevd_plugins/pydevd_line_validation.py create mode 100644 pydevd_tracing.py create mode 100644 pytest.ini create mode 100644 runfiles.py create mode 100644 setup.py create mode 100644 setup_pydevd_cython.py create mode 100644 stubs/_django_manager_body.py create mode 100644 test_pydevd_reload/__init__.py create mode 100644 test_pydevd_reload/test_pydevd_reload.py create mode 100644 tests/__init__.py create mode 100644 tests/test_check_pydevconsole.py create mode 100644 tests/test_get_referrers.py create mode 100644 tests/test_jyserver.py create mode 100644 tests/test_jysimpleTipper.py create mode 100644 tests/test_pydev_ipython_011.py create mode 100644 tests/test_pydevconsole.py create mode 100644 tests/test_pyserver.py create mode 100644 tests/test_simpleTipper.py create mode 100644 tests_mainloop/README create mode 100644 tests_mainloop/__init__.py create mode 100644 tests_mainloop/gui-glut.py create mode 100644 tests_mainloop/gui-gtk.py create mode 100644 tests_mainloop/gui-gtk3.py create mode 100644 tests_mainloop/gui-pyglet.py create mode 100644 tests_mainloop/gui-qt.py create mode 100644 tests_mainloop/gui-tk.py create mode 100644 tests_mainloop/gui-wx.py create mode 100644 tests_python/__init__.py create mode 100644 tests_python/check_debug_python.py create mode 100644 tests_python/debug_constants.py create mode 100644 tests_python/debugger_fixtures.py create mode 100644 tests_python/debugger_unittest.py create mode 100644 tests_python/flask1/.project create mode 100644 tests_python/flask1/.pydevproject create mode 100644 tests_python/flask1/app.py create mode 100644 tests_python/flask1/templates/bad.html create mode 100644 tests_python/flask1/templates/hello.html create mode 100644 tests_python/my_django_proj_17/.project create mode 100644 tests_python/my_django_proj_17/.pydevproject create mode 100644 tests_python/my_django_proj_17/manage.py create mode 100644 tests_python/my_django_proj_17/my_app/__init__.py create mode 100644 tests_python/my_django_proj_17/my_app/admin.py create mode 100644 tests_python/my_django_proj_17/my_app/forms.py create mode 100644 tests_python/my_django_proj_17/my_app/models.py create mode 100644 tests_python/my_django_proj_17/my_app/templates/my_app/index.html create mode 100644 tests_python/my_django_proj_17/my_app/templates/my_app/inherited.html create mode 100644 tests_python/my_django_proj_17/my_app/templates/my_app/inherits.html create mode 100644 tests_python/my_django_proj_17/my_app/templates/my_app/name.html create mode 100644 tests_python/my_django_proj_17/my_app/templates/my_app/no_var_error.html create mode 100644 tests_python/my_django_proj_17/my_app/templates/my_app/template_error.html create mode 100644 tests_python/my_django_proj_17/my_app/templates/my_app/template_error2.html create mode 100644 tests_python/my_django_proj_17/my_app/tests.py create mode 100644 tests_python/my_django_proj_17/my_app/urls.py create mode 100644 tests_python/my_django_proj_17/my_app/views.py create mode 100644 tests_python/my_django_proj_17/my_django_proj_17/__init__.py create mode 100644 tests_python/my_django_proj_17/my_django_proj_17/settings.py create mode 100644 tests_python/my_django_proj_17/my_django_proj_17/urls.py create mode 100644 tests_python/my_django_proj_17/my_django_proj_17/wsgi.py create mode 100644 tests_python/my_django_proj_21/.project create mode 100644 tests_python/my_django_proj_21/.pydevproject create mode 100644 tests_python/my_django_proj_21/.settings/org.eclipse.core.resources.prefs create mode 100644 tests_python/my_django_proj_21/.settings/org.python.pydev.yaml create mode 100644 tests_python/my_django_proj_21/manage.py create mode 100644 tests_python/my_django_proj_21/my_app/__init__.py create mode 100644 tests_python/my_django_proj_21/my_app/admin.py create mode 100644 tests_python/my_django_proj_21/my_app/apps.py create mode 100644 tests_python/my_django_proj_21/my_app/forms.py create mode 100644 tests_python/my_django_proj_21/my_app/migrations/__init__.py create mode 100644 tests_python/my_django_proj_21/my_app/models.py create mode 100644 tests_python/my_django_proj_21/my_app/templates/my_app/index.html create mode 100644 tests_python/my_django_proj_21/my_app/templates/my_app/inherited.html create mode 100644 tests_python/my_django_proj_21/my_app/templates/my_app/inherits.html create mode 100644 tests_python/my_django_proj_21/my_app/templates/my_app/name.html create mode 100644 tests_python/my_django_proj_21/my_app/templates/my_app/no_var_error.html create mode 100644 tests_python/my_django_proj_21/my_app/templates/my_app/template_error.html create mode 100644 tests_python/my_django_proj_21/my_app/templates/my_app/template_error2.html create mode 100644 tests_python/my_django_proj_21/my_app/tests.py create mode 100644 tests_python/my_django_proj_21/my_app/urls.py create mode 100644 tests_python/my_django_proj_21/my_app/views.py create mode 100644 tests_python/my_django_proj_21/my_django_proj_21/__init__.py create mode 100644 tests_python/my_django_proj_21/my_django_proj_21/settings.py create mode 100644 tests_python/my_django_proj_21/my_django_proj_21/urls.py create mode 100644 tests_python/my_django_proj_21/my_django_proj_21/wsgi.py create mode 100644 tests_python/my_extensions/pydevd_plugins/__init__.py create mode 100644 tests_python/my_extensions/pydevd_plugins/extensions/__init__.py create mode 100644 tests_python/my_extensions/pydevd_plugins/extensions/pydevd_plugin_test_events.py create mode 100644 tests_python/my_extensions/pydevd_plugins/extensions/pydevd_plugin_test_exttype.py create mode 100644 tests_python/performance_check.py create mode 100644 tests_python/regression_check.py create mode 100644 tests_python/resource_path_translation/__init__.py create mode 100644 tests_python/resource_path_translation/other.py create mode 100644 tests_python/resources/__init__.py create mode 100644 tests_python/resources/_bytecode_big_method.py create mode 100644 tests_python/resources/_bytecode_constructs.py create mode 100644 tests_python/resources/_bytecode_many_names_example.py create mode 100644 tests_python/resources/_bytecode_overflow_example.py create mode 100644 tests_python/resources/_bytecode_super.py create mode 100644 tests_python/resources/_debugger_case1.py create mode 100644 tests_python/resources/_debugger_case13.py create mode 100644 tests_python/resources/_debugger_case14.py create mode 100644 tests_python/resources/_debugger_case15.py create mode 100644 tests_python/resources/_debugger_case15_execfile.py create mode 100644 tests_python/resources/_debugger_case16.py create mode 100644 tests_python/resources/_debugger_case17.py create mode 100644 tests_python/resources/_debugger_case17a.py create mode 100644 tests_python/resources/_debugger_case18.py create mode 100644 tests_python/resources/_debugger_case19.py create mode 100644 tests_python/resources/_debugger_case2.py create mode 100644 tests_python/resources/_debugger_case20.py create mode 100644 tests_python/resources/_debugger_case3.py create mode 100644 tests_python/resources/_debugger_case4.py create mode 100644 tests_python/resources/_debugger_case56.py create mode 100644 tests_python/resources/_debugger_case89.py create mode 100644 tests_python/resources/_debugger_case_adjust_breakpoint.py create mode 100644 tests_python/resources/_debugger_case_async.py create mode 100644 tests_python/resources/_debugger_case_asyncio.py create mode 100644 tests_python/resources/_debugger_case_attach_to_pid_multiple_threads.py create mode 100644 tests_python/resources/_debugger_case_attach_to_pid_simple.py create mode 100644 tests_python/resources/_debugger_case_breakpoint.py create mode 100644 tests_python/resources/_debugger_case_breakpoint2.py create mode 100644 tests_python/resources/_debugger_case_breakpoint_condition_exc.py create mode 100644 tests_python/resources/_debugger_case_breakpoint_remote.py create mode 100644 tests_python/resources/_debugger_case_breakpoint_remote_no_import.py create mode 100644 tests_python/resources/_debugger_case_change_breaks.py create mode 100644 tests_python/resources/_debugger_case_check_tracer.py create mode 100644 tests_python/resources/_debugger_case_completions.py create mode 100644 tests_python/resources/_debugger_case_custom_frames.py create mode 100644 tests_python/resources/_debugger_case_custom_message.py create mode 100644 tests_python/resources/_debugger_case_deadlock_thread_eval.py create mode 100644 tests_python/resources/_debugger_case_debug_options.py create mode 100644 tests_python/resources/_debugger_case_deep_stacks.py create mode 100644 tests_python/resources/_debugger_case_dir_exception.py create mode 100644 tests_python/resources/_debugger_case_dont_trace.py create mode 100644 tests_python/resources/_debugger_case_dont_trace_test.py create mode 100644 tests_python/resources/_debugger_case_evaluate.py create mode 100644 tests_python/resources/_debugger_case_event_ext.py create mode 100644 tests_python/resources/_debugger_case_exceptions.py create mode 100644 tests_python/resources/_debugger_case_frame_eval.py create mode 100644 tests_python/resources/_debugger_case_generator.py create mode 100644 tests_python/resources/_debugger_case_generator2.py create mode 100644 tests_python/resources/_debugger_case_generator3.py create mode 100644 tests_python/resources/_debugger_case_generator_py2.py create mode 100644 tests_python/resources/_debugger_case_generator_py3.py create mode 100644 tests_python/resources/_debugger_case_generator_step_in.py create mode 100644 tests_python/resources/_debugger_case_get_next_statement_targets.py create mode 100644 tests_python/resources/_debugger_case_get_thread_stack.py create mode 100644 tests_python/resources/_debugger_case_gevent.py create mode 100644 tests_python/resources/_debugger_case_gevent_simple.py create mode 100644 tests_python/resources/_debugger_case_gevent_subprocess.py create mode 100644 tests_python/resources/_debugger_case_globals.py create mode 100644 tests_python/resources/_debugger_case_gui_event_loop.py create mode 100644 tests_python/resources/_debugger_case_gui_event_loop_qt5.py create mode 100644 tests_python/resources/_debugger_case_hasattr_crash.py create mode 100644 tests_python/resources/_debugger_case_hit_count.py create mode 100644 tests_python/resources/_debugger_case_ignore_exceptions.py create mode 100644 tests_python/resources/_debugger_case_import_imported.py create mode 100644 tests_python/resources/_debugger_case_import_main.py create mode 100644 tests_python/resources/_debugger_case_lambda_multiline.py create mode 100644 tests_python/resources/_debugger_case_lamda.py create mode 100644 tests_python/resources/_debugger_case_large_exception_stack.py create mode 100644 tests_python/resources/_debugger_case_linecache.py create mode 100644 tests_python/resources/_debugger_case_linecache_existing_file.py create mode 100644 tests_python/resources/_debugger_case_listen_dap_messages.py create mode 100644 tests_python/resources/_debugger_case_local_variables.py create mode 100644 tests_python/resources/_debugger_case_local_variables2.py create mode 100644 tests_python/resources/_debugger_case_local_variables3.py create mode 100644 tests_python/resources/_debugger_case_local_variables_hex.py create mode 100644 tests_python/resources/_debugger_case_logging.py create mode 100644 tests_python/resources/_debugger_case_m_switch.py create mode 100644 tests_python/resources/_debugger_case_m_switch_2.py create mode 100644 tests_python/resources/_debugger_case_matplotlib.py create mode 100644 tests_python/resources/_debugger_case_method_single_line.py create mode 100644 tests_python/resources/_debugger_case_module.py create mode 100644 tests_python/resources/_debugger_case_module_entry_point.py create mode 100644 tests_python/resources/_debugger_case_multi_threads_stepping.py create mode 100644 tests_python/resources/_debugger_case_multiple_threads.py create mode 100644 tests_python/resources/_debugger_case_multiprocessing.py create mode 100644 tests_python/resources/_debugger_case_multiprocessing_2.py create mode 100644 tests_python/resources/_debugger_case_multiprocessing_pool.py create mode 100644 tests_python/resources/_debugger_case_multiprocessing_stopped_threads.py create mode 100644 tests_python/resources/_debugger_case_namedtuple.py create mode 100644 tests_python/resources/_debugger_case_no_subprocess_patching.py create mode 100644 tests_python/resources/_debugger_case_odict.py create mode 100644 tests_python/resources/_debugger_case_path_translation.py create mode 100644 tests_python/resources/_debugger_case_pause_continue.py create mode 100644 tests_python/resources/_debugger_case_print.py create mode 100644 tests_python/resources/_debugger_case_pydevd_customization.py create mode 100644 tests_python/resources/_debugger_case_python_c.py create mode 100644 tests_python/resources/_debugger_case_qthread1.py create mode 100644 tests_python/resources/_debugger_case_qthread2.py create mode 100644 tests_python/resources/_debugger_case_qthread3.py create mode 100644 tests_python/resources/_debugger_case_qthread4.py create mode 100644 tests_python/resources/_debugger_case_quoting.py create mode 100644 tests_python/resources/_debugger_case_raise_with_cause.py create mode 100644 tests_python/resources/_debugger_case_redirect.py create mode 100644 tests_python/resources/_debugger_case_remote.py create mode 100644 tests_python/resources/_debugger_case_remote_1.py create mode 100644 tests_python/resources/_debugger_case_remote_2.py create mode 100644 tests_python/resources/_debugger_case_remote_threads.py create mode 100644 tests_python/resources/_debugger_case_remote_unhandled_exceptions.py create mode 100644 tests_python/resources/_debugger_case_remote_unhandled_exceptions2.py create mode 100644 tests_python/resources/_debugger_case_remove_breakpoint.py create mode 100644 tests_python/resources/_debugger_case_replace_process.py create mode 100644 tests_python/resources/_debugger_case_return_value.py create mode 100644 tests_python/resources/_debugger_case_return_value_asyncio.py create mode 100644 tests_python/resources/_debugger_case_scapy.py create mode 100644 tests_python/resources/_debugger_case_scoped_stepping.py create mode 100644 tests_python/resources/_debugger_case_scoped_stepping_target.py create mode 100644 tests_python/resources/_debugger_case_scoped_stepping_target2.py create mode 100644 tests_python/resources/_debugger_case_scoped_stepping_target_async.py create mode 100644 tests_python/resources/_debugger_case_set_next_statement.py create mode 100644 tests_python/resources/_debugger_case_settrace.py create mode 100644 tests_python/resources/_debugger_case_show_bytecode.py create mode 100644 tests_python/resources/_debugger_case_simple_calls.py create mode 100644 tests_python/resources/_debugger_case_skip_breakpoint_in_exceptions.py create mode 100644 tests_python/resources/_debugger_case_smart_step_into.py create mode 100644 tests_python/resources/_debugger_case_smart_step_into2.py create mode 100644 tests_python/resources/_debugger_case_smart_step_into3.py create mode 100644 tests_python/resources/_debugger_case_source_map_goto_target.py create mode 100644 tests_python/resources/_debugger_case_source_mapping.py create mode 100644 tests_python/resources/_debugger_case_source_mapping_and_reference.py create mode 100644 tests_python/resources/_debugger_case_source_mapping_jmc.py create mode 100644 tests_python/resources/_debugger_case_source_reference.py create mode 100644 tests_python/resources/_debugger_case_stepping.py create mode 100644 tests_python/resources/_debugger_case_stop_async_iteration.py create mode 100644 tests_python/resources/_debugger_case_subprocess_and_fork.py create mode 100644 tests_python/resources/_debugger_case_subprocess_target.zip create mode 100644 tests_python/resources/_debugger_case_subprocess_zip.py create mode 100644 tests_python/resources/_debugger_case_suspend_all.py create mode 100644 tests_python/resources/_debugger_case_suspend_policy.py create mode 100644 tests_python/resources/_debugger_case_sysexit.py create mode 100644 tests_python/resources/_debugger_case_sysexit_0.py create mode 100644 tests_python/resources/_debugger_case_sysexit_none.py create mode 100644 tests_python/resources/_debugger_case_terminate.py create mode 100644 tests_python/resources/_debugger_case_thread_creation_deadlock.py create mode 100644 tests_python/resources/_debugger_case_thread_started_exited.py create mode 100644 tests_python/resources/_debugger_case_trace_dispatch.py create mode 100644 tests_python/resources/_debugger_case_tracing.py create mode 100644 tests_python/resources/_debugger_case_trio.py create mode 100644 tests_python/resources/_debugger_case_type_ext.py create mode 100644 tests_python/resources/_debugger_case_unhandled_exception_get_stack.py create mode 100644 tests_python/resources/_debugger_case_unhandled_exceptions.py create mode 100644 tests_python/resources/_debugger_case_unhandled_exceptions_custom.py create mode 100644 tests_python/resources/_debugger_case_unhandled_exceptions_generator.py create mode 100644 tests_python/resources/_debugger_case_unhandled_exceptions_listcomp.py create mode 100644 tests_python/resources/_debugger_case_unhandled_exceptions_on_top_level.py create mode 100644 tests_python/resources/_debugger_case_unhandled_exceptions_on_top_level2.py create mode 100644 tests_python/resources/_debugger_case_unhandled_just_my_code.py create mode 100644 tests_python/resources/_debugger_case_user_unhandled.py create mode 100644 tests_python/resources/_debugger_case_user_unhandled2.py create mode 100644 tests_python/resources/_debugger_case_variables_with_same_name.py create mode 100644 tests_python/resources/_debugger_case_wait_for_attach.py create mode 100644 tests_python/resources/_debugger_case_wait_for_attach_impl.py create mode 100644 tests_python/resources/_debugger_case_warnings.py create mode 100644 tests_python/resources/_debugger_case_yield_from.py create mode 100644 tests_python/resources/_debugger_case_zip_files.py create mode 100644 tests_python/resources/_performance_1.py create mode 100644 tests_python/resources/_performance_2.py create mode 100644 tests_python/resources/_performance_3.py create mode 100644 tests_python/resources/_pydev_coverage_cyrillic_encoding_py2.py create mode 100644 tests_python/resources/_pydev_coverage_cyrillic_encoding_py3.py create mode 100644 tests_python/resources/_pydev_coverage_syntax_error.py create mode 100644 tests_python/resources/_pydevd_test_find_main_thread_id.py create mode 100644 tests_python/resources/launch/foo/__main__.py create mode 100644 tests_python/resources/launch/foo/bar.py create mode 100644 tests_python/resources/launch_py2/__init__.py create mode 100644 tests_python/resources/launch_py2/foo/__init__.py create mode 100644 tests_python/resources/launch_py2/foo/__main__.py create mode 100644 tests_python/resources/launch_py2/foo/bar.py create mode 100644 tests_python/resources/my_code/__init__.py create mode 100644 tests_python/resources/my_code/my_code.py create mode 100644 tests_python/resources/my_code/my_code_coroutine.py create mode 100644 tests_python/resources/my_code/my_code_coroutine_user_unhandled.py create mode 100644 tests_python/resources/my_code/my_code_coroutine_user_unhandled_no_stop.py create mode 100644 tests_python/resources/my_code/my_code_double_step.py create mode 100644 tests_python/resources/my_code/my_code_exception.py create mode 100644 tests_python/resources/my_code/my_code_exception_on_other.py create mode 100644 tests_python/resources/my_code/my_code_exception_user_unhandled.py create mode 100644 tests_python/resources/my_code/my_code_on_entry.py create mode 100644 tests_python/resources/not_my_code/__init__.py create mode 100644 tests_python/resources/not_my_code/empty_file.py create mode 100644 tests_python/resources/not_my_code/main_on_entry.py create mode 100644 tests_python/resources/not_my_code/main_on_entry2.py create mode 100644 tests_python/resources/not_my_code/not_my_coroutine.py create mode 100644 tests_python/resources/not_my_code/other.py create mode 100644 tests_python/resources/not_my_code/other_noop.py create mode 100644 tests_python/resources/wrong_bytecode/_debugger_case_wrong_bytecode.py create mode 100644 tests_python/resources/wrong_bytecode/helper/__init__.py create mode 100644 tests_python/resources/wrong_bytecode/helper/helper/__init__.py create mode 100644 tests_python/resources/wrong_bytecode/helper/helper/helper/__init__.py create mode 100644 tests_python/test_additional_thread_info.py create mode 100644 tests_python/test_bytecode_manipulation.py create mode 100644 tests_python/test_code_obj_to_source_code.py create mode 100644 tests_python/test_collect_bytecode_info.py create mode 100644 tests_python/test_collect_bytecode_info/test_collect_try_except_info.json create mode 100644 tests_python/test_collect_bytecode_info/test_iter_bytecode.py26.json create mode 100644 tests_python/test_collect_bytecode_info/test_iter_bytecode.py27.json create mode 100644 tests_python/test_collect_bytecode_info/test_iter_bytecode.py36.json create mode 100644 tests_python/test_collect_bytecode_info/test_iter_bytecode.py37.json create mode 100644 tests_python/test_console.py create mode 100644 tests_python/test_convert_utilities.py create mode 100644 tests_python/test_debugger.py create mode 100644 tests_python/test_debugger_json.py create mode 100644 tests_python/test_dump_threads.py create mode 100644 tests_python/test_evaluate_expression.py create mode 100644 tests_python/test_extract_token.py create mode 100644 tests_python/test_fixtures.py create mode 100644 tests_python/test_frame_eval_and_tracing.py create mode 100644 tests_python/test_frame_evaluator.py create mode 100644 tests_python/test_null.py create mode 100644 tests_python/test_process_command_line.py create mode 100644 tests_python/test_pydev_monkey.py create mode 100644 tests_python/test_pydevcoverage.py create mode 100644 tests_python/test_pydevd_api.py create mode 100644 tests_python/test_pydevd_filtering.py create mode 100644 tests_python/test_pydevd_io.py create mode 100644 tests_python/test_resolvers.py create mode 100644 tests_python/test_run.py create mode 100644 tests_python/test_safe_repr.py create mode 100644 tests_python/test_save_locals.py create mode 100644 tests_python/test_schema.py create mode 100644 tests_python/test_smart_step_into_bytecode.py create mode 100644 tests_python/test_suspended_frames_manager.py create mode 100644 tests_python/test_timeout_tracker.py create mode 100644 tests_python/test_tracing_gotchas.py create mode 100644 tests_python/test_tracing_on_top_level.py create mode 100644 tests_python/test_utilities.py create mode 100644 tests_python/tests_single_notification.py create mode 100644 tests_runfiles/not_in_default_pythonpath.txt create mode 100644 tests_runfiles/samples/.cvsignore create mode 100644 tests_runfiles/samples/nested_dir/.cvsignore create mode 100644 tests_runfiles/samples/nested_dir/__init__.py create mode 100644 tests_runfiles/samples/nested_dir/nested2/.cvsignore create mode 100644 tests_runfiles/samples/nested_dir/nested2/__init__.py create mode 100644 tests_runfiles/samples/nested_dir/nested2/deep_nest_test.py create mode 100644 tests_runfiles/samples/nested_dir/nested2/non_test_file.py create mode 100644 tests_runfiles/samples/nested_dir/nested3/.cvsignore create mode 100644 tests_runfiles/samples/nested_dir/nested3/__init__.py create mode 100644 tests_runfiles/samples/nested_dir/nested3/junk.txt create mode 100644 tests_runfiles/samples/nested_dir/nested3/non_test_file.py create mode 100644 tests_runfiles/samples/nested_dir/non_test_file.py create mode 100644 tests_runfiles/samples/nested_dir/simple4_test.py create mode 100644 tests_runfiles/samples/non_test_file.py create mode 100644 tests_runfiles/samples/not_in_default_pythonpath.txt create mode 100644 tests_runfiles/samples/simple2_test.py create mode 100644 tests_runfiles/samples/simple3_test.py create mode 100644 tests_runfiles/samples/simpleClass_test.py create mode 100644 tests_runfiles/samples/simpleModule_test.py create mode 100644 tests_runfiles/samples/simple_test.py create mode 100644 tests_runfiles/test_pydevd_property.py create mode 100644 tests_runfiles/test_pydevdio.py create mode 100644 tests_runfiles/test_runfiles.py diff --git a/.github/install_and_run_debug_py.sh b/.github/install_and_run_debug_py.sh new file mode 100644 index 0000000..8a38cf4 --- /dev/null +++ b/.github/install_and_run_debug_py.sh @@ -0,0 +1,35 @@ +# Build the cython extensions (to check that we don't crash when they're there in debug mode). +python setup_pydevd_cython.py build_ext --inplace + +curl -L https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz -o Python-3.8.3.tgz +tar -xzf Python-3.8.3.tgz +cd Python-3.8.3 +mkdir debug +cd debug +../configure --with-pydebug +make + +curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py +./python get-pip.py + +./python -m pip install "pytest" +./python -m pip install "psutil" +./python -m pip install "untangle" + +# Check that it worked. +./python -c "import pytest" +./python -c "import psutil" +./python -c "import untangle" + +cd .. +cd .. +ls -la + +./Python-3.8.3/debug/python -c "import sys;assert hasattr(sys,'gettotalrefcount')" + +cd tests_python + +# Although we compiled cython, all we're checking is that we don't crash (since it was built for the release env). +../Python-3.8.3/debug/python -m pytest test_debugger_json.py -k "test_case_json_change_breaks or test_remote_debugger_basic" +export PYTHONPATH=.. +../Python-3.8.3/debug/python -c "import check_debug_python;check_debug_python.check() " diff --git a/.github/workflows/pydevd-tests-python.yml b/.github/workflows/pydevd-tests-python.yml new file mode 100644 index 0000000..85e7c43 --- /dev/null +++ b/.github/workflows/pydevd-tests-python.yml @@ -0,0 +1,117 @@ +name: PyDev.Debugger Tests + +on: + - push + - pull_request + +env: + DISPLAY: ":99" + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + name: [ + "ubuntu-pypy3", + "macos-py37-cython", + "ubuntu-py38-cython-checkbin", + "windows-py39-cython", + "windows-py310-cython", + "windows-py311-cython", + ] + + include: + - name: "ubuntu-pypy3" + python: "pypy3" + os: ubuntu-latest + PYDEVD_USE_CYTHON: NO + - name: "macos-py37-cython" + python: "3.7" + os: macos-latest + PYDEVD_USE_CYTHON: YES + - name: "ubuntu-py38-cython-checkbin" + python: "3.8" + os: ubuntu-latest + PYDEVD_USE_CYTHON: YES + - name: "windows-py39-cython" + python: "3.9" + os: windows-latest + PYDEVD_USE_CYTHON: YES + - name: "windows-py310-cython" + python: "3.10" + os: windows-latest + PYDEVD_USE_CYTHON: YES + # See: https://github.com/actions/python-versions/releases + - name: "windows-py311-cython" + python: "3.11.0-beta.3" + os: windows-latest + PYDEVD_USE_CYTHON: YES + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python }} + - name: Install gdb/xvfb/ptrace_scope + run: | + sudo apt-get update + sudo apt-get install gdb + sudo sysctl kernel.yama.ptrace_scope=0 + sudo apt-get install xvfb + sudo apt-get install libqt5x11extras5 + Xvfb -ac :99 -screen 0 1280x1024x16 > /dev/null 2>&1 & + if: contains(matrix.name, 'ubuntu') + - name: Install common Python deps + run: | + pip install --upgrade pip + pip install wheel --no-warn-script-location + pip install cython --no-warn-script-location + pip install psutil --no-warn-script-location + pip install numpy --no-warn-script-location + pip install pytest --no-warn-script-location + pip install pytest-xdist --no-warn-script-location + pip install psutil --no-warn-script-location + pip install ipython --no-warn-script-location + pip install untangle --no-warn-script-location + - name: Install Python 3.x deps + if: contains(matrix.name, 'py3') && !contains(matrix.name, 'pypy') && !contains(matrix.name, 'py311') + run: | + pip install PySide2 --no-warn-script-location + pip install django + pip install cherrypy --no-warn-script-location + pip install gevent + - name: Install Pandas + if: contains(matrix.name, 'py310') && !contains(matrix.name, 'pypy') + # The pandas Styler also requires jinja2. + run: pip install pandas jinja2 --no-warn-script-location + - name: Install Pypy 3 deps + if: contains(matrix.name, 'py3') + run: | + pip install trio + - name: Check cython unchanged + if: contains(matrix.name, 'checkbin') + env: + PYTHONPATH: . + run: | + python build_tools/build.py + python build_tools/check_no_git_modifications.py + - name: Create cython binaries + if: contains(matrix.name, 'cython') + run: | + python setup_pydevd_cython.py build_ext --inplace + - name: Check debug + if: contains(matrix.name, 'checkdebug') + run: | + ./.github/install_and_run_debug_py.sh + - name: Run Python 3.x tests + env: + # QT_DEBUG_PLUGINS: 1 + PYTHONPATH: . + PYDEVD_USE_CYTHON: ${{matrix.PYDEVD_USE_CYTHON }} + run: | + python -m pytest -n auto -rf + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b03edda --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*.class +_pydevd_bundle/*.so +# Distribution / packaging +.Python +env/ +bin/ +build/temp.* +develop-eggs/ +dist/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg +.vscode + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +snippet.py +build/* +.pytest_cache +/.mypy_cache/ diff --git a/.project b/.project new file mode 100644 index 0000000..a6cc6d6 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + PyDev.Debugger + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000..84c06fb --- /dev/null +++ b/.pydevproject @@ -0,0 +1,34 @@ + + + + + + + + /${PROJECT_DIR_NAME} + + + /${PROJECT_DIR_NAME}/build_tools + + + /${PROJECT_DIR_NAME}/jython_test_deps/ant.jar + + + /${PROJECT_DIR_NAME}/jython_test_deps/junit.jar + + + /${PROJECT_DIR_NAME}/pydevd_attach_to_process + + + + + + python interpreter + + + Default + + + 3.6 + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..ef94674 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,45 @@ +eclipse.preferences.version=1 +encoding//.settings/org.python.pydev.yaml=UTF-8 +encoding//_pydevd_bundle/_debug_adapter/pydevd_schema.py=utf-8 +encoding//pydev_ipython/inputhook.py=utf-8 +encoding//pydev_ipython/inputhookglut.py=utf-8 +encoding//pydev_ipython/inputhookgtk.py=utf-8 +encoding//pydev_ipython/inputhookgtk3.py=utf-8 +encoding//pydev_ipython/inputhookpyglet.py=utf-8 +encoding//pydev_ipython/inputhookqt4.py=utf-8 +encoding//pydev_ipython/inputhookqt5.py=utf-8 +encoding//pydev_ipython/inputhooktk.py=utf-8 +encoding//pydev_ipython/inputhookwx.py=utf-8 +encoding//pydev_ipython/version.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/breakpoint.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/crash.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/interactive.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/process.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/thread.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/util.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/__init__.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/advapi32.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/context_amd64.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/context_i386.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/dbghelp.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/defines.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/gdi32.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/kernel32.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/ntdll.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/peb_teb.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/psapi.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/shell32.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/shlwapi.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/user32.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/version.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/wtsapi32.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/window.py=utf-8 +encoding//tests_python/debugger_fixtures.py=utf-8 +encoding//tests_python/resources/_debugger_case_redirect.py=utf-8 +encoding//tests_python/test_collect_bytecode_info.py=utf-8 +encoding//tests_python/test_convert_utilities.py=utf-8 +encoding//tests_python/test_debugger.py=utf-8 +encoding//tests_python/test_debugger_json.py=utf-8 +encoding//tests_python/test_extract_token.py=utf-8 +encoding//tests_python/test_pydev_monkey.py=utf-8 +encoding//tests_python/test_safe_repr.py=utf-8 diff --git a/.settings/org.python.pydev.yaml b/.settings/org.python.pydev.yaml new file mode 100644 index 0000000..4a90160 --- /dev/null +++ b/.settings/org.python.pydev.yaml @@ -0,0 +1,47 @@ +ADD_NEW_LINE_AT_END_OF_FILE: true +AUTOPEP8_PARAMETERS: '' +AUTO_ADD_SELF: true +AUTO_BRACES: true +AUTO_COLON: true +AUTO_DEDENT_ELSE: true +AUTO_INDENT_AFTER_PAR_WIDTH: 1 +AUTO_INDENT_TO_PAR_LEVEL: false +AUTO_LINK: false +AUTO_LITERALS: true +AUTO_PAR: true +AUTO_WRITE_IMPORT_STR: true +BLACK_PARAMETERS: '' +BLANK_LINES_INNER: 1 +BLANK_LINES_TOP_LEVEL: 2 +BREAK_IMPORTS_MODE: PARENTHESIS +DATE_FIELD_FORMAT: yyyy-MM-dd +DATE_FIELD_NAME: __updated__ +DELETE_UNUSED_IMPORTS: false +ENABLE_DATE_FIELD_ACTION: false +FORMATTER_STYLE: PYDEVF +FORMAT_BEFORE_SAVING: true +FORMAT_ONLY_CHANGED_LINES: false +FORMAT_WITH_AUTOPEP8: false +FROM_IMPORTS_FIRST: false +GROUP_IMPORTS: true +IMPORT_ENGINE: IMPORT_ENGINE_PEP_8 +INDENT_AFTER_PAR_AS_PEP8: false +MANAGE_BLANK_LINES: true +MULTILINE_IMPORTS: true +PEP8_IMPORTS: true +PYDEV_TEST_RUNNER: '2' +PYDEV_TEST_RUNNER_DEFAULT_PARAMETERS: --capture=no -vv --tb=native -n 0 +PYDEV_USE_PYUNIT_VIEW: true +SAVE_ACTIONS_ONLY_ON_WORKSPACE_FILES: true +SMART_INDENT_PAR: true +SMART_LINE_MOVE: false +SORT_IMPORTS_ON_SAVE: false +SORT_NAMES_GROUPED: false +SPACES_BEFORE_COMMENT: '2' +SPACES_IN_START_COMMENT: '1' +TRIM_EMPTY_LINES: true +TRIM_MULTILINE_LITERALS: true +USE_ASSIGN_WITH_PACES_INSIDER_PARENTESIS: false +USE_OPERATORS_WITH_SPACE: true +USE_SPACE_AFTER_COMMA: true +USE_SPACE_FOR_PARENTESIS: false diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5032843 --- /dev/null +++ b/LICENSE @@ -0,0 +1,203 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation + distributed under this Agreement, and +b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + + where such changes and/or additions to the Program originate from and are + distributed by that particular Contributor. A Contribution 'originates' + from a Contributor if it was added to the Program by such Contributor + itself or anyone acting on such Contributor's behalf. Contributions do not + include additions to the Program which: (i) are separate modules of + software distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + a) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free copyright license to + reproduce, prepare derivative works of, publicly display, publicly + perform, distribute and sublicense the Contribution of such Contributor, + if any, and such derivative works, in source code and object code form. + b) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free patent license under + Licensed Patents to make, use, sell, offer to sell, import and otherwise + transfer the Contribution of such Contributor, if any, in source code and + object code form. This patent license shall apply to the combination of + the Contribution and the Program if, at the time the Contribution is + added by the Contributor, such addition of the Contribution causes such + combination to be covered by the Licensed Patents. The patent license + shall not apply to any other combinations which include the Contribution. + No hardware per se is licensed hereunder. + c) Recipient understands that although each Contributor grants the licenses + to its Contributions set forth herein, no assurances are provided by any + Contributor that the Program does not infringe the patent or other + intellectual property rights of any other entity. Each Contributor + disclaims any liability to Recipient for claims brought by any other + entity based on infringement of intellectual property rights or + otherwise. As a condition to exercising the rights and licenses granted + hereunder, each Recipient hereby assumes sole responsibility to secure + any other intellectual property rights needed, if any. For example, if a + third party patent license is required to allow Recipient to distribute + the Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + d) Each Contributor represents that to its knowledge it has sufficient + copyright rights in its Contribution, if any, to grant the copyright + license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under +its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + b) its license agreement: + i) effectively disclaims on behalf of all Contributors all warranties + and conditions, express and implied, including warranties or + conditions of title and non-infringement, and implied warranties or + conditions of merchantability and fitness for a particular purpose; + ii) effectively excludes on behalf of all Contributors all liability for + damages, including direct, indirect, special, incidental and + consequential damages, such as lost profits; + iii) states that any provisions which differ from this Agreement are + offered by that Contributor alone and not by any other party; and + iv) states that source code for the Program is available from such + Contributor, and informs licensees how to obtain it in a reasonable + manner on or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + b) a copy of this Agreement must be included with each copy of the Program. + Contributors may not remove or alter any copyright notices contained + within the Program. + +Each Contributor must identify itself as the originator of its Contribution, +if +any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, +if a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such Commercial +Contributor in connection with its distribution of the Program in a commercial +product offering. The obligations in this section do not apply to any claims +or Losses relating to any actual or alleged intellectual property +infringement. In order to qualify, an Indemnified Contributor must: +a) promptly notify the Commercial Contributor in writing of such claim, and +b) allow the Commercial Contributor to control, and cooperate with the +Commercial Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any such claim at +its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If +that Commercial Contributor then makes performance claims, or offers +warranties related to Product X, those performance claims and warranties are +such Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with its +exercise of rights under this Agreement , including but not limited to the +risks and costs of program errors, compliance with applicable laws, damage to +or loss of data, programs or equipment, and unavailability or interruption of +operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION +LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this Agreement, and without further action by the +parties hereto, such provision shall be reformed to the minimum extent +necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Program itself +(excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted +under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue +and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to +time. No one other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement Steward. The +Eclipse Foundation may assign the responsibility to serve as the Agreement +Steward to a suitable separate entity. Each new version of the Agreement will +be given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the +Agreement under which it was received. In addition, after a new version of the +Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly +stated in Sections 2(a) and 2(b) above, Recipient receives no rights or +licenses to the intellectual property of any Contributor under this Agreement, +whether expressly, by implication, estoppel or otherwise. All rights in the +Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial in +any resulting litigation. \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..61e38e3 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,8 @@ +include *.rst *.txt *.md LICENSE *.pyx *.cpp *.hpp +recursive-include pydevd_attach_to_process *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp +recursive-include pydevd_attach_to_process/common *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp +recursive-include pydevd_attach_to_process/linux_and_mac *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp +recursive-include pydevd_attach_to_process/winappdbg *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp +recursive-include pydevd_attach_to_process/windows *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp +recursive-include _pydevd_bundle *.pyx *.cpp *.hpp +recursive-include build_tools *.py \ No newline at end of file diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..e8e25ec --- /dev/null +++ b/README.rst @@ -0,0 +1,37 @@ +PyDev.Debugger +============== + +The sources for the PyDev.Debugger may be seen at: + +https://github.com/fabioz/PyDev.Debugger + +In general, the debugger backend should **NOT** be installed separately if you're using an IDE which already +bundles it (such as PyDev, PyCharm or bundled through debugpy, which is the debug adapter used in +VSCode Python and Visual Studio Python). + +It is however available in PyPi so that it can be installed for doing remote debugging with `pip` -- so, when +debugging a process which runs in another machine, it's possible to `pip install pydevd` and in the code use +`pydevd.settrace(host='10.1.1.1')` to connect the debugger backend to the debugger UI running in the IDE +(whereas previously the sources had to be manually copied from the IDE installation). + +It should be compatible with Python 2.7 onwards (as well as Jython 2.7, IronPython and PyPy -- and +any other variant which properly supports the Python structure for debuggers -- i.e.: sys.settrace/threading.settrace). + +Recent versions contain speedup modules using Cython, which are generated with a few changes in the regular files +to `cythonize` the files. To update and compile the cython sources (and generate some other auto-generated files), +`build_tools/build.py` should be run -- note that the resulting .pyx and .c files should be commited. + +To generate a distribution with the precompiled binaries for the IDE, `build_binaries_windows.py` should be run ( +note that the environments must be pre-created as specified in that file). + +To generate a distribution to upload to PyPi, `python setup.py sdist bdist_wheel` should be run for each python version +which should have a wheel and afterwards `twine upload -s dist/pydevd-*` should be run to actually upload the contents +to PyPi. + +GitHub Actions (CI): + +.. |github_actions| https://github.com/fabioz/PyDev.Debugger/workflows/PyDev.Debugger Tests/badge.svg + :target: https://github.com/fabioz/PyDev.Debugger/workflows/PyDev.Debugger Tests/badge.svg + +|github_actions| + diff --git a/_pydev_bundle/__init__.py b/_pydev_bundle/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/_pydev_bundle/_pydev_calltip_util.py b/_pydev_bundle/_pydev_calltip_util.py new file mode 100644 index 0000000..aca108f --- /dev/null +++ b/_pydev_bundle/_pydev_calltip_util.py @@ -0,0 +1,155 @@ +''' +License: Apache 2.0 +Author: Yuli Fitterman +''' +import types + +from _pydevd_bundle.pydevd_constants import IS_JYTHON + +try: + import inspect +except: + import traceback; + + traceback.print_exc() # Ok, no inspect available (search will not work) + +from _pydev_bundle._pydev_imports_tipper import signature_from_docstring + + +def is_bound_method(obj): + if isinstance(obj, types.MethodType): + return getattr(obj, '__self__', getattr(obj, 'im_self', None)) is not None + else: + return False + + +def get_class_name(instance): + return getattr(getattr(instance, "__class__", None), "__name__", None) + + +def get_bound_class_name(obj): + my_self = getattr(obj, '__self__', getattr(obj, 'im_self', None)) + if my_self is None: + return None + return get_class_name(my_self) + + +def get_description(obj): + try: + ob_call = obj.__call__ + except: + ob_call = None + + if isinstance(obj, type) or type(obj).__name__ == 'classobj': + fob = getattr(obj, '__init__', lambda: None) + if not isinstance(fob, (types.FunctionType, types.MethodType)): + fob = obj + elif is_bound_method(ob_call): + fob = ob_call + else: + fob = obj + + argspec = "" + fn_name = None + fn_class = None + if isinstance(fob, (types.FunctionType, types.MethodType)): + spec_info = inspect.getfullargspec(fob) + argspec = inspect.formatargspec(*spec_info) + fn_name = getattr(fob, '__name__', None) + if isinstance(obj, type) or type(obj).__name__ == 'classobj': + fn_name = "__init__" + fn_class = getattr(obj, "__name__", "UnknownClass") + elif is_bound_method(obj) or is_bound_method(ob_call): + fn_class = get_bound_class_name(obj) or "UnknownClass" + + else: + fn_name = getattr(fob, '__name__', None) + fn_self = getattr(fob, '__self__', None) + if fn_self is not None and not isinstance(fn_self, types.ModuleType): + fn_class = get_class_name(fn_self) + + doc_string = get_docstring(ob_call) if is_bound_method(ob_call) else get_docstring(obj) + return create_method_stub(fn_name, fn_class, argspec, doc_string) + + +def create_method_stub(fn_name, fn_class, argspec, doc_string): + if fn_name and argspec: + doc_string = "" if doc_string is None else doc_string + fn_stub = create_function_stub(fn_name, argspec, doc_string, indent=1 if fn_class else 0) + if fn_class: + expr = fn_class if fn_name == '__init__' else fn_class + '().' + fn_name + return create_class_stub(fn_class, fn_stub) + "\n" + expr + else: + expr = fn_name + return fn_stub + "\n" + expr + elif doc_string: + if fn_name: + restored_signature, _ = signature_from_docstring(doc_string, fn_name) + if restored_signature: + return create_method_stub(fn_name, fn_class, restored_signature, doc_string) + return create_function_stub('unknown', '(*args, **kwargs)', doc_string) + '\nunknown' + + else: + return '' + + +def get_docstring(obj): + if obj is not None: + try: + if IS_JYTHON: + # Jython + doc = obj.__doc__ + if doc is not None: + return doc + + from _pydev_bundle import _pydev_jy_imports_tipper + + is_method, infos = _pydev_jy_imports_tipper.ismethod(obj) + ret = '' + if is_method: + for info in infos: + ret += info.get_as_doc() + return ret + + else: + + doc = inspect.getdoc(obj) + if doc is not None: + return doc + except: + pass + else: + return '' + try: + # if no attempt succeeded, try to return repr()... + return repr(obj) + except: + try: + # otherwise the class + return str(obj.__class__) + except: + # if all fails, go to an empty string + return '' + + +def create_class_stub(class_name, contents): + return "class %s(object):\n%s" % (class_name, contents) + + +def create_function_stub(fn_name, fn_argspec, fn_docstring, indent=0): + + def shift_right(string, prefix): + return ''.join(prefix + line for line in string.splitlines(True)) + + fn_docstring = shift_right(inspect.cleandoc(fn_docstring), " " * (indent + 1)) + ret = ''' +def %s%s: + """%s""" + pass +''' % (fn_name, fn_argspec, fn_docstring) + ret = ret[1:] # remove first /n + ret = ret.replace('\t', " ") + if indent: + prefix = " " * indent + ret = shift_right(ret, prefix) + return ret diff --git a/_pydev_bundle/_pydev_completer.py b/_pydev_bundle/_pydev_completer.py new file mode 100644 index 0000000..ed0db4e --- /dev/null +++ b/_pydev_bundle/_pydev_completer.py @@ -0,0 +1,267 @@ +from collections import namedtuple +from string import ascii_letters, digits + +from _pydevd_bundle import pydevd_xml +import pydevconsole + +import builtins as __builtin__ # Py3 + +try: + import java.lang # @UnusedImport + from _pydev_bundle import _pydev_jy_imports_tipper + _pydev_imports_tipper = _pydev_jy_imports_tipper +except ImportError: + IS_JYTHON = False + from _pydev_bundle import _pydev_imports_tipper + +dir2 = _pydev_imports_tipper.generate_imports_tip_for_module + + +#======================================================================================================================= +# _StartsWithFilter +#======================================================================================================================= +class _StartsWithFilter: + ''' + Used because we can't create a lambda that'll use an outer scope in jython 2.1 + ''' + + def __init__(self, start_with): + self.start_with = start_with.lower() + + def __call__(self, name): + return name.lower().startswith(self.start_with) + + +#======================================================================================================================= +# Completer +# +# This class was gotten from IPython.completer (dir2 was replaced with the completer already in pydev) +#======================================================================================================================= +class Completer: + + def __init__(self, namespace=None, global_namespace=None): + """Create a new completer for the command line. + + Completer([namespace,global_namespace]) -> completer instance. + + If unspecified, the default namespace where completions are performed + is __main__ (technically, __main__.__dict__). Namespaces should be + given as dictionaries. + + An optional second namespace can be given. This allows the completer + to handle cases where both the local and global scopes need to be + distinguished. + + Completer instances should be used as the completion mechanism of + readline via the set_completer() call: + + readline.set_completer(Completer(my_namespace).complete) + """ + + # Don't bind to namespace quite yet, but flag whether the user wants a + # specific namespace or to use __main__.__dict__. This will allow us + # to bind to __main__.__dict__ at completion time, not now. + if namespace is None: + self.use_main_ns = 1 + else: + self.use_main_ns = 0 + self.namespace = namespace + + # The global namespace, if given, can be bound directly + if global_namespace is None: + self.global_namespace = {} + else: + self.global_namespace = global_namespace + + def complete(self, text): + """Return the next possible completion for 'text'. + + This is called successively with state == 0, 1, 2, ... until it + returns None. The completion should begin with 'text'. + + """ + if self.use_main_ns: + # In pydev this option should never be used + raise RuntimeError('Namespace must be provided!') + self.namespace = __main__.__dict__ # @UndefinedVariable + + if "." in text: + return self.attr_matches(text) + else: + return self.global_matches(text) + + def global_matches(self, text): + """Compute matches when text is a simple name. + + Return a list of all keywords, built-in functions and names currently + defined in self.namespace or self.global_namespace that match. + + """ + + def get_item(obj, attr): + return obj[attr] + + a = {} + + for dict_with_comps in [__builtin__.__dict__, self.namespace, self.global_namespace]: # @UndefinedVariable + a.update(dict_with_comps) + + filter = _StartsWithFilter(text) + + return dir2(a, a.keys(), get_item, filter) + + def attr_matches(self, text): + """Compute matches when text contains a dot. + + Assuming the text is of the form NAME.NAME....[NAME], and is + evaluatable in self.namespace or self.global_namespace, it will be + evaluated and its attributes (as revealed by dir()) are used as + possible completions. (For class instances, class members are are + also considered.) + + WARNING: this can still invoke arbitrary C code, if an object + with a __getattr__ hook is evaluated. + + """ + import re + + # Another option, seems to work great. Catches things like ''. + m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) # @UndefinedVariable + + if not m: + return [] + + expr, attr = m.group(1, 3) + try: + obj = eval(expr, self.namespace) + except: + try: + obj = eval(expr, self.global_namespace) + except: + return [] + + filter = _StartsWithFilter(attr) + + words = dir2(obj, filter=filter) + + return words + + +def generate_completions(frame, act_tok): + ''' + :return list(tuple(method_name, docstring, parameters, completion_type)) + + method_name: str + docstring: str + parameters: str -- i.e.: "(a, b)" + completion_type is an int + See: _pydev_bundle._pydev_imports_tipper for TYPE_ constants + ''' + if frame is None: + return [] + + # Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329 + # (Names not resolved in generator expression in method) + # See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html + updated_globals = {} + updated_globals.update(frame.f_globals) + updated_globals.update(frame.f_locals) # locals later because it has precedence over the actual globals + + if pydevconsole.IPYTHON: + completions = pydevconsole.get_completions(act_tok, act_tok, updated_globals, frame.f_locals) + else: + completer = Completer(updated_globals, None) + # list(tuple(name, descr, parameters, type)) + completions = completer.complete(act_tok) + + return completions + + +def generate_completions_as_xml(frame, act_tok): + completions = generate_completions(frame, act_tok) + return completions_to_xml(completions) + + +def completions_to_xml(completions): + valid_xml = pydevd_xml.make_valid_xml_value + quote = pydevd_xml.quote + msg = [""] + + for comp in completions: + msg.append('') + msg.append("") + + return ''.join(msg) + + +identifier_start = ascii_letters + '_' +identifier_part = ascii_letters + '_' + digits + +identifier_start = set(identifier_start) +identifier_part = set(identifier_part) + + +def isidentifier(s): + return s.isidentifier() + + +TokenAndQualifier = namedtuple('TokenAndQualifier', 'token, qualifier') + + +def extract_token_and_qualifier(text, line=0, column=0): + ''' + Extracts the token a qualifier from the text given the line/colum + (see test_extract_token_and_qualifier for examples). + + :param unicode text: + :param int line: 0-based + :param int column: 0-based + ''' + # Note: not using the tokenize module because text should be unicode and + # line/column refer to the unicode text (otherwise we'd have to know + # those ranges after converted to bytes). + if line < 0: + line = 0 + if column < 0: + column = 0 + + if isinstance(text, bytes): + text = text.decode('utf-8') + + lines = text.splitlines() + try: + text = lines[line] + except IndexError: + return TokenAndQualifier(u'', u'') + + if column >= len(text): + column = len(text) + + text = text[:column] + token = u'' + qualifier = u'' + + temp_token = [] + for i in range(column - 1, -1, -1): + c = text[i] + if c in identifier_part or isidentifier(c) or c == u'.': + temp_token.append(c) + else: + break + temp_token = u''.join(reversed(temp_token)) + if u'.' in temp_token: + temp_token = temp_token.split(u'.') + token = u'.'.join(temp_token[:-1]) + qualifier = temp_token[-1] + else: + qualifier = temp_token + + return TokenAndQualifier(token, qualifier) diff --git a/_pydev_bundle/_pydev_execfile.py b/_pydev_bundle/_pydev_execfile.py new file mode 100644 index 0000000..28ae403 --- /dev/null +++ b/_pydev_bundle/_pydev_execfile.py @@ -0,0 +1,14 @@ +# We must redefine it in Py3k if it's not already there +def execfile(file, glob=None, loc=None): + if glob is None: + import sys + glob = sys._getframe().f_back.f_globals + if loc is None: + loc = glob + + import tokenize + with tokenize.open(file) as stream: + contents = stream.read() + + # execute the script (note: it's important to compile first to have the filename set in debug mode) + exec(compile(contents + "\n", file, 'exec'), glob, loc) diff --git a/_pydev_bundle/_pydev_filesystem_encoding.py b/_pydev_bundle/_pydev_filesystem_encoding.py new file mode 100644 index 0000000..6264e3d --- /dev/null +++ b/_pydev_bundle/_pydev_filesystem_encoding.py @@ -0,0 +1,41 @@ +import sys + + +def __getfilesystemencoding(): + ''' + Note: there's a copy of this method in interpreterInfo.py + ''' + try: + ret = sys.getfilesystemencoding() + if not ret: + raise RuntimeError('Unable to get encoding.') + return ret + except: + try: + #Handle Jython + from java.lang import System # @UnresolvedImport + env = System.getProperty("os.name").lower() + if env.find('win') != -1: + return 'ISO-8859-1' #mbcs does not work on Jython, so, use a (hopefully) suitable replacement + return 'utf-8' + except: + pass + + #Only available from 2.3 onwards. + if sys.platform == 'win32': + return 'mbcs' + return 'utf-8' + +def getfilesystemencoding(): + try: + ret = __getfilesystemencoding() + + #Check if the encoding is actually there to be used! + if hasattr('', 'encode'): + ''.encode(ret) + if hasattr('', 'decode'): + ''.decode(ret) + + return ret + except: + return 'utf-8' diff --git a/_pydev_bundle/_pydev_getopt.py b/_pydev_bundle/_pydev_getopt.py new file mode 100644 index 0000000..5548651 --- /dev/null +++ b/_pydev_bundle/_pydev_getopt.py @@ -0,0 +1,130 @@ + +#======================================================================================================================= +# getopt code copied since gnu_getopt is not available on jython 2.1 +#======================================================================================================================= +class GetoptError(Exception): + opt = '' + msg = '' + def __init__(self, msg, opt=''): + self.msg = msg + self.opt = opt + Exception.__init__(self, msg, opt) + + def __str__(self): + return self.msg + + +def gnu_getopt(args, shortopts, longopts=[]): + """getopt(args, options[, long_options]) -> opts, args + + This function works like getopt(), except that GNU style scanning + mode is used by default. This means that option and non-option + arguments may be intermixed. The getopt() function stops + processing options as soon as a non-option argument is + encountered. + + If the first character of the option string is `+', or if the + environment variable POSIXLY_CORRECT is set, then option + processing stops as soon as a non-option argument is encountered. + """ + + opts = [] + prog_args = [] + if type('') == type(longopts): + longopts = [longopts] + else: + longopts = list(longopts) + + # Allow options after non-option arguments? + all_options_first = False + if shortopts.startswith('+'): + shortopts = shortopts[1:] + all_options_first = True + + while args: + if args[0] == '--': + prog_args += args[1:] + break + + if args[0][:2] == '--': + opts, args = do_longs(opts, args[0][2:], longopts, args[1:]) + elif args[0][:1] == '-': + opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:]) + else: + if all_options_first: + prog_args += args + break + else: + prog_args.append(args[0]) + args = args[1:] + + return opts, prog_args + +def do_longs(opts, opt, longopts, args): + try: + i = opt.index('=') + except ValueError: + optarg = None + else: + opt, optarg = opt[:i], opt[i + 1:] + + has_arg, opt = long_has_args(opt, longopts) + if has_arg: + if optarg is None: + if not args: + raise GetoptError('option --%s requires argument' % opt, opt) + optarg, args = args[0], args[1:] + elif optarg: + raise GetoptError('option --%s must not have an argument' % opt, opt) + opts.append(('--' + opt, optarg or '')) + return opts, args + +# Return: +# has_arg? +# full option name +def long_has_args(opt, longopts): + possibilities = [o for o in longopts if o.startswith(opt)] + if not possibilities: + raise GetoptError('option --%s not recognized' % opt, opt) + # Is there an exact match? + if opt in possibilities: + return False, opt + elif opt + '=' in possibilities: + return True, opt + # No exact match, so better be unique. + if len(possibilities) > 1: + # XXX since possibilities contains all valid continuations, might be + # nice to work them into the error msg + raise GetoptError('option --%s not a unique prefix' % opt, opt) + assert len(possibilities) == 1 + unique_match = possibilities[0] + has_arg = unique_match.endswith('=') + if has_arg: + unique_match = unique_match[:-1] + return has_arg, unique_match + +def do_shorts(opts, optstring, shortopts, args): + while optstring != '': + opt, optstring = optstring[0], optstring[1:] + if short_has_arg(opt, shortopts): + if optstring == '': + if not args: + raise GetoptError('option -%s requires argument' % opt, + opt) + optstring, args = args[0], args[1:] + optarg, optstring = optstring, '' + else: + optarg = '' + opts.append(('-' + opt, optarg)) + return opts, args + +def short_has_arg(opt, shortopts): + for i in range(len(shortopts)): + if opt == shortopts[i] != ':': + return shortopts.startswith(':', i + 1) + raise GetoptError('option -%s not recognized' % opt, opt) + + +#======================================================================================================================= +# End getopt code +#======================================================================================================================= diff --git a/_pydev_bundle/_pydev_imports_tipper.py b/_pydev_bundle/_pydev_imports_tipper.py new file mode 100644 index 0000000..7f89c75 --- /dev/null +++ b/_pydev_bundle/_pydev_imports_tipper.py @@ -0,0 +1,373 @@ +import inspect +import os.path +import sys + +from _pydev_bundle._pydev_tipper_common import do_find +from _pydevd_bundle.pydevd_utils import hasattr_checked, dir_checked + +from inspect import getfullargspec + + +def getargspec(*args, **kwargs): + arg_spec = getfullargspec(*args, **kwargs) + return arg_spec.args, arg_spec.varargs, arg_spec.varkw, arg_spec.defaults, arg_spec.kwonlyargs or [], arg_spec.kwonlydefaults or {} + + +# completion types. +TYPE_IMPORT = '0' +TYPE_CLASS = '1' +TYPE_FUNCTION = '2' +TYPE_ATTR = '3' +TYPE_BUILTIN = '4' +TYPE_PARAM = '5' + + +def _imp(name, log=None): + try: + return __import__(name) + except: + if '.' in name: + sub = name[0:name.rfind('.')] + + if log is not None: + log.add_content('Unable to import', name, 'trying with', sub) + log.add_exception() + + return _imp(sub, log) + else: + s = 'Unable to import module: %s - sys.path: %s' % (str(name), sys.path) + if log is not None: + log.add_content(s) + log.add_exception() + + raise ImportError(s) + + +IS_IPY = False +if sys.platform == 'cli': + IS_IPY = True + _old_imp = _imp + + def _imp(name, log=None): + # We must add a reference in clr for .Net + import clr # @UnresolvedImport + initial_name = name + while '.' in name: + try: + clr.AddReference(name) + break # If it worked, that's OK. + except: + name = name[0:name.rfind('.')] + else: + try: + clr.AddReference(name) + except: + pass # That's OK (not dot net module). + + return _old_imp(initial_name, log) + + +def get_file(mod): + f = None + try: + f = inspect.getsourcefile(mod) or inspect.getfile(mod) + except: + try: + f = getattr(mod, '__file__', None) + except: + f = None + if f and f.lower(f[-4:]) in ['.pyc', '.pyo']: + filename = f[:-4] + '.py' + if os.path.exists(filename): + f = filename + + return f + + +def Find(name, log=None): + f = None + + mod = _imp(name, log) + parent = mod + foundAs = '' + + if inspect.ismodule(mod): + f = get_file(mod) + + components = name.split('.') + + old_comp = None + for comp in components[1:]: + try: + # this happens in the following case: + # we have mx.DateTime.mxDateTime.mxDateTime.pyd + # but after importing it, mx.DateTime.mxDateTime shadows access to mxDateTime.pyd + mod = getattr(mod, comp) + except AttributeError: + if old_comp != comp: + raise + + if inspect.ismodule(mod): + f = get_file(mod) + else: + if len(foundAs) > 0: + foundAs = foundAs + '.' + foundAs = foundAs + comp + + old_comp = comp + + return f, mod, parent, foundAs + + +def search_definition(data): + '''@return file, line, col + ''' + + data = data.replace('\n', '') + if data.endswith('.'): + data = data.rstrip('.') + f, mod, parent, foundAs = Find(data) + try: + return do_find(f, mod), foundAs + except: + return do_find(f, parent), foundAs + + +def generate_tip(data, log=None): + data = data.replace('\n', '') + if data.endswith('.'): + data = data.rstrip('.') + + f, mod, parent, foundAs = Find(data, log) + # print_ >> open('temp.txt', 'w'), f + tips = generate_imports_tip_for_module(mod) + return f, tips + + +def check_char(c): + if c == '-' or c == '.': + return '_' + return c + + +_SENTINEL = object() + + +def generate_imports_tip_for_module(obj_to_complete, dir_comps=None, getattr=getattr, filter=lambda name:True): + ''' + @param obj_to_complete: the object from where we should get the completions + @param dir_comps: if passed, we should not 'dir' the object and should just iterate those passed as kwonly_arg parameter + @param getattr: the way to get kwonly_arg given object from the obj_to_complete (used for the completer) + @param filter: kwonly_arg callable that receives the name and decides if it should be appended or not to the results + @return: list of tuples, so that each tuple represents kwonly_arg completion with: + name, doc, args, type (from the TYPE_* constants) + ''' + ret = [] + + if dir_comps is None: + dir_comps = dir_checked(obj_to_complete) + if hasattr_checked(obj_to_complete, '__dict__'): + dir_comps.append('__dict__') + if hasattr_checked(obj_to_complete, '__class__'): + dir_comps.append('__class__') + + get_complete_info = True + + if len(dir_comps) > 1000: + # ok, we don't want to let our users wait forever... + # no complete info for you... + + get_complete_info = False + + dontGetDocsOn = (float, int, str, tuple, list, dict) + dontGetattrOn = (dict, list, set, tuple) + for d in dir_comps: + + if d is None: + continue + + if not filter(d): + continue + + args = '' + + try: + try: + if isinstance(obj_to_complete, dontGetattrOn): + raise Exception('Since python 3.9, e.g. "dict[str]" will return' + " a dict that's only supposed to take strings. " + 'Interestingly, e.g. dict["val"] is also valid ' + 'and presumably represents a dict that only takes ' + 'keys that are "val". This breaks our check for ' + 'class attributes.') + obj = getattr(obj_to_complete.__class__, d) + except: + obj = getattr(obj_to_complete, d) + except: # just ignore and get it without additional info + ret.append((d, '', args, TYPE_BUILTIN)) + else: + + if get_complete_info: + try: + retType = TYPE_BUILTIN + + # check if we have to get docs + getDoc = True + for class_ in dontGetDocsOn: + + if isinstance(obj, class_): + getDoc = False + break + + doc = '' + if getDoc: + # no need to get this info... too many constants are defined and + # makes things much slower (passing all that through sockets takes quite some time) + try: + doc = inspect.getdoc(obj) + if doc is None: + doc = '' + except: # may happen on jython when checking java classes (so, just ignore it) + doc = '' + + if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj): + try: + args, vargs, kwargs, defaults, kwonly_args, kwonly_defaults = getargspec(obj) + + args = args[:] + + for kwonly_arg in kwonly_args: + default = kwonly_defaults.get(kwonly_arg, _SENTINEL) + if default is not _SENTINEL: + args.append('%s=%s' % (kwonly_arg, default)) + else: + args.append(str(kwonly_arg)) + + args = '(%s)' % (', '.join(args)) + except TypeError: + # ok, let's see if we can get the arguments from the doc + args, doc = signature_from_docstring(doc, getattr(obj, '__name__', None)) + + retType = TYPE_FUNCTION + + elif inspect.isclass(obj): + retType = TYPE_CLASS + + elif inspect.ismodule(obj): + retType = TYPE_IMPORT + + else: + retType = TYPE_ATTR + + # add token and doc to return - assure only strings. + ret.append((d, doc, args, retType)) + + except: # just ignore and get it without aditional info + ret.append((d, '', args, TYPE_BUILTIN)) + + else: # get_complete_info == False + if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj): + retType = TYPE_FUNCTION + + elif inspect.isclass(obj): + retType = TYPE_CLASS + + elif inspect.ismodule(obj): + retType = TYPE_IMPORT + + else: + retType = TYPE_ATTR + # ok, no complete info, let's try to do this as fast and clean as possible + # so, no docs for this kind of information, only the signatures + ret.append((d, '', str(args), retType)) + + return ret + + +def signature_from_docstring(doc, obj_name): + args = '()' + try: + found = False + if len(doc) > 0: + if IS_IPY: + # Handle case where we have the situation below + # sort(self, object cmp, object key) + # sort(self, object cmp, object key, bool reverse) + # sort(self) + # sort(self, object cmp) + + # Or: sort(self: list, cmp: object, key: object) + # sort(self: list, cmp: object, key: object, reverse: bool) + # sort(self: list) + # sort(self: list, cmp: object) + if obj_name: + name = obj_name + '(' + + # Fix issue where it was appearing sort(aa)sort(bb)sort(cc) in the same line. + lines = doc.splitlines() + if len(lines) == 1: + c = doc.count(name) + if c > 1: + doc = ('\n' + name).join(doc.split(name)) + + major = '' + for line in doc.splitlines(): + if line.startswith(name) and line.endswith(')'): + if len(line) > len(major): + major = line + if major: + args = major[major.index('('):] + found = True + + if not found: + i = doc.find('->') + if i < 0: + i = doc.find('--') + if i < 0: + i = doc.find('\n') + if i < 0: + i = doc.find('\r') + + if i > 0: + s = doc[0:i] + s = s.strip() + + # let's see if we have a docstring in the first line + if s[-1] == ')': + start = s.find('(') + if start >= 0: + end = s.find('[') + if end <= 0: + end = s.find(')') + if end <= 0: + end = len(s) + + args = s[start:end] + if not args[-1] == ')': + args = args + ')' + + # now, get rid of unwanted chars + l = len(args) - 1 + r = [] + for i in range(len(args)): + if i == 0 or i == l: + r.append(args[i]) + else: + r.append(check_char(args[i])) + + args = ''.join(r) + + if IS_IPY: + if args.startswith('(self:'): + i = args.find(',') + if i >= 0: + args = '(self' + args[i:] + else: + args = '(self)' + i = args.find(')') + if i > 0: + args = args[:i + 1] + + except: + pass + return args, doc diff --git a/_pydev_bundle/_pydev_jy_imports_tipper.py b/_pydev_bundle/_pydev_jy_imports_tipper.py new file mode 100644 index 0000000..a30c4d3 --- /dev/null +++ b/_pydev_bundle/_pydev_jy_imports_tipper.py @@ -0,0 +1,492 @@ +import traceback +from io import StringIO +from java.lang import StringBuffer # @UnresolvedImport +from java.lang import String # @UnresolvedImport +import java.lang # @UnresolvedImport +import sys +from _pydev_bundle._pydev_tipper_common import do_find + +from org.python.core import PyReflectedFunction # @UnresolvedImport + +from org.python import core # @UnresolvedImport +from org.python.core import PyClass # @UnresolvedImport + +# completion types. +TYPE_IMPORT = '0' +TYPE_CLASS = '1' +TYPE_FUNCTION = '2' +TYPE_ATTR = '3' +TYPE_BUILTIN = '4' +TYPE_PARAM = '5' + + +def _imp(name): + try: + return __import__(name) + except: + if '.' in name: + sub = name[0:name.rfind('.')] + return _imp(sub) + else: + s = 'Unable to import module: %s - sys.path: %s' % (str(name), sys.path) + raise RuntimeError(s) + + +import java.util +_java_rt_file = getattr(java.util, '__file__', None) + + +def Find(name): + f = None + if name.startswith('__builtin__'): + if name == '__builtin__.str': + name = 'org.python.core.PyString' + elif name == '__builtin__.dict': + name = 'org.python.core.PyDictionary' + + mod = _imp(name) + parent = mod + foundAs = '' + + try: + f = getattr(mod, '__file__', None) + except: + f = None + + components = name.split('.') + old_comp = None + for comp in components[1:]: + try: + # this happens in the following case: + # we have mx.DateTime.mxDateTime.mxDateTime.pyd + # but after importing it, mx.DateTime.mxDateTime does shadows access to mxDateTime.pyd + mod = getattr(mod, comp) + except AttributeError: + if old_comp != comp: + raise + + if hasattr(mod, '__file__'): + f = mod.__file__ + else: + if len(foundAs) > 0: + foundAs = foundAs + '.' + foundAs = foundAs + comp + + old_comp = comp + + if f is None and name.startswith('java.lang'): + # Hack: java.lang.__file__ is None on Jython 2.7 (whereas it pointed to rt.jar on Jython 2.5). + f = _java_rt_file + + if f is not None: + if f.endswith('.pyc'): + f = f[:-1] + elif f.endswith('$py.class'): + f = f[:-len('$py.class')] + '.py' + return f, mod, parent, foundAs + + +def format_param_class_name(paramClassName): + if paramClassName.startswith(''): + paramClassName = paramClassName[len(' + paramClassName = paramClassName.split('\'')[1] + except: + paramClassName = repr(paramTypesClass) # just in case something else happens... it will at least be visible + # if the parameter equals [C, it means it it a char array, so, let's change it + + a = format_param_class_name(paramClassName) + # a = a.replace('[]','Array') + # a = a.replace('Object', 'obj') + # a = a.replace('String', 's') + # a = a.replace('Integer', 'i') + # a = a.replace('Char', 'c') + # a = a.replace('Double', 'd') + args.append(a) # so we don't leave invalid code + + info = Info(name, args=args, ret=ret) + # print_ info.basic_as_str() + infos.append(info) + + return 1, infos + except Exception: + s = StringIO() + traceback.print_exc(file=s) + return 1, [Info(str('ERROR'), doc=s.getvalue())] + + return 0, None + + +def ismodule(mod): + # java modules... do we have other way to know that? + if not hasattr(mod, 'getClass') and not hasattr(mod, '__class__') \ + and hasattr(mod, '__name__'): + return 1 + + return isinstance(mod, core.PyModule) + + +def dir_obj(obj): + ret = [] + found = java.util.HashMap() + original = obj + if hasattr(obj, '__class__'): + if obj.__class__ == java.lang.Class: + + # get info about superclasses + classes = [] + classes.append(obj) + try: + c = obj.getSuperclass() + except TypeError: + # may happen on jython when getting the java.lang.Class class + c = obj.getSuperclass(obj) + + while c != None: + classes.append(c) + c = c.getSuperclass() + + # get info about interfaces + interfs = [] + for obj in classes: + try: + interfs.extend(obj.getInterfaces()) + except TypeError: + interfs.extend(obj.getInterfaces(obj)) + classes.extend(interfs) + + # now is the time when we actually get info on the declared methods and fields + for obj in classes: + try: + declaredMethods = obj.getDeclaredMethods() + except TypeError: + declaredMethods = obj.getDeclaredMethods(obj) + + try: + declaredFields = obj.getDeclaredFields() + except TypeError: + declaredFields = obj.getDeclaredFields(obj) + + for i in range(len(declaredMethods)): + name = declaredMethods[i].getName() + ret.append(name) + found.put(name, 1) + + for i in range(len(declaredFields)): + name = declaredFields[i].getName() + ret.append(name) + found.put(name, 1) + + elif isclass(obj.__class__): + d = dir(obj.__class__) + for name in d: + ret.append(name) + found.put(name, 1) + + # this simple dir does not always get all the info, that's why we have the part before + # (e.g.: if we do a dir on String, some methods that are from other interfaces such as + # charAt don't appear) + d = dir(original) + for name in d: + if found.get(name) != 1: + ret.append(name) + + return ret + + +def format_arg(arg): + '''formats an argument to be shown + ''' + + s = str(arg) + dot = s.rfind('.') + if dot >= 0: + s = s[dot + 1:] + + s = s.replace(';', '') + s = s.replace('[]', 'Array') + if len(s) > 0: + c = s[0].lower() + s = c + s[1:] + + return s + + +def search_definition(data): + '''@return file, line, col + ''' + + data = data.replace('\n', '') + if data.endswith('.'): + data = data.rstrip('.') + f, mod, parent, foundAs = Find(data) + try: + return do_find(f, mod), foundAs + except: + return do_find(f, parent), foundAs + + +def generate_imports_tip_for_module(obj_to_complete, dir_comps=None, getattr=getattr, filter=lambda name:True): + ''' + @param obj_to_complete: the object from where we should get the completions + @param dir_comps: if passed, we should not 'dir' the object and should just iterate those passed as a parameter + @param getattr: the way to get a given object from the obj_to_complete (used for the completer) + @param filter: a callable that receives the name and decides if it should be appended or not to the results + @return: list of tuples, so that each tuple represents a completion with: + name, doc, args, type (from the TYPE_* constants) + ''' + ret = [] + + if dir_comps is None: + dir_comps = dir_obj(obj_to_complete) + + for d in dir_comps: + + if d is None: + continue + + if not filter(d): + continue + + args = '' + doc = '' + retType = TYPE_BUILTIN + + try: + obj = getattr(obj_to_complete, d) + except (AttributeError, java.lang.NoClassDefFoundError): + # jython has a bug in its custom classloader that prevents some things from working correctly, so, let's see if + # we can fix that... (maybe fixing it in jython itself would be a better idea, as this is clearly a bug) + # for that we need a custom classloader... we have references from it in the below places: + # + # http://mindprod.com/jgloss/classloader.html + # http://www.javaworld.com/javaworld/jw-03-2000/jw-03-classload-p2.html + # http://freshmeat.net/articles/view/1643/ + # + # note: this only happens when we add things to the sys.path at runtime, if they are added to the classpath + # before the run, everything goes fine. + # + # The code below ilustrates what I mean... + # + # import sys + # sys.path.insert(1, r"C:\bin\eclipse310\plugins\org.junit_3.8.1\junit.jar" ) + # + # import junit.framework + # print_ dir(junit.framework) #shows the TestCase class here + # + # import junit.framework.TestCase + # + # raises the error: + # Traceback (innermost last): + # File "", line 1, in ? + # ImportError: No module named TestCase + # + # whereas if we had added the jar to the classpath before, everything would be fine by now... + + ret.append((d, '', '', retType)) + # that's ok, private things cannot be gotten... + continue + else: + + isMet = ismethod(obj) + if isMet[0] and isMet[1]: + info = isMet[1][0] + try: + args, vargs, kwargs = info.args, info.varargs, info.kwargs + doc = info.get_as_doc() + r = '' + for a in (args): + if len(r) > 0: + r += ', ' + r += format_arg(a) + args = '(%s)' % (r) + except TypeError: + traceback.print_exc() + args = '()' + + retType = TYPE_FUNCTION + + elif isclass(obj): + retType = TYPE_CLASS + + elif ismodule(obj): + retType = TYPE_IMPORT + + # add token and doc to return - assure only strings. + ret.append((d, doc, args, retType)) + + return ret + + +if __name__ == "__main__": + sys.path.append(r'D:\dev_programs\eclipse_3\310\eclipse\plugins\org.junit_3.8.1\junit.jar') + sys.stdout.write('%s\n' % Find('junit.framework.TestCase')) diff --git a/_pydev_bundle/_pydev_log.py b/_pydev_bundle/_pydev_log.py new file mode 100644 index 0000000..7328d62 --- /dev/null +++ b/_pydev_bundle/_pydev_log.py @@ -0,0 +1,24 @@ +import traceback +import sys +from io import StringIO + + +class Log: + + def __init__(self): + self._contents = [] + + def add_content(self, *content): + self._contents.append(' '.join(content)) + + def add_exception(self): + s = StringIO() + exc_info = sys.exc_info() + traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], limit=None, file=s) + self._contents.append(s.getvalue()) + + def get_contents(self): + return '\n'.join(self._contents) + + def clear_log(self): + del self._contents[:] diff --git a/_pydev_bundle/_pydev_saved_modules.py b/_pydev_bundle/_pydev_saved_modules.py new file mode 100644 index 0000000..bcf5f9b --- /dev/null +++ b/_pydev_bundle/_pydev_saved_modules.py @@ -0,0 +1,110 @@ +import sys +import os + + +def find_in_pythonpath(module_name): + # Check all the occurrences where we could match the given module/package in the PYTHONPATH. + # + # This is a simplistic approach, but probably covers most of the cases we're interested in + # (i.e.: this may fail in more elaborate cases of import customization or .zip imports, but + # this should be rare in general). + found_at = [] + + parts = module_name.split('.') # split because we need to convert mod.name to mod/name + for path in sys.path: + target = os.path.join(path, *parts) + target_py = target + '.py' + if os.path.isdir(target): + found_at.append(target) + if os.path.exists(target_py): + found_at.append(target_py) + return found_at + + +class DebuggerInitializationError(Exception): + pass + + +class VerifyShadowedImport(object): + + def __init__(self, import_name): + self.import_name = import_name + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type is not None: + if exc_type == DebuggerInitializationError: + return False # It's already an error we generated. + + # We couldn't even import it... + found_at = find_in_pythonpath(self.import_name) + + if len(found_at) <= 1: + # It wasn't found anywhere or there was just 1 occurrence. + # Let's just return to show the original error. + return False + + # We found more than 1 occurrence of the same module in the PYTHONPATH + # (the user module and the standard library module). + # Let's notify the user as it seems that the module was shadowed. + msg = self._generate_shadowed_import_message(found_at) + raise DebuggerInitializationError(msg) + + def _generate_shadowed_import_message(self, found_at): + msg = '''It was not possible to initialize the debugger due to a module name conflict. + +i.e.: the module "%(import_name)s" could not be imported because it is shadowed by: +%(found_at)s +Please rename this file/folder so that the original module from the standard library can be imported.''' % { + 'import_name': self.import_name, 'found_at': found_at[0]} + + return msg + + def check(self, module, expected_attributes): + msg = '' + for expected_attribute in expected_attributes: + try: + getattr(module, expected_attribute) + except: + msg = self._generate_shadowed_import_message([module.__file__]) + break + + if msg: + raise DebuggerInitializationError(msg) + + +with VerifyShadowedImport('threading') as verify_shadowed: + import threading; verify_shadowed.check(threading, ['Thread', 'settrace', 'setprofile', 'Lock', 'RLock', 'current_thread']) + +with VerifyShadowedImport('time') as verify_shadowed: + import time; verify_shadowed.check(time, ['sleep', 'time', 'mktime']) + +with VerifyShadowedImport('socket') as verify_shadowed: + import socket; verify_shadowed.check(socket, ['socket', 'gethostname', 'getaddrinfo']) + +with VerifyShadowedImport('select') as verify_shadowed: + import select; verify_shadowed.check(select, ['select']) + +with VerifyShadowedImport('code') as verify_shadowed: + import code as _code; verify_shadowed.check(_code, ['compile_command', 'InteractiveInterpreter']) + +with VerifyShadowedImport('_thread') as verify_shadowed: + import _thread as thread; verify_shadowed.check(thread, ['start_new_thread', 'start_new', 'allocate_lock']) + +with VerifyShadowedImport('queue') as verify_shadowed: + import queue as _queue; verify_shadowed.check(_queue, ['Queue', 'LifoQueue', 'Empty', 'Full', 'deque']) + +with VerifyShadowedImport('xmlrpclib') as verify_shadowed: + import xmlrpc.client as xmlrpclib; verify_shadowed.check(xmlrpclib, ['ServerProxy', 'Marshaller', 'Server']) + +with VerifyShadowedImport('xmlrpc.server') as verify_shadowed: + import xmlrpc.server as xmlrpcserver; verify_shadowed.check(xmlrpcserver, ['SimpleXMLRPCServer']) + +with VerifyShadowedImport('http.server') as verify_shadowed: + import http.server as BaseHTTPServer; verify_shadowed.check(BaseHTTPServer, ['BaseHTTPRequestHandler']) + +# If set, this is a version of the threading.enumerate that doesn't have the patching to remove the pydevd threads. +# Note: as it can't be set during execution, don't import the name (import the module and access it through its name). +pydevd_saved_threading_enumerate = None diff --git a/_pydev_bundle/_pydev_sys_patch.py b/_pydev_bundle/_pydev_sys_patch.py new file mode 100644 index 0000000..f506750 --- /dev/null +++ b/_pydev_bundle/_pydev_sys_patch.py @@ -0,0 +1,73 @@ +import sys + + +def patch_sys_module(): + + def patched_exc_info(fun): + + def pydev_debugger_exc_info(): + type, value, traceback = fun() + if type == ImportError: + # we should not show frame added by plugin_import call + if traceback and hasattr(traceback, "tb_next"): + return type, value, traceback.tb_next + return type, value, traceback + + return pydev_debugger_exc_info + + system_exc_info = sys.exc_info + sys.exc_info = patched_exc_info(system_exc_info) + if not hasattr(sys, "system_exc_info"): + sys.system_exc_info = system_exc_info + + +def patched_reload(orig_reload): + + def pydev_debugger_reload(module): + orig_reload(module) + if module.__name__ == "sys": + # if sys module was reloaded we should patch it again + patch_sys_module() + + return pydev_debugger_reload + + +def patch_reload(): + import builtins # Py3 + + if hasattr(builtins, "reload"): + sys.builtin_orig_reload = builtins.reload + builtins.reload = patched_reload(sys.builtin_orig_reload) # @UndefinedVariable + try: + import imp + sys.imp_orig_reload = imp.reload + imp.reload = patched_reload(sys.imp_orig_reload) # @UndefinedVariable + except: + pass + else: + try: + import importlib + sys.importlib_orig_reload = importlib.reload # @UndefinedVariable + importlib.reload = patched_reload(sys.importlib_orig_reload) # @UndefinedVariable + except: + pass + + del builtins + + +def cancel_patches_in_sys_module(): + sys.exc_info = sys.system_exc_info # @UndefinedVariable + import builtins # Py3 + + if hasattr(sys, "builtin_orig_reload"): + builtins.reload = sys.builtin_orig_reload + + if hasattr(sys, "imp_orig_reload"): + import imp + imp.reload = sys.imp_orig_reload + + if hasattr(sys, "importlib_orig_reload"): + import importlib + importlib.reload = sys.importlib_orig_reload + + del builtins diff --git a/_pydev_bundle/_pydev_tipper_common.py b/_pydev_bundle/_pydev_tipper_common.py new file mode 100644 index 0000000..d97e95d --- /dev/null +++ b/_pydev_bundle/_pydev_tipper_common.py @@ -0,0 +1,52 @@ +import inspect +import re + + +def do_find(f, mod): + import linecache + if inspect.ismodule(mod): + return f, 0, 0 + + lines = linecache.getlines(f) + + if inspect.isclass(mod): + name = mod.__name__ + pat = re.compile(r'^\s*class\s*' + name + r'\b') + for i in range(len(lines)): + if pat.match(lines[i]): + return f, i, 0 + + return f, 0, 0 + + if inspect.ismethod(mod): + mod = mod.im_func + + if inspect.isfunction(mod): + try: + mod = mod.func_code + except AttributeError: + mod = mod.__code__ # python 3k + + if inspect.istraceback(mod): + mod = mod.tb_frame + + if inspect.isframe(mod): + mod = mod.f_code + + if inspect.iscode(mod): + if not hasattr(mod, 'co_filename'): + return None, 0, 0 + + if not hasattr(mod, 'co_firstlineno'): + return mod.co_filename, 0, 0 + + lnum = mod.co_firstlineno + pat = re.compile(r'^(\s*def\s)|(.*(? 0: + if pat.match(lines[lnum]): + break + lnum -= 1 + + return f, lnum, 0 + + raise RuntimeError('Do not know about: ' + f + ' ' + str(mod)) diff --git a/_pydev_bundle/fsnotify/__init__.py b/_pydev_bundle/fsnotify/__init__.py new file mode 100644 index 0000000..fe6ed41 --- /dev/null +++ b/_pydev_bundle/fsnotify/__init__.py @@ -0,0 +1,353 @@ +''' +Sample usage to track changes in a thread. + + import threading + import time + watcher = fsnotify.Watcher() + watcher.accepted_file_extensions = {'.py', '.pyw'} + + # Configure target values to compute throttling. + # Note: internal sleep times will be updated based on + # profiling the actual application runtime to match + # those values. + + watcher.target_time_for_single_scan = 2. + watcher.target_time_for_notification = 4. + + watcher.set_tracked_paths([target_dir]) + + def start_watching(): # Called from thread + for change_enum, change_path in watcher.iter_changes(): + if change_enum == fsnotify.Change.added: + print('Added: ', change_path) + elif change_enum == fsnotify.Change.modified: + print('Modified: ', change_path) + elif change_enum == fsnotify.Change.deleted: + print('Deleted: ', change_path) + + t = threading.Thread(target=start_watching) + t.daemon = True + t.start() + + try: + ... + finally: + watcher.dispose() + + +Note: changes are only reported for files (added/modified/deleted), not directories. +''' +import threading +import sys +from os.path import basename +from _pydev_bundle import pydev_log +from os import scandir + +try: + from enum import IntEnum +except: + + class IntEnum(object): + pass + +import time + +__author__ = 'Fabio Zadrozny' +__email__ = 'fabiofz@gmail.com' +__version__ = '0.1.5' # Version here and in setup.py + + +class Change(IntEnum): + added = 1 + modified = 2 + deleted = 3 + + +class _SingleVisitInfo(object): + + def __init__(self): + self.count = 0 + self.visited_dirs = set() + self.file_to_mtime = {} + self.last_sleep_time = time.time() + + +class _PathWatcher(object): + ''' + Helper to watch a single path. + ''' + + def __init__(self, root_path, accept_directory, accept_file, single_visit_info, max_recursion_level, sleep_time=.0): + ''' + :type root_path: str + :type accept_directory: Callback[str, bool] + :type accept_file: Callback[str, bool] + :type max_recursion_level: int + :type sleep_time: float + ''' + self.accept_directory = accept_directory + self.accept_file = accept_file + self._max_recursion_level = max_recursion_level + + self._root_path = root_path + + # Initial sleep value for throttling, it'll be auto-updated based on the + # Watcher.target_time_for_single_scan. + self.sleep_time = sleep_time + + self.sleep_at_elapsed = 1. / 30. + + # When created, do the initial snapshot right away! + old_file_to_mtime = {} + self._check(single_visit_info, lambda _change: None, old_file_to_mtime) + + def __eq__(self, o): + if isinstance(o, _PathWatcher): + return self._root_path == o._root_path + + return False + + def __ne__(self, o): + return not self == o + + def __hash__(self): + return hash(self._root_path) + + def _check_dir(self, dir_path, single_visit_info, append_change, old_file_to_mtime, level): + # This is the actual poll loop + if dir_path in single_visit_info.visited_dirs or level > self._max_recursion_level: + return + single_visit_info.visited_dirs.add(dir_path) + try: + if isinstance(dir_path, bytes): + try: + dir_path = dir_path.decode(sys.getfilesystemencoding()) + except UnicodeDecodeError: + try: + dir_path = dir_path.decode('utf-8') + except UnicodeDecodeError: + return # Ignore if we can't deal with the path. + + new_files = single_visit_info.file_to_mtime + + for entry in scandir(dir_path): + single_visit_info.count += 1 + + # Throttle if needed inside the loop + # to avoid consuming too much CPU. + if single_visit_info.count % 300 == 0: + if self.sleep_time > 0: + t = time.time() + diff = t - single_visit_info.last_sleep_time + if diff > self.sleep_at_elapsed: + time.sleep(self.sleep_time) + single_visit_info.last_sleep_time = time.time() + + if entry.is_dir(): + if self.accept_directory(entry.path): + self._check_dir(entry.path, single_visit_info, append_change, old_file_to_mtime, level + 1) + + elif self.accept_file(entry.path): + stat = entry.stat() + mtime = (stat.st_mtime_ns, stat.st_size) + path = entry.path + new_files[path] = mtime + + old_mtime = old_file_to_mtime.pop(path, None) + if not old_mtime: + append_change((Change.added, path)) + elif old_mtime != mtime: + append_change((Change.modified, path)) + + except OSError: + pass # Directory was removed in the meanwhile. + + def _check(self, single_visit_info, append_change, old_file_to_mtime): + self._check_dir(self._root_path, single_visit_info, append_change, old_file_to_mtime, 0) + + +class Watcher(object): + + # By default (if accept_directory is not specified), these will be the + # ignored directories. + ignored_dirs = {u'.git', u'__pycache__', u'.idea', u'node_modules', u'.metadata'} + + # By default (if accept_file is not specified), these will be the + # accepted files. + accepted_file_extensions = () + + # Set to the target value for doing full scan of all files (adds a sleep inside the poll loop + # which processes files to reach the target time). + # Lower values will consume more CPU + # Set to 0.0 to have no sleeps (which will result in a higher cpu load). + target_time_for_single_scan = 2.0 + + # Set the target value from the start of one scan to the start of another scan (adds a + # sleep after a full poll is done to reach the target time). + # Lower values will consume more CPU. + # Set to 0.0 to have a new scan start right away without any sleeps. + target_time_for_notification = 4.0 + + # Set to True to print the time for a single poll through all the paths. + print_poll_time = False + + # This is the maximum recursion level. + max_recursion_level = 10 + + def __init__(self, accept_directory=None, accept_file=None): + ''' + :param Callable[str, bool] accept_directory: + Callable that returns whether a directory should be watched. + Note: if passed it'll override the `ignored_dirs` + + :param Callable[str, bool] accept_file: + Callable that returns whether a file should be watched. + Note: if passed it'll override the `accepted_file_extensions`. + ''' + self._path_watchers = set() + self._disposed = threading.Event() + + if accept_directory is None: + accept_directory = lambda dir_path: basename(dir_path) not in self.ignored_dirs + if accept_file is None: + accept_file = lambda path_name: \ + not self.accepted_file_extensions or path_name.endswith(self.accepted_file_extensions) + self.accept_file = accept_file + self.accept_directory = accept_directory + self._single_visit_info = _SingleVisitInfo() + + @property + def accept_directory(self): + return self._accept_directory + + @accept_directory.setter + def accept_directory(self, accept_directory): + self._accept_directory = accept_directory + for path_watcher in self._path_watchers: + path_watcher.accept_directory = accept_directory + + @property + def accept_file(self): + return self._accept_file + + @accept_file.setter + def accept_file(self, accept_file): + self._accept_file = accept_file + for path_watcher in self._path_watchers: + path_watcher.accept_file = accept_file + + def dispose(self): + self._disposed.set() + + @property + def path_watchers(self): + return tuple(self._path_watchers) + + def set_tracked_paths(self, paths): + """ + Note: always resets all path trackers to track the passed paths. + """ + if not isinstance(paths, (list, tuple, set)): + paths = (paths,) + + # Sort by the path len so that the bigger paths come first (so, + # if there's any nesting we want the nested paths to be visited + # before the parent paths so that the max_recursion_level is correct). + paths = sorted(set(paths), key=lambda path:-len(path)) + path_watchers = set() + + self._single_visit_info = _SingleVisitInfo() + + initial_time = time.time() + for path in paths: + sleep_time = 0. # When collecting the first time, sleep_time should be 0! + path_watcher = _PathWatcher( + path, + self.accept_directory, + self.accept_file, + self._single_visit_info, + max_recursion_level=self.max_recursion_level, + sleep_time=sleep_time, + ) + + path_watchers.add(path_watcher) + + actual_time = (time.time() - initial_time) + + pydev_log.debug('Tracking the following paths for changes: %s', paths) + pydev_log.debug('Time to track: %.2fs', actual_time) + pydev_log.debug('Folders found: %s', len(self._single_visit_info.visited_dirs)) + pydev_log.debug('Files found: %s', len(self._single_visit_info.file_to_mtime)) + self._path_watchers = path_watchers + + def iter_changes(self): + ''' + Continuously provides changes (until dispose() is called). + + Changes provided are tuples with the Change enum and filesystem path. + + :rtype: Iterable[Tuple[Change, str]] + ''' + while not self._disposed.is_set(): + initial_time = time.time() + + old_visit_info = self._single_visit_info + old_file_to_mtime = old_visit_info.file_to_mtime + changes = [] + append_change = changes.append + + self._single_visit_info = single_visit_info = _SingleVisitInfo() + for path_watcher in self._path_watchers: + path_watcher._check(single_visit_info, append_change, old_file_to_mtime) + + # Note that we pop entries while visiting, so, what remained is what's deleted. + for entry in old_file_to_mtime: + append_change((Change.deleted, entry)) + + for change in changes: + yield change + + actual_time = (time.time() - initial_time) + if self.print_poll_time: + print('--- Total poll time: %.3fs' % actual_time) + + if actual_time > 0: + if self.target_time_for_single_scan <= 0.0: + for path_watcher in self._path_watchers: + path_watcher.sleep_time = 0.0 + else: + perc = self.target_time_for_single_scan / actual_time + + # Prevent from changing the values too much (go slowly into the right + # direction). + # (to prevent from cases where the user puts the machine on sleep and + # values become too skewed). + if perc > 2.: + perc = 2. + elif perc < 0.5: + perc = 0.5 + + for path_watcher in self._path_watchers: + if path_watcher.sleep_time <= 0.0: + path_watcher.sleep_time = 0.001 + new_sleep_time = path_watcher.sleep_time * perc + + # Prevent from changing the values too much (go slowly into the right + # direction). + # (to prevent from cases where the user puts the machine on sleep and + # values become too skewed). + diff_sleep_time = new_sleep_time - path_watcher.sleep_time + path_watcher.sleep_time += (diff_sleep_time / (3.0 * len(self._path_watchers))) + + if actual_time > 0: + self._disposed.wait(actual_time) + + if path_watcher.sleep_time < 0.001: + path_watcher.sleep_time = 0.001 + + # print('new sleep time: %s' % path_watcher.sleep_time) + + diff = self.target_time_for_notification - actual_time + if diff > 0.: + self._disposed.wait(diff) + diff --git a/_pydev_bundle/pydev_console_utils.py b/_pydev_bundle/pydev_console_utils.py new file mode 100644 index 0000000..5c87ac8 --- /dev/null +++ b/_pydev_bundle/pydev_console_utils.py @@ -0,0 +1,639 @@ +import os +import sys +import traceback +from _pydev_bundle.pydev_imports import xmlrpclib, _queue, Exec +from _pydev_bundle._pydev_calltip_util import get_description +from _pydevd_bundle import pydevd_vars +from _pydevd_bundle import pydevd_xml +from _pydevd_bundle.pydevd_constants import (IS_JYTHON, NEXT_VALUE_SEPARATOR, get_global_debugger, + silence_warnings_decorator) +from contextlib import contextmanager +from _pydev_bundle import pydev_log +from _pydevd_bundle.pydevd_utils import interrupt_main_thread + +from io import StringIO + + +# ======================================================================================================================= +# BaseStdIn +# ======================================================================================================================= +class BaseStdIn: + + def __init__(self, original_stdin=sys.stdin, *args, **kwargs): + try: + self.encoding = sys.stdin.encoding + except: + # Not sure if it's available in all Python versions... + pass + self.original_stdin = original_stdin + + try: + self.errors = sys.stdin.errors # Who knew? sys streams have an errors attribute! + except: + # Not sure if it's available in all Python versions... + pass + + def readline(self, *args, **kwargs): + # sys.stderr.write('Cannot readline out of the console evaluation\n') -- don't show anything + # This could happen if the user had done input('enter number).<-- upon entering this, that message would appear, + # which is not something we want. + return '\n' + + def write(self, *args, **kwargs): + pass # not available StdIn (but it can be expected to be in the stream interface) + + def flush(self, *args, **kwargs): + pass # not available StdIn (but it can be expected to be in the stream interface) + + def read(self, *args, **kwargs): + # in the interactive interpreter, a read and a readline are the same. + return self.readline() + + def close(self, *args, **kwargs): + pass # expected in StdIn + + def __iter__(self): + # BaseStdIn would not be considered as Iterable in Python 3 without explicit `__iter__` implementation + return self.original_stdin.__iter__() + + def __getattr__(self, item): + # it's called if the attribute wasn't found + if hasattr(self.original_stdin, item): + return getattr(self.original_stdin, item) + raise AttributeError("%s has no attribute %s" % (self.original_stdin, item)) + + +# ======================================================================================================================= +# StdIn +# ======================================================================================================================= +class StdIn(BaseStdIn): + ''' + Object to be added to stdin (to emulate it as non-blocking while the next line arrives) + ''' + + def __init__(self, interpreter, host, client_port, original_stdin=sys.stdin): + BaseStdIn.__init__(self, original_stdin) + self.interpreter = interpreter + self.client_port = client_port + self.host = host + + def readline(self, *args, **kwargs): + # Ok, callback into the client to get the new input + try: + server = xmlrpclib.Server('http://%s:%s' % (self.host, self.client_port)) + requested_input = server.RequestInput() + if not requested_input: + return '\n' # Yes, a readline must return something (otherwise we can get an EOFError on the input() call). + else: + # readline should end with '\n' (not doing so makes IPython 5 remove the last *valid* character). + requested_input += '\n' + return requested_input + except KeyboardInterrupt: + raise # Let KeyboardInterrupt go through -- #PyDev-816: Interrupting infinite loop in the Interactive Console + except: + return '\n' + + def close(self, *args, **kwargs): + pass # expected in StdIn + + +#======================================================================================================================= +# DebugConsoleStdIn +#======================================================================================================================= +class DebugConsoleStdIn(BaseStdIn): + ''' + Object to be added to stdin (to emulate it as non-blocking while the next line arrives) + ''' + + def __init__(self, py_db, original_stdin): + ''' + :param py_db: + If None, get_global_debugger() is used. + ''' + BaseStdIn.__init__(self, original_stdin) + self._py_db = py_db + self._in_notification = 0 + + def __send_input_requested_message(self, is_started): + try: + py_db = self._py_db + if py_db is None: + py_db = get_global_debugger() + + if py_db is None: + return + + cmd = py_db.cmd_factory.make_input_requested_message(is_started) + py_db.writer.add_command(cmd) + except Exception: + pydev_log.exception() + + @contextmanager + def notify_input_requested(self): + self._in_notification += 1 + if self._in_notification == 1: + self.__send_input_requested_message(True) + try: + yield + finally: + self._in_notification -= 1 + if self._in_notification == 0: + self.__send_input_requested_message(False) + + def readline(self, *args, **kwargs): + with self.notify_input_requested(): + return self.original_stdin.readline(*args, **kwargs) + + def read(self, *args, **kwargs): + with self.notify_input_requested(): + return self.original_stdin.read(*args, **kwargs) + + +class CodeFragment: + + def __init__(self, text, is_single_line=True): + self.text = text + self.is_single_line = is_single_line + + def append(self, code_fragment): + self.text = self.text + "\n" + code_fragment.text + if not code_fragment.is_single_line: + self.is_single_line = False + + +# ======================================================================================================================= +# BaseInterpreterInterface +# ======================================================================================================================= +class BaseInterpreterInterface: + + def __init__(self, mainThread, connect_status_queue=None): + self.mainThread = mainThread + self.interruptable = False + self.exec_queue = _queue.Queue(0) + self.buffer = None + self.banner_shown = False + self.connect_status_queue = connect_status_queue + self.mpl_modules_for_patching = {} + self.init_mpl_modules_for_patching() + + def build_banner(self): + return 'print({0})\n'.format(repr(self.get_greeting_msg())) + + def get_greeting_msg(self): + return 'PyDev console: starting.\n' + + def init_mpl_modules_for_patching(self): + from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot + self.mpl_modules_for_patching = { + "matplotlib": lambda: activate_matplotlib(self.enableGui), + "matplotlib.pyplot": activate_pyplot, + "pylab": activate_pylab + } + + def need_more_for_code(self, source): + # PyDev-502: PyDev 3.9 F2 doesn't support backslash continuations + + # Strangely even the IPython console is_complete said it was complete + # even with a continuation char at the end. + if source.endswith('\\'): + return True + + if hasattr(self.interpreter, 'is_complete'): + return not self.interpreter.is_complete(source) + try: + # At this point, it should always be single. + # If we don't do this, things as: + # + # for i in range(10): print(i) + # + # (in a single line) don't work. + # Note that it won't give an error and code will be None (so, it'll + # use execMultipleLines in the next call in this case). + symbol = 'single' + code = self.interpreter.compile(source, '', symbol) + except (OverflowError, SyntaxError, ValueError): + # Case 1 + return False + if code is None: + # Case 2 + return True + + # Case 3 + return False + + def need_more(self, code_fragment): + if self.buffer is None: + self.buffer = code_fragment + else: + self.buffer.append(code_fragment) + + return self.need_more_for_code(self.buffer.text) + + def create_std_in(self, debugger=None, original_std_in=None): + if debugger is None: + return StdIn(self, self.host, self.client_port, original_stdin=original_std_in) + else: + return DebugConsoleStdIn(py_db=debugger, original_stdin=original_std_in) + + def add_exec(self, code_fragment, debugger=None): + # In case sys.excepthook called, use original excepthook #PyDev-877: Debug console freezes with Python 3.5+ + # (showtraceback does it on python 3.5 onwards) + sys.excepthook = sys.__excepthook__ + try: + original_in = sys.stdin + try: + help = None + if 'pydoc' in sys.modules: + pydoc = sys.modules['pydoc'] # Don't import it if it still is not there. + + if hasattr(pydoc, 'help'): + # You never know how will the API be changed, so, let's code defensively here + help = pydoc.help + if not hasattr(help, 'input'): + help = None + except: + # Just ignore any error here + pass + + more = False + try: + sys.stdin = self.create_std_in(debugger, original_in) + try: + if help is not None: + # This will enable the help() function to work. + try: + try: + help.input = sys.stdin + except AttributeError: + help._input = sys.stdin + except: + help = None + if not self._input_error_printed: + self._input_error_printed = True + sys.stderr.write('\nError when trying to update pydoc.help.input\n') + sys.stderr.write('(help() may not work -- please report this as a bug in the pydev bugtracker).\n\n') + traceback.print_exc() + + try: + self.start_exec() + if hasattr(self, 'debugger'): + self.debugger.enable_tracing() + + more = self.do_add_exec(code_fragment) + + if hasattr(self, 'debugger'): + self.debugger.disable_tracing() + + self.finish_exec(more) + finally: + if help is not None: + try: + try: + help.input = original_in + except AttributeError: + help._input = original_in + except: + pass + + finally: + sys.stdin = original_in + except SystemExit: + raise + except: + traceback.print_exc() + finally: + sys.__excepthook__ = sys.excepthook + + return more + + def do_add_exec(self, codeFragment): + ''' + Subclasses should override. + + @return: more (True if more input is needed to complete the statement and False if the statement is complete). + ''' + raise NotImplementedError() + + def get_namespace(self): + ''' + Subclasses should override. + + @return: dict with namespace. + ''' + raise NotImplementedError() + + def __resolve_reference__(self, text): + """ + + :type text: str + """ + obj = None + if '.' not in text: + try: + obj = self.get_namespace()[text] + except KeyError: + pass + + if obj is None: + try: + obj = self.get_namespace()['__builtins__'][text] + except: + pass + + if obj is None: + try: + obj = getattr(self.get_namespace()['__builtins__'], text, None) + except: + pass + + else: + try: + last_dot = text.rindex('.') + parent_context = text[0:last_dot] + res = pydevd_vars.eval_in_context(parent_context, self.get_namespace(), self.get_namespace()) + obj = getattr(res, text[last_dot + 1:]) + except: + pass + return obj + + def getDescription(self, text): + try: + obj = self.__resolve_reference__(text) + if obj is None: + return '' + return get_description(obj) + except: + return '' + + def do_exec_code(self, code, is_single_line): + try: + code_fragment = CodeFragment(code, is_single_line) + more = self.need_more(code_fragment) + if not more: + code_fragment = self.buffer + self.buffer = None + self.exec_queue.put(code_fragment) + + return more + except: + traceback.print_exc() + return False + + def execLine(self, line): + return self.do_exec_code(line, True) + + def execMultipleLines(self, lines): + if IS_JYTHON: + more = False + for line in lines.split('\n'): + more = self.do_exec_code(line, True) + return more + else: + return self.do_exec_code(lines, False) + + def interrupt(self): + self.buffer = None # Also clear the buffer when it's interrupted. + try: + if self.interruptable: + # Fix for #PyDev-500: Console interrupt can't interrupt on sleep + interrupt_main_thread(self.mainThread) + + self.finish_exec(False) + return True + except: + traceback.print_exc() + return False + + def close(self): + sys.exit(0) + + def start_exec(self): + self.interruptable = True + + def get_server(self): + if getattr(self, 'host', None) is not None: + return xmlrpclib.Server('http://%s:%s' % (self.host, self.client_port)) + else: + return None + + server = property(get_server) + + def ShowConsole(self): + server = self.get_server() + if server is not None: + server.ShowConsole() + + def finish_exec(self, more): + self.interruptable = False + + server = self.get_server() + + if server is not None: + return server.NotifyFinished(more) + else: + return True + + def getFrame(self): + xml = StringIO() + hidden_ns = self.get_ipython_hidden_vars_dict() + xml.write("") + xml.write(pydevd_xml.frame_vars_to_xml(self.get_namespace(), hidden_ns)) + xml.write("") + + return xml.getvalue() + + @silence_warnings_decorator + def getVariable(self, attributes): + xml = StringIO() + xml.write("") + val_dict = pydevd_vars.resolve_compound_var_object_fields(self.get_namespace(), attributes) + if val_dict is None: + val_dict = {} + + for k, val in val_dict.items(): + val = val_dict[k] + evaluate_full_value = pydevd_xml.should_evaluate_full_value(val) + xml.write(pydevd_vars.var_to_xml(val, k, evaluate_full_value=evaluate_full_value)) + + xml.write("") + + return xml.getvalue() + + def getArray(self, attr, roffset, coffset, rows, cols, format): + name = attr.split("\t")[-1] + array = pydevd_vars.eval_in_context(name, self.get_namespace(), self.get_namespace()) + return pydevd_vars.table_like_struct_to_xml(array, name, roffset, coffset, rows, cols, format) + + def evaluate(self, expression): + xml = StringIO() + xml.write("") + result = pydevd_vars.eval_in_context(expression, self.get_namespace(), self.get_namespace()) + xml.write(pydevd_vars.var_to_xml(result, expression)) + xml.write("") + return xml.getvalue() + + @silence_warnings_decorator + def loadFullValue(self, seq, scope_attrs): + """ + Evaluate full value for async Console variables in a separate thread and send results to IDE side + :param seq: id of command + :param scope_attrs: a sequence of variables with their attributes separated by NEXT_VALUE_SEPARATOR + (i.e.: obj\tattr1\tattr2NEXT_VALUE_SEPARATORobj2\attr1\tattr2) + :return: + """ + frame_variables = self.get_namespace() + var_objects = [] + vars = scope_attrs.split(NEXT_VALUE_SEPARATOR) + for var_attrs in vars: + if '\t' in var_attrs: + name, attrs = var_attrs.split('\t', 1) + + else: + name = var_attrs + attrs = None + if name in frame_variables: + var_object = pydevd_vars.resolve_var_object(frame_variables[name], attrs) + var_objects.append((var_object, name)) + else: + var_object = pydevd_vars.eval_in_context(name, frame_variables, frame_variables) + var_objects.append((var_object, name)) + + from _pydevd_bundle.pydevd_comm import GetValueAsyncThreadConsole + py_db = getattr(self, 'debugger', None) + + if py_db is None: + py_db = get_global_debugger() + + if py_db is None: + from pydevd import PyDB + py_db = PyDB() + + t = GetValueAsyncThreadConsole(py_db, self.get_server(), seq, var_objects) + t.start() + + def changeVariable(self, attr, value): + + def do_change_variable(): + Exec('%s=%s' % (attr, value), self.get_namespace(), self.get_namespace()) + + # Important: it has to be really enabled in the main thread, so, schedule + # it to run in the main thread. + self.exec_queue.put(do_change_variable) + + def connectToDebugger(self, debuggerPort, debugger_options=None): + ''' + Used to show console with variables connection. + Mainly, monkey-patches things in the debugger structure so that the debugger protocol works. + ''' + + if debugger_options is None: + debugger_options = {} + env_key = "PYDEVD_EXTRA_ENVS" + if env_key in debugger_options: + for (env_name, value) in debugger_options[env_key].items(): + existing_value = os.environ.get(env_name, None) + if existing_value: + os.environ[env_name] = "%s%c%s" % (existing_value, os.path.pathsep, value) + else: + os.environ[env_name] = value + if env_name == "PYTHONPATH": + sys.path.append(value) + + del debugger_options[env_key] + + def do_connect_to_debugger(): + try: + # Try to import the packages needed to attach the debugger + import pydevd + from _pydev_bundle._pydev_saved_modules import threading + except: + # This happens on Jython embedded in host eclipse + traceback.print_exc() + sys.stderr.write('pydevd is not available, cannot connect\n') + + from _pydevd_bundle.pydevd_constants import set_thread_id + from _pydev_bundle import pydev_localhost + set_thread_id(threading.current_thread(), "console_main") + + VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java + VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java + f = FakeFrame() + f.f_back = None + f.f_globals = {} # As globals=locals here, let's simply let it empty (and save a bit of network traffic). + f.f_locals = self.get_namespace() + + self.debugger = pydevd.PyDB() + self.debugger.add_fake_frame(thread_id=VIRTUAL_CONSOLE_ID, frame_id=VIRTUAL_FRAME_ID, frame=f) + try: + pydevd.apply_debugger_options(debugger_options) + self.debugger.connect(pydev_localhost.get_localhost(), debuggerPort) + self.debugger.prepare_to_run() + self.debugger.disable_tracing() + except: + traceback.print_exc() + sys.stderr.write('Failed to connect to target debugger.\n') + + # Register to process commands when idle + self.debugrunning = False + try: + import pydevconsole + pydevconsole.set_debug_hook(self.debugger.process_internal_commands) + except: + traceback.print_exc() + sys.stderr.write('Version of Python does not support debuggable Interactive Console.\n') + + # Important: it has to be really enabled in the main thread, so, schedule + # it to run in the main thread. + self.exec_queue.put(do_connect_to_debugger) + + return ('connect complete',) + + def handshake(self): + if self.connect_status_queue is not None: + self.connect_status_queue.put(True) + return "PyCharm" + + def get_connect_status_queue(self): + return self.connect_status_queue + + def hello(self, input_str): + # Don't care what the input string is + return ("Hello eclipse",) + + def enableGui(self, guiname): + ''' Enable the GUI specified in guiname (see inputhook for list). + As with IPython, enabling multiple GUIs isn't an error, but + only the last one's main loop runs and it may not work + ''' + + def do_enable_gui(): + from _pydev_bundle.pydev_versioncheck import versionok_for_gui + if versionok_for_gui(): + try: + from pydev_ipython.inputhook import enable_gui + enable_gui(guiname) + except: + sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname) + traceback.print_exc() + elif guiname not in ['none', '', None]: + # Only print a warning if the guiname was going to do something + sys.stderr.write("PyDev console: Python version does not support GUI event loop integration for '%s'\n" % guiname) + # Return value does not matter, so return back what was sent + return guiname + + # Important: it has to be really enabled in the main thread, so, schedule + # it to run in the main thread. + self.exec_queue.put(do_enable_gui) + + def get_ipython_hidden_vars_dict(self): + return None + + +# ======================================================================================================================= +# FakeFrame +# ======================================================================================================================= +class FakeFrame: + ''' + Used to show console with variables connection. + A class to be used as a mock of a frame. + ''' diff --git a/_pydev_bundle/pydev_import_hook.py b/_pydev_bundle/pydev_import_hook.py new file mode 100644 index 0000000..519d8d7 --- /dev/null +++ b/_pydev_bundle/pydev_import_hook.py @@ -0,0 +1,40 @@ + +import sys +import traceback +from types import ModuleType +from _pydevd_bundle.pydevd_constants import DebugInfoHolder + +import builtins + + +class ImportHookManager(ModuleType): + + def __init__(self, name, system_import): + ModuleType.__init__(self, name) + self._system_import = system_import + self._modules_to_patch = {} + + def add_module_name(self, module_name, activate_function): + self._modules_to_patch[module_name] = activate_function + + def do_import(self, name, *args, **kwargs): + module = self._system_import(name, *args, **kwargs) + try: + activate_func = self._modules_to_patch.pop(name, None) + if activate_func: + activate_func() # call activate function + except: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 2: + traceback.print_exc() + + # Restore normal system importer to reduce performance impact + # of calling this method every time an import statement is invoked + if not self._modules_to_patch: + builtins.__import__ = self._system_import + + return module + + +import_hook_manager = ImportHookManager(__name__ + '.import_hook', builtins.__import__) +builtins.__import__ = import_hook_manager.do_import +sys.modules[import_hook_manager.__name__] = import_hook_manager diff --git a/_pydev_bundle/pydev_imports.py b/_pydev_bundle/pydev_imports.py new file mode 100644 index 0000000..edc2429 --- /dev/null +++ b/_pydev_bundle/pydev_imports.py @@ -0,0 +1,13 @@ +from _pydev_bundle._pydev_saved_modules import xmlrpclib +from _pydev_bundle._pydev_saved_modules import xmlrpcserver + +SimpleXMLRPCServer = xmlrpcserver.SimpleXMLRPCServer + +from _pydev_bundle._pydev_execfile import execfile + +from _pydev_bundle._pydev_saved_modules import _queue + +from _pydevd_bundle.pydevd_exec2 import Exec + +from urllib.parse import quote, quote_plus, unquote_plus # @UnresolvedImport + diff --git a/_pydev_bundle/pydev_ipython_console.py b/_pydev_bundle/pydev_ipython_console.py new file mode 100644 index 0000000..a1221f9 --- /dev/null +++ b/_pydev_bundle/pydev_ipython_console.py @@ -0,0 +1,97 @@ +import sys +from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface + +import traceback + +# Uncomment to force PyDev standard shell. +# raise ImportError() + +from _pydev_bundle.pydev_ipython_console_011 import get_pydev_frontend + + +#======================================================================================================================= +# InterpreterInterface +#======================================================================================================================= +class InterpreterInterface(BaseInterpreterInterface): + ''' + The methods in this class should be registered in the xml-rpc server. + ''' + + def __init__(self, host, client_port, main_thread, show_banner=True, connect_status_queue=None): + BaseInterpreterInterface.__init__(self, main_thread, connect_status_queue) + self.client_port = client_port + self.host = host + self.interpreter = get_pydev_frontend(host, client_port) + self._input_error_printed = False + self.notification_succeeded = False + self.notification_tries = 0 + self.notification_max_tries = 3 + self.show_banner = show_banner + + self.notify_about_magic() + + def get_greeting_msg(self): + if self.show_banner: + self.interpreter.show_banner() + return self.interpreter.get_greeting_msg() + + def do_add_exec(self, code_fragment): + self.notify_about_magic() + if code_fragment.text.rstrip().endswith('??'): + print('IPython-->') + try: + res = bool(self.interpreter.add_exec(code_fragment.text)) + finally: + if code_fragment.text.rstrip().endswith('??'): + print('<--IPython') + + return res + + def get_namespace(self): + return self.interpreter.get_namespace() + + def getCompletions(self, text, act_tok): + return self.interpreter.getCompletions(text, act_tok) + + def close(self): + sys.exit(0) + + def notify_about_magic(self): + if not self.notification_succeeded: + self.notification_tries += 1 + if self.notification_tries > self.notification_max_tries: + return + completions = self.getCompletions("%", "%") + magic_commands = [x[0] for x in completions] + + server = self.get_server() + + if server is not None: + try: + server.NotifyAboutMagic(magic_commands, self.interpreter.is_automagic()) + self.notification_succeeded = True + except: + self.notification_succeeded = False + + def get_ipython_hidden_vars_dict(self): + try: + if hasattr(self.interpreter, 'ipython') and hasattr(self.interpreter.ipython, 'user_ns_hidden'): + user_ns_hidden = self.interpreter.ipython.user_ns_hidden + if isinstance(user_ns_hidden, dict): + # Since IPython 2 dict `user_ns_hidden` contains hidden variables and values + user_hidden_dict = user_ns_hidden.copy() + else: + # In IPython 1.x `user_ns_hidden` used to be a set with names of hidden variables + user_hidden_dict = dict([(key, val) for key, val in self.interpreter.ipython.user_ns.items() + if key in user_ns_hidden]) + + # while `_`, `__` and `___` were not initialized, they are not presented in `user_ns_hidden` + user_hidden_dict.setdefault('_', '') + user_hidden_dict.setdefault('__', '') + user_hidden_dict.setdefault('___', '') + + return user_hidden_dict + except: + # Getting IPython variables shouldn't break loading frame variables + traceback.print_exc() + diff --git a/_pydev_bundle/pydev_ipython_console_011.py b/_pydev_bundle/pydev_ipython_console_011.py new file mode 100644 index 0000000..eaf4738 --- /dev/null +++ b/_pydev_bundle/pydev_ipython_console_011.py @@ -0,0 +1,516 @@ +# TODO that would make IPython integration better +# - show output other times then when enter was pressed +# - support proper exit to allow IPython to cleanup (e.g. temp files created with %edit) +# - support Ctrl-D (Ctrl-Z on Windows) +# - use IPython (numbered) prompts in PyDev +# - better integration of IPython and PyDev completions +# - some of the semantics on handling the code completion are not correct: +# eg: Start a line with % and then type c should give %cd as a completion by it doesn't +# however type %c and request completions and %cd is given as an option +# eg: Completing a magic when user typed it without the leading % causes the % to be inserted +# to the left of what should be the first colon. +"""Interface to TerminalInteractiveShell for PyDev Interactive Console frontend + for IPython 0.11 to 1.0+. +""" + +from __future__ import print_function + +import os +import sys +import codeop +import traceback + +from IPython.core.error import UsageError +from IPython.core.completer import IPCompleter +from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC +from IPython.core.usage import default_banner_parts +from IPython.utils.strdispatch import StrDispatch +import IPython.core.release as IPythonRelease +from IPython.terminal.interactiveshell import TerminalInteractiveShell +try: + from traitlets import CBool, Unicode +except ImportError: + from IPython.utils.traitlets import CBool, Unicode +from IPython.core import release + +from _pydev_bundle.pydev_imports import xmlrpclib + +default_pydev_banner_parts = default_banner_parts + +default_pydev_banner = ''.join(default_pydev_banner_parts) + + +def show_in_pager(self, strng, *args, **kwargs): + """ Run a string through pager """ + # On PyDev we just output the string, there are scroll bars in the console + # to handle "paging". This is the same behaviour as when TERM==dump (see + # page.py) + # for compatibility with mime-bundle form: + if isinstance(strng, dict): + strng = strng.get('text/plain', strng) + print(strng) + + +def create_editor_hook(pydev_host, pydev_client_port): + + def call_editor(filename, line=0, wait=True): + """ Open an editor in PyDev """ + if line is None: + line = 0 + + # Make sure to send an absolution path because unlike most editor hooks + # we don't launch a process. This is more like what happens in the zmqshell + filename = os.path.abspath(filename) + + # import sys + # sys.__stderr__.write('Calling editor at: %s:%s\n' % (pydev_host, pydev_client_port)) + + # Tell PyDev to open the editor + server = xmlrpclib.Server('http://%s:%s' % (pydev_host, pydev_client_port)) + server.IPythonEditor(filename, str(line)) + + if wait: + input("Press Enter when done editing:") + + return call_editor + + +class PyDevIPCompleter(IPCompleter): + + def __init__(self, *args, **kwargs): + """ Create a Completer that reuses the advanced completion support of PyDev + in addition to the completion support provided by IPython """ + IPCompleter.__init__(self, *args, **kwargs) + # Use PyDev for python matches, see getCompletions below + if self.python_matches in self.matchers: + # `self.python_matches` matches attributes or global python names + self.matchers.remove(self.python_matches) + + +class PyDevIPCompleter6(IPCompleter): + + def __init__(self, *args, **kwargs): + """ Create a Completer that reuses the advanced completion support of PyDev + in addition to the completion support provided by IPython """ + IPCompleter.__init__(self, *args, **kwargs) + + @property + def matchers(self): + """All active matcher routines for completion""" + # To remove python_matches we now have to override it as it's now a property in the superclass. + return [ + self.file_matches, + self.magic_matches, + self.python_func_kw_matches, + self.dict_key_matches, + ] + + @matchers.setter + def matchers(self, value): + # To stop the init in IPCompleter raising an AttributeError we now have to specify a setter as it's now a property in the superclass. + return + + +class PyDevTerminalInteractiveShell(TerminalInteractiveShell): + banner1 = Unicode(default_pydev_banner, config=True, + help="""The part of the banner to be printed before the profile""" + ) + + # TODO term_title: (can PyDev's title be changed???, see terminal.py for where to inject code, in particular set_term_title as used by %cd) + # for now, just disable term_title + term_title = CBool(False) + + # Note in version 0.11 there is no guard in the IPython code about displaying a + # warning, so with 0.11 you get: + # WARNING: Readline services not available or not loaded. + # WARNING: The auto-indent feature requires the readline library + # Disable readline, readline type code is all handled by PyDev (on Java side) + readline_use = CBool(False) + # autoindent has no meaning in PyDev (PyDev always handles that on the Java side), + # and attempting to enable it will print a warning in the absence of readline. + autoindent = CBool(False) + # Force console to not give warning about color scheme choice and default to NoColor. + # TODO It would be nice to enable colors in PyDev but: + # - The PyDev Console (Eclipse Console) does not support the full range of colors, so the + # effect isn't as nice anyway at the command line + # - If done, the color scheme should default to LightBG, but actually be dependent on + # any settings the user has (such as if a dark theme is in use, then Linux is probably + # a better theme). + colors_force = CBool(True) + colors = Unicode("NoColor") + # Since IPython 5 the terminal interface is not compatible with Emacs `inferior-shell` and + # the `simple_prompt` flag is needed + simple_prompt = CBool(True) + + # In the PyDev Console, GUI control is done via hookable XML-RPC server + @staticmethod + def enable_gui(gui=None, app=None): + """Switch amongst GUI input hooks by name. + """ + # Deferred import + from pydev_ipython.inputhook import enable_gui as real_enable_gui + try: + return real_enable_gui(gui, app) + except ValueError as e: + raise UsageError("%s" % e) + + #------------------------------------------------------------------------- + # Things related to hooks + #------------------------------------------------------------------------- + + def init_history(self): + # Disable history so that we don't have an additional thread for that + # (and we don't use the history anyways). + self.config.HistoryManager.enabled = False + super(PyDevTerminalInteractiveShell, self).init_history() + + def init_hooks(self): + super(PyDevTerminalInteractiveShell, self).init_hooks() + self.set_hook('show_in_pager', show_in_pager) + + #------------------------------------------------------------------------- + # Things related to exceptions + #------------------------------------------------------------------------- + + def showtraceback(self, exc_tuple=None, *args, **kwargs): + # IPython does a lot of clever stuff with Exceptions. However mostly + # it is related to IPython running in a terminal instead of an IDE. + # (e.g. it prints out snippets of code around the stack trace) + # PyDev does a lot of clever stuff too, so leave exception handling + # with default print_exc that PyDev can parse and do its clever stuff + # with (e.g. it puts links back to the original source code) + try: + if exc_tuple is None: + etype, value, tb = sys.exc_info() + else: + etype, value, tb = exc_tuple + except ValueError: + return + + if tb is not None: + traceback.print_exception(etype, value, tb) + + #------------------------------------------------------------------------- + # Things related to text completion + #------------------------------------------------------------------------- + + # The way to construct an IPCompleter changed in most versions, + # so we have a custom, per version implementation of the construction + + def _new_completer_100(self): + completer = PyDevIPCompleter(shell=self, + namespace=self.user_ns, + global_namespace=self.user_global_ns, + alias_table=self.alias_manager.alias_table, + use_readline=self.has_readline, + parent=self, + ) + return completer + + def _new_completer_234(self): + # correct for IPython versions 2.x, 3.x, 4.x + completer = PyDevIPCompleter(shell=self, + namespace=self.user_ns, + global_namespace=self.user_global_ns, + use_readline=self.has_readline, + parent=self, + ) + return completer + + def _new_completer_500(self): + completer = PyDevIPCompleter(shell=self, + namespace=self.user_ns, + global_namespace=self.user_global_ns, + use_readline=False, + parent=self + ) + return completer + + def _new_completer_600(self): + completer = PyDevIPCompleter6(shell=self, + namespace=self.user_ns, + global_namespace=self.user_global_ns, + use_readline=False, + parent=self + ) + return completer + + def add_completer_hooks(self): + from IPython.core.completerlib import module_completer, magic_run_completer, cd_completer + try: + from IPython.core.completerlib import reset_completer + except ImportError: + # reset_completer was added for rel-0.13 + reset_completer = None + self.configurables.append(self.Completer) + + # Add custom completers to the basic ones built into IPCompleter + sdisp = self.strdispatchers.get('complete_command', StrDispatch()) + self.strdispatchers['complete_command'] = sdisp + self.Completer.custom_completers = sdisp + + self.set_hook('complete_command', module_completer, str_key='import') + self.set_hook('complete_command', module_completer, str_key='from') + self.set_hook('complete_command', magic_run_completer, str_key='%run') + self.set_hook('complete_command', cd_completer, str_key='%cd') + if reset_completer: + self.set_hook('complete_command', reset_completer, str_key='%reset') + + def init_completer(self): + """Initialize the completion machinery. + + This creates a completer that provides the completions that are + IPython specific. We use this to supplement PyDev's core code + completions. + """ + # PyDev uses its own completer and custom hooks so that it uses + # most completions from PyDev's core completer which provides + # extra information. + # See getCompletions for where the two sets of results are merged + + if IPythonRelease._version_major >= 6: + self.Completer = self._new_completer_600() + elif IPythonRelease._version_major >= 5: + self.Completer = self._new_completer_500() + elif IPythonRelease._version_major >= 2: + self.Completer = self._new_completer_234() + elif IPythonRelease._version_major >= 1: + self.Completer = self._new_completer_100() + + if hasattr(self.Completer, 'use_jedi'): + self.Completer.use_jedi = False + + self.add_completer_hooks() + + if IPythonRelease._version_major <= 3: + # Only configure readline if we truly are using readline. IPython can + # do tab-completion over the network, in GUIs, etc, where readline + # itself may be absent + if self.has_readline: + self.set_readline_completer() + + #------------------------------------------------------------------------- + # Things related to aliases + #------------------------------------------------------------------------- + + def init_alias(self): + # InteractiveShell defines alias's we want, but TerminalInteractiveShell defines + # ones we don't. So don't use super and instead go right to InteractiveShell + InteractiveShell.init_alias(self) + + #------------------------------------------------------------------------- + # Things related to exiting + #------------------------------------------------------------------------- + def ask_exit(self): + """ Ask the shell to exit. Can be overiden and used as a callback. """ + # TODO PyDev's console does not have support from the Python side to exit + # the console. If user forces the exit (with sys.exit()) then the console + # simply reports errors. e.g.: + # >>> import sys + # >>> sys.exit() + # Failed to create input stream: Connection refused + # >>> + # Console already exited with value: 0 while waiting for an answer. + # Error stream: + # Output stream: + # >>> + # + # Alternatively if you use the non-IPython shell this is what happens + # >>> exit() + # :None + # >>> + # :None + # >>> + # + super(PyDevTerminalInteractiveShell, self).ask_exit() + print('To exit the PyDev Console, terminate the console within IDE.') + + #------------------------------------------------------------------------- + # Things related to magics + #------------------------------------------------------------------------- + + def init_magics(self): + super(PyDevTerminalInteractiveShell, self).init_magics() + # TODO Any additional magics for PyDev? + + +InteractiveShellABC.register(PyDevTerminalInteractiveShell) # @UndefinedVariable + + +#======================================================================================================================= +# _PyDevFrontEnd +#======================================================================================================================= +class _PyDevFrontEnd: + + version = release.__version__ + + def __init__(self): + # Create and initialize our IPython instance. + if hasattr(PyDevTerminalInteractiveShell, '_instance') and PyDevTerminalInteractiveShell._instance is not None: + self.ipython = PyDevTerminalInteractiveShell._instance + else: + self.ipython = PyDevTerminalInteractiveShell.instance() + + self._curr_exec_line = 0 + self._curr_exec_lines = [] + + def show_banner(self): + self.ipython.show_banner() + + def update(self, globals, locals): + ns = self.ipython.user_ns + + for key, value in list(ns.items()): + if key not in locals: + locals[key] = value + + self.ipython.user_global_ns.clear() + self.ipython.user_global_ns.update(globals) + self.ipython.user_ns = locals + + if hasattr(self.ipython, 'history_manager') and hasattr(self.ipython.history_manager, 'save_thread'): + self.ipython.history_manager.save_thread.pydev_do_not_trace = True # don't trace ipython history saving thread + + def complete(self, string): + try: + if string: + return self.ipython.complete(None, line=string, cursor_pos=string.__len__()) + else: + return self.ipython.complete(string, string, 0) + except: + # Silence completer exceptions + pass + + def is_complete(self, string): + # Based on IPython 0.10.1 + + if string in ('', '\n'): + # Prefiltering, eg through ipython0, may return an empty + # string although some operations have been accomplished. We + # thus want to consider an empty string as a complete + # statement. + return True + else: + try: + # Add line returns here, to make sure that the statement is + # complete (except if '\' was used). + # This should probably be done in a different place (like + # maybe 'prefilter_input' method? For now, this works. + clean_string = string.rstrip('\n') + if not clean_string.endswith('\\'): + clean_string += '\n\n' + + is_complete = codeop.compile_command( + clean_string, + "", + "exec" + ) + except Exception: + # XXX: Hack: return True so that the + # code gets executed and the error captured. + is_complete = True + return is_complete + + def getCompletions(self, text, act_tok): + # Get completions from IPython and from PyDev and merge the results + # IPython only gives context free list of completions, while PyDev + # gives detailed information about completions. + try: + TYPE_IPYTHON = '11' + TYPE_IPYTHON_MAGIC = '12' + _line, ipython_completions = self.complete(text) + + from _pydev_bundle._pydev_completer import Completer + completer = Completer(self.get_namespace(), None) + ret = completer.complete(act_tok) + append = ret.append + ip = self.ipython + pydev_completions = set([f[0] for f in ret]) + for ipython_completion in ipython_completions: + + # PyCharm was not expecting completions with '%'... + # Could be fixed in the backend, but it's probably better + # fixing it at PyCharm. + # if ipython_completion.startswith('%'): + # ipython_completion = ipython_completion[1:] + + if ipython_completion not in pydev_completions: + pydev_completions.add(ipython_completion) + inf = ip.object_inspect(ipython_completion) + if inf['type_name'] == 'Magic function': + pydev_type = TYPE_IPYTHON_MAGIC + else: + pydev_type = TYPE_IPYTHON + pydev_doc = inf['docstring'] + if pydev_doc is None: + pydev_doc = '' + append((ipython_completion, pydev_doc, '', pydev_type)) + return ret + except: + import traceback;traceback.print_exc() + return [] + + def get_namespace(self): + return self.ipython.user_ns + + def clear_buffer(self): + del self._curr_exec_lines[:] + + def add_exec(self, line): + if self._curr_exec_lines: + self._curr_exec_lines.append(line) + + buf = '\n'.join(self._curr_exec_lines) + + if self.is_complete(buf): + self._curr_exec_line += 1 + self.ipython.run_cell(buf) + del self._curr_exec_lines[:] + return False # execute complete (no more) + + return True # needs more + else: + + if not self.is_complete(line): + # Did not execute + self._curr_exec_lines.append(line) + return True # needs more + else: + self._curr_exec_line += 1 + self.ipython.run_cell(line, store_history=True) + # hist = self.ipython.history_manager.output_hist_reprs + # rep = hist.get(self._curr_exec_line, None) + # if rep is not None: + # print(rep) + return False # execute complete (no more) + + def is_automagic(self): + return self.ipython.automagic + + def get_greeting_msg(self): + return 'PyDev console: using IPython %s\n' % self.version + + +class _PyDevFrontEndContainer: + _instance = None + _last_host_port = None + + +def get_pydev_frontend(pydev_host, pydev_client_port): + if _PyDevFrontEndContainer._instance is None: + _PyDevFrontEndContainer._instance = _PyDevFrontEnd() + + if _PyDevFrontEndContainer._last_host_port != (pydev_host, pydev_client_port): + _PyDevFrontEndContainer._last_host_port = pydev_host, pydev_client_port + + # Back channel to PyDev to open editors (in the future other + # info may go back this way. This is the same channel that is + # used to get stdin, see StdIn in pydev_console_utils) + _PyDevFrontEndContainer._instance.ipython.hooks['editor'] = create_editor_hook(pydev_host, pydev_client_port) + + # Note: setting the callback directly because setting it with set_hook would actually create a chain instead + # of ovewriting at each new call). + # _PyDevFrontEndContainer._instance.ipython.set_hook('editor', create_editor_hook(pydev_host, pydev_client_port)) + + return _PyDevFrontEndContainer._instance + diff --git a/_pydev_bundle/pydev_is_thread_alive.py b/_pydev_bundle/pydev_is_thread_alive.py new file mode 100644 index 0000000..d949ba2 --- /dev/null +++ b/_pydev_bundle/pydev_is_thread_alive.py @@ -0,0 +1,23 @@ +from _pydev_bundle._pydev_saved_modules import threading + +# Hack for https://www.brainwy.com/tracker/PyDev/363 (i.e.: calling is_alive() can throw AssertionError under some +# circumstances). +# It is required to debug threads started by start_new_thread in Python 3.4 +_temp = threading.Thread() +if hasattr(_temp, '_is_stopped'): # Python 3.x has this + + def is_thread_alive(t): + return not t._is_stopped + +elif hasattr(_temp, '_Thread__stopped'): # Python 2.x has this + + def is_thread_alive(t): + return not t._Thread__stopped + +else: + + # Jython wraps a native java thread and thus only obeys the public API. + def is_thread_alive(t): + return t.is_alive() + +del _temp diff --git a/_pydev_bundle/pydev_localhost.py b/_pydev_bundle/pydev_localhost.py new file mode 100644 index 0000000..0d2838d --- /dev/null +++ b/_pydev_bundle/pydev_localhost.py @@ -0,0 +1,67 @@ +from _pydev_bundle._pydev_saved_modules import socket +import sys + +IS_JYTHON = sys.platform.find('java') != -1 + +_cache = None + + +def get_localhost(): + ''' + Should return 127.0.0.1 in ipv4 and ::1 in ipv6 + + localhost is not used because on windows vista/windows 7, there can be issues where the resolving doesn't work + properly and takes a lot of time (had this issue on the pyunit server). + + Using the IP directly solves the problem. + ''' + # TODO: Needs better investigation! + + global _cache + if _cache is None: + try: + for addr_info in socket.getaddrinfo("localhost", 80, 0, 0, socket.SOL_TCP): + config = addr_info[4] + if config[0] == '127.0.0.1': + _cache = '127.0.0.1' + return _cache + except: + # Ok, some versions of Python don't have getaddrinfo or SOL_TCP... Just consider it 127.0.0.1 in this case. + _cache = '127.0.0.1' + else: + _cache = 'localhost' + + return _cache + + +def get_socket_names(n_sockets, close=False): + socket_names = [] + sockets = [] + for _ in range(n_sockets): + if IS_JYTHON: + # Although the option which would be pure java *should* work for Jython, the socket being returned is still 0 + # (i.e.: it doesn't give the local port bound, only the original port, which was 0). + from java.net import ServerSocket + sock = ServerSocket(0) + socket_name = get_localhost(), sock.getLocalPort() + else: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((get_localhost(), 0)) + socket_name = sock.getsockname() + + sockets.append(sock) + socket_names.append(socket_name) + + if close: + for s in sockets: + s.close() + return socket_names + + +def get_socket_name(close=False): + return get_socket_names(1, close)[0] + + +if __name__ == '__main__': + print(get_socket_name()) diff --git a/_pydev_bundle/pydev_log.py b/_pydev_bundle/pydev_log.py new file mode 100644 index 0000000..7155195 --- /dev/null +++ b/_pydev_bundle/pydev_log.py @@ -0,0 +1,276 @@ +from _pydevd_bundle.pydevd_constants import DebugInfoHolder, SHOW_COMPILE_CYTHON_COMMAND_LINE, NULL, LOG_TIME, \ + ForkSafeLock +from contextlib import contextmanager +import traceback +import os +import sys + + +class _LoggingGlobals(object): + _warn_once_map = {} + _debug_stream_filename = None + _debug_stream = NULL + _debug_stream_initialized = False + _initialize_lock = ForkSafeLock() + + +def initialize_debug_stream(reinitialize=False): + ''' + :param bool reinitialize: + Reinitialize is used to update the debug stream after a fork (thus, if it wasn't + initialized, we don't need to do anything, just wait for the first regular log call + to initialize). + ''' + if reinitialize: + if not _LoggingGlobals._debug_stream_initialized: + return + else: + if _LoggingGlobals._debug_stream_initialized: + return + + with _LoggingGlobals._initialize_lock: + # Initialization is done lazilly, so, it's possible that multiple threads try to initialize + # logging. + + # Check initial conditions again after obtaining the lock. + if reinitialize: + if not _LoggingGlobals._debug_stream_initialized: + return + else: + if _LoggingGlobals._debug_stream_initialized: + return + + _LoggingGlobals._debug_stream_initialized = True + + # Note: we cannot initialize with sys.stderr because when forking we may end up logging things in 'os' calls. + _LoggingGlobals._debug_stream = NULL + _LoggingGlobals._debug_stream_filename = None + + if not DebugInfoHolder.PYDEVD_DEBUG_FILE: + _LoggingGlobals._debug_stream = sys.stderr + else: + # Add pid to the filename. + try: + target_file = DebugInfoHolder.PYDEVD_DEBUG_FILE + debug_file = _compute_filename_with_pid(target_file) + _LoggingGlobals._debug_stream = open(debug_file, 'w') + _LoggingGlobals._debug_stream_filename = debug_file + except Exception: + _LoggingGlobals._debug_stream = sys.stderr + # Don't fail when trying to setup logging, just show the exception. + traceback.print_exc() + + +def _compute_filename_with_pid(target_file, pid=None): + # Note: used in tests. + dirname = os.path.dirname(target_file) + basename = os.path.basename(target_file) + try: + os.makedirs(dirname) + except Exception: + pass # Ignore error if it already exists. + + name, ext = os.path.splitext(basename) + if pid is None: + pid = os.getpid() + return os.path.join(dirname, '%s.%s%s' % (name, pid, ext)) + + +def log_to(log_file:str, log_level:int=3) -> None: + with _LoggingGlobals._initialize_lock: + # Can be set directly. + DebugInfoHolder.DEBUG_TRACE_LEVEL = log_level + + if DebugInfoHolder.PYDEVD_DEBUG_FILE != log_file: + # Note that we don't need to reset it unless it actually changed + # (would be the case where it's set as an env var in a new process + # and a subprocess initializes logging to the same value). + _LoggingGlobals._debug_stream = NULL + _LoggingGlobals._debug_stream_filename = None + + DebugInfoHolder.PYDEVD_DEBUG_FILE = log_file + + _LoggingGlobals._debug_stream_initialized = False + + +def list_log_files(pydevd_debug_file): + log_files = [] + dirname = os.path.dirname(pydevd_debug_file) + basename = os.path.basename(pydevd_debug_file) + if os.path.isdir(dirname): + name, ext = os.path.splitext(basename) + for f in os.listdir(dirname): + if f.startswith(name) and f.endswith(ext): + log_files.append(os.path.join(dirname, f)) + return log_files + + +@contextmanager +def log_context(trace_level, stream): + ''' + To be used to temporarily change the logging settings. + ''' + with _LoggingGlobals._initialize_lock: + original_trace_level = DebugInfoHolder.DEBUG_TRACE_LEVEL + original_debug_stream = _LoggingGlobals._debug_stream + original_pydevd_debug_file = DebugInfoHolder.PYDEVD_DEBUG_FILE + original_debug_stream_filename = _LoggingGlobals._debug_stream_filename + original_initialized = _LoggingGlobals._debug_stream_initialized + + DebugInfoHolder.DEBUG_TRACE_LEVEL = trace_level + _LoggingGlobals._debug_stream = stream + _LoggingGlobals._debug_stream_initialized = True + try: + yield + finally: + with _LoggingGlobals._initialize_lock: + DebugInfoHolder.DEBUG_TRACE_LEVEL = original_trace_level + _LoggingGlobals._debug_stream = original_debug_stream + DebugInfoHolder.PYDEVD_DEBUG_FILE = original_pydevd_debug_file + _LoggingGlobals._debug_stream_filename = original_debug_stream_filename + _LoggingGlobals._debug_stream_initialized = original_initialized + + +import time +_last_log_time = time.time() + +# Set to True to show pid in each logged message (usually the file has it, but sometimes it's handy). +_LOG_PID = False + + +def _pydevd_log(level, msg, *args): + ''' + Levels are: + + 0 most serious warnings/errors (always printed) + 1 warnings/significant events + 2 informational trace + 3 verbose mode + ''' + if level <= DebugInfoHolder.DEBUG_TRACE_LEVEL: + # yes, we can have errors printing if the console of the program has been finished (and we're still trying to print something) + try: + try: + if args: + msg = msg % args + except: + msg = '%s - %s' % (msg, args) + + if LOG_TIME: + global _last_log_time + new_log_time = time.time() + time_diff = new_log_time - _last_log_time + _last_log_time = new_log_time + msg = '%.2fs - %s\n' % (time_diff, msg,) + else: + msg = '%s\n' % (msg,) + + if _LOG_PID: + msg = '<%s> - %s\n' % (os.getpid(), msg,) + + try: + try: + initialize_debug_stream() # Do it as late as possible + _LoggingGlobals._debug_stream.write(msg) + except TypeError: + if isinstance(msg, bytes): + # Depending on the StringIO flavor, it may only accept unicode. + msg = msg.decode('utf-8', 'replace') + _LoggingGlobals._debug_stream.write(msg) + except UnicodeEncodeError: + # When writing to the stream it's possible that the string can't be represented + # in the encoding expected (in this case, convert it to the stream encoding + # or ascii if we can't find one suitable using a suitable replace). + encoding = getattr(_LoggingGlobals._debug_stream, 'encoding', 'ascii') + msg = msg.encode(encoding, 'backslashreplace') + msg = msg.decode(encoding) + _LoggingGlobals._debug_stream.write(msg) + + _LoggingGlobals._debug_stream.flush() + except: + pass + return True + + +def _pydevd_log_exception(msg='', *args): + if msg or args: + _pydevd_log(0, msg, *args) + try: + initialize_debug_stream() # Do it as late as possible + traceback.print_exc(file=_LoggingGlobals._debug_stream) + _LoggingGlobals._debug_stream.flush() + except: + raise + + +def verbose(msg, *args): + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 3: + _pydevd_log(3, msg, *args) + + +def debug(msg, *args): + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 2: + _pydevd_log(2, msg, *args) + + +def info(msg, *args): + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + _pydevd_log(1, msg, *args) + + +warn = info + + +def critical(msg, *args): + _pydevd_log(0, msg, *args) + + +def exception(msg='', *args): + try: + _pydevd_log_exception(msg, *args) + except: + pass # Should never fail (even at interpreter shutdown). + + +error = exception + + +def error_once(msg, *args): + try: + if args: + message = msg % args + else: + message = str(msg) + except: + message = '%s - %s' % (msg, args) + + if message not in _LoggingGlobals._warn_once_map: + _LoggingGlobals._warn_once_map[message] = True + critical(message) + + +def exception_once(msg, *args): + try: + if args: + message = msg % args + else: + message = str(msg) + except: + message = '%s - %s' % (msg, args) + + if message not in _LoggingGlobals._warn_once_map: + _LoggingGlobals._warn_once_map[message] = True + exception(message) + + +def debug_once(msg, *args): + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 3: + error_once(msg, *args) + + +def show_compile_cython_command_line(): + if SHOW_COMPILE_CYTHON_COMMAND_LINE: + dirname = os.path.dirname(os.path.dirname(__file__)) + error_once("warning: Debugger speedups using cython not found. Run '\"%s\" \"%s\" build_ext --inplace' to build.", + sys.executable, os.path.join(dirname, 'setup_pydevd_cython.py')) + diff --git a/_pydev_bundle/pydev_monkey.py b/_pydev_bundle/pydev_monkey.py new file mode 100644 index 0000000..9f6c15f --- /dev/null +++ b/_pydev_bundle/pydev_monkey.py @@ -0,0 +1,1190 @@ +# License: EPL +import os +import re +import sys +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle.pydevd_constants import get_global_debugger, IS_WINDOWS, IS_JYTHON, get_current_thread_id, \ + sorted_dict_repr, set_global_debugger, DebugInfoHolder +from _pydev_bundle import pydev_log +from contextlib import contextmanager +from _pydevd_bundle import pydevd_constants +from _pydevd_bundle.pydevd_defaults import PydevdCustomization +import ast + +try: + from pathlib import Path +except ImportError: + Path = None + +#=============================================================================== +# Things that are dependent on having the pydevd debugger +#=============================================================================== + +pydev_src_dir = os.path.dirname(os.path.dirname(__file__)) + +_arg_patch = threading.local() + + +@contextmanager +def skip_subprocess_arg_patch(): + _arg_patch.apply_arg_patching = False + try: + yield + finally: + _arg_patch.apply_arg_patching = True + + +def _get_apply_arg_patching(): + return getattr(_arg_patch, 'apply_arg_patching', True) + + +def _get_setup_updated_with_protocol_and_ppid(setup, is_exec=False): + if setup is None: + setup = {} + setup = setup.copy() + # Discard anything related to the protocol (we'll set the the protocol based on the one + # currently set). + setup.pop(pydevd_constants.ARGUMENT_HTTP_JSON_PROTOCOL, None) + setup.pop(pydevd_constants.ARGUMENT_JSON_PROTOCOL, None) + setup.pop(pydevd_constants.ARGUMENT_QUOTED_LINE_PROTOCOL, None) + + if not is_exec: + # i.e.: The ppid for the subprocess is the current pid. + # If it's an exec, keep it what it was. + setup[pydevd_constants.ARGUMENT_PPID] = os.getpid() + + protocol = pydevd_constants.get_protocol() + if protocol == pydevd_constants.HTTP_JSON_PROTOCOL: + setup[pydevd_constants.ARGUMENT_HTTP_JSON_PROTOCOL] = True + + elif protocol == pydevd_constants.JSON_PROTOCOL: + setup[pydevd_constants.ARGUMENT_JSON_PROTOCOL] = True + + elif protocol == pydevd_constants.QUOTED_LINE_PROTOCOL: + setup[pydevd_constants.ARGUMENT_QUOTED_LINE_PROTOCOL] = True + + elif protocol == pydevd_constants.HTTP_PROTOCOL: + setup[pydevd_constants.ARGUMENT_HTTP_PROTOCOL] = True + + else: + pydev_log.debug('Unexpected protocol: %s', protocol) + + if DebugInfoHolder.PYDEVD_DEBUG_FILE: + setup['log-file'] = DebugInfoHolder.PYDEVD_DEBUG_FILE + + if DebugInfoHolder.DEBUG_TRACE_LEVEL: + setup['log-level'] = DebugInfoHolder.DEBUG_TRACE_LEVEL + + return setup + + +class _LastFutureImportFinder(ast.NodeVisitor): + + def __init__(self): + self.last_future_import_found = None + + def visit_ImportFrom(self, node): + if node.module == '__future__': + self.last_future_import_found = node + + +def _get_offset_from_line_col(code, line, col): + offset = 0 + for i, line_contents in enumerate(code.splitlines(True)): + if i == line: + offset += col + return offset + else: + offset += len(line_contents) + + return -1 + + +def _separate_future_imports(code): + ''' + :param code: + The code from where we want to get the __future__ imports (note that it's possible that + there's no such entry). + + :return tuple(str, str): + The return is a tuple(future_import, code). + + If the future import is not available a return such as ('', code) is given, otherwise, the + future import will end with a ';' (so that it can be put right before the pydevd attach + code). + ''' + try: + node = ast.parse(code, '', 'exec') + visitor = _LastFutureImportFinder() + visitor.visit(node) + + if visitor.last_future_import_found is None: + return '', code + + node = visitor.last_future_import_found + offset = -1 + if hasattr(node, 'end_lineno') and hasattr(node, 'end_col_offset'): + # Python 3.8 onwards has these (so, use when possible). + line, col = node.end_lineno, node.end_col_offset + offset = _get_offset_from_line_col(code, line - 1, col) # ast lines are 1-based, make it 0-based. + + else: + # end line/col not available, let's just find the offset and then search + # for the alias from there. + line, col = node.lineno, node.col_offset + offset = _get_offset_from_line_col(code, line - 1, col) # ast lines are 1-based, make it 0-based. + if offset >= 0 and node.names: + from_future_import_name = node.names[-1].name + i = code.find(from_future_import_name, offset) + if i < 0: + offset = -1 + else: + offset = i + len(from_future_import_name) + + if offset >= 0: + for i in range(offset, len(code)): + if code[i] in (' ', '\t', ';', ')', '\n'): + offset += 1 + else: + break + + future_import = code[:offset] + code_remainder = code[offset:] + + # Now, put '\n' lines back into the code remainder (we had to search for + # `\n)`, but in case we just got the `\n`, it should be at the remainder, + # not at the future import. + while future_import.endswith('\n'): + future_import = future_import[:-1] + code_remainder = '\n' + code_remainder + + if not future_import.endswith(';'): + future_import += ';' + return future_import, code_remainder + + # This shouldn't happen... + pydev_log.info('Unable to find line %s in code:\n%r', line, code) + return '', code + + except: + pydev_log.exception('Error getting from __future__ imports from: %r', code) + return '', code + + +def _get_python_c_args(host, port, code, args, setup): + setup = _get_setup_updated_with_protocol_and_ppid(setup) + + # i.e.: We want to make the repr sorted so that it works in tests. + setup_repr = setup if setup is None else (sorted_dict_repr(setup)) + + future_imports = '' + if '__future__' in code: + # If the code has a __future__ import, we need to be able to strip the __future__ + # imports from the code and add them to the start of our code snippet. + future_imports, code = _separate_future_imports(code) + + return ("%simport sys; sys.path.insert(0, r'%s'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL=%r; " + "pydevd.settrace(host=%r, port=%s, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=%r, client_access_token=%r, __setup_holder__=%s); " + "%s" + ) % ( + future_imports, + pydev_src_dir, + pydevd_constants.get_protocol(), + host, + port, + setup.get('access-token'), + setup.get('client-access-token'), + setup_repr, + code) + + +def _get_host_port(): + import pydevd + host, port = pydevd.dispatch() + return host, port + + +def _is_managed_arg(arg): + pydevd_py = _get_str_type_compatible(arg, 'pydevd.py') + if arg.endswith(pydevd_py): + return True + return False + + +def _on_forked_process(setup_tracing=True): + pydevd_constants.after_fork() + pydev_log.initialize_debug_stream(reinitialize=True) + + if setup_tracing: + pydev_log.debug('pydevd on forked process: %s', os.getpid()) + + import pydevd + pydevd.threadingCurrentThread().__pydevd_main_thread = True + pydevd.settrace_forked(setup_tracing=setup_tracing) + + +def _on_set_trace_for_new_thread(global_debugger): + if global_debugger is not None: + global_debugger.enable_tracing() + + +def _get_str_type_compatible(s, args): + ''' + This method converts `args` to byte/unicode based on the `s' type. + ''' + if isinstance(args, (list, tuple)): + ret = [] + for arg in args: + if type(s) == type(arg): + ret.append(arg) + else: + if isinstance(s, bytes): + ret.append(arg.encode('utf-8')) + else: + ret.append(arg.decode('utf-8')) + return ret + else: + if type(s) == type(args): + return args + else: + if isinstance(s, bytes): + return args.encode('utf-8') + else: + return args.decode('utf-8') + + +#=============================================================================== +# Things related to monkey-patching +#=============================================================================== +def is_python(path): + single_quote, double_quote = _get_str_type_compatible(path, ["'", '"']) + + if path.endswith(single_quote) or path.endswith(double_quote): + path = path[1:len(path) - 1] + filename = os.path.basename(path).lower() + for name in _get_str_type_compatible(filename, ['python', 'jython', 'pypy']): + if filename.find(name) != -1: + return True + + return False + + +class InvalidTypeInArgsException(Exception): + pass + + +def remove_quotes_from_args(args): + if sys.platform == "win32": + new_args = [] + + for x in args: + if Path is not None and isinstance(x, Path): + x = str(x) + else: + if not isinstance(x, (bytes, str)): + raise InvalidTypeInArgsException(str(type(x))) + + double_quote, two_double_quotes = _get_str_type_compatible(x, ['"', '""']) + + if x != two_double_quotes: + if len(x) > 1 and x.startswith(double_quote) and x.endswith(double_quote): + x = x[1:-1] + + new_args.append(x) + return new_args + else: + new_args = [] + for x in args: + if Path is not None and isinstance(x, Path): + x = x.as_posix() + else: + if not isinstance(x, (bytes, str)): + raise InvalidTypeInArgsException(str(type(x))) + new_args.append(x) + + return new_args + + +def quote_arg_win32(arg): + fix_type = lambda x: _get_str_type_compatible(arg, x) + + # See if we need to quote at all - empty strings need quoting, as do strings + # with whitespace or quotes in them. Backslashes do not need quoting. + if arg and not set(arg).intersection(fix_type(' "\t\n\v')): + return arg + + # Per https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw, + # the standard way to interpret arguments in double quotes is as follows: + # + # 2N backslashes followed by a quotation mark produce N backslashes followed by + # begin/end quote. This does not become part of the parsed argument, but toggles + # the "in quotes" mode. + # + # 2N+1 backslashes followed by a quotation mark again produce N backslashes followed + # by a quotation mark literal ("). This does not toggle the "in quotes" mode. + # + # N backslashes not followed by a quotation mark simply produce N backslashes. + # + # This code needs to do the reverse transformation, thus: + # + # N backslashes followed by " produce 2N+1 backslashes followed by " + # + # N backslashes at the end (i.e. where the closing " goes) produce 2N backslashes. + # + # N backslashes in any other position remain as is. + + arg = re.sub(fix_type(r'(\\*)\"'), fix_type(r'\1\1\\"'), arg) + arg = re.sub(fix_type(r'(\\*)$'), fix_type(r'\1\1'), arg) + return fix_type('"') + arg + fix_type('"') + + +def quote_args(args): + if sys.platform == "win32": + return list(map(quote_arg_win32, args)) + else: + return args + + +def patch_args(args, is_exec=False): + ''' + :param list args: + Arguments to patch. + + :param bool is_exec: + If it's an exec, the current process will be replaced (this means we have + to keep the same ppid). + ''' + try: + pydev_log.debug("Patching args: %s", args) + original_args = args + try: + unquoted_args = remove_quotes_from_args(args) + except InvalidTypeInArgsException as e: + pydev_log.info('Unable to monkey-patch subprocess arguments because a type found in the args is invalid: %s', e) + return original_args + + # Internally we should reference original_args (if we want to return them) or unquoted_args + # to add to the list which will be then quoted in the end. + del args + + from pydevd import SetupHolder + if not unquoted_args: + return original_args + + if not is_python(unquoted_args[0]): + pydev_log.debug("Process is not python, returning.") + return original_args + + # Note: we create a copy as string to help with analyzing the arguments, but + # the final list should have items from the unquoted_args as they were initially. + args_as_str = _get_str_type_compatible('', unquoted_args) + + params_with_value_in_separate_arg = ( + '--check-hash-based-pycs', + '--jit' # pypy option + ) + + # All short switches may be combined together. The ones below require a value and the + # value itself may be embedded in the arg. + # + # i.e.: Python accepts things as: + # + # python -OQold -qmtest + # + # Which is the same as: + # + # python -O -Q old -q -m test + # + # or even: + # + # python -OQold "-vcimport sys;print(sys)" + # + # Which is the same as: + # + # python -O -Q old -v -c "import sys;print(sys)" + + params_with_combinable_arg = set(('W', 'X', 'Q', 'c', 'm')) + + module_name = None + before_module_flag = '' + module_name_i_start = -1 + module_name_i_end = -1 + + code = None + code_i = -1 + code_i_end = -1 + code_flag = '' + + filename = None + filename_i = -1 + + ignore_next = True # start ignoring the first (the first entry is the python executable) + for i, arg_as_str in enumerate(args_as_str): + if ignore_next: + ignore_next = False + continue + + if arg_as_str.startswith('-'): + if arg_as_str == '-': + # Contents will be read from the stdin. This is not currently handled. + pydev_log.debug('Unable to fix arguments to attach debugger on subprocess when reading from stdin ("python ... -").') + return original_args + + if arg_as_str.startswith(params_with_value_in_separate_arg): + if arg_as_str in params_with_value_in_separate_arg: + ignore_next = True + continue + + break_out = False + for j, c in enumerate(arg_as_str): + + # i.e.: Python supports -X faulthandler as well as -Xfaulthandler + # (in one case we have to ignore the next and in the other we don't + # have to ignore it). + if c in params_with_combinable_arg: + remainder = arg_as_str[j + 1:] + if not remainder: + ignore_next = True + + if c == 'm': + # i.e.: Something as + # python -qm test + # python -m test + # python -qmtest + before_module_flag = arg_as_str[:j] # before_module_flag would then be "-q" + if before_module_flag == '-': + before_module_flag = '' + module_name_i_start = i + if not remainder: + module_name = unquoted_args[i + 1] + module_name_i_end = i + 1 + else: + # i.e.: python -qmtest should provide 'test' as the module_name + module_name = unquoted_args[i][j + 1:] + module_name_i_end = module_name_i_start + break_out = True + break + + elif c == 'c': + # i.e.: Something as + # python -qc "import sys" + # python -c "import sys" + # python "-qcimport sys" + code_flag = arg_as_str[:j + 1] # code_flag would then be "-qc" + + if not remainder: + # arg_as_str is something as "-qc", "import sys" + code = unquoted_args[i + 1] + code_i_end = i + 2 + else: + # if arg_as_str is something as "-qcimport sys" + code = remainder # code would be "import sys" + code_i_end = i + 1 + code_i = i + break_out = True + break + + else: + break + + if break_out: + break + + else: + # It doesn't start with '-' and we didn't ignore this entry: + # this means that this is the file to be executed. + filename = unquoted_args[i] + + # Note that the filename is not validated here. + # There are cases where even a .exe is valid (xonsh.exe): + # https://github.com/microsoft/debugpy/issues/945 + # So, we should support whatever runpy.run_path + # supports in this case. + + filename_i = i + + if _is_managed_arg(filename): # no need to add pydevd twice + pydev_log.debug('Skipped monkey-patching as pydevd.py is in args already.') + return original_args + + break + else: + # We didn't find the filename (something is unexpected). + pydev_log.debug('Unable to fix arguments to attach debugger on subprocess (filename not found).') + return original_args + + if code_i != -1: + host, port = _get_host_port() + + if port is not None: + new_args = [] + new_args.extend(unquoted_args[:code_i]) + new_args.append(code_flag) + new_args.append(_get_python_c_args(host, port, code, unquoted_args, SetupHolder.setup)) + new_args.extend(unquoted_args[code_i_end:]) + + return quote_args(new_args) + + first_non_vm_index = max(filename_i, module_name_i_start) + if first_non_vm_index == -1: + pydev_log.debug('Unable to fix arguments to attach debugger on subprocess (could not resolve filename nor module name).') + return original_args + + # Original args should be something as: + # ['X:\\pysrc\\pydevd.py', '--multiprocess', '--print-in-debugger-startup', + # '--vm_type', 'python', '--client', '127.0.0.1', '--port', '56352', '--file', 'x:\\snippet1.py'] + from _pydevd_bundle.pydevd_command_line_handling import setup_to_argv + new_args = [] + new_args.extend(unquoted_args[:first_non_vm_index]) + if before_module_flag: + new_args.append(before_module_flag) + + add_module_at = len(new_args) + 1 + + new_args.extend(setup_to_argv( + _get_setup_updated_with_protocol_and_ppid(SetupHolder.setup, is_exec=is_exec), + skip_names=set(('module', 'cmd-line')) + )) + new_args.append('--file') + + if module_name is not None: + assert module_name_i_start != -1 + assert module_name_i_end != -1 + # Always after 'pydevd' (i.e.: pydevd "--module" --multiprocess ...) + new_args.insert(add_module_at, '--module') + new_args.append(module_name) + new_args.extend(unquoted_args[module_name_i_end + 1:]) + + elif filename is not None: + assert filename_i != -1 + new_args.append(filename) + new_args.extend(unquoted_args[filename_i + 1:]) + + else: + raise AssertionError('Internal error (unexpected condition)') + + return quote_args(new_args) + except: + pydev_log.exception('Error patching args (debugger not attached to subprocess).') + return original_args + + +def str_to_args_windows(args): + # See https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments. + # + # Implemetation ported from DebugPlugin.parseArgumentsWindows: + # https://github.com/eclipse/eclipse.platform.debug/blob/master/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java + + result = [] + + DEFAULT = 0 + ARG = 1 + IN_DOUBLE_QUOTE = 2 + + state = DEFAULT + backslashes = 0 + buf = '' + + args_len = len(args) + for i in range(args_len): + ch = args[i] + if (ch == '\\'): + backslashes += 1 + continue + elif (backslashes != 0): + if ch == '"': + while backslashes >= 2: + backslashes -= 2 + buf += '\\' + if (backslashes == 1): + if (state == DEFAULT): + state = ARG + + buf += '"' + backslashes = 0 + continue + # else fall through to switch + else: + # false alarm, treat passed backslashes literally... + if (state == DEFAULT): + state = ARG + + while backslashes > 0: + backslashes -= 1 + buf += '\\' + # fall through to switch + if ch in (' ', '\t'): + if (state == DEFAULT): + # skip + continue + elif (state == ARG): + state = DEFAULT + result.append(buf) + buf = '' + continue + + if state in (DEFAULT, ARG): + if ch == '"': + state = IN_DOUBLE_QUOTE + else: + state = ARG + buf += ch + + elif state == IN_DOUBLE_QUOTE: + if ch == '"': + if (i + 1 < args_len and args[i + 1] == '"'): + # Undocumented feature in Windows: + # Two consecutive double quotes inside a double-quoted argument are interpreted as + # a single double quote. + buf += '"' + i += 1 + else: + state = ARG + else: + buf += ch + + else: + raise RuntimeError('Illegal condition') + + if len(buf) > 0 or state != DEFAULT: + result.append(buf) + + return result + + +def patch_arg_str_win(arg_str): + args = str_to_args_windows(arg_str) + # Fix https://youtrack.jetbrains.com/issue/PY-9767 (args may be empty) + if not args or not is_python(args[0]): + return arg_str + arg_str = ' '.join(patch_args(args)) + pydev_log.debug("New args: %s", arg_str) + return arg_str + + +def monkey_patch_module(module, funcname, create_func): + if hasattr(module, funcname): + original_name = 'original_' + funcname + if not hasattr(module, original_name): + setattr(module, original_name, getattr(module, funcname)) + setattr(module, funcname, create_func(original_name)) + + +def monkey_patch_os(funcname, create_func): + monkey_patch_module(os, funcname, create_func) + + +def warn_multiproc(): + pass # TODO: Provide logging as messages to the IDE. + # pydev_log.error_once( + # "pydev debugger: New process is launching (breakpoints won't work in the new process).\n" + # "pydev debugger: To debug that process please enable 'Attach to subprocess automatically while debugging?' option in the debugger settings.\n") + # + + +def create_warn_multiproc(original_name): + + def new_warn_multiproc(*args, **kwargs): + import os + + warn_multiproc() + + return getattr(os, original_name)(*args, **kwargs) + + return new_warn_multiproc + + +def create_execl(original_name): + + def new_execl(path, *args): + """ + os.execl(path, arg0, arg1, ...) + os.execle(path, arg0, arg1, ..., env) + os.execlp(file, arg0, arg1, ...) + os.execlpe(file, arg0, arg1, ..., env) + """ + if _get_apply_arg_patching(): + args = patch_args(args, is_exec=True) + send_process_created_message() + send_process_about_to_be_replaced() + + return getattr(os, original_name)(path, *args) + + return new_execl + + +def create_execv(original_name): + + def new_execv(path, args): + """ + os.execv(path, args) + os.execvp(file, args) + """ + if _get_apply_arg_patching(): + args = patch_args(args, is_exec=True) + send_process_created_message() + send_process_about_to_be_replaced() + + return getattr(os, original_name)(path, args) + + return new_execv + + +def create_execve(original_name): + """ + os.execve(path, args, env) + os.execvpe(file, args, env) + """ + + def new_execve(path, args, env): + if _get_apply_arg_patching(): + args = patch_args(args, is_exec=True) + send_process_created_message() + send_process_about_to_be_replaced() + + return getattr(os, original_name)(path, args, env) + + return new_execve + + +def create_spawnl(original_name): + + def new_spawnl(mode, path, *args): + """ + os.spawnl(mode, path, arg0, arg1, ...) + os.spawnlp(mode, file, arg0, arg1, ...) + """ + if _get_apply_arg_patching(): + args = patch_args(args) + send_process_created_message() + + return getattr(os, original_name)(mode, path, *args) + + return new_spawnl + + +def create_spawnv(original_name): + + def new_spawnv(mode, path, args): + """ + os.spawnv(mode, path, args) + os.spawnvp(mode, file, args) + """ + if _get_apply_arg_patching(): + args = patch_args(args) + send_process_created_message() + + return getattr(os, original_name)(mode, path, args) + + return new_spawnv + + +def create_spawnve(original_name): + """ + os.spawnve(mode, path, args, env) + os.spawnvpe(mode, file, args, env) + """ + + def new_spawnve(mode, path, args, env): + if _get_apply_arg_patching(): + args = patch_args(args) + send_process_created_message() + + return getattr(os, original_name)(mode, path, args, env) + + return new_spawnve + + +def create_posix_spawn(original_name): + """ + os.posix_spawn(executable, args, env, **kwargs) + """ + + def new_posix_spawn(executable, args, env, **kwargs): + if _get_apply_arg_patching(): + args = patch_args(args) + send_process_created_message() + + return getattr(os, original_name)(executable, args, env, **kwargs) + + return new_posix_spawn + + +def create_fork_exec(original_name): + """ + _posixsubprocess.fork_exec(args, executable_list, close_fds, ... (13 more)) + """ + + def new_fork_exec(args, *other_args): + import _posixsubprocess # @UnresolvedImport + if _get_apply_arg_patching(): + args = patch_args(args) + send_process_created_message() + + return getattr(_posixsubprocess, original_name)(args, *other_args) + + return new_fork_exec + + +def create_warn_fork_exec(original_name): + """ + _posixsubprocess.fork_exec(args, executable_list, close_fds, ... (13 more)) + """ + + def new_warn_fork_exec(*args): + try: + import _posixsubprocess + warn_multiproc() + return getattr(_posixsubprocess, original_name)(*args) + except: + pass + + return new_warn_fork_exec + + +def create_CreateProcess(original_name): + """ + CreateProcess(*args, **kwargs) + """ + + def new_CreateProcess(app_name, cmd_line, *args): + try: + import _subprocess + except ImportError: + import _winapi as _subprocess + + if _get_apply_arg_patching(): + cmd_line = patch_arg_str_win(cmd_line) + send_process_created_message() + + return getattr(_subprocess, original_name)(app_name, cmd_line, *args) + + return new_CreateProcess + + +def create_CreateProcessWarnMultiproc(original_name): + """ + CreateProcess(*args, **kwargs) + """ + + def new_CreateProcess(*args): + try: + import _subprocess + except ImportError: + import _winapi as _subprocess + warn_multiproc() + return getattr(_subprocess, original_name)(*args) + + return new_CreateProcess + + +def create_fork(original_name): + + def new_fork(): + # A simple fork will result in a new python process + is_new_python_process = True + frame = sys._getframe() + + apply_arg_patch = _get_apply_arg_patching() + + is_subprocess_fork = False + while frame is not None: + if frame.f_code.co_name == '_execute_child' and 'subprocess' in frame.f_code.co_filename: + is_subprocess_fork = True + # If we're actually in subprocess.Popen creating a child, it may + # result in something which is not a Python process, (so, we + # don't want to connect with it in the forked version). + executable = frame.f_locals.get('executable') + if executable is not None: + is_new_python_process = False + if is_python(executable): + is_new_python_process = True + break + + frame = frame.f_back + frame = None # Just make sure we don't hold on to it. + + protocol = pydevd_constants.get_protocol() + + child_process = getattr(os, original_name)() # fork + if not child_process: + if is_new_python_process: + PydevdCustomization.DEFAULT_PROTOCOL = protocol + _on_forked_process(setup_tracing=apply_arg_patch and not is_subprocess_fork) + else: + set_global_debugger(None) + else: + if is_new_python_process: + send_process_created_message() + return child_process + + return new_fork + + +def send_process_created_message(): + py_db = get_global_debugger() + if py_db is not None: + py_db.send_process_created_message() + + +def send_process_about_to_be_replaced(): + py_db = get_global_debugger() + if py_db is not None: + py_db.send_process_about_to_be_replaced() + + +def patch_new_process_functions(): + # os.execl(path, arg0, arg1, ...) + # os.execle(path, arg0, arg1, ..., env) + # os.execlp(file, arg0, arg1, ...) + # os.execlpe(file, arg0, arg1, ..., env) + # os.execv(path, args) + # os.execve(path, args, env) + # os.execvp(file, args) + # os.execvpe(file, args, env) + monkey_patch_os('execl', create_execl) + monkey_patch_os('execle', create_execl) + monkey_patch_os('execlp', create_execl) + monkey_patch_os('execlpe', create_execl) + monkey_patch_os('execv', create_execv) + monkey_patch_os('execve', create_execve) + monkey_patch_os('execvp', create_execv) + monkey_patch_os('execvpe', create_execve) + + # os.spawnl(mode, path, ...) + # os.spawnle(mode, path, ..., env) + # os.spawnlp(mode, file, ...) + # os.spawnlpe(mode, file, ..., env) + # os.spawnv(mode, path, args) + # os.spawnve(mode, path, args, env) + # os.spawnvp(mode, file, args) + # os.spawnvpe(mode, file, args, env) + + monkey_patch_os('spawnl', create_spawnl) + monkey_patch_os('spawnle', create_spawnl) + monkey_patch_os('spawnlp', create_spawnl) + monkey_patch_os('spawnlpe', create_spawnl) + monkey_patch_os('spawnv', create_spawnv) + monkey_patch_os('spawnve', create_spawnve) + monkey_patch_os('spawnvp', create_spawnv) + monkey_patch_os('spawnvpe', create_spawnve) + monkey_patch_os('posix_spawn', create_posix_spawn) + + if not IS_JYTHON: + if not IS_WINDOWS: + monkey_patch_os('fork', create_fork) + try: + import _posixsubprocess + monkey_patch_module(_posixsubprocess, 'fork_exec', create_fork_exec) + except ImportError: + pass + else: + # Windows + try: + import _subprocess + except ImportError: + import _winapi as _subprocess + monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcess) + + +def patch_new_process_functions_with_warning(): + monkey_patch_os('execl', create_warn_multiproc) + monkey_patch_os('execle', create_warn_multiproc) + monkey_patch_os('execlp', create_warn_multiproc) + monkey_patch_os('execlpe', create_warn_multiproc) + monkey_patch_os('execv', create_warn_multiproc) + monkey_patch_os('execve', create_warn_multiproc) + monkey_patch_os('execvp', create_warn_multiproc) + monkey_patch_os('execvpe', create_warn_multiproc) + monkey_patch_os('spawnl', create_warn_multiproc) + monkey_patch_os('spawnle', create_warn_multiproc) + monkey_patch_os('spawnlp', create_warn_multiproc) + monkey_patch_os('spawnlpe', create_warn_multiproc) + monkey_patch_os('spawnv', create_warn_multiproc) + monkey_patch_os('spawnve', create_warn_multiproc) + monkey_patch_os('spawnvp', create_warn_multiproc) + monkey_patch_os('spawnvpe', create_warn_multiproc) + monkey_patch_os('posix_spawn', create_warn_multiproc) + + if not IS_JYTHON: + if not IS_WINDOWS: + monkey_patch_os('fork', create_warn_multiproc) + try: + import _posixsubprocess + monkey_patch_module(_posixsubprocess, 'fork_exec', create_warn_fork_exec) + except ImportError: + pass + else: + # Windows + try: + import _subprocess + except ImportError: + import _winapi as _subprocess + monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcessWarnMultiproc) + + +class _NewThreadStartupWithTrace: + + def __init__(self, original_func, args, kwargs): + self.original_func = original_func + self.args = args + self.kwargs = kwargs + + def __call__(self): + # We monkey-patch the thread creation so that this function is called in the new thread. At this point + # we notify of its creation and start tracing it. + py_db = get_global_debugger() + + thread_id = None + if py_db is not None: + # Note: if this is a thread from threading.py, we're too early in the boostrap process (because we mocked + # the start_new_thread internal machinery and thread._bootstrap has not finished), so, the code below needs + # to make sure that we use the current thread bound to the original function and not use + # threading.current_thread() unless we're sure it's a dummy thread. + t = getattr(self.original_func, '__self__', getattr(self.original_func, 'im_self', None)) + if not isinstance(t, threading.Thread): + # This is not a threading.Thread but a Dummy thread (so, get it as a dummy thread using + # currentThread). + t = threading.current_thread() + + if not getattr(t, 'is_pydev_daemon_thread', False): + thread_id = get_current_thread_id(t) + py_db.notify_thread_created(thread_id, t) + _on_set_trace_for_new_thread(py_db) + + if getattr(py_db, 'thread_analyser', None) is not None: + try: + from _pydevd_bundle.pydevd_concurrency_analyser.pydevd_concurrency_logger import log_new_thread + log_new_thread(py_db, t) + except: + sys.stderr.write("Failed to detect new thread for visualization") + try: + ret = self.original_func(*self.args, **self.kwargs) + finally: + if thread_id is not None: + if py_db is not None: + # At thread shutdown we only have pydevd-related code running (which shouldn't + # be tracked). + py_db.disable_tracing() + py_db.notify_thread_not_alive(thread_id) + + return ret + + +class _NewThreadStartupWithoutTrace: + + def __init__(self, original_func, args, kwargs): + self.original_func = original_func + self.args = args + self.kwargs = kwargs + + def __call__(self): + return self.original_func(*self.args, **self.kwargs) + + +_UseNewThreadStartup = _NewThreadStartupWithTrace + + +def _get_threading_modules_to_patch(): + threading_modules_to_patch = [] + + try: + import thread as _thread + except: + import _thread + threading_modules_to_patch.append(_thread) + threading_modules_to_patch.append(threading) + + return threading_modules_to_patch + + +threading_modules_to_patch = _get_threading_modules_to_patch() + + +def patch_thread_module(thread_module): + + if getattr(thread_module, '_original_start_new_thread', None) is None: + if thread_module is threading: + if not hasattr(thread_module, '_start_new_thread'): + return # Jython doesn't have it. + _original_start_new_thread = thread_module._original_start_new_thread = thread_module._start_new_thread + else: + _original_start_new_thread = thread_module._original_start_new_thread = thread_module.start_new_thread + else: + _original_start_new_thread = thread_module._original_start_new_thread + + class ClassWithPydevStartNewThread: + + def pydev_start_new_thread(self, function, args=(), kwargs={}): + ''' + We need to replace the original thread_module.start_new_thread with this function so that threads started + through it and not through the threading module are properly traced. + ''' + return _original_start_new_thread(_UseNewThreadStartup(function, args, kwargs), ()) + + # This is a hack for the situation where the thread_module.start_new_thread is declared inside a class, such as the one below + # class F(object): + # start_new_thread = thread_module.start_new_thread + # + # def start_it(self): + # self.start_new_thread(self.function, args, kwargs) + # So, if it's an already bound method, calling self.start_new_thread won't really receive a different 'self' -- it + # does work in the default case because in builtins self isn't passed either. + pydev_start_new_thread = ClassWithPydevStartNewThread().pydev_start_new_thread + + try: + # We need to replace the original thread_module.start_new_thread with this function so that threads started through + # it and not through the threading module are properly traced. + if thread_module is threading: + thread_module._start_new_thread = pydev_start_new_thread + else: + thread_module.start_new_thread = pydev_start_new_thread + thread_module.start_new = pydev_start_new_thread + except: + pass + + +def patch_thread_modules(): + for t in threading_modules_to_patch: + patch_thread_module(t) + + +def undo_patch_thread_modules(): + for t in threading_modules_to_patch: + try: + t.start_new_thread = t._original_start_new_thread + except: + pass + + try: + t.start_new = t._original_start_new_thread + except: + pass + + try: + t._start_new_thread = t._original_start_new_thread + except: + pass + + +def disable_trace_thread_modules(): + ''' + Can be used to temporarily stop tracing threads created with thread.start_new_thread. + ''' + global _UseNewThreadStartup + _UseNewThreadStartup = _NewThreadStartupWithoutTrace + + +def enable_trace_thread_modules(): + ''' + Can be used to start tracing threads created with thread.start_new_thread again. + ''' + global _UseNewThreadStartup + _UseNewThreadStartup = _NewThreadStartupWithTrace + + +def get_original_start_new_thread(threading_module): + try: + return threading_module._original_start_new_thread + except: + return threading_module.start_new_thread diff --git a/_pydev_bundle/pydev_monkey_qt.py b/_pydev_bundle/pydev_monkey_qt.py new file mode 100644 index 0000000..e348b84 --- /dev/null +++ b/_pydev_bundle/pydev_monkey_qt.py @@ -0,0 +1,216 @@ +from __future__ import nested_scopes + +from _pydev_bundle._pydev_saved_modules import threading +import os +from _pydev_bundle import pydev_log + + +def set_trace_in_qt(): + from _pydevd_bundle.pydevd_comm import get_global_debugger + py_db = get_global_debugger() + if py_db is not None: + threading.current_thread() # Create the dummy thread for qt. + py_db.enable_tracing() + + +_patched_qt = False + + +def patch_qt(qt_support_mode): + ''' + This method patches qt (PySide2, PySide, PyQt4, PyQt5) so that we have hooks to set the tracing for QThread. + ''' + if not qt_support_mode: + return + + if qt_support_mode is True or qt_support_mode == 'True': + # do not break backward compatibility + qt_support_mode = 'auto' + + if qt_support_mode == 'auto': + qt_support_mode = os.getenv('PYDEVD_PYQT_MODE', 'auto') + + # Avoid patching more than once + global _patched_qt + if _patched_qt: + return + + pydev_log.debug('Qt support mode: %s', qt_support_mode) + + _patched_qt = True + + if qt_support_mode == 'auto': + + patch_qt_on_import = None + try: + import PySide2 # @UnresolvedImport @UnusedImport + qt_support_mode = 'pyside2' + except: + try: + import Pyside # @UnresolvedImport @UnusedImport + qt_support_mode = 'pyside' + except: + try: + import PyQt5 # @UnresolvedImport @UnusedImport + qt_support_mode = 'pyqt5' + except: + try: + import PyQt4 # @UnresolvedImport @UnusedImport + qt_support_mode = 'pyqt4' + except: + return + + if qt_support_mode == 'pyside2': + try: + import PySide2.QtCore # @UnresolvedImport + _internal_patch_qt(PySide2.QtCore, qt_support_mode) + except: + return + + elif qt_support_mode == 'pyside': + try: + import PySide.QtCore # @UnresolvedImport + _internal_patch_qt(PySide.QtCore, qt_support_mode) + except: + return + + elif qt_support_mode == 'pyqt5': + try: + import PyQt5.QtCore # @UnresolvedImport + _internal_patch_qt(PyQt5.QtCore) + except: + return + + elif qt_support_mode == 'pyqt4': + # Ok, we have an issue here: + # PyDev-452: Selecting PyQT API version using sip.setapi fails in debug mode + # http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html + # Mostly, if the user uses a different API version (i.e.: v2 instead of v1), + # that has to be done before importing PyQt4 modules (PySide/PyQt5 don't have this issue + # as they only implements v2). + patch_qt_on_import = 'PyQt4' + + def get_qt_core_module(): + import PyQt4.QtCore # @UnresolvedImport + return PyQt4.QtCore + + _patch_import_to_patch_pyqt_on_import(patch_qt_on_import, get_qt_core_module) + + else: + raise ValueError('Unexpected qt support mode: %s' % (qt_support_mode,)) + + +def _patch_import_to_patch_pyqt_on_import(patch_qt_on_import, get_qt_core_module): + # I don't like this approach very much as we have to patch __import__, but I like even less + # asking the user to configure something in the client side... + # So, our approach is to patch PyQt4 right before the user tries to import it (at which + # point he should've set the sip api version properly already anyways). + + pydev_log.debug('Setting up Qt post-import monkeypatch.') + + dotted = patch_qt_on_import + '.' + original_import = __import__ + + from _pydev_bundle._pydev_sys_patch import patch_sys_module, patch_reload, cancel_patches_in_sys_module + + patch_sys_module() + patch_reload() + + def patched_import(name, *args, **kwargs): + if patch_qt_on_import == name or name.startswith(dotted): + builtins.__import__ = original_import + cancel_patches_in_sys_module() + _internal_patch_qt(get_qt_core_module()) # Patch it only when the user would import the qt module + return original_import(name, *args, **kwargs) + + import builtins # Py3 + + builtins.__import__ = patched_import + + +def _internal_patch_qt(QtCore, qt_support_mode='auto'): + pydev_log.debug('Patching Qt: %s', QtCore) + + _original_thread_init = QtCore.QThread.__init__ + _original_runnable_init = QtCore.QRunnable.__init__ + _original_QThread = QtCore.QThread + + class FuncWrapper: + + def __init__(self, original): + self._original = original + + def __call__(self, *args, **kwargs): + set_trace_in_qt() + return self._original(*args, **kwargs) + + class StartedSignalWrapper(QtCore.QObject): # Wrapper for the QThread.started signal + + try: + _signal = QtCore.Signal() # @UndefinedVariable + except: + _signal = QtCore.pyqtSignal() # @UndefinedVariable + + def __init__(self, thread, original_started): + QtCore.QObject.__init__(self) + self.thread = thread + self.original_started = original_started + if qt_support_mode in ('pyside', 'pyside2'): + self._signal = original_started + else: + self._signal.connect(self._on_call) + self.original_started.connect(self._signal) + + def connect(self, func, *args, **kwargs): + if qt_support_mode in ('pyside', 'pyside2'): + return self._signal.connect(FuncWrapper(func), *args, **kwargs) + else: + return self._signal.connect(func, *args, **kwargs) + + def disconnect(self, *args, **kwargs): + return self._signal.disconnect(*args, **kwargs) + + def emit(self, *args, **kwargs): + return self._signal.emit(*args, **kwargs) + + def _on_call(self, *args, **kwargs): + set_trace_in_qt() + + class ThreadWrapper(QtCore.QThread): # Wrapper for QThread + + def __init__(self, *args, **kwargs): + _original_thread_init(self, *args, **kwargs) + + # In PyQt5 the program hangs when we try to call original run method of QThread class. + # So we need to distinguish instances of QThread class and instances of QThread inheritors. + if self.__class__.run == _original_QThread.run: + self.run = self._exec_run + else: + self._original_run = self.run + self.run = self._new_run + self._original_started = self.started + self.started = StartedSignalWrapper(self, self.started) + + def _exec_run(self): + set_trace_in_qt() + self.exec_() + return None + + def _new_run(self): + set_trace_in_qt() + return self._original_run() + + class RunnableWrapper(QtCore.QRunnable): # Wrapper for QRunnable + + def __init__(self, *args, **kwargs): + _original_runnable_init(self, *args, **kwargs) + + self._original_run = self.run + self.run = self._new_run + + def _new_run(self): + set_trace_in_qt() + return self._original_run() + + QtCore.QThread = ThreadWrapper + QtCore.QRunnable = RunnableWrapper diff --git a/_pydev_bundle/pydev_override.py b/_pydev_bundle/pydev_override.py new file mode 100644 index 0000000..d7581d2 --- /dev/null +++ b/_pydev_bundle/pydev_override.py @@ -0,0 +1,35 @@ +def overrides(method): + ''' + Meant to be used as + + class B: + @overrides(A.m1) + def m1(self): + pass + ''' + def wrapper(func): + if func.__name__ != method.__name__: + msg = "Wrong @override: %r expected, but overwriting %r." + msg = msg % (func.__name__, method.__name__) + raise AssertionError(msg) + + if func.__doc__ is None: + func.__doc__ = method.__doc__ + + return func + + return wrapper + +def implements(method): + def wrapper(func): + if func.__name__ != method.__name__: + msg = "Wrong @implements: %r expected, but implementing %r." + msg = msg % (func.__name__, method.__name__) + raise AssertionError(msg) + + if func.__doc__ is None: + func.__doc__ = method.__doc__ + + return func + + return wrapper \ No newline at end of file diff --git a/_pydev_bundle/pydev_umd.py b/_pydev_bundle/pydev_umd.py new file mode 100644 index 0000000..134ce4c --- /dev/null +++ b/_pydev_bundle/pydev_umd.py @@ -0,0 +1,180 @@ +""" +The UserModuleDeleter and runfile methods are copied from +Spyder and carry their own license agreement. +http://code.google.com/p/spyderlib/source/browse/spyderlib/widgets/externalshell/sitecustomize.py + +Spyder License Agreement (MIT License) +-------------------------------------- + +Copyright (c) 2009-2012 Pierre Raybaut + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +""" + +import sys +import os +from _pydev_bundle._pydev_execfile import execfile + + +# The following classes and functions are mainly intended to be used from +# an interactive Python session +class UserModuleDeleter: + """ + User Module Deleter (UMD) aims at deleting user modules + to force Python to deeply reload them during import + + pathlist [list]: ignore list in terms of module path + namelist [list]: ignore list in terms of module name + """ + + def __init__(self, namelist=None, pathlist=None): + if namelist is None: + namelist = [] + self.namelist = namelist + if pathlist is None: + pathlist = [] + self.pathlist = pathlist + try: + # ignore all files in org.python.pydev/pysrc + import pydev_pysrc, inspect + self.pathlist.append(os.path.dirname(pydev_pysrc.__file__)) + except: + pass + self.previous_modules = list(sys.modules.keys()) + + def is_module_ignored(self, modname, modpath): + for path in [sys.prefix] + self.pathlist: + if modpath.startswith(path): + return True + else: + return set(modname.split('.')) & set(self.namelist) + + def run(self, verbose=False): + """ + Del user modules to force Python to deeply reload them + + Do not del modules which are considered as system modules, i.e. + modules installed in subdirectories of Python interpreter's binary + Do not del C modules + """ + log = [] + modules_copy = dict(sys.modules) + for modname, module in modules_copy.items(): + if modname == 'aaaaa': + print(modname, module) + print(self.previous_modules) + if modname not in self.previous_modules: + modpath = getattr(module, '__file__', None) + if modpath is None: + # *module* is a C module that is statically linked into the + # interpreter. There is no way to know its path, so we + # choose to ignore it. + continue + if not self.is_module_ignored(modname, modpath): + log.append(modname) + del sys.modules[modname] + if verbose and log: + print("\x1b[4;33m%s\x1b[24m%s\x1b[0m" % ("UMD has deleted", + ": " + ", ".join(log))) + + +__umd__ = None + +_get_globals_callback = None + + +def _set_globals_function(get_globals): + global _get_globals_callback + _get_globals_callback = get_globals + + +def _get_globals(): + """Return current Python interpreter globals namespace""" + if _get_globals_callback is not None: + return _get_globals_callback() + else: + try: + from __main__ import __dict__ as namespace + except ImportError: + try: + # The import fails on IronPython + import __main__ + namespace = __main__.__dict__ + except: + namespace + shell = namespace.get('__ipythonshell__') + if shell is not None and hasattr(shell, 'user_ns'): + # IPython 0.12+ kernel + return shell.user_ns + else: + # Python interpreter + return namespace + return namespace + + +def runfile(filename, args=None, wdir=None, namespace=None): + """ + Run filename + args: command line arguments (string) + wdir: working directory + """ + try: + if hasattr(filename, 'decode'): + filename = filename.decode('utf-8') + except (UnicodeError, TypeError): + pass + global __umd__ + if os.environ.get("PYDEV_UMD_ENABLED", "").lower() == "true": + if __umd__ is None: + namelist = os.environ.get("PYDEV_UMD_NAMELIST", None) + if namelist is not None: + namelist = namelist.split(',') + __umd__ = UserModuleDeleter(namelist=namelist) + else: + verbose = os.environ.get("PYDEV_UMD_VERBOSE", "").lower() == "true" + __umd__.run(verbose=verbose) + if args is not None and not isinstance(args, (bytes, str)): + raise TypeError("expected a character buffer object") + if namespace is None: + namespace = _get_globals() + if '__file__' in namespace: + old_file = namespace['__file__'] + else: + old_file = None + namespace['__file__'] = filename + sys.argv = [filename] + if args is not None: + for arg in args.split(): + sys.argv.append(arg) + if wdir is not None: + try: + if hasattr(wdir, 'decode'): + wdir = wdir.decode('utf-8') + except (UnicodeError, TypeError): + pass + os.chdir(wdir) + execfile(filename, namespace) + sys.argv = [''] + if old_file is None: + del namespace['__file__'] + else: + namespace['__file__'] = old_file diff --git a/_pydev_bundle/pydev_versioncheck.py b/_pydev_bundle/pydev_versioncheck.py new file mode 100644 index 0000000..70bf765 --- /dev/null +++ b/_pydev_bundle/pydev_versioncheck.py @@ -0,0 +1,16 @@ +import sys + +def versionok_for_gui(): + ''' Return True if running Python is suitable for GUI Event Integration and deeper IPython integration ''' + # We require Python 2.6+ ... + if sys.hexversion < 0x02060000: + return False + # Or Python 3.2+ + if sys.hexversion >= 0x03000000 and sys.hexversion < 0x03020000: + return False + # Not supported under Jython nor IronPython + if sys.platform.startswith("java") or sys.platform.startswith('cli'): + return False + + return True + diff --git a/_pydev_runfiles/__init__.py b/_pydev_runfiles/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/_pydev_runfiles/pydev_runfiles.py b/_pydev_runfiles/pydev_runfiles.py new file mode 100644 index 0000000..9c199e1 --- /dev/null +++ b/_pydev_runfiles/pydev_runfiles.py @@ -0,0 +1,857 @@ +from __future__ import nested_scopes + +import fnmatch +import os.path +from _pydev_runfiles.pydev_runfiles_coverage import start_coverage_support +from _pydevd_bundle.pydevd_constants import * # @UnusedWildImport +import re +import time + + +#======================================================================================================================= +# Configuration +#======================================================================================================================= +class Configuration: + + def __init__( + self, + files_or_dirs='', + verbosity=2, + include_tests=None, + tests=None, + port=None, + files_to_tests=None, + jobs=1, + split_jobs='tests', + coverage_output_dir=None, + coverage_include=None, + coverage_output_file=None, + exclude_files=None, + exclude_tests=None, + include_files=None, + django=False, + ): + self.files_or_dirs = files_or_dirs + self.verbosity = verbosity + self.include_tests = include_tests + self.tests = tests + self.port = port + self.files_to_tests = files_to_tests + self.jobs = jobs + self.split_jobs = split_jobs + self.django = django + + if include_tests: + assert isinstance(include_tests, (list, tuple)) + + if exclude_files: + assert isinstance(exclude_files, (list, tuple)) + + if exclude_tests: + assert isinstance(exclude_tests, (list, tuple)) + + self.exclude_files = exclude_files + self.include_files = include_files + self.exclude_tests = exclude_tests + + self.coverage_output_dir = coverage_output_dir + self.coverage_include = coverage_include + self.coverage_output_file = coverage_output_file + + def __str__(self): + return '''Configuration + - files_or_dirs: %s + - verbosity: %s + - tests: %s + - port: %s + - files_to_tests: %s + - jobs: %s + - split_jobs: %s + + - include_files: %s + - include_tests: %s + + - exclude_files: %s + - exclude_tests: %s + + - coverage_output_dir: %s + - coverage_include_dir: %s + - coverage_output_file: %s + + - django: %s +''' % ( + self.files_or_dirs, + self.verbosity, + self.tests, + self.port, + self.files_to_tests, + self.jobs, + self.split_jobs, + + self.include_files, + self.include_tests, + + self.exclude_files, + self.exclude_tests, + + self.coverage_output_dir, + self.coverage_include, + self.coverage_output_file, + + self.django, + ) + + +#======================================================================================================================= +# parse_cmdline +#======================================================================================================================= +def parse_cmdline(argv=None): + """ + Parses command line and returns test directories, verbosity, test filter and test suites + + usage: + runfiles.py -v|--verbosity -t|--tests dirs|files + + Multiprocessing options: + jobs=number (with the number of jobs to be used to run the tests) + split_jobs='module'|'tests' + if == module, a given job will always receive all the tests from a module + if == tests, the tests will be split independently of their originating module (default) + + --exclude_files = comma-separated list of patterns with files to exclude (fnmatch style) + --include_files = comma-separated list of patterns with files to include (fnmatch style) + --exclude_tests = comma-separated list of patterns with test names to exclude (fnmatch style) + + Note: if --tests is given, --exclude_files, --include_files and --exclude_tests are ignored! + """ + if argv is None: + argv = sys.argv + + verbosity = 2 + include_tests = None + tests = None + port = None + jobs = 1 + split_jobs = 'tests' + files_to_tests = {} + coverage_output_dir = None + coverage_include = None + exclude_files = None + exclude_tests = None + include_files = None + django = False + + from _pydev_bundle._pydev_getopt import gnu_getopt + optlist, dirs = gnu_getopt( + argv[1:], "", + [ + "verbosity=", + "tests=", + + "port=", + "config_file=", + + "jobs=", + "split_jobs=", + + "include_tests=", + "include_files=", + + "exclude_files=", + "exclude_tests=", + + "coverage_output_dir=", + "coverage_include=", + + "django=" + ] + ) + + for opt, value in optlist: + if opt in ("-v", "--verbosity"): + verbosity = value + + elif opt in ("-p", "--port"): + port = int(value) + + elif opt in ("-j", "--jobs"): + jobs = int(value) + + elif opt in ("-s", "--split_jobs"): + split_jobs = value + if split_jobs not in ('module', 'tests'): + raise AssertionError('Expected split to be either "module" or "tests". Was :%s' % (split_jobs,)) + + elif opt in ("-d", "--coverage_output_dir",): + coverage_output_dir = value.strip() + + elif opt in ("-i", "--coverage_include",): + coverage_include = value.strip() + + elif opt in ("-I", "--include_tests"): + include_tests = value.split(',') + + elif opt in ("-E", "--exclude_files"): + exclude_files = value.split(',') + + elif opt in ("-F", "--include_files"): + include_files = value.split(',') + + elif opt in ("-e", "--exclude_tests"): + exclude_tests = value.split(',') + + elif opt in ("-t", "--tests"): + tests = value.split(',') + + elif opt in ("--django",): + django = value.strip() in ['true', 'True', '1'] + + elif opt in ("-c", "--config_file"): + config_file = value.strip() + if os.path.exists(config_file): + f = open(config_file, 'r') + try: + config_file_contents = f.read() + finally: + f.close() + + if config_file_contents: + config_file_contents = config_file_contents.strip() + + if config_file_contents: + for line in config_file_contents.splitlines(): + file_and_test = line.split('|') + if len(file_and_test) == 2: + file, test = file_and_test + if file in files_to_tests: + files_to_tests[file].append(test) + else: + files_to_tests[file] = [test] + + else: + sys.stderr.write('Could not find config file: %s\n' % (config_file,)) + + if type([]) != type(dirs): + dirs = [dirs] + + ret_dirs = [] + for d in dirs: + if '|' in d: + # paths may come from the ide separated by | + ret_dirs.extend(d.split('|')) + else: + ret_dirs.append(d) + + verbosity = int(verbosity) + + if tests: + if verbosity > 4: + sys.stdout.write('--tests provided. Ignoring --exclude_files, --exclude_tests and --include_files\n') + exclude_files = exclude_tests = include_files = None + + config = Configuration( + ret_dirs, + verbosity, + include_tests, + tests, + port, + files_to_tests, + jobs, + split_jobs, + coverage_output_dir, + coverage_include, + exclude_files=exclude_files, + exclude_tests=exclude_tests, + include_files=include_files, + django=django, + ) + + if verbosity > 5: + sys.stdout.write(str(config) + '\n') + return config + + +#======================================================================================================================= +# PydevTestRunner +#======================================================================================================================= +class PydevTestRunner(object): + """ finds and runs a file or directory of files as a unit test """ + + __py_extensions = ["*.py", "*.pyw"] + __exclude_files = ["__init__.*"] + + # Just to check that only this attributes will be written to this file + __slots__ = [ + 'verbosity', # Always used + + 'files_to_tests', # If this one is given, the ones below are not used + + 'files_or_dirs', # Files or directories received in the command line + 'include_tests', # The filter used to collect the tests + 'tests', # Strings with the tests to be run + + 'jobs', # Integer with the number of jobs that should be used to run the test cases + 'split_jobs', # String with 'tests' or 'module' (how should the jobs be split) + + 'configuration', + 'coverage', + ] + + def __init__(self, configuration): + self.verbosity = configuration.verbosity + + self.jobs = configuration.jobs + self.split_jobs = configuration.split_jobs + + files_to_tests = configuration.files_to_tests + if files_to_tests: + self.files_to_tests = files_to_tests + self.files_or_dirs = list(files_to_tests.keys()) + self.tests = None + else: + self.files_to_tests = {} + self.files_or_dirs = configuration.files_or_dirs + self.tests = configuration.tests + + self.configuration = configuration + self.__adjust_path() + + def __adjust_path(self): + """ add the current file or directory to the python path """ + path_to_append = None + for n in range(len(self.files_or_dirs)): + dir_name = self.__unixify(self.files_or_dirs[n]) + if os.path.isdir(dir_name): + if not dir_name.endswith("/"): + self.files_or_dirs[n] = dir_name + "/" + path_to_append = os.path.normpath(dir_name) + elif os.path.isfile(dir_name): + path_to_append = os.path.dirname(dir_name) + else: + if not os.path.exists(dir_name): + block_line = '*' * 120 + sys.stderr.write('\n%s\n* PyDev test runner error: %s does not exist.\n%s\n' % (block_line, dir_name, block_line)) + return + msg = ("unknown type. \n%s\nshould be file or a directory.\n" % (dir_name)) + raise RuntimeError(msg) + if path_to_append is not None: + # Add it as the last one (so, first things are resolved against the default dirs and + # if none resolves, then we try a relative import). + sys.path.append(path_to_append) + + def __is_valid_py_file(self, fname): + """ tests that a particular file contains the proper file extension + and is not in the list of files to exclude """ + is_valid_fname = 0 + for invalid_fname in self.__class__.__exclude_files: + is_valid_fname += int(not fnmatch.fnmatch(fname, invalid_fname)) + if_valid_ext = 0 + for ext in self.__class__.__py_extensions: + if_valid_ext += int(fnmatch.fnmatch(fname, ext)) + return is_valid_fname > 0 and if_valid_ext > 0 + + def __unixify(self, s): + """ stupid windows. converts the backslash to forwardslash for consistency """ + return os.path.normpath(s).replace(os.sep, "/") + + def __importify(self, s, dir=False): + """ turns directory separators into dots and removes the ".py*" extension + so the string can be used as import statement """ + if not dir: + dirname, fname = os.path.split(s) + + if fname.count('.') > 1: + # if there's a file named xxx.xx.py, it is not a valid module, so, let's not load it... + return + + imp_stmt_pieces = [dirname.replace("\\", "/").replace("/", "."), os.path.splitext(fname)[0]] + + if len(imp_stmt_pieces[0]) == 0: + imp_stmt_pieces = imp_stmt_pieces[1:] + + return ".".join(imp_stmt_pieces) + + else: # handle dir + return s.replace("\\", "/").replace("/", ".") + + def __add_files(self, pyfiles, root, files): + """ if files match, appends them to pyfiles. used by os.path.walk fcn """ + for fname in files: + if self.__is_valid_py_file(fname): + name_without_base_dir = self.__unixify(os.path.join(root, fname)) + pyfiles.append(name_without_base_dir) + + def find_import_files(self): + """ return a list of files to import """ + if self.files_to_tests: + pyfiles = self.files_to_tests.keys() + else: + pyfiles = [] + + for base_dir in self.files_or_dirs: + if os.path.isdir(base_dir): + for root, dirs, files in os.walk(base_dir): + # Note: handling directories that should be excluded from the search because + # they don't have __init__.py + exclude = {} + for d in dirs: + for init in ['__init__.py', '__init__.pyo', '__init__.pyc', '__init__.pyw', '__init__$py.class']: + if os.path.exists(os.path.join(root, d, init).replace('\\', '/')): + break + else: + exclude[d] = 1 + + if exclude: + new = [] + for d in dirs: + if d not in exclude: + new.append(d) + + dirs[:] = new + + self.__add_files(pyfiles, root, files) + + elif os.path.isfile(base_dir): + pyfiles.append(base_dir) + + if self.configuration.exclude_files or self.configuration.include_files: + ret = [] + for f in pyfiles: + add = True + basename = os.path.basename(f) + if self.configuration.include_files: + add = False + + for pat in self.configuration.include_files: + if fnmatch.fnmatchcase(basename, pat): + add = True + break + + if not add: + if self.verbosity > 3: + sys.stdout.write('Skipped file: %s (did not match any include_files pattern: %s)\n' % (f, self.configuration.include_files)) + + elif self.configuration.exclude_files: + for pat in self.configuration.exclude_files: + if fnmatch.fnmatchcase(basename, pat): + if self.verbosity > 3: + sys.stdout.write('Skipped file: %s (matched exclude_files pattern: %s)\n' % (f, pat)) + + elif self.verbosity > 2: + sys.stdout.write('Skipped file: %s\n' % (f,)) + + add = False + break + + if add: + if self.verbosity > 3: + sys.stdout.write('Adding file: %s for test discovery.\n' % (f,)) + ret.append(f) + + pyfiles = ret + + return pyfiles + + def __get_module_from_str(self, modname, print_exception, pyfile): + """ Import the module in the given import path. + * Returns the "final" module, so importing "coilib40.subject.visu" + returns the "visu" module, not the "coilib40" as returned by __import__ """ + try: + mod = __import__(modname) + for part in modname.split('.')[1:]: + mod = getattr(mod, part) + return mod + except: + if print_exception: + from _pydev_runfiles import pydev_runfiles_xml_rpc + from _pydevd_bundle import pydevd_io + buf_err = pydevd_io.start_redirect(keep_original_redirection=True, std='stderr') + buf_out = pydevd_io.start_redirect(keep_original_redirection=True, std='stdout') + try: + import traceback;traceback.print_exc() + sys.stderr.write('ERROR: Module: %s could not be imported (file: %s).\n' % (modname, pyfile)) + finally: + pydevd_io.end_redirect('stderr') + pydevd_io.end_redirect('stdout') + + pydev_runfiles_xml_rpc.notifyTest( + 'error', buf_out.getvalue(), buf_err.getvalue(), pyfile, modname, 0) + + return None + + def remove_duplicates_keeping_order(self, seq): + seen = set() + seen_add = seen.add + return [x for x in seq if not (x in seen or seen_add(x))] + + def find_modules_from_files(self, pyfiles): + """ returns a list of modules given a list of files """ + # let's make sure that the paths we want are in the pythonpath... + imports = [(s, self.__importify(s)) for s in pyfiles] + + sys_path = [os.path.normpath(path) for path in sys.path] + sys_path = self.remove_duplicates_keeping_order(sys_path) + + system_paths = [] + for s in sys_path: + system_paths.append(self.__importify(s, True)) + + ret = [] + for pyfile, imp in imports: + if imp is None: + continue # can happen if a file is not a valid module + choices = [] + for s in system_paths: + if imp.startswith(s): + add = imp[len(s) + 1:] + if add: + choices.append(add) + # sys.stdout.write(' ' + add + ' ') + + if not choices: + sys.stdout.write('PYTHONPATH not found for file: %s\n' % imp) + else: + for i, import_str in enumerate(choices): + print_exception = i == len(choices) - 1 + mod = self.__get_module_from_str(import_str, print_exception, pyfile) + if mod is not None: + ret.append((pyfile, mod, import_str)) + break + + return ret + + #=================================================================================================================== + # GetTestCaseNames + #=================================================================================================================== + class GetTestCaseNames: + """Yes, we need a class for that (cannot use outer context on jython 2.1)""" + + def __init__(self, accepted_classes, accepted_methods): + self.accepted_classes = accepted_classes + self.accepted_methods = accepted_methods + + def __call__(self, testCaseClass): + """Return a sorted sequence of method names found within testCaseClass""" + testFnNames = [] + className = testCaseClass.__name__ + + if className in self.accepted_classes: + for attrname in dir(testCaseClass): + # If a class is chosen, we select all the 'test' methods' + if attrname.startswith('test') and hasattr(getattr(testCaseClass, attrname), '__call__'): + testFnNames.append(attrname) + + else: + for attrname in dir(testCaseClass): + # If we have the class+method name, we must do a full check and have an exact match. + if className + '.' + attrname in self.accepted_methods: + if hasattr(getattr(testCaseClass, attrname), '__call__'): + testFnNames.append(attrname) + + # sorted() is not available in jython 2.1 + testFnNames.sort() + return testFnNames + + def _decorate_test_suite(self, suite, pyfile, module_name): + import unittest + if isinstance(suite, unittest.TestSuite): + add = False + suite.__pydev_pyfile__ = pyfile + suite.__pydev_module_name__ = module_name + + for t in suite._tests: + t.__pydev_pyfile__ = pyfile + t.__pydev_module_name__ = module_name + if self._decorate_test_suite(t, pyfile, module_name): + add = True + + return add + + elif isinstance(suite, unittest.TestCase): + return True + + else: + return False + + def find_tests_from_modules(self, file_and_modules_and_module_name): + """ returns the unittests given a list of modules """ + # Use our own suite! + from _pydev_runfiles import pydev_runfiles_unittest + import unittest + unittest.TestLoader.suiteClass = pydev_runfiles_unittest.PydevTestSuite + loader = unittest.TestLoader() + + ret = [] + if self.files_to_tests: + for pyfile, m, module_name in file_and_modules_and_module_name: + accepted_classes = {} + accepted_methods = {} + tests = self.files_to_tests[pyfile] + for t in tests: + accepted_methods[t] = t + + loader.getTestCaseNames = self.GetTestCaseNames(accepted_classes, accepted_methods) + + suite = loader.loadTestsFromModule(m) + if self._decorate_test_suite(suite, pyfile, module_name): + ret.append(suite) + return ret + + if self.tests: + accepted_classes = {} + accepted_methods = {} + + for t in self.tests: + splitted = t.split('.') + if len(splitted) == 1: + accepted_classes[t] = t + + elif len(splitted) == 2: + accepted_methods[t] = t + + loader.getTestCaseNames = self.GetTestCaseNames(accepted_classes, accepted_methods) + + for pyfile, m, module_name in file_and_modules_and_module_name: + suite = loader.loadTestsFromModule(m) + if self._decorate_test_suite(suite, pyfile, module_name): + ret.append(suite) + + return ret + + def filter_tests(self, test_objs, internal_call=False): + """ based on a filter name, only return those tests that have + the test case names that match """ + import unittest + if not internal_call: + if not self.configuration.include_tests and not self.tests and not self.configuration.exclude_tests: + # No need to filter if we have nothing to filter! + return test_objs + + if self.verbosity > 1: + if self.configuration.include_tests: + sys.stdout.write('Tests to include: %s\n' % (self.configuration.include_tests,)) + + if self.tests: + sys.stdout.write('Tests to run: %s\n' % (self.tests,)) + + if self.configuration.exclude_tests: + sys.stdout.write('Tests to exclude: %s\n' % (self.configuration.exclude_tests,)) + + test_suite = [] + for test_obj in test_objs: + + if isinstance(test_obj, unittest.TestSuite): + # Note: keep the suites as they are and just 'fix' the tests (so, don't use the iter_tests). + if test_obj._tests: + test_obj._tests = self.filter_tests(test_obj._tests, True) + if test_obj._tests: # Only add the suite if we still have tests there. + test_suite.append(test_obj) + + elif isinstance(test_obj, unittest.TestCase): + try: + testMethodName = test_obj._TestCase__testMethodName + except AttributeError: + # changed in python 2.5 + testMethodName = test_obj._testMethodName + + add = True + if self.configuration.exclude_tests: + for pat in self.configuration.exclude_tests: + if fnmatch.fnmatchcase(testMethodName, pat): + if self.verbosity > 3: + sys.stdout.write('Skipped test: %s (matched exclude_tests pattern: %s)\n' % (testMethodName, pat)) + + elif self.verbosity > 2: + sys.stdout.write('Skipped test: %s\n' % (testMethodName,)) + + add = False + break + + if add: + if self.__match_tests(self.tests, test_obj, testMethodName): + include = True + if self.configuration.include_tests: + include = False + for pat in self.configuration.include_tests: + if fnmatch.fnmatchcase(testMethodName, pat): + include = True + break + if include: + test_suite.append(test_obj) + else: + if self.verbosity > 3: + sys.stdout.write('Skipped test: %s (did not match any include_tests pattern %s)\n' % ( + testMethodName, self.configuration.include_tests,)) + return test_suite + + def iter_tests(self, test_objs): + # Note: not using yield because of Jython 2.1. + import unittest + tests = [] + for test_obj in test_objs: + if isinstance(test_obj, unittest.TestSuite): + tests.extend(self.iter_tests(test_obj._tests)) + + elif isinstance(test_obj, unittest.TestCase): + tests.append(test_obj) + return tests + + def list_test_names(self, test_objs): + names = [] + for tc in self.iter_tests(test_objs): + try: + testMethodName = tc._TestCase__testMethodName + except AttributeError: + # changed in python 2.5 + testMethodName = tc._testMethodName + names.append(testMethodName) + return names + + def __match_tests(self, tests, test_case, test_method_name): + if not tests: + return 1 + + for t in tests: + class_and_method = t.split('.') + if len(class_and_method) == 1: + # only class name + if class_and_method[0] == test_case.__class__.__name__: + return 1 + + elif len(class_and_method) == 2: + if class_and_method[0] == test_case.__class__.__name__ and class_and_method[1] == test_method_name: + return 1 + + return 0 + + def __match(self, filter_list, name): + """ returns whether a test name matches the test filter """ + if filter_list is None: + return 1 + for f in filter_list: + if re.match(f, name): + return 1 + return 0 + + def run_tests(self, handle_coverage=True): + """ runs all tests """ + sys.stdout.write("Finding files... ") + files = self.find_import_files() + if self.verbosity > 3: + sys.stdout.write('%s ... done.\n' % (self.files_or_dirs)) + else: + sys.stdout.write('done.\n') + sys.stdout.write("Importing test modules ... ") + + if handle_coverage: + coverage_files, coverage = start_coverage_support(self.configuration) + + file_and_modules_and_module_name = self.find_modules_from_files(files) + sys.stdout.write("done.\n") + + all_tests = self.find_tests_from_modules(file_and_modules_and_module_name) + all_tests = self.filter_tests(all_tests) + + from _pydev_runfiles import pydev_runfiles_unittest + test_suite = pydev_runfiles_unittest.PydevTestSuite(all_tests) + from _pydev_runfiles import pydev_runfiles_xml_rpc + pydev_runfiles_xml_rpc.notifyTestsCollected(test_suite.countTestCases()) + + start_time = time.time() + + def run_tests(): + executed_in_parallel = False + if self.jobs > 1: + from _pydev_runfiles import pydev_runfiles_parallel + + # What may happen is that the number of jobs needed is lower than the number of jobs requested + # (e.g.: 2 jobs were requested for running 1 test) -- in which case execute_tests_in_parallel will + # return False and won't run any tests. + executed_in_parallel = pydev_runfiles_parallel.execute_tests_in_parallel( + all_tests, self.jobs, self.split_jobs, self.verbosity, coverage_files, self.configuration.coverage_include) + + if not executed_in_parallel: + # If in coverage, we don't need to pass anything here (coverage is already enabled for this execution). + runner = pydev_runfiles_unittest.PydevTextTestRunner(stream=sys.stdout, descriptions=1, verbosity=self.verbosity) + sys.stdout.write('\n') + runner.run(test_suite) + + if self.configuration.django: + get_django_test_suite_runner()(run_tests).run_tests([]) + else: + run_tests() + + if handle_coverage: + coverage.stop() + coverage.save() + + total_time = 'Finished in: %.2f secs.' % (time.time() - start_time,) + pydev_runfiles_xml_rpc.notifyTestRunFinished(total_time) + + +DJANGO_TEST_SUITE_RUNNER = None + + +def get_django_test_suite_runner(): + global DJANGO_TEST_SUITE_RUNNER + if DJANGO_TEST_SUITE_RUNNER: + return DJANGO_TEST_SUITE_RUNNER + try: + # django >= 1.8 + import django + from django.test.runner import DiscoverRunner + + class MyDjangoTestSuiteRunner(DiscoverRunner): + + def __init__(self, on_run_suite): + django.setup() + DiscoverRunner.__init__(self) + self.on_run_suite = on_run_suite + + def build_suite(self, *args, **kwargs): + pass + + def suite_result(self, *args, **kwargs): + pass + + def run_suite(self, *args, **kwargs): + self.on_run_suite() + + except: + # django < 1.8 + try: + from django.test.simple import DjangoTestSuiteRunner + except: + + class DjangoTestSuiteRunner: + + def __init__(self): + pass + + def run_tests(self, *args, **kwargs): + raise AssertionError("Unable to run suite with django.test.runner.DiscoverRunner nor django.test.simple.DjangoTestSuiteRunner because it couldn't be imported.") + + class MyDjangoTestSuiteRunner(DjangoTestSuiteRunner): + + def __init__(self, on_run_suite): + DjangoTestSuiteRunner.__init__(self) + self.on_run_suite = on_run_suite + + def build_suite(self, *args, **kwargs): + pass + + def suite_result(self, *args, **kwargs): + pass + + def run_suite(self, *args, **kwargs): + self.on_run_suite() + + DJANGO_TEST_SUITE_RUNNER = MyDjangoTestSuiteRunner + return DJANGO_TEST_SUITE_RUNNER + + +#======================================================================================================================= +# main +#======================================================================================================================= +def main(configuration): + PydevTestRunner(configuration).run_tests() diff --git a/_pydev_runfiles/pydev_runfiles_coverage.py b/_pydev_runfiles/pydev_runfiles_coverage.py new file mode 100644 index 0000000..a835925 --- /dev/null +++ b/_pydev_runfiles/pydev_runfiles_coverage.py @@ -0,0 +1,76 @@ +import os.path +import sys +from _pydevd_bundle.pydevd_constants import Null + + +#======================================================================================================================= +# get_coverage_files +#======================================================================================================================= +def get_coverage_files(coverage_output_dir, number_of_files): + base_dir = coverage_output_dir + ret = [] + i = 0 + while len(ret) < number_of_files: + while True: + f = os.path.join(base_dir, '.coverage.%s' % i) + i += 1 + if not os.path.exists(f): + ret.append(f) + break #Break only inner for. + return ret + + +#======================================================================================================================= +# start_coverage_support +#======================================================================================================================= +def start_coverage_support(configuration): + return start_coverage_support_from_params( + configuration.coverage_output_dir, + configuration.coverage_output_file, + configuration.jobs, + configuration.coverage_include, + ) + + +#======================================================================================================================= +# start_coverage_support_from_params +#======================================================================================================================= +def start_coverage_support_from_params(coverage_output_dir, coverage_output_file, jobs, coverage_include): + coverage_files = [] + coverage_instance = Null() + if coverage_output_dir or coverage_output_file: + try: + import coverage #@UnresolvedImport + except: + sys.stderr.write('Error: coverage module could not be imported\n') + sys.stderr.write('Please make sure that the coverage module (http://nedbatchelder.com/code/coverage/)\n') + sys.stderr.write('is properly installed in your interpreter: %s\n' % (sys.executable,)) + + import traceback;traceback.print_exc() + else: + if coverage_output_dir: + if not os.path.exists(coverage_output_dir): + sys.stderr.write('Error: directory for coverage output (%s) does not exist.\n' % (coverage_output_dir,)) + + elif not os.path.isdir(coverage_output_dir): + sys.stderr.write('Error: expected (%s) to be a directory.\n' % (coverage_output_dir,)) + + else: + n = jobs + if n <= 0: + n += 1 + n += 1 #Add 1 more for the current process (which will do the initial import). + coverage_files = get_coverage_files(coverage_output_dir, n) + os.environ['COVERAGE_FILE'] = coverage_files.pop(0) + + coverage_instance = coverage.coverage(source=[coverage_include]) + coverage_instance.start() + + elif coverage_output_file: + #Client of parallel run. + os.environ['COVERAGE_FILE'] = coverage_output_file + coverage_instance = coverage.coverage(source=[coverage_include]) + coverage_instance.start() + + return coverage_files, coverage_instance + diff --git a/_pydev_runfiles/pydev_runfiles_nose.py b/_pydev_runfiles/pydev_runfiles_nose.py new file mode 100644 index 0000000..20ea5b2 --- /dev/null +++ b/_pydev_runfiles/pydev_runfiles_nose.py @@ -0,0 +1,207 @@ +from nose.plugins.multiprocess import MultiProcessTestRunner # @UnresolvedImport +from nose.plugins.base import Plugin # @UnresolvedImport +import sys +from _pydev_runfiles import pydev_runfiles_xml_rpc +import time +from _pydev_runfiles.pydev_runfiles_coverage import start_coverage_support +from contextlib import contextmanager +from io import StringIO +import traceback + + +#======================================================================================================================= +# PydevPlugin +#======================================================================================================================= +class PydevPlugin(Plugin): + + def __init__(self, configuration): + self.configuration = configuration + Plugin.__init__(self) + + def begin(self): + # Called before any test is run (it's always called, with multiprocess or not) + self.start_time = time.time() + self.coverage_files, self.coverage = start_coverage_support(self.configuration) + + def finalize(self, result): + # Called after all tests are run (it's always called, with multiprocess or not) + self.coverage.stop() + self.coverage.save() + + pydev_runfiles_xml_rpc.notifyTestRunFinished('Finished in: %.2f secs.' % (time.time() - self.start_time,)) + + #=================================================================================================================== + # Methods below are not called with multiprocess (so, we monkey-patch MultiProcessTestRunner.consolidate + # so that they're called, but unfortunately we loose some info -- i.e.: the time for each test in this + # process). + #=================================================================================================================== + + class Sentinel(object): + pass + + @contextmanager + def _without_user_address(self, test): + # #PyDev-1095: Conflict between address in test and test.address() in PydevPlugin().report_cond() + user_test_instance = test.test + user_address = self.Sentinel + user_class_address = self.Sentinel + try: + if 'address' in user_test_instance.__dict__: + user_address = user_test_instance.__dict__.pop('address') + except: + # Just ignore anything here. + pass + try: + user_class_address = user_test_instance.__class__.address + del user_test_instance.__class__.address + except: + # Just ignore anything here. + pass + + try: + yield + finally: + if user_address is not self.Sentinel: + user_test_instance.__dict__['address'] = user_address + + if user_class_address is not self.Sentinel: + user_test_instance.__class__.address = user_class_address + + def _get_test_address(self, test): + try: + if hasattr(test, 'address'): + with self._without_user_address(test): + address = test.address() + + # test.address() is something as: + # ('D:\\workspaces\\temp\\test_workspace\\pytesting1\\src\\mod1\\hello.py', 'mod1.hello', 'TestCase.testMet1') + # + # and we must pass: location, test + # E.g.: ['D:\\src\\mod1\\hello.py', 'TestCase.testMet1'] + address = address[0], address[2] + else: + # multiprocess + try: + address = test[0], test[1] + except TypeError: + # It may be an error at setup, in which case it's not really a test, but a Context object. + f = test.context.__file__ + if f.endswith('.pyc'): + f = f[:-1] + elif f.endswith('$py.class'): + f = f[:-len('$py.class')] + '.py' + address = f, '?' + except: + sys.stderr.write("PyDev: Internal pydev error getting test address. Please report at the pydev bug tracker\n") + traceback.print_exc() + sys.stderr.write("\n\n\n") + address = '?', '?' + return address + + def report_cond(self, cond, test, captured_output, error=''): + ''' + @param cond: fail, error, ok + ''' + + address = self._get_test_address(test) + + error_contents = self.get_io_from_error(error) + try: + time_str = '%.2f' % (time.time() - test._pydev_start_time) + except: + time_str = '?' + + pydev_runfiles_xml_rpc.notifyTest(cond, captured_output, error_contents, address[0], address[1], time_str) + + def startTest(self, test): + test._pydev_start_time = time.time() + file, test = self._get_test_address(test) + pydev_runfiles_xml_rpc.notifyStartTest(file, test) + + def get_io_from_error(self, err): + if type(err) == type(()): + if len(err) != 3: + if len(err) == 2: + return err[1] # multiprocess + s = StringIO() + etype, value, tb = err + if isinstance(value, str): + return value + traceback.print_exception(etype, value, tb, file=s) + return s.getvalue() + return err + + def get_captured_output(self, test): + if hasattr(test, 'capturedOutput') and test.capturedOutput: + return test.capturedOutput + return '' + + def addError(self, test, err): + self.report_cond( + 'error', + test, + self.get_captured_output(test), + err, + ) + + def addFailure(self, test, err): + self.report_cond( + 'fail', + test, + self.get_captured_output(test), + err, + ) + + def addSuccess(self, test): + self.report_cond( + 'ok', + test, + self.get_captured_output(test), + '', + ) + + +PYDEV_NOSE_PLUGIN_SINGLETON = None + + +def start_pydev_nose_plugin_singleton(configuration): + global PYDEV_NOSE_PLUGIN_SINGLETON + PYDEV_NOSE_PLUGIN_SINGLETON = PydevPlugin(configuration) + return PYDEV_NOSE_PLUGIN_SINGLETON + + +original = MultiProcessTestRunner.consolidate + + +#======================================================================================================================= +# new_consolidate +#======================================================================================================================= +def new_consolidate(self, result, batch_result): + ''' + Used so that it can work with the multiprocess plugin. + Monkeypatched because nose seems a bit unsupported at this time (ideally + the plugin would have this support by default). + ''' + ret = original(self, result, batch_result) + + parent_frame = sys._getframe().f_back + # addr is something as D:\pytesting1\src\mod1\hello.py:TestCase.testMet4 + # so, convert it to what report_cond expects + addr = parent_frame.f_locals['addr'] + i = addr.rindex(':') + addr = [addr[:i], addr[i + 1:]] + + output, testsRun, failures, errors, errorClasses = batch_result + if failures or errors: + for failure in failures: + PYDEV_NOSE_PLUGIN_SINGLETON.report_cond('fail', addr, output, failure) + + for error in errors: + PYDEV_NOSE_PLUGIN_SINGLETON.report_cond('error', addr, output, error) + else: + PYDEV_NOSE_PLUGIN_SINGLETON.report_cond('ok', addr, output) + + return ret + + +MultiProcessTestRunner.consolidate = new_consolidate diff --git a/_pydev_runfiles/pydev_runfiles_parallel.py b/_pydev_runfiles/pydev_runfiles_parallel.py new file mode 100644 index 0000000..b34c45e --- /dev/null +++ b/_pydev_runfiles/pydev_runfiles_parallel.py @@ -0,0 +1,267 @@ +import unittest +from _pydev_bundle._pydev_saved_modules import thread +import queue as Queue +from _pydev_runfiles import pydev_runfiles_xml_rpc +import time +import os +import threading +import sys + + +#======================================================================================================================= +# flatten_test_suite +#======================================================================================================================= +def flatten_test_suite(test_suite, ret): + if isinstance(test_suite, unittest.TestSuite): + for t in test_suite._tests: + flatten_test_suite(t, ret) + + elif isinstance(test_suite, unittest.TestCase): + ret.append(test_suite) + + +#======================================================================================================================= +# execute_tests_in_parallel +#======================================================================================================================= +def execute_tests_in_parallel(tests, jobs, split, verbosity, coverage_files, coverage_include): + ''' + @param tests: list(PydevTestSuite) + A list with the suites to be run + + @param split: str + Either 'module' or the number of tests that should be run in each batch + + @param coverage_files: list(file) + A list with the files that should be used for giving coverage information (if empty, coverage information + should not be gathered). + + @param coverage_include: str + The pattern that should be included in the coverage. + + @return: bool + Returns True if the tests were actually executed in parallel. If the tests were not executed because only 1 + should be used (e.g.: 2 jobs were requested for running 1 test), False will be returned and no tests will be + run. + + It may also return False if in debug mode (in which case, multi-processes are not accepted) + ''' + try: + from _pydevd_bundle.pydevd_comm import get_global_debugger + if get_global_debugger() is not None: + return False + except: + pass # Ignore any error here. + + # This queue will receive the tests to be run. Each entry in a queue is a list with the tests to be run together When + # split == 'tests', each list will have a single element, when split == 'module', each list will have all the tests + # from a given module. + tests_queue = [] + + queue_elements = [] + if split == 'module': + module_to_tests = {} + for test in tests: + lst = [] + flatten_test_suite(test, lst) + for test in lst: + key = (test.__pydev_pyfile__, test.__pydev_module_name__) + module_to_tests.setdefault(key, []).append(test) + + for key, tests in module_to_tests.items(): + queue_elements.append(tests) + + if len(queue_elements) < jobs: + # Don't create jobs we will never use. + jobs = len(queue_elements) + + elif split == 'tests': + for test in tests: + lst = [] + flatten_test_suite(test, lst) + for test in lst: + queue_elements.append([test]) + + if len(queue_elements) < jobs: + # Don't create jobs we will never use. + jobs = len(queue_elements) + + else: + raise AssertionError('Do not know how to handle: %s' % (split,)) + + for test_cases in queue_elements: + test_queue_elements = [] + for test_case in test_cases: + try: + test_name = test_case.__class__.__name__ + "." + test_case._testMethodName + except AttributeError: + # Support for jython 2.1 (__testMethodName is pseudo-private in the test case) + test_name = test_case.__class__.__name__ + "." + test_case._TestCase__testMethodName + + test_queue_elements.append(test_case.__pydev_pyfile__ + '|' + test_name) + + tests_queue.append(test_queue_elements) + + if jobs < 2: + return False + + sys.stdout.write('Running tests in parallel with: %s jobs.\n' % (jobs,)) + + queue = Queue.Queue() + for item in tests_queue: + queue.put(item, block=False) + + providers = [] + clients = [] + for i in range(jobs): + test_cases_provider = CommunicationThread(queue) + providers.append(test_cases_provider) + + test_cases_provider.start() + port = test_cases_provider.port + + if coverage_files: + clients.append(ClientThread(i, port, verbosity, coverage_files.pop(0), coverage_include)) + else: + clients.append(ClientThread(i, port, verbosity)) + + for client in clients: + client.start() + + client_alive = True + while client_alive: + client_alive = False + for client in clients: + # Wait for all the clients to exit. + if not client.finished: + client_alive = True + time.sleep(.2) + break + + for provider in providers: + provider.shutdown() + + return True + + +#======================================================================================================================= +# CommunicationThread +#======================================================================================================================= +class CommunicationThread(threading.Thread): + + def __init__(self, tests_queue): + threading.Thread.__init__(self) + self.daemon = True + self.queue = tests_queue + self.finished = False + from _pydev_bundle.pydev_imports import SimpleXMLRPCServer + from _pydev_bundle import pydev_localhost + + # Create server + server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), 0), logRequests=False) + server.register_function(self.GetTestsToRun) + server.register_function(self.notifyStartTest) + server.register_function(self.notifyTest) + server.register_function(self.notifyCommands) + self.port = server.socket.getsockname()[1] + self.server = server + + def GetTestsToRun(self, job_id): + ''' + @param job_id: + + @return: list(str) + Each entry is a string in the format: filename|Test.testName + ''' + try: + ret = self.queue.get(block=False) + return ret + except: # Any exception getting from the queue (empty or not) means we finished our work on providing the tests. + self.finished = True + return [] + + def notifyCommands(self, job_id, commands): + # Batch notification. + for command in commands: + getattr(self, command[0])(job_id, *command[1], **command[2]) + + return True + + def notifyStartTest(self, job_id, *args, **kwargs): + pydev_runfiles_xml_rpc.notifyStartTest(*args, **kwargs) + return True + + def notifyTest(self, job_id, *args, **kwargs): + pydev_runfiles_xml_rpc.notifyTest(*args, **kwargs) + return True + + def shutdown(self): + if hasattr(self.server, 'shutdown'): + self.server.shutdown() + else: + self._shutdown = True + + def run(self): + if hasattr(self.server, 'shutdown'): + self.server.serve_forever() + else: + self._shutdown = False + while not self._shutdown: + self.server.handle_request() + + +#======================================================================================================================= +# Client +#======================================================================================================================= +class ClientThread(threading.Thread): + + def __init__(self, job_id, port, verbosity, coverage_output_file=None, coverage_include=None): + threading.Thread.__init__(self) + self.daemon = True + self.port = port + self.job_id = job_id + self.verbosity = verbosity + self.finished = False + self.coverage_output_file = coverage_output_file + self.coverage_include = coverage_include + + def _reader_thread(self, pipe, target): + while True: + target.write(pipe.read(1)) + + def run(self): + try: + from _pydev_runfiles import pydev_runfiles_parallel_client + # TODO: Support Jython: + # + # For jython, instead of using sys.executable, we should use: + # r'D:\bin\jdk_1_5_09\bin\java.exe', + # '-classpath', + # 'D:/bin/jython-2.2.1/jython.jar', + # 'org.python.util.jython', + + args = [ + sys.executable, + pydev_runfiles_parallel_client.__file__, + str(self.job_id), + str(self.port), + str(self.verbosity), + ] + + if self.coverage_output_file and self.coverage_include: + args.append(self.coverage_output_file) + args.append(self.coverage_include) + + import subprocess + if False: + proc = subprocess.Popen(args, env=os.environ, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + thread.start_new_thread(self._reader_thread, (proc.stdout, sys.stdout)) + + thread.start_new_thread(target=self._reader_thread, args=(proc.stderr, sys.stderr)) + else: + proc = subprocess.Popen(args, env=os.environ, shell=False) + proc.wait() + + finally: + self.finished = True + diff --git a/_pydev_runfiles/pydev_runfiles_parallel_client.py b/_pydev_runfiles/pydev_runfiles_parallel_client.py new file mode 100644 index 0000000..3d81dd5 --- /dev/null +++ b/_pydev_runfiles/pydev_runfiles_parallel_client.py @@ -0,0 +1,214 @@ +from _pydev_bundle.pydev_imports import xmlrpclib, _queue +Queue = _queue.Queue +import traceback +import sys +from _pydev_runfiles.pydev_runfiles_coverage import start_coverage_support_from_params +import threading + + +#======================================================================================================================= +# ParallelNotification +#======================================================================================================================= +class ParallelNotification(object): + + def __init__(self, method, args, kwargs): + self.method = method + self.args = args + self.kwargs = kwargs + + def to_tuple(self): + return self.method, self.args, self.kwargs + + +#======================================================================================================================= +# KillServer +#======================================================================================================================= +class KillServer(object): + pass + + + +#======================================================================================================================= +# ServerComm +#======================================================================================================================= +class ServerComm(threading.Thread): + + + + def __init__(self, job_id, server): + self.notifications_queue = Queue() + threading.Thread.__init__(self) + self.setDaemon(False) #Wait for all the notifications to be passed before exiting! + assert job_id is not None + assert port is not None + self.job_id = job_id + + self.finished = False + self.server = server + + + def run(self): + while True: + kill_found = False + commands = [] + command = self.notifications_queue.get(block=True) + if isinstance(command, KillServer): + kill_found = True + else: + assert isinstance(command, ParallelNotification) + commands.append(command.to_tuple()) + + try: + while True: + command = self.notifications_queue.get(block=False) #No block to create a batch. + if isinstance(command, KillServer): + kill_found = True + else: + assert isinstance(command, ParallelNotification) + commands.append(command.to_tuple()) + except: + pass #That's OK, we're getting it until it becomes empty so that we notify multiple at once. + + + if commands: + try: + #Batch notification. + self.server.lock.acquire() + try: + self.server.notifyCommands(self.job_id, commands) + finally: + self.server.lock.release() + except: + traceback.print_exc() + + if kill_found: + self.finished = True + return + + + +#======================================================================================================================= +# ServerFacade +#======================================================================================================================= +class ServerFacade(object): + + + def __init__(self, notifications_queue): + self.notifications_queue = notifications_queue + + + def notifyTestsCollected(self, *args, **kwargs): + pass #This notification won't be passed + + + def notifyTestRunFinished(self, *args, **kwargs): + pass #This notification won't be passed + + + def notifyStartTest(self, *args, **kwargs): + self.notifications_queue.put_nowait(ParallelNotification('notifyStartTest', args, kwargs)) + + + def notifyTest(self, *args, **kwargs): + self.notifications_queue.put_nowait(ParallelNotification('notifyTest', args, kwargs)) + + + +#======================================================================================================================= +# run_client +#======================================================================================================================= +def run_client(job_id, port, verbosity, coverage_output_file, coverage_include): + job_id = int(job_id) + + from _pydev_bundle import pydev_localhost + server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), port)) + server.lock = threading.Lock() + + + server_comm = ServerComm(job_id, server) + server_comm.start() + + try: + server_facade = ServerFacade(server_comm.notifications_queue) + from _pydev_runfiles import pydev_runfiles + from _pydev_runfiles import pydev_runfiles_xml_rpc + pydev_runfiles_xml_rpc.set_server(server_facade) + + #Starts None and when the 1st test is gotten, it's started (because a server may be initiated and terminated + #before receiving any test -- which would mean a different process got all the tests to run). + coverage = None + + try: + tests_to_run = [1] + while tests_to_run: + #Investigate: is it dangerous to use the same xmlrpclib server from different threads? + #It seems it should be, as it creates a new connection for each request... + server.lock.acquire() + try: + tests_to_run = server.GetTestsToRun(job_id) + finally: + server.lock.release() + + if not tests_to_run: + break + + if coverage is None: + _coverage_files, coverage = start_coverage_support_from_params( + None, coverage_output_file, 1, coverage_include) + + + files_to_tests = {} + for test in tests_to_run: + filename_and_test = test.split('|') + if len(filename_and_test) == 2: + files_to_tests.setdefault(filename_and_test[0], []).append(filename_and_test[1]) + + configuration = pydev_runfiles.Configuration( + '', + verbosity, + None, + None, + None, + files_to_tests, + 1, #Always single job here + None, + + #The coverage is handled in this loop. + coverage_output_file=None, + coverage_include=None, + ) + test_runner = pydev_runfiles.PydevTestRunner(configuration) + sys.stdout.flush() + test_runner.run_tests(handle_coverage=False) + finally: + if coverage is not None: + coverage.stop() + coverage.save() + + + except: + traceback.print_exc() + server_comm.notifications_queue.put_nowait(KillServer()) + + + +#======================================================================================================================= +# main +#======================================================================================================================= +if __name__ == '__main__': + if len(sys.argv) -1 == 3: + job_id, port, verbosity = sys.argv[1:] + coverage_output_file, coverage_include = None, None + + elif len(sys.argv) -1 == 5: + job_id, port, verbosity, coverage_output_file, coverage_include = sys.argv[1:] + + else: + raise AssertionError('Could not find out how to handle the parameters: '+sys.argv[1:]) + + job_id = int(job_id) + port = int(port) + verbosity = int(verbosity) + run_client(job_id, port, verbosity, coverage_output_file, coverage_include) + + diff --git a/_pydev_runfiles/pydev_runfiles_pytest2.py b/_pydev_runfiles/pydev_runfiles_pytest2.py new file mode 100644 index 0000000..793097d --- /dev/null +++ b/_pydev_runfiles/pydev_runfiles_pytest2.py @@ -0,0 +1,306 @@ +from _pydev_runfiles import pydev_runfiles_xml_rpc +import pickle +import zlib +import base64 +import os +from pydevd_file_utils import canonical_normalized_path +import pytest +import sys +import time +from pathlib import Path + +#========================================================================= +# Load filters with tests we should skip +#========================================================================= +py_test_accept_filter = None + + +def _load_filters(): + global py_test_accept_filter + if py_test_accept_filter is None: + py_test_accept_filter = os.environ.get('PYDEV_PYTEST_SKIP') + if py_test_accept_filter: + py_test_accept_filter = pickle.loads( + zlib.decompress(base64.b64decode(py_test_accept_filter))) + + # Newer versions of pytest resolve symlinks, so, we + # may need to filter with a resolved path too. + new_dct = {} + for filename, value in py_test_accept_filter.items(): + new_dct[canonical_normalized_path(str(Path(filename).resolve()))] = value + + py_test_accept_filter.update(new_dct) + + else: + py_test_accept_filter = {} + + +def is_in_xdist_node(): + main_pid = os.environ.get('PYDEV_MAIN_PID') + if main_pid and main_pid != str(os.getpid()): + return True + return False + + +connected = False + + +def connect_to_server_for_communication_to_xml_rpc_on_xdist(): + global connected + if connected: + return + connected = True + if is_in_xdist_node(): + port = os.environ.get('PYDEV_PYTEST_SERVER') + if not port: + sys.stderr.write( + 'Error: no PYDEV_PYTEST_SERVER environment variable defined.\n') + else: + pydev_runfiles_xml_rpc.initialize_server(int(port), daemon=True) + + +PY2 = sys.version_info[0] <= 2 +PY3 = not PY2 + + +class State: + start_time = time.time() + buf_err = None + buf_out = None + + +def start_redirect(): + if State.buf_out is not None: + return + from _pydevd_bundle import pydevd_io + State.buf_err = pydevd_io.start_redirect(keep_original_redirection=True, std='stderr') + State.buf_out = pydevd_io.start_redirect(keep_original_redirection=True, std='stdout') + + +def get_curr_output(): + buf_out = State.buf_out + buf_err = State.buf_err + return buf_out.getvalue() if buf_out is not None else '', buf_err.getvalue() if buf_err is not None else '' + + +def pytest_unconfigure(): + if is_in_xdist_node(): + return + # Only report that it finished when on the main node (we don't want to report + # the finish on each separate node). + pydev_runfiles_xml_rpc.notifyTestRunFinished( + 'Finished in: %.2f secs.' % (time.time() - State.start_time,)) + + +def pytest_collection_modifyitems(session, config, items): + # A note: in xdist, this is not called on the main process, only in the + # secondary nodes, so, we'll actually make the filter and report it multiple + # times. + connect_to_server_for_communication_to_xml_rpc_on_xdist() + + _load_filters() + if not py_test_accept_filter: + pydev_runfiles_xml_rpc.notifyTestsCollected(len(items)) + return # Keep on going (nothing to filter) + + new_items = [] + for item in items: + f = canonical_normalized_path(str(item.parent.fspath)) + name = item.name + + if f not in py_test_accept_filter: + # print('Skip file: %s' % (f,)) + continue # Skip the file + + i = name.find('[') + name_without_parametrize = None + if i > 0: + name_without_parametrize = name[:i] + + accept_tests = py_test_accept_filter[f] + + if item.cls is not None: + class_name = item.cls.__name__ + else: + class_name = None + for test in accept_tests: + if test == name: + # Direct match of the test (just go on with the default + # loading) + new_items.append(item) + break + + if name_without_parametrize is not None and test == name_without_parametrize: + # This happens when parameterizing pytest tests on older versions + # of pytest where the test name doesn't include the fixture name + # in it. + new_items.append(item) + break + + if class_name is not None: + if test == class_name + '.' + name: + new_items.append(item) + break + + if name_without_parametrize is not None and test == class_name + '.' + name_without_parametrize: + new_items.append(item) + break + + if class_name == test: + new_items.append(item) + break + else: + pass + # print('Skip test: %s.%s. Accept: %s' % (class_name, name, accept_tests)) + + # Modify the original list + items[:] = new_items + pydev_runfiles_xml_rpc.notifyTestsCollected(len(items)) + + +try: + """ + pytest > 5.4 uses own version of TerminalWriter based on py.io.TerminalWriter + and assumes there is a specific method TerminalWriter._write_source + so try load pytest version first or fallback to default one + """ + from _pytest._io import TerminalWriter +except ImportError: + from py.io import TerminalWriter + + +def _get_error_contents_from_report(report): + if report.longrepr is not None: + try: + tw = TerminalWriter(stringio=True) + stringio = tw.stringio + except TypeError: + import io + stringio = io.StringIO() + tw = TerminalWriter(file=stringio) + tw.hasmarkup = False + report.toterminal(tw) + exc = stringio.getvalue() + s = exc.strip() + if s: + return s + + return '' + + +def pytest_collectreport(report): + error_contents = _get_error_contents_from_report(report) + if error_contents: + report_test('fail', '', '', '', error_contents, 0.0) + + +def append_strings(s1, s2): + if s1.__class__ == s2.__class__: + return s1 + s2 + + # Prefer str + if isinstance(s1, bytes): + s1 = s1.decode('utf-8', 'replace') + + if isinstance(s2, bytes): + s2 = s2.decode('utf-8', 'replace') + + return s1 + s2 + + +def pytest_runtest_logreport(report): + if is_in_xdist_node(): + # When running with xdist, we don't want the report to be called from the node, only + # from the main process. + return + report_duration = report.duration + report_when = report.when + report_outcome = report.outcome + + if hasattr(report, 'wasxfail'): + if report_outcome != 'skipped': + report_outcome = 'passed' + + if report_outcome == 'passed': + # passed on setup/teardown: no need to report if in setup or teardown + # (only on the actual test if it passed). + if report_when in ('setup', 'teardown'): + return + + status = 'ok' + + elif report_outcome == 'skipped': + status = 'skip' + + else: + # It has only passed, skipped and failed (no error), so, let's consider + # error if not on call. + if report_when in ('setup', 'teardown'): + status = 'error' + + else: + # any error in the call (not in setup or teardown) is considered a + # regular failure. + status = 'fail' + + # This will work if pytest is not capturing it, if it is, nothing will + # come from here... + captured_output, error_contents = getattr(report, 'pydev_captured_output', ''), getattr(report, 'pydev_error_contents', '') + for type_section, value in report.sections: + if value: + if type_section in ('err', 'stderr', 'Captured stderr call'): + error_contents = append_strings(error_contents, value) + else: + captured_output = append_strings(error_contents, value) + + filename = getattr(report, 'pydev_fspath_strpath', '') + test = report.location[2] + + if report_outcome != 'skipped': + # On skipped, we'll have a traceback for the skip, which is not what we + # want. + exc = _get_error_contents_from_report(report) + if exc: + if error_contents: + error_contents = append_strings(error_contents, '----------------------------- Exceptions -----------------------------\n') + error_contents = append_strings(error_contents, exc) + + report_test(status, filename, test, captured_output, error_contents, report_duration) + + +def report_test(status, filename, test, captured_output, error_contents, duration): + ''' + @param filename: 'D:\\src\\mod1\\hello.py' + @param test: 'TestCase.testMet1' + @param status: fail, error, ok + ''' + time_str = '%.2f' % (duration,) + pydev_runfiles_xml_rpc.notifyTest( + status, captured_output, error_contents, filename, test, time_str) + + +if not hasattr(pytest, 'hookimpl'): + raise AssertionError('Please upgrade pytest (the current version of pytest: %s is unsupported)' % (pytest.__version__,)) + + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_makereport(item, call): + outcome = yield + report = outcome.get_result() + report.pydev_fspath_strpath = item.fspath.strpath + report.pydev_captured_output, report.pydev_error_contents = get_curr_output() + + +@pytest.mark.tryfirst +def pytest_runtest_setup(item): + ''' + Note: with xdist will be on a secondary process. + ''' + # We have our own redirection: if xdist does its redirection, we'll have + # nothing in our contents (which is OK), but if it does, we'll get nothing + # from pytest but will get our own here. + start_redirect() + filename = item.fspath.strpath + test = item.location[2] + + pydev_runfiles_xml_rpc.notifyStartTest(filename, test) diff --git a/_pydev_runfiles/pydev_runfiles_unittest.py b/_pydev_runfiles/pydev_runfiles_unittest.py new file mode 100644 index 0000000..fff1ef9 --- /dev/null +++ b/_pydev_runfiles/pydev_runfiles_unittest.py @@ -0,0 +1,150 @@ +import unittest as python_unittest +from _pydev_runfiles import pydev_runfiles_xml_rpc +import time +from _pydevd_bundle import pydevd_io +import traceback +from _pydevd_bundle.pydevd_constants import * # @UnusedWildImport +from io import StringIO + + +#======================================================================================================================= +# PydevTextTestRunner +#======================================================================================================================= +class PydevTextTestRunner(python_unittest.TextTestRunner): + + def _makeResult(self): + return PydevTestResult(self.stream, self.descriptions, self.verbosity) + + +_PythonTextTestResult = python_unittest.TextTestRunner()._makeResult().__class__ + + +#======================================================================================================================= +# PydevTestResult +#======================================================================================================================= +class PydevTestResult(_PythonTextTestResult): + + def addSubTest(self, test, subtest, err): + """Called at the end of a subtest. + 'err' is None if the subtest ended successfully, otherwise it's a + tuple of values as returned by sys.exc_info(). + """ + _PythonTextTestResult.addSubTest(self, test, subtest, err) + if err is not None: + subdesc = subtest._subDescription() + error = (test, self._exc_info_to_string(err, test)) + self._reportErrors([error], [], '', '%s %s' % (self.get_test_name(test), subdesc)) + + def startTest(self, test): + _PythonTextTestResult.startTest(self, test) + self.buf = pydevd_io.start_redirect(keep_original_redirection=True, std='both') + self.start_time = time.time() + self._current_errors_stack = [] + self._current_failures_stack = [] + + try: + test_name = test.__class__.__name__ + "." + test._testMethodName + except AttributeError: + # Support for jython 2.1 (__testMethodName is pseudo-private in the test case) + test_name = test.__class__.__name__ + "." + test._TestCase__testMethodName + + pydev_runfiles_xml_rpc.notifyStartTest( + test.__pydev_pyfile__, test_name) + + def get_test_name(self, test): + try: + try: + test_name = test.__class__.__name__ + "." + test._testMethodName + except AttributeError: + # Support for jython 2.1 (__testMethodName is pseudo-private in the test case) + try: + test_name = test.__class__.__name__ + "." + test._TestCase__testMethodName + # Support for class/module exceptions (test is instance of _ErrorHolder) + except: + test_name = test.description.split()[1][1:-1] + ' <' + test.description.split()[0] + '>' + except: + traceback.print_exc() + return '' + return test_name + + def stopTest(self, test): + end_time = time.time() + pydevd_io.end_redirect(std='both') + + _PythonTextTestResult.stopTest(self, test) + + captured_output = self.buf.getvalue() + del self.buf + error_contents = '' + test_name = self.get_test_name(test) + + diff_time = '%.2f' % (end_time - self.start_time) + + skipped = False + outcome = getattr(test, '_outcome', None) + if outcome is not None: + skipped = bool(getattr(outcome, 'skipped', None)) + + if skipped: + pydev_runfiles_xml_rpc.notifyTest( + 'skip', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time) + elif not self._current_errors_stack and not self._current_failures_stack: + pydev_runfiles_xml_rpc.notifyTest( + 'ok', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time) + else: + self._reportErrors(self._current_errors_stack, self._current_failures_stack, captured_output, test_name) + + def _reportErrors(self, errors, failures, captured_output, test_name, diff_time=''): + error_contents = [] + for test, s in errors + failures: + if type(s) == type((1,)): # If it's a tuple (for jython 2.1) + sio = StringIO() + traceback.print_exception(s[0], s[1], s[2], file=sio) + s = sio.getvalue() + error_contents.append(s) + + sep = '\n' + self.separator1 + error_contents = sep.join(error_contents) + + if errors and not failures: + try: + pydev_runfiles_xml_rpc.notifyTest( + 'error', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time) + except: + file_start = error_contents.find('File "') + file_end = error_contents.find('", ', file_start) + if file_start != -1 and file_end != -1: + file = error_contents[file_start + 6:file_end] + else: + file = '' + pydev_runfiles_xml_rpc.notifyTest( + 'error', captured_output, error_contents, file, test_name, diff_time) + + elif failures and not errors: + pydev_runfiles_xml_rpc.notifyTest( + 'fail', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time) + + else: # Ok, we got both, errors and failures. Let's mark it as an error in the end. + pydev_runfiles_xml_rpc.notifyTest( + 'error', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time) + + def addError(self, test, err): + _PythonTextTestResult.addError(self, test, err) + # Support for class/module exceptions (test is instance of _ErrorHolder) + if not hasattr(self, '_current_errors_stack') or test.__class__.__name__ == '_ErrorHolder': + # Not in start...end, so, report error now (i.e.: django pre/post-setup) + self._reportErrors([self.errors[-1]], [], '', self.get_test_name(test)) + else: + self._current_errors_stack.append(self.errors[-1]) + + def addFailure(self, test, err): + _PythonTextTestResult.addFailure(self, test, err) + if not hasattr(self, '_current_failures_stack'): + # Not in start...end, so, report error now (i.e.: django pre/post-setup) + self._reportErrors([], [self.failures[-1]], '', self.get_test_name(test)) + else: + self._current_failures_stack.append(self.failures[-1]) + + +class PydevTestSuite(python_unittest.TestSuite): + pass diff --git a/_pydev_runfiles/pydev_runfiles_xml_rpc.py b/_pydev_runfiles/pydev_runfiles_xml_rpc.py new file mode 100644 index 0000000..b4d6b5c --- /dev/null +++ b/_pydev_runfiles/pydev_runfiles_xml_rpc.py @@ -0,0 +1,257 @@ +import sys +import threading +import traceback +import warnings + +from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding +from _pydev_bundle.pydev_imports import xmlrpclib, _queue +from _pydevd_bundle.pydevd_constants import Null + +Queue = _queue.Queue + +# This may happen in IronPython (in Python it shouldn't happen as there are +# 'fast' replacements that are used in xmlrpclib.py) +warnings.filterwarnings( + 'ignore', 'The xmllib module is obsolete.*', DeprecationWarning) + +file_system_encoding = getfilesystemencoding() + + +#======================================================================================================================= +# _ServerHolder +#======================================================================================================================= +class _ServerHolder: + ''' + Helper so that we don't have to use a global here. + ''' + SERVER = None + + +#======================================================================================================================= +# set_server +#======================================================================================================================= +def set_server(server): + _ServerHolder.SERVER = server + + +#======================================================================================================================= +# ParallelNotification +#======================================================================================================================= +class ParallelNotification(object): + + def __init__(self, method, args): + self.method = method + self.args = args + + def to_tuple(self): + return self.method, self.args + + +#======================================================================================================================= +# KillServer +#======================================================================================================================= +class KillServer(object): + pass + + +#======================================================================================================================= +# ServerFacade +#======================================================================================================================= +class ServerFacade(object): + + def __init__(self, notifications_queue): + self.notifications_queue = notifications_queue + + def notifyTestsCollected(self, *args): + self.notifications_queue.put_nowait(ParallelNotification('notifyTestsCollected', args)) + + def notifyConnected(self, *args): + self.notifications_queue.put_nowait(ParallelNotification('notifyConnected', args)) + + def notifyTestRunFinished(self, *args): + self.notifications_queue.put_nowait(ParallelNotification('notifyTestRunFinished', args)) + + def notifyStartTest(self, *args): + self.notifications_queue.put_nowait(ParallelNotification('notifyStartTest', args)) + + def notifyTest(self, *args): + new_args = [] + for arg in args: + new_args.append(_encode_if_needed(arg)) + args = tuple(new_args) + self.notifications_queue.put_nowait(ParallelNotification('notifyTest', args)) + + +#======================================================================================================================= +# ServerComm +#======================================================================================================================= +class ServerComm(threading.Thread): + + def __init__(self, notifications_queue, port, daemon=False): + threading.Thread.__init__(self) + self.setDaemon(daemon) # If False, wait for all the notifications to be passed before exiting! + self.finished = False + self.notifications_queue = notifications_queue + + from _pydev_bundle import pydev_localhost + + # It is necessary to specify an encoding, that matches + # the encoding of all bytes-strings passed into an + # XMLRPC call: "All 8-bit strings in the data structure are assumed to use the + # packet encoding. Unicode strings are automatically converted, + # where necessary." + # Byte strings most likely come from file names. + encoding = file_system_encoding + if encoding == "mbcs": + # Windos symbolic name for the system encoding CP_ACP. + # We need to convert it into a encoding that is recognized by Java. + # Unfortunately this is not always possible. You could use + # GetCPInfoEx and get a name similar to "windows-1251". Then + # you need a table to translate on a best effort basis. Much to complicated. + # ISO-8859-1 is good enough. + encoding = "ISO-8859-1" + + self.server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), port), + encoding=encoding) + + def run(self): + while True: + kill_found = False + commands = [] + command = self.notifications_queue.get(block=True) + if isinstance(command, KillServer): + kill_found = True + else: + assert isinstance(command, ParallelNotification) + commands.append(command.to_tuple()) + + try: + while True: + command = self.notifications_queue.get(block=False) # No block to create a batch. + if isinstance(command, KillServer): + kill_found = True + else: + assert isinstance(command, ParallelNotification) + commands.append(command.to_tuple()) + except: + pass # That's OK, we're getting it until it becomes empty so that we notify multiple at once. + + if commands: + try: + self.server.notifyCommands(commands) + except: + traceback.print_exc() + + if kill_found: + self.finished = True + return + + +#======================================================================================================================= +# initialize_server +#======================================================================================================================= +def initialize_server(port, daemon=False): + if _ServerHolder.SERVER is None: + if port is not None: + notifications_queue = Queue() + _ServerHolder.SERVER = ServerFacade(notifications_queue) + _ServerHolder.SERVER_COMM = ServerComm(notifications_queue, port, daemon) + _ServerHolder.SERVER_COMM.start() + else: + # Create a null server, so that we keep the interface even without any connection. + _ServerHolder.SERVER = Null() + _ServerHolder.SERVER_COMM = Null() + + try: + _ServerHolder.SERVER.notifyConnected() + except: + traceback.print_exc() + + +#======================================================================================================================= +# notifyTest +#======================================================================================================================= +def notifyTestsCollected(tests_count): + assert tests_count is not None + try: + _ServerHolder.SERVER.notifyTestsCollected(tests_count) + except: + traceback.print_exc() + + +#======================================================================================================================= +# notifyStartTest +#======================================================================================================================= +def notifyStartTest(file, test): + ''' + @param file: the tests file (c:/temp/test.py) + @param test: the test ran (i.e.: TestCase.test1) + ''' + assert file is not None + if test is None: + test = '' # Could happen if we have an import error importing module. + + try: + _ServerHolder.SERVER.notifyStartTest(file, test) + except: + traceback.print_exc() + + +def _encode_if_needed(obj): + # In the java side we expect strings to be ISO-8859-1 (org.python.pydev.debug.pyunit.PyUnitServer.initializeDispatches().new Dispatch() {...}.getAsStr(Object)) + if isinstance(obj, str): # Unicode in py3 + return xmlrpclib.Binary(obj.encode('ISO-8859-1', 'xmlcharrefreplace')) + + elif isinstance(obj, bytes): + try: + return xmlrpclib.Binary(obj.decode(sys.stdin.encoding).encode('ISO-8859-1', 'xmlcharrefreplace')) + except: + return xmlrpclib.Binary(obj) # bytes already + + return obj + + +#======================================================================================================================= +# notifyTest +#======================================================================================================================= +def notifyTest(cond, captured_output, error_contents, file, test, time): + ''' + @param cond: ok, fail, error + @param captured_output: output captured from stdout + @param captured_output: output captured from stderr + @param file: the tests file (c:/temp/test.py) + @param test: the test ran (i.e.: TestCase.test1) + @param time: float with the number of seconds elapsed + ''' + assert cond is not None + assert captured_output is not None + assert error_contents is not None + assert file is not None + if test is None: + test = '' # Could happen if we have an import error importing module. + assert time is not None + try: + captured_output = _encode_if_needed(captured_output) + error_contents = _encode_if_needed(error_contents) + + _ServerHolder.SERVER.notifyTest(cond, captured_output, error_contents, file, test, time) + except: + traceback.print_exc() + + +#======================================================================================================================= +# notifyTestRunFinished +#======================================================================================================================= +def notifyTestRunFinished(total_time): + assert total_time is not None + try: + _ServerHolder.SERVER.notifyTestRunFinished(total_time) + except: + traceback.print_exc() + + +#======================================================================================================================= +# force_server_kill +#======================================================================================================================= +def force_server_kill(): + _ServerHolder.SERVER_COMM.notifications_queue.put_nowait(KillServer()) diff --git a/_pydevd_bundle/__init__.py b/_pydevd_bundle/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/_pydevd_bundle/_debug_adapter/__init__.py b/_pydevd_bundle/_debug_adapter/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/_pydevd_bundle/_debug_adapter/__main__pydevd_gen_debug_adapter_protocol.py b/_pydevd_bundle/_debug_adapter/__main__pydevd_gen_debug_adapter_protocol.py new file mode 100644 index 0000000..b45fa5f --- /dev/null +++ b/_pydevd_bundle/_debug_adapter/__main__pydevd_gen_debug_adapter_protocol.py @@ -0,0 +1,592 @@ +''' +Run this module to regenerate the `pydevd_schema.py` file. + +Note that it'll generate it based on the current debugProtocol.json. Erase it and rerun +to download the latest version. +''' + + +def is_variable_to_translate(cls_name, var_name): + if var_name in ('variablesReference', 'frameId', 'threadId'): + return True + + if cls_name == 'StackFrame' and var_name == 'id': + # It's frameId everywhere except on StackFrame. + return True + + if cls_name == 'Thread' and var_name == 'id': + # It's threadId everywhere except on Thread. + return True + + return False + + +def _get_noqa_for_var(prop_name): + return ' # noqa (assign to builtin)' if prop_name in ('type', 'format', 'id', 'hex', 'breakpoint', 'filter') else '' + + +class _OrderedSet(object): + # Not a good ordered set (just something to be small without adding any deps) + + def __init__(self, initial_contents=None): + self._contents = [] + self._contents_as_set = set() + if initial_contents is not None: + for x in initial_contents: + self.add(x) + + def add(self, x): + if x not in self._contents_as_set: + self._contents_as_set.add(x) + self._contents.append(x) + + def discard(self, x): + if x in self._contents_as_set: + self._contents_as_set.remove(x) + self._contents.remove(x) + + def copy(self): + return _OrderedSet(self._contents) + + def update(self, contents): + for x in contents: + self.add(x) + + def __iter__(self): + return iter(self._contents) + + def __contains__(self, item): + return item in self._contents_as_set + + def __len__(self): + return len(self._contents) + + def set_repr(self): + if len(self) == 0: + return 'set()' + + lst = [repr(x) for x in self] + return 'set([' + ', '.join(lst) + '])' + + +class Ref(object): + + def __init__(self, ref, ref_data): + self.ref = ref + self.ref_data = ref_data + + def __str__(self): + return self.ref + + +def load_schema_data(): + import os.path + import json + + json_file = os.path.join(os.path.dirname(__file__), 'debugProtocol.json') + if not os.path.exists(json_file): + import requests + req = requests.get('https://raw.githubusercontent.com/microsoft/debug-adapter-protocol/gh-pages/debugAdapterProtocol.json') + assert req.status_code == 200 + with open(json_file, 'wb') as stream: + stream.write(req.content) + + with open(json_file, 'rb') as json_contents: + json_schema_data = json.loads(json_contents.read()) + return json_schema_data + + +def load_custom_schema_data(): + import os.path + import json + + json_file = os.path.join(os.path.dirname(__file__), 'debugProtocolCustom.json') + + with open(json_file, 'rb') as json_contents: + json_schema_data = json.loads(json_contents.read()) + return json_schema_data + + +def create_classes_to_generate_structure(json_schema_data): + definitions = json_schema_data['definitions'] + + class_to_generatees = {} + + for name, definition in definitions.items(): + all_of = definition.get('allOf') + description = definition.get('description') + is_enum = definition.get('type') == 'string' and 'enum' in definition + enum_values = None + if is_enum: + enum_values = definition['enum'] + properties = {} + properties.update(definition.get('properties', {})) + required = _OrderedSet(definition.get('required', _OrderedSet())) + base_definitions = [] + + if all_of is not None: + for definition in all_of: + ref = definition.get('$ref') + if ref is not None: + assert ref.startswith('#/definitions/') + ref = ref[len('#/definitions/'):] + base_definitions.append(ref) + else: + if not description: + description = definition.get('description') + properties.update(definition.get('properties', {})) + required.update(_OrderedSet(definition.get('required', _OrderedSet()))) + + if isinstance(description, (list, tuple)): + description = '\n'.join(description) + + if name == 'ModulesRequest': # Hack to accept modules request without arguments (ptvsd: 2050). + required.discard('arguments') + class_to_generatees[name] = dict( + name=name, + properties=properties, + base_definitions=base_definitions, + description=description, + required=required, + is_enum=is_enum, + enum_values=enum_values + ) + return class_to_generatees + + +def collect_bases(curr_class, classes_to_generate, memo=None): + ret = [] + if memo is None: + memo = {} + + base_definitions = curr_class['base_definitions'] + for base_definition in base_definitions: + if base_definition not in memo: + ret.append(base_definition) + ret.extend(collect_bases(classes_to_generate[base_definition], classes_to_generate, memo)) + + return ret + + +def fill_properties_and_required_from_base(classes_to_generate): + # Now, resolve properties based on refs + for class_to_generate in classes_to_generate.values(): + dct = {} + s = _OrderedSet() + + for base_definition in reversed(collect_bases(class_to_generate, classes_to_generate)): + # Note: go from base to current so that the initial order of the properties has that + # same order. + dct.update(classes_to_generate[base_definition].get('properties', {})) + s.update(classes_to_generate[base_definition].get('required', _OrderedSet())) + + dct.update(class_to_generate['properties']) + class_to_generate['properties'] = dct + + s.update(class_to_generate['required']) + class_to_generate['required'] = s + + return class_to_generate + + +def update_class_to_generate_description(class_to_generate): + import textwrap + description = class_to_generate['description'] + lines = [] + for line in description.splitlines(): + wrapped = textwrap.wrap(line.strip(), 100) + lines.extend(wrapped) + lines.append('') + + while lines and lines[-1] == '': + lines = lines[:-1] + + class_to_generate['description'] = ' ' + ('\n '.join(lines)) + + +def update_class_to_generate_type(classes_to_generate, class_to_generate): + properties = class_to_generate.get('properties') + for _prop_name, prop_val in properties.items(): + prop_type = prop_val.get('type', '') + if not prop_type: + prop_type = prop_val.pop('$ref', '') + if prop_type: + assert prop_type.startswith('#/definitions/') + prop_type = prop_type[len('#/definitions/'):] + prop_val['type'] = Ref(prop_type, classes_to_generate[prop_type]) + + +def update_class_to_generate_register_dec(classes_to_generate, class_to_generate): + # Default + class_to_generate['register_request'] = '' + class_to_generate['register_dec'] = '@register' + + properties = class_to_generate.get('properties') + enum_type = properties.get('type', {}).get('enum') + command = None + event = None + if enum_type and len(enum_type) == 1 and next(iter(enum_type)) in ("request", "response", "event"): + msg_type = next(iter(enum_type)) + if msg_type == 'response': + # The actual command is typed in the request + response_name = class_to_generate['name'] + request_name = response_name[:-len('Response')] + 'Request' + if request_name in classes_to_generate: + command = classes_to_generate[request_name]['properties'].get('command') + else: + if response_name == 'ErrorResponse': + command = {'enum': ['error']} + else: + raise AssertionError('Unhandled: %s' % (response_name,)) + + elif msg_type == 'request': + command = properties.get('command') + + elif msg_type == 'event': + command = properties.get('event') + + else: + raise AssertionError('Unexpected condition.') + + if command: + enum = command.get('enum') + if enum and len(enum) == 1: + class_to_generate['register_request'] = '@register_%s(%r)\n' % (msg_type, enum[0]) + + +def extract_prop_name_and_prop(class_to_generate): + properties = class_to_generate.get('properties') + required = _OrderedSet(class_to_generate.get('required', _OrderedSet())) + + # Sort so that required come first + prop_name_and_prop = list(properties.items()) + + def compute_sort_key(x): + key = x[0] + if key in required: + if key == 'seq': + return 0.5 # seq when required is after the other required keys (to have a default of -1). + return 0 + return 1 + + prop_name_and_prop.sort(key=compute_sort_key) + + return prop_name_and_prop + + +def update_class_to_generate_to_json(class_to_generate): + required = _OrderedSet(class_to_generate.get('required', _OrderedSet())) + prop_name_and_prop = extract_prop_name_and_prop(class_to_generate) + + to_dict_body = ['def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused)'] + + translate_prop_names = [] + for prop_name, prop in prop_name_and_prop: + if is_variable_to_translate(class_to_generate['name'], prop_name): + translate_prop_names.append(prop_name) + + for prop_name, prop in prop_name_and_prop: + namespace = dict(prop_name=prop_name, noqa=_get_noqa_for_var(prop_name)) + to_dict_body.append(' %(prop_name)s = self.%(prop_name)s%(noqa)s' % namespace) + + if prop.get('type') == 'array': + to_dict_body.append(' if %(prop_name)s and hasattr(%(prop_name)s[0], "to_dict"):' % namespace) + to_dict_body.append(' %(prop_name)s = [x.to_dict() for x in %(prop_name)s]' % namespace) + + if translate_prop_names: + to_dict_body.append(' if update_ids_to_dap:') + for prop_name in translate_prop_names: + namespace = dict(prop_name=prop_name, noqa=_get_noqa_for_var(prop_name)) + to_dict_body.append(' if %(prop_name)s is not None:' % namespace) + to_dict_body.append(' %(prop_name)s = self._translate_id_to_dap(%(prop_name)s)%(noqa)s' % namespace) + + if not translate_prop_names: + update_dict_ids_from_dap_body = [] + else: + update_dict_ids_from_dap_body = ['', '', '@classmethod', 'def update_dict_ids_from_dap(cls, dct):'] + for prop_name in translate_prop_names: + namespace = dict(prop_name=prop_name) + update_dict_ids_from_dap_body.append(' if %(prop_name)r in dct:' % namespace) + update_dict_ids_from_dap_body.append(' dct[%(prop_name)r] = cls._translate_id_from_dap(dct[%(prop_name)r])' % namespace) + update_dict_ids_from_dap_body.append(' return dct') + + class_to_generate['update_dict_ids_from_dap'] = _indent_lines('\n'.join(update_dict_ids_from_dap_body)) + + to_dict_body.append(' dct = {') + first_not_required = False + + for prop_name, prop in prop_name_and_prop: + use_to_dict = prop['type'].__class__ == Ref and not prop['type'].ref_data.get('is_enum', False) + is_array = prop['type'] == 'array' + ref_array_cls_name = '' + if is_array: + ref = prop['items'].get('$ref') + if ref is not None: + ref_array_cls_name = ref.split('/')[-1] + + namespace = dict(prop_name=prop_name, ref_array_cls_name=ref_array_cls_name) + if prop_name in required: + if use_to_dict: + to_dict_body.append(' %(prop_name)r: %(prop_name)s.to_dict(update_ids_to_dap=update_ids_to_dap),' % namespace) + else: + if ref_array_cls_name: + to_dict_body.append(' %(prop_name)r: [%(ref_array_cls_name)s.update_dict_ids_to_dap(o) for o in %(prop_name)s] if (update_ids_to_dap and %(prop_name)s) else %(prop_name)s,' % namespace) + else: + to_dict_body.append(' %(prop_name)r: %(prop_name)s,' % namespace) + else: + if not first_not_required: + first_not_required = True + to_dict_body.append(' }') + + to_dict_body.append(' if %(prop_name)s is not None:' % namespace) + if use_to_dict: + to_dict_body.append(' dct[%(prop_name)r] = %(prop_name)s.to_dict(update_ids_to_dap=update_ids_to_dap)' % namespace) + else: + if ref_array_cls_name: + to_dict_body.append(' dct[%(prop_name)r] = [%(ref_array_cls_name)s.update_dict_ids_to_dap(o) for o in %(prop_name)s] if (update_ids_to_dap and %(prop_name)s) else %(prop_name)s' % namespace) + else: + to_dict_body.append(' dct[%(prop_name)r] = %(prop_name)s' % namespace) + + if not first_not_required: + first_not_required = True + to_dict_body.append(' }') + + to_dict_body.append(' dct.update(self.kwargs)') + to_dict_body.append(' return dct') + + class_to_generate['to_dict'] = _indent_lines('\n'.join(to_dict_body)) + + if not translate_prop_names: + update_dict_ids_to_dap_body = [] + else: + update_dict_ids_to_dap_body = ['', '', '@classmethod', 'def update_dict_ids_to_dap(cls, dct):'] + for prop_name in translate_prop_names: + namespace = dict(prop_name=prop_name) + update_dict_ids_to_dap_body.append(' if %(prop_name)r in dct:' % namespace) + update_dict_ids_to_dap_body.append(' dct[%(prop_name)r] = cls._translate_id_to_dap(dct[%(prop_name)r])' % namespace) + update_dict_ids_to_dap_body.append(' return dct') + + class_to_generate['update_dict_ids_to_dap'] = _indent_lines('\n'.join(update_dict_ids_to_dap_body)) + + +def update_class_to_generate_init(class_to_generate): + args = [] + init_body = [] + docstring = [] + + required = _OrderedSet(class_to_generate.get('required', _OrderedSet())) + prop_name_and_prop = extract_prop_name_and_prop(class_to_generate) + + translate_prop_names = [] + for prop_name, prop in prop_name_and_prop: + if is_variable_to_translate(class_to_generate['name'], prop_name): + translate_prop_names.append(prop_name) + + enum = prop.get('enum') + if enum and len(enum) == 1: + init_body.append(' self.%(prop_name)s = %(enum)r' % dict(prop_name=prop_name, enum=next(iter(enum)))) + else: + if prop_name in required: + if prop_name == 'seq': + args.append(prop_name + '=-1') + else: + args.append(prop_name) + else: + args.append(prop_name + '=None') + + if prop['type'].__class__ == Ref: + ref = prop['type'] + ref_data = ref.ref_data + if ref_data.get('is_enum', False): + init_body.append(' if %s is not None:' % (prop_name,)) + init_body.append(' assert %s in %s.VALID_VALUES' % (prop_name, str(ref))) + init_body.append(' self.%(prop_name)s = %(prop_name)s' % dict( + prop_name=prop_name)) + else: + namespace = dict( + prop_name=prop_name, + ref_name=str(ref) + ) + init_body.append(' if %(prop_name)s is None:' % namespace) + init_body.append(' self.%(prop_name)s = %(ref_name)s()' % namespace) + init_body.append(' else:') + init_body.append(' self.%(prop_name)s = %(ref_name)s(update_ids_from_dap=update_ids_from_dap, **%(prop_name)s) if %(prop_name)s.__class__ != %(ref_name)s else %(prop_name)s' % namespace + ) + + else: + init_body.append(' self.%(prop_name)s = %(prop_name)s' % dict(prop_name=prop_name)) + + if prop['type'] == 'array': + ref = prop['items'].get('$ref') + if ref is not None: + ref_array_cls_name = ref.split('/')[-1] + init_body.append(' if update_ids_from_dap and self.%(prop_name)s:' % dict(prop_name=prop_name)) + init_body.append(' for o in self.%(prop_name)s:' % dict(prop_name=prop_name)) + init_body.append(' %(ref_array_cls_name)s.update_dict_ids_from_dap(o)' % dict(ref_array_cls_name=ref_array_cls_name)) + + prop_type = prop['type'] + prop_description = prop.get('description', '') + + if isinstance(prop_description, (list, tuple)): + prop_description = '\n '.join(prop_description) + + docstring.append(':param %(prop_type)s %(prop_name)s: %(prop_description)s' % dict( + prop_type=prop_type, prop_name=prop_name, prop_description=prop_description)) + + if translate_prop_names: + init_body.append(' if update_ids_from_dap:') + for prop_name in translate_prop_names: + init_body.append(' self.%(prop_name)s = self._translate_id_from_dap(self.%(prop_name)s)' % dict(prop_name=prop_name)) + + docstring = _indent_lines('\n'.join(docstring)) + init_body = '\n'.join(init_body) + + # Actually bundle the whole __init__ from the parts. + args = ', '.join(args) + if args: + args = ', ' + args + + # Note: added kwargs because some messages are expected to be extended by the user (so, we'll actually + # make all extendable so that we don't have to worry about which ones -- we loose a little on typing, + # but may be better than doing a allow list based on something only pointed out in the documentation). + class_to_generate['init'] = '''def __init__(self%(args)s, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ +%(docstring)s + """ +%(init_body)s + self.kwargs = kwargs +''' % dict(args=args, init_body=init_body, docstring=docstring) + + class_to_generate['init'] = _indent_lines(class_to_generate['init']) + + +def update_class_to_generate_props(class_to_generate): + import json + + def default(o): + if isinstance(o, Ref): + return o.ref + raise AssertionError('Unhandled: %s' % (o,)) + + properties = class_to_generate['properties'] + class_to_generate['props'] = ' __props__ = %s' % _indent_lines( + json.dumps(properties, indent=4, default=default)).strip() + + +def update_class_to_generate_refs(class_to_generate): + properties = class_to_generate['properties'] + class_to_generate['refs'] = ' __refs__ = %s' % _OrderedSet( + key for (key, val) in properties.items() if val['type'].__class__ == Ref).set_repr() + + +def update_class_to_generate_enums(class_to_generate): + class_to_generate['enums'] = '' + if class_to_generate.get('is_enum', False): + enums = '' + for enum in class_to_generate['enum_values']: + enums += ' %s = %r\n' % (enum.upper(), enum) + enums += '\n' + enums += ' VALID_VALUES = %s\n\n' % _OrderedSet(class_to_generate['enum_values']).set_repr() + class_to_generate['enums'] = enums + + +def update_class_to_generate_objects(classes_to_generate, class_to_generate): + properties = class_to_generate['properties'] + for key, val in properties.items(): + if 'type' not in val: + val['type'] = 'TypeNA' + continue + + if val['type'] == 'object': + create_new = val.copy() + create_new.update({ + 'name': '%s%s' % (class_to_generate['name'], key.title()), + 'description': ' "%s" of %s' % (key, class_to_generate['name']) + }) + if 'properties' not in create_new: + create_new['properties'] = {} + + assert create_new['name'] not in classes_to_generate + classes_to_generate[create_new['name']] = create_new + + update_class_to_generate_type(classes_to_generate, create_new) + update_class_to_generate_props(create_new) + + # Update nested object types + update_class_to_generate_objects(classes_to_generate, create_new) + + val['type'] = Ref(create_new['name'], classes_to_generate[create_new['name']]) + val.pop('properties', None) + + +def gen_debugger_protocol(): + import os.path + import sys + + if sys.version_info[:2] < (3, 6): + raise AssertionError('Must be run with Python 3.6 onwards (to keep dict order).') + + classes_to_generate = create_classes_to_generate_structure(load_schema_data()) + classes_to_generate.update(create_classes_to_generate_structure(load_custom_schema_data())) + + class_to_generate = fill_properties_and_required_from_base(classes_to_generate) + + for class_to_generate in list(classes_to_generate.values()): + update_class_to_generate_description(class_to_generate) + update_class_to_generate_type(classes_to_generate, class_to_generate) + update_class_to_generate_props(class_to_generate) + update_class_to_generate_objects(classes_to_generate, class_to_generate) + + for class_to_generate in classes_to_generate.values(): + update_class_to_generate_refs(class_to_generate) + update_class_to_generate_init(class_to_generate) + update_class_to_generate_enums(class_to_generate) + update_class_to_generate_to_json(class_to_generate) + update_class_to_generate_register_dec(classes_to_generate, class_to_generate) + + class_template = ''' +%(register_request)s%(register_dec)s +class %(name)s(BaseSchema): + """ +%(description)s + + Note: automatically generated code. Do not edit manually. + """ + +%(enums)s%(props)s +%(refs)s + + __slots__ = list(__props__.keys()) + ['kwargs'] + +%(init)s%(update_dict_ids_from_dap)s + +%(to_dict)s%(update_dict_ids_to_dap)s +''' + + contents = [] + contents.append('# coding: utf-8') + contents.append('# Automatically generated code.') + contents.append('# Do not edit manually.') + contents.append('# Generated by running: %s' % os.path.basename(__file__)) + contents.append('from .pydevd_base_schema import BaseSchema, register, register_request, register_response, register_event') + contents.append('') + for class_to_generate in classes_to_generate.values(): + contents.append(class_template % class_to_generate) + + parent_dir = os.path.dirname(__file__) + schema = os.path.join(parent_dir, 'pydevd_schema.py') + with open(schema, 'w', encoding='utf-8') as stream: + stream.write('\n'.join(contents)) + + +def _indent_lines(lines, indent=' '): + out_lines = [] + for line in lines.splitlines(keepends=True): + out_lines.append(indent + line) + + return ''.join(out_lines) + + +if __name__ == '__main__': + + gen_debugger_protocol() diff --git a/_pydevd_bundle/_debug_adapter/debugProtocol.json b/_pydevd_bundle/_debug_adapter/debugProtocol.json new file mode 100644 index 0000000..8bbe944 --- /dev/null +++ b/_pydevd_bundle/_debug_adapter/debugProtocol.json @@ -0,0 +1,4084 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Debug Adapter Protocol", + "description": "The Debug Adapter Protocol defines the protocol used between an editor or IDE and a debugger or runtime.", + "type": "object", + + + "definitions": { + + "ProtocolMessage": { + "type": "object", + "title": "Base Protocol", + "description": "Base class of requests, responses, and events.", + "properties": { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "description": "Message type.", + "_enum": [ "request", "response", "event" ] + } + }, + "required": [ "seq", "type" ] + }, + + "Request": { + "allOf": [ { "$ref": "#/definitions/ProtocolMessage" }, { + "type": "object", + "description": "A client or debug adapter initiated request.", + "properties": { + "type": { + "type": "string", + "enum": [ "request" ] + }, + "command": { + "type": "string", + "description": "The command to execute." + }, + "arguments": { + "type": [ "array", "boolean", "integer", "null", "number" , "object", "string" ], + "description": "Object containing arguments for the command." + } + }, + "required": [ "type", "command" ] + }] + }, + + "Event": { + "allOf": [ { "$ref": "#/definitions/ProtocolMessage" }, { + "type": "object", + "description": "A debug adapter initiated event.", + "properties": { + "type": { + "type": "string", + "enum": [ "event" ] + }, + "event": { + "type": "string", + "description": "Type of event." + }, + "body": { + "type": [ "array", "boolean", "integer", "null", "number" , "object", "string" ], + "description": "Event-specific information." + } + }, + "required": [ "type", "event" ] + }] + }, + + "Response": { + "allOf": [ { "$ref": "#/definitions/ProtocolMessage" }, { + "type": "object", + "description": "Response for a request.", + "properties": { + "type": { + "type": "string", + "enum": [ "response" ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ "cancelled" ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ "array", "boolean", "integer", "null", "number" , "object", "string" ], + "description": "Contains request result if success is true and optional error details if success is false." + } + }, + "required": [ "type", "request_seq", "success", "command" ] + }] + }, + + "ErrorResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "On error (whenever 'success' is false), the body can provide more details.", + "properties": { + "body": { + "type": "object", + "properties": { + "error": { + "$ref": "#/definitions/Message", + "description": "An optional, structured error message." + } + } + } + }, + "required": [ "body" ] + }] + }, + + "CancelRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The 'cancel' request is used by the frontend in two situations:\n- to indicate that it is no longer interested in the result produced by a specific request issued earlier\n- to cancel a progress sequence. Clients should only call this request if the capability 'supportsCancelRequest' is true.\nThis request has a hint characteristic: a debug adapter can only be expected to make a 'best effort' in honouring this request but there are no guarantees.\nThe 'cancel' request may return an error if it could not cancel an operation but a frontend should refrain from presenting this error to end users.\nA frontend client should only call this request if the capability 'supportsCancelRequest' is true.\nThe request that got canceled still needs to send a response back. This can either be a normal result ('success' attribute true)\nor an error response ('success' attribute false and the 'message' set to 'cancelled').\nReturning partial results from a cancelled request is possible but please note that a frontend client has no generic way for detecting that a response is partial or not.\n The progress that got cancelled still needs to send a 'progressEnd' event back.\n A client should not assume that progress just got cancelled after sending the 'cancel' request.", + "properties": { + "command": { + "type": "string", + "enum": [ "cancel" ] + }, + "arguments": { + "$ref": "#/definitions/CancelArguments" + } + }, + "required": [ "command" ] + }] + }, + "CancelArguments": { + "type": "object", + "description": "Arguments for 'cancel' request.", + "properties": { + "requestId": { + "type": "integer", + "description": "The ID (attribute 'seq') of the request to cancel. If missing no request is cancelled.\nBoth a 'requestId' and a 'progressId' can be specified in one request." + }, + "progressId": { + "type": "string", + "description": "The ID (attribute 'progressId') of the progress to cancel. If missing no progress is cancelled.\nBoth a 'requestId' and a 'progressId' can be specified in one request." + } + } + }, + "CancelResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'cancel' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "InitializedEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "title": "Events", + "description": "This event indicates that the debug adapter is ready to accept configuration requests (e.g. SetBreakpointsRequest, SetExceptionBreakpointsRequest).\nA debug adapter is expected to send this event when it is ready to accept configuration requests (but not before the 'initialize' request has finished).\nThe sequence of events/requests is as follows:\n- adapters sends 'initialized' event (after the 'initialize' request has returned)\n- frontend sends zero or more 'setBreakpoints' requests\n- frontend sends one 'setFunctionBreakpoints' request (if capability 'supportsFunctionBreakpoints' is true)\n- frontend sends a 'setExceptionBreakpoints' request if one or more 'exceptionBreakpointFilters' have been defined (or if 'supportsConfigurationDoneRequest' is not defined or false)\n- frontend sends other future configuration requests\n- frontend sends one 'configurationDone' request to indicate the end of the configuration.", + "properties": { + "event": { + "type": "string", + "enum": [ "initialized" ] + } + }, + "required": [ "event" ] + }] + }, + + "StoppedEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that the execution of the debuggee has stopped due to some condition.\nThis can be caused by a break point previously set, a stepping request has completed, by executing a debugger statement etc.", + "properties": { + "event": { + "type": "string", + "enum": [ "stopped" ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.\nFor backward compatibility this string is shown in the UI if the 'description' attribute is missing (but it must not be translated).", + "_enum": [ "step", "breakpoint", "exception", "pause", "entry", "goto", "function breakpoint", "data breakpoint", "instruction breakpoint" ] + }, + "description": { + "type": "string", + "description": "The full reason for the event, e.g. 'Paused on exception'. This string is shown in the UI as is and must be translated." + }, + "threadId": { + "type": "integer", + "description": "The thread which was stopped." + }, + "preserveFocusHint": { + "type": "boolean", + "description": "A value of true hints to the frontend that this event should not change the focus." + }, + "text": { + "type": "string", + "description": "Additional information. E.g. if reason is 'exception', text contains the exception name. This string is shown in the UI." + }, + "allThreadsStopped": { + "type": "boolean", + "description": "If 'allThreadsStopped' is true, a debug adapter can announce that all threads have stopped.\n- The client should use this information to enable that all threads can be expanded to access their stacktraces.\n- If the attribute is missing or false, only the thread with the given threadId can be expanded." + }, + "hitBreakpointIds": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Ids of the breakpoints that triggered the event. In most cases there will be only a single breakpoint but here are some examples for multiple breakpoints:\n- Different types of breakpoints map to the same location.\n- Multiple source breakpoints get collapsed to the same instruction by the compiler/runtime.\n- Multiple function breakpoints with different function names map to the same location." + } + }, + "required": [ "reason" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "ContinuedEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that the execution of the debuggee has continued.\nPlease note: a debug adapter is not expected to send this event in response to a request that implies that execution continues, e.g. 'launch' or 'continue'.\nIt is only necessary to send a 'continued' event if there was no previous request that implied this.", + "properties": { + "event": { + "type": "string", + "enum": [ "continued" ] + }, + "body": { + "type": "object", + "properties": { + "threadId": { + "type": "integer", + "description": "The thread which was continued." + }, + "allThreadsContinued": { + "type": "boolean", + "description": "If 'allThreadsContinued' is true, a debug adapter can announce that all threads have continued." + } + }, + "required": [ "threadId" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "ExitedEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that the debuggee has exited and returns its exit code.", + "properties": { + "event": { + "type": "string", + "enum": [ "exited" ] + }, + "body": { + "type": "object", + "properties": { + "exitCode": { + "type": "integer", + "description": "The exit code returned from the debuggee." + } + }, + "required": [ "exitCode" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "TerminatedEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that debugging of the debuggee has terminated. This does **not** mean that the debuggee itself has exited.", + "properties": { + "event": { + "type": "string", + "enum": [ "terminated" ] + }, + "body": { + "type": "object", + "properties": { + "restart": { + "type": [ "array", "boolean", "integer", "null", "number", "object", "string" ], + "description": "A debug adapter may set 'restart' to true (or to an arbitrary object) to request that the front end restarts the session.\nThe value is not interpreted by the client and passed unmodified as an attribute '__restart' to the 'launch' and 'attach' requests." + } + } + } + }, + "required": [ "event" ] + }] + }, + + "ThreadEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that a thread has started or exited.", + "properties": { + "event": { + "type": "string", + "enum": [ "thread" ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.", + "_enum": [ "started", "exited" ] + }, + "threadId": { + "type": "integer", + "description": "The identifier of the thread." + } + }, + "required": ["reason", "threadId"] + } + }, + "required": [ "event", "body" ] + }] + }, + + "OutputEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that the target has produced some output.", + "properties": { + "event": { + "type": "string", + "enum": [ "output" ] + }, + "body": { + "type": "object", + "properties": { + "category": { + "type": "string", + "description": "The output category. If not specified or if the category is not understand by the client, 'console' is assumed.", + "_enum": [ "console", "important", "stdout", "stderr", "telemetry" ], + "enumDescriptions": [ + "Show the output in the client's default message UI, e.g. a 'debug console'. This category should only be used for informational output from the debugger (as opposed to the debuggee).", + "A hint for the client to show the ouput in the client's UI for important and highly visible information, e.g. as a popup notification. This category should only be used for important messages from the debugger (as opposed to the debuggee). Since this category value is a hint, clients might ignore the hint and assume the 'console' category.", + "Show the output as normal program output from the debuggee.", + "Show the output as error program output from the debuggee.", + "Send the output to telemetry instead of showing it to the user." + ] + }, + "output": { + "type": "string", + "description": "The output to report." + }, + "group": { + "type": "string", + "description": "Support for keeping an output log organized by grouping related messages.", + "enum": [ "start", "startCollapsed", "end" ], + "enumDescriptions": [ + "Start a new group in expanded mode. Subsequent output events are members of the group and should be shown indented.\nThe 'output' attribute becomes the name of the group and is not indented.", + "Start a new group in collapsed mode. Subsequent output events are members of the group and should be shown indented (as soon as the group is expanded).\nThe 'output' attribute becomes the name of the group and is not indented.", + "End the current group and decreases the indentation of subsequent output events.\nA non empty 'output' attribute is shown as the unindented end of the group." + ] + }, + "variablesReference": { + "type": "integer", + "description": "If an attribute 'variablesReference' exists and its value is > 0, the output contains objects which can be retrieved by passing 'variablesReference' to the 'variables' request. The value should be less than or equal to 2147483647 (2^31-1)." + }, + "source": { + "$ref": "#/definitions/Source", + "description": "An optional source location where the output was produced." + }, + "line": { + "type": "integer", + "description": "An optional source location line where the output was produced." + }, + "column": { + "type": "integer", + "description": "An optional source location column where the output was produced." + }, + "data": { + "type": [ "array", "boolean", "integer", "null", "number" , "object", "string" ], + "description": "Optional data to report. For the 'telemetry' category the data will be sent to telemetry, for the other categories the data is shown in JSON format." + } + }, + "required": ["output"] + } + }, + "required": [ "event", "body" ] + }] + }, + + "BreakpointEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that some information about a breakpoint has changed.", + "properties": { + "event": { + "type": "string", + "enum": [ "breakpoint" ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.", + "_enum": [ "changed", "new", "removed" ] + }, + "breakpoint": { + "$ref": "#/definitions/Breakpoint", + "description": "The 'id' attribute is used to find the target breakpoint and the other attributes are used as the new values." + } + }, + "required": [ "reason", "breakpoint" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "ModuleEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that some information about a module has changed.", + "properties": { + "event": { + "type": "string", + "enum": [ "module" ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.", + "enum": [ "new", "changed", "removed" ] + }, + "module": { + "$ref": "#/definitions/Module", + "description": "The new, changed, or removed module. In case of 'removed' only the module id is used." + } + }, + "required": [ "reason", "module" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "LoadedSourceEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that some source has been added, changed, or removed from the set of all loaded sources.", + "properties": { + "event": { + "type": "string", + "enum": [ "loadedSource" ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.", + "enum": [ "new", "changed", "removed" ] + }, + "source": { + "$ref": "#/definitions/Source", + "description": "The new, changed, or removed source." + } + }, + "required": [ "reason", "source" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "ProcessEvent": { + "allOf": [ + { "$ref": "#/definitions/Event" }, + { + "type": "object", + "description": "The event indicates that the debugger has begun debugging a new process. Either one that it has launched, or one that it has attached to.", + "properties": { + "event": { + "type": "string", + "enum": [ "process" ] + }, + "body": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The logical name of the process. This is usually the full path to process's executable file. Example: /home/example/myproj/program.js." + }, + "systemProcessId": { + "type": "integer", + "description": "The system process id of the debugged process. This property will be missing for non-system processes." + }, + "isLocalProcess": { + "type": "boolean", + "description": "If true, the process is running on the same computer as the debug adapter." + }, + "startMethod": { + "type": "string", + "enum": [ "launch", "attach", "attachForSuspendedLaunch" ], + "description": "Describes how the debug engine started debugging this process.", + "enumDescriptions": [ + "Process was launched under the debugger.", + "Debugger attached to an existing process.", + "A project launcher component has launched a new process in a suspended state and then asked the debugger to attach." + ] + }, + "pointerSize": { + "type": "integer", + "description": "The size of a pointer or address for this process, in bits. This value may be used by clients when formatting addresses for display." + } + }, + "required": [ "name" ] + } + }, + "required": [ "event", "body" ] + } + ] + }, + + "CapabilitiesEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates that one or more capabilities have changed.\nSince the capabilities are dependent on the frontend and its UI, it might not be possible to change that at random times (or too late).\nConsequently this event has a hint characteristic: a frontend can only be expected to make a 'best effort' in honouring individual capabilities but there are no guarantees.\nOnly changed capabilities need to be included, all other capabilities keep their values.", + "properties": { + "event": { + "type": "string", + "enum": [ "capabilities" ] + }, + "body": { + "type": "object", + "properties": { + "capabilities": { + "$ref": "#/definitions/Capabilities", + "description": "The set of updated capabilities." + } + }, + "required": [ "capabilities" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "ProgressStartEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event signals that a long running operation is about to start and\nprovides additional information for the client to set up a corresponding progress and cancellation UI.\nThe client is free to delay the showing of the UI in order to reduce flicker.\nThis event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request.", + "properties": { + "event": { + "type": "string", + "enum": [ "progressStart" ] + }, + "body": { + "type": "object", + "properties": { + "progressId": { + "type": "string", + "description": "An ID that must be used in subsequent 'progressUpdate' and 'progressEnd' events to make them refer to the same progress reporting.\nIDs must be unique within a debug session." + }, + "title": { + "type": "string", + "description": "Mandatory (short) title of the progress reporting. Shown in the UI to describe the long running operation." + }, + "requestId": { + "type": "integer", + "description": "The request ID that this progress report is related to. If specified a debug adapter is expected to emit\nprogress events for the long running request until the request has been either completed or cancelled.\nIf the request ID is omitted, the progress report is assumed to be related to some general activity of the debug adapter." + }, + "cancellable": { + "type": "boolean", + "description": "If true, the request that reports progress may be canceled with a 'cancel' request.\nSo this property basically controls whether the client should use UX that supports cancellation.\nClients that don't support cancellation are allowed to ignore the setting." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message." + }, + "percentage": { + "type": "number", + "description": "Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown." + } + }, + "required": [ "progressId", "title" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "ProgressUpdateEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event signals that the progress reporting needs to updated with a new message and/or percentage.\nThe client does not have to update the UI immediately, but the clients needs to keep track of the message and/or percentage values.\nThis event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request.", + "properties": { + "event": { + "type": "string", + "enum": [ "progressUpdate" ] + }, + "body": { + "type": "object", + "properties": { + "progressId": { + "type": "string", + "description": "The ID that was introduced in the initial 'progressStart' event." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message. If omitted, the previous message (if any) is used." + }, + "percentage": { + "type": "number", + "description": "Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown." + } + }, + "required": [ "progressId" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "ProgressEndEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event signals the end of the progress reporting with an optional final message.\nThis event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request.", + "properties": { + "event": { + "type": "string", + "enum": [ "progressEnd" ] + }, + "body": { + "type": "object", + "properties": { + "progressId": { + "type": "string", + "description": "The ID that was introduced in the initial 'ProgressStartEvent'." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message. If omitted, the previous message (if any) is used." + } + }, + "required": [ "progressId" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "InvalidatedEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "This event signals that some state in the debug adapter has changed and requires that the client needs to re-render the data snapshot previously requested.\nDebug adapters do not have to emit this event for runtime changes like stopped or thread events because in that case the client refetches the new state anyway. But the event can be used for example to refresh the UI after rendering formatting has changed in the debug adapter.\nThis event should only be sent if the debug adapter has received a value true for the 'supportsInvalidatedEvent' capability of the 'initialize' request.", + "properties": { + "event": { + "type": "string", + "enum": [ "invalidated" ] + }, + "body": { + "type": "object", + "properties": { + "areas": { + "type": "array", + "description": "Optional set of logical areas that got invalidated. This property has a hint characteristic: a client can only be expected to make a 'best effort' in honouring the areas but there are no guarantees. If this property is missing, empty, or if values are not understand the client should assume a single value 'all'.", + "items": { + "$ref": "#/definitions/InvalidatedAreas" + } + }, + "threadId": { + "type": "integer", + "description": "If specified, the client only needs to refetch data related to this thread." + }, + "stackFrameId": { + "type": "integer", + "description": "If specified, the client only needs to refetch data related to this stack frame (and the 'threadId' is ignored)." + } + } + } + }, + "required": [ "event", "body" ] + }] + }, + + "MemoryEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "This event indicates that some memory range has been updated. It should only be sent if the debug adapter has received a value true for the `supportsMemoryEvent` capability of the `initialize` request.\nClients typically react to the event by re-issuing a `readMemory` request if they show the memory identified by the `memoryReference` and if the updated memory range overlaps the displayed range. Clients should not make assumptions how individual memory references relate to each other, so they should not assume that they are part of a single continuous address range and might overlap.\nDebug adapters can use this event to indicate that the contents of a memory range has changed due to some other DAP request like `setVariable` or `setExpression`. Debug adapters are not expected to emit this event for each and every memory change of a running program, because that information is typically not available from debuggers and it would flood clients with too many events.", + "properties": { + "event": { + "type": "string", + "enum": [ "memory" ] + }, + "body": { + "type": "object", + "properties": { + "memoryReference": { + "type": "string", + "description": "Memory reference of a memory range that has been updated." + }, + "offset": { + "type": "integer", + "description": "Starting offset in bytes where memory has been updated. Can be negative." + }, + "count": { + "type": "integer", + "description": "Number of bytes updated." + } + }, + "required": [ "memoryReference", "offset", "count" ] + } + }, + "required": [ "event", "body" ] + }] + }, + + "RunInTerminalRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "title": "Reverse Requests", + "description": "This optional request is sent from the debug adapter to the client to run a command in a terminal.\nThis is typically used to launch the debuggee in a terminal provided by the client.\nThis request should only be called if the client has passed the value true for the 'supportsRunInTerminalRequest' capability of the 'initialize' request.", + "properties": { + "command": { + "type": "string", + "enum": [ "runInTerminal" ] + }, + "arguments": { + "$ref": "#/definitions/RunInTerminalRequestArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "RunInTerminalRequestArguments": { + "type": "object", + "description": "Arguments for 'runInTerminal' request.", + "properties": { + "kind": { + "type": "string", + "enum": [ "integrated", "external" ], + "description": "What kind of terminal to launch." + }, + "title": { + "type": "string", + "description": "Optional title of the terminal." + }, + "cwd": { + "type": "string", + "description": "Working directory for the command. For non-empty, valid paths this typically results in execution of a change directory command." + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of arguments. The first argument is the command to run." + }, + "env": { + "type": "object", + "description": "Environment key-value pairs that are added to or removed from the default environment.", + "additionalProperties": { + "type": [ "string", "null" ], + "description": "Proper values must be strings. A value of 'null' removes the variable from the environment." + } + } + }, + "required": [ "args", "cwd" ] + }, + "RunInTerminalResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'runInTerminal' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "processId": { + "type": "integer", + "description": "The process ID. The value should be less than or equal to 2147483647 (2^31-1)." + }, + "shellProcessId": { + "type": "integer", + "description": "The process ID of the terminal shell. The value should be less than or equal to 2147483647 (2^31-1)." + } + } + } + }, + "required": [ "body" ] + }] + }, + + "InitializeRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "title": "Requests", + "description": "The 'initialize' request is sent as the first request from the client to the debug adapter\nin order to configure it with client capabilities and to retrieve capabilities from the debug adapter.\nUntil the debug adapter has responded to with an 'initialize' response, the client must not send any additional requests or events to the debug adapter.\nIn addition the debug adapter is not allowed to send any requests or events to the client until it has responded with an 'initialize' response.\nThe 'initialize' request may only be sent once.", + "properties": { + "command": { + "type": "string", + "enum": [ "initialize" ] + }, + "arguments": { + "$ref": "#/definitions/InitializeRequestArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "InitializeRequestArguments": { + "type": "object", + "description": "Arguments for 'initialize' request.", + "properties": { + "clientID": { + "type": "string", + "description": "The ID of the (frontend) client using this adapter." + }, + "clientName": { + "type": "string", + "description": "The human readable name of the (frontend) client using this adapter." + }, + "adapterID": { + "type": "string", + "description": "The ID of the debug adapter." + }, + "locale": { + "type": "string", + "description": "The ISO-639 locale of the (frontend) client using this adapter, e.g. en-US or de-CH." + }, + "linesStartAt1": { + "type": "boolean", + "description": "If true all line numbers are 1-based (default)." + }, + "columnsStartAt1": { + "type": "boolean", + "description": "If true all column numbers are 1-based (default)." + }, + "pathFormat": { + "type": "string", + "_enum": [ "path", "uri" ], + "description": "Determines in what format paths are specified. The default is 'path', which is the native format." + }, + "supportsVariableType": { + "type": "boolean", + "description": "Client supports the optional type attribute for variables." + }, + "supportsVariablePaging": { + "type": "boolean", + "description": "Client supports the paging of variables." + }, + "supportsRunInTerminalRequest": { + "type": "boolean", + "description": "Client supports the runInTerminal request." + }, + "supportsMemoryReferences": { + "type": "boolean", + "description": "Client supports memory references." + }, + "supportsProgressReporting": { + "type": "boolean", + "description": "Client supports progress reporting." + }, + "supportsInvalidatedEvent": { + "type": "boolean", + "description": "Client supports the invalidated event." + }, + "supportsMemoryEvent": { + "type": "boolean", + "description": "Client supports the memory event." + } + }, + "required": [ "adapterID" ] + }, + "InitializeResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'initialize' request.", + "properties": { + "body": { + "$ref": "#/definitions/Capabilities", + "description": "The capabilities of this debug adapter." + } + } + }] + }, + + "ConfigurationDoneRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "This optional request indicates that the client has finished initialization of the debug adapter.\nSo it is the last request in the sequence of configuration requests (which was started by the 'initialized' event).\nClients should only call this request if the capability 'supportsConfigurationDoneRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "configurationDone" ] + }, + "arguments": { + "$ref": "#/definitions/ConfigurationDoneArguments" + } + }, + "required": [ "command" ] + }] + }, + "ConfigurationDoneArguments": { + "type": "object", + "description": "Arguments for 'configurationDone' request." + }, + "ConfigurationDoneResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'configurationDone' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "LaunchRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "This launch request is sent from the client to the debug adapter to start the debuggee with or without debugging (if 'noDebug' is true).\nSince launching is debugger/runtime specific, the arguments for this request are not part of this specification.", + "properties": { + "command": { + "type": "string", + "enum": [ "launch" ] + }, + "arguments": { + "$ref": "#/definitions/LaunchRequestArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "LaunchRequestArguments": { + "type": "object", + "description": "Arguments for 'launch' request. Additional attributes are implementation specific.", + "properties": { + "noDebug": { + "type": "boolean", + "description": "If noDebug is true the launch request should launch the program without enabling debugging." + }, + "__restart": { + "type": [ "array", "boolean", "integer", "null", "number", "object", "string" ], + "description": "Optional data from the previous, restarted session.\nThe data is sent as the 'restart' attribute of the 'terminated' event.\nThe client should leave the data intact." + } + } + }, + "LaunchResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'launch' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "AttachRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The attach request is sent from the client to the debug adapter to attach to a debuggee that is already running.\nSince attaching is debugger/runtime specific, the arguments for this request are not part of this specification.", + "properties": { + "command": { + "type": "string", + "enum": [ "attach" ] + }, + "arguments": { + "$ref": "#/definitions/AttachRequestArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "AttachRequestArguments": { + "type": "object", + "description": "Arguments for 'attach' request. Additional attributes are implementation specific.", + "properties": { + "__restart": { + "type": [ "array", "boolean", "integer", "null", "number", "object", "string" ], + "description": "Optional data from the previous, restarted session.\nThe data is sent as the 'restart' attribute of the 'terminated' event.\nThe client should leave the data intact." + } + } + }, + "AttachResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'attach' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "RestartRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Restarts a debug session. Clients should only call this request if the capability 'supportsRestartRequest' is true.\nIf the capability is missing or has the value false, a typical client will emulate 'restart' by terminating the debug adapter first and then launching it anew.", + "properties": { + "command": { + "type": "string", + "enum": [ "restart" ] + }, + "arguments": { + "$ref": "#/definitions/RestartArguments" + } + }, + "required": [ "command" ] + }] + }, + "RestartArguments": { + "type": "object", + "description": "Arguments for 'restart' request.", + "properties": { + "arguments": { + "oneOf": [ + { "$ref": "#/definitions/LaunchRequestArguments" }, + { "$ref": "#/definitions/AttachRequestArguments" } + ], + "description": "The latest version of the 'launch' or 'attach' configuration." + } + } + }, + "RestartResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'restart' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "DisconnectRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The 'disconnect' request is sent from the client to the debug adapter in order to stop debugging.\nIt asks the debug adapter to disconnect from the debuggee and to terminate the debug adapter.\nIf the debuggee has been started with the 'launch' request, the 'disconnect' request terminates the debuggee.\nIf the 'attach' request was used to connect to the debuggee, 'disconnect' does not terminate the debuggee.\nThis behavior can be controlled with the 'terminateDebuggee' argument (if supported by the debug adapter).", + "properties": { + "command": { + "type": "string", + "enum": [ "disconnect" ] + }, + "arguments": { + "$ref": "#/definitions/DisconnectArguments" + } + }, + "required": [ "command" ] + }] + }, + "DisconnectArguments": { + "type": "object", + "description": "Arguments for 'disconnect' request.", + "properties": { + "restart": { + "type": "boolean", + "description": "A value of true indicates that this 'disconnect' request is part of a restart sequence." + }, + "terminateDebuggee": { + "type": "boolean", + "description": "Indicates whether the debuggee should be terminated when the debugger is disconnected.\nIf unspecified, the debug adapter is free to do whatever it thinks is best.\nThe attribute is only honored by a debug adapter if the capability 'supportTerminateDebuggee' is true." + }, + "suspendDebuggee": { + "type": "boolean", + "description": "Indicates whether the debuggee should stay suspended when the debugger is disconnected.\nIf unspecified, the debuggee should resume execution.\nThe attribute is only honored by a debug adapter if the capability 'supportSuspendDebuggee' is true." + } + } + }, + "DisconnectResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'disconnect' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "TerminateRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The 'terminate' request is sent from the client to the debug adapter in order to give the debuggee a chance for terminating itself.\nClients should only call this request if the capability 'supportsTerminateRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "terminate" ] + }, + "arguments": { + "$ref": "#/definitions/TerminateArguments" + } + }, + "required": [ "command" ] + }] + }, + "TerminateArguments": { + "type": "object", + "description": "Arguments for 'terminate' request.", + "properties": { + "restart": { + "type": "boolean", + "description": "A value of true indicates that this 'terminate' request is part of a restart sequence." + } + } + }, + "TerminateResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'terminate' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "BreakpointLocationsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The 'breakpointLocations' request returns all possible locations for source breakpoints in a given range.\nClients should only call this request if the capability 'supportsBreakpointLocationsRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "breakpointLocations" ] + }, + "arguments": { + "$ref": "#/definitions/BreakpointLocationsArguments" + } + }, + "required": [ "command" ] + }] + + }, + "BreakpointLocationsArguments": { + "type": "object", + "description": "Arguments for 'breakpointLocations' request.", + "properties": { + "source": { + "$ref": "#/definitions/Source", + "description": "The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified." + }, + "line": { + "type": "integer", + "description": "Start line of range to search possible breakpoint locations in. If only the line is specified, the request returns all possible locations in that line." + }, + "column": { + "type": "integer", + "description": "Optional start column of range to search possible breakpoint locations in. If no start column is given, the first column in the start line is assumed." + }, + "endLine": { + "type": "integer", + "description": "Optional end line of range to search possible breakpoint locations in. If no end line is given, then the end line is assumed to be the start line." + }, + "endColumn": { + "type": "integer", + "description": "Optional end column of range to search possible breakpoint locations in. If no end column is given, then it is assumed to be in the last column of the end line." + } + }, + "required": [ "source", "line" ] + }, + "BreakpointLocationsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'breakpointLocations' request.\nContains possible locations for source breakpoints.", + "properties": { + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/BreakpointLocation" + }, + "description": "Sorted set of possible breakpoint locations." + } + }, + "required": [ "breakpoints" ] + } + }, + "required": [ "body" ] + }] + }, + + "SetBreakpointsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Sets multiple breakpoints for a single source and clears all previous breakpoints in that source.\nTo clear all breakpoint for a source, specify an empty array.\nWhen a breakpoint is hit, a 'stopped' event (with reason 'breakpoint') is generated.", + "properties": { + "command": { + "type": "string", + "enum": [ "setBreakpoints" ] + }, + "arguments": { + "$ref": "#/definitions/SetBreakpointsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetBreakpointsArguments": { + "type": "object", + "description": "Arguments for 'setBreakpoints' request.", + "properties": { + "source": { + "$ref": "#/definitions/Source", + "description": "The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified." + }, + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/SourceBreakpoint" + }, + "description": "The code locations of the breakpoints." + }, + "lines": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Deprecated: The code locations of the breakpoints." + }, + "sourceModified": { + "type": "boolean", + "description": "A value of true indicates that the underlying source has been modified which results in new breakpoint locations." + } + }, + "required": [ "source" ] + }, + "SetBreakpointsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'setBreakpoints' request.\nReturned is information about each breakpoint created by this request.\nThis includes the actual code location and whether the breakpoint could be verified.\nThe breakpoints returned are in the same order as the elements of the 'breakpoints'\n(or the deprecated 'lines') array in the arguments.", + "properties": { + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints.\nThe array elements are in the same order as the elements of the 'breakpoints' (or the deprecated 'lines') array in the arguments." + } + }, + "required": [ "breakpoints" ] + } + }, + "required": [ "body" ] + }] + }, + + "SetFunctionBreakpointsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Replaces all existing function breakpoints with new function breakpoints.\nTo clear all function breakpoints, specify an empty array.\nWhen a function breakpoint is hit, a 'stopped' event (with reason 'function breakpoint') is generated.\nClients should only call this request if the capability 'supportsFunctionBreakpoints' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "setFunctionBreakpoints" ] + }, + "arguments": { + "$ref": "#/definitions/SetFunctionBreakpointsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetFunctionBreakpointsArguments": { + "type": "object", + "description": "Arguments for 'setFunctionBreakpoints' request.", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/FunctionBreakpoint" + }, + "description": "The function names of the breakpoints." + } + }, + "required": [ "breakpoints" ] + }, + "SetFunctionBreakpointsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'setFunctionBreakpoints' request.\nReturned is information about each breakpoint created by this request.", + "properties": { + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array." + } + }, + "required": [ "breakpoints" ] + } + }, + "required": [ "body" ] + }] + }, + + "SetExceptionBreakpointsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request configures the debuggers response to thrown exceptions.\nIf an exception is configured to break, a 'stopped' event is fired (with reason 'exception').\nClients should only call this request if the capability 'exceptionBreakpointFilters' returns one or more filters.", + "properties": { + "command": { + "type": "string", + "enum": [ "setExceptionBreakpoints" ] + }, + "arguments": { + "$ref": "#/definitions/SetExceptionBreakpointsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetExceptionBreakpointsArguments": { + "type": "object", + "description": "Arguments for 'setExceptionBreakpoints' request.", + "properties": { + "filters": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Set of exception filters specified by their ID. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. The 'filter' and 'filterOptions' sets are additive." + }, + "filterOptions": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionFilterOptions" + }, + "description": "Set of exception filters and their options. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. This attribute is only honored by a debug adapter if the capability 'supportsExceptionFilterOptions' is true. The 'filter' and 'filterOptions' sets are additive." + }, + "exceptionOptions": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionOptions" + }, + "description": "Configuration options for selected exceptions.\nThe attribute is only honored by a debug adapter if the capability 'supportsExceptionOptions' is true." + } + }, + "required": [ "filters" ] + }, + "SetExceptionBreakpointsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'setExceptionBreakpoints' request.\nThe response contains an array of Breakpoint objects with information about each exception breakpoint or filter. The Breakpoint objects are in the same order as the elements of the 'filters', 'filterOptions', 'exceptionOptions' arrays given as arguments. If both 'filters' and 'filterOptions' are given, the returned array must start with 'filters' information first, followed by 'filterOptions' information.\nThe mandatory 'verified' property of a Breakpoint object signals whether the exception breakpoint or filter could be successfully created and whether the optional condition or hit count expressions are valid. In case of an error the 'message' property explains the problem. An optional 'id' property can be used to introduce a unique ID for the exception breakpoint or filter so that it can be updated subsequently by sending breakpoint events.\nFor backward compatibility both the 'breakpoints' array and the enclosing 'body' are optional. If these elements are missing a client will not be able to show problems for individual exception breakpoints or filters.", + "properties": { + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the exception breakpoints or filters.\nThe breakpoints returned are in the same order as the elements of the 'filters', 'filterOptions', 'exceptionOptions' arrays in the arguments. If both 'filters' and 'filterOptions' are given, the returned array must start with 'filters' information first, followed by 'filterOptions' information." + } + } + } + } + }] + }, + + "DataBreakpointInfoRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Obtains information on a possible data breakpoint that could be set on an expression or variable.\nClients should only call this request if the capability 'supportsDataBreakpoints' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "dataBreakpointInfo" ] + }, + "arguments": { + "$ref": "#/definitions/DataBreakpointInfoArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "DataBreakpointInfoArguments": { + "type": "object", + "description": "Arguments for 'dataBreakpointInfo' request.", + "properties": { + "variablesReference": { + "type": "integer", + "description": "Reference to the Variable container if the data breakpoint is requested for a child of the container." + }, + "name": { + "type": "string", + "description": "The name of the Variable's child to obtain data breakpoint information for.\nIf variablesReference isn't provided, this can be an expression." + } + }, + "required": [ "name" ] + }, + "DataBreakpointInfoResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'dataBreakpointInfo' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "dataId": { + "type": [ "string", "null" ], + "description": "An identifier for the data on which a data breakpoint can be registered with the setDataBreakpoints request or null if no data breakpoint is available." + }, + "description": { + "type": "string", + "description": "UI string that describes on what data the breakpoint is set on or why a data breakpoint is not available." + }, + "accessTypes": { + "type": "array", + "items": { + "$ref": "#/definitions/DataBreakpointAccessType" + }, + "description": "Optional attribute listing the available access types for a potential data breakpoint. A UI frontend could surface this information." + }, + "canPersist": { + "type": "boolean", + "description": "Optional attribute indicating that a potential data breakpoint could be persisted across sessions." + } + }, + "required": [ "dataId", "description" ] + } + }, + "required": [ "body" ] + }] + }, + + "SetDataBreakpointsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Replaces all existing data breakpoints with new data breakpoints.\nTo clear all data breakpoints, specify an empty array.\nWhen a data breakpoint is hit, a 'stopped' event (with reason 'data breakpoint') is generated.\nClients should only call this request if the capability 'supportsDataBreakpoints' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "setDataBreakpoints" ] + }, + "arguments": { + "$ref": "#/definitions/SetDataBreakpointsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetDataBreakpointsArguments": { + "type": "object", + "description": "Arguments for 'setDataBreakpoints' request.", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/DataBreakpoint" + }, + "description": "The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints." + } + }, + "required": [ "breakpoints" ] + }, + "SetDataBreakpointsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'setDataBreakpoints' request.\nReturned is information about each breakpoint created by this request.", + "properties": { + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the data breakpoints. The array elements correspond to the elements of the input argument 'breakpoints' array." + } + }, + "required": [ "breakpoints" ] + } + }, + "required": [ "body" ] + }] + }, + + "SetInstructionBreakpointsRequest": { + "allOf": [ + { "$ref": "#/definitions/Request" }, + { + "type": "object", + "description": "Replaces all existing instruction breakpoints. Typically, instruction breakpoints would be set from a diassembly window. \nTo clear all instruction breakpoints, specify an empty array.\nWhen an instruction breakpoint is hit, a 'stopped' event (with reason 'instruction breakpoint') is generated.\nClients should only call this request if the capability 'supportsInstructionBreakpoints' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "setInstructionBreakpoints" ] + }, + "arguments": { + "$ref": "#/definitions/SetInstructionBreakpointsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetInstructionBreakpointsArguments": { + "type": "object", + "description": "Arguments for 'setInstructionBreakpoints' request", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/InstructionBreakpoint" + }, + "description": "The instruction references of the breakpoints" + } + }, + "required": ["breakpoints"] + }, + "SetInstructionBreakpointsResponse": { + "allOf": [ + { "$ref": "#/definitions/Response" }, + { + "type": "object", + "description": "Response to 'setInstructionBreakpoints' request", + "properties": { + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array." + } + }, + "required": [ "breakpoints" ] + } + }, + "required": [ "body" ] + }] + }, + + "ContinueRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request resumes execution of all threads. If the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true resumes only the specified thread. If not all threads were resumed, the 'allThreadsContinued' attribute of the response must be set to false.", + "properties": { + "command": { + "type": "string", + "enum": [ "continue" ] + }, + "arguments": { + "$ref": "#/definitions/ContinueArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "ContinueArguments": { + "type": "object", + "description": "Arguments for 'continue' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, execution is resumed only for the thread with given 'threadId'." + } + }, + "required": [ "threadId" ] + }, + "ContinueResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'continue' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "allThreadsContinued": { + "type": "boolean", + "description": "The value true (or a missing property) signals to the client that all threads have been resumed. The value false must be returned if not all threads were resumed." + } + } + } + }, + "required": [ "body" ] + }] + }, + + "NextRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request executes one step (in the given granularity) for the specified thread and allows all other threads to run freely by resuming them.\nIf the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.", + "properties": { + "command": { + "type": "string", + "enum": [ "next" ] + }, + "arguments": { + "$ref": "#/definitions/NextArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "NextArguments": { + "type": "object", + "description": "Arguments for 'next' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Specifies the thread for which to resume execution for one step (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." + }, + "granularity": { + "$ref": "#/definitions/SteppingGranularity", + "description": "Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed." + } + }, + "required": [ "threadId" ] + }, + "NextResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'next' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "StepInRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request resumes the given thread to step into a function/method and allows all other threads to run freely by resuming them.\nIf the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming.\nIf the request cannot step into a target, 'stepIn' behaves like the 'next' request.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.\nIf there are multiple function/method calls (or other targets) on the source line,\nthe optional argument 'targetId' can be used to control into which target the 'stepIn' should occur.\nThe list of possible targets for a given source line can be retrieved via the 'stepInTargets' request.", + "properties": { + "command": { + "type": "string", + "enum": [ "stepIn" ] + }, + "arguments": { + "$ref": "#/definitions/StepInArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "StepInArguments": { + "type": "object", + "description": "Arguments for 'stepIn' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Specifies the thread for which to resume execution for one step-into (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." + }, + "targetId": { + "type": "integer", + "description": "Optional id of the target to step into." + }, + "granularity": { + "$ref": "#/definitions/SteppingGranularity", + "description": "Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed." + } + }, + "required": [ "threadId" ] + }, + "StepInResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'stepIn' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "StepOutRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request resumes the given thread to step out (return) from a function/method and allows all other threads to run freely by resuming them.\nIf the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.", + "properties": { + "command": { + "type": "string", + "enum": [ "stepOut" ] + }, + "arguments": { + "$ref": "#/definitions/StepOutArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "StepOutArguments": { + "type": "object", + "description": "Arguments for 'stepOut' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Specifies the thread for which to resume execution for one step-out (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." + }, + "granularity": { + "$ref": "#/definitions/SteppingGranularity", + "description": "Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed." + } + }, + "required": [ "threadId" ] + }, + "StepOutResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'stepOut' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "StepBackRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request executes one backward step (in the given granularity) for the specified thread and allows all other threads to run backward freely by resuming them.\nIf the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other suspended threads from resuming.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.\nClients should only call this request if the capability 'supportsStepBack' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "stepBack" ] + }, + "arguments": { + "$ref": "#/definitions/StepBackArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "StepBackArguments": { + "type": "object", + "description": "Arguments for 'stepBack' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Specifies the thread for which to resume execution for one step backwards (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." + }, + "granularity": { + "$ref": "#/definitions/SteppingGranularity", + "description": "Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed." + } + }, + "required": [ "threadId" ] + }, + "StepBackResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'stepBack' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "ReverseContinueRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request resumes backward execution of all threads. If the debug adapter supports single thread execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true resumes only the specified thread. If not all threads were resumed, the 'allThreadsContinued' attribute of the response must be set to false.\nClients should only call this request if the capability 'supportsStepBack' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "reverseContinue" ] + }, + "arguments": { + "$ref": "#/definitions/ReverseContinueArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "ReverseContinueArguments": { + "type": "object", + "description": "Arguments for 'reverseContinue' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, backward execution is resumed only for the thread with given 'threadId'." + } + + }, + "required": [ "threadId" ] + }, + "ReverseContinueResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'reverseContinue' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "RestartFrameRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request restarts execution of the specified stackframe.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'restart') after the restart has completed.\nClients should only call this request if the capability 'supportsRestartFrame' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "restartFrame" ] + }, + "arguments": { + "$ref": "#/definitions/RestartFrameArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "RestartFrameArguments": { + "type": "object", + "description": "Arguments for 'restartFrame' request.", + "properties": { + "frameId": { + "type": "integer", + "description": "Restart this stackframe." + } + }, + "required": [ "frameId" ] + }, + "RestartFrameResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'restartFrame' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "GotoRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request sets the location where the debuggee will continue to run.\nThis makes it possible to skip the execution of code or to executed code again.\nThe code between the current location and the goto target is not executed but skipped.\nThe debug adapter first sends the response and then a 'stopped' event with reason 'goto'.\nClients should only call this request if the capability 'supportsGotoTargetsRequest' is true (because only then goto targets exist that can be passed as arguments).", + "properties": { + "command": { + "type": "string", + "enum": [ "goto" ] + }, + "arguments": { + "$ref": "#/definitions/GotoArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "GotoArguments": { + "type": "object", + "description": "Arguments for 'goto' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Set the goto target for this thread." + }, + "targetId": { + "type": "integer", + "description": "The location where the debuggee will continue to run." + } + }, + "required": [ "threadId", "targetId" ] + }, + "GotoResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'goto' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "PauseRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request suspends the debuggee.\nThe debug adapter first sends the response and then a 'stopped' event (with reason 'pause') after the thread has been paused successfully.", + "properties": { + "command": { + "type": "string", + "enum": [ "pause" ] + }, + "arguments": { + "$ref": "#/definitions/PauseArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "PauseArguments": { + "type": "object", + "description": "Arguments for 'pause' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Pause execution for this thread." + } + }, + "required": [ "threadId" ] + }, + "PauseResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'pause' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "StackTraceRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request returns a stacktrace from the current execution state of a given thread.\nA client can request all stack frames by omitting the startFrame and levels arguments. For performance conscious clients and if the debug adapter's 'supportsDelayedStackTraceLoading' capability is true, stack frames can be retrieved in a piecemeal way with the startFrame and levels arguments. The response of the stackTrace request may contain a totalFrames property that hints at the total number of frames in the stack. If a client needs this total number upfront, it can issue a request for a single (first) frame and depending on the value of totalFrames decide how to proceed. In any case a client should be prepared to receive less frames than requested, which is an indication that the end of the stack has been reached.", + "properties": { + "command": { + "type": "string", + "enum": [ "stackTrace" ] + }, + "arguments": { + "$ref": "#/definitions/StackTraceArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "StackTraceArguments": { + "type": "object", + "description": "Arguments for 'stackTrace' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Retrieve the stacktrace for this thread." + }, + "startFrame": { + "type": "integer", + "description": "The index of the first frame to return; if omitted frames start at 0." + }, + "levels": { + "type": "integer", + "description": "The maximum number of frames to return. If levels is not specified or 0, all frames are returned." + }, + "format": { + "$ref": "#/definitions/StackFrameFormat", + "description": "Specifies details on how to format the stack frames.\nThe attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true." + } + }, + "required": [ "threadId" ] + }, + "StackTraceResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'stackTrace' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "stackFrames": { + "type": "array", + "items": { + "$ref": "#/definitions/StackFrame" + }, + "description": "The frames of the stackframe. If the array has length zero, there are no stackframes available.\nThis means that there is no location information available." + }, + "totalFrames": { + "type": "integer", + "description": "The total number of frames available in the stack. If omitted or if totalFrames is larger than the available frames, a client is expected to request frames until a request returns less frames than requested (which indicates the end of the stack). Returning monotonically increasing totalFrames values for subsequent requests can be used to enforce paging in the client." + } + }, + "required": [ "stackFrames" ] + } + }, + "required": [ "body" ] + }] + }, + + "ScopesRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request returns the variable scopes for a given stackframe ID.", + "properties": { + "command": { + "type": "string", + "enum": [ "scopes" ] + }, + "arguments": { + "$ref": "#/definitions/ScopesArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "ScopesArguments": { + "type": "object", + "description": "Arguments for 'scopes' request.", + "properties": { + "frameId": { + "type": "integer", + "description": "Retrieve the scopes for this stackframe." + } + }, + "required": [ "frameId" ] + }, + "ScopesResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'scopes' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "scopes": { + "type": "array", + "items": { + "$ref": "#/definitions/Scope" + }, + "description": "The scopes of the stackframe. If the array has length zero, there are no scopes available." + } + }, + "required": [ "scopes" ] + } + }, + "required": [ "body" ] + }] + }, + + "VariablesRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Retrieves all child variables for the given variable reference.\nAn optional filter can be used to limit the fetched children to either named or indexed children.", + "properties": { + "command": { + "type": "string", + "enum": [ "variables" ] + }, + "arguments": { + "$ref": "#/definitions/VariablesArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "VariablesArguments": { + "type": "object", + "description": "Arguments for 'variables' request.", + "properties": { + "variablesReference": { + "type": "integer", + "description": "The Variable reference." + }, + "filter": { + "type": "string", + "enum": [ "indexed", "named" ], + "description": "Optional filter to limit the child variables to either named or indexed. If omitted, both types are fetched." + }, + "start": { + "type": "integer", + "description": "The index of the first variable to return; if omitted children start at 0." + }, + "count": { + "type": "integer", + "description": "The number of variables to return. If count is missing or 0, all variables are returned." + }, + "format": { + "$ref": "#/definitions/ValueFormat", + "description": "Specifies details on how to format the Variable values.\nThe attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true." + } + }, + "required": [ "variablesReference" ] + }, + "VariablesResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'variables' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/Variable" + }, + "description": "All (or a range) of variables for the given variable reference." + } + }, + "required": [ "variables" ] + } + }, + "required": [ "body" ] + }] + }, + + "SetVariableRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Set the variable with the given name in the variable container to a new value. Clients should only call this request if the capability 'supportsSetVariable' is true.\nIf a debug adapter implements both setVariable and setExpression, a client will only use setExpression if the variable has an evaluateName property.", + "properties": { + "command": { + "type": "string", + "enum": [ "setVariable" ] + }, + "arguments": { + "$ref": "#/definitions/SetVariableArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetVariableArguments": { + "type": "object", + "description": "Arguments for 'setVariable' request.", + "properties": { + "variablesReference": { + "type": "integer", + "description": "The reference of the variable container." + }, + "name": { + "type": "string", + "description": "The name of the variable in the container." + }, + "value": { + "type": "string", + "description": "The value of the variable." + }, + "format": { + "$ref": "#/definitions/ValueFormat", + "description": "Specifies details on how to format the response value." + } + }, + "required": [ "variablesReference", "name", "value" ] + }, + "SetVariableResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'setVariable' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "The new value of the variable." + }, + "type": { + "type": "string", + "description": "The type of the new value. Typically shown in the UI when hovering over the value." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the new value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + } + }, + "required": [ "value" ] + } + }, + "required": [ "body" ] + }] + }, + + "SourceRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request retrieves the source code for a given source reference.", + "properties": { + "command": { + "type": "string", + "enum": [ "source" ] + }, + "arguments": { + "$ref": "#/definitions/SourceArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SourceArguments": { + "type": "object", + "description": "Arguments for 'source' request.", + "properties": { + "source": { + "$ref": "#/definitions/Source", + "description": "Specifies the source content to load. Either source.path or source.sourceReference must be specified." + }, + "sourceReference": { + "type": "integer", + "description": "The reference to the source. This is the same as source.sourceReference.\nThis is provided for backward compatibility since old backends do not understand the 'source' attribute." + } + }, + "required": [ "sourceReference" ] + }, + "SourceResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'source' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "content": { + "type": "string", + "description": "Content of the source reference." + }, + "mimeType": { + "type": "string", + "description": "Optional content type (mime type) of the source." + } + }, + "required": [ "content" ] + } + }, + "required": [ "body" ] + }] + }, + + "ThreadsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request retrieves a list of all threads.", + "properties": { + "command": { + "type": "string", + "enum": [ "threads" ] + } + }, + "required": [ "command" ] + }] + }, + "ThreadsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'threads' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "threads": { + "type": "array", + "items": { + "$ref": "#/definitions/Thread" + }, + "description": "All threads." + } + }, + "required": [ "threads" ] + } + }, + "required": [ "body" ] + }] + }, + + "TerminateThreadsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request terminates the threads with the given ids.\nClients should only call this request if the capability 'supportsTerminateThreadsRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "terminateThreads" ] + }, + "arguments": { + "$ref": "#/definitions/TerminateThreadsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "TerminateThreadsArguments": { + "type": "object", + "description": "Arguments for 'terminateThreads' request.", + "properties": { + "threadIds": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Ids of threads to be terminated." + } + } + }, + "TerminateThreadsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'terminateThreads' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "ModulesRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Modules can be retrieved from the debug adapter with this request which can either return all modules or a range of modules to support paging.\nClients should only call this request if the capability 'supportsModulesRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "modules" ] + }, + "arguments": { + "$ref": "#/definitions/ModulesArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "ModulesArguments": { + "type": "object", + "description": "Arguments for 'modules' request.", + "properties": { + "startModule": { + "type": "integer", + "description": "The index of the first module to return; if omitted modules start at 0." + }, + "moduleCount": { + "type": "integer", + "description": "The number of modules to return. If moduleCount is not specified or 0, all modules are returned." + } + } + }, + "ModulesResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'modules' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "modules": { + "type": "array", + "items": { + "$ref": "#/definitions/Module" + }, + "description": "All modules or range of modules." + }, + "totalModules": { + "type": "integer", + "description": "The total number of modules available." + } + }, + "required": [ "modules" ] + } + }, + "required": [ "body" ] + }] + }, + + "LoadedSourcesRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Retrieves the set of all sources currently loaded by the debugged process.\nClients should only call this request if the capability 'supportsLoadedSourcesRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "loadedSources" ] + }, + "arguments": { + "$ref": "#/definitions/LoadedSourcesArguments" + } + }, + "required": [ "command" ] + }] + }, + "LoadedSourcesArguments": { + "type": "object", + "description": "Arguments for 'loadedSources' request." + }, + "LoadedSourcesResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'loadedSources' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "$ref": "#/definitions/Source" + }, + "description": "Set of loaded sources." + } + }, + "required": [ "sources" ] + } + }, + "required": [ "body" ] + }] + }, + + "EvaluateRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Evaluates the given expression in the context of the top most stack frame.\nThe expression has access to any variables and arguments that are in scope.", + "properties": { + "command": { + "type": "string", + "enum": [ "evaluate" ] + }, + "arguments": { + "$ref": "#/definitions/EvaluateArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "EvaluateArguments": { + "type": "object", + "description": "Arguments for 'evaluate' request.", + "properties": { + "expression": { + "type": "string", + "description": "The expression to evaluate." + }, + "frameId": { + "type": "integer", + "description": "Evaluate the expression in the scope of this stack frame. If not specified, the expression is evaluated in the global scope." + }, + "context": { + "type": "string", + "_enum": [ "watch", "repl", "hover", "clipboard" ], + "enumDescriptions": [ + "evaluate is run in a watch.", + "evaluate is run from REPL console.", + "evaluate is run from a data hover.", + "evaluate is run to generate the value that will be stored in the clipboard.\nThe attribute is only honored by a debug adapter if the capability 'supportsClipboardContext' is true." + ], + "description": "The context in which the evaluate request is run." + }, + "format": { + "$ref": "#/definitions/ValueFormat", + "description": "Specifies details on how to format the Evaluate result.\nThe attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true." + } + }, + "required": [ "expression" ] + }, + "EvaluateResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'evaluate' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "result": { + "type": "string", + "description": "The result of the evaluate request." + }, + "type": { + "type": "string", + "description": "The optional type of the evaluate result.\nThis attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request." + }, + "presentationHint": { + "$ref": "#/definitions/VariablePresentationHint", + "description": "Properties of a evaluate result that can be used to determine how to render the result in the UI." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the evaluate result is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "memoryReference": { + "type": "string", + "description": "Optional memory reference to a location appropriate for this result.\nFor pointer type eval results, this is generally a reference to the memory address contained in the pointer.\nThis attribute should be returned by a debug adapter if the client has passed the value true for the 'supportsMemoryReferences' capability of the 'initialize' request." + } + }, + "required": [ "result", "variablesReference" ] + } + }, + "required": [ "body" ] + }] + }, + + "SetExpressionRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Evaluates the given 'value' expression and assigns it to the 'expression' which must be a modifiable l-value.\nThe expressions have access to any variables and arguments that are in scope of the specified frame.\nClients should only call this request if the capability 'supportsSetExpression' is true.\nIf a debug adapter implements both setExpression and setVariable, a client will only use setExpression if the variable has an evaluateName property.", + "properties": { + "command": { + "type": "string", + "enum": [ "setExpression" ] + }, + "arguments": { + "$ref": "#/definitions/SetExpressionArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetExpressionArguments": { + "type": "object", + "description": "Arguments for 'setExpression' request.", + "properties": { + "expression": { + "type": "string", + "description": "The l-value expression to assign to." + }, + "value": { + "type": "string", + "description": "The value expression to assign to the l-value expression." + }, + "frameId": { + "type": "integer", + "description": "Evaluate the expressions in the scope of this stack frame. If not specified, the expressions are evaluated in the global scope." + }, + "format": { + "$ref": "#/definitions/ValueFormat", + "description": "Specifies how the resulting value should be formatted." + } + }, + "required": [ "expression", "value" ] + }, + "SetExpressionResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'setExpression' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "The new value of the expression." + }, + "type": { + "type": "string", + "description": "The optional type of the value.\nThis attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request." + }, + "presentationHint": { + "$ref": "#/definitions/VariablePresentationHint", + "description": "Properties of a value that can be used to determine how to render the result in the UI." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + } + }, + "required": [ "value" ] + } + }, + "required": [ "body" ] + }] + }, + + "StepInTargetsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "This request retrieves the possible stepIn targets for the specified stack frame.\nThese targets can be used in the 'stepIn' request.\nThe StepInTargets may only be called if the 'supportsStepInTargetsRequest' capability exists and is true.\nClients should only call this request if the capability 'supportsStepInTargetsRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "stepInTargets" ] + }, + "arguments": { + "$ref": "#/definitions/StepInTargetsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "StepInTargetsArguments": { + "type": "object", + "description": "Arguments for 'stepInTargets' request.", + "properties": { + "frameId": { + "type": "integer", + "description": "The stack frame for which to retrieve the possible stepIn targets." + } + }, + "required": [ "frameId" ] + }, + "StepInTargetsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'stepInTargets' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/StepInTarget" + }, + "description": "The possible stepIn targets of the specified source location." + } + }, + "required": [ "targets" ] + } + }, + "required": [ "body" ] + }] + }, + + "GotoTargetsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "This request retrieves the possible goto targets for the specified source location.\nThese targets can be used in the 'goto' request.\nClients should only call this request if the capability 'supportsGotoTargetsRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "gotoTargets" ] + }, + "arguments": { + "$ref": "#/definitions/GotoTargetsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "GotoTargetsArguments": { + "type": "object", + "description": "Arguments for 'gotoTargets' request.", + "properties": { + "source": { + "$ref": "#/definitions/Source", + "description": "The source location for which the goto targets are determined." + }, + "line": { + "type": "integer", + "description": "The line location for which the goto targets are determined." + }, + "column": { + "type": "integer", + "description": "An optional column location for which the goto targets are determined." + } + }, + "required": [ "source", "line" ] + }, + "GotoTargetsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'gotoTargets' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/GotoTarget" + }, + "description": "The possible goto targets of the specified location." + } + }, + "required": [ "targets" ] + } + }, + "required": [ "body" ] + }] + }, + + "CompletionsRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Returns a list of possible completions for a given caret position and text.\nClients should only call this request if the capability 'supportsCompletionsRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "completions" ] + }, + "arguments": { + "$ref": "#/definitions/CompletionsArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "CompletionsArguments": { + "type": "object", + "description": "Arguments for 'completions' request.", + "properties": { + "frameId": { + "type": "integer", + "description": "Returns completions in the scope of this stack frame. If not specified, the completions are returned for the global scope." + }, + "text": { + "type": "string", + "description": "One or more source lines. Typically this is the text a user has typed into the debug console before he asked for completion." + }, + "column": { + "type": "integer", + "description": "The character position for which to determine the completion proposals." + }, + "line": { + "type": "integer", + "description": "An optional line for which to determine the completion proposals. If missing the first line of the text is assumed." + } + }, + "required": [ "text", "column" ] + }, + "CompletionsResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'completions' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/CompletionItem" + }, + "description": "The possible completions for ." + } + }, + "required": [ "targets" ] + } + }, + "required": [ "body" ] + }] + }, + + "ExceptionInfoRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Retrieves the details of the exception that caused this event to be raised.\nClients should only call this request if the capability 'supportsExceptionInfoRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "exceptionInfo" ] + }, + "arguments": { + "$ref": "#/definitions/ExceptionInfoArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "ExceptionInfoArguments": { + "type": "object", + "description": "Arguments for 'exceptionInfo' request.", + "properties": { + "threadId": { + "type": "integer", + "description": "Thread for which exception information should be retrieved." + } + }, + "required": [ "threadId" ] + }, + "ExceptionInfoResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'exceptionInfo' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "exceptionId": { + "type": "string", + "description": "ID of the exception that was thrown." + }, + "description": { + "type": "string", + "description": "Descriptive text for the exception provided by the debug adapter." + }, + "breakMode": { + "$ref": "#/definitions/ExceptionBreakMode", + "description": "Mode that caused the exception notification to be raised." + }, + "details": { + "$ref": "#/definitions/ExceptionDetails", + "description": "Detailed information about the exception." + } + }, + "required": [ "exceptionId", "breakMode" ] + } + }, + "required": [ "body" ] + }] + }, + + "ReadMemoryRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Reads bytes from memory at the provided location.\nClients should only call this request if the capability 'supportsReadMemoryRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "readMemory" ] + }, + "arguments": { + "$ref": "#/definitions/ReadMemoryArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "ReadMemoryArguments": { + "type": "object", + "description": "Arguments for 'readMemory' request.", + "properties": { + "memoryReference": { + "type": "string", + "description": "Memory reference to the base location from which data should be read." + }, + "offset": { + "type": "integer", + "description": "Optional offset (in bytes) to be applied to the reference location before reading data. Can be negative." + }, + "count": { + "type": "integer", + "description": "Number of bytes to read at the specified location and offset." + } + }, + "required": [ "memoryReference", "count" ] + }, + "ReadMemoryResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'readMemory' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "The address of the first byte of data returned.\nTreated as a hex value if prefixed with '0x', or as a decimal value otherwise." + }, + "unreadableBytes": { + "type": "integer", + "description": "The number of unreadable bytes encountered after the last successfully read byte.\nThis can be used to determine the number of bytes that must be skipped before a subsequent 'readMemory' request will succeed." + }, + "data": { + "type": "string", + "description": "The bytes read from memory, encoded using base64." + } + }, + "required": [ "address" ] + } + } + }] + }, + + "WriteMemoryRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Writes bytes to memory at the provided location.\nClients should only call this request if the capability 'supportsWriteMemoryRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "writeMemory" ] + }, + "arguments": { + "$ref": "#/definitions/WriteMemoryArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "WriteMemoryArguments": { + "type": "object", + "description": "Arguments for 'writeMemory' request.", + "properties": { + "memoryReference": { + "type": "string", + "description": "Memory reference to the base location to which data should be written." + }, + "offset": { + "type": "integer", + "description": "Optional offset (in bytes) to be applied to the reference location before writing data. Can be negative." + }, + "allowPartial": { + "type": "boolean", + "description": "Optional property to control partial writes. If true, the debug adapter should attempt to write memory even if the entire memory region is not writable. In such a case the debug adapter should stop after hitting the first byte of memory that cannot be written and return the number of bytes written in the response via the 'offset' and 'bytesWritten' properties.\nIf false or missing, a debug adapter should attempt to verify the region is writable before writing, and fail the response if it is not." + }, + "data": { + "type": "string", + "description": "Bytes to write, encoded using base64." + } + }, + "required": [ "memoryReference", "data" ] + }, + "WriteMemoryResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'writeMemory' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "offset": { + "type": "integer", + "description": "Optional property that should be returned when 'allowPartial' is true to indicate the offset of the first byte of data successfully written. Can be negative." + }, + "bytesWritten": { + "type": "integer", + "description": "Optional property that should be returned when 'allowPartial' is true to indicate the number of bytes starting from address that were successfully written." + } + } + } + } + }] + }, + + "DisassembleRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "Disassembles code stored at the provided location.\nClients should only call this request if the capability 'supportsDisassembleRequest' is true.", + "properties": { + "command": { + "type": "string", + "enum": [ "disassemble" ] + }, + "arguments": { + "$ref": "#/definitions/DisassembleArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "DisassembleArguments": { + "type": "object", + "description": "Arguments for 'disassemble' request.", + "properties": { + "memoryReference": { + "type": "string", + "description": "Memory reference to the base location containing the instructions to disassemble." + }, + "offset": { + "type": "integer", + "description": "Optional offset (in bytes) to be applied to the reference location before disassembling. Can be negative." + }, + "instructionOffset": { + "type": "integer", + "description": "Optional offset (in instructions) to be applied after the byte offset (if any) before disassembling. Can be negative." + }, + "instructionCount": { + "type": "integer", + "description": "Number of instructions to disassemble starting at the specified location and offset.\nAn adapter must return exactly this number of instructions - any unavailable instructions should be replaced with an implementation-defined 'invalid instruction' value." + }, + "resolveSymbols": { + "type": "boolean", + "description": "If true, the adapter should attempt to resolve memory addresses and other values to symbolic names." + } + }, + "required": [ "memoryReference", "instructionCount" ] + }, + "DisassembleResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'disassemble' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "instructions": { + "type": "array", + "items": { + "$ref": "#/definitions/DisassembledInstruction" + }, + "description": "The list of disassembled instructions." + } + }, + "required": [ "instructions" ] + } + } + }] + }, + + "Capabilities": { + "type": "object", + "title": "Types", + "description": "Information about the capabilities of a debug adapter.", + "properties": { + "supportsConfigurationDoneRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'configurationDone' request." + }, + "supportsFunctionBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports function breakpoints." + }, + "supportsConditionalBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports conditional breakpoints." + }, + "supportsHitConditionalBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports breakpoints that break execution after a specified number of hits." + }, + "supportsEvaluateForHovers": { + "type": "boolean", + "description": "The debug adapter supports a (side effect free) evaluate request for data hovers." + }, + "exceptionBreakpointFilters": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionBreakpointsFilter" + }, + "description": "Available exception filter options for the 'setExceptionBreakpoints' request." + }, + "supportsStepBack": { + "type": "boolean", + "description": "The debug adapter supports stepping back via the 'stepBack' and 'reverseContinue' requests." + }, + "supportsSetVariable": { + "type": "boolean", + "description": "The debug adapter supports setting a variable to a value." + }, + "supportsRestartFrame": { + "type": "boolean", + "description": "The debug adapter supports restarting a frame." + }, + "supportsGotoTargetsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'gotoTargets' request." + }, + "supportsStepInTargetsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'stepInTargets' request." + }, + "supportsCompletionsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'completions' request." + }, + "completionTriggerCharacters": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The set of characters that should trigger completion in a REPL. If not specified, the UI should assume the '.' character." + }, + "supportsModulesRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'modules' request." + }, + "additionalModuleColumns": { + "type": "array", + "items": { + "$ref": "#/definitions/ColumnDescriptor" + }, + "description": "The set of additional module information exposed by the debug adapter." + }, + "supportedChecksumAlgorithms": { + "type": "array", + "items": { + "$ref": "#/definitions/ChecksumAlgorithm" + }, + "description": "Checksum algorithms supported by the debug adapter." + }, + "supportsRestartRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'restart' request. In this case a client should not implement 'restart' by terminating and relaunching the adapter but by calling the RestartRequest." + }, + "supportsExceptionOptions": { + "type": "boolean", + "description": "The debug adapter supports 'exceptionOptions' on the setExceptionBreakpoints request." + }, + "supportsValueFormattingOptions": { + "type": "boolean", + "description": "The debug adapter supports a 'format' attribute on the stackTraceRequest, variablesRequest, and evaluateRequest." + }, + "supportsExceptionInfoRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'exceptionInfo' request." + }, + "supportTerminateDebuggee": { + "type": "boolean", + "description": "The debug adapter supports the 'terminateDebuggee' attribute on the 'disconnect' request." + }, + "supportSuspendDebuggee": { + "type": "boolean", + "description": "The debug adapter supports the 'suspendDebuggee' attribute on the 'disconnect' request." + }, + "supportsDelayedStackTraceLoading": { + "type": "boolean", + "description": "The debug adapter supports the delayed loading of parts of the stack, which requires that both the 'startFrame' and 'levels' arguments and an optional 'totalFrames' result of the 'StackTrace' request are supported." + }, + "supportsLoadedSourcesRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'loadedSources' request." + }, + "supportsLogPoints": { + "type": "boolean", + "description": "The debug adapter supports logpoints by interpreting the 'logMessage' attribute of the SourceBreakpoint." + }, + "supportsTerminateThreadsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'terminateThreads' request." + }, + "supportsSetExpression": { + "type": "boolean", + "description": "The debug adapter supports the 'setExpression' request." + }, + "supportsTerminateRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'terminate' request." + }, + "supportsDataBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports data breakpoints." + }, + "supportsReadMemoryRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'readMemory' request." + }, + "supportsWriteMemoryRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'writeMemory' request." + }, + "supportsDisassembleRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'disassemble' request." + }, + "supportsCancelRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'cancel' request." + }, + "supportsBreakpointLocationsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'breakpointLocations' request." + }, + "supportsClipboardContext": { + "type": "boolean", + "description": "The debug adapter supports the 'clipboard' context value in the 'evaluate' request." + }, + "supportsSteppingGranularity": { + "type": "boolean", + "description": "The debug adapter supports stepping granularities (argument 'granularity') for the stepping requests." + }, + "supportsInstructionBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports adding breakpoints based on instruction references." + }, + "supportsExceptionFilterOptions": { + "type": "boolean", + "description": "The debug adapter supports 'filterOptions' as an argument on the 'setExceptionBreakpoints' request." + }, + "supportsSingleThreadExecutionRequests": { + "type": "boolean", + "description": "The debug adapter supports the 'singleThread' property on the execution requests ('continue', 'next', 'stepIn', 'stepOut', 'reverseContinue', 'stepBack')." + } + } + }, + + "ExceptionBreakpointsFilter": { + "type": "object", + "description": "An ExceptionBreakpointsFilter is shown in the UI as an filter option for configuring how exceptions are dealt with.", + "properties": { + "filter": { + "type": "string", + "description": "The internal ID of the filter option. This value is passed to the 'setExceptionBreakpoints' request." + }, + "label": { + "type": "string", + "description": "The name of the filter option. This will be shown in the UI." + }, + "description": { + "type": "string", + "description": "An optional help text providing additional information about the exception filter. This string is typically shown as a hover and must be translated." + }, + "default": { + "type": "boolean", + "description": "Initial value of the filter option. If not specified a value 'false' is assumed." + }, + "supportsCondition": { + "type": "boolean", + "description": "Controls whether a condition can be specified for this filter option. If false or missing, a condition can not be set." + }, + "conditionDescription": { + "type": "string", + "description": "An optional help text providing information about the condition. This string is shown as the placeholder text for a text box and must be translated." + } + }, + "required": [ "filter", "label" ] + }, + + "Message": { + "type": "object", + "description": "A structured message object. Used to return errors from requests.", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the message." + }, + "format": { + "type": "string", + "description": "A format string for the message. Embedded variables have the form '{name}'.\nIf variable name starts with an underscore character, the variable does not contain user data (PII) and can be safely used for telemetry purposes." + }, + "variables": { + "type": "object", + "description": "An object used as a dictionary for looking up the variables in the format string.", + "additionalProperties": { + "type": "string", + "description": "Values must be strings." + } + }, + "sendTelemetry": { + "type": "boolean", + "description": "If true send to telemetry." + }, + "showUser": { + "type": "boolean", + "description": "If true show user." + }, + "url": { + "type": "string", + "description": "An optional url where additional information about this message can be found." + }, + "urlLabel": { + "type": "string", + "description": "An optional label that is presented to the user as the UI for opening the url." + } + }, + "required": [ "id", "format" ] + }, + + "Module": { + "type": "object", + "description": "A Module object represents a row in the modules view.\nTwo attributes are mandatory: an id identifies a module in the modules view and is used in a ModuleEvent for identifying a module for adding, updating or deleting.\nThe name is used to minimally render the module in the UI.\n\nAdditional attributes can be added to the module. They will show up in the module View if they have a corresponding ColumnDescriptor.\n\nTo avoid an unnecessary proliferation of additional attributes with similar semantics but different names\nwe recommend to re-use attributes from the 'recommended' list below first, and only introduce new attributes if nothing appropriate could be found.", + "properties": { + "id": { + "type": ["integer", "string"], + "description": "Unique identifier for the module." + }, + "name": { + "type": "string", + "description": "A name of the module." + }, + "path": { + "type": "string", + "description": "optional but recommended attributes.\nalways try to use these first before introducing additional attributes.\n\nLogical full path to the module. The exact definition is implementation defined, but usually this would be a full path to the on-disk file for the module." + }, + "isOptimized": { + "type": "boolean", + "description": "True if the module is optimized." + }, + "isUserCode": { + "type": "boolean", + "description": "True if the module is considered 'user code' by a debugger that supports 'Just My Code'." + }, + "version": { + "type": "string", + "description": "Version of Module." + }, + "symbolStatus": { + "type": "string", + "description": "User understandable description of if symbols were found for the module (ex: 'Symbols Loaded', 'Symbols not found', etc." + }, + "symbolFilePath": { + "type": "string", + "description": "Logical full path to the symbol file. The exact definition is implementation defined." + }, + "dateTimeStamp": { + "type": "string", + "description": "Module created or modified." + }, + "addressRange": { + "type": "string", + "description": "Address range covered by this module." + } + }, + "required": [ "id", "name" ] + }, + + "ColumnDescriptor": { + "type": "object", + "description": "A ColumnDescriptor specifies what module attribute to show in a column of the ModulesView, how to format it,\nand what the column's label should be.\nIt is only used if the underlying UI actually supports this level of customization.", + "properties": { + "attributeName": { + "type": "string", + "description": "Name of the attribute rendered in this column." + }, + "label": { + "type": "string", + "description": "Header UI label of column." + }, + "format": { + "type": "string", + "description": "Format to use for the rendered values in this column. TBD how the format strings looks like." + }, + "type": { + "type": "string", + "enum": [ "string", "number", "boolean", "unixTimestampUTC" ], + "description": "Datatype of values in this column. Defaults to 'string' if not specified." + }, + "width": { + "type": "integer", + "description": "Width of this column in characters (hint only)." + } + }, + "required": [ "attributeName", "label"] + }, + + "ModulesViewDescriptor": { + "type": "object", + "description": "The ModulesViewDescriptor is the container for all declarative configuration options of a ModuleView.\nFor now it only specifies the columns to be shown in the modules view.", + "properties": { + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/ColumnDescriptor" + } + } + }, + "required": [ "columns" ] + }, + + "Thread": { + "type": "object", + "description": "A Thread", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for the thread." + }, + "name": { + "type": "string", + "description": "A name of the thread." + } + }, + "required": [ "id", "name" ] + }, + + "Source": { + "type": "object", + "description": "A Source is a descriptor for source code.\nIt is returned from the debug adapter as part of a StackFrame and it is used by clients when specifying breakpoints.", + "properties": { + "name": { + "type": "string", + "description": "The short name of the source. Every source returned from the debug adapter has a name.\nWhen sending a source to the debug adapter this name is optional." + }, + "path": { + "type": "string", + "description": "The path of the source to be shown in the UI.\nIt is only used to locate and load the content of the source if no sourceReference is specified (or its value is 0)." + }, + "sourceReference": { + "type": "integer", + "description": "If sourceReference > 0 the contents of the source must be retrieved through the SourceRequest (even if a path is specified).\nA sourceReference is only valid for a session, so it must not be used to persist a source.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "presentationHint": { + "type": "string", + "description": "An optional hint for how to present the source in the UI.\nA value of 'deemphasize' can be used to indicate that the source is not available or that it is skipped on stepping.", + "enum": [ "normal", "emphasize", "deemphasize" ] + }, + "origin": { + "type": "string", + "description": "The (optional) origin of this source: possible values 'internal module', 'inlined content from source map', etc." + }, + "sources": { + "type": "array", + "items": { + "$ref": "#/definitions/Source" + }, + "description": "An optional list of sources that are related to this source. These may be the source that generated this source." + }, + "adapterData": { + "type": [ "array", "boolean", "integer", "null", "number", "object", "string" ], + "description": "Optional data that a debug adapter might want to loop through the client.\nThe client should leave the data intact and persist it across sessions. The client should not interpret the data." + }, + "checksums": { + "type": "array", + "items": { + "$ref": "#/definitions/Checksum" + }, + "description": "The checksums associated with this file." + } + } + }, + + "StackFrame": { + "type": "object", + "description": "A Stackframe contains the source location.", + "properties": { + "id": { + "type": "integer", + "description": "An identifier for the stack frame. It must be unique across all threads.\nThis id can be used to retrieve the scopes of the frame with the 'scopesRequest' or to restart the execution of a stackframe." + }, + "name": { + "type": "string", + "description": "The name of the stack frame, typically a method name." + }, + "source": { + "$ref": "#/definitions/Source", + "description": "The optional source of the frame." + }, + "line": { + "type": "integer", + "description": "The line within the file of the frame. If source is null or doesn't exist, line is 0 and must be ignored." + }, + "column": { + "type": "integer", + "description": "The column within the line. If source is null or doesn't exist, column is 0 and must be ignored." + }, + "endLine": { + "type": "integer", + "description": "An optional end line of the range covered by the stack frame." + }, + "endColumn": { + "type": "integer", + "description": "An optional end column of the range covered by the stack frame." + }, + "canRestart": { + "type": "boolean", + "description": "Indicates whether this frame can be restarted with the 'restart' request. Clients should only use this if the debug adapter supports the 'restart' request (capability 'supportsRestartRequest' is true)." + }, + "instructionPointerReference": { + "type": "string", + "description": "Optional memory reference for the current instruction pointer in this frame." + }, + "moduleId": { + "type": ["integer", "string"], + "description": "The module associated with this frame, if any." + }, + "presentationHint": { + "type": "string", + "enum": [ "normal", "label", "subtle" ], + "description": "An optional hint for how to present this frame in the UI.\nA value of 'label' can be used to indicate that the frame is an artificial frame that is used as a visual label or separator. A value of 'subtle' can be used to change the appearance of a frame in a 'subtle' way." + } + }, + "required": [ "id", "name", "line", "column" ] + }, + + "Scope": { + "type": "object", + "description": "A Scope is a named container for variables. Optionally a scope can map to a source or a range within a source.", + "properties": { + "name": { + "type": "string", + "description": "Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This string is shown in the UI as is and can be translated." + }, + "presentationHint": { + "type": "string", + "description": "An optional hint for how to present this scope in the UI. If this attribute is missing, the scope is shown with a generic UI.", + "_enum": [ "arguments", "locals", "registers" ], + "enumDescriptions": [ + "Scope contains method arguments.", + "Scope contains local variables.", + "Scope contains registers. Only a single 'registers' scope should be returned from a 'scopes' request." + ] + }, + "variablesReference": { + "type": "integer", + "description": "The variables of this scope can be retrieved by passing the value of variablesReference to the VariablesRequest." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named variables in this scope.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed variables in this scope.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks." + }, + "expensive": { + "type": "boolean", + "description": "If true, the number of variables in this scope is large or expensive to retrieve." + }, + "source": { + "$ref": "#/definitions/Source", + "description": "Optional source for this scope." + }, + "line": { + "type": "integer", + "description": "Optional start line of the range covered by this scope." + }, + "column": { + "type": "integer", + "description": "Optional start column of the range covered by this scope." + }, + "endLine": { + "type": "integer", + "description": "Optional end line of the range covered by this scope." + }, + "endColumn": { + "type": "integer", + "description": "Optional end column of the range covered by this scope." + } + }, + "required": [ "name", "variablesReference", "expensive" ] + }, + + "Variable": { + "type": "object", + "description": "A Variable is a name/value pair.\nOptionally a variable can have a 'type' that is shown if space permits or when hovering over the variable's name.\nAn optional 'kind' is used to render additional properties of the variable, e.g. different icons can be used to indicate that a variable is public or private.\nIf the value is structured (has children), a handle is provided to retrieve the children with the VariablesRequest.\nIf the number of named or indexed children is large, the numbers should be returned via the optional 'namedVariables' and 'indexedVariables' attributes.\nThe client can use this optional information to present the children in a paged UI and fetch them in chunks.", + "properties": { + "name": { + "type": "string", + "description": "The variable's name." + }, + "value": { + "type": "string", + "description": "The variable's value. This can be a multi-line text, e.g. for a function the body of a function." + }, + "type": { + "type": "string", + "description": "The type of the variable's value. Typically shown in the UI when hovering over the value.\nThis attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request." + }, + "presentationHint": { + "$ref": "#/definitions/VariablePresentationHint", + "description": "Properties of a variable that can be used to determine how to render the variable in the UI." + }, + "evaluateName": { + "type": "string", + "description": "Optional evaluatable name of this variable which can be passed to the 'EvaluateRequest' to fetch the variable's value." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the variable is structured and its children can be retrieved by passing variablesReference to the VariablesRequest." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the children in a paged UI and fetch them in chunks." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the children in a paged UI and fetch them in chunks." + }, + "memoryReference": { + "type": "string", + "description": "Optional memory reference for the variable if the variable represents executable code, such as a function pointer.\nThis attribute is only required if the client has passed the value true for the 'supportsMemoryReferences' capability of the 'initialize' request." + } + }, + "required": [ "name", "value", "variablesReference" ] + }, + + "VariablePresentationHint": { + "type": "object", + "description": "Optional properties of a variable that can be used to determine how to render the variable in the UI.", + "properties": { + "kind": { + "description": "The kind of variable. Before introducing additional values, try to use the listed values.", + "type": "string", + "_enum": [ "property", "method", "class", "data", "event", "baseClass", "innerClass", "interface", "mostDerivedClass", "virtual", "dataBreakpoint" ], + "enumDescriptions": [ + "Indicates that the object is a property.", + "Indicates that the object is a method.", + "Indicates that the object is a class.", + "Indicates that the object is data.", + "Indicates that the object is an event.", + "Indicates that the object is a base class.", + "Indicates that the object is an inner class.", + "Indicates that the object is an interface.", + "Indicates that the object is the most derived class.", + "Indicates that the object is virtual, that means it is a synthetic object introducedby the\nadapter for rendering purposes, e.g. an index range for large arrays.", + "Deprecated: Indicates that a data breakpoint is registered for the object. The 'hasDataBreakpoint' attribute should generally be used instead." + ] + }, + "attributes": { + "description": "Set of attributes represented as an array of strings. Before introducing additional values, try to use the listed values.", + "type": "array", + "items": { + "type": "string", + "_enum": [ "static", "constant", "readOnly", "rawString", "hasObjectId", "canHaveObjectId", "hasSideEffects", "hasDataBreakpoint" ], + "enumDescriptions": [ + "Indicates that the object is static.", + "Indicates that the object is a constant.", + "Indicates that the object is read only.", + "Indicates that the object is a raw string.", + "Indicates that the object can have an Object ID created for it.", + "Indicates that the object has an Object ID associated with it.", + "Indicates that the evaluation had side effects.", + "Indicates that the object has its value tracked by a data breakpoint." + ] + } + }, + "visibility": { + "description": "Visibility of variable. Before introducing additional values, try to use the listed values.", + "type": "string", + "_enum": [ "public", "private", "protected", "internal", "final" ] + } + } + }, + + "BreakpointLocation": { + "type": "object", + "description": "Properties of a breakpoint location returned from the 'breakpointLocations' request.", + "properties": { + "line": { + "type": "integer", + "description": "Start line of breakpoint location." + }, + "column": { + "type": "integer", + "description": "Optional start column of breakpoint location." + }, + "endLine": { + "type": "integer", + "description": "Optional end line of breakpoint location if the location covers a range." + }, + "endColumn": { + "type": "integer", + "description": "Optional end column of breakpoint location if the location covers a range." + } + }, + "required": [ "line" ] + }, + + "SourceBreakpoint": { + "type": "object", + "description": "Properties of a breakpoint or logpoint passed to the setBreakpoints request.", + "properties": { + "line": { + "type": "integer", + "description": "The source line of the breakpoint or logpoint." + }, + "column": { + "type": "integer", + "description": "An optional source column of the breakpoint." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional breakpoints.\nIt is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true." + }, + "hitCondition": { + "type": "string", + "description": "An optional expression that controls how many hits of the breakpoint are ignored.\nThe backend is expected to interpret the expression as needed.\nThe attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true." + }, + "logMessage": { + "type": "string", + "description": "If this attribute exists and is non-empty, the backend must not 'break' (stop)\nbut log the message instead. Expressions within {} are interpolated.\nThe attribute is only honored by a debug adapter if the capability 'supportsLogPoints' is true." + } + }, + "required": [ "line" ] + }, + + "FunctionBreakpoint": { + "type": "object", + "description": "Properties of a breakpoint passed to the setFunctionBreakpoints request.", + "properties": { + "name": { + "type": "string", + "description": "The name of the function." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional breakpoints.\nIt is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true." + }, + "hitCondition": { + "type": "string", + "description": "An optional expression that controls how many hits of the breakpoint are ignored.\nThe backend is expected to interpret the expression as needed.\nThe attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true." + } + }, + "required": [ "name" ] + }, + + "DataBreakpointAccessType": { + "type": "string", + "description": "This enumeration defines all possible access types for data breakpoints.", + "enum": [ "read", "write", "readWrite" ] + }, + + "DataBreakpoint": { + "type": "object", + "description": "Properties of a data breakpoint passed to the setDataBreakpoints request.", + "properties": { + "dataId": { + "type": "string", + "description": "An id representing the data. This id is returned from the dataBreakpointInfo request." + }, + "accessType": { + "$ref": "#/definitions/DataBreakpointAccessType", + "description": "The access type of the data." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional breakpoints." + }, + "hitCondition": { + "type": "string", + "description": "An optional expression that controls how many hits of the breakpoint are ignored.\nThe backend is expected to interpret the expression as needed." + } + }, + "required": [ "dataId" ] + }, + + "InstructionBreakpoint": { + "type": "object", + "description": "Properties of a breakpoint passed to the setInstructionBreakpoints request", + "properties": { + "instructionReference": { + "type": "string", + "description": "The instruction reference of the breakpoint.\nThis should be a memory or instruction pointer reference from an EvaluateResponse, Variable, StackFrame, GotoTarget, or Breakpoint." + }, + "offset": { + "type": "integer", + "description": "An optional offset from the instruction reference.\nThis can be negative." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional breakpoints.\nIt is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true." + }, + "hitCondition": { + "type": "string", + "description": "An optional expression that controls how many hits of the breakpoint are ignored.\nThe backend is expected to interpret the expression as needed.\nThe attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true." + } + }, + "required": [ "instructionReference" ] + }, + + "Breakpoint": { + "type": "object", + "description": "Information about a Breakpoint created in setBreakpoints, setFunctionBreakpoints, setInstructionBreakpoints, or setDataBreakpoints.", + "properties": { + "id": { + "type": "integer", + "description": "An optional identifier for the breakpoint. It is needed if breakpoint events are used to update or remove breakpoints." + }, + "verified": { + "type": "boolean", + "description": "If true breakpoint could be set (but not necessarily at the desired location)." + }, + "message": { + "type": "string", + "description": "An optional message about the state of the breakpoint.\nThis is shown to the user and can be used to explain why a breakpoint could not be verified." + }, + "source": { + "$ref": "#/definitions/Source", + "description": "The source where the breakpoint is located." + }, + "line": { + "type": "integer", + "description": "The start line of the actual range covered by the breakpoint." + }, + "column": { + "type": "integer", + "description": "An optional start column of the actual range covered by the breakpoint." + }, + "endLine": { + "type": "integer", + "description": "An optional end line of the actual range covered by the breakpoint." + }, + "endColumn": { + "type": "integer", + "description": "An optional end column of the actual range covered by the breakpoint.\nIf no end line is given, then the end column is assumed to be in the start line." + }, + "instructionReference": { + "type": "string", + "description": "An optional memory reference to where the breakpoint is set." + }, + "offset": { + "type": "integer", + "description": "An optional offset from the instruction reference.\nThis can be negative." + } + }, + "required": [ "verified" ] + }, + + "SteppingGranularity": { + "type": "string", + "description": "The granularity of one 'step' in the stepping requests 'next', 'stepIn', 'stepOut', and 'stepBack'.", + "enum": [ "statement", "line", "instruction" ], + "enumDescriptions": [ + "The step should allow the program to run until the current statement has finished executing.\nThe meaning of a statement is determined by the adapter and it may be considered equivalent to a line.\nFor example 'for(int i = 0; i < 10; i++) could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'.", + "The step should allow the program to run until the current source line has executed.", + "The step should allow one instruction to execute (e.g. one x86 instruction)." + ] + }, + + "StepInTarget": { + "type": "object", + "description": "A StepInTarget can be used in the 'stepIn' request and determines into which single target the stepIn request should step.", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for a stepIn target." + }, + "label": { + "type": "string", + "description": "The name of the stepIn target (shown in the UI)." + } + }, + "required": [ "id", "label" ] + }, + + "GotoTarget": { + "type": "object", + "description": "A GotoTarget describes a code location that can be used as a target in the 'goto' request.\nThe possible goto targets can be determined via the 'gotoTargets' request.", + "properties": { + "id": { + "type": "integer", + "description": "Unique identifier for a goto target. This is used in the goto request." + }, + "label": { + "type": "string", + "description": "The name of the goto target (shown in the UI)." + }, + "line": { + "type": "integer", + "description": "The line of the goto target." + }, + "column": { + "type": "integer", + "description": "An optional column of the goto target." + }, + "endLine": { + "type": "integer", + "description": "An optional end line of the range covered by the goto target." + }, + "endColumn": { + "type": "integer", + "description": "An optional end column of the range covered by the goto target." + }, + "instructionPointerReference": { + "type": "string", + "description": "Optional memory reference for the instruction pointer value represented by this target." + } + }, + "required": [ "id", "label", "line" ] + }, + + "CompletionItem": { + "type": "object", + "description": "CompletionItems are the suggestions returned from the CompletionsRequest.", + "properties": { + "label": { + "type": "string", + "description": "The label of this completion item. By default this is also the text that is inserted when selecting this completion." + }, + "text": { + "type": "string", + "description": "If text is not falsy then it is inserted instead of the label." + }, + "sortText": { + "type": "string", + "description": "A string that should be used when comparing this item with other items. When `falsy` the label is used." + }, + "type": { + "$ref": "#/definitions/CompletionItemType", + "description": "The item's type. Typically the client uses this information to render the item in the UI with an icon." + }, + "start": { + "type": "integer", + "description": "This value determines the location (in the CompletionsRequest's 'text' attribute) where the completion text is added.\nIf missing the text is added at the location specified by the CompletionsRequest's 'column' attribute." + }, + "length": { + "type": "integer", + "description": "This value determines how many characters are overwritten by the completion text.\nIf missing the value 0 is assumed which results in the completion text being inserted." + }, + "selectionStart": { + "type": "integer", + "description": "Determines the start of the new selection after the text has been inserted (or replaced).\nThe start position must in the range 0 and length of the completion text.\nIf omitted the selection starts at the end of the completion text." + }, + "selectionLength": { + "type": "integer", + "description": "Determines the length of the new selection after the text has been inserted (or replaced).\nThe selection can not extend beyond the bounds of the completion text.\nIf omitted the length is assumed to be 0." + } + }, + "required": [ "label" ] + }, + + "CompletionItemType": { + "type": "string", + "description": "Some predefined types for the CompletionItem. Please note that not all clients have specific icons for all of them.", + "enum": [ "method", "function", "constructor", "field", "variable", "class", "interface", "module", "property", "unit", "value", "enum", "keyword", "snippet", "text", "color", "file", "reference", "customcolor" ] + }, + + "ChecksumAlgorithm": { + "type": "string", + "description": "Names of checksum algorithms that may be supported by a debug adapter.", + "enum": [ "MD5", "SHA1", "SHA256", "timestamp" ] + }, + + "Checksum": { + "type": "object", + "description": "The checksum of an item calculated by the specified algorithm.", + "properties": { + "algorithm": { + "$ref": "#/definitions/ChecksumAlgorithm", + "description": "The algorithm used to calculate this checksum." + }, + "checksum": { + "type": "string", + "description": "Value of the checksum." + } + }, + "required": [ "algorithm", "checksum" ] + }, + + "ValueFormat": { + "type": "object", + "description": "Provides formatting information for a value.", + "properties": { + "hex": { + "type": "boolean", + "description": "Display the value in hex." + } + } + }, + + "StackFrameFormat": { + "allOf": [ { "$ref": "#/definitions/ValueFormat" }, { + "type": "object", + "description": "Provides formatting information for a stack frame.", + "properties": { + "parameters": { + "type": "boolean", + "description": "Displays parameters for the stack frame." + }, + "parameterTypes": { + "type": "boolean", + "description": "Displays the types of parameters for the stack frame." + }, + "parameterNames": { + "type": "boolean", + "description": "Displays the names of parameters for the stack frame." + }, + "parameterValues": { + "type": "boolean", + "description": "Displays the values of parameters for the stack frame." + }, + "line": { + "type": "boolean", + "description": "Displays the line number of the stack frame." + }, + "module": { + "type": "boolean", + "description": "Displays the module of the stack frame." + }, + "includeAll": { + "type": "boolean", + "description": "Includes all stack frames, including those the debug adapter might otherwise hide." + } + } + }] + }, + + "ExceptionFilterOptions": { + "type": "object", + "description": "An ExceptionFilterOptions is used to specify an exception filter together with a condition for the setExceptionsFilter request.", + "properties": { + "filterId": { + "type": "string", + "description": "ID of an exception filter returned by the 'exceptionBreakpointFilters' capability." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional exceptions.\nThe exception will break into the debugger if the result of the condition is true." + } + }, + "required": [ "filterId" ] + }, + + "ExceptionOptions": { + "type": "object", + "description": "An ExceptionOptions assigns configuration options to a set of exceptions.", + "properties": { + "path": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionPathSegment" + }, + "description": "A path that selects a single or multiple exceptions in a tree. If 'path' is missing, the whole tree is selected.\nBy convention the first segment of the path is a category that is used to group exceptions in the UI." + }, + "breakMode": { + "$ref": "#/definitions/ExceptionBreakMode", + "description": "Condition when a thrown exception should result in a break." + } + }, + "required": [ "breakMode" ] + }, + + "ExceptionBreakMode": { + "type": "string", + "description": "This enumeration defines all possible conditions when a thrown exception should result in a break.\nnever: never breaks,\nalways: always breaks,\nunhandled: breaks when exception unhandled,\nuserUnhandled: breaks if the exception is not handled by user code.", + "enum": [ "never", "always", "unhandled", "userUnhandled" ] + }, + + "ExceptionPathSegment": { + "type": "object", + "description": "An ExceptionPathSegment represents a segment in a path that is used to match leafs or nodes in a tree of exceptions.\nIf a segment consists of more than one name, it matches the names provided if 'negate' is false or missing or\nit matches anything except the names provided if 'negate' is true.", + "properties": { + "negate": { + "type": "boolean", + "description": "If false or missing this segment matches the names provided, otherwise it matches anything except the names provided." + }, + "names": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Depending on the value of 'negate' the names that should match or not match." + } + }, + "required": [ "names" ] + }, + + "ExceptionDetails": { + "type": "object", + "description": "Detailed information about an exception that has occurred.", + "properties": { + "message": { + "type": "string", + "description": "Message contained in the exception." + }, + "typeName": { + "type": "string", + "description": "Short type name of the exception object." + }, + "fullTypeName": { + "type": "string", + "description": "Fully-qualified type name of the exception object." + }, + "evaluateName": { + "type": "string", + "description": "Optional expression that can be evaluated in the current scope to obtain the exception object." + }, + "stackTrace": { + "type": "string", + "description": "Stack trace at the time the exception was thrown." + }, + "innerException": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionDetails" + }, + "description": "Details of the exception contained by this exception, if any." + } + } + }, + + "DisassembledInstruction": { + "type": "object", + "description": "Represents a single disassembled instruction.", + "properties": { + "address": { + "type": "string", + "description": "The address of the instruction. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise." + }, + "instructionBytes": { + "type": "string", + "description": "Optional raw bytes representing the instruction and its operands, in an implementation-defined format." + }, + "instruction": { + "type": "string", + "description": "Text representing the instruction and its operands, in an implementation-defined format." + }, + "symbol": { + "type": "string", + "description": "Name of the symbol that corresponds with the location of this instruction, if any." + }, + "location": { + "$ref": "#/definitions/Source", + "description": "Source location that corresponds to this instruction, if any.\nShould always be set (if available) on the first instruction returned,\nbut can be omitted afterwards if this instruction maps to the same source file as the previous instruction." + }, + "line": { + "type": "integer", + "description": "The line within the source location that corresponds to this instruction, if any." + }, + "column": { + "type": "integer", + "description": "The column within the line that corresponds to this instruction, if any." + }, + "endLine": { + "type": "integer", + "description": "The end line of the range that corresponds to this instruction, if any." + }, + "endColumn": { + "type": "integer", + "description": "The end column of the range that corresponds to this instruction, if any." + } + }, + "required": [ "address", "instruction" ] + }, + + "InvalidatedAreas": { + "type": "string", + "description": "Logical areas that can be invalidated by the 'invalidated' event.", + "_enum": [ "all", "stacks", "threads", "variables" ], + "enumDescriptions": [ + "All previously fetched data has become invalid and needs to be refetched.", + "Previously fetched stack related data has become invalid and needs to be refetched.", + "Previously fetched thread related data has become invalid and needs to be refetched.", + "Previously fetched variable data has become invalid and needs to be refetched." + ] + } + + } +} diff --git a/_pydevd_bundle/_debug_adapter/debugProtocolCustom.json b/_pydevd_bundle/_debug_adapter/debugProtocolCustom.json new file mode 100644 index 0000000..a0a9b87 --- /dev/null +++ b/_pydevd_bundle/_debug_adapter/debugProtocolCustom.json @@ -0,0 +1,325 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Custom Debug Adapter Protocol", + "description": "Extension to the DAP to support additional features.", + "type": "object", + + + "definitions": { + + "SetDebuggerPropertyRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request can be used to enable or disable debugger features.", + "properties": { + "command": { + "type": "string", + "enum": [ "setDebuggerProperty" ] + }, + "arguments": { + "$ref": "#/definitions/SetDebuggerPropertyArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetDebuggerPropertyArguments": { + "type": "object", + "description": "Arguments for 'setDebuggerProperty' request.", + "properties": { + "ideOS": { + "type": [ "string" ], + "description": "OS where the ide is running. Supported values [Windows, Linux]" + }, + "dontTraceStartPatterns": { + "type": [ "array" ], + "description": "Patterns to match with the start of the file paths. Matching paths will be added to a list of file where trace is ignored." + }, + "dontTraceEndPatterns": { + "type": [ "array" ], + "description": "Patterns to match with the end of the file paths. Matching paths will be added to a list of file where trace is ignored." + }, + "skipSuspendOnBreakpointException": { + "type": [ "array" ], + "description": "List of exceptions that should be skipped when doing condition evaluations." + }, + "skipPrintBreakpointException": { + "type": [ "array" ], + "description": "List of exceptions that should skip printing to stderr when doing condition evaluations." + }, + "multiThreadsSingleNotification": { + "type": [ "boolean" ], + "description": "If false then a notification is generated for each thread event. If true a single event is gnenerated, and all threads follow that behavior." + } + } + }, + "SetDebuggerPropertyResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'setDebuggerProperty' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "PydevdInputRequestedEvent": { + "allOf": [ { "$ref": "#/definitions/Event" }, { + "type": "object", + "description": "The event indicates input was requested by debuggee.", + "properties": { + "event": { + "type": "string", + "enum": [ "pydevdInputRequested" ] + } + }, + "required": [ "event" ] + }] + }, + + "SetPydevdSourceMapRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": [ + "Sets multiple PydevdSourceMap for a single source and clears all previous PydevdSourceMap in that source.", + "i.e.: Maps paths and lines in a 1:N mapping (use case: map a single file in the IDE to multiple IPython cells).", + "To clear all PydevdSourceMap for a source, specify an empty array.", + "Interaction with breakpoints: When a new mapping is sent, breakpoints that match the source (or previously matched a source) are reapplied.", + "Interaction with launch pathMapping: both mappings are independent. This mapping is applied after the launch pathMapping." + ], + "properties": { + "command": { + "type": "string", + "enum": [ "setPydevdSourceMap" ] + }, + "arguments": { + "$ref": "#/definitions/SetPydevdSourceMapArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "SetPydevdSourceMapArguments": { + "type": "object", + "description": "Arguments for 'setPydevdSourceMap' request.", + "properties": { + "source": { + "$ref": "#/definitions/Source", + "description": "The source location of the PydevdSourceMap; 'source.path' must be specified (e.g.: for an ipython notebook this could be something as /home/notebook/note.py)." + }, + "pydevdSourceMaps": { + "type": "array", + "items": { + "$ref": "#/definitions/PydevdSourceMap" + }, + "description": "The PydevdSourceMaps to be set to the given source (provide an empty array to clear the source mappings for a given path)." + } + }, + "required": [ "source", "pydevdSourceMap" ] + }, + "SetPydevdSourceMapResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'setPydevdSourceMap' request. This is just an acknowledgement, so no body field is required." + }] + }, + + "PydevdSourceMap": { + "type": "object", + "description": "Information that allows mapping a local line to a remote source/line.", + "properties": { + "line": { + "type": "integer", + "description": "The local line to which the mapping should map to (e.g.: for an ipython notebook this would be the first line of the cell in the file)." + }, + "endLine": { + "type": "integer", + "description": "The end line." + }, + "runtimeSource": { + "$ref": "#/definitions/Source", + "description": "The path that the user has remotely -- 'source.path' must be specified (e.g.: for an ipython notebook this could be something as '')" + }, + "runtimeLine": { + "type": "integer", + "description": "The remote line to which the mapping should map to (e.g.: for an ipython notebook this would be always 1 as it'd map the start of the cell)." + } + }, + "required": ["line", "endLine", "runtimeSource", "runtimeLine"] + }, + + "PydevdSystemInfoRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "The request can be used retrieve system information, python version, etc.", + "properties": { + "command": { + "type": "string", + "enum": [ "pydevdSystemInfo" ] + }, + "arguments": { + "$ref": "#/definitions/PydevdSystemInfoArguments" + } + }, + "required": [ "command" ] + }] + }, + "PydevdSystemInfoArguments": { + "type": "object", + "description": "Arguments for 'pydevdSystemInfo' request." + }, + "PydevdSystemInfoResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'pydevdSystemInfo' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "python": { + "$ref": "#/definitions/PydevdPythonInfo", + "description": "Information about the python version running in the current process." + }, + "platform": { + "$ref": "#/definitions/PydevdPlatformInfo", + "description": "Information about the plarforn on which the current process is running." + }, + "process": { + "$ref": "#/definitions/PydevdProcessInfo", + "description": "Information about the current process." + }, + "pydevd": { + "$ref": "#/definitions/PydevdInfo", + "description": "Information about pydevd." + } + }, + "required": [ "python", "platform", "process", "pydevd" ] + } + }, + "required": [ "body" ] + }] + }, + + "PydevdPythonInfo": { + "type": "object", + "description": "This object contains python version and implementation details.", + "properties": { + "version": { + "type": "string", + "description": "Python version as a string in semver format: ..." + }, + "implementation": { + "$ref": "#/definitions/PydevdPythonImplementationInfo", + "description": "Python version as a string in this format ..." + } + } + }, + "PydevdPythonImplementationInfo": { + "type": "object", + "description": "This object contains python implementation details.", + "properties": { + "name": { + "type": "string", + "description": "Python implementation name." + }, + "version": { + "type": "string", + "description": "Python version as a string in semver format: ..." + }, + "description": { + "type": "string", + "description": "Optional description for this python implementation." + } + } + }, + "PydevdPlatformInfo": { + "type": "object", + "description": "This object contains python version and implementation details.", + "properties": { + "name": { + "type": "string", + "description": "Name of the platform as returned by 'sys.platform'." + } + } + }, + "PydevdProcessInfo": { + "type": "object", + "description": "This object contains python process details.", + "properties": { + "pid": { + "type": "integer", + "description": "Process ID for the current process." + }, + "ppid": { + "type": "integer", + "description": "Parent Process ID for the current process." + }, + "executable": { + "type": "string", + "description": "Path to the executable as returned by 'sys.executable'." + }, + "bitness": { + "type": "integer", + "description": "Integer value indicating the bitness of the current process." + } + } + }, + "PydevdInfo": { + "type": "object", + "description": "This object contains details on pydevd.", + "properties": { + "usingCython": { + "type": "boolean", + "description": "Specifies whether the cython native module is being used." + }, + "usingFrameEval": { + "type": "boolean", + "description": "Specifies whether the frame eval native module is being used." + } + } + }, + "PydevdAuthorizeRequest": { + "allOf": [ { "$ref": "#/definitions/Request" }, { + "type": "object", + "description": "A request to authorize the ide to start accepting commands.", + "properties": { + "command": { + "type": "string", + "enum": [ "pydevdAuthorize" ] + }, + "arguments": { + "$ref": "#/definitions/PydevdAuthorizeArguments" + } + }, + "required": [ "command", "arguments" ] + }] + }, + "PydevdAuthorizeArguments": { + "type": "object", + "description": "Arguments for 'pydevdAuthorize' request.", + "properties": { + "debugServerAccessToken": { + "type": "string" , + "description": "The access token to access the debug server." + } + }, + "required": [ "command" ] + }, + "PydevdAuthorizeResponse": { + "allOf": [ { "$ref": "#/definitions/Response" }, { + "type": "object", + "description": "Response to 'pydevdAuthorize' request.", + "properties": { + "body": { + "type": "object", + "properties": { + "clientAccessToken": { + "type": "string", + "description": "The access token to access the client (i.e.: usually the IDE)." + } + }, + "required": [ "clientAccessToken" ] + } + }, + "required": [ "body" ] + }] + } + } +} \ No newline at end of file diff --git a/_pydevd_bundle/_debug_adapter/pydevd_base_schema.py b/_pydevd_bundle/_debug_adapter/pydevd_base_schema.py new file mode 100644 index 0000000..0cbb3f5 --- /dev/null +++ b/_pydevd_bundle/_debug_adapter/pydevd_base_schema.py @@ -0,0 +1,147 @@ +from _pydevd_bundle._debug_adapter.pydevd_schema_log import debug_exception +import json +import itertools +from functools import partial + + +class BaseSchema(object): + + @staticmethod + def initialize_ids_translation(): + BaseSchema._dap_id_to_obj_id = {0:0, None:None} + BaseSchema._obj_id_to_dap_id = {0:0, None:None} + BaseSchema._next_dap_id = partial(next, itertools.count(1)) + + def to_json(self): + return json.dumps(self.to_dict()) + + @staticmethod + def _translate_id_to_dap(obj_id): + if obj_id == '*': + return '*' + # Note: we don't invalidate ids, so, if some object starts using the same id + # of another object, the same id will be used. + dap_id = BaseSchema._obj_id_to_dap_id.get(obj_id) + if dap_id is None: + dap_id = BaseSchema._obj_id_to_dap_id[obj_id] = BaseSchema._next_dap_id() + BaseSchema._dap_id_to_obj_id[dap_id] = obj_id + return dap_id + + @staticmethod + def _translate_id_from_dap(dap_id): + if dap_id == '*': + return '*' + try: + return BaseSchema._dap_id_to_obj_id[dap_id] + except: + raise KeyError('Wrong ID sent from the client: %s' % (dap_id,)) + + @staticmethod + def update_dict_ids_to_dap(dct): + return dct + + @staticmethod + def update_dict_ids_from_dap(dct): + return dct + + +BaseSchema.initialize_ids_translation() + +_requests_to_types = {} +_responses_to_types = {} +_event_to_types = {} +_all_messages = {} + + +def register(cls): + _all_messages[cls.__name__] = cls + return cls + + +def register_request(command): + + def do_register(cls): + _requests_to_types[command] = cls + return cls + + return do_register + + +def register_response(command): + + def do_register(cls): + _responses_to_types[command] = cls + return cls + + return do_register + + +def register_event(event): + + def do_register(cls): + _event_to_types[event] = cls + return cls + + return do_register + + +def from_dict(dct, update_ids_from_dap=False): + msg_type = dct.get('type') + if msg_type is None: + raise ValueError('Unable to make sense of message: %s' % (dct,)) + + if msg_type == 'request': + to_type = _requests_to_types + use = dct['command'] + + elif msg_type == 'response': + to_type = _responses_to_types + use = dct['command'] + + else: + to_type = _event_to_types + use = dct['event'] + + cls = to_type.get(use) + if cls is None: + raise ValueError('Unable to create message from dict: %s. %s not in %s' % (dct, use, sorted(to_type.keys()))) + try: + return cls(update_ids_from_dap=update_ids_from_dap, **dct) + except: + msg = 'Error creating %s from %s' % (cls, dct) + debug_exception(msg) + raise + + +def from_json(json_msg, update_ids_from_dap=False, on_dict_loaded=lambda dct:None): + if isinstance(json_msg, bytes): + json_msg = json_msg.decode('utf-8') + + as_dict = json.loads(json_msg) + on_dict_loaded(as_dict) + try: + return from_dict(as_dict, update_ids_from_dap=update_ids_from_dap) + except: + if as_dict.get('type') == 'response' and not as_dict.get('success'): + # Error messages may not have required body (return as a generic Response). + Response = _all_messages['Response'] + return Response(**as_dict) + else: + raise + + +def get_response_class(request): + if request.__class__ == dict: + return _responses_to_types[request['command']] + return _responses_to_types[request.command] + + +def build_response(request, kwargs=None): + if kwargs is None: + kwargs = {'success':True} + else: + if 'success' not in kwargs: + kwargs['success'] = True + response_class = _responses_to_types[request.command] + kwargs.setdefault('seq', -1) # To be overwritten before sending + return response_class(command=request.command, request_seq=request.seq, **kwargs) diff --git a/_pydevd_bundle/_debug_adapter/pydevd_schema.py b/_pydevd_bundle/_debug_adapter/pydevd_schema.py new file mode 100644 index 0000000..3159f63 --- /dev/null +++ b/_pydevd_bundle/_debug_adapter/pydevd_schema.py @@ -0,0 +1,19514 @@ +# coding: utf-8 +# Automatically generated code. +# Do not edit manually. +# Generated by running: __main__pydevd_gen_debug_adapter_protocol.py +from .pydevd_base_schema import BaseSchema, register, register_request, register_response, register_event + + +@register +class ProtocolMessage(BaseSchema): + """ + Base class of requests, responses, and events. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "description": "Message type.", + "_enum": [ + "request", + "response", + "event" + ] + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, type, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: Message type. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = type + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + seq = self.seq + dct = { + 'type': type, + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class Request(BaseSchema): + """ + A client or debug adapter initiated request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "description": "The command to execute." + }, + "arguments": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Object containing arguments for the command." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, command, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: The command to execute. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] arguments: Object containing arguments for the command. + """ + self.type = 'request' + self.command = command + self.seq = seq + self.arguments = arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments + dct.update(self.kwargs) + return dct + + +@register +class Event(BaseSchema): + """ + A debug adapter initiated event. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "description": "Type of event." + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Event-specific information." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, event, seq=-1, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: Type of event. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Event-specific information. + """ + self.type = 'event' + self.event = event + self.seq = seq + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + seq = self.seq + body = self.body + dct = { + 'type': type, + 'event': event, + 'seq': seq, + } + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register +class Response(BaseSchema): + """ + Response for a request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_response('error') +@register +class ErrorResponse(BaseSchema): + """ + On error (whenever 'success' is false), the body can provide more details. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "error": { + "$ref": "#/definitions/Message", + "description": "An optional, structured error message." + } + } + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param ErrorResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = ErrorResponseBody() + else: + self.body = ErrorResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ErrorResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('cancel') +@register +class CancelRequest(BaseSchema): + """ + The 'cancel' request is used by the frontend in two situations: + + - to indicate that it is no longer interested in the result produced by a specific request issued + earlier + + - to cancel a progress sequence. Clients should only call this request if the capability + 'supportsCancelRequest' is true. + + This request has a hint characteristic: a debug adapter can only be expected to make a 'best effort' + in honouring this request but there are no guarantees. + + The 'cancel' request may return an error if it could not cancel an operation but a frontend should + refrain from presenting this error to end users. + + A frontend client should only call this request if the capability 'supportsCancelRequest' is true. + + The request that got canceled still needs to send a response back. This can either be a normal + result ('success' attribute true) + + or an error response ('success' attribute false and the 'message' set to 'cancelled'). + + Returning partial results from a cancelled request is possible but please note that a frontend + client has no generic way for detecting that a response is partial or not. + + The progress that got cancelled still needs to send a 'progressEnd' event back. + + A client should not assume that progress just got cancelled after sending the 'cancel' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "cancel" + ] + }, + "arguments": { + "type": "CancelArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param CancelArguments arguments: + """ + self.type = 'request' + self.command = 'cancel' + self.seq = seq + if arguments is None: + self.arguments = CancelArguments() + else: + self.arguments = CancelArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != CancelArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class CancelArguments(BaseSchema): + """ + Arguments for 'cancel' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "requestId": { + "type": "integer", + "description": "The ID (attribute 'seq') of the request to cancel. If missing no request is cancelled.\nBoth a 'requestId' and a 'progressId' can be specified in one request." + }, + "progressId": { + "type": "string", + "description": "The ID (attribute 'progressId') of the progress to cancel. If missing no progress is cancelled.\nBoth a 'requestId' and a 'progressId' can be specified in one request." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, requestId=None, progressId=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer requestId: The ID (attribute 'seq') of the request to cancel. If missing no request is cancelled. + Both a 'requestId' and a 'progressId' can be specified in one request. + :param string progressId: The ID (attribute 'progressId') of the progress to cancel. If missing no progress is cancelled. + Both a 'requestId' and a 'progressId' can be specified in one request. + """ + self.requestId = requestId + self.progressId = progressId + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + requestId = self.requestId + progressId = self.progressId + dct = { + } + if requestId is not None: + dct['requestId'] = requestId + if progressId is not None: + dct['progressId'] = progressId + dct.update(self.kwargs) + return dct + + +@register_response('cancel') +@register +class CancelResponse(BaseSchema): + """ + Response to 'cancel' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_event('initialized') +@register +class InitializedEvent(BaseSchema): + """ + This event indicates that the debug adapter is ready to accept configuration requests (e.g. + SetBreakpointsRequest, SetExceptionBreakpointsRequest). + + A debug adapter is expected to send this event when it is ready to accept configuration requests + (but not before the 'initialize' request has finished). + + The sequence of events/requests is as follows: + + - adapters sends 'initialized' event (after the 'initialize' request has returned) + + - frontend sends zero or more 'setBreakpoints' requests + + - frontend sends one 'setFunctionBreakpoints' request (if capability 'supportsFunctionBreakpoints' + is true) + + - frontend sends a 'setExceptionBreakpoints' request if one or more 'exceptionBreakpointFilters' + have been defined (or if 'supportsConfigurationDoneRequest' is not defined or false) + + - frontend sends other future configuration requests + + - frontend sends one 'configurationDone' request to indicate the end of the configuration. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "initialized" + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Event-specific information." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Event-specific information. + """ + self.type = 'event' + self.event = 'initialized' + self.seq = seq + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + seq = self.seq + body = self.body + dct = { + 'type': type, + 'event': event, + 'seq': seq, + } + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_event('stopped') +@register +class StoppedEvent(BaseSchema): + """ + The event indicates that the execution of the debuggee has stopped due to some condition. + + This can be caused by a break point previously set, a stepping request has completed, by executing a + debugger statement etc. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "stopped" + ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.\nFor backward compatibility this string is shown in the UI if the 'description' attribute is missing (but it must not be translated).", + "_enum": [ + "step", + "breakpoint", + "exception", + "pause", + "entry", + "goto", + "function breakpoint", + "data breakpoint", + "instruction breakpoint" + ] + }, + "description": { + "type": "string", + "description": "The full reason for the event, e.g. 'Paused on exception'. This string is shown in the UI as is and must be translated." + }, + "threadId": { + "type": "integer", + "description": "The thread which was stopped." + }, + "preserveFocusHint": { + "type": "boolean", + "description": "A value of true hints to the frontend that this event should not change the focus." + }, + "text": { + "type": "string", + "description": "Additional information. E.g. if reason is 'exception', text contains the exception name. This string is shown in the UI." + }, + "allThreadsStopped": { + "type": "boolean", + "description": "If 'allThreadsStopped' is true, a debug adapter can announce that all threads have stopped.\n- The client should use this information to enable that all threads can be expanded to access their stacktraces.\n- If the attribute is missing or false, only the thread with the given threadId can be expanded." + }, + "hitBreakpointIds": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Ids of the breakpoints that triggered the event. In most cases there will be only a single breakpoint but here are some examples for multiple breakpoints:\n- Different types of breakpoints map to the same location.\n- Multiple source breakpoints get collapsed to the same instruction by the compiler/runtime.\n- Multiple function breakpoints with different function names map to the same location." + } + }, + "required": [ + "reason" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param StoppedEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'stopped' + if body is None: + self.body = StoppedEventBody() + else: + self.body = StoppedEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != StoppedEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('continued') +@register +class ContinuedEvent(BaseSchema): + """ + The event indicates that the execution of the debuggee has continued. + + Please note: a debug adapter is not expected to send this event in response to a request that + implies that execution continues, e.g. 'launch' or 'continue'. + + It is only necessary to send a 'continued' event if there was no previous request that implied this. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "continued" + ] + }, + "body": { + "type": "object", + "properties": { + "threadId": { + "type": "integer", + "description": "The thread which was continued." + }, + "allThreadsContinued": { + "type": "boolean", + "description": "If 'allThreadsContinued' is true, a debug adapter can announce that all threads have continued." + } + }, + "required": [ + "threadId" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param ContinuedEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'continued' + if body is None: + self.body = ContinuedEventBody() + else: + self.body = ContinuedEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ContinuedEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('exited') +@register +class ExitedEvent(BaseSchema): + """ + The event indicates that the debuggee has exited and returns its exit code. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "exited" + ] + }, + "body": { + "type": "object", + "properties": { + "exitCode": { + "type": "integer", + "description": "The exit code returned from the debuggee." + } + }, + "required": [ + "exitCode" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param ExitedEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'exited' + if body is None: + self.body = ExitedEventBody() + else: + self.body = ExitedEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ExitedEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('terminated') +@register +class TerminatedEvent(BaseSchema): + """ + The event indicates that debugging of the debuggee has terminated. This does **not** mean that the + debuggee itself has exited. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "terminated" + ] + }, + "body": { + "type": "object", + "properties": { + "restart": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "A debug adapter may set 'restart' to true (or to an arbitrary object) to request that the front end restarts the session.\nThe value is not interpreted by the client and passed unmodified as an attribute '__restart' to the 'launch' and 'attach' requests." + } + } + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param TerminatedEventBody body: + """ + self.type = 'event' + self.event = 'terminated' + self.seq = seq + if body is None: + self.body = TerminatedEventBody() + else: + self.body = TerminatedEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != TerminatedEventBody else body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + seq = self.seq + body = self.body + dct = { + 'type': type, + 'event': event, + 'seq': seq, + } + if body is not None: + dct['body'] = body.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register_event('thread') +@register +class ThreadEvent(BaseSchema): + """ + The event indicates that a thread has started or exited. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "thread" + ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.", + "_enum": [ + "started", + "exited" + ] + }, + "threadId": { + "type": "integer", + "description": "The identifier of the thread." + } + }, + "required": [ + "reason", + "threadId" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param ThreadEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'thread' + if body is None: + self.body = ThreadEventBody() + else: + self.body = ThreadEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ThreadEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('output') +@register +class OutputEvent(BaseSchema): + """ + The event indicates that the target has produced some output. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "output" + ] + }, + "body": { + "type": "object", + "properties": { + "category": { + "type": "string", + "description": "The output category. If not specified or if the category is not understand by the client, 'console' is assumed.", + "_enum": [ + "console", + "important", + "stdout", + "stderr", + "telemetry" + ], + "enumDescriptions": [ + "Show the output in the client's default message UI, e.g. a 'debug console'. This category should only be used for informational output from the debugger (as opposed to the debuggee).", + "A hint for the client to show the ouput in the client's UI for important and highly visible information, e.g. as a popup notification. This category should only be used for important messages from the debugger (as opposed to the debuggee). Since this category value is a hint, clients might ignore the hint and assume the 'console' category.", + "Show the output as normal program output from the debuggee.", + "Show the output as error program output from the debuggee.", + "Send the output to telemetry instead of showing it to the user." + ] + }, + "output": { + "type": "string", + "description": "The output to report." + }, + "group": { + "type": "string", + "description": "Support for keeping an output log organized by grouping related messages.", + "enum": [ + "start", + "startCollapsed", + "end" + ], + "enumDescriptions": [ + "Start a new group in expanded mode. Subsequent output events are members of the group and should be shown indented.\nThe 'output' attribute becomes the name of the group and is not indented.", + "Start a new group in collapsed mode. Subsequent output events are members of the group and should be shown indented (as soon as the group is expanded).\nThe 'output' attribute becomes the name of the group and is not indented.", + "End the current group and decreases the indentation of subsequent output events.\nA non empty 'output' attribute is shown as the unindented end of the group." + ] + }, + "variablesReference": { + "type": "integer", + "description": "If an attribute 'variablesReference' exists and its value is > 0, the output contains objects which can be retrieved by passing 'variablesReference' to the 'variables' request. The value should be less than or equal to 2147483647 (2^31-1)." + }, + "source": { + "$ref": "#/definitions/Source", + "description": "An optional source location where the output was produced." + }, + "line": { + "type": "integer", + "description": "An optional source location line where the output was produced." + }, + "column": { + "type": "integer", + "description": "An optional source location column where the output was produced." + }, + "data": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Optional data to report. For the 'telemetry' category the data will be sent to telemetry, for the other categories the data is shown in JSON format." + } + }, + "required": [ + "output" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param OutputEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'output' + if body is None: + self.body = OutputEventBody() + else: + self.body = OutputEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != OutputEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('breakpoint') +@register +class BreakpointEvent(BaseSchema): + """ + The event indicates that some information about a breakpoint has changed. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "breakpoint" + ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.", + "_enum": [ + "changed", + "new", + "removed" + ] + }, + "breakpoint": { + "$ref": "#/definitions/Breakpoint", + "description": "The 'id' attribute is used to find the target breakpoint and the other attributes are used as the new values." + } + }, + "required": [ + "reason", + "breakpoint" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param BreakpointEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'breakpoint' + if body is None: + self.body = BreakpointEventBody() + else: + self.body = BreakpointEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != BreakpointEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('module') +@register +class ModuleEvent(BaseSchema): + """ + The event indicates that some information about a module has changed. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "module" + ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.", + "enum": [ + "new", + "changed", + "removed" + ] + }, + "module": { + "$ref": "#/definitions/Module", + "description": "The new, changed, or removed module. In case of 'removed' only the module id is used." + } + }, + "required": [ + "reason", + "module" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param ModuleEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'module' + if body is None: + self.body = ModuleEventBody() + else: + self.body = ModuleEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ModuleEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('loadedSource') +@register +class LoadedSourceEvent(BaseSchema): + """ + The event indicates that some source has been added, changed, or removed from the set of all loaded + sources. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "loadedSource" + ] + }, + "body": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "The reason for the event.", + "enum": [ + "new", + "changed", + "removed" + ] + }, + "source": { + "$ref": "#/definitions/Source", + "description": "The new, changed, or removed source." + } + }, + "required": [ + "reason", + "source" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param LoadedSourceEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'loadedSource' + if body is None: + self.body = LoadedSourceEventBody() + else: + self.body = LoadedSourceEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != LoadedSourceEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('process') +@register +class ProcessEvent(BaseSchema): + """ + The event indicates that the debugger has begun debugging a new process. Either one that it has + launched, or one that it has attached to. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "process" + ] + }, + "body": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The logical name of the process. This is usually the full path to process's executable file. Example: /home/example/myproj/program.js." + }, + "systemProcessId": { + "type": "integer", + "description": "The system process id of the debugged process. This property will be missing for non-system processes." + }, + "isLocalProcess": { + "type": "boolean", + "description": "If true, the process is running on the same computer as the debug adapter." + }, + "startMethod": { + "type": "string", + "enum": [ + "launch", + "attach", + "attachForSuspendedLaunch" + ], + "description": "Describes how the debug engine started debugging this process.", + "enumDescriptions": [ + "Process was launched under the debugger.", + "Debugger attached to an existing process.", + "A project launcher component has launched a new process in a suspended state and then asked the debugger to attach." + ] + }, + "pointerSize": { + "type": "integer", + "description": "The size of a pointer or address for this process, in bits. This value may be used by clients when formatting addresses for display." + } + }, + "required": [ + "name" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param ProcessEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'process' + if body is None: + self.body = ProcessEventBody() + else: + self.body = ProcessEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ProcessEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('capabilities') +@register +class CapabilitiesEvent(BaseSchema): + """ + The event indicates that one or more capabilities have changed. + + Since the capabilities are dependent on the frontend and its UI, it might not be possible to change + that at random times (or too late). + + Consequently this event has a hint characteristic: a frontend can only be expected to make a 'best + effort' in honouring individual capabilities but there are no guarantees. + + Only changed capabilities need to be included, all other capabilities keep their values. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "capabilities" + ] + }, + "body": { + "type": "object", + "properties": { + "capabilities": { + "$ref": "#/definitions/Capabilities", + "description": "The set of updated capabilities." + } + }, + "required": [ + "capabilities" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param CapabilitiesEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'capabilities' + if body is None: + self.body = CapabilitiesEventBody() + else: + self.body = CapabilitiesEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != CapabilitiesEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('progressStart') +@register +class ProgressStartEvent(BaseSchema): + """ + The event signals that a long running operation is about to start and + + provides additional information for the client to set up a corresponding progress and cancellation + UI. + + The client is free to delay the showing of the UI in order to reduce flicker. + + This event should only be sent if the client has passed the value true for the + 'supportsProgressReporting' capability of the 'initialize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "progressStart" + ] + }, + "body": { + "type": "object", + "properties": { + "progressId": { + "type": "string", + "description": "An ID that must be used in subsequent 'progressUpdate' and 'progressEnd' events to make them refer to the same progress reporting.\nIDs must be unique within a debug session." + }, + "title": { + "type": "string", + "description": "Mandatory (short) title of the progress reporting. Shown in the UI to describe the long running operation." + }, + "requestId": { + "type": "integer", + "description": "The request ID that this progress report is related to. If specified a debug adapter is expected to emit\nprogress events for the long running request until the request has been either completed or cancelled.\nIf the request ID is omitted, the progress report is assumed to be related to some general activity of the debug adapter." + }, + "cancellable": { + "type": "boolean", + "description": "If true, the request that reports progress may be canceled with a 'cancel' request.\nSo this property basically controls whether the client should use UX that supports cancellation.\nClients that don't support cancellation are allowed to ignore the setting." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message." + }, + "percentage": { + "type": "number", + "description": "Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown." + } + }, + "required": [ + "progressId", + "title" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param ProgressStartEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'progressStart' + if body is None: + self.body = ProgressStartEventBody() + else: + self.body = ProgressStartEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ProgressStartEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('progressUpdate') +@register +class ProgressUpdateEvent(BaseSchema): + """ + The event signals that the progress reporting needs to updated with a new message and/or percentage. + + The client does not have to update the UI immediately, but the clients needs to keep track of the + message and/or percentage values. + + This event should only be sent if the client has passed the value true for the + 'supportsProgressReporting' capability of the 'initialize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "progressUpdate" + ] + }, + "body": { + "type": "object", + "properties": { + "progressId": { + "type": "string", + "description": "The ID that was introduced in the initial 'progressStart' event." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message. If omitted, the previous message (if any) is used." + }, + "percentage": { + "type": "number", + "description": "Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown." + } + }, + "required": [ + "progressId" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param ProgressUpdateEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'progressUpdate' + if body is None: + self.body = ProgressUpdateEventBody() + else: + self.body = ProgressUpdateEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ProgressUpdateEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('progressEnd') +@register +class ProgressEndEvent(BaseSchema): + """ + The event signals the end of the progress reporting with an optional final message. + + This event should only be sent if the client has passed the value true for the + 'supportsProgressReporting' capability of the 'initialize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "progressEnd" + ] + }, + "body": { + "type": "object", + "properties": { + "progressId": { + "type": "string", + "description": "The ID that was introduced in the initial 'ProgressStartEvent'." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message. If omitted, the previous message (if any) is used." + } + }, + "required": [ + "progressId" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param ProgressEndEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'progressEnd' + if body is None: + self.body = ProgressEndEventBody() + else: + self.body = ProgressEndEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ProgressEndEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('invalidated') +@register +class InvalidatedEvent(BaseSchema): + """ + This event signals that some state in the debug adapter has changed and requires that the client + needs to re-render the data snapshot previously requested. + + Debug adapters do not have to emit this event for runtime changes like stopped or thread events + because in that case the client refetches the new state anyway. But the event can be used for + example to refresh the UI after rendering formatting has changed in the debug adapter. + + This event should only be sent if the debug adapter has received a value true for the + 'supportsInvalidatedEvent' capability of the 'initialize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "invalidated" + ] + }, + "body": { + "type": "object", + "properties": { + "areas": { + "type": "array", + "description": "Optional set of logical areas that got invalidated. This property has a hint characteristic: a client can only be expected to make a 'best effort' in honouring the areas but there are no guarantees. If this property is missing, empty, or if values are not understand the client should assume a single value 'all'.", + "items": { + "$ref": "#/definitions/InvalidatedAreas" + } + }, + "threadId": { + "type": "integer", + "description": "If specified, the client only needs to refetch data related to this thread." + }, + "stackFrameId": { + "type": "integer", + "description": "If specified, the client only needs to refetch data related to this stack frame (and the 'threadId' is ignored)." + } + } + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param InvalidatedEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'invalidated' + if body is None: + self.body = InvalidatedEventBody() + else: + self.body = InvalidatedEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != InvalidatedEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_event('memory') +@register +class MemoryEvent(BaseSchema): + """ + This event indicates that some memory range has been updated. It should only be sent if the debug + adapter has received a value true for the `supportsMemoryEvent` capability of the `initialize` + request. + + Clients typically react to the event by re-issuing a `readMemory` request if they show the memory + identified by the `memoryReference` and if the updated memory range overlaps the displayed range. + Clients should not make assumptions how individual memory references relate to each other, so they + should not assume that they are part of a single continuous address range and might overlap. + + Debug adapters can use this event to indicate that the contents of a memory range has changed due to + some other DAP request like `setVariable` or `setExpression`. Debug adapters are not expected to + emit this event for each and every memory change of a running program, because that information is + typically not available from debuggers and it would flood clients with too many events. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "memory" + ] + }, + "body": { + "type": "object", + "properties": { + "memoryReference": { + "type": "string", + "description": "Memory reference of a memory range that has been updated." + }, + "offset": { + "type": "integer", + "description": "Starting offset in bytes where memory has been updated. Can be negative." + }, + "count": { + "type": "integer", + "description": "Number of bytes updated." + } + }, + "required": [ + "memoryReference", + "offset", + "count" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, body, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param MemoryEventBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'event' + self.event = 'memory' + if body is None: + self.body = MemoryEventBody() + else: + self.body = MemoryEventBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != MemoryEventBody else body + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + body = self.body + seq = self.seq + dct = { + 'type': type, + 'event': event, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register_request('runInTerminal') +@register +class RunInTerminalRequest(BaseSchema): + """ + This optional request is sent from the debug adapter to the client to run a command in a terminal. + + This is typically used to launch the debuggee in a terminal provided by the client. + + This request should only be called if the client has passed the value true for the + 'supportsRunInTerminalRequest' capability of the 'initialize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "runInTerminal" + ] + }, + "arguments": { + "type": "RunInTerminalRequestArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param RunInTerminalRequestArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'runInTerminal' + if arguments is None: + self.arguments = RunInTerminalRequestArguments() + else: + self.arguments = RunInTerminalRequestArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != RunInTerminalRequestArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class RunInTerminalRequestArguments(BaseSchema): + """ + Arguments for 'runInTerminal' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "kind": { + "type": "string", + "enum": [ + "integrated", + "external" + ], + "description": "What kind of terminal to launch." + }, + "title": { + "type": "string", + "description": "Optional title of the terminal." + }, + "cwd": { + "type": "string", + "description": "Working directory for the command. For non-empty, valid paths this typically results in execution of a change directory command." + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of arguments. The first argument is the command to run." + }, + "env": { + "type": "object", + "description": "Environment key-value pairs that are added to or removed from the default environment.", + "additionalProperties": { + "type": [ + "string", + "null" + ], + "description": "Proper values must be strings. A value of 'null' removes the variable from the environment." + } + } + } + __refs__ = set(['env']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, cwd, args, kind=None, title=None, env=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string cwd: Working directory for the command. For non-empty, valid paths this typically results in execution of a change directory command. + :param array args: List of arguments. The first argument is the command to run. + :param string kind: What kind of terminal to launch. + :param string title: Optional title of the terminal. + :param RunInTerminalRequestArgumentsEnv env: Environment key-value pairs that are added to or removed from the default environment. + """ + self.cwd = cwd + self.args = args + self.kind = kind + self.title = title + if env is None: + self.env = RunInTerminalRequestArgumentsEnv() + else: + self.env = RunInTerminalRequestArgumentsEnv(update_ids_from_dap=update_ids_from_dap, **env) if env.__class__ != RunInTerminalRequestArgumentsEnv else env + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + cwd = self.cwd + args = self.args + if args and hasattr(args[0], "to_dict"): + args = [x.to_dict() for x in args] + kind = self.kind + title = self.title + env = self.env + dct = { + 'cwd': cwd, + 'args': args, + } + if kind is not None: + dct['kind'] = kind + if title is not None: + dct['title'] = title + if env is not None: + dct['env'] = env.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register_response('runInTerminal') +@register +class RunInTerminalResponse(BaseSchema): + """ + Response to 'runInTerminal' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "processId": { + "type": "integer", + "description": "The process ID. The value should be less than or equal to 2147483647 (2^31-1)." + }, + "shellProcessId": { + "type": "integer", + "description": "The process ID of the terminal shell. The value should be less than or equal to 2147483647 (2^31-1)." + } + } + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param RunInTerminalResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = RunInTerminalResponseBody() + else: + self.body = RunInTerminalResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != RunInTerminalResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('initialize') +@register +class InitializeRequest(BaseSchema): + """ + The 'initialize' request is sent as the first request from the client to the debug adapter + + in order to configure it with client capabilities and to retrieve capabilities from the debug + adapter. + + Until the debug adapter has responded to with an 'initialize' response, the client must not send any + additional requests or events to the debug adapter. + + In addition the debug adapter is not allowed to send any requests or events to the client until it + has responded with an 'initialize' response. + + The 'initialize' request may only be sent once. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "initialize" + ] + }, + "arguments": { + "type": "InitializeRequestArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param InitializeRequestArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'initialize' + if arguments is None: + self.arguments = InitializeRequestArguments() + else: + self.arguments = InitializeRequestArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != InitializeRequestArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class InitializeRequestArguments(BaseSchema): + """ + Arguments for 'initialize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "clientID": { + "type": "string", + "description": "The ID of the (frontend) client using this adapter." + }, + "clientName": { + "type": "string", + "description": "The human readable name of the (frontend) client using this adapter." + }, + "adapterID": { + "type": "string", + "description": "The ID of the debug adapter." + }, + "locale": { + "type": "string", + "description": "The ISO-639 locale of the (frontend) client using this adapter, e.g. en-US or de-CH." + }, + "linesStartAt1": { + "type": "boolean", + "description": "If true all line numbers are 1-based (default)." + }, + "columnsStartAt1": { + "type": "boolean", + "description": "If true all column numbers are 1-based (default)." + }, + "pathFormat": { + "type": "string", + "_enum": [ + "path", + "uri" + ], + "description": "Determines in what format paths are specified. The default is 'path', which is the native format." + }, + "supportsVariableType": { + "type": "boolean", + "description": "Client supports the optional type attribute for variables." + }, + "supportsVariablePaging": { + "type": "boolean", + "description": "Client supports the paging of variables." + }, + "supportsRunInTerminalRequest": { + "type": "boolean", + "description": "Client supports the runInTerminal request." + }, + "supportsMemoryReferences": { + "type": "boolean", + "description": "Client supports memory references." + }, + "supportsProgressReporting": { + "type": "boolean", + "description": "Client supports progress reporting." + }, + "supportsInvalidatedEvent": { + "type": "boolean", + "description": "Client supports the invalidated event." + }, + "supportsMemoryEvent": { + "type": "boolean", + "description": "Client supports the memory event." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, adapterID, clientID=None, clientName=None, locale=None, linesStartAt1=None, columnsStartAt1=None, pathFormat=None, supportsVariableType=None, supportsVariablePaging=None, supportsRunInTerminalRequest=None, supportsMemoryReferences=None, supportsProgressReporting=None, supportsInvalidatedEvent=None, supportsMemoryEvent=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string adapterID: The ID of the debug adapter. + :param string clientID: The ID of the (frontend) client using this adapter. + :param string clientName: The human readable name of the (frontend) client using this adapter. + :param string locale: The ISO-639 locale of the (frontend) client using this adapter, e.g. en-US or de-CH. + :param boolean linesStartAt1: If true all line numbers are 1-based (default). + :param boolean columnsStartAt1: If true all column numbers are 1-based (default). + :param string pathFormat: Determines in what format paths are specified. The default is 'path', which is the native format. + :param boolean supportsVariableType: Client supports the optional type attribute for variables. + :param boolean supportsVariablePaging: Client supports the paging of variables. + :param boolean supportsRunInTerminalRequest: Client supports the runInTerminal request. + :param boolean supportsMemoryReferences: Client supports memory references. + :param boolean supportsProgressReporting: Client supports progress reporting. + :param boolean supportsInvalidatedEvent: Client supports the invalidated event. + :param boolean supportsMemoryEvent: Client supports the memory event. + """ + self.adapterID = adapterID + self.clientID = clientID + self.clientName = clientName + self.locale = locale + self.linesStartAt1 = linesStartAt1 + self.columnsStartAt1 = columnsStartAt1 + self.pathFormat = pathFormat + self.supportsVariableType = supportsVariableType + self.supportsVariablePaging = supportsVariablePaging + self.supportsRunInTerminalRequest = supportsRunInTerminalRequest + self.supportsMemoryReferences = supportsMemoryReferences + self.supportsProgressReporting = supportsProgressReporting + self.supportsInvalidatedEvent = supportsInvalidatedEvent + self.supportsMemoryEvent = supportsMemoryEvent + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + adapterID = self.adapterID + clientID = self.clientID + clientName = self.clientName + locale = self.locale + linesStartAt1 = self.linesStartAt1 + columnsStartAt1 = self.columnsStartAt1 + pathFormat = self.pathFormat + supportsVariableType = self.supportsVariableType + supportsVariablePaging = self.supportsVariablePaging + supportsRunInTerminalRequest = self.supportsRunInTerminalRequest + supportsMemoryReferences = self.supportsMemoryReferences + supportsProgressReporting = self.supportsProgressReporting + supportsInvalidatedEvent = self.supportsInvalidatedEvent + supportsMemoryEvent = self.supportsMemoryEvent + dct = { + 'adapterID': adapterID, + } + if clientID is not None: + dct['clientID'] = clientID + if clientName is not None: + dct['clientName'] = clientName + if locale is not None: + dct['locale'] = locale + if linesStartAt1 is not None: + dct['linesStartAt1'] = linesStartAt1 + if columnsStartAt1 is not None: + dct['columnsStartAt1'] = columnsStartAt1 + if pathFormat is not None: + dct['pathFormat'] = pathFormat + if supportsVariableType is not None: + dct['supportsVariableType'] = supportsVariableType + if supportsVariablePaging is not None: + dct['supportsVariablePaging'] = supportsVariablePaging + if supportsRunInTerminalRequest is not None: + dct['supportsRunInTerminalRequest'] = supportsRunInTerminalRequest + if supportsMemoryReferences is not None: + dct['supportsMemoryReferences'] = supportsMemoryReferences + if supportsProgressReporting is not None: + dct['supportsProgressReporting'] = supportsProgressReporting + if supportsInvalidatedEvent is not None: + dct['supportsInvalidatedEvent'] = supportsInvalidatedEvent + if supportsMemoryEvent is not None: + dct['supportsMemoryEvent'] = supportsMemoryEvent + dct.update(self.kwargs) + return dct + + +@register_response('initialize') +@register +class InitializeResponse(BaseSchema): + """ + Response to 'initialize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "description": "The capabilities of this debug adapter.", + "type": "Capabilities" + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param Capabilities body: The capabilities of this debug adapter. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + if body is None: + self.body = Capabilities() + else: + self.body = Capabilities(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != Capabilities else body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register_request('configurationDone') +@register +class ConfigurationDoneRequest(BaseSchema): + """ + This optional request indicates that the client has finished initialization of the debug adapter. + + So it is the last request in the sequence of configuration requests (which was started by the + 'initialized' event). + + Clients should only call this request if the capability 'supportsConfigurationDoneRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "configurationDone" + ] + }, + "arguments": { + "type": "ConfigurationDoneArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param ConfigurationDoneArguments arguments: + """ + self.type = 'request' + self.command = 'configurationDone' + self.seq = seq + if arguments is None: + self.arguments = ConfigurationDoneArguments() + else: + self.arguments = ConfigurationDoneArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != ConfigurationDoneArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class ConfigurationDoneArguments(BaseSchema): + """ + Arguments for 'configurationDone' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register_response('configurationDone') +@register +class ConfigurationDoneResponse(BaseSchema): + """ + Response to 'configurationDone' request. This is just an acknowledgement, so no body field is + required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('launch') +@register +class LaunchRequest(BaseSchema): + """ + This launch request is sent from the client to the debug adapter to start the debuggee with or + without debugging (if 'noDebug' is true). + + Since launching is debugger/runtime specific, the arguments for this request are not part of this + specification. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "launch" + ] + }, + "arguments": { + "type": "LaunchRequestArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param LaunchRequestArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'launch' + if arguments is None: + self.arguments = LaunchRequestArguments() + else: + self.arguments = LaunchRequestArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != LaunchRequestArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class LaunchRequestArguments(BaseSchema): + """ + Arguments for 'launch' request. Additional attributes are implementation specific. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "noDebug": { + "type": "boolean", + "description": "If noDebug is true the launch request should launch the program without enabling debugging." + }, + "__restart": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Optional data from the previous, restarted session.\nThe data is sent as the 'restart' attribute of the 'terminated' event.\nThe client should leave the data intact." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, noDebug=None, __restart=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean noDebug: If noDebug is true the launch request should launch the program without enabling debugging. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] __restart: Optional data from the previous, restarted session. + The data is sent as the 'restart' attribute of the 'terminated' event. + The client should leave the data intact. + """ + self.noDebug = noDebug + self.__restart = __restart + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + noDebug = self.noDebug + __restart = self.__restart + dct = { + } + if noDebug is not None: + dct['noDebug'] = noDebug + if __restart is not None: + dct['__restart'] = __restart + dct.update(self.kwargs) + return dct + + +@register_response('launch') +@register +class LaunchResponse(BaseSchema): + """ + Response to 'launch' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('attach') +@register +class AttachRequest(BaseSchema): + """ + The attach request is sent from the client to the debug adapter to attach to a debuggee that is + already running. + + Since attaching is debugger/runtime specific, the arguments for this request are not part of this + specification. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "attach" + ] + }, + "arguments": { + "type": "AttachRequestArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param AttachRequestArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'attach' + if arguments is None: + self.arguments = AttachRequestArguments() + else: + self.arguments = AttachRequestArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != AttachRequestArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class AttachRequestArguments(BaseSchema): + """ + Arguments for 'attach' request. Additional attributes are implementation specific. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "__restart": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Optional data from the previous, restarted session.\nThe data is sent as the 'restart' attribute of the 'terminated' event.\nThe client should leave the data intact." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, __restart=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] __restart: Optional data from the previous, restarted session. + The data is sent as the 'restart' attribute of the 'terminated' event. + The client should leave the data intact. + """ + self.__restart = __restart + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + __restart = self.__restart + dct = { + } + if __restart is not None: + dct['__restart'] = __restart + dct.update(self.kwargs) + return dct + + +@register_response('attach') +@register +class AttachResponse(BaseSchema): + """ + Response to 'attach' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('restart') +@register +class RestartRequest(BaseSchema): + """ + Restarts a debug session. Clients should only call this request if the capability + 'supportsRestartRequest' is true. + + If the capability is missing or has the value false, a typical client will emulate 'restart' by + terminating the debug adapter first and then launching it anew. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "restart" + ] + }, + "arguments": { + "type": "RestartArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param RestartArguments arguments: + """ + self.type = 'request' + self.command = 'restart' + self.seq = seq + if arguments is None: + self.arguments = RestartArguments() + else: + self.arguments = RestartArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != RestartArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class RestartArguments(BaseSchema): + """ + Arguments for 'restart' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "arguments": { + "oneOf": [ + { + "$ref": "#/definitions/LaunchRequestArguments" + }, + { + "$ref": "#/definitions/AttachRequestArguments" + } + ], + "description": "The latest version of the 'launch' or 'attach' configuration." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param TypeNA arguments: The latest version of the 'launch' or 'attach' configuration. + """ + self.arguments = arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + arguments = self.arguments + dct = { + } + if arguments is not None: + dct['arguments'] = arguments + dct.update(self.kwargs) + return dct + + +@register_response('restart') +@register +class RestartResponse(BaseSchema): + """ + Response to 'restart' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('disconnect') +@register +class DisconnectRequest(BaseSchema): + """ + The 'disconnect' request is sent from the client to the debug adapter in order to stop debugging. + + It asks the debug adapter to disconnect from the debuggee and to terminate the debug adapter. + + If the debuggee has been started with the 'launch' request, the 'disconnect' request terminates the + debuggee. + + If the 'attach' request was used to connect to the debuggee, 'disconnect' does not terminate the + debuggee. + + This behavior can be controlled with the 'terminateDebuggee' argument (if supported by the debug + adapter). + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "disconnect" + ] + }, + "arguments": { + "type": "DisconnectArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param DisconnectArguments arguments: + """ + self.type = 'request' + self.command = 'disconnect' + self.seq = seq + if arguments is None: + self.arguments = DisconnectArguments() + else: + self.arguments = DisconnectArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != DisconnectArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class DisconnectArguments(BaseSchema): + """ + Arguments for 'disconnect' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "restart": { + "type": "boolean", + "description": "A value of true indicates that this 'disconnect' request is part of a restart sequence." + }, + "terminateDebuggee": { + "type": "boolean", + "description": "Indicates whether the debuggee should be terminated when the debugger is disconnected.\nIf unspecified, the debug adapter is free to do whatever it thinks is best.\nThe attribute is only honored by a debug adapter if the capability 'supportTerminateDebuggee' is true." + }, + "suspendDebuggee": { + "type": "boolean", + "description": "Indicates whether the debuggee should stay suspended when the debugger is disconnected.\nIf unspecified, the debuggee should resume execution.\nThe attribute is only honored by a debug adapter if the capability 'supportSuspendDebuggee' is true." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, restart=None, terminateDebuggee=None, suspendDebuggee=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean restart: A value of true indicates that this 'disconnect' request is part of a restart sequence. + :param boolean terminateDebuggee: Indicates whether the debuggee should be terminated when the debugger is disconnected. + If unspecified, the debug adapter is free to do whatever it thinks is best. + The attribute is only honored by a debug adapter if the capability 'supportTerminateDebuggee' is true. + :param boolean suspendDebuggee: Indicates whether the debuggee should stay suspended when the debugger is disconnected. + If unspecified, the debuggee should resume execution. + The attribute is only honored by a debug adapter if the capability 'supportSuspendDebuggee' is true. + """ + self.restart = restart + self.terminateDebuggee = terminateDebuggee + self.suspendDebuggee = suspendDebuggee + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + restart = self.restart + terminateDebuggee = self.terminateDebuggee + suspendDebuggee = self.suspendDebuggee + dct = { + } + if restart is not None: + dct['restart'] = restart + if terminateDebuggee is not None: + dct['terminateDebuggee'] = terminateDebuggee + if suspendDebuggee is not None: + dct['suspendDebuggee'] = suspendDebuggee + dct.update(self.kwargs) + return dct + + +@register_response('disconnect') +@register +class DisconnectResponse(BaseSchema): + """ + Response to 'disconnect' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('terminate') +@register +class TerminateRequest(BaseSchema): + """ + The 'terminate' request is sent from the client to the debug adapter in order to give the debuggee a + chance for terminating itself. + + Clients should only call this request if the capability 'supportsTerminateRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "terminate" + ] + }, + "arguments": { + "type": "TerminateArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param TerminateArguments arguments: + """ + self.type = 'request' + self.command = 'terminate' + self.seq = seq + if arguments is None: + self.arguments = TerminateArguments() + else: + self.arguments = TerminateArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != TerminateArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class TerminateArguments(BaseSchema): + """ + Arguments for 'terminate' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "restart": { + "type": "boolean", + "description": "A value of true indicates that this 'terminate' request is part of a restart sequence." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, restart=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean restart: A value of true indicates that this 'terminate' request is part of a restart sequence. + """ + self.restart = restart + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + restart = self.restart + dct = { + } + if restart is not None: + dct['restart'] = restart + dct.update(self.kwargs) + return dct + + +@register_response('terminate') +@register +class TerminateResponse(BaseSchema): + """ + Response to 'terminate' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('breakpointLocations') +@register +class BreakpointLocationsRequest(BaseSchema): + """ + The 'breakpointLocations' request returns all possible locations for source breakpoints in a given + range. + + Clients should only call this request if the capability 'supportsBreakpointLocationsRequest' is + true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "breakpointLocations" + ] + }, + "arguments": { + "type": "BreakpointLocationsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param BreakpointLocationsArguments arguments: + """ + self.type = 'request' + self.command = 'breakpointLocations' + self.seq = seq + if arguments is None: + self.arguments = BreakpointLocationsArguments() + else: + self.arguments = BreakpointLocationsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != BreakpointLocationsArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class BreakpointLocationsArguments(BaseSchema): + """ + Arguments for 'breakpointLocations' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "source": { + "description": "The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified.", + "type": "Source" + }, + "line": { + "type": "integer", + "description": "Start line of range to search possible breakpoint locations in. If only the line is specified, the request returns all possible locations in that line." + }, + "column": { + "type": "integer", + "description": "Optional start column of range to search possible breakpoint locations in. If no start column is given, the first column in the start line is assumed." + }, + "endLine": { + "type": "integer", + "description": "Optional end line of range to search possible breakpoint locations in. If no end line is given, then the end line is assumed to be the start line." + }, + "endColumn": { + "type": "integer", + "description": "Optional end column of range to search possible breakpoint locations in. If no end column is given, then it is assumed to be in the last column of the end line." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, source, line, column=None, endLine=None, endColumn=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param Source source: The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified. + :param integer line: Start line of range to search possible breakpoint locations in. If only the line is specified, the request returns all possible locations in that line. + :param integer column: Optional start column of range to search possible breakpoint locations in. If no start column is given, the first column in the start line is assumed. + :param integer endLine: Optional end line of range to search possible breakpoint locations in. If no end line is given, then the end line is assumed to be the start line. + :param integer endColumn: Optional end column of range to search possible breakpoint locations in. If no end column is given, then it is assumed to be in the last column of the end line. + """ + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.line = line + self.column = column + self.endLine = endLine + self.endColumn = endColumn + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + source = self.source + line = self.line + column = self.column + endLine = self.endLine + endColumn = self.endColumn + dct = { + 'source': source.to_dict(update_ids_to_dap=update_ids_to_dap), + 'line': line, + } + if column is not None: + dct['column'] = column + if endLine is not None: + dct['endLine'] = endLine + if endColumn is not None: + dct['endColumn'] = endColumn + dct.update(self.kwargs) + return dct + + +@register_response('breakpointLocations') +@register +class BreakpointLocationsResponse(BaseSchema): + """ + Response to 'breakpointLocations' request. + + Contains possible locations for source breakpoints. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/BreakpointLocation" + }, + "description": "Sorted set of possible breakpoint locations." + } + }, + "required": [ + "breakpoints" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param BreakpointLocationsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = BreakpointLocationsResponseBody() + else: + self.body = BreakpointLocationsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != BreakpointLocationsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('setBreakpoints') +@register +class SetBreakpointsRequest(BaseSchema): + """ + Sets multiple breakpoints for a single source and clears all previous breakpoints in that source. + + To clear all breakpoint for a source, specify an empty array. + + When a breakpoint is hit, a 'stopped' event (with reason 'breakpoint') is generated. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setBreakpoints" + ] + }, + "arguments": { + "type": "SetBreakpointsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetBreakpointsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setBreakpoints' + if arguments is None: + self.arguments = SetBreakpointsArguments() + else: + self.arguments = SetBreakpointsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetBreakpointsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetBreakpointsArguments(BaseSchema): + """ + Arguments for 'setBreakpoints' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "source": { + "description": "The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified.", + "type": "Source" + }, + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/SourceBreakpoint" + }, + "description": "The code locations of the breakpoints." + }, + "lines": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Deprecated: The code locations of the breakpoints." + }, + "sourceModified": { + "type": "boolean", + "description": "A value of true indicates that the underlying source has been modified which results in new breakpoint locations." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, source, breakpoints=None, lines=None, sourceModified=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param Source source: The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified. + :param array breakpoints: The code locations of the breakpoints. + :param array lines: Deprecated: The code locations of the breakpoints. + :param boolean sourceModified: A value of true indicates that the underlying source has been modified which results in new breakpoint locations. + """ + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + SourceBreakpoint.update_dict_ids_from_dap(o) + self.lines = lines + self.sourceModified = sourceModified + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + source = self.source + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + lines = self.lines + if lines and hasattr(lines[0], "to_dict"): + lines = [x.to_dict() for x in lines] + sourceModified = self.sourceModified + dct = { + 'source': source.to_dict(update_ids_to_dap=update_ids_to_dap), + } + if breakpoints is not None: + dct['breakpoints'] = [SourceBreakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints + if lines is not None: + dct['lines'] = lines + if sourceModified is not None: + dct['sourceModified'] = sourceModified + dct.update(self.kwargs) + return dct + + +@register_response('setBreakpoints') +@register +class SetBreakpointsResponse(BaseSchema): + """ + Response to 'setBreakpoints' request. + + Returned is information about each breakpoint created by this request. + + This includes the actual code location and whether the breakpoint could be verified. + + The breakpoints returned are in the same order as the elements of the 'breakpoints' + + (or the deprecated 'lines') array in the arguments. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints.\nThe array elements are in the same order as the elements of the 'breakpoints' (or the deprecated 'lines') array in the arguments." + } + }, + "required": [ + "breakpoints" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param SetBreakpointsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = SetBreakpointsResponseBody() + else: + self.body = SetBreakpointsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != SetBreakpointsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('setFunctionBreakpoints') +@register +class SetFunctionBreakpointsRequest(BaseSchema): + """ + Replaces all existing function breakpoints with new function breakpoints. + + To clear all function breakpoints, specify an empty array. + + When a function breakpoint is hit, a 'stopped' event (with reason 'function breakpoint') is + generated. + + Clients should only call this request if the capability 'supportsFunctionBreakpoints' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setFunctionBreakpoints" + ] + }, + "arguments": { + "type": "SetFunctionBreakpointsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetFunctionBreakpointsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setFunctionBreakpoints' + if arguments is None: + self.arguments = SetFunctionBreakpointsArguments() + else: + self.arguments = SetFunctionBreakpointsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetFunctionBreakpointsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetFunctionBreakpointsArguments(BaseSchema): + """ + Arguments for 'setFunctionBreakpoints' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/FunctionBreakpoint" + }, + "description": "The function names of the breakpoints." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: The function names of the breakpoints. + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + FunctionBreakpoint.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + 'breakpoints': [FunctionBreakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints, + } + dct.update(self.kwargs) + return dct + + +@register_response('setFunctionBreakpoints') +@register +class SetFunctionBreakpointsResponse(BaseSchema): + """ + Response to 'setFunctionBreakpoints' request. + + Returned is information about each breakpoint created by this request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array." + } + }, + "required": [ + "breakpoints" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param SetFunctionBreakpointsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = SetFunctionBreakpointsResponseBody() + else: + self.body = SetFunctionBreakpointsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != SetFunctionBreakpointsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('setExceptionBreakpoints') +@register +class SetExceptionBreakpointsRequest(BaseSchema): + """ + The request configures the debuggers response to thrown exceptions. + + If an exception is configured to break, a 'stopped' event is fired (with reason 'exception'). + + Clients should only call this request if the capability 'exceptionBreakpointFilters' returns one or + more filters. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setExceptionBreakpoints" + ] + }, + "arguments": { + "type": "SetExceptionBreakpointsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetExceptionBreakpointsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setExceptionBreakpoints' + if arguments is None: + self.arguments = SetExceptionBreakpointsArguments() + else: + self.arguments = SetExceptionBreakpointsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetExceptionBreakpointsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetExceptionBreakpointsArguments(BaseSchema): + """ + Arguments for 'setExceptionBreakpoints' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "filters": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Set of exception filters specified by their ID. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. The 'filter' and 'filterOptions' sets are additive." + }, + "filterOptions": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionFilterOptions" + }, + "description": "Set of exception filters and their options. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. This attribute is only honored by a debug adapter if the capability 'supportsExceptionFilterOptions' is true. The 'filter' and 'filterOptions' sets are additive." + }, + "exceptionOptions": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionOptions" + }, + "description": "Configuration options for selected exceptions.\nThe attribute is only honored by a debug adapter if the capability 'supportsExceptionOptions' is true." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, filters, filterOptions=None, exceptionOptions=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array filters: Set of exception filters specified by their ID. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. The 'filter' and 'filterOptions' sets are additive. + :param array filterOptions: Set of exception filters and their options. The set of all possible exception filters is defined by the 'exceptionBreakpointFilters' capability. This attribute is only honored by a debug adapter if the capability 'supportsExceptionFilterOptions' is true. The 'filter' and 'filterOptions' sets are additive. + :param array exceptionOptions: Configuration options for selected exceptions. + The attribute is only honored by a debug adapter if the capability 'supportsExceptionOptions' is true. + """ + self.filters = filters + self.filterOptions = filterOptions + if update_ids_from_dap and self.filterOptions: + for o in self.filterOptions: + ExceptionFilterOptions.update_dict_ids_from_dap(o) + self.exceptionOptions = exceptionOptions + if update_ids_from_dap and self.exceptionOptions: + for o in self.exceptionOptions: + ExceptionOptions.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + filters = self.filters + if filters and hasattr(filters[0], "to_dict"): + filters = [x.to_dict() for x in filters] + filterOptions = self.filterOptions + if filterOptions and hasattr(filterOptions[0], "to_dict"): + filterOptions = [x.to_dict() for x in filterOptions] + exceptionOptions = self.exceptionOptions + if exceptionOptions and hasattr(exceptionOptions[0], "to_dict"): + exceptionOptions = [x.to_dict() for x in exceptionOptions] + dct = { + 'filters': filters, + } + if filterOptions is not None: + dct['filterOptions'] = [ExceptionFilterOptions.update_dict_ids_to_dap(o) for o in filterOptions] if (update_ids_to_dap and filterOptions) else filterOptions + if exceptionOptions is not None: + dct['exceptionOptions'] = [ExceptionOptions.update_dict_ids_to_dap(o) for o in exceptionOptions] if (update_ids_to_dap and exceptionOptions) else exceptionOptions + dct.update(self.kwargs) + return dct + + +@register_response('setExceptionBreakpoints') +@register +class SetExceptionBreakpointsResponse(BaseSchema): + """ + Response to 'setExceptionBreakpoints' request. + + The response contains an array of Breakpoint objects with information about each exception + breakpoint or filter. The Breakpoint objects are in the same order as the elements of the 'filters', + 'filterOptions', 'exceptionOptions' arrays given as arguments. If both 'filters' and 'filterOptions' + are given, the returned array must start with 'filters' information first, followed by + 'filterOptions' information. + + The mandatory 'verified' property of a Breakpoint object signals whether the exception breakpoint or + filter could be successfully created and whether the optional condition or hit count expressions are + valid. In case of an error the 'message' property explains the problem. An optional 'id' property + can be used to introduce a unique ID for the exception breakpoint or filter so that it can be + updated subsequently by sending breakpoint events. + + For backward compatibility both the 'breakpoints' array and the enclosing 'body' are optional. If + these elements are missing a client will not be able to show problems for individual exception + breakpoints or filters. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the exception breakpoints or filters.\nThe breakpoints returned are in the same order as the elements of the 'filters', 'filterOptions', 'exceptionOptions' arrays in the arguments. If both 'filters' and 'filterOptions' are given, the returned array must start with 'filters' information first, followed by 'filterOptions' information." + } + } + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param SetExceptionBreakpointsResponseBody body: + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + if body is None: + self.body = SetExceptionBreakpointsResponseBody() + else: + self.body = SetExceptionBreakpointsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != SetExceptionBreakpointsResponseBody else body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register_request('dataBreakpointInfo') +@register +class DataBreakpointInfoRequest(BaseSchema): + """ + Obtains information on a possible data breakpoint that could be set on an expression or variable. + + Clients should only call this request if the capability 'supportsDataBreakpoints' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "dataBreakpointInfo" + ] + }, + "arguments": { + "type": "DataBreakpointInfoArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param DataBreakpointInfoArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'dataBreakpointInfo' + if arguments is None: + self.arguments = DataBreakpointInfoArguments() + else: + self.arguments = DataBreakpointInfoArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != DataBreakpointInfoArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class DataBreakpointInfoArguments(BaseSchema): + """ + Arguments for 'dataBreakpointInfo' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "variablesReference": { + "type": "integer", + "description": "Reference to the Variable container if the data breakpoint is requested for a child of the container." + }, + "name": { + "type": "string", + "description": "The name of the Variable's child to obtain data breakpoint information for.\nIf variablesReference isn't provided, this can be an expression." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, name, variablesReference=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string name: The name of the Variable's child to obtain data breakpoint information for. + If variablesReference isn't provided, this can be an expression. + :param integer variablesReference: Reference to the Variable container if the data breakpoint is requested for a child of the container. + """ + self.name = name + self.variablesReference = variablesReference + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + name = self.name + variablesReference = self.variablesReference + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'name': name, + } + if variablesReference is not None: + dct['variablesReference'] = variablesReference + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register_response('dataBreakpointInfo') +@register +class DataBreakpointInfoResponse(BaseSchema): + """ + Response to 'dataBreakpointInfo' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "dataId": { + "type": [ + "string", + "null" + ], + "description": "An identifier for the data on which a data breakpoint can be registered with the setDataBreakpoints request or null if no data breakpoint is available." + }, + "description": { + "type": "string", + "description": "UI string that describes on what data the breakpoint is set on or why a data breakpoint is not available." + }, + "accessTypes": { + "type": "array", + "items": { + "$ref": "#/definitions/DataBreakpointAccessType" + }, + "description": "Optional attribute listing the available access types for a potential data breakpoint. A UI frontend could surface this information." + }, + "canPersist": { + "type": "boolean", + "description": "Optional attribute indicating that a potential data breakpoint could be persisted across sessions." + } + }, + "required": [ + "dataId", + "description" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param DataBreakpointInfoResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = DataBreakpointInfoResponseBody() + else: + self.body = DataBreakpointInfoResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != DataBreakpointInfoResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('setDataBreakpoints') +@register +class SetDataBreakpointsRequest(BaseSchema): + """ + Replaces all existing data breakpoints with new data breakpoints. + + To clear all data breakpoints, specify an empty array. + + When a data breakpoint is hit, a 'stopped' event (with reason 'data breakpoint') is generated. + + Clients should only call this request if the capability 'supportsDataBreakpoints' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setDataBreakpoints" + ] + }, + "arguments": { + "type": "SetDataBreakpointsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetDataBreakpointsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setDataBreakpoints' + if arguments is None: + self.arguments = SetDataBreakpointsArguments() + else: + self.arguments = SetDataBreakpointsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetDataBreakpointsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetDataBreakpointsArguments(BaseSchema): + """ + Arguments for 'setDataBreakpoints' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/DataBreakpoint" + }, + "description": "The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints. + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + DataBreakpoint.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + 'breakpoints': [DataBreakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints, + } + dct.update(self.kwargs) + return dct + + +@register_response('setDataBreakpoints') +@register +class SetDataBreakpointsResponse(BaseSchema): + """ + Response to 'setDataBreakpoints' request. + + Returned is information about each breakpoint created by this request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the data breakpoints. The array elements correspond to the elements of the input argument 'breakpoints' array." + } + }, + "required": [ + "breakpoints" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param SetDataBreakpointsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = SetDataBreakpointsResponseBody() + else: + self.body = SetDataBreakpointsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != SetDataBreakpointsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('setInstructionBreakpoints') +@register +class SetInstructionBreakpointsRequest(BaseSchema): + """ + Replaces all existing instruction breakpoints. Typically, instruction breakpoints would be set from + a diassembly window. + + To clear all instruction breakpoints, specify an empty array. + + When an instruction breakpoint is hit, a 'stopped' event (with reason 'instruction breakpoint') is + generated. + + Clients should only call this request if the capability 'supportsInstructionBreakpoints' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setInstructionBreakpoints" + ] + }, + "arguments": { + "type": "SetInstructionBreakpointsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetInstructionBreakpointsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setInstructionBreakpoints' + if arguments is None: + self.arguments = SetInstructionBreakpointsArguments() + else: + self.arguments = SetInstructionBreakpointsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetInstructionBreakpointsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetInstructionBreakpointsArguments(BaseSchema): + """ + Arguments for 'setInstructionBreakpoints' request + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/InstructionBreakpoint" + }, + "description": "The instruction references of the breakpoints" + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: The instruction references of the breakpoints + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + InstructionBreakpoint.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + 'breakpoints': [InstructionBreakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints, + } + dct.update(self.kwargs) + return dct + + +@register_response('setInstructionBreakpoints') +@register +class SetInstructionBreakpointsResponse(BaseSchema): + """ + Response to 'setInstructionBreakpoints' request + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array." + } + }, + "required": [ + "breakpoints" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param SetInstructionBreakpointsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = SetInstructionBreakpointsResponseBody() + else: + self.body = SetInstructionBreakpointsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != SetInstructionBreakpointsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('continue') +@register +class ContinueRequest(BaseSchema): + """ + The request resumes execution of all threads. If the debug adapter supports single thread execution + (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true + resumes only the specified thread. If not all threads were resumed, the 'allThreadsContinued' + attribute of the response must be set to false. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "continue" + ] + }, + "arguments": { + "type": "ContinueArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param ContinueArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'continue' + if arguments is None: + self.arguments = ContinueArguments() + else: + self.arguments = ContinueArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != ContinueArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class ContinueArguments(BaseSchema): + """ + Arguments for 'continue' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, execution is resumed only for the thread with given 'threadId'." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, singleThread=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed. + :param boolean singleThread: If this optional flag is true, execution is resumed only for the thread with given 'threadId'. + """ + self.threadId = threadId + self.singleThread = singleThread + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + singleThread = self.singleThread + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + if singleThread is not None: + dct['singleThread'] = singleThread + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('continue') +@register +class ContinueResponse(BaseSchema): + """ + Response to 'continue' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "allThreadsContinued": { + "type": "boolean", + "description": "The value true (or a missing property) signals to the client that all threads have been resumed. The value false must be returned if not all threads were resumed." + } + } + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param ContinueResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = ContinueResponseBody() + else: + self.body = ContinueResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ContinueResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('next') +@register +class NextRequest(BaseSchema): + """ + The request executes one step (in the given granularity) for the specified thread and allows all + other threads to run freely by resuming them. + + If the debug adapter supports single thread execution (see capability + 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other + suspended threads from resuming. + + The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the + step has completed. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "next" + ] + }, + "arguments": { + "type": "NextArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param NextArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'next' + if arguments is None: + self.arguments = NextArguments() + else: + self.arguments = NextArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != NextArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class NextArguments(BaseSchema): + """ + Arguments for 'next' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Specifies the thread for which to resume execution for one step (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." + }, + "granularity": { + "description": "Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed.", + "type": "SteppingGranularity" + } + } + __refs__ = set(['granularity']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, singleThread=None, granularity=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Specifies the thread for which to resume execution for one step (of the given granularity). + :param boolean singleThread: If this optional flag is true, all other suspended threads are not resumed. + :param SteppingGranularity granularity: Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. + """ + self.threadId = threadId + self.singleThread = singleThread + if granularity is not None: + assert granularity in SteppingGranularity.VALID_VALUES + self.granularity = granularity + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + singleThread = self.singleThread + granularity = self.granularity + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + if singleThread is not None: + dct['singleThread'] = singleThread + if granularity is not None: + dct['granularity'] = granularity + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('next') +@register +class NextResponse(BaseSchema): + """ + Response to 'next' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('stepIn') +@register +class StepInRequest(BaseSchema): + """ + The request resumes the given thread to step into a function/method and allows all other threads to + run freely by resuming them. + + If the debug adapter supports single thread execution (see capability + 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other + suspended threads from resuming. + + If the request cannot step into a target, 'stepIn' behaves like the 'next' request. + + The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the + step has completed. + + If there are multiple function/method calls (or other targets) on the source line, + + the optional argument 'targetId' can be used to control into which target the 'stepIn' should occur. + + The list of possible targets for a given source line can be retrieved via the 'stepInTargets' + request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "stepIn" + ] + }, + "arguments": { + "type": "StepInArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param StepInArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'stepIn' + if arguments is None: + self.arguments = StepInArguments() + else: + self.arguments = StepInArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != StepInArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class StepInArguments(BaseSchema): + """ + Arguments for 'stepIn' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Specifies the thread for which to resume execution for one step-into (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." + }, + "targetId": { + "type": "integer", + "description": "Optional id of the target to step into." + }, + "granularity": { + "description": "Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed.", + "type": "SteppingGranularity" + } + } + __refs__ = set(['granularity']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, singleThread=None, targetId=None, granularity=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Specifies the thread for which to resume execution for one step-into (of the given granularity). + :param boolean singleThread: If this optional flag is true, all other suspended threads are not resumed. + :param integer targetId: Optional id of the target to step into. + :param SteppingGranularity granularity: Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. + """ + self.threadId = threadId + self.singleThread = singleThread + self.targetId = targetId + if granularity is not None: + assert granularity in SteppingGranularity.VALID_VALUES + self.granularity = granularity + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + singleThread = self.singleThread + targetId = self.targetId + granularity = self.granularity + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + if singleThread is not None: + dct['singleThread'] = singleThread + if targetId is not None: + dct['targetId'] = targetId + if granularity is not None: + dct['granularity'] = granularity + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('stepIn') +@register +class StepInResponse(BaseSchema): + """ + Response to 'stepIn' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('stepOut') +@register +class StepOutRequest(BaseSchema): + """ + The request resumes the given thread to step out (return) from a function/method and allows all + other threads to run freely by resuming them. + + If the debug adapter supports single thread execution (see capability + 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other + suspended threads from resuming. + + The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the + step has completed. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "stepOut" + ] + }, + "arguments": { + "type": "StepOutArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param StepOutArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'stepOut' + if arguments is None: + self.arguments = StepOutArguments() + else: + self.arguments = StepOutArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != StepOutArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class StepOutArguments(BaseSchema): + """ + Arguments for 'stepOut' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Specifies the thread for which to resume execution for one step-out (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." + }, + "granularity": { + "description": "Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed.", + "type": "SteppingGranularity" + } + } + __refs__ = set(['granularity']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, singleThread=None, granularity=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Specifies the thread for which to resume execution for one step-out (of the given granularity). + :param boolean singleThread: If this optional flag is true, all other suspended threads are not resumed. + :param SteppingGranularity granularity: Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. + """ + self.threadId = threadId + self.singleThread = singleThread + if granularity is not None: + assert granularity in SteppingGranularity.VALID_VALUES + self.granularity = granularity + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + singleThread = self.singleThread + granularity = self.granularity + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + if singleThread is not None: + dct['singleThread'] = singleThread + if granularity is not None: + dct['granularity'] = granularity + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('stepOut') +@register +class StepOutResponse(BaseSchema): + """ + Response to 'stepOut' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('stepBack') +@register +class StepBackRequest(BaseSchema): + """ + The request executes one backward step (in the given granularity) for the specified thread and + allows all other threads to run backward freely by resuming them. + + If the debug adapter supports single thread execution (see capability + 'supportsSingleThreadExecutionRequests') setting the 'singleThread' argument to true prevents other + suspended threads from resuming. + + The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the + step has completed. + + Clients should only call this request if the capability 'supportsStepBack' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "stepBack" + ] + }, + "arguments": { + "type": "StepBackArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param StepBackArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'stepBack' + if arguments is None: + self.arguments = StepBackArguments() + else: + self.arguments = StepBackArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != StepBackArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class StepBackArguments(BaseSchema): + """ + Arguments for 'stepBack' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Specifies the thread for which to resume execution for one step backwards (of the given granularity)." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, all other suspended threads are not resumed." + }, + "granularity": { + "description": "Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed.", + "type": "SteppingGranularity" + } + } + __refs__ = set(['granularity']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, singleThread=None, granularity=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Specifies the thread for which to resume execution for one step backwards (of the given granularity). + :param boolean singleThread: If this optional flag is true, all other suspended threads are not resumed. + :param SteppingGranularity granularity: Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. + """ + self.threadId = threadId + self.singleThread = singleThread + if granularity is not None: + assert granularity in SteppingGranularity.VALID_VALUES + self.granularity = granularity + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + singleThread = self.singleThread + granularity = self.granularity + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + if singleThread is not None: + dct['singleThread'] = singleThread + if granularity is not None: + dct['granularity'] = granularity + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('stepBack') +@register +class StepBackResponse(BaseSchema): + """ + Response to 'stepBack' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('reverseContinue') +@register +class ReverseContinueRequest(BaseSchema): + """ + The request resumes backward execution of all threads. If the debug adapter supports single thread + execution (see capability 'supportsSingleThreadExecutionRequests') setting the 'singleThread' + argument to true resumes only the specified thread. If not all threads were resumed, the + 'allThreadsContinued' attribute of the response must be set to false. + + Clients should only call this request if the capability 'supportsStepBack' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "reverseContinue" + ] + }, + "arguments": { + "type": "ReverseContinueArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param ReverseContinueArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'reverseContinue' + if arguments is None: + self.arguments = ReverseContinueArguments() + else: + self.arguments = ReverseContinueArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != ReverseContinueArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class ReverseContinueArguments(BaseSchema): + """ + Arguments for 'reverseContinue' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed." + }, + "singleThread": { + "type": "boolean", + "description": "If this optional flag is true, backward execution is resumed only for the thread with given 'threadId'." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, singleThread=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Specifies the active thread. If the debug adapter supports single thread execution (see 'supportsSingleThreadExecutionRequests') and the optional argument 'singleThread' is true, only the thread with this ID is resumed. + :param boolean singleThread: If this optional flag is true, backward execution is resumed only for the thread with given 'threadId'. + """ + self.threadId = threadId + self.singleThread = singleThread + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + singleThread = self.singleThread + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + if singleThread is not None: + dct['singleThread'] = singleThread + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('reverseContinue') +@register +class ReverseContinueResponse(BaseSchema): + """ + Response to 'reverseContinue' request. This is just an acknowledgement, so no body field is + required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('restartFrame') +@register +class RestartFrameRequest(BaseSchema): + """ + The request restarts execution of the specified stackframe. + + The debug adapter first sends the response and then a 'stopped' event (with reason 'restart') after + the restart has completed. + + Clients should only call this request if the capability 'supportsRestartFrame' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "restartFrame" + ] + }, + "arguments": { + "type": "RestartFrameArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param RestartFrameArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'restartFrame' + if arguments is None: + self.arguments = RestartFrameArguments() + else: + self.arguments = RestartFrameArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != RestartFrameArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class RestartFrameArguments(BaseSchema): + """ + Arguments for 'restartFrame' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "frameId": { + "type": "integer", + "description": "Restart this stackframe." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, frameId, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer frameId: Restart this stackframe. + """ + self.frameId = frameId + if update_ids_from_dap: + self.frameId = self._translate_id_from_dap(self.frameId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_from_dap(dct['frameId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + frameId = self.frameId + if update_ids_to_dap: + if frameId is not None: + frameId = self._translate_id_to_dap(frameId) + dct = { + 'frameId': frameId, + } + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_to_dap(dct['frameId']) + return dct + + +@register_response('restartFrame') +@register +class RestartFrameResponse(BaseSchema): + """ + Response to 'restartFrame' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('goto') +@register +class GotoRequest(BaseSchema): + """ + The request sets the location where the debuggee will continue to run. + + This makes it possible to skip the execution of code or to executed code again. + + The code between the current location and the goto target is not executed but skipped. + + The debug adapter first sends the response and then a 'stopped' event with reason 'goto'. + + Clients should only call this request if the capability 'supportsGotoTargetsRequest' is true + (because only then goto targets exist that can be passed as arguments). + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "goto" + ] + }, + "arguments": { + "type": "GotoArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param GotoArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'goto' + if arguments is None: + self.arguments = GotoArguments() + else: + self.arguments = GotoArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != GotoArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class GotoArguments(BaseSchema): + """ + Arguments for 'goto' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Set the goto target for this thread." + }, + "targetId": { + "type": "integer", + "description": "The location where the debuggee will continue to run." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, targetId, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Set the goto target for this thread. + :param integer targetId: The location where the debuggee will continue to run. + """ + self.threadId = threadId + self.targetId = targetId + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + targetId = self.targetId + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + 'targetId': targetId, + } + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('goto') +@register +class GotoResponse(BaseSchema): + """ + Response to 'goto' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('pause') +@register +class PauseRequest(BaseSchema): + """ + The request suspends the debuggee. + + The debug adapter first sends the response and then a 'stopped' event (with reason 'pause') after + the thread has been paused successfully. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "pause" + ] + }, + "arguments": { + "type": "PauseArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param PauseArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'pause' + if arguments is None: + self.arguments = PauseArguments() + else: + self.arguments = PauseArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != PauseArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class PauseArguments(BaseSchema): + """ + Arguments for 'pause' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Pause execution for this thread." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Pause execution for this thread. + """ + self.threadId = threadId + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('pause') +@register +class PauseResponse(BaseSchema): + """ + Response to 'pause' request. This is just an acknowledgement, so no body field is required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('stackTrace') +@register +class StackTraceRequest(BaseSchema): + """ + The request returns a stacktrace from the current execution state of a given thread. + + A client can request all stack frames by omitting the startFrame and levels arguments. For + performance conscious clients and if the debug adapter's 'supportsDelayedStackTraceLoading' + capability is true, stack frames can be retrieved in a piecemeal way with the startFrame and levels + arguments. The response of the stackTrace request may contain a totalFrames property that hints at + the total number of frames in the stack. If a client needs this total number upfront, it can issue a + request for a single (first) frame and depending on the value of totalFrames decide how to proceed. + In any case a client should be prepared to receive less frames than requested, which is an + indication that the end of the stack has been reached. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "stackTrace" + ] + }, + "arguments": { + "type": "StackTraceArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param StackTraceArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'stackTrace' + if arguments is None: + self.arguments = StackTraceArguments() + else: + self.arguments = StackTraceArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != StackTraceArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class StackTraceArguments(BaseSchema): + """ + Arguments for 'stackTrace' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Retrieve the stacktrace for this thread." + }, + "startFrame": { + "type": "integer", + "description": "The index of the first frame to return; if omitted frames start at 0." + }, + "levels": { + "type": "integer", + "description": "The maximum number of frames to return. If levels is not specified or 0, all frames are returned." + }, + "format": { + "description": "Specifies details on how to format the stack frames.\nThe attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true.", + "type": "StackFrameFormat" + } + } + __refs__ = set(['format']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, startFrame=None, levels=None, format=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Retrieve the stacktrace for this thread. + :param integer startFrame: The index of the first frame to return; if omitted frames start at 0. + :param integer levels: The maximum number of frames to return. If levels is not specified or 0, all frames are returned. + :param StackFrameFormat format: Specifies details on how to format the stack frames. + The attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true. + """ + self.threadId = threadId + self.startFrame = startFrame + self.levels = levels + if format is None: + self.format = StackFrameFormat() + else: + self.format = StackFrameFormat(update_ids_from_dap=update_ids_from_dap, **format) if format.__class__ != StackFrameFormat else format + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + startFrame = self.startFrame + levels = self.levels + format = self.format # noqa (assign to builtin) + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + if startFrame is not None: + dct['startFrame'] = startFrame + if levels is not None: + dct['levels'] = levels + if format is not None: + dct['format'] = format.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('stackTrace') +@register +class StackTraceResponse(BaseSchema): + """ + Response to 'stackTrace' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "stackFrames": { + "type": "array", + "items": { + "$ref": "#/definitions/StackFrame" + }, + "description": "The frames of the stackframe. If the array has length zero, there are no stackframes available.\nThis means that there is no location information available." + }, + "totalFrames": { + "type": "integer", + "description": "The total number of frames available in the stack. If omitted or if totalFrames is larger than the available frames, a client is expected to request frames until a request returns less frames than requested (which indicates the end of the stack). Returning monotonically increasing totalFrames values for subsequent requests can be used to enforce paging in the client." + } + }, + "required": [ + "stackFrames" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param StackTraceResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = StackTraceResponseBody() + else: + self.body = StackTraceResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != StackTraceResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('scopes') +@register +class ScopesRequest(BaseSchema): + """ + The request returns the variable scopes for a given stackframe ID. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "scopes" + ] + }, + "arguments": { + "type": "ScopesArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param ScopesArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'scopes' + if arguments is None: + self.arguments = ScopesArguments() + else: + self.arguments = ScopesArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != ScopesArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class ScopesArguments(BaseSchema): + """ + Arguments for 'scopes' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "frameId": { + "type": "integer", + "description": "Retrieve the scopes for this stackframe." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, frameId, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer frameId: Retrieve the scopes for this stackframe. + """ + self.frameId = frameId + if update_ids_from_dap: + self.frameId = self._translate_id_from_dap(self.frameId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_from_dap(dct['frameId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + frameId = self.frameId + if update_ids_to_dap: + if frameId is not None: + frameId = self._translate_id_to_dap(frameId) + dct = { + 'frameId': frameId, + } + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_to_dap(dct['frameId']) + return dct + + +@register_response('scopes') +@register +class ScopesResponse(BaseSchema): + """ + Response to 'scopes' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "scopes": { + "type": "array", + "items": { + "$ref": "#/definitions/Scope" + }, + "description": "The scopes of the stackframe. If the array has length zero, there are no scopes available." + } + }, + "required": [ + "scopes" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param ScopesResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = ScopesResponseBody() + else: + self.body = ScopesResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ScopesResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('variables') +@register +class VariablesRequest(BaseSchema): + """ + Retrieves all child variables for the given variable reference. + + An optional filter can be used to limit the fetched children to either named or indexed children. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "variables" + ] + }, + "arguments": { + "type": "VariablesArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param VariablesArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'variables' + if arguments is None: + self.arguments = VariablesArguments() + else: + self.arguments = VariablesArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != VariablesArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class VariablesArguments(BaseSchema): + """ + Arguments for 'variables' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "variablesReference": { + "type": "integer", + "description": "The Variable reference." + }, + "filter": { + "type": "string", + "enum": [ + "indexed", + "named" + ], + "description": "Optional filter to limit the child variables to either named or indexed. If omitted, both types are fetched." + }, + "start": { + "type": "integer", + "description": "The index of the first variable to return; if omitted children start at 0." + }, + "count": { + "type": "integer", + "description": "The number of variables to return. If count is missing or 0, all variables are returned." + }, + "format": { + "description": "Specifies details on how to format the Variable values.\nThe attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true.", + "type": "ValueFormat" + } + } + __refs__ = set(['format']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, variablesReference, filter=None, start=None, count=None, format=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer variablesReference: The Variable reference. + :param string filter: Optional filter to limit the child variables to either named or indexed. If omitted, both types are fetched. + :param integer start: The index of the first variable to return; if omitted children start at 0. + :param integer count: The number of variables to return. If count is missing or 0, all variables are returned. + :param ValueFormat format: Specifies details on how to format the Variable values. + The attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true. + """ + self.variablesReference = variablesReference + self.filter = filter + self.start = start + self.count = count + if format is None: + self.format = ValueFormat() + else: + self.format = ValueFormat(update_ids_from_dap=update_ids_from_dap, **format) if format.__class__ != ValueFormat else format + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + variablesReference = self.variablesReference + filter = self.filter # noqa (assign to builtin) + start = self.start + count = self.count + format = self.format # noqa (assign to builtin) + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'variablesReference': variablesReference, + } + if filter is not None: + dct['filter'] = filter + if start is not None: + dct['start'] = start + if count is not None: + dct['count'] = count + if format is not None: + dct['format'] = format.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register_response('variables') +@register +class VariablesResponse(BaseSchema): + """ + Response to 'variables' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/Variable" + }, + "description": "All (or a range) of variables for the given variable reference." + } + }, + "required": [ + "variables" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param VariablesResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = VariablesResponseBody() + else: + self.body = VariablesResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != VariablesResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('setVariable') +@register +class SetVariableRequest(BaseSchema): + """ + Set the variable with the given name in the variable container to a new value. Clients should only + call this request if the capability 'supportsSetVariable' is true. + + If a debug adapter implements both setVariable and setExpression, a client will only use + setExpression if the variable has an evaluateName property. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setVariable" + ] + }, + "arguments": { + "type": "SetVariableArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetVariableArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setVariable' + if arguments is None: + self.arguments = SetVariableArguments() + else: + self.arguments = SetVariableArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetVariableArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetVariableArguments(BaseSchema): + """ + Arguments for 'setVariable' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "variablesReference": { + "type": "integer", + "description": "The reference of the variable container." + }, + "name": { + "type": "string", + "description": "The name of the variable in the container." + }, + "value": { + "type": "string", + "description": "The value of the variable." + }, + "format": { + "description": "Specifies details on how to format the response value.", + "type": "ValueFormat" + } + } + __refs__ = set(['format']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, variablesReference, name, value, format=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer variablesReference: The reference of the variable container. + :param string name: The name of the variable in the container. + :param string value: The value of the variable. + :param ValueFormat format: Specifies details on how to format the response value. + """ + self.variablesReference = variablesReference + self.name = name + self.value = value + if format is None: + self.format = ValueFormat() + else: + self.format = ValueFormat(update_ids_from_dap=update_ids_from_dap, **format) if format.__class__ != ValueFormat else format + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + variablesReference = self.variablesReference + name = self.name + value = self.value + format = self.format # noqa (assign to builtin) + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'variablesReference': variablesReference, + 'name': name, + 'value': value, + } + if format is not None: + dct['format'] = format.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register_response('setVariable') +@register +class SetVariableResponse(BaseSchema): + """ + Response to 'setVariable' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "The new value of the variable." + }, + "type": { + "type": "string", + "description": "The type of the new value. Typically shown in the UI when hovering over the value." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the new value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + } + }, + "required": [ + "value" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param SetVariableResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = SetVariableResponseBody() + else: + self.body = SetVariableResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != SetVariableResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('source') +@register +class SourceRequest(BaseSchema): + """ + The request retrieves the source code for a given source reference. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "source" + ] + }, + "arguments": { + "type": "SourceArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SourceArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'source' + if arguments is None: + self.arguments = SourceArguments() + else: + self.arguments = SourceArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SourceArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SourceArguments(BaseSchema): + """ + Arguments for 'source' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "source": { + "description": "Specifies the source content to load. Either source.path or source.sourceReference must be specified.", + "type": "Source" + }, + "sourceReference": { + "type": "integer", + "description": "The reference to the source. This is the same as source.sourceReference.\nThis is provided for backward compatibility since old backends do not understand the 'source' attribute." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, sourceReference, source=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer sourceReference: The reference to the source. This is the same as source.sourceReference. + This is provided for backward compatibility since old backends do not understand the 'source' attribute. + :param Source source: Specifies the source content to load. Either source.path or source.sourceReference must be specified. + """ + self.sourceReference = sourceReference + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + sourceReference = self.sourceReference + source = self.source + dct = { + 'sourceReference': sourceReference, + } + if source is not None: + dct['source'] = source.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register_response('source') +@register +class SourceResponse(BaseSchema): + """ + Response to 'source' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "content": { + "type": "string", + "description": "Content of the source reference." + }, + "mimeType": { + "type": "string", + "description": "Optional content type (mime type) of the source." + } + }, + "required": [ + "content" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param SourceResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = SourceResponseBody() + else: + self.body = SourceResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != SourceResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('threads') +@register +class ThreadsRequest(BaseSchema): + """ + The request retrieves a list of all threads. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "threads" + ] + }, + "arguments": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Object containing arguments for the command." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] arguments: Object containing arguments for the command. + """ + self.type = 'request' + self.command = 'threads' + self.seq = seq + self.arguments = arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments + dct.update(self.kwargs) + return dct + + +@register_response('threads') +@register +class ThreadsResponse(BaseSchema): + """ + Response to 'threads' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "threads": { + "type": "array", + "items": { + "$ref": "#/definitions/Thread" + }, + "description": "All threads." + } + }, + "required": [ + "threads" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param ThreadsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = ThreadsResponseBody() + else: + self.body = ThreadsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ThreadsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('terminateThreads') +@register +class TerminateThreadsRequest(BaseSchema): + """ + The request terminates the threads with the given ids. + + Clients should only call this request if the capability 'supportsTerminateThreadsRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "terminateThreads" + ] + }, + "arguments": { + "type": "TerminateThreadsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param TerminateThreadsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'terminateThreads' + if arguments is None: + self.arguments = TerminateThreadsArguments() + else: + self.arguments = TerminateThreadsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != TerminateThreadsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class TerminateThreadsArguments(BaseSchema): + """ + Arguments for 'terminateThreads' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadIds": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Ids of threads to be terminated." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadIds=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array threadIds: Ids of threads to be terminated. + """ + self.threadIds = threadIds + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadIds = self.threadIds + if threadIds and hasattr(threadIds[0], "to_dict"): + threadIds = [x.to_dict() for x in threadIds] + dct = { + } + if threadIds is not None: + dct['threadIds'] = threadIds + dct.update(self.kwargs) + return dct + + +@register_response('terminateThreads') +@register +class TerminateThreadsResponse(BaseSchema): + """ + Response to 'terminateThreads' request. This is just an acknowledgement, so no body field is + required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('modules') +@register +class ModulesRequest(BaseSchema): + """ + Modules can be retrieved from the debug adapter with this request which can either return all + modules or a range of modules to support paging. + + Clients should only call this request if the capability 'supportsModulesRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "modules" + ] + }, + "arguments": { + "type": "ModulesArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param ModulesArguments arguments: + """ + self.type = 'request' + self.command = 'modules' + self.seq = seq + if arguments is None: + self.arguments = ModulesArguments() + else: + self.arguments = ModulesArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != ModulesArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class ModulesArguments(BaseSchema): + """ + Arguments for 'modules' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "startModule": { + "type": "integer", + "description": "The index of the first module to return; if omitted modules start at 0." + }, + "moduleCount": { + "type": "integer", + "description": "The number of modules to return. If moduleCount is not specified or 0, all modules are returned." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, startModule=None, moduleCount=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer startModule: The index of the first module to return; if omitted modules start at 0. + :param integer moduleCount: The number of modules to return. If moduleCount is not specified or 0, all modules are returned. + """ + self.startModule = startModule + self.moduleCount = moduleCount + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + startModule = self.startModule + moduleCount = self.moduleCount + dct = { + } + if startModule is not None: + dct['startModule'] = startModule + if moduleCount is not None: + dct['moduleCount'] = moduleCount + dct.update(self.kwargs) + return dct + + +@register_response('modules') +@register +class ModulesResponse(BaseSchema): + """ + Response to 'modules' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "modules": { + "type": "array", + "items": { + "$ref": "#/definitions/Module" + }, + "description": "All modules or range of modules." + }, + "totalModules": { + "type": "integer", + "description": "The total number of modules available." + } + }, + "required": [ + "modules" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param ModulesResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = ModulesResponseBody() + else: + self.body = ModulesResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ModulesResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('loadedSources') +@register +class LoadedSourcesRequest(BaseSchema): + """ + Retrieves the set of all sources currently loaded by the debugged process. + + Clients should only call this request if the capability 'supportsLoadedSourcesRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "loadedSources" + ] + }, + "arguments": { + "type": "LoadedSourcesArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param LoadedSourcesArguments arguments: + """ + self.type = 'request' + self.command = 'loadedSources' + self.seq = seq + if arguments is None: + self.arguments = LoadedSourcesArguments() + else: + self.arguments = LoadedSourcesArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != LoadedSourcesArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class LoadedSourcesArguments(BaseSchema): + """ + Arguments for 'loadedSources' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register_response('loadedSources') +@register +class LoadedSourcesResponse(BaseSchema): + """ + Response to 'loadedSources' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "$ref": "#/definitions/Source" + }, + "description": "Set of loaded sources." + } + }, + "required": [ + "sources" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param LoadedSourcesResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = LoadedSourcesResponseBody() + else: + self.body = LoadedSourcesResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != LoadedSourcesResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('evaluate') +@register +class EvaluateRequest(BaseSchema): + """ + Evaluates the given expression in the context of the top most stack frame. + + The expression has access to any variables and arguments that are in scope. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "evaluate" + ] + }, + "arguments": { + "type": "EvaluateArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param EvaluateArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'evaluate' + if arguments is None: + self.arguments = EvaluateArguments() + else: + self.arguments = EvaluateArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != EvaluateArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class EvaluateArguments(BaseSchema): + """ + Arguments for 'evaluate' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "expression": { + "type": "string", + "description": "The expression to evaluate." + }, + "frameId": { + "type": "integer", + "description": "Evaluate the expression in the scope of this stack frame. If not specified, the expression is evaluated in the global scope." + }, + "context": { + "type": "string", + "_enum": [ + "watch", + "repl", + "hover", + "clipboard" + ], + "enumDescriptions": [ + "evaluate is run in a watch.", + "evaluate is run from REPL console.", + "evaluate is run from a data hover.", + "evaluate is run to generate the value that will be stored in the clipboard.\nThe attribute is only honored by a debug adapter if the capability 'supportsClipboardContext' is true." + ], + "description": "The context in which the evaluate request is run." + }, + "format": { + "description": "Specifies details on how to format the Evaluate result.\nThe attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true.", + "type": "ValueFormat" + } + } + __refs__ = set(['format']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, expression, frameId=None, context=None, format=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string expression: The expression to evaluate. + :param integer frameId: Evaluate the expression in the scope of this stack frame. If not specified, the expression is evaluated in the global scope. + :param string context: The context in which the evaluate request is run. + :param ValueFormat format: Specifies details on how to format the Evaluate result. + The attribute is only honored by a debug adapter if the capability 'supportsValueFormattingOptions' is true. + """ + self.expression = expression + self.frameId = frameId + self.context = context + if format is None: + self.format = ValueFormat() + else: + self.format = ValueFormat(update_ids_from_dap=update_ids_from_dap, **format) if format.__class__ != ValueFormat else format + if update_ids_from_dap: + self.frameId = self._translate_id_from_dap(self.frameId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_from_dap(dct['frameId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + expression = self.expression + frameId = self.frameId + context = self.context + format = self.format # noqa (assign to builtin) + if update_ids_to_dap: + if frameId is not None: + frameId = self._translate_id_to_dap(frameId) + dct = { + 'expression': expression, + } + if frameId is not None: + dct['frameId'] = frameId + if context is not None: + dct['context'] = context + if format is not None: + dct['format'] = format.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_to_dap(dct['frameId']) + return dct + + +@register_response('evaluate') +@register +class EvaluateResponse(BaseSchema): + """ + Response to 'evaluate' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "result": { + "type": "string", + "description": "The result of the evaluate request." + }, + "type": { + "type": "string", + "description": "The optional type of the evaluate result.\nThis attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request." + }, + "presentationHint": { + "$ref": "#/definitions/VariablePresentationHint", + "description": "Properties of a evaluate result that can be used to determine how to render the result in the UI." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the evaluate result is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "memoryReference": { + "type": "string", + "description": "Optional memory reference to a location appropriate for this result.\nFor pointer type eval results, this is generally a reference to the memory address contained in the pointer.\nThis attribute should be returned by a debug adapter if the client has passed the value true for the 'supportsMemoryReferences' capability of the 'initialize' request." + } + }, + "required": [ + "result", + "variablesReference" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param EvaluateResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = EvaluateResponseBody() + else: + self.body = EvaluateResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != EvaluateResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('setExpression') +@register +class SetExpressionRequest(BaseSchema): + """ + Evaluates the given 'value' expression and assigns it to the 'expression' which must be a modifiable + l-value. + + The expressions have access to any variables and arguments that are in scope of the specified frame. + + Clients should only call this request if the capability 'supportsSetExpression' is true. + + If a debug adapter implements both setExpression and setVariable, a client will only use + setExpression if the variable has an evaluateName property. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setExpression" + ] + }, + "arguments": { + "type": "SetExpressionArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetExpressionArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setExpression' + if arguments is None: + self.arguments = SetExpressionArguments() + else: + self.arguments = SetExpressionArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetExpressionArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetExpressionArguments(BaseSchema): + """ + Arguments for 'setExpression' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "expression": { + "type": "string", + "description": "The l-value expression to assign to." + }, + "value": { + "type": "string", + "description": "The value expression to assign to the l-value expression." + }, + "frameId": { + "type": "integer", + "description": "Evaluate the expressions in the scope of this stack frame. If not specified, the expressions are evaluated in the global scope." + }, + "format": { + "description": "Specifies how the resulting value should be formatted.", + "type": "ValueFormat" + } + } + __refs__ = set(['format']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, expression, value, frameId=None, format=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string expression: The l-value expression to assign to. + :param string value: The value expression to assign to the l-value expression. + :param integer frameId: Evaluate the expressions in the scope of this stack frame. If not specified, the expressions are evaluated in the global scope. + :param ValueFormat format: Specifies how the resulting value should be formatted. + """ + self.expression = expression + self.value = value + self.frameId = frameId + if format is None: + self.format = ValueFormat() + else: + self.format = ValueFormat(update_ids_from_dap=update_ids_from_dap, **format) if format.__class__ != ValueFormat else format + if update_ids_from_dap: + self.frameId = self._translate_id_from_dap(self.frameId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_from_dap(dct['frameId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + expression = self.expression + value = self.value + frameId = self.frameId + format = self.format # noqa (assign to builtin) + if update_ids_to_dap: + if frameId is not None: + frameId = self._translate_id_to_dap(frameId) + dct = { + 'expression': expression, + 'value': value, + } + if frameId is not None: + dct['frameId'] = frameId + if format is not None: + dct['format'] = format.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_to_dap(dct['frameId']) + return dct + + +@register_response('setExpression') +@register +class SetExpressionResponse(BaseSchema): + """ + Response to 'setExpression' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "The new value of the expression." + }, + "type": { + "type": "string", + "description": "The optional type of the value.\nThis attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request." + }, + "presentationHint": { + "$ref": "#/definitions/VariablePresentationHint", + "description": "Properties of a value that can be used to determine how to render the result in the UI." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + } + }, + "required": [ + "value" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param SetExpressionResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = SetExpressionResponseBody() + else: + self.body = SetExpressionResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != SetExpressionResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('stepInTargets') +@register +class StepInTargetsRequest(BaseSchema): + """ + This request retrieves the possible stepIn targets for the specified stack frame. + + These targets can be used in the 'stepIn' request. + + The StepInTargets may only be called if the 'supportsStepInTargetsRequest' capability exists and is + true. + + Clients should only call this request if the capability 'supportsStepInTargetsRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "stepInTargets" + ] + }, + "arguments": { + "type": "StepInTargetsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param StepInTargetsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'stepInTargets' + if arguments is None: + self.arguments = StepInTargetsArguments() + else: + self.arguments = StepInTargetsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != StepInTargetsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class StepInTargetsArguments(BaseSchema): + """ + Arguments for 'stepInTargets' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "frameId": { + "type": "integer", + "description": "The stack frame for which to retrieve the possible stepIn targets." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, frameId, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer frameId: The stack frame for which to retrieve the possible stepIn targets. + """ + self.frameId = frameId + if update_ids_from_dap: + self.frameId = self._translate_id_from_dap(self.frameId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_from_dap(dct['frameId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + frameId = self.frameId + if update_ids_to_dap: + if frameId is not None: + frameId = self._translate_id_to_dap(frameId) + dct = { + 'frameId': frameId, + } + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_to_dap(dct['frameId']) + return dct + + +@register_response('stepInTargets') +@register +class StepInTargetsResponse(BaseSchema): + """ + Response to 'stepInTargets' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/StepInTarget" + }, + "description": "The possible stepIn targets of the specified source location." + } + }, + "required": [ + "targets" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param StepInTargetsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = StepInTargetsResponseBody() + else: + self.body = StepInTargetsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != StepInTargetsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('gotoTargets') +@register +class GotoTargetsRequest(BaseSchema): + """ + This request retrieves the possible goto targets for the specified source location. + + These targets can be used in the 'goto' request. + + Clients should only call this request if the capability 'supportsGotoTargetsRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "gotoTargets" + ] + }, + "arguments": { + "type": "GotoTargetsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param GotoTargetsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'gotoTargets' + if arguments is None: + self.arguments = GotoTargetsArguments() + else: + self.arguments = GotoTargetsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != GotoTargetsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class GotoTargetsArguments(BaseSchema): + """ + Arguments for 'gotoTargets' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "source": { + "description": "The source location for which the goto targets are determined.", + "type": "Source" + }, + "line": { + "type": "integer", + "description": "The line location for which the goto targets are determined." + }, + "column": { + "type": "integer", + "description": "An optional column location for which the goto targets are determined." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, source, line, column=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param Source source: The source location for which the goto targets are determined. + :param integer line: The line location for which the goto targets are determined. + :param integer column: An optional column location for which the goto targets are determined. + """ + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.line = line + self.column = column + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + source = self.source + line = self.line + column = self.column + dct = { + 'source': source.to_dict(update_ids_to_dap=update_ids_to_dap), + 'line': line, + } + if column is not None: + dct['column'] = column + dct.update(self.kwargs) + return dct + + +@register_response('gotoTargets') +@register +class GotoTargetsResponse(BaseSchema): + """ + Response to 'gotoTargets' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/GotoTarget" + }, + "description": "The possible goto targets of the specified location." + } + }, + "required": [ + "targets" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param GotoTargetsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = GotoTargetsResponseBody() + else: + self.body = GotoTargetsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != GotoTargetsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('completions') +@register +class CompletionsRequest(BaseSchema): + """ + Returns a list of possible completions for a given caret position and text. + + Clients should only call this request if the capability 'supportsCompletionsRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "completions" + ] + }, + "arguments": { + "type": "CompletionsArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param CompletionsArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'completions' + if arguments is None: + self.arguments = CompletionsArguments() + else: + self.arguments = CompletionsArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != CompletionsArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class CompletionsArguments(BaseSchema): + """ + Arguments for 'completions' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "frameId": { + "type": "integer", + "description": "Returns completions in the scope of this stack frame. If not specified, the completions are returned for the global scope." + }, + "text": { + "type": "string", + "description": "One or more source lines. Typically this is the text a user has typed into the debug console before he asked for completion." + }, + "column": { + "type": "integer", + "description": "The character position for which to determine the completion proposals." + }, + "line": { + "type": "integer", + "description": "An optional line for which to determine the completion proposals. If missing the first line of the text is assumed." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, text, column, frameId=None, line=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string text: One or more source lines. Typically this is the text a user has typed into the debug console before he asked for completion. + :param integer column: The character position for which to determine the completion proposals. + :param integer frameId: Returns completions in the scope of this stack frame. If not specified, the completions are returned for the global scope. + :param integer line: An optional line for which to determine the completion proposals. If missing the first line of the text is assumed. + """ + self.text = text + self.column = column + self.frameId = frameId + self.line = line + if update_ids_from_dap: + self.frameId = self._translate_id_from_dap(self.frameId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_from_dap(dct['frameId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + text = self.text + column = self.column + frameId = self.frameId + line = self.line + if update_ids_to_dap: + if frameId is not None: + frameId = self._translate_id_to_dap(frameId) + dct = { + 'text': text, + 'column': column, + } + if frameId is not None: + dct['frameId'] = frameId + if line is not None: + dct['line'] = line + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'frameId' in dct: + dct['frameId'] = cls._translate_id_to_dap(dct['frameId']) + return dct + + +@register_response('completions') +@register +class CompletionsResponse(BaseSchema): + """ + Response to 'completions' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/CompletionItem" + }, + "description": "The possible completions for ." + } + }, + "required": [ + "targets" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param CompletionsResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = CompletionsResponseBody() + else: + self.body = CompletionsResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != CompletionsResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('exceptionInfo') +@register +class ExceptionInfoRequest(BaseSchema): + """ + Retrieves the details of the exception that caused this event to be raised. + + Clients should only call this request if the capability 'supportsExceptionInfoRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "exceptionInfo" + ] + }, + "arguments": { + "type": "ExceptionInfoArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param ExceptionInfoArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'exceptionInfo' + if arguments is None: + self.arguments = ExceptionInfoArguments() + else: + self.arguments = ExceptionInfoArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != ExceptionInfoArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class ExceptionInfoArguments(BaseSchema): + """ + Arguments for 'exceptionInfo' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "Thread for which exception information should be retrieved." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: Thread for which exception information should be retrieved. + """ + self.threadId = threadId + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register_response('exceptionInfo') +@register +class ExceptionInfoResponse(BaseSchema): + """ + Response to 'exceptionInfo' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "exceptionId": { + "type": "string", + "description": "ID of the exception that was thrown." + }, + "description": { + "type": "string", + "description": "Descriptive text for the exception provided by the debug adapter." + }, + "breakMode": { + "$ref": "#/definitions/ExceptionBreakMode", + "description": "Mode that caused the exception notification to be raised." + }, + "details": { + "$ref": "#/definitions/ExceptionDetails", + "description": "Detailed information about the exception." + } + }, + "required": [ + "exceptionId", + "breakMode" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param ExceptionInfoResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = ExceptionInfoResponseBody() + else: + self.body = ExceptionInfoResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ExceptionInfoResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register_request('readMemory') +@register +class ReadMemoryRequest(BaseSchema): + """ + Reads bytes from memory at the provided location. + + Clients should only call this request if the capability 'supportsReadMemoryRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "readMemory" + ] + }, + "arguments": { + "type": "ReadMemoryArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param ReadMemoryArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'readMemory' + if arguments is None: + self.arguments = ReadMemoryArguments() + else: + self.arguments = ReadMemoryArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != ReadMemoryArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class ReadMemoryArguments(BaseSchema): + """ + Arguments for 'readMemory' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "memoryReference": { + "type": "string", + "description": "Memory reference to the base location from which data should be read." + }, + "offset": { + "type": "integer", + "description": "Optional offset (in bytes) to be applied to the reference location before reading data. Can be negative." + }, + "count": { + "type": "integer", + "description": "Number of bytes to read at the specified location and offset." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, memoryReference, count, offset=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string memoryReference: Memory reference to the base location from which data should be read. + :param integer count: Number of bytes to read at the specified location and offset. + :param integer offset: Optional offset (in bytes) to be applied to the reference location before reading data. Can be negative. + """ + self.memoryReference = memoryReference + self.count = count + self.offset = offset + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + memoryReference = self.memoryReference + count = self.count + offset = self.offset + dct = { + 'memoryReference': memoryReference, + 'count': count, + } + if offset is not None: + dct['offset'] = offset + dct.update(self.kwargs) + return dct + + +@register_response('readMemory') +@register +class ReadMemoryResponse(BaseSchema): + """ + Response to 'readMemory' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "The address of the first byte of data returned.\nTreated as a hex value if prefixed with '0x', or as a decimal value otherwise." + }, + "unreadableBytes": { + "type": "integer", + "description": "The number of unreadable bytes encountered after the last successfully read byte.\nThis can be used to determine the number of bytes that must be skipped before a subsequent 'readMemory' request will succeed." + }, + "data": { + "type": "string", + "description": "The bytes read from memory, encoded using base64." + } + }, + "required": [ + "address" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ReadMemoryResponseBody body: + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + if body is None: + self.body = ReadMemoryResponseBody() + else: + self.body = ReadMemoryResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != ReadMemoryResponseBody else body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register_request('writeMemory') +@register +class WriteMemoryRequest(BaseSchema): + """ + Writes bytes to memory at the provided location. + + Clients should only call this request if the capability 'supportsWriteMemoryRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "writeMemory" + ] + }, + "arguments": { + "type": "WriteMemoryArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param WriteMemoryArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'writeMemory' + if arguments is None: + self.arguments = WriteMemoryArguments() + else: + self.arguments = WriteMemoryArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != WriteMemoryArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class WriteMemoryArguments(BaseSchema): + """ + Arguments for 'writeMemory' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "memoryReference": { + "type": "string", + "description": "Memory reference to the base location to which data should be written." + }, + "offset": { + "type": "integer", + "description": "Optional offset (in bytes) to be applied to the reference location before writing data. Can be negative." + }, + "allowPartial": { + "type": "boolean", + "description": "Optional property to control partial writes. If true, the debug adapter should attempt to write memory even if the entire memory region is not writable. In such a case the debug adapter should stop after hitting the first byte of memory that cannot be written and return the number of bytes written in the response via the 'offset' and 'bytesWritten' properties.\nIf false or missing, a debug adapter should attempt to verify the region is writable before writing, and fail the response if it is not." + }, + "data": { + "type": "string", + "description": "Bytes to write, encoded using base64." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, memoryReference, data, offset=None, allowPartial=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string memoryReference: Memory reference to the base location to which data should be written. + :param string data: Bytes to write, encoded using base64. + :param integer offset: Optional offset (in bytes) to be applied to the reference location before writing data. Can be negative. + :param boolean allowPartial: Optional property to control partial writes. If true, the debug adapter should attempt to write memory even if the entire memory region is not writable. In such a case the debug adapter should stop after hitting the first byte of memory that cannot be written and return the number of bytes written in the response via the 'offset' and 'bytesWritten' properties. + If false or missing, a debug adapter should attempt to verify the region is writable before writing, and fail the response if it is not. + """ + self.memoryReference = memoryReference + self.data = data + self.offset = offset + self.allowPartial = allowPartial + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + memoryReference = self.memoryReference + data = self.data + offset = self.offset + allowPartial = self.allowPartial + dct = { + 'memoryReference': memoryReference, + 'data': data, + } + if offset is not None: + dct['offset'] = offset + if allowPartial is not None: + dct['allowPartial'] = allowPartial + dct.update(self.kwargs) + return dct + + +@register_response('writeMemory') +@register +class WriteMemoryResponse(BaseSchema): + """ + Response to 'writeMemory' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "offset": { + "type": "integer", + "description": "Optional property that should be returned when 'allowPartial' is true to indicate the offset of the first byte of data successfully written. Can be negative." + }, + "bytesWritten": { + "type": "integer", + "description": "Optional property that should be returned when 'allowPartial' is true to indicate the number of bytes starting from address that were successfully written." + } + } + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param WriteMemoryResponseBody body: + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + if body is None: + self.body = WriteMemoryResponseBody() + else: + self.body = WriteMemoryResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != WriteMemoryResponseBody else body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register_request('disassemble') +@register +class DisassembleRequest(BaseSchema): + """ + Disassembles code stored at the provided location. + + Clients should only call this request if the capability 'supportsDisassembleRequest' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "disassemble" + ] + }, + "arguments": { + "type": "DisassembleArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param DisassembleArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'disassemble' + if arguments is None: + self.arguments = DisassembleArguments() + else: + self.arguments = DisassembleArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != DisassembleArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class DisassembleArguments(BaseSchema): + """ + Arguments for 'disassemble' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "memoryReference": { + "type": "string", + "description": "Memory reference to the base location containing the instructions to disassemble." + }, + "offset": { + "type": "integer", + "description": "Optional offset (in bytes) to be applied to the reference location before disassembling. Can be negative." + }, + "instructionOffset": { + "type": "integer", + "description": "Optional offset (in instructions) to be applied after the byte offset (if any) before disassembling. Can be negative." + }, + "instructionCount": { + "type": "integer", + "description": "Number of instructions to disassemble starting at the specified location and offset.\nAn adapter must return exactly this number of instructions - any unavailable instructions should be replaced with an implementation-defined 'invalid instruction' value." + }, + "resolveSymbols": { + "type": "boolean", + "description": "If true, the adapter should attempt to resolve memory addresses and other values to symbolic names." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, memoryReference, instructionCount, offset=None, instructionOffset=None, resolveSymbols=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string memoryReference: Memory reference to the base location containing the instructions to disassemble. + :param integer instructionCount: Number of instructions to disassemble starting at the specified location and offset. + An adapter must return exactly this number of instructions - any unavailable instructions should be replaced with an implementation-defined 'invalid instruction' value. + :param integer offset: Optional offset (in bytes) to be applied to the reference location before disassembling. Can be negative. + :param integer instructionOffset: Optional offset (in instructions) to be applied after the byte offset (if any) before disassembling. Can be negative. + :param boolean resolveSymbols: If true, the adapter should attempt to resolve memory addresses and other values to symbolic names. + """ + self.memoryReference = memoryReference + self.instructionCount = instructionCount + self.offset = offset + self.instructionOffset = instructionOffset + self.resolveSymbols = resolveSymbols + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + memoryReference = self.memoryReference + instructionCount = self.instructionCount + offset = self.offset + instructionOffset = self.instructionOffset + resolveSymbols = self.resolveSymbols + dct = { + 'memoryReference': memoryReference, + 'instructionCount': instructionCount, + } + if offset is not None: + dct['offset'] = offset + if instructionOffset is not None: + dct['instructionOffset'] = instructionOffset + if resolveSymbols is not None: + dct['resolveSymbols'] = resolveSymbols + dct.update(self.kwargs) + return dct + + +@register_response('disassemble') +@register +class DisassembleResponse(BaseSchema): + """ + Response to 'disassemble' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "instructions": { + "type": "array", + "items": { + "$ref": "#/definitions/DisassembledInstruction" + }, + "description": "The list of disassembled instructions." + } + }, + "required": [ + "instructions" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param DisassembleResponseBody body: + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + if body is None: + self.body = DisassembleResponseBody() + else: + self.body = DisassembleResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != DisassembleResponseBody else body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class Capabilities(BaseSchema): + """ + Information about the capabilities of a debug adapter. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "supportsConfigurationDoneRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'configurationDone' request." + }, + "supportsFunctionBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports function breakpoints." + }, + "supportsConditionalBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports conditional breakpoints." + }, + "supportsHitConditionalBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports breakpoints that break execution after a specified number of hits." + }, + "supportsEvaluateForHovers": { + "type": "boolean", + "description": "The debug adapter supports a (side effect free) evaluate request for data hovers." + }, + "exceptionBreakpointFilters": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionBreakpointsFilter" + }, + "description": "Available exception filter options for the 'setExceptionBreakpoints' request." + }, + "supportsStepBack": { + "type": "boolean", + "description": "The debug adapter supports stepping back via the 'stepBack' and 'reverseContinue' requests." + }, + "supportsSetVariable": { + "type": "boolean", + "description": "The debug adapter supports setting a variable to a value." + }, + "supportsRestartFrame": { + "type": "boolean", + "description": "The debug adapter supports restarting a frame." + }, + "supportsGotoTargetsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'gotoTargets' request." + }, + "supportsStepInTargetsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'stepInTargets' request." + }, + "supportsCompletionsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'completions' request." + }, + "completionTriggerCharacters": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The set of characters that should trigger completion in a REPL. If not specified, the UI should assume the '.' character." + }, + "supportsModulesRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'modules' request." + }, + "additionalModuleColumns": { + "type": "array", + "items": { + "$ref": "#/definitions/ColumnDescriptor" + }, + "description": "The set of additional module information exposed by the debug adapter." + }, + "supportedChecksumAlgorithms": { + "type": "array", + "items": { + "$ref": "#/definitions/ChecksumAlgorithm" + }, + "description": "Checksum algorithms supported by the debug adapter." + }, + "supportsRestartRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'restart' request. In this case a client should not implement 'restart' by terminating and relaunching the adapter but by calling the RestartRequest." + }, + "supportsExceptionOptions": { + "type": "boolean", + "description": "The debug adapter supports 'exceptionOptions' on the setExceptionBreakpoints request." + }, + "supportsValueFormattingOptions": { + "type": "boolean", + "description": "The debug adapter supports a 'format' attribute on the stackTraceRequest, variablesRequest, and evaluateRequest." + }, + "supportsExceptionInfoRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'exceptionInfo' request." + }, + "supportTerminateDebuggee": { + "type": "boolean", + "description": "The debug adapter supports the 'terminateDebuggee' attribute on the 'disconnect' request." + }, + "supportSuspendDebuggee": { + "type": "boolean", + "description": "The debug adapter supports the 'suspendDebuggee' attribute on the 'disconnect' request." + }, + "supportsDelayedStackTraceLoading": { + "type": "boolean", + "description": "The debug adapter supports the delayed loading of parts of the stack, which requires that both the 'startFrame' and 'levels' arguments and an optional 'totalFrames' result of the 'StackTrace' request are supported." + }, + "supportsLoadedSourcesRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'loadedSources' request." + }, + "supportsLogPoints": { + "type": "boolean", + "description": "The debug adapter supports logpoints by interpreting the 'logMessage' attribute of the SourceBreakpoint." + }, + "supportsTerminateThreadsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'terminateThreads' request." + }, + "supportsSetExpression": { + "type": "boolean", + "description": "The debug adapter supports the 'setExpression' request." + }, + "supportsTerminateRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'terminate' request." + }, + "supportsDataBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports data breakpoints." + }, + "supportsReadMemoryRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'readMemory' request." + }, + "supportsWriteMemoryRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'writeMemory' request." + }, + "supportsDisassembleRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'disassemble' request." + }, + "supportsCancelRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'cancel' request." + }, + "supportsBreakpointLocationsRequest": { + "type": "boolean", + "description": "The debug adapter supports the 'breakpointLocations' request." + }, + "supportsClipboardContext": { + "type": "boolean", + "description": "The debug adapter supports the 'clipboard' context value in the 'evaluate' request." + }, + "supportsSteppingGranularity": { + "type": "boolean", + "description": "The debug adapter supports stepping granularities (argument 'granularity') for the stepping requests." + }, + "supportsInstructionBreakpoints": { + "type": "boolean", + "description": "The debug adapter supports adding breakpoints based on instruction references." + }, + "supportsExceptionFilterOptions": { + "type": "boolean", + "description": "The debug adapter supports 'filterOptions' as an argument on the 'setExceptionBreakpoints' request." + }, + "supportsSingleThreadExecutionRequests": { + "type": "boolean", + "description": "The debug adapter supports the 'singleThread' property on the execution requests ('continue', 'next', 'stepIn', 'stepOut', 'reverseContinue', 'stepBack')." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, supportsConfigurationDoneRequest=None, supportsFunctionBreakpoints=None, supportsConditionalBreakpoints=None, supportsHitConditionalBreakpoints=None, supportsEvaluateForHovers=None, exceptionBreakpointFilters=None, supportsStepBack=None, supportsSetVariable=None, supportsRestartFrame=None, supportsGotoTargetsRequest=None, supportsStepInTargetsRequest=None, supportsCompletionsRequest=None, completionTriggerCharacters=None, supportsModulesRequest=None, additionalModuleColumns=None, supportedChecksumAlgorithms=None, supportsRestartRequest=None, supportsExceptionOptions=None, supportsValueFormattingOptions=None, supportsExceptionInfoRequest=None, supportTerminateDebuggee=None, supportSuspendDebuggee=None, supportsDelayedStackTraceLoading=None, supportsLoadedSourcesRequest=None, supportsLogPoints=None, supportsTerminateThreadsRequest=None, supportsSetExpression=None, supportsTerminateRequest=None, supportsDataBreakpoints=None, supportsReadMemoryRequest=None, supportsWriteMemoryRequest=None, supportsDisassembleRequest=None, supportsCancelRequest=None, supportsBreakpointLocationsRequest=None, supportsClipboardContext=None, supportsSteppingGranularity=None, supportsInstructionBreakpoints=None, supportsExceptionFilterOptions=None, supportsSingleThreadExecutionRequests=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean supportsConfigurationDoneRequest: The debug adapter supports the 'configurationDone' request. + :param boolean supportsFunctionBreakpoints: The debug adapter supports function breakpoints. + :param boolean supportsConditionalBreakpoints: The debug adapter supports conditional breakpoints. + :param boolean supportsHitConditionalBreakpoints: The debug adapter supports breakpoints that break execution after a specified number of hits. + :param boolean supportsEvaluateForHovers: The debug adapter supports a (side effect free) evaluate request for data hovers. + :param array exceptionBreakpointFilters: Available exception filter options for the 'setExceptionBreakpoints' request. + :param boolean supportsStepBack: The debug adapter supports stepping back via the 'stepBack' and 'reverseContinue' requests. + :param boolean supportsSetVariable: The debug adapter supports setting a variable to a value. + :param boolean supportsRestartFrame: The debug adapter supports restarting a frame. + :param boolean supportsGotoTargetsRequest: The debug adapter supports the 'gotoTargets' request. + :param boolean supportsStepInTargetsRequest: The debug adapter supports the 'stepInTargets' request. + :param boolean supportsCompletionsRequest: The debug adapter supports the 'completions' request. + :param array completionTriggerCharacters: The set of characters that should trigger completion in a REPL. If not specified, the UI should assume the '.' character. + :param boolean supportsModulesRequest: The debug adapter supports the 'modules' request. + :param array additionalModuleColumns: The set of additional module information exposed by the debug adapter. + :param array supportedChecksumAlgorithms: Checksum algorithms supported by the debug adapter. + :param boolean supportsRestartRequest: The debug adapter supports the 'restart' request. In this case a client should not implement 'restart' by terminating and relaunching the adapter but by calling the RestartRequest. + :param boolean supportsExceptionOptions: The debug adapter supports 'exceptionOptions' on the setExceptionBreakpoints request. + :param boolean supportsValueFormattingOptions: The debug adapter supports a 'format' attribute on the stackTraceRequest, variablesRequest, and evaluateRequest. + :param boolean supportsExceptionInfoRequest: The debug adapter supports the 'exceptionInfo' request. + :param boolean supportTerminateDebuggee: The debug adapter supports the 'terminateDebuggee' attribute on the 'disconnect' request. + :param boolean supportSuspendDebuggee: The debug adapter supports the 'suspendDebuggee' attribute on the 'disconnect' request. + :param boolean supportsDelayedStackTraceLoading: The debug adapter supports the delayed loading of parts of the stack, which requires that both the 'startFrame' and 'levels' arguments and an optional 'totalFrames' result of the 'StackTrace' request are supported. + :param boolean supportsLoadedSourcesRequest: The debug adapter supports the 'loadedSources' request. + :param boolean supportsLogPoints: The debug adapter supports logpoints by interpreting the 'logMessage' attribute of the SourceBreakpoint. + :param boolean supportsTerminateThreadsRequest: The debug adapter supports the 'terminateThreads' request. + :param boolean supportsSetExpression: The debug adapter supports the 'setExpression' request. + :param boolean supportsTerminateRequest: The debug adapter supports the 'terminate' request. + :param boolean supportsDataBreakpoints: The debug adapter supports data breakpoints. + :param boolean supportsReadMemoryRequest: The debug adapter supports the 'readMemory' request. + :param boolean supportsWriteMemoryRequest: The debug adapter supports the 'writeMemory' request. + :param boolean supportsDisassembleRequest: The debug adapter supports the 'disassemble' request. + :param boolean supportsCancelRequest: The debug adapter supports the 'cancel' request. + :param boolean supportsBreakpointLocationsRequest: The debug adapter supports the 'breakpointLocations' request. + :param boolean supportsClipboardContext: The debug adapter supports the 'clipboard' context value in the 'evaluate' request. + :param boolean supportsSteppingGranularity: The debug adapter supports stepping granularities (argument 'granularity') for the stepping requests. + :param boolean supportsInstructionBreakpoints: The debug adapter supports adding breakpoints based on instruction references. + :param boolean supportsExceptionFilterOptions: The debug adapter supports 'filterOptions' as an argument on the 'setExceptionBreakpoints' request. + :param boolean supportsSingleThreadExecutionRequests: The debug adapter supports the 'singleThread' property on the execution requests ('continue', 'next', 'stepIn', 'stepOut', 'reverseContinue', 'stepBack'). + """ + self.supportsConfigurationDoneRequest = supportsConfigurationDoneRequest + self.supportsFunctionBreakpoints = supportsFunctionBreakpoints + self.supportsConditionalBreakpoints = supportsConditionalBreakpoints + self.supportsHitConditionalBreakpoints = supportsHitConditionalBreakpoints + self.supportsEvaluateForHovers = supportsEvaluateForHovers + self.exceptionBreakpointFilters = exceptionBreakpointFilters + if update_ids_from_dap and self.exceptionBreakpointFilters: + for o in self.exceptionBreakpointFilters: + ExceptionBreakpointsFilter.update_dict_ids_from_dap(o) + self.supportsStepBack = supportsStepBack + self.supportsSetVariable = supportsSetVariable + self.supportsRestartFrame = supportsRestartFrame + self.supportsGotoTargetsRequest = supportsGotoTargetsRequest + self.supportsStepInTargetsRequest = supportsStepInTargetsRequest + self.supportsCompletionsRequest = supportsCompletionsRequest + self.completionTriggerCharacters = completionTriggerCharacters + self.supportsModulesRequest = supportsModulesRequest + self.additionalModuleColumns = additionalModuleColumns + if update_ids_from_dap and self.additionalModuleColumns: + for o in self.additionalModuleColumns: + ColumnDescriptor.update_dict_ids_from_dap(o) + self.supportedChecksumAlgorithms = supportedChecksumAlgorithms + if update_ids_from_dap and self.supportedChecksumAlgorithms: + for o in self.supportedChecksumAlgorithms: + ChecksumAlgorithm.update_dict_ids_from_dap(o) + self.supportsRestartRequest = supportsRestartRequest + self.supportsExceptionOptions = supportsExceptionOptions + self.supportsValueFormattingOptions = supportsValueFormattingOptions + self.supportsExceptionInfoRequest = supportsExceptionInfoRequest + self.supportTerminateDebuggee = supportTerminateDebuggee + self.supportSuspendDebuggee = supportSuspendDebuggee + self.supportsDelayedStackTraceLoading = supportsDelayedStackTraceLoading + self.supportsLoadedSourcesRequest = supportsLoadedSourcesRequest + self.supportsLogPoints = supportsLogPoints + self.supportsTerminateThreadsRequest = supportsTerminateThreadsRequest + self.supportsSetExpression = supportsSetExpression + self.supportsTerminateRequest = supportsTerminateRequest + self.supportsDataBreakpoints = supportsDataBreakpoints + self.supportsReadMemoryRequest = supportsReadMemoryRequest + self.supportsWriteMemoryRequest = supportsWriteMemoryRequest + self.supportsDisassembleRequest = supportsDisassembleRequest + self.supportsCancelRequest = supportsCancelRequest + self.supportsBreakpointLocationsRequest = supportsBreakpointLocationsRequest + self.supportsClipboardContext = supportsClipboardContext + self.supportsSteppingGranularity = supportsSteppingGranularity + self.supportsInstructionBreakpoints = supportsInstructionBreakpoints + self.supportsExceptionFilterOptions = supportsExceptionFilterOptions + self.supportsSingleThreadExecutionRequests = supportsSingleThreadExecutionRequests + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + supportsConfigurationDoneRequest = self.supportsConfigurationDoneRequest + supportsFunctionBreakpoints = self.supportsFunctionBreakpoints + supportsConditionalBreakpoints = self.supportsConditionalBreakpoints + supportsHitConditionalBreakpoints = self.supportsHitConditionalBreakpoints + supportsEvaluateForHovers = self.supportsEvaluateForHovers + exceptionBreakpointFilters = self.exceptionBreakpointFilters + if exceptionBreakpointFilters and hasattr(exceptionBreakpointFilters[0], "to_dict"): + exceptionBreakpointFilters = [x.to_dict() for x in exceptionBreakpointFilters] + supportsStepBack = self.supportsStepBack + supportsSetVariable = self.supportsSetVariable + supportsRestartFrame = self.supportsRestartFrame + supportsGotoTargetsRequest = self.supportsGotoTargetsRequest + supportsStepInTargetsRequest = self.supportsStepInTargetsRequest + supportsCompletionsRequest = self.supportsCompletionsRequest + completionTriggerCharacters = self.completionTriggerCharacters + if completionTriggerCharacters and hasattr(completionTriggerCharacters[0], "to_dict"): + completionTriggerCharacters = [x.to_dict() for x in completionTriggerCharacters] + supportsModulesRequest = self.supportsModulesRequest + additionalModuleColumns = self.additionalModuleColumns + if additionalModuleColumns and hasattr(additionalModuleColumns[0], "to_dict"): + additionalModuleColumns = [x.to_dict() for x in additionalModuleColumns] + supportedChecksumAlgorithms = self.supportedChecksumAlgorithms + if supportedChecksumAlgorithms and hasattr(supportedChecksumAlgorithms[0], "to_dict"): + supportedChecksumAlgorithms = [x.to_dict() for x in supportedChecksumAlgorithms] + supportsRestartRequest = self.supportsRestartRequest + supportsExceptionOptions = self.supportsExceptionOptions + supportsValueFormattingOptions = self.supportsValueFormattingOptions + supportsExceptionInfoRequest = self.supportsExceptionInfoRequest + supportTerminateDebuggee = self.supportTerminateDebuggee + supportSuspendDebuggee = self.supportSuspendDebuggee + supportsDelayedStackTraceLoading = self.supportsDelayedStackTraceLoading + supportsLoadedSourcesRequest = self.supportsLoadedSourcesRequest + supportsLogPoints = self.supportsLogPoints + supportsTerminateThreadsRequest = self.supportsTerminateThreadsRequest + supportsSetExpression = self.supportsSetExpression + supportsTerminateRequest = self.supportsTerminateRequest + supportsDataBreakpoints = self.supportsDataBreakpoints + supportsReadMemoryRequest = self.supportsReadMemoryRequest + supportsWriteMemoryRequest = self.supportsWriteMemoryRequest + supportsDisassembleRequest = self.supportsDisassembleRequest + supportsCancelRequest = self.supportsCancelRequest + supportsBreakpointLocationsRequest = self.supportsBreakpointLocationsRequest + supportsClipboardContext = self.supportsClipboardContext + supportsSteppingGranularity = self.supportsSteppingGranularity + supportsInstructionBreakpoints = self.supportsInstructionBreakpoints + supportsExceptionFilterOptions = self.supportsExceptionFilterOptions + supportsSingleThreadExecutionRequests = self.supportsSingleThreadExecutionRequests + dct = { + } + if supportsConfigurationDoneRequest is not None: + dct['supportsConfigurationDoneRequest'] = supportsConfigurationDoneRequest + if supportsFunctionBreakpoints is not None: + dct['supportsFunctionBreakpoints'] = supportsFunctionBreakpoints + if supportsConditionalBreakpoints is not None: + dct['supportsConditionalBreakpoints'] = supportsConditionalBreakpoints + if supportsHitConditionalBreakpoints is not None: + dct['supportsHitConditionalBreakpoints'] = supportsHitConditionalBreakpoints + if supportsEvaluateForHovers is not None: + dct['supportsEvaluateForHovers'] = supportsEvaluateForHovers + if exceptionBreakpointFilters is not None: + dct['exceptionBreakpointFilters'] = [ExceptionBreakpointsFilter.update_dict_ids_to_dap(o) for o in exceptionBreakpointFilters] if (update_ids_to_dap and exceptionBreakpointFilters) else exceptionBreakpointFilters + if supportsStepBack is not None: + dct['supportsStepBack'] = supportsStepBack + if supportsSetVariable is not None: + dct['supportsSetVariable'] = supportsSetVariable + if supportsRestartFrame is not None: + dct['supportsRestartFrame'] = supportsRestartFrame + if supportsGotoTargetsRequest is not None: + dct['supportsGotoTargetsRequest'] = supportsGotoTargetsRequest + if supportsStepInTargetsRequest is not None: + dct['supportsStepInTargetsRequest'] = supportsStepInTargetsRequest + if supportsCompletionsRequest is not None: + dct['supportsCompletionsRequest'] = supportsCompletionsRequest + if completionTriggerCharacters is not None: + dct['completionTriggerCharacters'] = completionTriggerCharacters + if supportsModulesRequest is not None: + dct['supportsModulesRequest'] = supportsModulesRequest + if additionalModuleColumns is not None: + dct['additionalModuleColumns'] = [ColumnDescriptor.update_dict_ids_to_dap(o) for o in additionalModuleColumns] if (update_ids_to_dap and additionalModuleColumns) else additionalModuleColumns + if supportedChecksumAlgorithms is not None: + dct['supportedChecksumAlgorithms'] = [ChecksumAlgorithm.update_dict_ids_to_dap(o) for o in supportedChecksumAlgorithms] if (update_ids_to_dap and supportedChecksumAlgorithms) else supportedChecksumAlgorithms + if supportsRestartRequest is not None: + dct['supportsRestartRequest'] = supportsRestartRequest + if supportsExceptionOptions is not None: + dct['supportsExceptionOptions'] = supportsExceptionOptions + if supportsValueFormattingOptions is not None: + dct['supportsValueFormattingOptions'] = supportsValueFormattingOptions + if supportsExceptionInfoRequest is not None: + dct['supportsExceptionInfoRequest'] = supportsExceptionInfoRequest + if supportTerminateDebuggee is not None: + dct['supportTerminateDebuggee'] = supportTerminateDebuggee + if supportSuspendDebuggee is not None: + dct['supportSuspendDebuggee'] = supportSuspendDebuggee + if supportsDelayedStackTraceLoading is not None: + dct['supportsDelayedStackTraceLoading'] = supportsDelayedStackTraceLoading + if supportsLoadedSourcesRequest is not None: + dct['supportsLoadedSourcesRequest'] = supportsLoadedSourcesRequest + if supportsLogPoints is not None: + dct['supportsLogPoints'] = supportsLogPoints + if supportsTerminateThreadsRequest is not None: + dct['supportsTerminateThreadsRequest'] = supportsTerminateThreadsRequest + if supportsSetExpression is not None: + dct['supportsSetExpression'] = supportsSetExpression + if supportsTerminateRequest is not None: + dct['supportsTerminateRequest'] = supportsTerminateRequest + if supportsDataBreakpoints is not None: + dct['supportsDataBreakpoints'] = supportsDataBreakpoints + if supportsReadMemoryRequest is not None: + dct['supportsReadMemoryRequest'] = supportsReadMemoryRequest + if supportsWriteMemoryRequest is not None: + dct['supportsWriteMemoryRequest'] = supportsWriteMemoryRequest + if supportsDisassembleRequest is not None: + dct['supportsDisassembleRequest'] = supportsDisassembleRequest + if supportsCancelRequest is not None: + dct['supportsCancelRequest'] = supportsCancelRequest + if supportsBreakpointLocationsRequest is not None: + dct['supportsBreakpointLocationsRequest'] = supportsBreakpointLocationsRequest + if supportsClipboardContext is not None: + dct['supportsClipboardContext'] = supportsClipboardContext + if supportsSteppingGranularity is not None: + dct['supportsSteppingGranularity'] = supportsSteppingGranularity + if supportsInstructionBreakpoints is not None: + dct['supportsInstructionBreakpoints'] = supportsInstructionBreakpoints + if supportsExceptionFilterOptions is not None: + dct['supportsExceptionFilterOptions'] = supportsExceptionFilterOptions + if supportsSingleThreadExecutionRequests is not None: + dct['supportsSingleThreadExecutionRequests'] = supportsSingleThreadExecutionRequests + dct.update(self.kwargs) + return dct + + +@register +class ExceptionBreakpointsFilter(BaseSchema): + """ + An ExceptionBreakpointsFilter is shown in the UI as an filter option for configuring how exceptions + are dealt with. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "filter": { + "type": "string", + "description": "The internal ID of the filter option. This value is passed to the 'setExceptionBreakpoints' request." + }, + "label": { + "type": "string", + "description": "The name of the filter option. This will be shown in the UI." + }, + "description": { + "type": "string", + "description": "An optional help text providing additional information about the exception filter. This string is typically shown as a hover and must be translated." + }, + "default": { + "type": "boolean", + "description": "Initial value of the filter option. If not specified a value 'false' is assumed." + }, + "supportsCondition": { + "type": "boolean", + "description": "Controls whether a condition can be specified for this filter option. If false or missing, a condition can not be set." + }, + "conditionDescription": { + "type": "string", + "description": "An optional help text providing information about the condition. This string is shown as the placeholder text for a text box and must be translated." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, filter, label, description=None, default=None, supportsCondition=None, conditionDescription=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string filter: The internal ID of the filter option. This value is passed to the 'setExceptionBreakpoints' request. + :param string label: The name of the filter option. This will be shown in the UI. + :param string description: An optional help text providing additional information about the exception filter. This string is typically shown as a hover and must be translated. + :param boolean default: Initial value of the filter option. If not specified a value 'false' is assumed. + :param boolean supportsCondition: Controls whether a condition can be specified for this filter option. If false or missing, a condition can not be set. + :param string conditionDescription: An optional help text providing information about the condition. This string is shown as the placeholder text for a text box and must be translated. + """ + self.filter = filter + self.label = label + self.description = description + self.default = default + self.supportsCondition = supportsCondition + self.conditionDescription = conditionDescription + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + filter = self.filter # noqa (assign to builtin) + label = self.label + description = self.description + default = self.default + supportsCondition = self.supportsCondition + conditionDescription = self.conditionDescription + dct = { + 'filter': filter, + 'label': label, + } + if description is not None: + dct['description'] = description + if default is not None: + dct['default'] = default + if supportsCondition is not None: + dct['supportsCondition'] = supportsCondition + if conditionDescription is not None: + dct['conditionDescription'] = conditionDescription + dct.update(self.kwargs) + return dct + + +@register +class Message(BaseSchema): + """ + A structured message object. Used to return errors from requests. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "id": { + "type": "integer", + "description": "Unique identifier for the message." + }, + "format": { + "type": "string", + "description": "A format string for the message. Embedded variables have the form '{name}'.\nIf variable name starts with an underscore character, the variable does not contain user data (PII) and can be safely used for telemetry purposes." + }, + "variables": { + "type": "object", + "description": "An object used as a dictionary for looking up the variables in the format string.", + "additionalProperties": { + "type": "string", + "description": "Values must be strings." + } + }, + "sendTelemetry": { + "type": "boolean", + "description": "If true send to telemetry." + }, + "showUser": { + "type": "boolean", + "description": "If true show user." + }, + "url": { + "type": "string", + "description": "An optional url where additional information about this message can be found." + }, + "urlLabel": { + "type": "string", + "description": "An optional label that is presented to the user as the UI for opening the url." + } + } + __refs__ = set(['variables']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, id, format, variables=None, sendTelemetry=None, showUser=None, url=None, urlLabel=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer id: Unique identifier for the message. + :param string format: A format string for the message. Embedded variables have the form '{name}'. + If variable name starts with an underscore character, the variable does not contain user data (PII) and can be safely used for telemetry purposes. + :param MessageVariables variables: An object used as a dictionary for looking up the variables in the format string. + :param boolean sendTelemetry: If true send to telemetry. + :param boolean showUser: If true show user. + :param string url: An optional url where additional information about this message can be found. + :param string urlLabel: An optional label that is presented to the user as the UI for opening the url. + """ + self.id = id + self.format = format + if variables is None: + self.variables = MessageVariables() + else: + self.variables = MessageVariables(update_ids_from_dap=update_ids_from_dap, **variables) if variables.__class__ != MessageVariables else variables + self.sendTelemetry = sendTelemetry + self.showUser = showUser + self.url = url + self.urlLabel = urlLabel + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + id = self.id # noqa (assign to builtin) + format = self.format # noqa (assign to builtin) + variables = self.variables + sendTelemetry = self.sendTelemetry + showUser = self.showUser + url = self.url + urlLabel = self.urlLabel + dct = { + 'id': id, + 'format': format, + } + if variables is not None: + dct['variables'] = variables.to_dict(update_ids_to_dap=update_ids_to_dap) + if sendTelemetry is not None: + dct['sendTelemetry'] = sendTelemetry + if showUser is not None: + dct['showUser'] = showUser + if url is not None: + dct['url'] = url + if urlLabel is not None: + dct['urlLabel'] = urlLabel + dct.update(self.kwargs) + return dct + + +@register +class Module(BaseSchema): + """ + A Module object represents a row in the modules view. + + Two attributes are mandatory: an id identifies a module in the modules view and is used in a + ModuleEvent for identifying a module for adding, updating or deleting. + + The name is used to minimally render the module in the UI. + + + Additional attributes can be added to the module. They will show up in the module View if they have + a corresponding ColumnDescriptor. + + + To avoid an unnecessary proliferation of additional attributes with similar semantics but different + names + + we recommend to re-use attributes from the 'recommended' list below first, and only introduce new + attributes if nothing appropriate could be found. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "id": { + "type": [ + "integer", + "string" + ], + "description": "Unique identifier for the module." + }, + "name": { + "type": "string", + "description": "A name of the module." + }, + "path": { + "type": "string", + "description": "optional but recommended attributes.\nalways try to use these first before introducing additional attributes.\n\nLogical full path to the module. The exact definition is implementation defined, but usually this would be a full path to the on-disk file for the module." + }, + "isOptimized": { + "type": "boolean", + "description": "True if the module is optimized." + }, + "isUserCode": { + "type": "boolean", + "description": "True if the module is considered 'user code' by a debugger that supports 'Just My Code'." + }, + "version": { + "type": "string", + "description": "Version of Module." + }, + "symbolStatus": { + "type": "string", + "description": "User understandable description of if symbols were found for the module (ex: 'Symbols Loaded', 'Symbols not found', etc." + }, + "symbolFilePath": { + "type": "string", + "description": "Logical full path to the symbol file. The exact definition is implementation defined." + }, + "dateTimeStamp": { + "type": "string", + "description": "Module created or modified." + }, + "addressRange": { + "type": "string", + "description": "Address range covered by this module." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, id, name, path=None, isOptimized=None, isUserCode=None, version=None, symbolStatus=None, symbolFilePath=None, dateTimeStamp=None, addressRange=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param ['integer', 'string'] id: Unique identifier for the module. + :param string name: A name of the module. + :param string path: optional but recommended attributes. + always try to use these first before introducing additional attributes. + + Logical full path to the module. The exact definition is implementation defined, but usually this would be a full path to the on-disk file for the module. + :param boolean isOptimized: True if the module is optimized. + :param boolean isUserCode: True if the module is considered 'user code' by a debugger that supports 'Just My Code'. + :param string version: Version of Module. + :param string symbolStatus: User understandable description of if symbols were found for the module (ex: 'Symbols Loaded', 'Symbols not found', etc. + :param string symbolFilePath: Logical full path to the symbol file. The exact definition is implementation defined. + :param string dateTimeStamp: Module created or modified. + :param string addressRange: Address range covered by this module. + """ + self.id = id + self.name = name + self.path = path + self.isOptimized = isOptimized + self.isUserCode = isUserCode + self.version = version + self.symbolStatus = symbolStatus + self.symbolFilePath = symbolFilePath + self.dateTimeStamp = dateTimeStamp + self.addressRange = addressRange + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + id = self.id # noqa (assign to builtin) + name = self.name + path = self.path + isOptimized = self.isOptimized + isUserCode = self.isUserCode + version = self.version + symbolStatus = self.symbolStatus + symbolFilePath = self.symbolFilePath + dateTimeStamp = self.dateTimeStamp + addressRange = self.addressRange + dct = { + 'id': id, + 'name': name, + } + if path is not None: + dct['path'] = path + if isOptimized is not None: + dct['isOptimized'] = isOptimized + if isUserCode is not None: + dct['isUserCode'] = isUserCode + if version is not None: + dct['version'] = version + if symbolStatus is not None: + dct['symbolStatus'] = symbolStatus + if symbolFilePath is not None: + dct['symbolFilePath'] = symbolFilePath + if dateTimeStamp is not None: + dct['dateTimeStamp'] = dateTimeStamp + if addressRange is not None: + dct['addressRange'] = addressRange + dct.update(self.kwargs) + return dct + + +@register +class ColumnDescriptor(BaseSchema): + """ + A ColumnDescriptor specifies what module attribute to show in a column of the ModulesView, how to + format it, + + and what the column's label should be. + + It is only used if the underlying UI actually supports this level of customization. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "attributeName": { + "type": "string", + "description": "Name of the attribute rendered in this column." + }, + "label": { + "type": "string", + "description": "Header UI label of column." + }, + "format": { + "type": "string", + "description": "Format to use for the rendered values in this column. TBD how the format strings looks like." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "unixTimestampUTC" + ], + "description": "Datatype of values in this column. Defaults to 'string' if not specified." + }, + "width": { + "type": "integer", + "description": "Width of this column in characters (hint only)." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, attributeName, label, format=None, type=None, width=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string attributeName: Name of the attribute rendered in this column. + :param string label: Header UI label of column. + :param string format: Format to use for the rendered values in this column. TBD how the format strings looks like. + :param string type: Datatype of values in this column. Defaults to 'string' if not specified. + :param integer width: Width of this column in characters (hint only). + """ + self.attributeName = attributeName + self.label = label + self.format = format + self.type = type + self.width = width + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + attributeName = self.attributeName + label = self.label + format = self.format # noqa (assign to builtin) + type = self.type # noqa (assign to builtin) + width = self.width + dct = { + 'attributeName': attributeName, + 'label': label, + } + if format is not None: + dct['format'] = format + if type is not None: + dct['type'] = type + if width is not None: + dct['width'] = width + dct.update(self.kwargs) + return dct + + +@register +class ModulesViewDescriptor(BaseSchema): + """ + The ModulesViewDescriptor is the container for all declarative configuration options of a + ModuleView. + + For now it only specifies the columns to be shown in the modules view. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/ColumnDescriptor" + } + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, columns, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array columns: + """ + self.columns = columns + if update_ids_from_dap and self.columns: + for o in self.columns: + ColumnDescriptor.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + columns = self.columns + if columns and hasattr(columns[0], "to_dict"): + columns = [x.to_dict() for x in columns] + dct = { + 'columns': [ColumnDescriptor.update_dict_ids_to_dap(o) for o in columns] if (update_ids_to_dap and columns) else columns, + } + dct.update(self.kwargs) + return dct + + +@register +class Thread(BaseSchema): + """ + A Thread + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "id": { + "type": "integer", + "description": "Unique identifier for the thread." + }, + "name": { + "type": "string", + "description": "A name of the thread." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, id, name, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer id: Unique identifier for the thread. + :param string name: A name of the thread. + """ + self.id = id + self.name = name + if update_ids_from_dap: + self.id = self._translate_id_from_dap(self.id) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'id' in dct: + dct['id'] = cls._translate_id_from_dap(dct['id']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + id = self.id # noqa (assign to builtin) + name = self.name + if update_ids_to_dap: + if id is not None: + id = self._translate_id_to_dap(id) # noqa (assign to builtin) + dct = { + 'id': id, + 'name': name, + } + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'id' in dct: + dct['id'] = cls._translate_id_to_dap(dct['id']) + return dct + + +@register +class Source(BaseSchema): + """ + A Source is a descriptor for source code. + + It is returned from the debug adapter as part of a StackFrame and it is used by clients when + specifying breakpoints. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "name": { + "type": "string", + "description": "The short name of the source. Every source returned from the debug adapter has a name.\nWhen sending a source to the debug adapter this name is optional." + }, + "path": { + "type": "string", + "description": "The path of the source to be shown in the UI.\nIt is only used to locate and load the content of the source if no sourceReference is specified (or its value is 0)." + }, + "sourceReference": { + "type": "integer", + "description": "If sourceReference > 0 the contents of the source must be retrieved through the SourceRequest (even if a path is specified).\nA sourceReference is only valid for a session, so it must not be used to persist a source.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "presentationHint": { + "type": "string", + "description": "An optional hint for how to present the source in the UI.\nA value of 'deemphasize' can be used to indicate that the source is not available or that it is skipped on stepping.", + "enum": [ + "normal", + "emphasize", + "deemphasize" + ] + }, + "origin": { + "type": "string", + "description": "The (optional) origin of this source: possible values 'internal module', 'inlined content from source map', etc." + }, + "sources": { + "type": "array", + "items": { + "$ref": "#/definitions/Source" + }, + "description": "An optional list of sources that are related to this source. These may be the source that generated this source." + }, + "adapterData": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Optional data that a debug adapter might want to loop through the client.\nThe client should leave the data intact and persist it across sessions. The client should not interpret the data." + }, + "checksums": { + "type": "array", + "items": { + "$ref": "#/definitions/Checksum" + }, + "description": "The checksums associated with this file." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, name=None, path=None, sourceReference=None, presentationHint=None, origin=None, sources=None, adapterData=None, checksums=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string name: The short name of the source. Every source returned from the debug adapter has a name. + When sending a source to the debug adapter this name is optional. + :param string path: The path of the source to be shown in the UI. + It is only used to locate and load the content of the source if no sourceReference is specified (or its value is 0). + :param integer sourceReference: If sourceReference > 0 the contents of the source must be retrieved through the SourceRequest (even if a path is specified). + A sourceReference is only valid for a session, so it must not be used to persist a source. + The value should be less than or equal to 2147483647 (2^31-1). + :param string presentationHint: An optional hint for how to present the source in the UI. + A value of 'deemphasize' can be used to indicate that the source is not available or that it is skipped on stepping. + :param string origin: The (optional) origin of this source: possible values 'internal module', 'inlined content from source map', etc. + :param array sources: An optional list of sources that are related to this source. These may be the source that generated this source. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] adapterData: Optional data that a debug adapter might want to loop through the client. + The client should leave the data intact and persist it across sessions. The client should not interpret the data. + :param array checksums: The checksums associated with this file. + """ + self.name = name + self.path = path + self.sourceReference = sourceReference + self.presentationHint = presentationHint + self.origin = origin + self.sources = sources + if update_ids_from_dap and self.sources: + for o in self.sources: + Source.update_dict_ids_from_dap(o) + self.adapterData = adapterData + self.checksums = checksums + if update_ids_from_dap and self.checksums: + for o in self.checksums: + Checksum.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + name = self.name + path = self.path + sourceReference = self.sourceReference + presentationHint = self.presentationHint + origin = self.origin + sources = self.sources + if sources and hasattr(sources[0], "to_dict"): + sources = [x.to_dict() for x in sources] + adapterData = self.adapterData + checksums = self.checksums + if checksums and hasattr(checksums[0], "to_dict"): + checksums = [x.to_dict() for x in checksums] + dct = { + } + if name is not None: + dct['name'] = name + if path is not None: + dct['path'] = path + if sourceReference is not None: + dct['sourceReference'] = sourceReference + if presentationHint is not None: + dct['presentationHint'] = presentationHint + if origin is not None: + dct['origin'] = origin + if sources is not None: + dct['sources'] = [Source.update_dict_ids_to_dap(o) for o in sources] if (update_ids_to_dap and sources) else sources + if adapterData is not None: + dct['adapterData'] = adapterData + if checksums is not None: + dct['checksums'] = [Checksum.update_dict_ids_to_dap(o) for o in checksums] if (update_ids_to_dap and checksums) else checksums + dct.update(self.kwargs) + return dct + + +@register +class StackFrame(BaseSchema): + """ + A Stackframe contains the source location. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "id": { + "type": "integer", + "description": "An identifier for the stack frame. It must be unique across all threads.\nThis id can be used to retrieve the scopes of the frame with the 'scopesRequest' or to restart the execution of a stackframe." + }, + "name": { + "type": "string", + "description": "The name of the stack frame, typically a method name." + }, + "source": { + "description": "The optional source of the frame.", + "type": "Source" + }, + "line": { + "type": "integer", + "description": "The line within the file of the frame. If source is null or doesn't exist, line is 0 and must be ignored." + }, + "column": { + "type": "integer", + "description": "The column within the line. If source is null or doesn't exist, column is 0 and must be ignored." + }, + "endLine": { + "type": "integer", + "description": "An optional end line of the range covered by the stack frame." + }, + "endColumn": { + "type": "integer", + "description": "An optional end column of the range covered by the stack frame." + }, + "canRestart": { + "type": "boolean", + "description": "Indicates whether this frame can be restarted with the 'restart' request. Clients should only use this if the debug adapter supports the 'restart' request (capability 'supportsRestartRequest' is true)." + }, + "instructionPointerReference": { + "type": "string", + "description": "Optional memory reference for the current instruction pointer in this frame." + }, + "moduleId": { + "type": [ + "integer", + "string" + ], + "description": "The module associated with this frame, if any." + }, + "presentationHint": { + "type": "string", + "enum": [ + "normal", + "label", + "subtle" + ], + "description": "An optional hint for how to present this frame in the UI.\nA value of 'label' can be used to indicate that the frame is an artificial frame that is used as a visual label or separator. A value of 'subtle' can be used to change the appearance of a frame in a 'subtle' way." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, id, name, line, column, source=None, endLine=None, endColumn=None, canRestart=None, instructionPointerReference=None, moduleId=None, presentationHint=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer id: An identifier for the stack frame. It must be unique across all threads. + This id can be used to retrieve the scopes of the frame with the 'scopesRequest' or to restart the execution of a stackframe. + :param string name: The name of the stack frame, typically a method name. + :param integer line: The line within the file of the frame. If source is null or doesn't exist, line is 0 and must be ignored. + :param integer column: The column within the line. If source is null or doesn't exist, column is 0 and must be ignored. + :param Source source: The optional source of the frame. + :param integer endLine: An optional end line of the range covered by the stack frame. + :param integer endColumn: An optional end column of the range covered by the stack frame. + :param boolean canRestart: Indicates whether this frame can be restarted with the 'restart' request. Clients should only use this if the debug adapter supports the 'restart' request (capability 'supportsRestartRequest' is true). + :param string instructionPointerReference: Optional memory reference for the current instruction pointer in this frame. + :param ['integer', 'string'] moduleId: The module associated with this frame, if any. + :param string presentationHint: An optional hint for how to present this frame in the UI. + A value of 'label' can be used to indicate that the frame is an artificial frame that is used as a visual label or separator. A value of 'subtle' can be used to change the appearance of a frame in a 'subtle' way. + """ + self.id = id + self.name = name + self.line = line + self.column = column + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.endLine = endLine + self.endColumn = endColumn + self.canRestart = canRestart + self.instructionPointerReference = instructionPointerReference + self.moduleId = moduleId + self.presentationHint = presentationHint + if update_ids_from_dap: + self.id = self._translate_id_from_dap(self.id) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'id' in dct: + dct['id'] = cls._translate_id_from_dap(dct['id']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + id = self.id # noqa (assign to builtin) + name = self.name + line = self.line + column = self.column + source = self.source + endLine = self.endLine + endColumn = self.endColumn + canRestart = self.canRestart + instructionPointerReference = self.instructionPointerReference + moduleId = self.moduleId + presentationHint = self.presentationHint + if update_ids_to_dap: + if id is not None: + id = self._translate_id_to_dap(id) # noqa (assign to builtin) + dct = { + 'id': id, + 'name': name, + 'line': line, + 'column': column, + } + if source is not None: + dct['source'] = source.to_dict(update_ids_to_dap=update_ids_to_dap) + if endLine is not None: + dct['endLine'] = endLine + if endColumn is not None: + dct['endColumn'] = endColumn + if canRestart is not None: + dct['canRestart'] = canRestart + if instructionPointerReference is not None: + dct['instructionPointerReference'] = instructionPointerReference + if moduleId is not None: + dct['moduleId'] = moduleId + if presentationHint is not None: + dct['presentationHint'] = presentationHint + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'id' in dct: + dct['id'] = cls._translate_id_to_dap(dct['id']) + return dct + + +@register +class Scope(BaseSchema): + """ + A Scope is a named container for variables. Optionally a scope can map to a source or a range within + a source. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "name": { + "type": "string", + "description": "Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This string is shown in the UI as is and can be translated." + }, + "presentationHint": { + "type": "string", + "description": "An optional hint for how to present this scope in the UI. If this attribute is missing, the scope is shown with a generic UI.", + "_enum": [ + "arguments", + "locals", + "registers" + ], + "enumDescriptions": [ + "Scope contains method arguments.", + "Scope contains local variables.", + "Scope contains registers. Only a single 'registers' scope should be returned from a 'scopes' request." + ] + }, + "variablesReference": { + "type": "integer", + "description": "The variables of this scope can be retrieved by passing the value of variablesReference to the VariablesRequest." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named variables in this scope.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed variables in this scope.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks." + }, + "expensive": { + "type": "boolean", + "description": "If true, the number of variables in this scope is large or expensive to retrieve." + }, + "source": { + "description": "Optional source for this scope.", + "type": "Source" + }, + "line": { + "type": "integer", + "description": "Optional start line of the range covered by this scope." + }, + "column": { + "type": "integer", + "description": "Optional start column of the range covered by this scope." + }, + "endLine": { + "type": "integer", + "description": "Optional end line of the range covered by this scope." + }, + "endColumn": { + "type": "integer", + "description": "Optional end column of the range covered by this scope." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, name, variablesReference, expensive, presentationHint=None, namedVariables=None, indexedVariables=None, source=None, line=None, column=None, endLine=None, endColumn=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string name: Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This string is shown in the UI as is and can be translated. + :param integer variablesReference: The variables of this scope can be retrieved by passing the value of variablesReference to the VariablesRequest. + :param boolean expensive: If true, the number of variables in this scope is large or expensive to retrieve. + :param string presentationHint: An optional hint for how to present this scope in the UI. If this attribute is missing, the scope is shown with a generic UI. + :param integer namedVariables: The number of named variables in this scope. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + :param integer indexedVariables: The number of indexed variables in this scope. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + :param Source source: Optional source for this scope. + :param integer line: Optional start line of the range covered by this scope. + :param integer column: Optional start column of the range covered by this scope. + :param integer endLine: Optional end line of the range covered by this scope. + :param integer endColumn: Optional end column of the range covered by this scope. + """ + self.name = name + self.variablesReference = variablesReference + self.expensive = expensive + self.presentationHint = presentationHint + self.namedVariables = namedVariables + self.indexedVariables = indexedVariables + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.line = line + self.column = column + self.endLine = endLine + self.endColumn = endColumn + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + name = self.name + variablesReference = self.variablesReference + expensive = self.expensive + presentationHint = self.presentationHint + namedVariables = self.namedVariables + indexedVariables = self.indexedVariables + source = self.source + line = self.line + column = self.column + endLine = self.endLine + endColumn = self.endColumn + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'name': name, + 'variablesReference': variablesReference, + 'expensive': expensive, + } + if presentationHint is not None: + dct['presentationHint'] = presentationHint + if namedVariables is not None: + dct['namedVariables'] = namedVariables + if indexedVariables is not None: + dct['indexedVariables'] = indexedVariables + if source is not None: + dct['source'] = source.to_dict(update_ids_to_dap=update_ids_to_dap) + if line is not None: + dct['line'] = line + if column is not None: + dct['column'] = column + if endLine is not None: + dct['endLine'] = endLine + if endColumn is not None: + dct['endColumn'] = endColumn + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register +class Variable(BaseSchema): + """ + A Variable is a name/value pair. + + Optionally a variable can have a 'type' that is shown if space permits or when hovering over the + variable's name. + + An optional 'kind' is used to render additional properties of the variable, e.g. different icons can + be used to indicate that a variable is public or private. + + If the value is structured (has children), a handle is provided to retrieve the children with the + VariablesRequest. + + If the number of named or indexed children is large, the numbers should be returned via the optional + 'namedVariables' and 'indexedVariables' attributes. + + The client can use this optional information to present the children in a paged UI and fetch them in + chunks. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "name": { + "type": "string", + "description": "The variable's name." + }, + "value": { + "type": "string", + "description": "The variable's value. This can be a multi-line text, e.g. for a function the body of a function." + }, + "type": { + "type": "string", + "description": "The type of the variable's value. Typically shown in the UI when hovering over the value.\nThis attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request." + }, + "presentationHint": { + "description": "Properties of a variable that can be used to determine how to render the variable in the UI.", + "type": "VariablePresentationHint" + }, + "evaluateName": { + "type": "string", + "description": "Optional evaluatable name of this variable which can be passed to the 'EvaluateRequest' to fetch the variable's value." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the variable is structured and its children can be retrieved by passing variablesReference to the VariablesRequest." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the children in a paged UI and fetch them in chunks." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the children in a paged UI and fetch them in chunks." + }, + "memoryReference": { + "type": "string", + "description": "Optional memory reference for the variable if the variable represents executable code, such as a function pointer.\nThis attribute is only required if the client has passed the value true for the 'supportsMemoryReferences' capability of the 'initialize' request." + } + } + __refs__ = set(['presentationHint']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, name, value, variablesReference, type=None, presentationHint=None, evaluateName=None, namedVariables=None, indexedVariables=None, memoryReference=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string name: The variable's name. + :param string value: The variable's value. This can be a multi-line text, e.g. for a function the body of a function. + :param integer variablesReference: If variablesReference is > 0, the variable is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. + :param string type: The type of the variable's value. Typically shown in the UI when hovering over the value. + This attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request. + :param VariablePresentationHint presentationHint: Properties of a variable that can be used to determine how to render the variable in the UI. + :param string evaluateName: Optional evaluatable name of this variable which can be passed to the 'EvaluateRequest' to fetch the variable's value. + :param integer namedVariables: The number of named child variables. + The client can use this optional information to present the children in a paged UI and fetch them in chunks. + :param integer indexedVariables: The number of indexed child variables. + The client can use this optional information to present the children in a paged UI and fetch them in chunks. + :param string memoryReference: Optional memory reference for the variable if the variable represents executable code, such as a function pointer. + This attribute is only required if the client has passed the value true for the 'supportsMemoryReferences' capability of the 'initialize' request. + """ + self.name = name + self.value = value + self.variablesReference = variablesReference + self.type = type + if presentationHint is None: + self.presentationHint = VariablePresentationHint() + else: + self.presentationHint = VariablePresentationHint(update_ids_from_dap=update_ids_from_dap, **presentationHint) if presentationHint.__class__ != VariablePresentationHint else presentationHint + self.evaluateName = evaluateName + self.namedVariables = namedVariables + self.indexedVariables = indexedVariables + self.memoryReference = memoryReference + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + name = self.name + value = self.value + variablesReference = self.variablesReference + type = self.type # noqa (assign to builtin) + presentationHint = self.presentationHint + evaluateName = self.evaluateName + namedVariables = self.namedVariables + indexedVariables = self.indexedVariables + memoryReference = self.memoryReference + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'name': name, + 'value': value, + 'variablesReference': variablesReference, + } + if type is not None: + dct['type'] = type + if presentationHint is not None: + dct['presentationHint'] = presentationHint.to_dict(update_ids_to_dap=update_ids_to_dap) + if evaluateName is not None: + dct['evaluateName'] = evaluateName + if namedVariables is not None: + dct['namedVariables'] = namedVariables + if indexedVariables is not None: + dct['indexedVariables'] = indexedVariables + if memoryReference is not None: + dct['memoryReference'] = memoryReference + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register +class VariablePresentationHint(BaseSchema): + """ + Optional properties of a variable that can be used to determine how to render the variable in the + UI. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "kind": { + "description": "The kind of variable. Before introducing additional values, try to use the listed values.", + "type": "string", + "_enum": [ + "property", + "method", + "class", + "data", + "event", + "baseClass", + "innerClass", + "interface", + "mostDerivedClass", + "virtual", + "dataBreakpoint" + ], + "enumDescriptions": [ + "Indicates that the object is a property.", + "Indicates that the object is a method.", + "Indicates that the object is a class.", + "Indicates that the object is data.", + "Indicates that the object is an event.", + "Indicates that the object is a base class.", + "Indicates that the object is an inner class.", + "Indicates that the object is an interface.", + "Indicates that the object is the most derived class.", + "Indicates that the object is virtual, that means it is a synthetic object introducedby the\nadapter for rendering purposes, e.g. an index range for large arrays.", + "Deprecated: Indicates that a data breakpoint is registered for the object. The 'hasDataBreakpoint' attribute should generally be used instead." + ] + }, + "attributes": { + "description": "Set of attributes represented as an array of strings. Before introducing additional values, try to use the listed values.", + "type": "array", + "items": { + "type": "string", + "_enum": [ + "static", + "constant", + "readOnly", + "rawString", + "hasObjectId", + "canHaveObjectId", + "hasSideEffects", + "hasDataBreakpoint" + ], + "enumDescriptions": [ + "Indicates that the object is static.", + "Indicates that the object is a constant.", + "Indicates that the object is read only.", + "Indicates that the object is a raw string.", + "Indicates that the object can have an Object ID created for it.", + "Indicates that the object has an Object ID associated with it.", + "Indicates that the evaluation had side effects.", + "Indicates that the object has its value tracked by a data breakpoint." + ] + } + }, + "visibility": { + "description": "Visibility of variable. Before introducing additional values, try to use the listed values.", + "type": "string", + "_enum": [ + "public", + "private", + "protected", + "internal", + "final" + ] + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, kind=None, attributes=None, visibility=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string kind: The kind of variable. Before introducing additional values, try to use the listed values. + :param array attributes: Set of attributes represented as an array of strings. Before introducing additional values, try to use the listed values. + :param string visibility: Visibility of variable. Before introducing additional values, try to use the listed values. + """ + self.kind = kind + self.attributes = attributes + self.visibility = visibility + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + kind = self.kind + attributes = self.attributes + if attributes and hasattr(attributes[0], "to_dict"): + attributes = [x.to_dict() for x in attributes] + visibility = self.visibility + dct = { + } + if kind is not None: + dct['kind'] = kind + if attributes is not None: + dct['attributes'] = attributes + if visibility is not None: + dct['visibility'] = visibility + dct.update(self.kwargs) + return dct + + +@register +class BreakpointLocation(BaseSchema): + """ + Properties of a breakpoint location returned from the 'breakpointLocations' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "line": { + "type": "integer", + "description": "Start line of breakpoint location." + }, + "column": { + "type": "integer", + "description": "Optional start column of breakpoint location." + }, + "endLine": { + "type": "integer", + "description": "Optional end line of breakpoint location if the location covers a range." + }, + "endColumn": { + "type": "integer", + "description": "Optional end column of breakpoint location if the location covers a range." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, line, column=None, endLine=None, endColumn=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer line: Start line of breakpoint location. + :param integer column: Optional start column of breakpoint location. + :param integer endLine: Optional end line of breakpoint location if the location covers a range. + :param integer endColumn: Optional end column of breakpoint location if the location covers a range. + """ + self.line = line + self.column = column + self.endLine = endLine + self.endColumn = endColumn + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + line = self.line + column = self.column + endLine = self.endLine + endColumn = self.endColumn + dct = { + 'line': line, + } + if column is not None: + dct['column'] = column + if endLine is not None: + dct['endLine'] = endLine + if endColumn is not None: + dct['endColumn'] = endColumn + dct.update(self.kwargs) + return dct + + +@register +class SourceBreakpoint(BaseSchema): + """ + Properties of a breakpoint or logpoint passed to the setBreakpoints request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "line": { + "type": "integer", + "description": "The source line of the breakpoint or logpoint." + }, + "column": { + "type": "integer", + "description": "An optional source column of the breakpoint." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional breakpoints.\nIt is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true." + }, + "hitCondition": { + "type": "string", + "description": "An optional expression that controls how many hits of the breakpoint are ignored.\nThe backend is expected to interpret the expression as needed.\nThe attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true." + }, + "logMessage": { + "type": "string", + "description": "If this attribute exists and is non-empty, the backend must not 'break' (stop)\nbut log the message instead. Expressions within {} are interpolated.\nThe attribute is only honored by a debug adapter if the capability 'supportsLogPoints' is true." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, line, column=None, condition=None, hitCondition=None, logMessage=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer line: The source line of the breakpoint or logpoint. + :param integer column: An optional source column of the breakpoint. + :param string condition: An optional expression for conditional breakpoints. + It is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true. + :param string hitCondition: An optional expression that controls how many hits of the breakpoint are ignored. + The backend is expected to interpret the expression as needed. + The attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true. + :param string logMessage: If this attribute exists and is non-empty, the backend must not 'break' (stop) + but log the message instead. Expressions within {} are interpolated. + The attribute is only honored by a debug adapter if the capability 'supportsLogPoints' is true. + """ + self.line = line + self.column = column + self.condition = condition + self.hitCondition = hitCondition + self.logMessage = logMessage + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + line = self.line + column = self.column + condition = self.condition + hitCondition = self.hitCondition + logMessage = self.logMessage + dct = { + 'line': line, + } + if column is not None: + dct['column'] = column + if condition is not None: + dct['condition'] = condition + if hitCondition is not None: + dct['hitCondition'] = hitCondition + if logMessage is not None: + dct['logMessage'] = logMessage + dct.update(self.kwargs) + return dct + + +@register +class FunctionBreakpoint(BaseSchema): + """ + Properties of a breakpoint passed to the setFunctionBreakpoints request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "name": { + "type": "string", + "description": "The name of the function." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional breakpoints.\nIt is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true." + }, + "hitCondition": { + "type": "string", + "description": "An optional expression that controls how many hits of the breakpoint are ignored.\nThe backend is expected to interpret the expression as needed.\nThe attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, name, condition=None, hitCondition=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string name: The name of the function. + :param string condition: An optional expression for conditional breakpoints. + It is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true. + :param string hitCondition: An optional expression that controls how many hits of the breakpoint are ignored. + The backend is expected to interpret the expression as needed. + The attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true. + """ + self.name = name + self.condition = condition + self.hitCondition = hitCondition + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + name = self.name + condition = self.condition + hitCondition = self.hitCondition + dct = { + 'name': name, + } + if condition is not None: + dct['condition'] = condition + if hitCondition is not None: + dct['hitCondition'] = hitCondition + dct.update(self.kwargs) + return dct + + +@register +class DataBreakpointAccessType(BaseSchema): + """ + This enumeration defines all possible access types for data breakpoints. + + Note: automatically generated code. Do not edit manually. + """ + + READ = 'read' + WRITE = 'write' + READWRITE = 'readWrite' + + VALID_VALUES = set(['read', 'write', 'readWrite']) + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register +class DataBreakpoint(BaseSchema): + """ + Properties of a data breakpoint passed to the setDataBreakpoints request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "dataId": { + "type": "string", + "description": "An id representing the data. This id is returned from the dataBreakpointInfo request." + }, + "accessType": { + "description": "The access type of the data.", + "type": "DataBreakpointAccessType" + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional breakpoints." + }, + "hitCondition": { + "type": "string", + "description": "An optional expression that controls how many hits of the breakpoint are ignored.\nThe backend is expected to interpret the expression as needed." + } + } + __refs__ = set(['accessType']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, dataId, accessType=None, condition=None, hitCondition=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string dataId: An id representing the data. This id is returned from the dataBreakpointInfo request. + :param DataBreakpointAccessType accessType: The access type of the data. + :param string condition: An optional expression for conditional breakpoints. + :param string hitCondition: An optional expression that controls how many hits of the breakpoint are ignored. + The backend is expected to interpret the expression as needed. + """ + self.dataId = dataId + if accessType is not None: + assert accessType in DataBreakpointAccessType.VALID_VALUES + self.accessType = accessType + self.condition = condition + self.hitCondition = hitCondition + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dataId = self.dataId + accessType = self.accessType + condition = self.condition + hitCondition = self.hitCondition + dct = { + 'dataId': dataId, + } + if accessType is not None: + dct['accessType'] = accessType + if condition is not None: + dct['condition'] = condition + if hitCondition is not None: + dct['hitCondition'] = hitCondition + dct.update(self.kwargs) + return dct + + +@register +class InstructionBreakpoint(BaseSchema): + """ + Properties of a breakpoint passed to the setInstructionBreakpoints request + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "instructionReference": { + "type": "string", + "description": "The instruction reference of the breakpoint.\nThis should be a memory or instruction pointer reference from an EvaluateResponse, Variable, StackFrame, GotoTarget, or Breakpoint." + }, + "offset": { + "type": "integer", + "description": "An optional offset from the instruction reference.\nThis can be negative." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional breakpoints.\nIt is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true." + }, + "hitCondition": { + "type": "string", + "description": "An optional expression that controls how many hits of the breakpoint are ignored.\nThe backend is expected to interpret the expression as needed.\nThe attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, instructionReference, offset=None, condition=None, hitCondition=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string instructionReference: The instruction reference of the breakpoint. + This should be a memory or instruction pointer reference from an EvaluateResponse, Variable, StackFrame, GotoTarget, or Breakpoint. + :param integer offset: An optional offset from the instruction reference. + This can be negative. + :param string condition: An optional expression for conditional breakpoints. + It is only honored by a debug adapter if the capability 'supportsConditionalBreakpoints' is true. + :param string hitCondition: An optional expression that controls how many hits of the breakpoint are ignored. + The backend is expected to interpret the expression as needed. + The attribute is only honored by a debug adapter if the capability 'supportsHitConditionalBreakpoints' is true. + """ + self.instructionReference = instructionReference + self.offset = offset + self.condition = condition + self.hitCondition = hitCondition + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + instructionReference = self.instructionReference + offset = self.offset + condition = self.condition + hitCondition = self.hitCondition + dct = { + 'instructionReference': instructionReference, + } + if offset is not None: + dct['offset'] = offset + if condition is not None: + dct['condition'] = condition + if hitCondition is not None: + dct['hitCondition'] = hitCondition + dct.update(self.kwargs) + return dct + + +@register +class Breakpoint(BaseSchema): + """ + Information about a Breakpoint created in setBreakpoints, setFunctionBreakpoints, + setInstructionBreakpoints, or setDataBreakpoints. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "id": { + "type": "integer", + "description": "An optional identifier for the breakpoint. It is needed if breakpoint events are used to update or remove breakpoints." + }, + "verified": { + "type": "boolean", + "description": "If true breakpoint could be set (but not necessarily at the desired location)." + }, + "message": { + "type": "string", + "description": "An optional message about the state of the breakpoint.\nThis is shown to the user and can be used to explain why a breakpoint could not be verified." + }, + "source": { + "description": "The source where the breakpoint is located.", + "type": "Source" + }, + "line": { + "type": "integer", + "description": "The start line of the actual range covered by the breakpoint." + }, + "column": { + "type": "integer", + "description": "An optional start column of the actual range covered by the breakpoint." + }, + "endLine": { + "type": "integer", + "description": "An optional end line of the actual range covered by the breakpoint." + }, + "endColumn": { + "type": "integer", + "description": "An optional end column of the actual range covered by the breakpoint.\nIf no end line is given, then the end column is assumed to be in the start line." + }, + "instructionReference": { + "type": "string", + "description": "An optional memory reference to where the breakpoint is set." + }, + "offset": { + "type": "integer", + "description": "An optional offset from the instruction reference.\nThis can be negative." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, verified, id=None, message=None, source=None, line=None, column=None, endLine=None, endColumn=None, instructionReference=None, offset=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean verified: If true breakpoint could be set (but not necessarily at the desired location). + :param integer id: An optional identifier for the breakpoint. It is needed if breakpoint events are used to update or remove breakpoints. + :param string message: An optional message about the state of the breakpoint. + This is shown to the user and can be used to explain why a breakpoint could not be verified. + :param Source source: The source where the breakpoint is located. + :param integer line: The start line of the actual range covered by the breakpoint. + :param integer column: An optional start column of the actual range covered by the breakpoint. + :param integer endLine: An optional end line of the actual range covered by the breakpoint. + :param integer endColumn: An optional end column of the actual range covered by the breakpoint. + If no end line is given, then the end column is assumed to be in the start line. + :param string instructionReference: An optional memory reference to where the breakpoint is set. + :param integer offset: An optional offset from the instruction reference. + This can be negative. + """ + self.verified = verified + self.id = id + self.message = message + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.line = line + self.column = column + self.endLine = endLine + self.endColumn = endColumn + self.instructionReference = instructionReference + self.offset = offset + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + verified = self.verified + id = self.id # noqa (assign to builtin) + message = self.message + source = self.source + line = self.line + column = self.column + endLine = self.endLine + endColumn = self.endColumn + instructionReference = self.instructionReference + offset = self.offset + dct = { + 'verified': verified, + } + if id is not None: + dct['id'] = id + if message is not None: + dct['message'] = message + if source is not None: + dct['source'] = source.to_dict(update_ids_to_dap=update_ids_to_dap) + if line is not None: + dct['line'] = line + if column is not None: + dct['column'] = column + if endLine is not None: + dct['endLine'] = endLine + if endColumn is not None: + dct['endColumn'] = endColumn + if instructionReference is not None: + dct['instructionReference'] = instructionReference + if offset is not None: + dct['offset'] = offset + dct.update(self.kwargs) + return dct + + +@register +class SteppingGranularity(BaseSchema): + """ + The granularity of one 'step' in the stepping requests 'next', 'stepIn', 'stepOut', and 'stepBack'. + + Note: automatically generated code. Do not edit manually. + """ + + STATEMENT = 'statement' + LINE = 'line' + INSTRUCTION = 'instruction' + + VALID_VALUES = set(['statement', 'line', 'instruction']) + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register +class StepInTarget(BaseSchema): + """ + A StepInTarget can be used in the 'stepIn' request and determines into which single target the + stepIn request should step. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "id": { + "type": "integer", + "description": "Unique identifier for a stepIn target." + }, + "label": { + "type": "string", + "description": "The name of the stepIn target (shown in the UI)." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, id, label, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer id: Unique identifier for a stepIn target. + :param string label: The name of the stepIn target (shown in the UI). + """ + self.id = id + self.label = label + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + id = self.id # noqa (assign to builtin) + label = self.label + dct = { + 'id': id, + 'label': label, + } + dct.update(self.kwargs) + return dct + + +@register +class GotoTarget(BaseSchema): + """ + A GotoTarget describes a code location that can be used as a target in the 'goto' request. + + The possible goto targets can be determined via the 'gotoTargets' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "id": { + "type": "integer", + "description": "Unique identifier for a goto target. This is used in the goto request." + }, + "label": { + "type": "string", + "description": "The name of the goto target (shown in the UI)." + }, + "line": { + "type": "integer", + "description": "The line of the goto target." + }, + "column": { + "type": "integer", + "description": "An optional column of the goto target." + }, + "endLine": { + "type": "integer", + "description": "An optional end line of the range covered by the goto target." + }, + "endColumn": { + "type": "integer", + "description": "An optional end column of the range covered by the goto target." + }, + "instructionPointerReference": { + "type": "string", + "description": "Optional memory reference for the instruction pointer value represented by this target." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, id, label, line, column=None, endLine=None, endColumn=None, instructionPointerReference=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer id: Unique identifier for a goto target. This is used in the goto request. + :param string label: The name of the goto target (shown in the UI). + :param integer line: The line of the goto target. + :param integer column: An optional column of the goto target. + :param integer endLine: An optional end line of the range covered by the goto target. + :param integer endColumn: An optional end column of the range covered by the goto target. + :param string instructionPointerReference: Optional memory reference for the instruction pointer value represented by this target. + """ + self.id = id + self.label = label + self.line = line + self.column = column + self.endLine = endLine + self.endColumn = endColumn + self.instructionPointerReference = instructionPointerReference + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + id = self.id # noqa (assign to builtin) + label = self.label + line = self.line + column = self.column + endLine = self.endLine + endColumn = self.endColumn + instructionPointerReference = self.instructionPointerReference + dct = { + 'id': id, + 'label': label, + 'line': line, + } + if column is not None: + dct['column'] = column + if endLine is not None: + dct['endLine'] = endLine + if endColumn is not None: + dct['endColumn'] = endColumn + if instructionPointerReference is not None: + dct['instructionPointerReference'] = instructionPointerReference + dct.update(self.kwargs) + return dct + + +@register +class CompletionItem(BaseSchema): + """ + CompletionItems are the suggestions returned from the CompletionsRequest. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "label": { + "type": "string", + "description": "The label of this completion item. By default this is also the text that is inserted when selecting this completion." + }, + "text": { + "type": "string", + "description": "If text is not falsy then it is inserted instead of the label." + }, + "sortText": { + "type": "string", + "description": "A string that should be used when comparing this item with other items. When `falsy` the label is used." + }, + "type": { + "description": "The item's type. Typically the client uses this information to render the item in the UI with an icon.", + "type": "CompletionItemType" + }, + "start": { + "type": "integer", + "description": "This value determines the location (in the CompletionsRequest's 'text' attribute) where the completion text is added.\nIf missing the text is added at the location specified by the CompletionsRequest's 'column' attribute." + }, + "length": { + "type": "integer", + "description": "This value determines how many characters are overwritten by the completion text.\nIf missing the value 0 is assumed which results in the completion text being inserted." + }, + "selectionStart": { + "type": "integer", + "description": "Determines the start of the new selection after the text has been inserted (or replaced).\nThe start position must in the range 0 and length of the completion text.\nIf omitted the selection starts at the end of the completion text." + }, + "selectionLength": { + "type": "integer", + "description": "Determines the length of the new selection after the text has been inserted (or replaced).\nThe selection can not extend beyond the bounds of the completion text.\nIf omitted the length is assumed to be 0." + } + } + __refs__ = set(['type']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, label, text=None, sortText=None, type=None, start=None, length=None, selectionStart=None, selectionLength=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string label: The label of this completion item. By default this is also the text that is inserted when selecting this completion. + :param string text: If text is not falsy then it is inserted instead of the label. + :param string sortText: A string that should be used when comparing this item with other items. When `falsy` the label is used. + :param CompletionItemType type: The item's type. Typically the client uses this information to render the item in the UI with an icon. + :param integer start: This value determines the location (in the CompletionsRequest's 'text' attribute) where the completion text is added. + If missing the text is added at the location specified by the CompletionsRequest's 'column' attribute. + :param integer length: This value determines how many characters are overwritten by the completion text. + If missing the value 0 is assumed which results in the completion text being inserted. + :param integer selectionStart: Determines the start of the new selection after the text has been inserted (or replaced). + The start position must in the range 0 and length of the completion text. + If omitted the selection starts at the end of the completion text. + :param integer selectionLength: Determines the length of the new selection after the text has been inserted (or replaced). + The selection can not extend beyond the bounds of the completion text. + If omitted the length is assumed to be 0. + """ + self.label = label + self.text = text + self.sortText = sortText + if type is not None: + assert type in CompletionItemType.VALID_VALUES + self.type = type + self.start = start + self.length = length + self.selectionStart = selectionStart + self.selectionLength = selectionLength + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + label = self.label + text = self.text + sortText = self.sortText + type = self.type # noqa (assign to builtin) + start = self.start + length = self.length + selectionStart = self.selectionStart + selectionLength = self.selectionLength + dct = { + 'label': label, + } + if text is not None: + dct['text'] = text + if sortText is not None: + dct['sortText'] = sortText + if type is not None: + dct['type'] = type + if start is not None: + dct['start'] = start + if length is not None: + dct['length'] = length + if selectionStart is not None: + dct['selectionStart'] = selectionStart + if selectionLength is not None: + dct['selectionLength'] = selectionLength + dct.update(self.kwargs) + return dct + + +@register +class CompletionItemType(BaseSchema): + """ + Some predefined types for the CompletionItem. Please note that not all clients have specific icons + for all of them. + + Note: automatically generated code. Do not edit manually. + """ + + METHOD = 'method' + FUNCTION = 'function' + CONSTRUCTOR = 'constructor' + FIELD = 'field' + VARIABLE = 'variable' + CLASS = 'class' + INTERFACE = 'interface' + MODULE = 'module' + PROPERTY = 'property' + UNIT = 'unit' + VALUE = 'value' + ENUM = 'enum' + KEYWORD = 'keyword' + SNIPPET = 'snippet' + TEXT = 'text' + COLOR = 'color' + FILE = 'file' + REFERENCE = 'reference' + CUSTOMCOLOR = 'customcolor' + + VALID_VALUES = set(['method', 'function', 'constructor', 'field', 'variable', 'class', 'interface', 'module', 'property', 'unit', 'value', 'enum', 'keyword', 'snippet', 'text', 'color', 'file', 'reference', 'customcolor']) + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register +class ChecksumAlgorithm(BaseSchema): + """ + Names of checksum algorithms that may be supported by a debug adapter. + + Note: automatically generated code. Do not edit manually. + """ + + MD5 = 'MD5' + SHA1 = 'SHA1' + SHA256 = 'SHA256' + TIMESTAMP = 'timestamp' + + VALID_VALUES = set(['MD5', 'SHA1', 'SHA256', 'timestamp']) + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register +class Checksum(BaseSchema): + """ + The checksum of an item calculated by the specified algorithm. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "algorithm": { + "description": "The algorithm used to calculate this checksum.", + "type": "ChecksumAlgorithm" + }, + "checksum": { + "type": "string", + "description": "Value of the checksum." + } + } + __refs__ = set(['algorithm']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, algorithm, checksum, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param ChecksumAlgorithm algorithm: The algorithm used to calculate this checksum. + :param string checksum: Value of the checksum. + """ + if algorithm is not None: + assert algorithm in ChecksumAlgorithm.VALID_VALUES + self.algorithm = algorithm + self.checksum = checksum + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + algorithm = self.algorithm + checksum = self.checksum + dct = { + 'algorithm': algorithm, + 'checksum': checksum, + } + dct.update(self.kwargs) + return dct + + +@register +class ValueFormat(BaseSchema): + """ + Provides formatting information for a value. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "hex": { + "type": "boolean", + "description": "Display the value in hex." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, hex=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean hex: Display the value in hex. + """ + self.hex = hex + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + hex = self.hex # noqa (assign to builtin) + dct = { + } + if hex is not None: + dct['hex'] = hex + dct.update(self.kwargs) + return dct + + +@register +class StackFrameFormat(BaseSchema): + """ + Provides formatting information for a stack frame. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "hex": { + "type": "boolean", + "description": "Display the value in hex." + }, + "parameters": { + "type": "boolean", + "description": "Displays parameters for the stack frame." + }, + "parameterTypes": { + "type": "boolean", + "description": "Displays the types of parameters for the stack frame." + }, + "parameterNames": { + "type": "boolean", + "description": "Displays the names of parameters for the stack frame." + }, + "parameterValues": { + "type": "boolean", + "description": "Displays the values of parameters for the stack frame." + }, + "line": { + "type": "boolean", + "description": "Displays the line number of the stack frame." + }, + "module": { + "type": "boolean", + "description": "Displays the module of the stack frame." + }, + "includeAll": { + "type": "boolean", + "description": "Includes all stack frames, including those the debug adapter might otherwise hide." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, hex=None, parameters=None, parameterTypes=None, parameterNames=None, parameterValues=None, line=None, module=None, includeAll=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean hex: Display the value in hex. + :param boolean parameters: Displays parameters for the stack frame. + :param boolean parameterTypes: Displays the types of parameters for the stack frame. + :param boolean parameterNames: Displays the names of parameters for the stack frame. + :param boolean parameterValues: Displays the values of parameters for the stack frame. + :param boolean line: Displays the line number of the stack frame. + :param boolean module: Displays the module of the stack frame. + :param boolean includeAll: Includes all stack frames, including those the debug adapter might otherwise hide. + """ + self.hex = hex + self.parameters = parameters + self.parameterTypes = parameterTypes + self.parameterNames = parameterNames + self.parameterValues = parameterValues + self.line = line + self.module = module + self.includeAll = includeAll + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + hex = self.hex # noqa (assign to builtin) + parameters = self.parameters + parameterTypes = self.parameterTypes + parameterNames = self.parameterNames + parameterValues = self.parameterValues + line = self.line + module = self.module + includeAll = self.includeAll + dct = { + } + if hex is not None: + dct['hex'] = hex + if parameters is not None: + dct['parameters'] = parameters + if parameterTypes is not None: + dct['parameterTypes'] = parameterTypes + if parameterNames is not None: + dct['parameterNames'] = parameterNames + if parameterValues is not None: + dct['parameterValues'] = parameterValues + if line is not None: + dct['line'] = line + if module is not None: + dct['module'] = module + if includeAll is not None: + dct['includeAll'] = includeAll + dct.update(self.kwargs) + return dct + + +@register +class ExceptionFilterOptions(BaseSchema): + """ + An ExceptionFilterOptions is used to specify an exception filter together with a condition for the + setExceptionsFilter request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "filterId": { + "type": "string", + "description": "ID of an exception filter returned by the 'exceptionBreakpointFilters' capability." + }, + "condition": { + "type": "string", + "description": "An optional expression for conditional exceptions.\nThe exception will break into the debugger if the result of the condition is true." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, filterId, condition=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string filterId: ID of an exception filter returned by the 'exceptionBreakpointFilters' capability. + :param string condition: An optional expression for conditional exceptions. + The exception will break into the debugger if the result of the condition is true. + """ + self.filterId = filterId + self.condition = condition + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + filterId = self.filterId + condition = self.condition + dct = { + 'filterId': filterId, + } + if condition is not None: + dct['condition'] = condition + dct.update(self.kwargs) + return dct + + +@register +class ExceptionOptions(BaseSchema): + """ + An ExceptionOptions assigns configuration options to a set of exceptions. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "path": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionPathSegment" + }, + "description": "A path that selects a single or multiple exceptions in a tree. If 'path' is missing, the whole tree is selected.\nBy convention the first segment of the path is a category that is used to group exceptions in the UI." + }, + "breakMode": { + "description": "Condition when a thrown exception should result in a break.", + "type": "ExceptionBreakMode" + } + } + __refs__ = set(['breakMode']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakMode, path=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param ExceptionBreakMode breakMode: Condition when a thrown exception should result in a break. + :param array path: A path that selects a single or multiple exceptions in a tree. If 'path' is missing, the whole tree is selected. + By convention the first segment of the path is a category that is used to group exceptions in the UI. + """ + if breakMode is not None: + assert breakMode in ExceptionBreakMode.VALID_VALUES + self.breakMode = breakMode + self.path = path + if update_ids_from_dap and self.path: + for o in self.path: + ExceptionPathSegment.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakMode = self.breakMode + path = self.path + if path and hasattr(path[0], "to_dict"): + path = [x.to_dict() for x in path] + dct = { + 'breakMode': breakMode, + } + if path is not None: + dct['path'] = [ExceptionPathSegment.update_dict_ids_to_dap(o) for o in path] if (update_ids_to_dap and path) else path + dct.update(self.kwargs) + return dct + + +@register +class ExceptionBreakMode(BaseSchema): + """ + This enumeration defines all possible conditions when a thrown exception should result in a break. + + never: never breaks, + + always: always breaks, + + unhandled: breaks when exception unhandled, + + userUnhandled: breaks if the exception is not handled by user code. + + Note: automatically generated code. Do not edit manually. + """ + + NEVER = 'never' + ALWAYS = 'always' + UNHANDLED = 'unhandled' + USERUNHANDLED = 'userUnhandled' + + VALID_VALUES = set(['never', 'always', 'unhandled', 'userUnhandled']) + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register +class ExceptionPathSegment(BaseSchema): + """ + An ExceptionPathSegment represents a segment in a path that is used to match leafs or nodes in a + tree of exceptions. + + If a segment consists of more than one name, it matches the names provided if 'negate' is false or + missing or + + it matches anything except the names provided if 'negate' is true. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "negate": { + "type": "boolean", + "description": "If false or missing this segment matches the names provided, otherwise it matches anything except the names provided." + }, + "names": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Depending on the value of 'negate' the names that should match or not match." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, names, negate=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array names: Depending on the value of 'negate' the names that should match or not match. + :param boolean negate: If false or missing this segment matches the names provided, otherwise it matches anything except the names provided. + """ + self.names = names + self.negate = negate + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + names = self.names + if names and hasattr(names[0], "to_dict"): + names = [x.to_dict() for x in names] + negate = self.negate + dct = { + 'names': names, + } + if negate is not None: + dct['negate'] = negate + dct.update(self.kwargs) + return dct + + +@register +class ExceptionDetails(BaseSchema): + """ + Detailed information about an exception that has occurred. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "message": { + "type": "string", + "description": "Message contained in the exception." + }, + "typeName": { + "type": "string", + "description": "Short type name of the exception object." + }, + "fullTypeName": { + "type": "string", + "description": "Fully-qualified type name of the exception object." + }, + "evaluateName": { + "type": "string", + "description": "Optional expression that can be evaluated in the current scope to obtain the exception object." + }, + "stackTrace": { + "type": "string", + "description": "Stack trace at the time the exception was thrown." + }, + "innerException": { + "type": "array", + "items": { + "$ref": "#/definitions/ExceptionDetails" + }, + "description": "Details of the exception contained by this exception, if any." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, message=None, typeName=None, fullTypeName=None, evaluateName=None, stackTrace=None, innerException=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string message: Message contained in the exception. + :param string typeName: Short type name of the exception object. + :param string fullTypeName: Fully-qualified type name of the exception object. + :param string evaluateName: Optional expression that can be evaluated in the current scope to obtain the exception object. + :param string stackTrace: Stack trace at the time the exception was thrown. + :param array innerException: Details of the exception contained by this exception, if any. + """ + self.message = message + self.typeName = typeName + self.fullTypeName = fullTypeName + self.evaluateName = evaluateName + self.stackTrace = stackTrace + self.innerException = innerException + if update_ids_from_dap and self.innerException: + for o in self.innerException: + ExceptionDetails.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + message = self.message + typeName = self.typeName + fullTypeName = self.fullTypeName + evaluateName = self.evaluateName + stackTrace = self.stackTrace + innerException = self.innerException + if innerException and hasattr(innerException[0], "to_dict"): + innerException = [x.to_dict() for x in innerException] + dct = { + } + if message is not None: + dct['message'] = message + if typeName is not None: + dct['typeName'] = typeName + if fullTypeName is not None: + dct['fullTypeName'] = fullTypeName + if evaluateName is not None: + dct['evaluateName'] = evaluateName + if stackTrace is not None: + dct['stackTrace'] = stackTrace + if innerException is not None: + dct['innerException'] = [ExceptionDetails.update_dict_ids_to_dap(o) for o in innerException] if (update_ids_to_dap and innerException) else innerException + dct.update(self.kwargs) + return dct + + +@register +class DisassembledInstruction(BaseSchema): + """ + Represents a single disassembled instruction. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "address": { + "type": "string", + "description": "The address of the instruction. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise." + }, + "instructionBytes": { + "type": "string", + "description": "Optional raw bytes representing the instruction and its operands, in an implementation-defined format." + }, + "instruction": { + "type": "string", + "description": "Text representing the instruction and its operands, in an implementation-defined format." + }, + "symbol": { + "type": "string", + "description": "Name of the symbol that corresponds with the location of this instruction, if any." + }, + "location": { + "description": "Source location that corresponds to this instruction, if any.\nShould always be set (if available) on the first instruction returned,\nbut can be omitted afterwards if this instruction maps to the same source file as the previous instruction.", + "type": "Source" + }, + "line": { + "type": "integer", + "description": "The line within the source location that corresponds to this instruction, if any." + }, + "column": { + "type": "integer", + "description": "The column within the line that corresponds to this instruction, if any." + }, + "endLine": { + "type": "integer", + "description": "The end line of the range that corresponds to this instruction, if any." + }, + "endColumn": { + "type": "integer", + "description": "The end column of the range that corresponds to this instruction, if any." + } + } + __refs__ = set(['location']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, address, instruction, instructionBytes=None, symbol=None, location=None, line=None, column=None, endLine=None, endColumn=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string address: The address of the instruction. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. + :param string instruction: Text representing the instruction and its operands, in an implementation-defined format. + :param string instructionBytes: Optional raw bytes representing the instruction and its operands, in an implementation-defined format. + :param string symbol: Name of the symbol that corresponds with the location of this instruction, if any. + :param Source location: Source location that corresponds to this instruction, if any. + Should always be set (if available) on the first instruction returned, + but can be omitted afterwards if this instruction maps to the same source file as the previous instruction. + :param integer line: The line within the source location that corresponds to this instruction, if any. + :param integer column: The column within the line that corresponds to this instruction, if any. + :param integer endLine: The end line of the range that corresponds to this instruction, if any. + :param integer endColumn: The end column of the range that corresponds to this instruction, if any. + """ + self.address = address + self.instruction = instruction + self.instructionBytes = instructionBytes + self.symbol = symbol + if location is None: + self.location = Source() + else: + self.location = Source(update_ids_from_dap=update_ids_from_dap, **location) if location.__class__ != Source else location + self.line = line + self.column = column + self.endLine = endLine + self.endColumn = endColumn + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + address = self.address + instruction = self.instruction + instructionBytes = self.instructionBytes + symbol = self.symbol + location = self.location + line = self.line + column = self.column + endLine = self.endLine + endColumn = self.endColumn + dct = { + 'address': address, + 'instruction': instruction, + } + if instructionBytes is not None: + dct['instructionBytes'] = instructionBytes + if symbol is not None: + dct['symbol'] = symbol + if location is not None: + dct['location'] = location.to_dict(update_ids_to_dap=update_ids_to_dap) + if line is not None: + dct['line'] = line + if column is not None: + dct['column'] = column + if endLine is not None: + dct['endLine'] = endLine + if endColumn is not None: + dct['endColumn'] = endColumn + dct.update(self.kwargs) + return dct + + +@register +class InvalidatedAreas(BaseSchema): + """ + Logical areas that can be invalidated by the 'invalidated' event. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register_request('setDebuggerProperty') +@register +class SetDebuggerPropertyRequest(BaseSchema): + """ + The request can be used to enable or disable debugger features. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setDebuggerProperty" + ] + }, + "arguments": { + "type": "SetDebuggerPropertyArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetDebuggerPropertyArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setDebuggerProperty' + if arguments is None: + self.arguments = SetDebuggerPropertyArguments() + else: + self.arguments = SetDebuggerPropertyArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetDebuggerPropertyArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetDebuggerPropertyArguments(BaseSchema): + """ + Arguments for 'setDebuggerProperty' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "ideOS": { + "type": [ + "string" + ], + "description": "OS where the ide is running. Supported values [Windows, Linux]" + }, + "dontTraceStartPatterns": { + "type": [ + "array" + ], + "description": "Patterns to match with the start of the file paths. Matching paths will be added to a list of file where trace is ignored." + }, + "dontTraceEndPatterns": { + "type": [ + "array" + ], + "description": "Patterns to match with the end of the file paths. Matching paths will be added to a list of file where trace is ignored." + }, + "skipSuspendOnBreakpointException": { + "type": [ + "array" + ], + "description": "List of exceptions that should be skipped when doing condition evaluations." + }, + "skipPrintBreakpointException": { + "type": [ + "array" + ], + "description": "List of exceptions that should skip printing to stderr when doing condition evaluations." + }, + "multiThreadsSingleNotification": { + "type": [ + "boolean" + ], + "description": "If false then a notification is generated for each thread event. If true a single event is gnenerated, and all threads follow that behavior." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, ideOS=None, dontTraceStartPatterns=None, dontTraceEndPatterns=None, skipSuspendOnBreakpointException=None, skipPrintBreakpointException=None, multiThreadsSingleNotification=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param ['string'] ideOS: OS where the ide is running. Supported values [Windows, Linux] + :param ['array'] dontTraceStartPatterns: Patterns to match with the start of the file paths. Matching paths will be added to a list of file where trace is ignored. + :param ['array'] dontTraceEndPatterns: Patterns to match with the end of the file paths. Matching paths will be added to a list of file where trace is ignored. + :param ['array'] skipSuspendOnBreakpointException: List of exceptions that should be skipped when doing condition evaluations. + :param ['array'] skipPrintBreakpointException: List of exceptions that should skip printing to stderr when doing condition evaluations. + :param ['boolean'] multiThreadsSingleNotification: If false then a notification is generated for each thread event. If true a single event is gnenerated, and all threads follow that behavior. + """ + self.ideOS = ideOS + self.dontTraceStartPatterns = dontTraceStartPatterns + self.dontTraceEndPatterns = dontTraceEndPatterns + self.skipSuspendOnBreakpointException = skipSuspendOnBreakpointException + self.skipPrintBreakpointException = skipPrintBreakpointException + self.multiThreadsSingleNotification = multiThreadsSingleNotification + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + ideOS = self.ideOS + dontTraceStartPatterns = self.dontTraceStartPatterns + dontTraceEndPatterns = self.dontTraceEndPatterns + skipSuspendOnBreakpointException = self.skipSuspendOnBreakpointException + skipPrintBreakpointException = self.skipPrintBreakpointException + multiThreadsSingleNotification = self.multiThreadsSingleNotification + dct = { + } + if ideOS is not None: + dct['ideOS'] = ideOS + if dontTraceStartPatterns is not None: + dct['dontTraceStartPatterns'] = dontTraceStartPatterns + if dontTraceEndPatterns is not None: + dct['dontTraceEndPatterns'] = dontTraceEndPatterns + if skipSuspendOnBreakpointException is not None: + dct['skipSuspendOnBreakpointException'] = skipSuspendOnBreakpointException + if skipPrintBreakpointException is not None: + dct['skipPrintBreakpointException'] = skipPrintBreakpointException + if multiThreadsSingleNotification is not None: + dct['multiThreadsSingleNotification'] = multiThreadsSingleNotification + dct.update(self.kwargs) + return dct + + +@register_response('setDebuggerProperty') +@register +class SetDebuggerPropertyResponse(BaseSchema): + """ + Response to 'setDebuggerProperty' request. This is just an acknowledgement, so no body field is + required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_event('pydevdInputRequested') +@register +class PydevdInputRequestedEvent(BaseSchema): + """ + The event indicates input was requested by debuggee. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "event" + ] + }, + "event": { + "type": "string", + "enum": [ + "pydevdInputRequested" + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Event-specific information." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string event: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Event-specific information. + """ + self.type = 'event' + self.event = 'pydevdInputRequested' + self.seq = seq + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + event = self.event + seq = self.seq + body = self.body + dct = { + 'type': type, + 'event': event, + 'seq': seq, + } + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register_request('setPydevdSourceMap') +@register +class SetPydevdSourceMapRequest(BaseSchema): + """ + Sets multiple PydevdSourceMap for a single source and clears all previous PydevdSourceMap in that + source. + + i.e.: Maps paths and lines in a 1:N mapping (use case: map a single file in the IDE to multiple + IPython cells). + + To clear all PydevdSourceMap for a source, specify an empty array. + + Interaction with breakpoints: When a new mapping is sent, breakpoints that match the source (or + previously matched a source) are reapplied. + + Interaction with launch pathMapping: both mappings are independent. This mapping is applied after + the launch pathMapping. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "setPydevdSourceMap" + ] + }, + "arguments": { + "type": "SetPydevdSourceMapArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param SetPydevdSourceMapArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'setPydevdSourceMap' + if arguments is None: + self.arguments = SetPydevdSourceMapArguments() + else: + self.arguments = SetPydevdSourceMapArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetPydevdSourceMapArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class SetPydevdSourceMapArguments(BaseSchema): + """ + Arguments for 'setPydevdSourceMap' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "source": { + "description": "The source location of the PydevdSourceMap; 'source.path' must be specified (e.g.: for an ipython notebook this could be something as /home/notebook/note.py).", + "type": "Source" + }, + "pydevdSourceMaps": { + "type": "array", + "items": { + "$ref": "#/definitions/PydevdSourceMap" + }, + "description": "The PydevdSourceMaps to be set to the given source (provide an empty array to clear the source mappings for a given path)." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, source, pydevdSourceMaps=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param Source source: The source location of the PydevdSourceMap; 'source.path' must be specified (e.g.: for an ipython notebook this could be something as /home/notebook/note.py). + :param array pydevdSourceMaps: The PydevdSourceMaps to be set to the given source (provide an empty array to clear the source mappings for a given path). + """ + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.pydevdSourceMaps = pydevdSourceMaps + if update_ids_from_dap and self.pydevdSourceMaps: + for o in self.pydevdSourceMaps: + PydevdSourceMap.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + source = self.source + pydevdSourceMaps = self.pydevdSourceMaps + if pydevdSourceMaps and hasattr(pydevdSourceMaps[0], "to_dict"): + pydevdSourceMaps = [x.to_dict() for x in pydevdSourceMaps] + dct = { + 'source': source.to_dict(update_ids_to_dap=update_ids_to_dap), + } + if pydevdSourceMaps is not None: + dct['pydevdSourceMaps'] = [PydevdSourceMap.update_dict_ids_to_dap(o) for o in pydevdSourceMaps] if (update_ids_to_dap and pydevdSourceMaps) else pydevdSourceMaps + dct.update(self.kwargs) + return dct + + +@register_response('setPydevdSourceMap') +@register +class SetPydevdSourceMapResponse(BaseSchema): + """ + Response to 'setPydevdSourceMap' request. This is just an acknowledgement, so no body field is + required. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Contains request result if success is true and optional error details if success is false." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + self.seq = seq + self.message = message + self.body = body + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + seq = self.seq + message = self.message + body = self.body + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'seq': seq, + } + if message is not None: + dct['message'] = message + if body is not None: + dct['body'] = body + dct.update(self.kwargs) + return dct + + +@register +class PydevdSourceMap(BaseSchema): + """ + Information that allows mapping a local line to a remote source/line. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "line": { + "type": "integer", + "description": "The local line to which the mapping should map to (e.g.: for an ipython notebook this would be the first line of the cell in the file)." + }, + "endLine": { + "type": "integer", + "description": "The end line." + }, + "runtimeSource": { + "description": "The path that the user has remotely -- 'source.path' must be specified (e.g.: for an ipython notebook this could be something as '')", + "type": "Source" + }, + "runtimeLine": { + "type": "integer", + "description": "The remote line to which the mapping should map to (e.g.: for an ipython notebook this would be always 1 as it'd map the start of the cell)." + } + } + __refs__ = set(['runtimeSource']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, line, endLine, runtimeSource, runtimeLine, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer line: The local line to which the mapping should map to (e.g.: for an ipython notebook this would be the first line of the cell in the file). + :param integer endLine: The end line. + :param Source runtimeSource: The path that the user has remotely -- 'source.path' must be specified (e.g.: for an ipython notebook this could be something as '') + :param integer runtimeLine: The remote line to which the mapping should map to (e.g.: for an ipython notebook this would be always 1 as it'd map the start of the cell). + """ + self.line = line + self.endLine = endLine + if runtimeSource is None: + self.runtimeSource = Source() + else: + self.runtimeSource = Source(update_ids_from_dap=update_ids_from_dap, **runtimeSource) if runtimeSource.__class__ != Source else runtimeSource + self.runtimeLine = runtimeLine + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + line = self.line + endLine = self.endLine + runtimeSource = self.runtimeSource + runtimeLine = self.runtimeLine + dct = { + 'line': line, + 'endLine': endLine, + 'runtimeSource': runtimeSource.to_dict(update_ids_to_dap=update_ids_to_dap), + 'runtimeLine': runtimeLine, + } + dct.update(self.kwargs) + return dct + + +@register_request('pydevdSystemInfo') +@register +class PydevdSystemInfoRequest(BaseSchema): + """ + The request can be used retrieve system information, python version, etc. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "pydevdSystemInfo" + ] + }, + "arguments": { + "type": "PydevdSystemInfoArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, seq=-1, arguments=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param PydevdSystemInfoArguments arguments: + """ + self.type = 'request' + self.command = 'pydevdSystemInfo' + self.seq = seq + if arguments is None: + self.arguments = PydevdSystemInfoArguments() + else: + self.arguments = PydevdSystemInfoArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != PydevdSystemInfoArguments else arguments + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + seq = self.seq + arguments = self.arguments + dct = { + 'type': type, + 'command': command, + 'seq': seq, + } + if arguments is not None: + dct['arguments'] = arguments.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class PydevdSystemInfoArguments(BaseSchema): + """ + Arguments for 'pydevdSystemInfo' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register_response('pydevdSystemInfo') +@register +class PydevdSystemInfoResponse(BaseSchema): + """ + Response to 'pydevdSystemInfo' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "python": { + "$ref": "#/definitions/PydevdPythonInfo", + "description": "Information about the python version running in the current process." + }, + "platform": { + "$ref": "#/definitions/PydevdPlatformInfo", + "description": "Information about the plarforn on which the current process is running." + }, + "process": { + "$ref": "#/definitions/PydevdProcessInfo", + "description": "Information about the current process." + }, + "pydevd": { + "$ref": "#/definitions/PydevdInfo", + "description": "Information about pydevd." + } + }, + "required": [ + "python", + "platform", + "process", + "pydevd" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param PydevdSystemInfoResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = PydevdSystemInfoResponseBody() + else: + self.body = PydevdSystemInfoResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != PydevdSystemInfoResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register +class PydevdPythonInfo(BaseSchema): + """ + This object contains python version and implementation details. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "version": { + "type": "string", + "description": "Python version as a string in semver format: ..." + }, + "implementation": { + "description": "Python version as a string in this format ...", + "type": "PydevdPythonImplementationInfo" + } + } + __refs__ = set(['implementation']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, version=None, implementation=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string version: Python version as a string in semver format: ... + :param PydevdPythonImplementationInfo implementation: Python version as a string in this format ... + """ + self.version = version + if implementation is None: + self.implementation = PydevdPythonImplementationInfo() + else: + self.implementation = PydevdPythonImplementationInfo(update_ids_from_dap=update_ids_from_dap, **implementation) if implementation.__class__ != PydevdPythonImplementationInfo else implementation + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + version = self.version + implementation = self.implementation + dct = { + } + if version is not None: + dct['version'] = version + if implementation is not None: + dct['implementation'] = implementation.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class PydevdPythonImplementationInfo(BaseSchema): + """ + This object contains python implementation details. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "name": { + "type": "string", + "description": "Python implementation name." + }, + "version": { + "type": "string", + "description": "Python version as a string in semver format: ..." + }, + "description": { + "type": "string", + "description": "Optional description for this python implementation." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, name=None, version=None, description=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string name: Python implementation name. + :param string version: Python version as a string in semver format: ... + :param string description: Optional description for this python implementation. + """ + self.name = name + self.version = version + self.description = description + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + name = self.name + version = self.version + description = self.description + dct = { + } + if name is not None: + dct['name'] = name + if version is not None: + dct['version'] = version + if description is not None: + dct['description'] = description + dct.update(self.kwargs) + return dct + + +@register +class PydevdPlatformInfo(BaseSchema): + """ + This object contains python version and implementation details. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "name": { + "type": "string", + "description": "Name of the platform as returned by 'sys.platform'." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, name=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string name: Name of the platform as returned by 'sys.platform'. + """ + self.name = name + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + name = self.name + dct = { + } + if name is not None: + dct['name'] = name + dct.update(self.kwargs) + return dct + + +@register +class PydevdProcessInfo(BaseSchema): + """ + This object contains python process details. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "pid": { + "type": "integer", + "description": "Process ID for the current process." + }, + "ppid": { + "type": "integer", + "description": "Parent Process ID for the current process." + }, + "executable": { + "type": "string", + "description": "Path to the executable as returned by 'sys.executable'." + }, + "bitness": { + "type": "integer", + "description": "Integer value indicating the bitness of the current process." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, pid=None, ppid=None, executable=None, bitness=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer pid: Process ID for the current process. + :param integer ppid: Parent Process ID for the current process. + :param string executable: Path to the executable as returned by 'sys.executable'. + :param integer bitness: Integer value indicating the bitness of the current process. + """ + self.pid = pid + self.ppid = ppid + self.executable = executable + self.bitness = bitness + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + pid = self.pid + ppid = self.ppid + executable = self.executable + bitness = self.bitness + dct = { + } + if pid is not None: + dct['pid'] = pid + if ppid is not None: + dct['ppid'] = ppid + if executable is not None: + dct['executable'] = executable + if bitness is not None: + dct['bitness'] = bitness + dct.update(self.kwargs) + return dct + + +@register +class PydevdInfo(BaseSchema): + """ + This object contains details on pydevd. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "usingCython": { + "type": "boolean", + "description": "Specifies whether the cython native module is being used." + }, + "usingFrameEval": { + "type": "boolean", + "description": "Specifies whether the frame eval native module is being used." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, usingCython=None, usingFrameEval=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean usingCython: Specifies whether the cython native module is being used. + :param boolean usingFrameEval: Specifies whether the frame eval native module is being used. + """ + self.usingCython = usingCython + self.usingFrameEval = usingFrameEval + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + usingCython = self.usingCython + usingFrameEval = self.usingFrameEval + dct = { + } + if usingCython is not None: + dct['usingCython'] = usingCython + if usingFrameEval is not None: + dct['usingFrameEval'] = usingFrameEval + dct.update(self.kwargs) + return dct + + +@register_request('pydevdAuthorize') +@register +class PydevdAuthorizeRequest(BaseSchema): + """ + A request to authorize the ide to start accepting commands. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "request" + ] + }, + "command": { + "type": "string", + "enum": [ + "pydevdAuthorize" + ] + }, + "arguments": { + "type": "PydevdAuthorizeArguments" + } + } + __refs__ = set(['arguments']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param string command: + :param PydevdAuthorizeArguments arguments: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + """ + self.type = 'request' + self.command = 'pydevdAuthorize' + if arguments is None: + self.arguments = PydevdAuthorizeArguments() + else: + self.arguments = PydevdAuthorizeArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != PydevdAuthorizeArguments else arguments + self.seq = seq + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + command = self.command + arguments = self.arguments + seq = self.seq + dct = { + 'type': type, + 'command': command, + 'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + dct.update(self.kwargs) + return dct + + +@register +class PydevdAuthorizeArguments(BaseSchema): + """ + Arguments for 'pydevdAuthorize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "debugServerAccessToken": { + "type": "string", + "description": "The access token to access the debug server." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, debugServerAccessToken=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string debugServerAccessToken: The access token to access the debug server. + """ + self.debugServerAccessToken = debugServerAccessToken + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + debugServerAccessToken = self.debugServerAccessToken + dct = { + } + if debugServerAccessToken is not None: + dct['debugServerAccessToken'] = debugServerAccessToken + dct.update(self.kwargs) + return dct + + +@register_response('pydevdAuthorize') +@register +class PydevdAuthorizeResponse(BaseSchema): + """ + Response to 'pydevdAuthorize' request. + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "seq": { + "type": "integer", + "description": "Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request." + }, + "type": { + "type": "string", + "enum": [ + "response" + ] + }, + "request_seq": { + "type": "integer", + "description": "Sequence number of the corresponding request." + }, + "success": { + "type": "boolean", + "description": "Outcome of the request.\nIf true, the request was successful and the 'body' attribute may contain the result of the request.\nIf the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error')." + }, + "command": { + "type": "string", + "description": "The command requested." + }, + "message": { + "type": "string", + "description": "Contains the raw error in short form if 'success' is false.\nThis raw error might be interpreted by the frontend and is not shown in the UI.\nSome predefined values exist.", + "_enum": [ + "cancelled" + ], + "enumDescriptions": [ + "request was cancelled." + ] + }, + "body": { + "type": "object", + "properties": { + "clientAccessToken": { + "type": "string", + "description": "The access token to access the client (i.e.: usually the IDE)." + } + }, + "required": [ + "clientAccessToken" + ] + } + } + __refs__ = set(['body']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, request_seq, success, command, body, seq=-1, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string type: + :param integer request_seq: Sequence number of the corresponding request. + :param boolean success: Outcome of the request. + If true, the request was successful and the 'body' attribute may contain the result of the request. + If the value is false, the attribute 'message' contains the error in short form and the 'body' may contain additional information (see 'ErrorResponse.body.error'). + :param string command: The command requested. + :param PydevdAuthorizeResponseBody body: + :param integer seq: Sequence number (also known as message ID). For protocol messages of type 'request' this ID can be used to cancel the request. + :param string message: Contains the raw error in short form if 'success' is false. + This raw error might be interpreted by the frontend and is not shown in the UI. + Some predefined values exist. + """ + self.type = 'response' + self.request_seq = request_seq + self.success = success + self.command = command + if body is None: + self.body = PydevdAuthorizeResponseBody() + else: + self.body = PydevdAuthorizeResponseBody(update_ids_from_dap=update_ids_from_dap, **body) if body.__class__ != PydevdAuthorizeResponseBody else body + self.seq = seq + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + type = self.type # noqa (assign to builtin) + request_seq = self.request_seq + success = self.success + command = self.command + body = self.body + seq = self.seq + message = self.message + dct = { + 'type': type, + 'request_seq': request_seq, + 'success': success, + 'command': command, + 'body': body.to_dict(update_ids_to_dap=update_ids_to_dap), + 'seq': seq, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register +class ErrorResponseBody(BaseSchema): + """ + "body" of ErrorResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "error": { + "description": "An optional, structured error message.", + "type": "Message" + } + } + __refs__ = set(['error']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, error=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param Message error: An optional, structured error message. + """ + if error is None: + self.error = Message() + else: + self.error = Message(update_ids_from_dap=update_ids_from_dap, **error) if error.__class__ != Message else error + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + error = self.error + dct = { + } + if error is not None: + dct['error'] = error.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class StoppedEventBody(BaseSchema): + """ + "body" of StoppedEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "reason": { + "type": "string", + "description": "The reason for the event.\nFor backward compatibility this string is shown in the UI if the 'description' attribute is missing (but it must not be translated).", + "_enum": [ + "step", + "breakpoint", + "exception", + "pause", + "entry", + "goto", + "function breakpoint", + "data breakpoint", + "instruction breakpoint" + ] + }, + "description": { + "type": "string", + "description": "The full reason for the event, e.g. 'Paused on exception'. This string is shown in the UI as is and must be translated." + }, + "threadId": { + "type": "integer", + "description": "The thread which was stopped." + }, + "preserveFocusHint": { + "type": "boolean", + "description": "A value of true hints to the frontend that this event should not change the focus." + }, + "text": { + "type": "string", + "description": "Additional information. E.g. if reason is 'exception', text contains the exception name. This string is shown in the UI." + }, + "allThreadsStopped": { + "type": "boolean", + "description": "If 'allThreadsStopped' is true, a debug adapter can announce that all threads have stopped.\n- The client should use this information to enable that all threads can be expanded to access their stacktraces.\n- If the attribute is missing or false, only the thread with the given threadId can be expanded." + }, + "hitBreakpointIds": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Ids of the breakpoints that triggered the event. In most cases there will be only a single breakpoint but here are some examples for multiple breakpoints:\n- Different types of breakpoints map to the same location.\n- Multiple source breakpoints get collapsed to the same instruction by the compiler/runtime.\n- Multiple function breakpoints with different function names map to the same location." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, reason, description=None, threadId=None, preserveFocusHint=None, text=None, allThreadsStopped=None, hitBreakpointIds=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string reason: The reason for the event. + For backward compatibility this string is shown in the UI if the 'description' attribute is missing (but it must not be translated). + :param string description: The full reason for the event, e.g. 'Paused on exception'. This string is shown in the UI as is and must be translated. + :param integer threadId: The thread which was stopped. + :param boolean preserveFocusHint: A value of true hints to the frontend that this event should not change the focus. + :param string text: Additional information. E.g. if reason is 'exception', text contains the exception name. This string is shown in the UI. + :param boolean allThreadsStopped: If 'allThreadsStopped' is true, a debug adapter can announce that all threads have stopped. + - The client should use this information to enable that all threads can be expanded to access their stacktraces. + - If the attribute is missing or false, only the thread with the given threadId can be expanded. + :param array hitBreakpointIds: Ids of the breakpoints that triggered the event. In most cases there will be only a single breakpoint but here are some examples for multiple breakpoints: + - Different types of breakpoints map to the same location. + - Multiple source breakpoints get collapsed to the same instruction by the compiler/runtime. + - Multiple function breakpoints with different function names map to the same location. + """ + self.reason = reason + self.description = description + self.threadId = threadId + self.preserveFocusHint = preserveFocusHint + self.text = text + self.allThreadsStopped = allThreadsStopped + self.hitBreakpointIds = hitBreakpointIds + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + reason = self.reason + description = self.description + threadId = self.threadId + preserveFocusHint = self.preserveFocusHint + text = self.text + allThreadsStopped = self.allThreadsStopped + hitBreakpointIds = self.hitBreakpointIds + if hitBreakpointIds and hasattr(hitBreakpointIds[0], "to_dict"): + hitBreakpointIds = [x.to_dict() for x in hitBreakpointIds] + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'reason': reason, + } + if description is not None: + dct['description'] = description + if threadId is not None: + dct['threadId'] = threadId + if preserveFocusHint is not None: + dct['preserveFocusHint'] = preserveFocusHint + if text is not None: + dct['text'] = text + if allThreadsStopped is not None: + dct['allThreadsStopped'] = allThreadsStopped + if hitBreakpointIds is not None: + dct['hitBreakpointIds'] = hitBreakpointIds + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register +class ContinuedEventBody(BaseSchema): + """ + "body" of ContinuedEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threadId": { + "type": "integer", + "description": "The thread which was continued." + }, + "allThreadsContinued": { + "type": "boolean", + "description": "If 'allThreadsContinued' is true, a debug adapter can announce that all threads have continued." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threadId, allThreadsContinued=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer threadId: The thread which was continued. + :param boolean allThreadsContinued: If 'allThreadsContinued' is true, a debug adapter can announce that all threads have continued. + """ + self.threadId = threadId + self.allThreadsContinued = allThreadsContinued + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threadId = self.threadId + allThreadsContinued = self.allThreadsContinued + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'threadId': threadId, + } + if allThreadsContinued is not None: + dct['allThreadsContinued'] = allThreadsContinued + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register +class ExitedEventBody(BaseSchema): + """ + "body" of ExitedEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "exitCode": { + "type": "integer", + "description": "The exit code returned from the debuggee." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, exitCode, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer exitCode: The exit code returned from the debuggee. + """ + self.exitCode = exitCode + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + exitCode = self.exitCode + dct = { + 'exitCode': exitCode, + } + dct.update(self.kwargs) + return dct + + +@register +class TerminatedEventBody(BaseSchema): + """ + "body" of TerminatedEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "restart": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "A debug adapter may set 'restart' to true (or to an arbitrary object) to request that the front end restarts the session.\nThe value is not interpreted by the client and passed unmodified as an attribute '__restart' to the 'launch' and 'attach' requests." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, restart=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] restart: A debug adapter may set 'restart' to true (or to an arbitrary object) to request that the front end restarts the session. + The value is not interpreted by the client and passed unmodified as an attribute '__restart' to the 'launch' and 'attach' requests. + """ + self.restart = restart + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + restart = self.restart + dct = { + } + if restart is not None: + dct['restart'] = restart + dct.update(self.kwargs) + return dct + + +@register +class ThreadEventBody(BaseSchema): + """ + "body" of ThreadEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "reason": { + "type": "string", + "description": "The reason for the event.", + "_enum": [ + "started", + "exited" + ] + }, + "threadId": { + "type": "integer", + "description": "The identifier of the thread." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, reason, threadId, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string reason: The reason for the event. + :param integer threadId: The identifier of the thread. + """ + self.reason = reason + self.threadId = threadId + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + reason = self.reason + threadId = self.threadId + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + 'reason': reason, + 'threadId': threadId, + } + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register +class OutputEventBody(BaseSchema): + """ + "body" of OutputEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "category": { + "type": "string", + "description": "The output category. If not specified or if the category is not understand by the client, 'console' is assumed.", + "_enum": [ + "console", + "important", + "stdout", + "stderr", + "telemetry" + ], + "enumDescriptions": [ + "Show the output in the client's default message UI, e.g. a 'debug console'. This category should only be used for informational output from the debugger (as opposed to the debuggee).", + "A hint for the client to show the ouput in the client's UI for important and highly visible information, e.g. as a popup notification. This category should only be used for important messages from the debugger (as opposed to the debuggee). Since this category value is a hint, clients might ignore the hint and assume the 'console' category.", + "Show the output as normal program output from the debuggee.", + "Show the output as error program output from the debuggee.", + "Send the output to telemetry instead of showing it to the user." + ] + }, + "output": { + "type": "string", + "description": "The output to report." + }, + "group": { + "type": "string", + "description": "Support for keeping an output log organized by grouping related messages.", + "enum": [ + "start", + "startCollapsed", + "end" + ], + "enumDescriptions": [ + "Start a new group in expanded mode. Subsequent output events are members of the group and should be shown indented.\nThe 'output' attribute becomes the name of the group and is not indented.", + "Start a new group in collapsed mode. Subsequent output events are members of the group and should be shown indented (as soon as the group is expanded).\nThe 'output' attribute becomes the name of the group and is not indented.", + "End the current group and decreases the indentation of subsequent output events.\nA non empty 'output' attribute is shown as the unindented end of the group." + ] + }, + "variablesReference": { + "type": "integer", + "description": "If an attribute 'variablesReference' exists and its value is > 0, the output contains objects which can be retrieved by passing 'variablesReference' to the 'variables' request. The value should be less than or equal to 2147483647 (2^31-1)." + }, + "source": { + "description": "An optional source location where the output was produced.", + "type": "Source" + }, + "line": { + "type": "integer", + "description": "An optional source location line where the output was produced." + }, + "column": { + "type": "integer", + "description": "An optional source location column where the output was produced." + }, + "data": { + "type": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ], + "description": "Optional data to report. For the 'telemetry' category the data will be sent to telemetry, for the other categories the data is shown in JSON format." + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, output, category=None, group=None, variablesReference=None, source=None, line=None, column=None, data=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string output: The output to report. + :param string category: The output category. If not specified or if the category is not understand by the client, 'console' is assumed. + :param string group: Support for keeping an output log organized by grouping related messages. + :param integer variablesReference: If an attribute 'variablesReference' exists and its value is > 0, the output contains objects which can be retrieved by passing 'variablesReference' to the 'variables' request. The value should be less than or equal to 2147483647 (2^31-1). + :param Source source: An optional source location where the output was produced. + :param integer line: An optional source location line where the output was produced. + :param integer column: An optional source location column where the output was produced. + :param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] data: Optional data to report. For the 'telemetry' category the data will be sent to telemetry, for the other categories the data is shown in JSON format. + """ + self.output = output + self.category = category + self.group = group + self.variablesReference = variablesReference + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.line = line + self.column = column + self.data = data + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + output = self.output + category = self.category + group = self.group + variablesReference = self.variablesReference + source = self.source + line = self.line + column = self.column + data = self.data + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'output': output, + } + if category is not None: + dct['category'] = category + if group is not None: + dct['group'] = group + if variablesReference is not None: + dct['variablesReference'] = variablesReference + if source is not None: + dct['source'] = source.to_dict(update_ids_to_dap=update_ids_to_dap) + if line is not None: + dct['line'] = line + if column is not None: + dct['column'] = column + if data is not None: + dct['data'] = data + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register +class BreakpointEventBody(BaseSchema): + """ + "body" of BreakpointEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "reason": { + "type": "string", + "description": "The reason for the event.", + "_enum": [ + "changed", + "new", + "removed" + ] + }, + "breakpoint": { + "description": "The 'id' attribute is used to find the target breakpoint and the other attributes are used as the new values.", + "type": "Breakpoint" + } + } + __refs__ = set(['breakpoint']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, reason, breakpoint, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string reason: The reason for the event. + :param Breakpoint breakpoint: The 'id' attribute is used to find the target breakpoint and the other attributes are used as the new values. + """ + self.reason = reason + if breakpoint is None: + self.breakpoint = Breakpoint() + else: + self.breakpoint = Breakpoint(update_ids_from_dap=update_ids_from_dap, **breakpoint) if breakpoint.__class__ != Breakpoint else breakpoint + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + reason = self.reason + breakpoint = self.breakpoint # noqa (assign to builtin) + dct = { + 'reason': reason, + 'breakpoint': breakpoint.to_dict(update_ids_to_dap=update_ids_to_dap), + } + dct.update(self.kwargs) + return dct + + +@register +class ModuleEventBody(BaseSchema): + """ + "body" of ModuleEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "reason": { + "type": "string", + "description": "The reason for the event.", + "enum": [ + "new", + "changed", + "removed" + ] + }, + "module": { + "description": "The new, changed, or removed module. In case of 'removed' only the module id is used.", + "type": "Module" + } + } + __refs__ = set(['module']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, reason, module, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string reason: The reason for the event. + :param Module module: The new, changed, or removed module. In case of 'removed' only the module id is used. + """ + self.reason = reason + if module is None: + self.module = Module() + else: + self.module = Module(update_ids_from_dap=update_ids_from_dap, **module) if module.__class__ != Module else module + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + reason = self.reason + module = self.module + dct = { + 'reason': reason, + 'module': module.to_dict(update_ids_to_dap=update_ids_to_dap), + } + dct.update(self.kwargs) + return dct + + +@register +class LoadedSourceEventBody(BaseSchema): + """ + "body" of LoadedSourceEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "reason": { + "type": "string", + "description": "The reason for the event.", + "enum": [ + "new", + "changed", + "removed" + ] + }, + "source": { + "description": "The new, changed, or removed source.", + "type": "Source" + } + } + __refs__ = set(['source']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, reason, source, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string reason: The reason for the event. + :param Source source: The new, changed, or removed source. + """ + self.reason = reason + if source is None: + self.source = Source() + else: + self.source = Source(update_ids_from_dap=update_ids_from_dap, **source) if source.__class__ != Source else source + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + reason = self.reason + source = self.source + dct = { + 'reason': reason, + 'source': source.to_dict(update_ids_to_dap=update_ids_to_dap), + } + dct.update(self.kwargs) + return dct + + +@register +class ProcessEventBody(BaseSchema): + """ + "body" of ProcessEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "name": { + "type": "string", + "description": "The logical name of the process. This is usually the full path to process's executable file. Example: /home/example/myproj/program.js." + }, + "systemProcessId": { + "type": "integer", + "description": "The system process id of the debugged process. This property will be missing for non-system processes." + }, + "isLocalProcess": { + "type": "boolean", + "description": "If true, the process is running on the same computer as the debug adapter." + }, + "startMethod": { + "type": "string", + "enum": [ + "launch", + "attach", + "attachForSuspendedLaunch" + ], + "description": "Describes how the debug engine started debugging this process.", + "enumDescriptions": [ + "Process was launched under the debugger.", + "Debugger attached to an existing process.", + "A project launcher component has launched a new process in a suspended state and then asked the debugger to attach." + ] + }, + "pointerSize": { + "type": "integer", + "description": "The size of a pointer or address for this process, in bits. This value may be used by clients when formatting addresses for display." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, name, systemProcessId=None, isLocalProcess=None, startMethod=None, pointerSize=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string name: The logical name of the process. This is usually the full path to process's executable file. Example: /home/example/myproj/program.js. + :param integer systemProcessId: The system process id of the debugged process. This property will be missing for non-system processes. + :param boolean isLocalProcess: If true, the process is running on the same computer as the debug adapter. + :param string startMethod: Describes how the debug engine started debugging this process. + :param integer pointerSize: The size of a pointer or address for this process, in bits. This value may be used by clients when formatting addresses for display. + """ + self.name = name + self.systemProcessId = systemProcessId + self.isLocalProcess = isLocalProcess + self.startMethod = startMethod + self.pointerSize = pointerSize + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + name = self.name + systemProcessId = self.systemProcessId + isLocalProcess = self.isLocalProcess + startMethod = self.startMethod + pointerSize = self.pointerSize + dct = { + 'name': name, + } + if systemProcessId is not None: + dct['systemProcessId'] = systemProcessId + if isLocalProcess is not None: + dct['isLocalProcess'] = isLocalProcess + if startMethod is not None: + dct['startMethod'] = startMethod + if pointerSize is not None: + dct['pointerSize'] = pointerSize + dct.update(self.kwargs) + return dct + + +@register +class CapabilitiesEventBody(BaseSchema): + """ + "body" of CapabilitiesEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "capabilities": { + "description": "The set of updated capabilities.", + "type": "Capabilities" + } + } + __refs__ = set(['capabilities']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, capabilities, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param Capabilities capabilities: The set of updated capabilities. + """ + if capabilities is None: + self.capabilities = Capabilities() + else: + self.capabilities = Capabilities(update_ids_from_dap=update_ids_from_dap, **capabilities) if capabilities.__class__ != Capabilities else capabilities + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + capabilities = self.capabilities + dct = { + 'capabilities': capabilities.to_dict(update_ids_to_dap=update_ids_to_dap), + } + dct.update(self.kwargs) + return dct + + +@register +class ProgressStartEventBody(BaseSchema): + """ + "body" of ProgressStartEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "progressId": { + "type": "string", + "description": "An ID that must be used in subsequent 'progressUpdate' and 'progressEnd' events to make them refer to the same progress reporting.\nIDs must be unique within a debug session." + }, + "title": { + "type": "string", + "description": "Mandatory (short) title of the progress reporting. Shown in the UI to describe the long running operation." + }, + "requestId": { + "type": "integer", + "description": "The request ID that this progress report is related to. If specified a debug adapter is expected to emit\nprogress events for the long running request until the request has been either completed or cancelled.\nIf the request ID is omitted, the progress report is assumed to be related to some general activity of the debug adapter." + }, + "cancellable": { + "type": "boolean", + "description": "If true, the request that reports progress may be canceled with a 'cancel' request.\nSo this property basically controls whether the client should use UX that supports cancellation.\nClients that don't support cancellation are allowed to ignore the setting." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message." + }, + "percentage": { + "type": "number", + "description": "Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, progressId, title, requestId=None, cancellable=None, message=None, percentage=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string progressId: An ID that must be used in subsequent 'progressUpdate' and 'progressEnd' events to make them refer to the same progress reporting. + IDs must be unique within a debug session. + :param string title: Mandatory (short) title of the progress reporting. Shown in the UI to describe the long running operation. + :param integer requestId: The request ID that this progress report is related to. If specified a debug adapter is expected to emit + progress events for the long running request until the request has been either completed or cancelled. + If the request ID is omitted, the progress report is assumed to be related to some general activity of the debug adapter. + :param boolean cancellable: If true, the request that reports progress may be canceled with a 'cancel' request. + So this property basically controls whether the client should use UX that supports cancellation. + Clients that don't support cancellation are allowed to ignore the setting. + :param string message: Optional, more detailed progress message. + :param number percentage: Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown. + """ + self.progressId = progressId + self.title = title + self.requestId = requestId + self.cancellable = cancellable + self.message = message + self.percentage = percentage + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + progressId = self.progressId + title = self.title + requestId = self.requestId + cancellable = self.cancellable + message = self.message + percentage = self.percentage + dct = { + 'progressId': progressId, + 'title': title, + } + if requestId is not None: + dct['requestId'] = requestId + if cancellable is not None: + dct['cancellable'] = cancellable + if message is not None: + dct['message'] = message + if percentage is not None: + dct['percentage'] = percentage + dct.update(self.kwargs) + return dct + + +@register +class ProgressUpdateEventBody(BaseSchema): + """ + "body" of ProgressUpdateEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "progressId": { + "type": "string", + "description": "The ID that was introduced in the initial 'progressStart' event." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message. If omitted, the previous message (if any) is used." + }, + "percentage": { + "type": "number", + "description": "Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, progressId, message=None, percentage=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string progressId: The ID that was introduced in the initial 'progressStart' event. + :param string message: Optional, more detailed progress message. If omitted, the previous message (if any) is used. + :param number percentage: Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown. + """ + self.progressId = progressId + self.message = message + self.percentage = percentage + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + progressId = self.progressId + message = self.message + percentage = self.percentage + dct = { + 'progressId': progressId, + } + if message is not None: + dct['message'] = message + if percentage is not None: + dct['percentage'] = percentage + dct.update(self.kwargs) + return dct + + +@register +class ProgressEndEventBody(BaseSchema): + """ + "body" of ProgressEndEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "progressId": { + "type": "string", + "description": "The ID that was introduced in the initial 'ProgressStartEvent'." + }, + "message": { + "type": "string", + "description": "Optional, more detailed progress message. If omitted, the previous message (if any) is used." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, progressId, message=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string progressId: The ID that was introduced in the initial 'ProgressStartEvent'. + :param string message: Optional, more detailed progress message. If omitted, the previous message (if any) is used. + """ + self.progressId = progressId + self.message = message + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + progressId = self.progressId + message = self.message + dct = { + 'progressId': progressId, + } + if message is not None: + dct['message'] = message + dct.update(self.kwargs) + return dct + + +@register +class InvalidatedEventBody(BaseSchema): + """ + "body" of InvalidatedEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "areas": { + "type": "array", + "description": "Optional set of logical areas that got invalidated. This property has a hint characteristic: a client can only be expected to make a 'best effort' in honouring the areas but there are no guarantees. If this property is missing, empty, or if values are not understand the client should assume a single value 'all'.", + "items": { + "$ref": "#/definitions/InvalidatedAreas" + } + }, + "threadId": { + "type": "integer", + "description": "If specified, the client only needs to refetch data related to this thread." + }, + "stackFrameId": { + "type": "integer", + "description": "If specified, the client only needs to refetch data related to this stack frame (and the 'threadId' is ignored)." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, areas=None, threadId=None, stackFrameId=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array areas: Optional set of logical areas that got invalidated. This property has a hint characteristic: a client can only be expected to make a 'best effort' in honouring the areas but there are no guarantees. If this property is missing, empty, or if values are not understand the client should assume a single value 'all'. + :param integer threadId: If specified, the client only needs to refetch data related to this thread. + :param integer stackFrameId: If specified, the client only needs to refetch data related to this stack frame (and the 'threadId' is ignored). + """ + self.areas = areas + if update_ids_from_dap and self.areas: + for o in self.areas: + InvalidatedAreas.update_dict_ids_from_dap(o) + self.threadId = threadId + self.stackFrameId = stackFrameId + if update_ids_from_dap: + self.threadId = self._translate_id_from_dap(self.threadId) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_from_dap(dct['threadId']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + areas = self.areas + if areas and hasattr(areas[0], "to_dict"): + areas = [x.to_dict() for x in areas] + threadId = self.threadId + stackFrameId = self.stackFrameId + if update_ids_to_dap: + if threadId is not None: + threadId = self._translate_id_to_dap(threadId) + dct = { + } + if areas is not None: + dct['areas'] = [InvalidatedAreas.update_dict_ids_to_dap(o) for o in areas] if (update_ids_to_dap and areas) else areas + if threadId is not None: + dct['threadId'] = threadId + if stackFrameId is not None: + dct['stackFrameId'] = stackFrameId + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'threadId' in dct: + dct['threadId'] = cls._translate_id_to_dap(dct['threadId']) + return dct + + +@register +class MemoryEventBody(BaseSchema): + """ + "body" of MemoryEvent + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "memoryReference": { + "type": "string", + "description": "Memory reference of a memory range that has been updated." + }, + "offset": { + "type": "integer", + "description": "Starting offset in bytes where memory has been updated. Can be negative." + }, + "count": { + "type": "integer", + "description": "Number of bytes updated." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, memoryReference, offset, count, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string memoryReference: Memory reference of a memory range that has been updated. + :param integer offset: Starting offset in bytes where memory has been updated. Can be negative. + :param integer count: Number of bytes updated. + """ + self.memoryReference = memoryReference + self.offset = offset + self.count = count + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + memoryReference = self.memoryReference + offset = self.offset + count = self.count + dct = { + 'memoryReference': memoryReference, + 'offset': offset, + 'count': count, + } + dct.update(self.kwargs) + return dct + + +@register +class RunInTerminalRequestArgumentsEnv(BaseSchema): + """ + "env" of RunInTerminalRequestArguments + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register +class RunInTerminalResponseBody(BaseSchema): + """ + "body" of RunInTerminalResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "processId": { + "type": "integer", + "description": "The process ID. The value should be less than or equal to 2147483647 (2^31-1)." + }, + "shellProcessId": { + "type": "integer", + "description": "The process ID of the terminal shell. The value should be less than or equal to 2147483647 (2^31-1)." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, processId=None, shellProcessId=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer processId: The process ID. The value should be less than or equal to 2147483647 (2^31-1). + :param integer shellProcessId: The process ID of the terminal shell. The value should be less than or equal to 2147483647 (2^31-1). + """ + self.processId = processId + self.shellProcessId = shellProcessId + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + processId = self.processId + shellProcessId = self.shellProcessId + dct = { + } + if processId is not None: + dct['processId'] = processId + if shellProcessId is not None: + dct['shellProcessId'] = shellProcessId + dct.update(self.kwargs) + return dct + + +@register +class BreakpointLocationsResponseBody(BaseSchema): + """ + "body" of BreakpointLocationsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/BreakpointLocation" + }, + "description": "Sorted set of possible breakpoint locations." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: Sorted set of possible breakpoint locations. + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + BreakpointLocation.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + 'breakpoints': [BreakpointLocation.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints, + } + dct.update(self.kwargs) + return dct + + +@register +class SetBreakpointsResponseBody(BaseSchema): + """ + "body" of SetBreakpointsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints.\nThe array elements are in the same order as the elements of the 'breakpoints' (or the deprecated 'lines') array in the arguments." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: Information about the breakpoints. + The array elements are in the same order as the elements of the 'breakpoints' (or the deprecated 'lines') array in the arguments. + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + Breakpoint.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + 'breakpoints': [Breakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints, + } + dct.update(self.kwargs) + return dct + + +@register +class SetFunctionBreakpointsResponseBody(BaseSchema): + """ + "body" of SetFunctionBreakpointsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array. + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + Breakpoint.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + 'breakpoints': [Breakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints, + } + dct.update(self.kwargs) + return dct + + +@register +class SetExceptionBreakpointsResponseBody(BaseSchema): + """ + "body" of SetExceptionBreakpointsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the exception breakpoints or filters.\nThe breakpoints returned are in the same order as the elements of the 'filters', 'filterOptions', 'exceptionOptions' arrays in the arguments. If both 'filters' and 'filterOptions' are given, the returned array must start with 'filters' information first, followed by 'filterOptions' information." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: Information about the exception breakpoints or filters. + The breakpoints returned are in the same order as the elements of the 'filters', 'filterOptions', 'exceptionOptions' arrays in the arguments. If both 'filters' and 'filterOptions' are given, the returned array must start with 'filters' information first, followed by 'filterOptions' information. + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + Breakpoint.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + } + if breakpoints is not None: + dct['breakpoints'] = [Breakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints + dct.update(self.kwargs) + return dct + + +@register +class DataBreakpointInfoResponseBody(BaseSchema): + """ + "body" of DataBreakpointInfoResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "dataId": { + "type": [ + "string", + "null" + ], + "description": "An identifier for the data on which a data breakpoint can be registered with the setDataBreakpoints request or null if no data breakpoint is available." + }, + "description": { + "type": "string", + "description": "UI string that describes on what data the breakpoint is set on or why a data breakpoint is not available." + }, + "accessTypes": { + "type": "array", + "items": { + "$ref": "#/definitions/DataBreakpointAccessType" + }, + "description": "Optional attribute listing the available access types for a potential data breakpoint. A UI frontend could surface this information." + }, + "canPersist": { + "type": "boolean", + "description": "Optional attribute indicating that a potential data breakpoint could be persisted across sessions." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, dataId, description, accessTypes=None, canPersist=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param ['string', 'null'] dataId: An identifier for the data on which a data breakpoint can be registered with the setDataBreakpoints request or null if no data breakpoint is available. + :param string description: UI string that describes on what data the breakpoint is set on or why a data breakpoint is not available. + :param array accessTypes: Optional attribute listing the available access types for a potential data breakpoint. A UI frontend could surface this information. + :param boolean canPersist: Optional attribute indicating that a potential data breakpoint could be persisted across sessions. + """ + self.dataId = dataId + self.description = description + self.accessTypes = accessTypes + if update_ids_from_dap and self.accessTypes: + for o in self.accessTypes: + DataBreakpointAccessType.update_dict_ids_from_dap(o) + self.canPersist = canPersist + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dataId = self.dataId + description = self.description + accessTypes = self.accessTypes + if accessTypes and hasattr(accessTypes[0], "to_dict"): + accessTypes = [x.to_dict() for x in accessTypes] + canPersist = self.canPersist + dct = { + 'dataId': dataId, + 'description': description, + } + if accessTypes is not None: + dct['accessTypes'] = [DataBreakpointAccessType.update_dict_ids_to_dap(o) for o in accessTypes] if (update_ids_to_dap and accessTypes) else accessTypes + if canPersist is not None: + dct['canPersist'] = canPersist + dct.update(self.kwargs) + return dct + + +@register +class SetDataBreakpointsResponseBody(BaseSchema): + """ + "body" of SetDataBreakpointsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the data breakpoints. The array elements correspond to the elements of the input argument 'breakpoints' array." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: Information about the data breakpoints. The array elements correspond to the elements of the input argument 'breakpoints' array. + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + Breakpoint.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + 'breakpoints': [Breakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints, + } + dct.update(self.kwargs) + return dct + + +@register +class SetInstructionBreakpointsResponseBody(BaseSchema): + """ + "body" of SetInstructionBreakpointsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "breakpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/Breakpoint" + }, + "description": "Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, breakpoints, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array breakpoints: Information about the breakpoints. The array elements correspond to the elements of the 'breakpoints' array. + """ + self.breakpoints = breakpoints + if update_ids_from_dap and self.breakpoints: + for o in self.breakpoints: + Breakpoint.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + breakpoints = self.breakpoints + if breakpoints and hasattr(breakpoints[0], "to_dict"): + breakpoints = [x.to_dict() for x in breakpoints] + dct = { + 'breakpoints': [Breakpoint.update_dict_ids_to_dap(o) for o in breakpoints] if (update_ids_to_dap and breakpoints) else breakpoints, + } + dct.update(self.kwargs) + return dct + + +@register +class ContinueResponseBody(BaseSchema): + """ + "body" of ContinueResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "allThreadsContinued": { + "type": "boolean", + "description": "The value true (or a missing property) signals to the client that all threads have been resumed. The value false must be returned if not all threads were resumed." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, allThreadsContinued=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param boolean allThreadsContinued: The value true (or a missing property) signals to the client that all threads have been resumed. The value false must be returned if not all threads were resumed. + """ + self.allThreadsContinued = allThreadsContinued + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + allThreadsContinued = self.allThreadsContinued + dct = { + } + if allThreadsContinued is not None: + dct['allThreadsContinued'] = allThreadsContinued + dct.update(self.kwargs) + return dct + + +@register +class StackTraceResponseBody(BaseSchema): + """ + "body" of StackTraceResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "stackFrames": { + "type": "array", + "items": { + "$ref": "#/definitions/StackFrame" + }, + "description": "The frames of the stackframe. If the array has length zero, there are no stackframes available.\nThis means that there is no location information available." + }, + "totalFrames": { + "type": "integer", + "description": "The total number of frames available in the stack. If omitted or if totalFrames is larger than the available frames, a client is expected to request frames until a request returns less frames than requested (which indicates the end of the stack). Returning monotonically increasing totalFrames values for subsequent requests can be used to enforce paging in the client." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, stackFrames, totalFrames=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array stackFrames: The frames of the stackframe. If the array has length zero, there are no stackframes available. + This means that there is no location information available. + :param integer totalFrames: The total number of frames available in the stack. If omitted or if totalFrames is larger than the available frames, a client is expected to request frames until a request returns less frames than requested (which indicates the end of the stack). Returning monotonically increasing totalFrames values for subsequent requests can be used to enforce paging in the client. + """ + self.stackFrames = stackFrames + if update_ids_from_dap and self.stackFrames: + for o in self.stackFrames: + StackFrame.update_dict_ids_from_dap(o) + self.totalFrames = totalFrames + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + stackFrames = self.stackFrames + if stackFrames and hasattr(stackFrames[0], "to_dict"): + stackFrames = [x.to_dict() for x in stackFrames] + totalFrames = self.totalFrames + dct = { + 'stackFrames': [StackFrame.update_dict_ids_to_dap(o) for o in stackFrames] if (update_ids_to_dap and stackFrames) else stackFrames, + } + if totalFrames is not None: + dct['totalFrames'] = totalFrames + dct.update(self.kwargs) + return dct + + +@register +class ScopesResponseBody(BaseSchema): + """ + "body" of ScopesResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "scopes": { + "type": "array", + "items": { + "$ref": "#/definitions/Scope" + }, + "description": "The scopes of the stackframe. If the array has length zero, there are no scopes available." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, scopes, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array scopes: The scopes of the stackframe. If the array has length zero, there are no scopes available. + """ + self.scopes = scopes + if update_ids_from_dap and self.scopes: + for o in self.scopes: + Scope.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + scopes = self.scopes + if scopes and hasattr(scopes[0], "to_dict"): + scopes = [x.to_dict() for x in scopes] + dct = { + 'scopes': [Scope.update_dict_ids_to_dap(o) for o in scopes] if (update_ids_to_dap and scopes) else scopes, + } + dct.update(self.kwargs) + return dct + + +@register +class VariablesResponseBody(BaseSchema): + """ + "body" of VariablesResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/Variable" + }, + "description": "All (or a range) of variables for the given variable reference." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, variables, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array variables: All (or a range) of variables for the given variable reference. + """ + self.variables = variables + if update_ids_from_dap and self.variables: + for o in self.variables: + Variable.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + variables = self.variables + if variables and hasattr(variables[0], "to_dict"): + variables = [x.to_dict() for x in variables] + dct = { + 'variables': [Variable.update_dict_ids_to_dap(o) for o in variables] if (update_ids_to_dap and variables) else variables, + } + dct.update(self.kwargs) + return dct + + +@register +class SetVariableResponseBody(BaseSchema): + """ + "body" of SetVariableResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "value": { + "type": "string", + "description": "The new value of the variable." + }, + "type": { + "type": "string", + "description": "The type of the new value. Typically shown in the UI when hovering over the value." + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the new value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, value, type=None, variablesReference=None, namedVariables=None, indexedVariables=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string value: The new value of the variable. + :param string type: The type of the new value. Typically shown in the UI when hovering over the value. + :param integer variablesReference: If variablesReference is > 0, the new value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. + The value should be less than or equal to 2147483647 (2^31-1). + :param integer namedVariables: The number of named child variables. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + The value should be less than or equal to 2147483647 (2^31-1). + :param integer indexedVariables: The number of indexed child variables. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + The value should be less than or equal to 2147483647 (2^31-1). + """ + self.value = value + self.type = type + self.variablesReference = variablesReference + self.namedVariables = namedVariables + self.indexedVariables = indexedVariables + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + value = self.value + type = self.type # noqa (assign to builtin) + variablesReference = self.variablesReference + namedVariables = self.namedVariables + indexedVariables = self.indexedVariables + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'value': value, + } + if type is not None: + dct['type'] = type + if variablesReference is not None: + dct['variablesReference'] = variablesReference + if namedVariables is not None: + dct['namedVariables'] = namedVariables + if indexedVariables is not None: + dct['indexedVariables'] = indexedVariables + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register +class SourceResponseBody(BaseSchema): + """ + "body" of SourceResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "content": { + "type": "string", + "description": "Content of the source reference." + }, + "mimeType": { + "type": "string", + "description": "Optional content type (mime type) of the source." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, content, mimeType=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string content: Content of the source reference. + :param string mimeType: Optional content type (mime type) of the source. + """ + self.content = content + self.mimeType = mimeType + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + content = self.content + mimeType = self.mimeType + dct = { + 'content': content, + } + if mimeType is not None: + dct['mimeType'] = mimeType + dct.update(self.kwargs) + return dct + + +@register +class ThreadsResponseBody(BaseSchema): + """ + "body" of ThreadsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "threads": { + "type": "array", + "items": { + "$ref": "#/definitions/Thread" + }, + "description": "All threads." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, threads, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array threads: All threads. + """ + self.threads = threads + if update_ids_from_dap and self.threads: + for o in self.threads: + Thread.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + threads = self.threads + if threads and hasattr(threads[0], "to_dict"): + threads = [x.to_dict() for x in threads] + dct = { + 'threads': [Thread.update_dict_ids_to_dap(o) for o in threads] if (update_ids_to_dap and threads) else threads, + } + dct.update(self.kwargs) + return dct + + +@register +class ModulesResponseBody(BaseSchema): + """ + "body" of ModulesResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "modules": { + "type": "array", + "items": { + "$ref": "#/definitions/Module" + }, + "description": "All modules or range of modules." + }, + "totalModules": { + "type": "integer", + "description": "The total number of modules available." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, modules, totalModules=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array modules: All modules or range of modules. + :param integer totalModules: The total number of modules available. + """ + self.modules = modules + if update_ids_from_dap and self.modules: + for o in self.modules: + Module.update_dict_ids_from_dap(o) + self.totalModules = totalModules + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + modules = self.modules + if modules and hasattr(modules[0], "to_dict"): + modules = [x.to_dict() for x in modules] + totalModules = self.totalModules + dct = { + 'modules': [Module.update_dict_ids_to_dap(o) for o in modules] if (update_ids_to_dap and modules) else modules, + } + if totalModules is not None: + dct['totalModules'] = totalModules + dct.update(self.kwargs) + return dct + + +@register +class LoadedSourcesResponseBody(BaseSchema): + """ + "body" of LoadedSourcesResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "sources": { + "type": "array", + "items": { + "$ref": "#/definitions/Source" + }, + "description": "Set of loaded sources." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, sources, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array sources: Set of loaded sources. + """ + self.sources = sources + if update_ids_from_dap and self.sources: + for o in self.sources: + Source.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + sources = self.sources + if sources and hasattr(sources[0], "to_dict"): + sources = [x.to_dict() for x in sources] + dct = { + 'sources': [Source.update_dict_ids_to_dap(o) for o in sources] if (update_ids_to_dap and sources) else sources, + } + dct.update(self.kwargs) + return dct + + +@register +class EvaluateResponseBody(BaseSchema): + """ + "body" of EvaluateResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "result": { + "type": "string", + "description": "The result of the evaluate request." + }, + "type": { + "type": "string", + "description": "The optional type of the evaluate result.\nThis attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request." + }, + "presentationHint": { + "description": "Properties of a evaluate result that can be used to determine how to render the result in the UI.", + "type": "VariablePresentationHint" + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the evaluate result is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "memoryReference": { + "type": "string", + "description": "Optional memory reference to a location appropriate for this result.\nFor pointer type eval results, this is generally a reference to the memory address contained in the pointer.\nThis attribute should be returned by a debug adapter if the client has passed the value true for the 'supportsMemoryReferences' capability of the 'initialize' request." + } + } + __refs__ = set(['presentationHint']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, result, variablesReference, type=None, presentationHint=None, namedVariables=None, indexedVariables=None, memoryReference=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string result: The result of the evaluate request. + :param integer variablesReference: If variablesReference is > 0, the evaluate result is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. + The value should be less than or equal to 2147483647 (2^31-1). + :param string type: The optional type of the evaluate result. + This attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request. + :param VariablePresentationHint presentationHint: Properties of a evaluate result that can be used to determine how to render the result in the UI. + :param integer namedVariables: The number of named child variables. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + The value should be less than or equal to 2147483647 (2^31-1). + :param integer indexedVariables: The number of indexed child variables. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + The value should be less than or equal to 2147483647 (2^31-1). + :param string memoryReference: Optional memory reference to a location appropriate for this result. + For pointer type eval results, this is generally a reference to the memory address contained in the pointer. + This attribute should be returned by a debug adapter if the client has passed the value true for the 'supportsMemoryReferences' capability of the 'initialize' request. + """ + self.result = result + self.variablesReference = variablesReference + self.type = type + if presentationHint is None: + self.presentationHint = VariablePresentationHint() + else: + self.presentationHint = VariablePresentationHint(update_ids_from_dap=update_ids_from_dap, **presentationHint) if presentationHint.__class__ != VariablePresentationHint else presentationHint + self.namedVariables = namedVariables + self.indexedVariables = indexedVariables + self.memoryReference = memoryReference + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + result = self.result + variablesReference = self.variablesReference + type = self.type # noqa (assign to builtin) + presentationHint = self.presentationHint + namedVariables = self.namedVariables + indexedVariables = self.indexedVariables + memoryReference = self.memoryReference + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'result': result, + 'variablesReference': variablesReference, + } + if type is not None: + dct['type'] = type + if presentationHint is not None: + dct['presentationHint'] = presentationHint.to_dict(update_ids_to_dap=update_ids_to_dap) + if namedVariables is not None: + dct['namedVariables'] = namedVariables + if indexedVariables is not None: + dct['indexedVariables'] = indexedVariables + if memoryReference is not None: + dct['memoryReference'] = memoryReference + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register +class SetExpressionResponseBody(BaseSchema): + """ + "body" of SetExpressionResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "value": { + "type": "string", + "description": "The new value of the expression." + }, + "type": { + "type": "string", + "description": "The optional type of the value.\nThis attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request." + }, + "presentationHint": { + "description": "Properties of a value that can be used to determine how to render the result in the UI.", + "type": "VariablePresentationHint" + }, + "variablesReference": { + "type": "integer", + "description": "If variablesReference is > 0, the value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "namedVariables": { + "type": "integer", + "description": "The number of named child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + }, + "indexedVariables": { + "type": "integer", + "description": "The number of indexed child variables.\nThe client can use this optional information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)." + } + } + __refs__ = set(['presentationHint']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, value, type=None, presentationHint=None, variablesReference=None, namedVariables=None, indexedVariables=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string value: The new value of the expression. + :param string type: The optional type of the value. + This attribute should only be returned by a debug adapter if the client has passed the value true for the 'supportsVariableType' capability of the 'initialize' request. + :param VariablePresentationHint presentationHint: Properties of a value that can be used to determine how to render the result in the UI. + :param integer variablesReference: If variablesReference is > 0, the value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. + The value should be less than or equal to 2147483647 (2^31-1). + :param integer namedVariables: The number of named child variables. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + The value should be less than or equal to 2147483647 (2^31-1). + :param integer indexedVariables: The number of indexed child variables. + The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + The value should be less than or equal to 2147483647 (2^31-1). + """ + self.value = value + self.type = type + if presentationHint is None: + self.presentationHint = VariablePresentationHint() + else: + self.presentationHint = VariablePresentationHint(update_ids_from_dap=update_ids_from_dap, **presentationHint) if presentationHint.__class__ != VariablePresentationHint else presentationHint + self.variablesReference = variablesReference + self.namedVariables = namedVariables + self.indexedVariables = indexedVariables + if update_ids_from_dap: + self.variablesReference = self._translate_id_from_dap(self.variablesReference) + self.kwargs = kwargs + + + @classmethod + def update_dict_ids_from_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_from_dap(dct['variablesReference']) + return dct + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + value = self.value + type = self.type # noqa (assign to builtin) + presentationHint = self.presentationHint + variablesReference = self.variablesReference + namedVariables = self.namedVariables + indexedVariables = self.indexedVariables + if update_ids_to_dap: + if variablesReference is not None: + variablesReference = self._translate_id_to_dap(variablesReference) + dct = { + 'value': value, + } + if type is not None: + dct['type'] = type + if presentationHint is not None: + dct['presentationHint'] = presentationHint.to_dict(update_ids_to_dap=update_ids_to_dap) + if variablesReference is not None: + dct['variablesReference'] = variablesReference + if namedVariables is not None: + dct['namedVariables'] = namedVariables + if indexedVariables is not None: + dct['indexedVariables'] = indexedVariables + dct.update(self.kwargs) + return dct + + @classmethod + def update_dict_ids_to_dap(cls, dct): + if 'variablesReference' in dct: + dct['variablesReference'] = cls._translate_id_to_dap(dct['variablesReference']) + return dct + + +@register +class StepInTargetsResponseBody(BaseSchema): + """ + "body" of StepInTargetsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/StepInTarget" + }, + "description": "The possible stepIn targets of the specified source location." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, targets, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array targets: The possible stepIn targets of the specified source location. + """ + self.targets = targets + if update_ids_from_dap and self.targets: + for o in self.targets: + StepInTarget.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + targets = self.targets + if targets and hasattr(targets[0], "to_dict"): + targets = [x.to_dict() for x in targets] + dct = { + 'targets': [StepInTarget.update_dict_ids_to_dap(o) for o in targets] if (update_ids_to_dap and targets) else targets, + } + dct.update(self.kwargs) + return dct + + +@register +class GotoTargetsResponseBody(BaseSchema): + """ + "body" of GotoTargetsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/GotoTarget" + }, + "description": "The possible goto targets of the specified location." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, targets, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array targets: The possible goto targets of the specified location. + """ + self.targets = targets + if update_ids_from_dap and self.targets: + for o in self.targets: + GotoTarget.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + targets = self.targets + if targets and hasattr(targets[0], "to_dict"): + targets = [x.to_dict() for x in targets] + dct = { + 'targets': [GotoTarget.update_dict_ids_to_dap(o) for o in targets] if (update_ids_to_dap and targets) else targets, + } + dct.update(self.kwargs) + return dct + + +@register +class CompletionsResponseBody(BaseSchema): + """ + "body" of CompletionsResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "targets": { + "type": "array", + "items": { + "$ref": "#/definitions/CompletionItem" + }, + "description": "The possible completions for ." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, targets, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array targets: The possible completions for . + """ + self.targets = targets + if update_ids_from_dap and self.targets: + for o in self.targets: + CompletionItem.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + targets = self.targets + if targets and hasattr(targets[0], "to_dict"): + targets = [x.to_dict() for x in targets] + dct = { + 'targets': [CompletionItem.update_dict_ids_to_dap(o) for o in targets] if (update_ids_to_dap and targets) else targets, + } + dct.update(self.kwargs) + return dct + + +@register +class ExceptionInfoResponseBody(BaseSchema): + """ + "body" of ExceptionInfoResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "exceptionId": { + "type": "string", + "description": "ID of the exception that was thrown." + }, + "description": { + "type": "string", + "description": "Descriptive text for the exception provided by the debug adapter." + }, + "breakMode": { + "description": "Mode that caused the exception notification to be raised.", + "type": "ExceptionBreakMode" + }, + "details": { + "description": "Detailed information about the exception.", + "type": "ExceptionDetails" + } + } + __refs__ = set(['breakMode', 'details']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, exceptionId, breakMode, description=None, details=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string exceptionId: ID of the exception that was thrown. + :param ExceptionBreakMode breakMode: Mode that caused the exception notification to be raised. + :param string description: Descriptive text for the exception provided by the debug adapter. + :param ExceptionDetails details: Detailed information about the exception. + """ + self.exceptionId = exceptionId + if breakMode is not None: + assert breakMode in ExceptionBreakMode.VALID_VALUES + self.breakMode = breakMode + self.description = description + if details is None: + self.details = ExceptionDetails() + else: + self.details = ExceptionDetails(update_ids_from_dap=update_ids_from_dap, **details) if details.__class__ != ExceptionDetails else details + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + exceptionId = self.exceptionId + breakMode = self.breakMode + description = self.description + details = self.details + dct = { + 'exceptionId': exceptionId, + 'breakMode': breakMode, + } + if description is not None: + dct['description'] = description + if details is not None: + dct['details'] = details.to_dict(update_ids_to_dap=update_ids_to_dap) + dct.update(self.kwargs) + return dct + + +@register +class ReadMemoryResponseBody(BaseSchema): + """ + "body" of ReadMemoryResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "address": { + "type": "string", + "description": "The address of the first byte of data returned.\nTreated as a hex value if prefixed with '0x', or as a decimal value otherwise." + }, + "unreadableBytes": { + "type": "integer", + "description": "The number of unreadable bytes encountered after the last successfully read byte.\nThis can be used to determine the number of bytes that must be skipped before a subsequent 'readMemory' request will succeed." + }, + "data": { + "type": "string", + "description": "The bytes read from memory, encoded using base64." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, address, unreadableBytes=None, data=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string address: The address of the first byte of data returned. + Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. + :param integer unreadableBytes: The number of unreadable bytes encountered after the last successfully read byte. + This can be used to determine the number of bytes that must be skipped before a subsequent 'readMemory' request will succeed. + :param string data: The bytes read from memory, encoded using base64. + """ + self.address = address + self.unreadableBytes = unreadableBytes + self.data = data + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + address = self.address + unreadableBytes = self.unreadableBytes + data = self.data + dct = { + 'address': address, + } + if unreadableBytes is not None: + dct['unreadableBytes'] = unreadableBytes + if data is not None: + dct['data'] = data + dct.update(self.kwargs) + return dct + + +@register +class WriteMemoryResponseBody(BaseSchema): + """ + "body" of WriteMemoryResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "offset": { + "type": "integer", + "description": "Optional property that should be returned when 'allowPartial' is true to indicate the offset of the first byte of data successfully written. Can be negative." + }, + "bytesWritten": { + "type": "integer", + "description": "Optional property that should be returned when 'allowPartial' is true to indicate the number of bytes starting from address that were successfully written." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, offset=None, bytesWritten=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param integer offset: Optional property that should be returned when 'allowPartial' is true to indicate the offset of the first byte of data successfully written. Can be negative. + :param integer bytesWritten: Optional property that should be returned when 'allowPartial' is true to indicate the number of bytes starting from address that were successfully written. + """ + self.offset = offset + self.bytesWritten = bytesWritten + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + offset = self.offset + bytesWritten = self.bytesWritten + dct = { + } + if offset is not None: + dct['offset'] = offset + if bytesWritten is not None: + dct['bytesWritten'] = bytesWritten + dct.update(self.kwargs) + return dct + + +@register +class DisassembleResponseBody(BaseSchema): + """ + "body" of DisassembleResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "instructions": { + "type": "array", + "items": { + "$ref": "#/definitions/DisassembledInstruction" + }, + "description": "The list of disassembled instructions." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, instructions, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param array instructions: The list of disassembled instructions. + """ + self.instructions = instructions + if update_ids_from_dap and self.instructions: + for o in self.instructions: + DisassembledInstruction.update_dict_ids_from_dap(o) + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + instructions = self.instructions + if instructions and hasattr(instructions[0], "to_dict"): + instructions = [x.to_dict() for x in instructions] + dct = { + 'instructions': [DisassembledInstruction.update_dict_ids_to_dap(o) for o in instructions] if (update_ids_to_dap and instructions) else instructions, + } + dct.update(self.kwargs) + return dct + + +@register +class MessageVariables(BaseSchema): + """ + "variables" of Message + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = {} + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + + """ + + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + dct = { + } + dct.update(self.kwargs) + return dct + + +@register +class PydevdSystemInfoResponseBody(BaseSchema): + """ + "body" of PydevdSystemInfoResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "python": { + "description": "Information about the python version running in the current process.", + "type": "PydevdPythonInfo" + }, + "platform": { + "description": "Information about the plarforn on which the current process is running.", + "type": "PydevdPlatformInfo" + }, + "process": { + "description": "Information about the current process.", + "type": "PydevdProcessInfo" + }, + "pydevd": { + "description": "Information about pydevd.", + "type": "PydevdInfo" + } + } + __refs__ = set(['python', 'platform', 'process', 'pydevd']) + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, python, platform, process, pydevd, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param PydevdPythonInfo python: Information about the python version running in the current process. + :param PydevdPlatformInfo platform: Information about the plarforn on which the current process is running. + :param PydevdProcessInfo process: Information about the current process. + :param PydevdInfo pydevd: Information about pydevd. + """ + if python is None: + self.python = PydevdPythonInfo() + else: + self.python = PydevdPythonInfo(update_ids_from_dap=update_ids_from_dap, **python) if python.__class__ != PydevdPythonInfo else python + if platform is None: + self.platform = PydevdPlatformInfo() + else: + self.platform = PydevdPlatformInfo(update_ids_from_dap=update_ids_from_dap, **platform) if platform.__class__ != PydevdPlatformInfo else platform + if process is None: + self.process = PydevdProcessInfo() + else: + self.process = PydevdProcessInfo(update_ids_from_dap=update_ids_from_dap, **process) if process.__class__ != PydevdProcessInfo else process + if pydevd is None: + self.pydevd = PydevdInfo() + else: + self.pydevd = PydevdInfo(update_ids_from_dap=update_ids_from_dap, **pydevd) if pydevd.__class__ != PydevdInfo else pydevd + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + python = self.python + platform = self.platform + process = self.process + pydevd = self.pydevd + dct = { + 'python': python.to_dict(update_ids_to_dap=update_ids_to_dap), + 'platform': platform.to_dict(update_ids_to_dap=update_ids_to_dap), + 'process': process.to_dict(update_ids_to_dap=update_ids_to_dap), + 'pydevd': pydevd.to_dict(update_ids_to_dap=update_ids_to_dap), + } + dct.update(self.kwargs) + return dct + + +@register +class PydevdAuthorizeResponseBody(BaseSchema): + """ + "body" of PydevdAuthorizeResponse + + Note: automatically generated code. Do not edit manually. + """ + + __props__ = { + "clientAccessToken": { + "type": "string", + "description": "The access token to access the client (i.e.: usually the IDE)." + } + } + __refs__ = set() + + __slots__ = list(__props__.keys()) + ['kwargs'] + + def __init__(self, clientAccessToken, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused) + """ + :param string clientAccessToken: The access token to access the client (i.e.: usually the IDE). + """ + self.clientAccessToken = clientAccessToken + self.kwargs = kwargs + + + def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused) + clientAccessToken = self.clientAccessToken + dct = { + 'clientAccessToken': clientAccessToken, + } + dct.update(self.kwargs) + return dct diff --git a/_pydevd_bundle/_debug_adapter/pydevd_schema_log.py b/_pydevd_bundle/_debug_adapter/pydevd_schema_log.py new file mode 100644 index 0000000..28b7292 --- /dev/null +++ b/_pydevd_bundle/_debug_adapter/pydevd_schema_log.py @@ -0,0 +1,46 @@ +import os +import traceback +from _pydevd_bundle.pydevd_constants import ForkSafeLock + +_pid = os.getpid() +_pid_msg = '%s: ' % (_pid,) + +_debug_lock = ForkSafeLock() + +DEBUG = False +DEBUG_FILE = os.path.join(os.path.dirname(__file__), '__debug_output__.txt') + + +def debug(msg): + if DEBUG: + with _debug_lock: + _pid_prefix = _pid_msg + if isinstance(msg, bytes): + _pid_prefix = _pid_prefix.encode('utf-8') + + if not msg.endswith(b'\r') and not msg.endswith(b'\n'): + msg += b'\n' + mode = 'a+b' + else: + if not msg.endswith('\r') and not msg.endswith('\n'): + msg += '\n' + mode = 'a+' + with open(DEBUG_FILE, mode) as stream: + stream.write(_pid_prefix) + stream.write(msg) + + +def debug_exception(msg=None): + if DEBUG: + if msg: + debug(msg) + + with _debug_lock: + + with open(DEBUG_FILE, 'a+') as stream: + _pid_prefix = _pid_msg + if isinstance(msg, bytes): + _pid_prefix = _pid_prefix.encode('utf-8') + stream.write(_pid_prefix) + + traceback.print_exc(file=stream) diff --git a/_pydevd_bundle/pydevconsole_code.py b/_pydevd_bundle/pydevconsole_code.py new file mode 100644 index 0000000..e6ba300 --- /dev/null +++ b/_pydevd_bundle/pydevconsole_code.py @@ -0,0 +1,554 @@ +""" +A copy of the code module in the standard library with some changes to work with +async evaluation. + +Utilities needed to emulate Python's interactive interpreter. +""" + +# Inspired by similar code by Jeff Epler and Fredrik Lundh. + +import sys +import traceback +import inspect + +# START --------------------------- from codeop import CommandCompiler, compile_command +# START --------------------------- from codeop import CommandCompiler, compile_command +# START --------------------------- from codeop import CommandCompiler, compile_command +# START --------------------------- from codeop import CommandCompiler, compile_command +# START --------------------------- from codeop import CommandCompiler, compile_command +r"""Utilities to compile possibly incomplete Python source code. + +This module provides two interfaces, broadly similar to the builtin +function compile(), which take program text, a filename and a 'mode' +and: + +- Return code object if the command is complete and valid +- Return None if the command is incomplete +- Raise SyntaxError, ValueError or OverflowError if the command is a + syntax error (OverflowError and ValueError can be produced by + malformed literals). + +Approach: + +First, check if the source consists entirely of blank lines and +comments; if so, replace it with 'pass', because the built-in +parser doesn't always do the right thing for these. + +Compile three times: as is, with \n, and with \n\n appended. If it +compiles as is, it's complete. If it compiles with one \n appended, +we expect more. If it doesn't compile either way, we compare the +error we get when compiling with \n or \n\n appended. If the errors +are the same, the code is broken. But if the errors are different, we +expect more. Not intuitive; not even guaranteed to hold in future +releases; but this matches the compiler's behavior from Python 1.4 +through 2.2, at least. + +Caveat: + +It is possible (but not likely) that the parser stops parsing with a +successful outcome before reaching the end of the source; in this +case, trailing symbols may be ignored instead of causing an error. +For example, a backslash followed by two newlines may be followed by +arbitrary garbage. This will be fixed once the API for the parser is +better. + +The two interfaces are: + +compile_command(source, filename, symbol): + + Compiles a single command in the manner described above. + +CommandCompiler(): + + Instances of this class have __call__ methods identical in + signature to compile_command; the difference is that if the + instance compiles program text containing a __future__ statement, + the instance 'remembers' and compiles all subsequent program texts + with the statement in force. + +The module also provides another class: + +Compile(): + + Instances of this class act like the built-in function compile, + but with 'memory' in the sense described above. +""" + +import __future__ + +_features = [getattr(__future__, fname) + for fname in __future__.all_feature_names] + +__all__ = ["compile_command", "Compile", "CommandCompiler"] + +PyCF_DONT_IMPLY_DEDENT = 0x200 # Matches pythonrun.h + + +def _maybe_compile(compiler, source, filename, symbol): + # Check for source consisting of only blank lines and comments + for line in source.split("\n"): + line = line.strip() + if line and line[0] != '#': + break # Leave it alone + else: + if symbol != "eval": + source = "pass" # Replace it with a 'pass' statement + + err = err1 = err2 = None + code = code1 = code2 = None + + try: + code = compiler(source, filename, symbol) + except SyntaxError as err: + pass + + try: + code1 = compiler(source + "\n", filename, symbol) + except SyntaxError as e: + err1 = e + + try: + code2 = compiler(source + "\n\n", filename, symbol) + except SyntaxError as e: + err2 = e + + try: + if code: + return code + if not code1 and repr(err1) == repr(err2): + raise err1 + finally: + err1 = err2 = None + + +def _compile(source, filename, symbol): + return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT) + + +def compile_command(source, filename="", symbol="single"): + r"""Compile a command and determine whether it is incomplete. + + Arguments: + + source -- the source string; may contain \n characters + filename -- optional filename from which source was read; default + "" + symbol -- optional grammar start symbol; "single" (default) or "eval" + + Return value / exceptions raised: + + - Return a code object if the command is complete and valid + - Return None if the command is incomplete + - Raise SyntaxError, ValueError or OverflowError if the command is a + syntax error (OverflowError and ValueError can be produced by + malformed literals). + """ + return _maybe_compile(_compile, source, filename, symbol) + + +class Compile: + """Instances of this class behave much like the built-in compile + function, but if one is used to compile text containing a future + statement, it "remembers" and compiles all subsequent program texts + with the statement in force.""" + + def __init__(self): + self.flags = PyCF_DONT_IMPLY_DEDENT + + try: + from ast import PyCF_ALLOW_TOP_LEVEL_AWAIT + self.flags |= PyCF_ALLOW_TOP_LEVEL_AWAIT + except: + pass + + def __call__(self, source, filename, symbol): + codeob = compile(source, filename, symbol, self.flags, 1) + for feature in _features: + if codeob.co_flags & feature.compiler_flag: + self.flags |= feature.compiler_flag + return codeob + + +class CommandCompiler: + """Instances of this class have __call__ methods identical in + signature to compile_command; the difference is that if the + instance compiles program text containing a __future__ statement, + the instance 'remembers' and compiles all subsequent program texts + with the statement in force.""" + + def __init__(self,): + self.compiler = Compile() + + def __call__(self, source, filename="", symbol="single"): + r"""Compile a command and determine whether it is incomplete. + + Arguments: + + source -- the source string; may contain \n characters + filename -- optional filename from which source was read; + default "" + symbol -- optional grammar start symbol; "single" (default) or + "eval" + + Return value / exceptions raised: + + - Return a code object if the command is complete and valid + - Return None if the command is incomplete + - Raise SyntaxError, ValueError or OverflowError if the command is a + syntax error (OverflowError and ValueError can be produced by + malformed literals). + """ + return _maybe_compile(self.compiler, source, filename, symbol) + +# END --------------------------- from codeop import CommandCompiler, compile_command +# END --------------------------- from codeop import CommandCompiler, compile_command +# END --------------------------- from codeop import CommandCompiler, compile_command +# END --------------------------- from codeop import CommandCompiler, compile_command +# END --------------------------- from codeop import CommandCompiler, compile_command + + +__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact", + "compile_command"] + +from _pydev_bundle._pydev_saved_modules import threading + + +class _EvalAwaitInNewEventLoop(threading.Thread): + + def __init__(self, compiled, updated_globals, updated_locals): + threading.Thread.__init__(self) + self.daemon = True + self._compiled = compiled + self._updated_globals = updated_globals + self._updated_locals = updated_locals + + # Output + self.evaluated_value = None + self.exc = None + + async def _async_func(self): + return await eval(self._compiled, self._updated_locals, self._updated_globals) + + def run(self): + try: + import asyncio + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + self.evaluated_value = asyncio.run(self._async_func()) + except: + self.exc = sys.exc_info() + + +class InteractiveInterpreter: + """Base class for InteractiveConsole. + + This class deals with parsing and interpreter state (the user's + namespace); it doesn't deal with input buffering or prompting or + input file naming (the filename is always passed in explicitly). + + """ + + def __init__(self, locals=None): + """Constructor. + + The optional 'locals' argument specifies the dictionary in + which code will be executed; it defaults to a newly created + dictionary with key "__name__" set to "__console__" and key + "__doc__" set to None. + + """ + if locals is None: + locals = {"__name__": "__console__", "__doc__": None} + self.locals = locals + self.compile = CommandCompiler() + + def runsource(self, source, filename="", symbol="single"): + """Compile and run some source in the interpreter. + + Arguments are as for compile_command(). + + One of several things can happen: + + 1) The input is incorrect; compile_command() raised an + exception (SyntaxError or OverflowError). A syntax traceback + will be printed by calling the showsyntaxerror() method. + + 2) The input is incomplete, and more input is required; + compile_command() returned None. Nothing happens. + + 3) The input is complete; compile_command() returned a code + object. The code is executed by calling self.runcode() (which + also handles run-time exceptions, except for SystemExit). + + The return value is True in case 2, False in the other cases (unless + an exception is raised). The return value can be used to + decide whether to use sys.ps1 or sys.ps2 to prompt the next + line. + + """ + try: + code = self.compile(source, filename, symbol) + except (OverflowError, SyntaxError, ValueError): + # Case 1 + self.showsyntaxerror(filename) + return False + + if code is None: + # Case 2 + return True + + # Case 3 + self.runcode(code) + return False + + def runcode(self, code): + """Execute a code object. + + When an exception occurs, self.showtraceback() is called to + display a traceback. All exceptions are caught except + SystemExit, which is reraised. + + A note about KeyboardInterrupt: this exception may occur + elsewhere in this code, and may not always be caught. The + caller should be prepared to deal with it. + + """ + try: + is_async = False + if hasattr(inspect, 'CO_COROUTINE'): + is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE + + if is_async: + t = _EvalAwaitInNewEventLoop(code, self.locals, None) + t.start() + t.join() + + if t.exc: + raise t.exc[1].with_traceback(t.exc[2]) + + else: + exec(code, self.locals) + except SystemExit: + raise + except: + self.showtraceback() + + def showsyntaxerror(self, filename=None): + """Display the syntax error that just occurred. + + This doesn't display a stack trace because there isn't one. + + If a filename is given, it is stuffed in the exception instead + of what was there before (because Python's parser always uses + "" when reading from a string). + + The output is written by self.write(), below. + + """ + type, value, tb = sys.exc_info() + sys.last_type = type + sys.last_value = value + sys.last_traceback = tb + if filename and type is SyntaxError: + # Work hard to stuff the correct filename in the exception + try: + msg, (dummy_filename, lineno, offset, line) = value.args + except ValueError: + # Not the format we expect; leave it alone + pass + else: + # Stuff in the right filename + value = SyntaxError(msg, (filename, lineno, offset, line)) + sys.last_value = value + if sys.excepthook is sys.__excepthook__: + lines = traceback.format_exception_only(type, value) + self.write(''.join(lines)) + else: + # If someone has set sys.excepthook, we let that take precedence + # over self.write + sys.excepthook(type, value, tb) + + def showtraceback(self): + """Display the exception that just occurred. + + We remove the first stack item because it is our own code. + + The output is written by self.write(), below. + + """ + sys.last_type, sys.last_value, last_tb = ei = sys.exc_info() + sys.last_traceback = last_tb + try: + lines = traceback.format_exception(ei[0], ei[1], last_tb.tb_next) + if sys.excepthook is sys.__excepthook__: + self.write(''.join(lines)) + else: + # If someone has set sys.excepthook, we let that take precedence + # over self.write + sys.excepthook(ei[0], ei[1], last_tb) + finally: + last_tb = ei = None + + def write(self, data): + """Write a string. + + The base implementation writes to sys.stderr; a subclass may + replace this with a different implementation. + + """ + sys.stderr.write(data) + + +class InteractiveConsole(InteractiveInterpreter): + """Closely emulate the behavior of the interactive Python interpreter. + + This class builds on InteractiveInterpreter and adds prompting + using the familiar sys.ps1 and sys.ps2, and input buffering. + + """ + + def __init__(self, locals=None, filename=""): + """Constructor. + + The optional locals argument will be passed to the + InteractiveInterpreter base class. + + The optional filename argument should specify the (file)name + of the input stream; it will show up in tracebacks. + + """ + InteractiveInterpreter.__init__(self, locals) + self.filename = filename + self.resetbuffer() + + def resetbuffer(self): + """Reset the input buffer.""" + self.buffer = [] + + def interact(self, banner=None, exitmsg=None): + """Closely emulate the interactive Python console. + + The optional banner argument specifies the banner to print + before the first interaction; by default it prints a banner + similar to the one printed by the real Python interpreter, + followed by the current class name in parentheses (so as not + to confuse this with the real interpreter -- since it's so + close!). + + The optional exitmsg argument specifies the exit message + printed when exiting. Pass the empty string to suppress + printing an exit message. If exitmsg is not given or None, + a default message is printed. + + """ + try: + sys.ps1 + except AttributeError: + sys.ps1 = ">>> " + try: + sys.ps2 + except AttributeError: + sys.ps2 = "... " + cprt = 'Type "help", "copyright", "credits" or "license" for more information.' + if banner is None: + self.write("Python %s on %s\n%s\n(%s)\n" % + (sys.version, sys.platform, cprt, + self.__class__.__name__)) + elif banner: + self.write("%s\n" % str(banner)) + more = 0 + while 1: + try: + if more: + prompt = sys.ps2 + else: + prompt = sys.ps1 + try: + line = self.raw_input(prompt) + except EOFError: + self.write("\n") + break + else: + more = self.push(line) + except KeyboardInterrupt: + self.write("\nKeyboardInterrupt\n") + self.resetbuffer() + more = 0 + if exitmsg is None: + self.write('now exiting %s...\n' % self.__class__.__name__) + elif exitmsg != '': + self.write('%s\n' % exitmsg) + + def push(self, line): + """Push a line to the interpreter. + + The line should not have a trailing newline; it may have + internal newlines. The line is appended to a buffer and the + interpreter's runsource() method is called with the + concatenated contents of the buffer as source. If this + indicates that the command was executed or invalid, the buffer + is reset; otherwise, the command is incomplete, and the buffer + is left as it was after the line was appended. The return + value is 1 if more input is required, 0 if the line was dealt + with in some way (this is the same as runsource()). + + """ + self.buffer.append(line) + source = "\n".join(self.buffer) + more = self.runsource(source, self.filename) + if not more: + self.resetbuffer() + return more + + def raw_input(self, prompt=""): + """Write a prompt and read a line. + + The returned line does not include the trailing newline. + When the user enters the EOF key sequence, EOFError is raised. + + The base implementation uses the built-in function + input(); a subclass may replace this with a different + implementation. + + """ + return input(prompt) + + +def interact(banner=None, readfunc=None, local=None, exitmsg=None): + """Closely emulate the interactive Python interpreter. + + This is a backwards compatible interface to the InteractiveConsole + class. When readfunc is not specified, it attempts to import the + readline module to enable GNU readline if it is available. + + Arguments (all optional, all default to None): + + banner -- passed to InteractiveConsole.interact() + readfunc -- if not None, replaces InteractiveConsole.raw_input() + local -- passed to InteractiveInterpreter.__init__() + exitmsg -- passed to InteractiveConsole.interact() + + """ + console = InteractiveConsole(local) + if readfunc is not None: + console.raw_input = readfunc + else: + try: + import readline + except ImportError: + pass + console.interact(banner, exitmsg) + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('-q', action='store_true', + help="don't print version and copyright messages") + args = parser.parse_args() + if args.q or sys.flags.quiet: + banner = '' + else: + banner = None + interact(banner) diff --git a/_pydevd_bundle/pydevd_additional_thread_info.py b/_pydevd_bundle/pydevd_additional_thread_info.py new file mode 100644 index 0000000..5d2fde0 --- /dev/null +++ b/_pydevd_bundle/pydevd_additional_thread_info.py @@ -0,0 +1,19 @@ +# Defines which version of the PyDBAdditionalThreadInfo we'll use. +from _pydevd_bundle.pydevd_constants import ENV_FALSE_LOWER_VALUES, USE_CYTHON_FLAG, \ + ENV_TRUE_LOWER_VALUES + +if USE_CYTHON_FLAG in ENV_TRUE_LOWER_VALUES: + # We must import the cython version if forcing cython + from _pydevd_bundle.pydevd_cython_wrapper import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock # @UnusedImport + +elif USE_CYTHON_FLAG in ENV_FALSE_LOWER_VALUES: + # Use the regular version if not forcing cython + from _pydevd_bundle.pydevd_additional_thread_info_regular import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock # @UnusedImport @Reimport + +else: + # Regular: use fallback if not found (message is already given elsewhere). + try: + from _pydevd_bundle.pydevd_cython_wrapper import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock + except ImportError: + from _pydevd_bundle.pydevd_additional_thread_info_regular import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock # @UnusedImport + diff --git a/_pydevd_bundle/pydevd_additional_thread_info_regular.py b/_pydevd_bundle/pydevd_additional_thread_info_regular.py new file mode 100644 index 0000000..2ed1313 --- /dev/null +++ b/_pydevd_bundle/pydevd_additional_thread_info_regular.py @@ -0,0 +1,153 @@ +from _pydevd_bundle.pydevd_constants import (STATE_RUN, PYTHON_SUSPEND, SUPPORT_GEVENT, ForkSafeLock, + _current_frames) +from _pydev_bundle import pydev_log +# IFDEF CYTHON +# pydev_log.debug("Using Cython speedups") +# ELSE +from _pydevd_bundle.pydevd_frame import PyDBFrame +# ENDIF + +version = 11 + + +#======================================================================================================================= +# PyDBAdditionalThreadInfo +#======================================================================================================================= +# IFDEF CYTHON +# cdef class PyDBAdditionalThreadInfo: +# ELSE +class PyDBAdditionalThreadInfo(object): +# ENDIF + + # Note: the params in cython are declared in pydevd_cython.pxd. + # IFDEF CYTHON + # ELSE + __slots__ = [ + 'pydev_state', + 'pydev_step_stop', + 'pydev_original_step_cmd', + 'pydev_step_cmd', + 'pydev_notify_kill', + 'pydev_django_resolve_frame', + 'pydev_call_from_jinja2', + 'pydev_call_inside_jinja2', + 'is_tracing', + 'conditional_breakpoint_exception', + 'pydev_message', + 'suspend_type', + 'pydev_next_line', + 'pydev_func_name', + 'suspended_at_unhandled', + 'trace_suspend_type', + 'top_level_thread_tracer_no_back_frames', + 'top_level_thread_tracer_unhandled', + 'thread_tracer', + 'step_in_initial_location', + + # Used for CMD_SMART_STEP_INTO (to know which smart step into variant to use) + 'pydev_smart_parent_offset', + 'pydev_smart_child_offset', + + # Used for CMD_SMART_STEP_INTO (list[_pydevd_bundle.pydevd_bytecode_utils.Variant]) + # Filled when the cmd_get_smart_step_into_variants is requested (so, this is a copy + # of the last request for a given thread and pydev_smart_parent_offset/pydev_smart_child_offset relies on it). + 'pydev_smart_step_into_variants', + 'target_id_to_smart_step_into_variant', + + 'pydev_use_scoped_step_frame', + ] + # ENDIF + + def __init__(self): + self.pydev_state = STATE_RUN # STATE_RUN or STATE_SUSPEND + self.pydev_step_stop = None + + # Note: we have `pydev_original_step_cmd` and `pydev_step_cmd` because the original is to + # say the action that started it and the other is to say what's the current tracing behavior + # (because it's possible that we start with a step over but may have to switch to a + # different step strategy -- for instance, if a step over is done and we return the current + # method the strategy is changed to a step in). + + self.pydev_original_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. + self.pydev_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. + + self.pydev_notify_kill = False + self.pydev_django_resolve_frame = False + self.pydev_call_from_jinja2 = None + self.pydev_call_inside_jinja2 = None + self.is_tracing = 0 + self.conditional_breakpoint_exception = None + self.pydev_message = '' + self.suspend_type = PYTHON_SUSPEND + self.pydev_next_line = -1 + self.pydev_func_name = '.invalid.' # Must match the type in cython + self.suspended_at_unhandled = False + self.trace_suspend_type = 'trace' # 'trace' or 'frame_eval' + self.top_level_thread_tracer_no_back_frames = [] + self.top_level_thread_tracer_unhandled = None + self.thread_tracer = None + self.step_in_initial_location = None + self.pydev_smart_parent_offset = -1 + self.pydev_smart_child_offset = -1 + self.pydev_smart_step_into_variants = () + self.target_id_to_smart_step_into_variant = {} + + # Flag to indicate ipython use-case where each line will be executed as a call/line/return + # in a new new frame but in practice we want to consider each new frame as if it was all + # part of the same frame. + # + # In practice this means that a step over shouldn't revert to a step in and we need some + # special logic to know when we should stop in a step over as we need to consider 2 + # different frames as being equal if they're logically the continuation of a frame + # being executed by ipython line by line. + # + # See: https://github.com/microsoft/debugpy/issues/869#issuecomment-1132141003 + self.pydev_use_scoped_step_frame = False + + def get_topmost_frame(self, thread): + ''' + Gets the topmost frame for the given thread. Note that it may be None + and callers should remove the reference to the frame as soon as possible + to avoid disturbing user code. + ''' + # sys._current_frames(): dictionary with thread id -> topmost frame + current_frames = _current_frames() + topmost_frame = current_frames.get(thread.ident) + if topmost_frame is None: + # Note: this is expected for dummy threads (so, getting the topmost frame should be + # treated as optional). + pydev_log.info( + 'Unable to get topmost frame for thread: %s, thread.ident: %s, id(thread): %s\nCurrent frames: %s.\n' + 'GEVENT_SUPPORT: %s', + thread, + thread.ident, + id(thread), + current_frames, + SUPPORT_GEVENT, + ) + + return topmost_frame + + def __str__(self): + return 'State:%s Stop:%s Cmd: %s Kill:%s' % ( + self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill) + + +_set_additional_thread_info_lock = ForkSafeLock() + + +def set_additional_thread_info(thread): + try: + additional_info = thread.additional_info + if additional_info is None: + raise AttributeError() + except: + with _set_additional_thread_info_lock: + # If it's not there, set it within a lock to avoid any racing + # conditions. + additional_info = getattr(thread, 'additional_info', None) + if additional_info is None: + additional_info = PyDBAdditionalThreadInfo() + thread.additional_info = additional_info + + return additional_info diff --git a/_pydevd_bundle/pydevd_api.py b/_pydevd_bundle/pydevd_api.py new file mode 100644 index 0000000..4015152 --- /dev/null +++ b/_pydevd_bundle/pydevd_api.py @@ -0,0 +1,1140 @@ +import sys +import bisect +import types + +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle import pydevd_utils, pydevd_source_mapping +from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info +from _pydevd_bundle.pydevd_comm import (InternalGetThreadStack, internal_get_completions, + InternalSetNextStatementThread, internal_reload_code, + InternalGetVariable, InternalGetArray, InternalLoadFullValue, + internal_get_description, internal_get_frame, internal_evaluate_expression, InternalConsoleExec, + internal_get_variable_json, internal_change_variable, internal_change_variable_json, + internal_evaluate_expression_json, internal_set_expression_json, internal_get_exception_details_json, + internal_step_in_thread, internal_smart_step_into) +from _pydevd_bundle.pydevd_comm_constants import (CMD_THREAD_SUSPEND, file_system_encoding, + CMD_STEP_INTO_MY_CODE, CMD_STOP_ON_START, CMD_SMART_STEP_INTO) +from _pydevd_bundle.pydevd_constants import (get_current_thread_id, set_protocol, get_protocol, + HTTP_JSON_PROTOCOL, JSON_PROTOCOL, DebugInfoHolder, IS_WINDOWS) +from _pydevd_bundle.pydevd_net_command_factory_json import NetCommandFactoryJson +from _pydevd_bundle.pydevd_net_command_factory_xml import NetCommandFactory +import pydevd_file_utils +from _pydev_bundle import pydev_log +from _pydevd_bundle.pydevd_breakpoints import LineBreakpoint +from pydevd_tracing import get_exception_traceback_str +import os +import subprocess +import ctypes +from _pydevd_bundle.pydevd_collect_bytecode_info import code_to_bytecode_representation +import itertools +import linecache +from _pydevd_bundle.pydevd_utils import DAPGrouper +from _pydevd_bundle.pydevd_daemon_thread import run_as_pydevd_daemon_thread +from _pydevd_bundle.pydevd_thread_lifecycle import pydevd_find_thread_by_id, resume_threads +import tokenize + +try: + import dis +except ImportError: + + def _get_code_lines(code): + raise NotImplementedError + +else: + + def _get_code_lines(code): + if not isinstance(code, types.CodeType): + path = code + with tokenize.open(path) as f: + src = f.read() + code = compile(src, path, 'exec', 0, dont_inherit=True) + return _get_code_lines(code) + + def iterate(): + # First, get all line starts for this code object. This does not include + # bodies of nested class and function definitions, as they have their + # own objects. + for _, lineno in dis.findlinestarts(code): + yield lineno + + # For nested class and function definitions, their respective code objects + # are constants referenced by this object. + for const in code.co_consts: + if isinstance(const, types.CodeType) and const.co_filename == code.co_filename: + for lineno in _get_code_lines(const): + yield lineno + + return iterate() + + +class PyDevdAPI(object): + + class VariablePresentation(object): + + def __init__(self, special='group', function='group', class_='group', protected='inline'): + self._presentation = { + DAPGrouper.SCOPE_SPECIAL_VARS: special, + DAPGrouper.SCOPE_FUNCTION_VARS: function, + DAPGrouper.SCOPE_CLASS_VARS: class_, + DAPGrouper.SCOPE_PROTECTED_VARS: protected, + } + + def get_presentation(self, scope): + return self._presentation[scope] + + def run(self, py_db): + py_db.ready_to_run = True + + def notify_initialize(self, py_db): + py_db.on_initialize() + + def notify_configuration_done(self, py_db): + py_db.on_configuration_done() + + def notify_disconnect(self, py_db): + py_db.on_disconnect() + + def set_protocol(self, py_db, seq, protocol): + set_protocol(protocol.strip()) + if get_protocol() in (HTTP_JSON_PROTOCOL, JSON_PROTOCOL): + cmd_factory_class = NetCommandFactoryJson + else: + cmd_factory_class = NetCommandFactory + + if not isinstance(py_db.cmd_factory, cmd_factory_class): + py_db.cmd_factory = cmd_factory_class() + + return py_db.cmd_factory.make_protocol_set_message(seq) + + def set_ide_os_and_breakpoints_by(self, py_db, seq, ide_os, breakpoints_by): + ''' + :param ide_os: 'WINDOWS' or 'UNIX' + :param breakpoints_by: 'ID' or 'LINE' + ''' + if breakpoints_by == 'ID': + py_db._set_breakpoints_with_id = True + else: + py_db._set_breakpoints_with_id = False + + self.set_ide_os(ide_os) + + return py_db.cmd_factory.make_version_message(seq) + + def set_ide_os(self, ide_os): + ''' + :param ide_os: 'WINDOWS' or 'UNIX' + ''' + pydevd_file_utils.set_ide_os(ide_os) + + def set_gui_event_loop(self, py_db, gui_event_loop): + py_db._gui_event_loop = gui_event_loop + + def send_error_message(self, py_db, msg): + cmd = py_db.cmd_factory.make_warning_message('pydevd: %s\n' % (msg,)) + py_db.writer.add_command(cmd) + + def set_show_return_values(self, py_db, show_return_values): + if show_return_values: + py_db.show_return_values = True + else: + if py_db.show_return_values: + # We should remove saved return values + py_db.remove_return_values_flag = True + py_db.show_return_values = False + pydev_log.debug("Show return values: %s", py_db.show_return_values) + + def list_threads(self, py_db, seq): + # Response is the command with the list of threads to be added to the writer thread. + return py_db.cmd_factory.make_list_threads_message(py_db, seq) + + def request_suspend_thread(self, py_db, thread_id='*'): + # Yes, thread suspend is done at this point, not through an internal command. + threads = [] + suspend_all = thread_id.strip() == '*' + if suspend_all: + threads = pydevd_utils.get_non_pydevd_threads() + + elif thread_id.startswith('__frame__:'): + sys.stderr.write("Can't suspend tasklet: %s\n" % (thread_id,)) + + else: + threads = [pydevd_find_thread_by_id(thread_id)] + + for t in threads: + if t is None: + continue + py_db.set_suspend( + t, + CMD_THREAD_SUSPEND, + suspend_other_threads=suspend_all, + is_pause=True, + ) + # Break here (even if it's suspend all) as py_db.set_suspend will + # take care of suspending other threads. + break + + def set_enable_thread_notifications(self, py_db, enable): + ''' + When disabled, no thread notifications (for creation/removal) will be + issued until it's re-enabled. + + Note that when it's re-enabled, a creation notification will be sent for + all existing threads even if it was previously sent (this is meant to + be used on disconnect/reconnect). + ''' + py_db.set_enable_thread_notifications(enable) + + def request_disconnect(self, py_db, resume_threads): + self.set_enable_thread_notifications(py_db, False) + self.remove_all_breakpoints(py_db, '*') + self.remove_all_exception_breakpoints(py_db) + self.notify_disconnect(py_db) + + if resume_threads: + self.request_resume_thread(thread_id='*') + + def request_resume_thread(self, thread_id): + resume_threads(thread_id) + + def request_completions(self, py_db, seq, thread_id, frame_id, act_tok, line=-1, column=-1): + py_db.post_method_as_internal_command( + thread_id, internal_get_completions, seq, thread_id, frame_id, act_tok, line=line, column=column) + + def request_stack(self, py_db, seq, thread_id, fmt=None, timeout=.5, start_frame=0, levels=0): + # If it's already suspended, get it right away. + internal_get_thread_stack = InternalGetThreadStack( + seq, thread_id, py_db, set_additional_thread_info, fmt=fmt, timeout=timeout, start_frame=start_frame, levels=levels) + if internal_get_thread_stack.can_be_executed_by(get_current_thread_id(threading.current_thread())): + internal_get_thread_stack.do_it(py_db) + else: + py_db.post_internal_command(internal_get_thread_stack, '*') + + def request_exception_info_json(self, py_db, request, thread_id, max_frames): + py_db.post_method_as_internal_command( + thread_id, + internal_get_exception_details_json, + request, + thread_id, + max_frames, + set_additional_thread_info=set_additional_thread_info, + iter_visible_frames_info=py_db.cmd_factory._iter_visible_frames_info, + ) + + def request_step(self, py_db, thread_id, step_cmd_id): + t = pydevd_find_thread_by_id(thread_id) + if t: + py_db.post_method_as_internal_command( + thread_id, + internal_step_in_thread, + thread_id, + step_cmd_id, + set_additional_thread_info=set_additional_thread_info, + ) + elif thread_id.startswith('__frame__:'): + sys.stderr.write("Can't make tasklet step command: %s\n" % (thread_id,)) + + def request_smart_step_into(self, py_db, seq, thread_id, offset, child_offset): + t = pydevd_find_thread_by_id(thread_id) + if t: + py_db.post_method_as_internal_command( + thread_id, internal_smart_step_into, thread_id, offset, child_offset, set_additional_thread_info=set_additional_thread_info) + elif thread_id.startswith('__frame__:'): + sys.stderr.write("Can't set next statement in tasklet: %s\n" % (thread_id,)) + + def request_smart_step_into_by_func_name(self, py_db, seq, thread_id, line, func_name): + # Same thing as set next, just with a different cmd id. + self.request_set_next(py_db, seq, thread_id, CMD_SMART_STEP_INTO, None, line, func_name) + + def request_set_next(self, py_db, seq, thread_id, set_next_cmd_id, original_filename, line, func_name): + ''' + set_next_cmd_id may actually be one of: + + CMD_RUN_TO_LINE + CMD_SET_NEXT_STATEMENT + + CMD_SMART_STEP_INTO -- note: request_smart_step_into is preferred if it's possible + to work with bytecode offset. + + :param Optional[str] original_filename: + If available, the filename may be source translated, otherwise no translation will take + place (the set next just needs the line afterwards as it executes locally, but for + the Jupyter integration, the source mapping may change the actual lines and not only + the filename). + ''' + t = pydevd_find_thread_by_id(thread_id) + if t: + if original_filename is not None: + translated_filename = self.filename_to_server(original_filename) # Apply user path mapping. + pydev_log.debug('Set next (after path translation) in: %s line: %s', translated_filename, line) + func_name = self.to_str(func_name) + + assert translated_filename.__class__ == str # i.e.: bytes on py2 and str on py3 + assert func_name.__class__ == str # i.e.: bytes on py2 and str on py3 + + # Apply source mapping (i.e.: ipython). + _source_mapped_filename, new_line, multi_mapping_applied = py_db.source_mapping.map_to_server( + translated_filename, line) + if multi_mapping_applied: + pydev_log.debug('Set next (after source mapping) in: %s line: %s', translated_filename, line) + line = new_line + + int_cmd = InternalSetNextStatementThread(thread_id, set_next_cmd_id, line, func_name, seq=seq) + py_db.post_internal_command(int_cmd, thread_id) + elif thread_id.startswith('__frame__:'): + sys.stderr.write("Can't set next statement in tasklet: %s\n" % (thread_id,)) + + def request_reload_code(self, py_db, seq, module_name, filename): + ''' + :param seq: if -1 no message will be sent back when the reload is done. + + Note: either module_name or filename may be None (but not both at the same time). + ''' + thread_id = '*' # Any thread + # Note: not going for the main thread because in this case it'd only do the load + # when we stopped on a breakpoint. + py_db.post_method_as_internal_command( + thread_id, internal_reload_code, seq, module_name, filename) + + def request_change_variable(self, py_db, seq, thread_id, frame_id, scope, attr, value): + ''' + :param scope: 'FRAME' or 'GLOBAL' + ''' + py_db.post_method_as_internal_command( + thread_id, internal_change_variable, seq, thread_id, frame_id, scope, attr, value) + + def request_get_variable(self, py_db, seq, thread_id, frame_id, scope, attrs): + ''' + :param scope: 'FRAME' or 'GLOBAL' + ''' + int_cmd = InternalGetVariable(seq, thread_id, frame_id, scope, attrs) + py_db.post_internal_command(int_cmd, thread_id) + + def request_get_array(self, py_db, seq, roffset, coffset, rows, cols, fmt, thread_id, frame_id, scope, attrs): + int_cmd = InternalGetArray(seq, roffset, coffset, rows, cols, fmt, thread_id, frame_id, scope, attrs) + py_db.post_internal_command(int_cmd, thread_id) + + def request_load_full_value(self, py_db, seq, thread_id, frame_id, vars): + int_cmd = InternalLoadFullValue(seq, thread_id, frame_id, vars) + py_db.post_internal_command(int_cmd, thread_id) + + def request_get_description(self, py_db, seq, thread_id, frame_id, expression): + py_db.post_method_as_internal_command( + thread_id, internal_get_description, seq, thread_id, frame_id, expression) + + def request_get_frame(self, py_db, seq, thread_id, frame_id): + py_db.post_method_as_internal_command( + thread_id, internal_get_frame, seq, thread_id, frame_id) + + def to_str(self, s): + ''' + -- in py3 raises an error if it's not str already. + ''' + if s.__class__ != str: + raise AssertionError('Expected to have str on Python 3. Found: %s (%s)' % (s, s.__class__)) + return s + + def filename_to_str(self, filename): + ''' + -- in py3 raises an error if it's not str already. + ''' + if filename.__class__ != str: + raise AssertionError('Expected to have str on Python 3. Found: %s (%s)' % (filename, filename.__class__)) + return filename + + def filename_to_server(self, filename): + filename = self.filename_to_str(filename) + filename = pydevd_file_utils.map_file_to_server(filename) + return filename + + class _DummyFrame(object): + ''' + Dummy frame to be used with PyDB.apply_files_filter (as we don't really have the + related frame as breakpoints are added before execution). + ''' + + class _DummyCode(object): + + def __init__(self, filename): + self.co_firstlineno = 1 + self.co_filename = filename + self.co_name = 'invalid func name ' + + def __init__(self, filename): + self.f_code = self._DummyCode(filename) + self.f_globals = {} + + ADD_BREAKPOINT_NO_ERROR = 0 + ADD_BREAKPOINT_FILE_NOT_FOUND = 1 + ADD_BREAKPOINT_FILE_EXCLUDED_BY_FILTERS = 2 + + # This means that the breakpoint couldn't be fully validated (more runtime + # information may be needed). + ADD_BREAKPOINT_LAZY_VALIDATION = 3 + ADD_BREAKPOINT_INVALID_LINE = 4 + + class _AddBreakpointResult(object): + + # :see: ADD_BREAKPOINT_NO_ERROR = 0 + # :see: ADD_BREAKPOINT_FILE_NOT_FOUND = 1 + # :see: ADD_BREAKPOINT_FILE_EXCLUDED_BY_FILTERS = 2 + # :see: ADD_BREAKPOINT_LAZY_VALIDATION = 3 + # :see: ADD_BREAKPOINT_INVALID_LINE = 4 + + __slots__ = ['error_code', 'breakpoint_id', 'translated_filename', 'translated_line', 'original_line'] + + def __init__(self, breakpoint_id, translated_filename, translated_line, original_line): + self.error_code = PyDevdAPI.ADD_BREAKPOINT_NO_ERROR + self.breakpoint_id = breakpoint_id + self.translated_filename = translated_filename + self.translated_line = translated_line + self.original_line = original_line + + def add_breakpoint( + self, py_db, original_filename, breakpoint_type, breakpoint_id, line, condition, func_name, + expression, suspend_policy, hit_condition, is_logpoint, adjust_line=False, on_changed_breakpoint_state=None): + ''' + :param str original_filename: + Note: must be sent as it was received in the protocol. It may be translated in this + function and its final value will be available in the returned _AddBreakpointResult. + + :param str breakpoint_type: + One of: 'python-line', 'django-line', 'jinja2-line'. + + :param int breakpoint_id: + + :param int line: + Note: it's possible that a new line was actually used. If that's the case its + final value will be available in the returned _AddBreakpointResult. + + :param condition: + Either None or the condition to activate the breakpoint. + + :param str func_name: + If "None" (str), may hit in any context. + Empty string will hit only top level. + Any other value must match the scope of the method to be matched. + + :param str expression: + None or the expression to be evaluated. + + :param suspend_policy: + Either "NONE" (to suspend only the current thread when the breakpoint is hit) or + "ALL" (to suspend all threads when a breakpoint is hit). + + :param str hit_condition: + An expression where `@HIT@` will be replaced by the number of hits. + i.e.: `@HIT@ == x` or `@HIT@ >= x` + + :param bool is_logpoint: + If True and an expression is passed, pydevd will create an io message command with the + result of the evaluation. + + :param bool adjust_line: + If True, the breakpoint line should be adjusted if the current line doesn't really + match an executable line (if possible). + + :param callable on_changed_breakpoint_state: + This is called when something changed internally on the breakpoint after it was initially + added (for instance, template file_to_line_to_breakpoints could be signaled as invalid initially and later + when the related template is loaded, if the line is valid it could be marked as valid). + + The signature for the callback should be: + on_changed_breakpoint_state(breakpoint_id: int, add_breakpoint_result: _AddBreakpointResult) + + Note that the add_breakpoint_result should not be modified by the callback (the + implementation may internally reuse the same instance multiple times). + + :return _AddBreakpointResult: + ''' + assert original_filename.__class__ == str, 'Expected str, found: %s' % (original_filename.__class__,) # i.e.: bytes on py2 and str on py3 + + original_filename_normalized = pydevd_file_utils.normcase_from_client(original_filename) + + pydev_log.debug('Request for breakpoint in: %s line: %s', original_filename, line) + original_line = line + # Parameters to reapply breakpoint. + api_add_breakpoint_params = (original_filename, breakpoint_type, breakpoint_id, line, condition, func_name, + expression, suspend_policy, hit_condition, is_logpoint) + + translated_filename = self.filename_to_server(original_filename) # Apply user path mapping. + pydev_log.debug('Breakpoint (after path translation) in: %s line: %s', translated_filename, line) + func_name = self.to_str(func_name) + + assert translated_filename.__class__ == str # i.e.: bytes on py2 and str on py3 + assert func_name.__class__ == str # i.e.: bytes on py2 and str on py3 + + # Apply source mapping (i.e.: ipython). + source_mapped_filename, new_line, multi_mapping_applied = py_db.source_mapping.map_to_server( + translated_filename, line) + + if multi_mapping_applied: + pydev_log.debug('Breakpoint (after source mapping) in: %s line: %s', source_mapped_filename, new_line) + # Note that source mapping is internal and does not change the resulting filename nor line + # (we want the outside world to see the line in the original file and not in the ipython + # cell, otherwise the editor wouldn't be correct as the returned line is the line to + # which the breakpoint will be moved in the editor). + result = self._AddBreakpointResult(breakpoint_id, original_filename, line, original_line) + + # If a multi-mapping was applied, consider it the canonical / source mapped version (translated to ipython cell). + translated_absolute_filename = source_mapped_filename + canonical_normalized_filename = pydevd_file_utils.normcase(source_mapped_filename) + line = new_line + + else: + translated_absolute_filename = pydevd_file_utils.absolute_path(translated_filename) + canonical_normalized_filename = pydevd_file_utils.canonical_normalized_path(translated_filename) + + if adjust_line and not translated_absolute_filename.startswith('<'): + # Validate file_to_line_to_breakpoints and adjust their positions. + try: + lines = sorted(_get_code_lines(translated_absolute_filename)) + except Exception: + pass + else: + if line not in lines: + # Adjust to the first preceding valid line. + idx = bisect.bisect_left(lines, line) + if idx > 0: + line = lines[idx - 1] + + result = self._AddBreakpointResult(breakpoint_id, original_filename, line, original_line) + + py_db.api_received_breakpoints[(original_filename_normalized, breakpoint_id)] = (canonical_normalized_filename, api_add_breakpoint_params) + + if not translated_absolute_filename.startswith('<'): + # Note: if a mapping pointed to a file starting with '<', don't validate. + + if not pydevd_file_utils.exists(translated_absolute_filename): + result.error_code = self.ADD_BREAKPOINT_FILE_NOT_FOUND + return result + + if ( + py_db.is_files_filter_enabled and + not py_db.get_require_module_for_filters() and + py_db.apply_files_filter(self._DummyFrame(translated_absolute_filename), translated_absolute_filename, False) + ): + # Note that if `get_require_module_for_filters()` returns False, we don't do this check. + # This is because we don't have the module name given a file at this point (in + # runtime it's gotten from the frame.f_globals). + # An option could be calculate it based on the filename and current sys.path, + # but on some occasions that may be wrong (for instance with `__main__` or if + # the user dynamically changes the PYTHONPATH). + + # Note: depending on the use-case, filters may be changed, so, keep on going and add the + # breakpoint even with the error code. + result.error_code = self.ADD_BREAKPOINT_FILE_EXCLUDED_BY_FILTERS + + if breakpoint_type == 'python-line': + added_breakpoint = LineBreakpoint( + breakpoint_id, line, condition, func_name, expression, suspend_policy, hit_condition=hit_condition, is_logpoint=is_logpoint) + + file_to_line_to_breakpoints = py_db.breakpoints + file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint + supported_type = True + + else: + add_plugin_breakpoint_result = None + plugin = py_db.get_plugin_lazy_init() + if plugin is not None: + add_plugin_breakpoint_result = plugin.add_breakpoint( + 'add_line_breakpoint', py_db, breakpoint_type, canonical_normalized_filename, + breakpoint_id, line, condition, expression, func_name, hit_condition=hit_condition, is_logpoint=is_logpoint, + add_breakpoint_result=result, on_changed_breakpoint_state=on_changed_breakpoint_state) + + if add_plugin_breakpoint_result is not None: + supported_type = True + added_breakpoint, file_to_line_to_breakpoints = add_plugin_breakpoint_result + file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint + else: + supported_type = False + + if not supported_type: + raise NameError(breakpoint_type) + + pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n', canonical_normalized_filename, line, func_name) + + if canonical_normalized_filename in file_to_id_to_breakpoint: + id_to_pybreakpoint = file_to_id_to_breakpoint[canonical_normalized_filename] + else: + id_to_pybreakpoint = file_to_id_to_breakpoint[canonical_normalized_filename] = {} + + id_to_pybreakpoint[breakpoint_id] = added_breakpoint + py_db.consolidate_breakpoints(canonical_normalized_filename, id_to_pybreakpoint, file_to_line_to_breakpoints) + if py_db.plugin is not None: + py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks() + py_db.plugin.after_breakpoints_consolidated(py_db, canonical_normalized_filename, id_to_pybreakpoint, file_to_line_to_breakpoints) + + py_db.on_breakpoints_changed() + return result + + def reapply_breakpoints(self, py_db): + ''' + Reapplies all the received breakpoints as they were received by the API (so, new + translations are applied). + ''' + pydev_log.debug('Reapplying breakpoints.') + values = list(py_db.api_received_breakpoints.values()) # Create a copy with items to reapply. + self.remove_all_breakpoints(py_db, '*') + for val in values: + _new_filename, api_add_breakpoint_params = val + self.add_breakpoint(py_db, *api_add_breakpoint_params) + + def remove_all_breakpoints(self, py_db, received_filename): + ''' + Removes all the breakpoints from a given file or from all files if received_filename == '*'. + + :param str received_filename: + Note: must be sent as it was received in the protocol. It may be translated in this + function. + ''' + assert received_filename.__class__ == str # i.e.: bytes on py2 and str on py3 + changed = False + lst = [ + py_db.file_to_id_to_line_breakpoint, + py_db.file_to_id_to_plugin_breakpoint, + py_db.breakpoints + ] + if hasattr(py_db, 'django_breakpoints'): + lst.append(py_db.django_breakpoints) + + if hasattr(py_db, 'jinja2_breakpoints'): + lst.append(py_db.jinja2_breakpoints) + + if received_filename == '*': + py_db.api_received_breakpoints.clear() + + for file_to_id_to_breakpoint in lst: + if file_to_id_to_breakpoint: + file_to_id_to_breakpoint.clear() + changed = True + + else: + received_filename_normalized = pydevd_file_utils.normcase_from_client(received_filename) + items = list(py_db.api_received_breakpoints.items()) # Create a copy to remove items. + translated_filenames = [] + for key, val in items: + original_filename_normalized, _breakpoint_id = key + if original_filename_normalized == received_filename_normalized: + canonical_normalized_filename, _api_add_breakpoint_params = val + # Note: there can be actually 1:N mappings due to source mapping (i.e.: ipython). + translated_filenames.append(canonical_normalized_filename) + del py_db.api_received_breakpoints[key] + + for canonical_normalized_filename in translated_filenames: + for file_to_id_to_breakpoint in lst: + if canonical_normalized_filename in file_to_id_to_breakpoint: + file_to_id_to_breakpoint.pop(canonical_normalized_filename, None) + changed = True + + if changed: + py_db.on_breakpoints_changed(removed=True) + + def remove_breakpoint(self, py_db, received_filename, breakpoint_type, breakpoint_id): + ''' + :param str received_filename: + Note: must be sent as it was received in the protocol. It may be translated in this + function. + + :param str breakpoint_type: + One of: 'python-line', 'django-line', 'jinja2-line'. + + :param int breakpoint_id: + ''' + received_filename_normalized = pydevd_file_utils.normcase_from_client(received_filename) + for key, val in list(py_db.api_received_breakpoints.items()): + original_filename_normalized, existing_breakpoint_id = key + _new_filename, _api_add_breakpoint_params = val + if received_filename_normalized == original_filename_normalized and existing_breakpoint_id == breakpoint_id: + del py_db.api_received_breakpoints[key] + break + else: + pydev_log.info( + 'Did not find breakpoint to remove: %s (breakpoint id: %s)', received_filename, breakpoint_id) + + file_to_id_to_breakpoint = None + received_filename = self.filename_to_server(received_filename) + canonical_normalized_filename = pydevd_file_utils.canonical_normalized_path(received_filename) + + if breakpoint_type == 'python-line': + file_to_line_to_breakpoints = py_db.breakpoints + file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint + + elif py_db.plugin is not None: + result = py_db.plugin.get_breakpoints(py_db, breakpoint_type) + if result is not None: + file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint + file_to_line_to_breakpoints = result + + if file_to_id_to_breakpoint is None: + pydev_log.critical('Error removing breakpoint. Cannot handle breakpoint of type %s', breakpoint_type) + + else: + try: + id_to_pybreakpoint = file_to_id_to_breakpoint.get(canonical_normalized_filename, {}) + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + existing = id_to_pybreakpoint[breakpoint_id] + pydev_log.info('Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % ( + canonical_normalized_filename, existing.line, existing.func_name, breakpoint_id)) + + del id_to_pybreakpoint[breakpoint_id] + py_db.consolidate_breakpoints(canonical_normalized_filename, id_to_pybreakpoint, file_to_line_to_breakpoints) + if py_db.plugin is not None: + py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks() + py_db.plugin.after_breakpoints_consolidated(py_db, canonical_normalized_filename, id_to_pybreakpoint, file_to_line_to_breakpoints) + + except KeyError: + pydev_log.info("Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n", + canonical_normalized_filename, breakpoint_id, list(id_to_pybreakpoint)) + + py_db.on_breakpoints_changed(removed=True) + + def set_function_breakpoints(self, py_db, function_breakpoints): + function_breakpoint_name_to_breakpoint = {} + for function_breakpoint in function_breakpoints: + function_breakpoint_name_to_breakpoint[function_breakpoint.func_name] = function_breakpoint + + py_db.function_breakpoint_name_to_breakpoint = function_breakpoint_name_to_breakpoint + py_db.on_breakpoints_changed() + + def request_exec_or_evaluate( + self, py_db, seq, thread_id, frame_id, expression, is_exec, trim_if_too_big, attr_to_set_result): + py_db.post_method_as_internal_command( + thread_id, internal_evaluate_expression, + seq, thread_id, frame_id, expression, is_exec, trim_if_too_big, attr_to_set_result) + + def request_exec_or_evaluate_json( + self, py_db, request, thread_id): + py_db.post_method_as_internal_command( + thread_id, internal_evaluate_expression_json, request, thread_id) + + def request_set_expression_json(self, py_db, request, thread_id): + py_db.post_method_as_internal_command( + thread_id, internal_set_expression_json, request, thread_id) + + def request_console_exec(self, py_db, seq, thread_id, frame_id, expression): + int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression) + py_db.post_internal_command(int_cmd, thread_id) + + def request_load_source(self, py_db, seq, filename): + ''' + :param str filename: + Note: must be sent as it was received in the protocol. It may be translated in this + function. + ''' + try: + filename = self.filename_to_server(filename) + assert filename.__class__ == str # i.e.: bytes on py2 and str on py3 + + with tokenize.open(filename) as stream: + source = stream.read() + cmd = py_db.cmd_factory.make_load_source_message(seq, source) + except: + cmd = py_db.cmd_factory.make_error_message(seq, get_exception_traceback_str()) + + py_db.writer.add_command(cmd) + + def get_decompiled_source_from_frame_id(self, py_db, frame_id): + ''' + :param py_db: + :param frame_id: + :throws Exception: + If unable to get the frame in the currently paused frames or if some error happened + when decompiling. + ''' + variable = py_db.suspended_frames_manager.get_variable(int(frame_id)) + frame = variable.value + + # Check if it's in the linecache first. + lines = (linecache.getline(frame.f_code.co_filename, i) for i in itertools.count(1)) + lines = itertools.takewhile(bool, lines) # empty lines are '\n', EOF is '' + + source = ''.join(lines) + if not source: + source = code_to_bytecode_representation(frame.f_code) + + return source + + def request_load_source_from_frame_id(self, py_db, seq, frame_id): + try: + source = self.get_decompiled_source_from_frame_id(py_db, frame_id) + cmd = py_db.cmd_factory.make_load_source_from_frame_id_message(seq, source) + except: + cmd = py_db.cmd_factory.make_error_message(seq, get_exception_traceback_str()) + + py_db.writer.add_command(cmd) + + def add_python_exception_breakpoint( + self, + py_db, + exception, + condition, + expression, + notify_on_handled_exceptions, + notify_on_unhandled_exceptions, + notify_on_user_unhandled_exceptions, + notify_on_first_raise_only, + ignore_libraries, + ): + exception_breakpoint = py_db.add_break_on_exception( + exception, + condition=condition, + expression=expression, + notify_on_handled_exceptions=notify_on_handled_exceptions, + notify_on_unhandled_exceptions=notify_on_unhandled_exceptions, + notify_on_user_unhandled_exceptions=notify_on_user_unhandled_exceptions, + notify_on_first_raise_only=notify_on_first_raise_only, + ignore_libraries=ignore_libraries, + ) + + if exception_breakpoint is not None: + py_db.on_breakpoints_changed() + + def add_plugins_exception_breakpoint(self, py_db, breakpoint_type, exception): + supported_type = False + plugin = py_db.get_plugin_lazy_init() + if plugin is not None: + supported_type = plugin.add_breakpoint('add_exception_breakpoint', py_db, breakpoint_type, exception) + + if supported_type: + py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks() + py_db.on_breakpoints_changed() + else: + raise NameError(breakpoint_type) + + def remove_python_exception_breakpoint(self, py_db, exception): + try: + cp = py_db.break_on_uncaught_exceptions.copy() + cp.pop(exception, None) + py_db.break_on_uncaught_exceptions = cp + + cp = py_db.break_on_caught_exceptions.copy() + cp.pop(exception, None) + py_db.break_on_caught_exceptions = cp + + cp = py_db.break_on_user_uncaught_exceptions.copy() + cp.pop(exception, None) + py_db.break_on_user_uncaught_exceptions = cp + except: + pydev_log.exception("Error while removing exception %s", sys.exc_info()[0]) + + py_db.on_breakpoints_changed(removed=True) + + def remove_plugins_exception_breakpoint(self, py_db, exception_type, exception): + # I.e.: no need to initialize lazy (if we didn't have it in the first place, we can't remove + # anything from it anyways). + plugin = py_db.plugin + if plugin is None: + return + + supported_type = plugin.remove_exception_breakpoint(py_db, exception_type, exception) + + if supported_type: + py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks() + else: + pydev_log.info('No exception of type: %s was previously registered.', exception_type) + + py_db.on_breakpoints_changed(removed=True) + + def remove_all_exception_breakpoints(self, py_db): + py_db.break_on_uncaught_exceptions = {} + py_db.break_on_caught_exceptions = {} + py_db.break_on_user_uncaught_exceptions = {} + + plugin = py_db.plugin + if plugin is not None: + plugin.remove_all_exception_breakpoints(py_db) + py_db.on_breakpoints_changed(removed=True) + + def set_project_roots(self, py_db, project_roots): + ''' + :param str project_roots: + ''' + py_db.set_project_roots(project_roots) + + def set_stepping_resumes_all_threads(self, py_db, stepping_resumes_all_threads): + py_db.stepping_resumes_all_threads = stepping_resumes_all_threads + + # Add it to the namespace so that it's available as PyDevdAPI.ExcludeFilter + from _pydevd_bundle.pydevd_filtering import ExcludeFilter # noqa + + def set_exclude_filters(self, py_db, exclude_filters): + ''' + :param list(PyDevdAPI.ExcludeFilter) exclude_filters: + ''' + py_db.set_exclude_filters(exclude_filters) + + def set_use_libraries_filter(self, py_db, use_libraries_filter): + py_db.set_use_libraries_filter(use_libraries_filter) + + def request_get_variable_json(self, py_db, request, thread_id): + ''' + :param VariablesRequest request: + ''' + py_db.post_method_as_internal_command( + thread_id, internal_get_variable_json, request) + + def request_change_variable_json(self, py_db, request, thread_id): + ''' + :param SetVariableRequest request: + ''' + py_db.post_method_as_internal_command( + thread_id, internal_change_variable_json, request) + + def set_dont_trace_start_end_patterns(self, py_db, start_patterns, end_patterns): + # Note: start/end patterns normalized internally. + start_patterns = tuple(pydevd_file_utils.normcase(x) for x in start_patterns) + end_patterns = tuple(pydevd_file_utils.normcase(x) for x in end_patterns) + + # After it's set the first time, we can still change it, but we need to reset the + # related caches. + reset_caches = False + dont_trace_start_end_patterns_previously_set = \ + py_db.dont_trace_external_files.__name__ == 'custom_dont_trace_external_files' + + if not dont_trace_start_end_patterns_previously_set and not start_patterns and not end_patterns: + # If it wasn't set previously and start and end patterns are empty we don't need to do anything. + return + + if not py_db.is_cache_file_type_empty(): + # i.e.: custom function set in set_dont_trace_start_end_patterns. + if dont_trace_start_end_patterns_previously_set: + reset_caches = py_db.dont_trace_external_files.start_patterns != start_patterns or \ + py_db.dont_trace_external_files.end_patterns != end_patterns + + else: + reset_caches = True + + def custom_dont_trace_external_files(abs_path): + normalized_abs_path = pydevd_file_utils.normcase(abs_path) + return normalized_abs_path.startswith(start_patterns) or normalized_abs_path.endswith(end_patterns) + + custom_dont_trace_external_files.start_patterns = start_patterns + custom_dont_trace_external_files.end_patterns = end_patterns + py_db.dont_trace_external_files = custom_dont_trace_external_files + + if reset_caches: + py_db.clear_dont_trace_start_end_patterns_caches() + + def stop_on_entry(self): + main_thread = pydevd_utils.get_main_thread() + if main_thread is None: + pydev_log.critical('Could not find main thread while setting Stop on Entry.') + else: + info = set_additional_thread_info(main_thread) + info.pydev_original_step_cmd = CMD_STOP_ON_START + info.pydev_step_cmd = CMD_STEP_INTO_MY_CODE + + def set_ignore_system_exit_codes(self, py_db, ignore_system_exit_codes): + py_db.set_ignore_system_exit_codes(ignore_system_exit_codes) + + SourceMappingEntry = pydevd_source_mapping.SourceMappingEntry + + def set_source_mapping(self, py_db, source_filename, mapping): + ''' + :param str source_filename: + The filename for the source mapping (bytes on py2 and str on py3). + This filename will be made absolute in this function. + + :param list(SourceMappingEntry) mapping: + A list with the source mapping entries to be applied to the given filename. + + :return str: + An error message if it was not possible to set the mapping or an empty string if + everything is ok. + ''' + source_filename = self.filename_to_server(source_filename) + absolute_source_filename = pydevd_file_utils.absolute_path(source_filename) + for map_entry in mapping: + map_entry.source_filename = absolute_source_filename + error_msg = py_db.source_mapping.set_source_mapping(absolute_source_filename, mapping) + if error_msg: + return error_msg + + self.reapply_breakpoints(py_db) + return '' + + def set_variable_presentation(self, py_db, variable_presentation): + assert isinstance(variable_presentation, self.VariablePresentation) + py_db.variable_presentation = variable_presentation + + def get_ppid(self): + ''' + Provides the parent pid (even for older versions of Python on Windows). + ''' + ppid = None + + try: + ppid = os.getppid() + except AttributeError: + pass + + if ppid is None and IS_WINDOWS: + ppid = self._get_windows_ppid() + + return ppid + + def _get_windows_ppid(self): + this_pid = os.getpid() + for ppid, pid in _list_ppid_and_pid(): + if pid == this_pid: + return ppid + + return None + + def _terminate_child_processes_windows(self, dont_terminate_child_pids): + this_pid = os.getpid() + for _ in range(50): # Try this at most 50 times before giving up. + + # Note: we can't kill the process itself with taskkill, so, we + # list immediate children, kill that tree and then exit this process. + + children_pids = [] + for ppid, pid in _list_ppid_and_pid(): + if ppid == this_pid: + if pid not in dont_terminate_child_pids: + children_pids.append(pid) + + if not children_pids: + break + else: + for pid in children_pids: + self._call( + ['taskkill', '/F', '/PID', str(pid), '/T'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + + del children_pids[:] + + def _terminate_child_processes_linux_and_mac(self, dont_terminate_child_pids): + this_pid = os.getpid() + + def list_children_and_stop_forking(initial_pid, stop=True): + children_pids = [] + if stop: + # Ask to stop forking (shouldn't be called for this process, only subprocesses). + self._call( + ['kill', '-STOP', str(initial_pid)], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + + list_popen = self._popen( + ['pgrep', '-P', str(initial_pid)], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + + if list_popen is not None: + stdout, _ = list_popen.communicate() + for line in stdout.splitlines(): + line = line.decode('ascii').strip() + if line: + pid = str(line) + if pid in dont_terminate_child_pids: + continue + children_pids.append(pid) + # Recursively get children. + children_pids.extend(list_children_and_stop_forking(pid)) + return children_pids + + previously_found = set() + + for _ in range(50): # Try this at most 50 times before giving up. + + children_pids = list_children_and_stop_forking(this_pid, stop=False) + found_new = False + + for pid in children_pids: + if pid not in previously_found: + found_new = True + previously_found.add(pid) + self._call( + ['kill', '-KILL', str(pid)], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + + if not found_new: + break + + def _popen(self, cmdline, **kwargs): + try: + return subprocess.Popen(cmdline, **kwargs) + except: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + pydev_log.exception('Error running: %s' % (' '.join(cmdline))) + return None + + def _call(self, cmdline, **kwargs): + try: + subprocess.check_call(cmdline, **kwargs) + except: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + pydev_log.exception('Error running: %s' % (' '.join(cmdline))) + + def set_terminate_child_processes(self, py_db, terminate_child_processes): + py_db.terminate_child_processes = terminate_child_processes + + def terminate_process(self, py_db): + ''' + Terminates the current process (and child processes if the option to also terminate + child processes is enabled). + ''' + try: + if py_db.terminate_child_processes: + pydev_log.debug('Terminating child processes.') + if IS_WINDOWS: + self._terminate_child_processes_windows(py_db.dont_terminate_child_pids) + else: + self._terminate_child_processes_linux_and_mac(py_db.dont_terminate_child_pids) + finally: + pydev_log.debug('Exiting process (os._exit(0)).') + os._exit(0) + + def _terminate_if_commands_processed(self, py_db): + py_db.dispose_and_kill_all_pydevd_threads() + self.terminate_process(py_db) + + def request_terminate_process(self, py_db): + # We mark with a terminate_requested to avoid that paused threads start running + # (we should terminate as is without letting any paused thread run). + py_db.terminate_requested = True + run_as_pydevd_daemon_thread(py_db, self._terminate_if_commands_processed, py_db) + + def setup_auto_reload_watcher(self, py_db, enable_auto_reload, watch_dirs, poll_target_time, exclude_patterns, include_patterns): + py_db.setup_auto_reload_watcher(enable_auto_reload, watch_dirs, poll_target_time, exclude_patterns, include_patterns) + + +def _list_ppid_and_pid(): + _TH32CS_SNAPPROCESS = 0x00000002 + + class PROCESSENTRY32(ctypes.Structure): + _fields_ = [("dwSize", ctypes.c_uint32), + ("cntUsage", ctypes.c_uint32), + ("th32ProcessID", ctypes.c_uint32), + ("th32DefaultHeapID", ctypes.c_size_t), + ("th32ModuleID", ctypes.c_uint32), + ("cntThreads", ctypes.c_uint32), + ("th32ParentProcessID", ctypes.c_uint32), + ("pcPriClassBase", ctypes.c_long), + ("dwFlags", ctypes.c_uint32), + ("szExeFile", ctypes.c_char * 260)] + + kernel32 = ctypes.windll.kernel32 + snapshot = kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0) + ppid_and_pids = [] + try: + process_entry = PROCESSENTRY32() + process_entry.dwSize = ctypes.sizeof(PROCESSENTRY32) + if not kernel32.Process32First(ctypes.c_void_p(snapshot), ctypes.byref(process_entry)): + pydev_log.critical('Process32First failed (getting process from CreateToolhelp32Snapshot).') + else: + while True: + ppid_and_pids.append((process_entry.th32ParentProcessID, process_entry.th32ProcessID)) + if not kernel32.Process32Next(ctypes.c_void_p(snapshot), ctypes.byref(process_entry)): + break + finally: + kernel32.CloseHandle(snapshot) + + return ppid_and_pids diff --git a/_pydevd_bundle/pydevd_breakpoints.py b/_pydevd_bundle/pydevd_breakpoints.py new file mode 100644 index 0000000..d92fccf --- /dev/null +++ b/_pydevd_bundle/pydevd_breakpoints.py @@ -0,0 +1,184 @@ +from _pydev_bundle import pydev_log +from _pydevd_bundle import pydevd_import_class +from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame +from _pydev_bundle._pydev_saved_modules import threading + + +class ExceptionBreakpoint(object): + + def __init__( + self, + qname, + condition, + expression, + notify_on_handled_exceptions, + notify_on_unhandled_exceptions, + notify_on_user_unhandled_exceptions, + notify_on_first_raise_only, + ignore_libraries + ): + exctype = get_exception_class(qname) + self.qname = qname + if exctype is not None: + self.name = exctype.__name__ + else: + self.name = None + + self.condition = condition + self.expression = expression + self.notify_on_unhandled_exceptions = notify_on_unhandled_exceptions + self.notify_on_handled_exceptions = notify_on_handled_exceptions + self.notify_on_first_raise_only = notify_on_first_raise_only + self.notify_on_user_unhandled_exceptions = notify_on_user_unhandled_exceptions + self.ignore_libraries = ignore_libraries + + self.type = exctype + + def __str__(self): + return self.qname + + @property + def has_condition(self): + return self.condition is not None + + def handle_hit_condition(self, frame): + return False + + +class LineBreakpoint(object): + + def __init__(self, breakpoint_id, line, condition, func_name, expression, suspend_policy="NONE", hit_condition=None, is_logpoint=False): + self.breakpoint_id = breakpoint_id + self.line = line + self.condition = condition + self.func_name = func_name + self.expression = expression + self.suspend_policy = suspend_policy + self.hit_condition = hit_condition + self._hit_count = 0 + self._hit_condition_lock = threading.Lock() + self.is_logpoint = is_logpoint + + @property + def has_condition(self): + return bool(self.condition) or bool(self.hit_condition) + + def handle_hit_condition(self, frame): + if not self.hit_condition: + return False + ret = False + with self._hit_condition_lock: + self._hit_count += 1 + expr = self.hit_condition.replace('@HIT@', str(self._hit_count)) + try: + ret = bool(eval(expr, frame.f_globals, frame.f_locals)) + except Exception: + ret = False + return ret + + +class FunctionBreakpoint(object): + + def __init__(self, func_name, condition, expression, suspend_policy="NONE", hit_condition=None, is_logpoint=False): + self.condition = condition + self.func_name = func_name + self.expression = expression + self.suspend_policy = suspend_policy + self.hit_condition = hit_condition + self._hit_count = 0 + self._hit_condition_lock = threading.Lock() + self.is_logpoint = is_logpoint + + @property + def has_condition(self): + return bool(self.condition) or bool(self.hit_condition) + + def handle_hit_condition(self, frame): + if not self.hit_condition: + return False + ret = False + with self._hit_condition_lock: + self._hit_count += 1 + expr = self.hit_condition.replace('@HIT@', str(self._hit_count)) + try: + ret = bool(eval(expr, frame.f_globals, frame.f_locals)) + except Exception: + ret = False + return ret + + +def get_exception_breakpoint(exctype, exceptions): + if not exctype: + exception_full_qname = None + else: + exception_full_qname = str(exctype.__module__) + '.' + exctype.__name__ + + exc = None + if exceptions is not None: + try: + return exceptions[exception_full_qname] + except KeyError: + for exception_breakpoint in exceptions.values(): + if exception_breakpoint.type is not None and issubclass(exctype, exception_breakpoint.type): + if exc is None or issubclass(exception_breakpoint.type, exc.type): + exc = exception_breakpoint + return exc + + +def stop_on_unhandled_exception(py_db, thread, additional_info, arg): + exctype, value, tb = arg + break_on_uncaught_exceptions = py_db.break_on_uncaught_exceptions + if break_on_uncaught_exceptions: + exception_breakpoint = py_db.get_exception_breakpoint(exctype, break_on_uncaught_exceptions) + else: + exception_breakpoint = None + + if not exception_breakpoint: + return + + if tb is None: # sometimes it can be None, e.g. with GTK + return + + if exctype is KeyboardInterrupt: + return + + if exctype is SystemExit and py_db.ignore_system_exit_code(value): + return + + frames = [] + user_frame = None + + while tb is not None: + if not py_db.exclude_exception_by_filter(exception_breakpoint, tb): + user_frame = tb.tb_frame + frames.append(tb.tb_frame) + tb = tb.tb_next + + if user_frame is None: + return + + frames_byid = dict([(id(frame), frame) for frame in frames]) + add_exception_to_frame(user_frame, arg) + if exception_breakpoint.condition is not None: + eval_result = py_db.handle_breakpoint_condition(additional_info, exception_breakpoint, user_frame) + if not eval_result: + return + + if exception_breakpoint.expression is not None: + py_db.handle_breakpoint_expression(exception_breakpoint, additional_info, user_frame) + + try: + additional_info.pydev_message = exception_breakpoint.qname + except: + additional_info.pydev_message = exception_breakpoint.qname.encode('utf-8') + + pydev_log.debug('Handling post-mortem stop on exception breakpoint %s' % (exception_breakpoint.qname,)) + + py_db.do_stop_on_unhandled_exception(thread, user_frame, frames_byid, arg) + + +def get_exception_class(kls): + try: + return eval(kls) + except: + return pydevd_import_class.import_name(kls) diff --git a/_pydevd_bundle/pydevd_bytecode_utils.py b/_pydevd_bundle/pydevd_bytecode_utils.py new file mode 100644 index 0000000..e8c9f54 --- /dev/null +++ b/_pydevd_bundle/pydevd_bytecode_utils.py @@ -0,0 +1,843 @@ +""" +Bytecode analysing utils. Originally added for using in smart step into. + +Note: not importable from Python 2. +""" + +from _pydev_bundle import pydev_log +from types import CodeType +from _pydevd_frame_eval.vendored.bytecode.instr import _Variable +from _pydevd_frame_eval.vendored import bytecode +from _pydevd_frame_eval.vendored.bytecode import cfg as bytecode_cfg +import dis +import opcode as _opcode + +from _pydevd_bundle.pydevd_constants import KeyifyList, DebugInfoHolder, IS_PY311_OR_GREATER +from bisect import bisect +from collections import deque + +# When True, throws errors on unknown bytecodes, when False, ignore those as if they didn't change the stack. +STRICT_MODE = False + +DEBUG = False + +_BINARY_OPS = set([opname for opname in dis.opname if opname.startswith('BINARY_')]) + +_BINARY_OP_MAP = { + 'BINARY_POWER': '__pow__', + 'BINARY_MULTIPLY': '__mul__', + 'BINARY_MATRIX_MULTIPLY': '__matmul__', + 'BINARY_FLOOR_DIVIDE': '__floordiv__', + 'BINARY_TRUE_DIVIDE': '__div__', + 'BINARY_MODULO': '__mod__', + 'BINARY_ADD': '__add__', + 'BINARY_SUBTRACT': '__sub__', + 'BINARY_LSHIFT': '__lshift__', + 'BINARY_RSHIFT': '__rshift__', + 'BINARY_AND': '__and__', + 'BINARY_OR': '__or__', + 'BINARY_XOR': '__xor__', + 'BINARY_SUBSCR': '__getitem__', + 'BINARY_DIVIDE': '__div__' +} + +_COMP_OP_MAP = { + '<': '__lt__', + '<=': '__le__', + '==': '__eq__', + '!=': '__ne__', + '>': '__gt__', + '>=': '__ge__', + 'in': '__contains__', + 'not in': '__contains__', +} + + +class Target(object): + __slots__ = ['arg', 'lineno', 'offset', 'children_targets'] + + def __init__(self, arg, lineno, offset, children_targets=()): + self.arg = arg + self.lineno = lineno + self.offset = offset + self.children_targets = children_targets + + def __repr__(self): + ret = [] + for s in self.__slots__: + ret.append('%s: %s' % (s, getattr(self, s))) + return 'Target(%s)' % ', '.join(ret) + + __str__ = __repr__ + + +class _TargetIdHashable(object): + + def __init__(self, target): + self.target = target + + def __eq__(self, other): + if not hasattr(other, 'target'): + return + return other.target is self.target + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return id(self.target) + + +class _StackInterpreter(object): + ''' + Good reference: https://github.com/python/cpython/blob/fcb55c0037baab6f98f91ee38ce84b6f874f034a/Python/ceval.c + ''' + + def __init__(self, bytecode): + self.bytecode = bytecode + self._stack = deque() + self.function_calls = [] + self.load_attrs = {} + self.func = set() + self.func_name_id_to_code_object = {} + + def __str__(self): + return 'Stack:\nFunction calls:\n%s\nLoad attrs:\n%s\n' % (self.function_calls, list(self.load_attrs.values())) + + def _getname(self, instr): + if instr.opcode in _opcode.hascompare: + cmp_op = dis.cmp_op[instr.arg] + if cmp_op not in ('exception match', 'BAD'): + return _COMP_OP_MAP.get(cmp_op, cmp_op) + return instr.arg + + def _getcallname(self, instr): + if instr.name == 'BINARY_SUBSCR': + return '__getitem__().__call__' + if instr.name == 'CALL_FUNCTION': + # Note: previously a '__call__().__call__' was returned, but this was a bit weird + # and on Python 3.9 this construct could appear for some internal things where + # it wouldn't be expected. + # Note: it'd be what we had in func()(). + return None + if instr.name == 'MAKE_FUNCTION': + return '__func__().__call__' + if instr.name == 'LOAD_ASSERTION_ERROR': + return 'AssertionError' + name = self._getname(instr) + if isinstance(name, CodeType): + name = name.co_qualname # Note: only available for Python 3.11 + if isinstance(name, _Variable): + name = name.name + + if not isinstance(name, str): + return None + if name.endswith('>'): # xxx., xxx., ... + return name.split('.')[-1] + return name + + def _no_stack_change(self, instr): + pass # Can be aliased when the instruction does nothing. + + def on_LOAD_GLOBAL(self, instr): + self._stack.append(instr) + + def on_POP_TOP(self, instr): + try: + self._stack.pop() + except IndexError: + pass # Ok (in the end of blocks) + + def on_LOAD_ATTR(self, instr): + self.on_POP_TOP(instr) # replaces the current top + self._stack.append(instr) + self.load_attrs[_TargetIdHashable(instr)] = Target(self._getname(instr), instr.lineno, instr.offset) + + on_LOOKUP_METHOD = on_LOAD_ATTR # Improvement in PyPy + + def on_LOAD_CONST(self, instr): + self._stack.append(instr) + + on_LOAD_DEREF = on_LOAD_CONST + on_LOAD_NAME = on_LOAD_CONST + on_LOAD_CLOSURE = on_LOAD_CONST + on_LOAD_CLASSDEREF = on_LOAD_CONST + + # Although it actually changes the stack, it's inconsequential for us as a function call can't + # really be found there. + on_IMPORT_NAME = _no_stack_change + on_IMPORT_FROM = _no_stack_change + on_IMPORT_STAR = _no_stack_change + on_SETUP_ANNOTATIONS = _no_stack_change + + def on_STORE_FAST(self, instr): + try: + self._stack.pop() + except IndexError: + pass # Ok, we may have a block just with the store + + # Note: it stores in the locals and doesn't put anything in the stack. + + on_STORE_GLOBAL = on_STORE_FAST + on_STORE_DEREF = on_STORE_FAST + on_STORE_ATTR = on_STORE_FAST + on_STORE_NAME = on_STORE_FAST + + on_DELETE_NAME = on_POP_TOP + on_DELETE_ATTR = on_POP_TOP + on_DELETE_GLOBAL = on_POP_TOP + on_DELETE_FAST = on_POP_TOP + on_DELETE_DEREF = on_POP_TOP + + on_DICT_UPDATE = on_POP_TOP + on_SET_UPDATE = on_POP_TOP + + on_GEN_START = on_POP_TOP + + def on_NOP(self, instr): + pass + + def _handle_call_from_instr(self, func_name_instr, func_call_instr): + self.load_attrs.pop(_TargetIdHashable(func_name_instr), None) + call_name = self._getcallname(func_name_instr) + target = None + if not call_name: + pass # Ignore if we can't identify a name + elif call_name in ('', '', '', ''): + code_obj = self.func_name_id_to_code_object[_TargetIdHashable(func_name_instr)] + if code_obj is not None: + children_targets = _get_smart_step_into_targets(code_obj) + if children_targets: + # i.e.: we have targets inside of a or . + # Note that to actually match this in the debugger we need to do matches on 2 frames, + # the one with the and then the actual target inside the . + target = Target(call_name, func_name_instr.lineno, func_call_instr.offset, children_targets) + self.function_calls.append( + target) + + else: + # Ok, regular call + target = Target(call_name, func_name_instr.lineno, func_call_instr.offset) + self.function_calls.append(target) + + if DEBUG and target is not None: + print('Created target', target) + self._stack.append(func_call_instr) # Keep the func call as the result + + def on_COMPARE_OP(self, instr): + try: + _right = self._stack.pop() + except IndexError: + return + try: + _left = self._stack.pop() + except IndexError: + return + + cmp_op = dis.cmp_op[instr.arg] + if cmp_op not in ('exception match', 'BAD'): + self.function_calls.append(Target(self._getname(instr), instr.lineno, instr.offset)) + + self._stack.append(instr) + + def on_IS_OP(self, instr): + try: + self._stack.pop() + except IndexError: + return + try: + self._stack.pop() + except IndexError: + return + + def on_BINARY_SUBSCR(self, instr): + try: + _sub = self._stack.pop() + except IndexError: + return + try: + _container = self._stack.pop() + except IndexError: + return + self.function_calls.append(Target(_BINARY_OP_MAP[instr.name], instr.lineno, instr.offset)) + self._stack.append(instr) + + on_BINARY_MATRIX_MULTIPLY = on_BINARY_SUBSCR + on_BINARY_POWER = on_BINARY_SUBSCR + on_BINARY_MULTIPLY = on_BINARY_SUBSCR + on_BINARY_FLOOR_DIVIDE = on_BINARY_SUBSCR + on_BINARY_TRUE_DIVIDE = on_BINARY_SUBSCR + on_BINARY_MODULO = on_BINARY_SUBSCR + on_BINARY_ADD = on_BINARY_SUBSCR + on_BINARY_SUBTRACT = on_BINARY_SUBSCR + on_BINARY_LSHIFT = on_BINARY_SUBSCR + on_BINARY_RSHIFT = on_BINARY_SUBSCR + on_BINARY_AND = on_BINARY_SUBSCR + on_BINARY_OR = on_BINARY_SUBSCR + on_BINARY_XOR = on_BINARY_SUBSCR + + def on_LOAD_METHOD(self, instr): + self.on_POP_TOP(instr) # Remove the previous as we're loading something from it. + self._stack.append(instr) + + def on_MAKE_FUNCTION(self, instr): + if not IS_PY311_OR_GREATER: + # The qualifier name is no longer put in the stack. + qualname = self._stack.pop() + code_obj_instr = self._stack.pop() + else: + # In 3.11 the code object has a co_qualname which we can use. + qualname = code_obj_instr = self._stack.pop() + + arg = instr.arg + if arg & 0x08: + _func_closure = self._stack.pop() + if arg & 0x04: + _func_annotations = self._stack.pop() + if arg & 0x02: + _func_kwdefaults = self._stack.pop() + if arg & 0x01: + _func_defaults = self._stack.pop() + + call_name = self._getcallname(qualname) + if call_name in ('', '', '', ''): + if isinstance(code_obj_instr.arg, CodeType): + self.func_name_id_to_code_object[_TargetIdHashable(qualname)] = code_obj_instr.arg + self._stack.append(qualname) + + def on_LOAD_FAST(self, instr): + self._stack.append(instr) + + def on_LOAD_ASSERTION_ERROR(self, instr): + self._stack.append(instr) + + on_LOAD_BUILD_CLASS = on_LOAD_FAST + + def on_CALL_METHOD(self, instr): + # pop the actual args + for _ in range(instr.arg): + self._stack.pop() + + func_name_instr = self._stack.pop() + self._handle_call_from_instr(func_name_instr, instr) + + def on_PUSH_NULL(self, instr): + self._stack.append(instr) + + def on_CALL_FUNCTION(self, instr): + arg = instr.arg + + argc = arg & 0xff # positional args + argc += ((arg >> 8) * 2) # keyword args + + # pop the actual args + for _ in range(argc): + try: + self._stack.pop() + except IndexError: + return + + try: + func_name_instr = self._stack.pop() + except IndexError: + return + self._handle_call_from_instr(func_name_instr, instr) + + def on_CALL_FUNCTION_KW(self, instr): + # names of kw args + _names_of_kw_args = self._stack.pop() + + # pop the actual args + arg = instr.arg + + argc = arg & 0xff # positional args + argc += ((arg >> 8) * 2) # keyword args + + for _ in range(argc): + self._stack.pop() + + func_name_instr = self._stack.pop() + self._handle_call_from_instr(func_name_instr, instr) + + def on_CALL_FUNCTION_VAR(self, instr): + # var name + _var_arg = self._stack.pop() + + # pop the actual args + arg = instr.arg + + argc = arg & 0xff # positional args + argc += ((arg >> 8) * 2) # keyword args + + for _ in range(argc): + self._stack.pop() + + func_name_instr = self._stack.pop() + self._handle_call_from_instr(func_name_instr, instr) + + def on_CALL_FUNCTION_VAR_KW(self, instr): + # names of kw args + _names_of_kw_args = self._stack.pop() + + arg = instr.arg + + argc = arg & 0xff # positional args + argc += ((arg >> 8) * 2) # keyword args + + # also pop **kwargs + self._stack.pop() + + # pop the actual args + for _ in range(argc): + self._stack.pop() + + func_name_instr = self._stack.pop() + self._handle_call_from_instr(func_name_instr, instr) + + def on_CALL_FUNCTION_EX(self, instr): + if instr.arg & 0x01: + _kwargs = self._stack.pop() + _callargs = self._stack.pop() + func_name_instr = self._stack.pop() + self._handle_call_from_instr(func_name_instr, instr) + + on_YIELD_VALUE = _no_stack_change + on_GET_AITER = _no_stack_change + on_GET_ANEXT = _no_stack_change + on_END_ASYNC_FOR = _no_stack_change + on_BEFORE_ASYNC_WITH = _no_stack_change + on_SETUP_ASYNC_WITH = _no_stack_change + on_YIELD_FROM = _no_stack_change + on_SETUP_LOOP = _no_stack_change + on_FOR_ITER = _no_stack_change + on_BREAK_LOOP = _no_stack_change + on_JUMP_ABSOLUTE = _no_stack_change + on_RERAISE = _no_stack_change + on_LIST_TO_TUPLE = _no_stack_change + on_CALL_FINALLY = _no_stack_change + on_POP_FINALLY = _no_stack_change + + def on_JUMP_IF_FALSE_OR_POP(self, instr): + try: + self._stack.pop() + except IndexError: + return + + on_JUMP_IF_TRUE_OR_POP = on_JUMP_IF_FALSE_OR_POP + + def on_JUMP_IF_NOT_EXC_MATCH(self, instr): + try: + self._stack.pop() + except IndexError: + return + try: + self._stack.pop() + except IndexError: + return + + def on_ROT_TWO(self, instr): + try: + p0 = self._stack.pop() + except IndexError: + return + + try: + p1 = self._stack.pop() + except: + self._stack.append(p0) + return + + self._stack.append(p0) + self._stack.append(p1) + + def on_ROT_THREE(self, instr): + try: + p0 = self._stack.pop() + except IndexError: + return + + try: + p1 = self._stack.pop() + except: + self._stack.append(p0) + return + + try: + p2 = self._stack.pop() + except: + self._stack.append(p0) + self._stack.append(p1) + return + + self._stack.append(p0) + self._stack.append(p1) + self._stack.append(p2) + + def on_ROT_FOUR(self, instr): + try: + p0 = self._stack.pop() + except IndexError: + return + + try: + p1 = self._stack.pop() + except: + self._stack.append(p0) + return + + try: + p2 = self._stack.pop() + except: + self._stack.append(p0) + self._stack.append(p1) + return + + try: + p3 = self._stack.pop() + except: + self._stack.append(p0) + self._stack.append(p1) + self._stack.append(p2) + return + + self._stack.append(p0) + self._stack.append(p1) + self._stack.append(p2) + self._stack.append(p3) + + def on_BUILD_LIST_FROM_ARG(self, instr): + self._stack.append(instr) + + def on_BUILD_MAP(self, instr): + for _i in range(instr.arg): + self._stack.pop() + self._stack.pop() + self._stack.append(instr) + + def on_BUILD_CONST_KEY_MAP(self, instr): + self.on_POP_TOP(instr) # keys + for _i in range(instr.arg): + self.on_POP_TOP(instr) # value + self._stack.append(instr) + + on_RETURN_VALUE = on_POP_TOP + on_POP_JUMP_IF_FALSE = on_POP_TOP + on_POP_JUMP_IF_TRUE = on_POP_TOP + on_DICT_MERGE = on_POP_TOP + on_LIST_APPEND = on_POP_TOP + on_SET_ADD = on_POP_TOP + on_LIST_EXTEND = on_POP_TOP + on_UNPACK_EX = on_POP_TOP + + # ok: doesn't change the stack (converts top to getiter(top)) + on_GET_ITER = _no_stack_change + on_GET_AWAITABLE = _no_stack_change + on_GET_YIELD_FROM_ITER = _no_stack_change + + def on_RETURN_GENERATOR(self, instr): + self._stack.append(instr) + + on_RETURN_GENERATOR = _no_stack_change + on_RESUME = _no_stack_change + + def on_MAP_ADD(self, instr): + self.on_POP_TOP(instr) + self.on_POP_TOP(instr) + + def on_UNPACK_SEQUENCE(self, instr): + self._stack.pop() + for _i in range(instr.arg): + self._stack.append(instr) + + def on_BUILD_LIST(self, instr): + for _i in range(instr.arg): + self.on_POP_TOP(instr) + self._stack.append(instr) + + on_BUILD_TUPLE = on_BUILD_LIST + on_BUILD_STRING = on_BUILD_LIST + on_BUILD_TUPLE_UNPACK_WITH_CALL = on_BUILD_LIST + on_BUILD_TUPLE_UNPACK = on_BUILD_LIST + on_BUILD_LIST_UNPACK = on_BUILD_LIST + on_BUILD_MAP_UNPACK_WITH_CALL = on_BUILD_LIST + on_BUILD_MAP_UNPACK = on_BUILD_LIST + on_BUILD_SET = on_BUILD_LIST + on_BUILD_SET_UNPACK = on_BUILD_LIST + + on_SETUP_FINALLY = _no_stack_change + on_POP_FINALLY = _no_stack_change + on_BEGIN_FINALLY = _no_stack_change + on_END_FINALLY = _no_stack_change + + def on_RAISE_VARARGS(self, instr): + for _i in range(instr.arg): + self.on_POP_TOP(instr) + + on_POP_BLOCK = _no_stack_change + on_JUMP_FORWARD = _no_stack_change + on_POP_EXCEPT = _no_stack_change + on_SETUP_EXCEPT = _no_stack_change + on_WITH_EXCEPT_START = _no_stack_change + + on_END_FINALLY = _no_stack_change + on_BEGIN_FINALLY = _no_stack_change + on_SETUP_WITH = _no_stack_change + on_WITH_CLEANUP_START = _no_stack_change + on_WITH_CLEANUP_FINISH = _no_stack_change + on_FORMAT_VALUE = _no_stack_change + on_EXTENDED_ARG = _no_stack_change + + def on_INPLACE_ADD(self, instr): + # This would actually pop 2 and leave the value in the stack. + # In a += 1 it pop `a` and `1` and leave the resulting value + # for a load. In our case, let's just pop the `1` and leave the `a` + # instead of leaving the INPLACE_ADD bytecode. + try: + self._stack.pop() + except IndexError: + pass + + on_INPLACE_POWER = on_INPLACE_ADD + on_INPLACE_MULTIPLY = on_INPLACE_ADD + on_INPLACE_MATRIX_MULTIPLY = on_INPLACE_ADD + on_INPLACE_TRUE_DIVIDE = on_INPLACE_ADD + on_INPLACE_FLOOR_DIVIDE = on_INPLACE_ADD + on_INPLACE_MODULO = on_INPLACE_ADD + on_INPLACE_SUBTRACT = on_INPLACE_ADD + on_INPLACE_RSHIFT = on_INPLACE_ADD + on_INPLACE_LSHIFT = on_INPLACE_ADD + on_INPLACE_AND = on_INPLACE_ADD + on_INPLACE_OR = on_INPLACE_ADD + on_INPLACE_XOR = on_INPLACE_ADD + + def on_DUP_TOP(self, instr): + try: + i = self._stack[-1] + except IndexError: + # ok (in the start of block) + self._stack.append(instr) + else: + self._stack.append(i) + + def on_DUP_TOP_TWO(self, instr): + if len(self._stack) == 0: + self._stack.append(instr) + return + + if len(self._stack) == 1: + i = self._stack[-1] + self._stack.append(i) + self._stack.append(instr) + return + + i = self._stack[-1] + j = self._stack[-2] + self._stack.append(j) + self._stack.append(i) + + def on_BUILD_SLICE(self, instr): + for _ in range(instr.arg): + try: + self._stack.pop() + except IndexError: + pass + self._stack.append(instr) + + def on_STORE_SUBSCR(self, instr): + try: + self._stack.pop() + self._stack.pop() + self._stack.pop() + except IndexError: + pass + + def on_DELETE_SUBSCR(self, instr): + try: + self._stack.pop() + self._stack.pop() + except IndexError: + pass + + # Note: on Python 3 this is only found on interactive mode to print the results of + # some evaluation. + on_PRINT_EXPR = on_POP_TOP + + on_UNARY_POSITIVE = _no_stack_change + on_UNARY_NEGATIVE = _no_stack_change + on_UNARY_NOT = _no_stack_change + on_UNARY_INVERT = _no_stack_change + + on_CACHE = _no_stack_change + on_PRECALL = _no_stack_change + + +def _get_smart_step_into_targets(code): + ''' + :return list(Target) + ''' + b = bytecode.Bytecode.from_code(code) + cfg = bytecode_cfg.ControlFlowGraph.from_bytecode(b) + + ret = [] + + for block in cfg: + if DEBUG: + print('\nStart block----') + stack = _StackInterpreter(block) + for instr in block: + try: + func_name = 'on_%s' % (instr.name,) + func = getattr(stack, func_name, None) + + if DEBUG: + if instr.name != 'CACHE': # Filter the ones we don't want to see. + print('\nWill handle: ', instr, '>>', stack._getname(instr), '<<') + print('Current stack:') + for entry in stack._stack: + print(' arg:', stack._getname(entry), '(', entry, ')') + + if func is None: + if STRICT_MODE: + raise AssertionError('%s not found.' % (func_name,)) + else: + continue + func(instr) + except: + if STRICT_MODE: + raise # Error in strict mode. + else: + # In non-strict mode, log it (if in verbose mode) and keep on going. + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 2: + pydev_log.exception('Exception computing step into targets (handled).') + + ret.extend(stack.function_calls) + # No longer considering attr loads as calls (while in theory sometimes it's possible + # that something as `some.attr` can turn out to be a property which could be stepped + # in, it's not that common in practice and can be surprising for users, so, disabling + # step into from stepping into properties). + # ret.extend(stack.load_attrs.values()) + + return ret + + +# Note that the offset is unique within the frame (so, we can use it as the target id). +# Also, as the offset is the instruction offset within the frame, it's possible to +# to inspect the parent frame for frame.f_lasti to know where we actually are (as the +# caller name may not always match the new frame name). +class Variant(object): + __slots__ = ['name', 'is_visited', 'line', 'offset', 'call_order', 'children_variants', 'parent'] + + def __init__(self, name, is_visited, line, offset, call_order, children_variants=None): + self.name = name + self.is_visited = is_visited + self.line = line + self.offset = offset + self.call_order = call_order + self.children_variants = children_variants + self.parent = None + if children_variants: + for variant in children_variants: + variant.parent = self + + def __repr__(self): + ret = [] + for s in self.__slots__: + if s == 'parent': + try: + parent = self.parent + except AttributeError: + ret.append('%s: ' % (s,)) + else: + if parent is None: + ret.append('parent: None') + else: + ret.append('parent: %s (%s)' % (parent.name, parent.offset)) + continue + + if s == 'children_variants': + ret.append('children_variants: %s' % (len(self.children_variants) if self.children_variants else 0)) + continue + + try: + ret.append('%s: %s' % (s, getattr(self, s))) + except AttributeError: + ret.append('%s: ' % (s,)) + return 'Variant(%s)' % ', '.join(ret) + + __str__ = __repr__ + + +def _convert_target_to_variant(target, start_line, end_line, call_order_cache, lasti, base): + name = target.arg + if not isinstance(name, str): + return + if target.lineno > end_line: + return + if target.lineno < start_line: + return + + call_order = call_order_cache.get(name, 0) + 1 + call_order_cache[name] = call_order + is_visited = target.offset <= lasti + + children_targets = target.children_targets + children_variants = None + if children_targets: + children_variants = [ + _convert_target_to_variant(child, start_line, end_line, call_order_cache, lasti, base) + for child in target.children_targets] + + return Variant(name, is_visited, target.lineno - base, target.offset, call_order, children_variants) + + +def calculate_smart_step_into_variants(frame, start_line, end_line, base=0): + """ + Calculate smart step into variants for the given line range. + :param frame: + :type frame: :py:class:`types.FrameType` + :param start_line: + :param end_line: + :return: A list of call names from the first to the last. + :note: it's guaranteed that the offsets appear in order. + :raise: :py:class:`RuntimeError` if failed to parse the bytecode or if dis cannot be used. + """ + variants = [] + code = frame.f_code + lasti = frame.f_lasti + + call_order_cache = {} + if DEBUG: + print('dis.dis:') + if IS_PY311_OR_GREATER: + dis.dis(code, show_caches=False) + else: + dis.dis(code) + + for target in _get_smart_step_into_targets(code): + variant = _convert_target_to_variant(target, start_line, end_line, call_order_cache, lasti, base) + if variant is None: + continue + variants.append(variant) + + return variants + + +def get_smart_step_into_variant_from_frame_offset(frame_f_lasti, variants): + """ + Given the frame.f_lasti, return the related `Variant`. + + :note: if the offset is found before any variant available or no variants are + available, None is returned. + + :rtype: Variant|NoneType + """ + if not variants: + return None + + i = bisect(KeyifyList(variants, lambda entry:entry.offset), frame_f_lasti) + + if i == 0: + return None + + else: + return variants[i - 1] diff --git a/_pydevd_bundle/pydevd_code_to_source.py b/_pydevd_bundle/pydevd_code_to_source.py new file mode 100644 index 0000000..40feb76 --- /dev/null +++ b/_pydevd_bundle/pydevd_code_to_source.py @@ -0,0 +1,611 @@ +""" +Decompiler that can be used with the debugger (where statements correctly represent the +line numbers). + +Note: this is a work in progress / proof of concept / not ready to be used. +""" + +import dis + +from _pydevd_bundle.pydevd_collect_bytecode_info import iter_instructions +from _pydev_bundle import pydev_log +import sys +import inspect +from io import StringIO + + +class _Stack(object): + + def __init__(self): + self._contents = [] + + def push(self, obj): + # print('push', obj) + self._contents.append(obj) + + def pop(self): + return self._contents.pop(-1) + + +INDENT_MARKER = object() +DEDENT_MARKER = object() +_SENTINEL = object() + +DEBUG = False + + +class _Token(object): + + def __init__(self, i_line, instruction=None, tok=_SENTINEL, priority=0, after=None, end_of_line=False): + ''' + :param i_line: + :param instruction: + :param tok: + :param priority: + :param after: + :param end_of_line: + Marker to signal only after all the other tokens have been written. + ''' + self.i_line = i_line + if tok is not _SENTINEL: + self.tok = tok + else: + if instruction is not None: + if inspect.iscode(instruction.argval): + self.tok = '' + else: + self.tok = str(instruction.argval) + else: + raise AssertionError('Either the tok or the instruction is needed.') + self.instruction = instruction + self.priority = priority + self.end_of_line = end_of_line + self._after_tokens = set() + self._after_handler_tokens = set() + if after: + self.mark_after(after) + + def mark_after(self, v): + if isinstance(v, _Token): + self._after_tokens.add(v) + elif isinstance(v, _BaseHandler): + self._after_handler_tokens.add(v) + + else: + raise AssertionError('Unhandled: %s' % (v,)) + + def get_after_tokens(self): + ret = self._after_tokens.copy() + for handler in self._after_handler_tokens: + ret.update(handler.tokens) + return ret + + def __repr__(self): + return 'Token(%s, after: %s)' % (self.tok, self.get_after_tokens()) + + __str__ = __repr__ + + +class _Writer(object): + + def __init__(self): + self.line_to_contents = {} + self.all_tokens = set() + + def get_line(self, line): + lst = self.line_to_contents.get(line) + if lst is None: + lst = self.line_to_contents[line] = [] + return lst + + def indent(self, line): + self.get_line(line).append(INDENT_MARKER) + + def dedent(self, line): + self.get_line(line).append(DEDENT_MARKER) + + def write(self, line, token): + if token in self.all_tokens: + return + self.all_tokens.add(token) + assert isinstance(token, _Token) + lst = self.get_line(line) + lst.append(token) + + +class _BaseHandler(object): + + def __init__(self, i_line, instruction, stack, writer, disassembler): + self.i_line = i_line + self.instruction = instruction + self.stack = stack + self.writer = writer + self.disassembler = disassembler + self.tokens = [] + self._handle() + + def _write_tokens(self): + for token in self.tokens: + self.writer.write(token.i_line, token) + + def _handle(self): + raise NotImplementedError(self) + + def __repr__(self, *args, **kwargs): + try: + return "%s line:%s" % (self.instruction, self.i_line) + except: + return object.__repr__(self) + + __str__ = __repr__ + + +_op_name_to_handler = {} + + +def _register(cls): + _op_name_to_handler[cls.opname] = cls + return cls + + +class _BasePushHandler(_BaseHandler): + + def _handle(self): + self.stack.push(self) + + +class _BaseLoadHandler(_BasePushHandler): + + def _handle(self): + _BasePushHandler._handle(self) + self.tokens = [_Token(self.i_line, self.instruction)] + + +@_register +class _LoadBuildClass(_BasePushHandler): + opname = "LOAD_BUILD_CLASS" + + +@_register +class _LoadConst(_BaseLoadHandler): + opname = "LOAD_CONST" + + +@_register +class _LoadName(_BaseLoadHandler): + opname = "LOAD_NAME" + + +@_register +class _LoadGlobal(_BaseLoadHandler): + opname = "LOAD_GLOBAL" + + +@_register +class _LoadFast(_BaseLoadHandler): + opname = "LOAD_FAST" + + +@_register +class _GetIter(_BaseHandler): + ''' + Implements TOS = iter(TOS). + ''' + opname = "GET_ITER" + iter_target = None + + def _handle(self): + self.iter_target = self.stack.pop() + self.tokens.extend(self.iter_target.tokens) + self.stack.push(self) + + +@_register +class _ForIter(_BaseHandler): + ''' + TOS is an iterator. Call its __next__() method. If this yields a new value, push it on the stack + (leaving the iterator below it). If the iterator indicates it is exhausted TOS is popped, and + the byte code counter is incremented by delta. + ''' + opname = "FOR_ITER" + + iter_in = None + + def _handle(self): + self.iter_in = self.stack.pop() + self.stack.push(self) + + def store_in_name(self, store_name): + for_token = _Token(self.i_line, None, 'for ') + self.tokens.append(for_token) + prev = for_token + + t_name = _Token(store_name.i_line, store_name.instruction, after=prev) + self.tokens.append(t_name) + prev = t_name + + in_token = _Token(store_name.i_line, None, ' in ', after=prev) + self.tokens.append(in_token) + prev = in_token + + max_line = store_name.i_line + if self.iter_in: + for t in self.iter_in.tokens: + t.mark_after(prev) + max_line = max(max_line, t.i_line) + prev = t + self.tokens.extend(self.iter_in.tokens) + + colon_token = _Token(self.i_line, None, ':', after=prev) + self.tokens.append(colon_token) + prev = for_token + + self._write_tokens() + + +@_register +class _StoreName(_BaseHandler): + ''' + Implements name = TOS. namei is the index of name in the attribute co_names of the code object. + The compiler tries to use STORE_FAST or STORE_GLOBAL if possible. + ''' + + opname = "STORE_NAME" + + def _handle(self): + v = self.stack.pop() + + if isinstance(v, _ForIter): + v.store_in_name(self) + else: + if not isinstance(v, _MakeFunction) or v.is_lambda: + line = self.i_line + for t in v.tokens: + line = min(line, t.i_line) + + t_name = _Token(line, self.instruction) + t_equal = _Token(line, None, '=', after=t_name) + + self.tokens.append(t_name) + self.tokens.append(t_equal) + + for t in v.tokens: + t.mark_after(t_equal) + self.tokens.extend(v.tokens) + + self._write_tokens() + + +@_register +class _ReturnValue(_BaseHandler): + """ + Returns with TOS to the caller of the function. + """ + + opname = "RETURN_VALUE" + + def _handle(self): + v = self.stack.pop() + return_token = _Token(self.i_line, None, 'return ', end_of_line=True) + self.tokens.append(return_token) + for token in v.tokens: + token.mark_after(return_token) + self.tokens.extend(v.tokens) + + self._write_tokens() + + +@_register +class _CallFunction(_BaseHandler): + """ + + CALL_FUNCTION(argc) + + Calls a callable object with positional arguments. argc indicates the number of positional + arguments. The top of the stack contains positional arguments, with the right-most argument + on top. Below the arguments is a callable object to call. CALL_FUNCTION pops all arguments + and the callable object off the stack, calls the callable object with those arguments, and + pushes the return value returned by the callable object. + + Changed in version 3.6: This opcode is used only for calls with positional arguments. + + """ + + opname = "CALL_FUNCTION" + + def _handle(self): + args = [] + for _i in range(self.instruction.argval + 1): + arg = self.stack.pop() + args.append(arg) + it = reversed(args) + name = next(it) + max_line = name.i_line + for t in name.tokens: + self.tokens.append(t) + + tok_open_parens = _Token(name.i_line, None, '(', after=name) + self.tokens.append(tok_open_parens) + + prev = tok_open_parens + for i, arg in enumerate(it): + for t in arg.tokens: + t.mark_after(name) + t.mark_after(prev) + max_line = max(max_line, t.i_line) + self.tokens.append(t) + prev = arg + + if i > 0: + comma_token = _Token(prev.i_line, None, ',', after=prev) + self.tokens.append(comma_token) + prev = comma_token + + tok_close_parens = _Token(max_line, None, ')', after=prev) + self.tokens.append(tok_close_parens) + + self._write_tokens() + + self.stack.push(self) + + +@_register +class _MakeFunctionPy3(_BaseHandler): + """ + Pushes a new function object on the stack. From bottom to top, the consumed stack must consist + of values if the argument carries a specified flag value + + 0x01 a tuple of default values for positional-only and positional-or-keyword parameters in positional order + + 0x02 a dictionary of keyword-only parameters' default values + + 0x04 an annotation dictionary + + 0x08 a tuple containing cells for free variables, making a closure + + the code associated with the function (at TOS1) + + the qualified name of the function (at TOS) + """ + + opname = "MAKE_FUNCTION" + is_lambda = False + + def _handle(self): + stack = self.stack + self.qualified_name = stack.pop() + self.code = stack.pop() + + default_node = None + if self.instruction.argval & 0x01: + default_node = stack.pop() + + is_lambda = self.is_lambda = '' in [x.tok for x in self.qualified_name.tokens] + + if not is_lambda: + def_token = _Token(self.i_line, None, 'def ') + self.tokens.append(def_token) + + for token in self.qualified_name.tokens: + self.tokens.append(token) + if not is_lambda: + token.mark_after(def_token) + prev = token + + open_parens_token = _Token(self.i_line, None, '(', after=prev) + self.tokens.append(open_parens_token) + prev = open_parens_token + + code = self.code.instruction.argval + + if default_node: + defaults = ([_SENTINEL] * (len(code.co_varnames) - len(default_node.instruction.argval))) + list(default_node.instruction.argval) + else: + defaults = [_SENTINEL] * len(code.co_varnames) + + for i, arg in enumerate(code.co_varnames): + if i > 0: + comma_token = _Token(prev.i_line, None, ', ', after=prev) + self.tokens.append(comma_token) + prev = comma_token + + arg_token = _Token(self.i_line, None, arg, after=prev) + self.tokens.append(arg_token) + + default = defaults[i] + if default is not _SENTINEL: + eq_token = _Token(default_node.i_line, None, '=', after=prev) + self.tokens.append(eq_token) + prev = eq_token + + default_token = _Token(default_node.i_line, None, str(default), after=prev) + self.tokens.append(default_token) + prev = default_token + + tok_close_parens = _Token(prev.i_line, None, '):', after=prev) + self.tokens.append(tok_close_parens) + + self._write_tokens() + + stack.push(self) + self.writer.indent(prev.i_line + 1) + self.writer.dedent(max(self.disassembler.merge_code(code))) + + +_MakeFunction = _MakeFunctionPy3 + + +def _print_after_info(line_contents, stream=None): + if stream is None: + stream = sys.stdout + for token in line_contents: + after_tokens = token.get_after_tokens() + if after_tokens: + s = '%s after: %s\n' % ( + repr(token.tok), + ('"' + '", "'.join(t.tok for t in token.get_after_tokens()) + '"')) + stream.write(s) + else: + stream.write('%s (NO REQUISITES)' % repr(token.tok)) + + +def _compose_line_contents(line_contents, previous_line_tokens): + lst = [] + handled = set() + + add_to_end_of_line = [] + delete_indexes = [] + for i, token in enumerate(line_contents): + if token.end_of_line: + add_to_end_of_line.append(token) + delete_indexes.append(i) + for i in reversed(delete_indexes): + del line_contents[i] + del delete_indexes + + while line_contents: + added = False + delete_indexes = [] + + for i, token in enumerate(line_contents): + after_tokens = token.get_after_tokens() + for after in after_tokens: + if after not in handled and after not in previous_line_tokens: + break + else: + added = True + previous_line_tokens.add(token) + handled.add(token) + lst.append(token.tok) + delete_indexes.append(i) + + for i in reversed(delete_indexes): + del line_contents[i] + + if not added: + if add_to_end_of_line: + line_contents.extend(add_to_end_of_line) + del add_to_end_of_line[:] + continue + + # Something is off, let's just add as is. + for token in line_contents: + if token not in handled: + lst.append(token.tok) + + stream = StringIO() + _print_after_info(line_contents, stream) + pydev_log.critical('Error. After markers are not correct:\n%s', stream.getvalue()) + break + return ''.join(lst) + + +class _PyCodeToSource(object): + + def __init__(self, co, memo=None): + if memo is None: + memo = {} + self.memo = memo + self.co = co + self.instructions = list(iter_instructions(co)) + self.stack = _Stack() + self.writer = _Writer() + + def _process_next(self, i_line): + instruction = self.instructions.pop(0) + handler_class = _op_name_to_handler.get(instruction.opname) + if handler_class is not None: + s = handler_class(i_line, instruction, self.stack, self.writer, self) + if DEBUG: + print(s) + + else: + if DEBUG: + print("UNHANDLED", instruction) + + def build_line_to_contents(self): + co = self.co + + op_offset_to_line = dict(dis.findlinestarts(co)) + curr_line_index = 0 + + instructions = self.instructions + while instructions: + instruction = instructions[0] + new_line_index = op_offset_to_line.get(instruction.offset) + if new_line_index is not None: + if new_line_index is not None: + curr_line_index = new_line_index + + self._process_next(curr_line_index) + return self.writer.line_to_contents + + def merge_code(self, code): + if DEBUG: + print('merge code ----') + # for d in dir(code): + # if not d.startswith('_'): + # print(d, getattr(code, d)) + line_to_contents = _PyCodeToSource(code, self.memo).build_line_to_contents() + lines = [] + for line, contents in sorted(line_to_contents.items()): + lines.append(line) + self.writer.get_line(line).extend(contents) + if DEBUG: + print('end merge code ----') + return lines + + def disassemble(self): + show_lines = False + line_to_contents = self.build_line_to_contents() + stream = StringIO() + last_line = 0 + indent = '' + previous_line_tokens = set() + for i_line, contents in sorted(line_to_contents.items()): + while last_line < i_line - 1: + if show_lines: + stream.write(u"%s.\n" % (last_line + 1,)) + else: + stream.write(u"\n") + last_line += 1 + + line_contents = [] + dedents_found = 0 + for part in contents: + if part is INDENT_MARKER: + if DEBUG: + print('found indent', i_line) + indent += ' ' + continue + if part is DEDENT_MARKER: + if DEBUG: + print('found dedent', i_line) + dedents_found += 1 + continue + line_contents.append(part) + + s = indent + _compose_line_contents(line_contents, previous_line_tokens) + if show_lines: + stream.write(u"%s. %s\n" % (i_line, s)) + else: + stream.write(u"%s\n" % s) + + if dedents_found: + indent = indent[:-(4 * dedents_found)] + last_line = i_line + + return stream.getvalue() + + +def code_obj_to_source(co): + """ + Converts a code object to source code to provide a suitable representation for the compiler when + the actual source code is not found. + + This is a work in progress / proof of concept / not ready to be used. + """ + ret = _PyCodeToSource(co).disassemble() + if DEBUG: + print(ret) + return ret diff --git a/_pydevd_bundle/pydevd_collect_bytecode_info.py b/_pydevd_bundle/pydevd_collect_bytecode_info.py new file mode 100644 index 0000000..711f7dd --- /dev/null +++ b/_pydevd_bundle/pydevd_collect_bytecode_info.py @@ -0,0 +1,925 @@ +import dis +import inspect +import sys +from collections import namedtuple + +from _pydev_bundle import pydev_log +from opcode import (EXTENDED_ARG, HAVE_ARGUMENT, cmp_op, hascompare, hasconst, + hasfree, hasjrel, haslocal, hasname, opname) + +from io import StringIO + + +class TryExceptInfo(object): + + def __init__(self, try_line, ignore=False): + ''' + :param try_line: + :param ignore: + Usually we should ignore any block that's not a try..except + (this can happen for finally blocks, with statements, etc, for + which we create temporary entries). + ''' + self.try_line = try_line + self.ignore = ignore + self.except_line = -1 + self.except_end_line = -1 + self.raise_lines_in_except = [] + + # Note: these may not be available if generated from source instead of bytecode. + self.except_bytecode_offset = -1 + self.except_end_bytecode_offset = -1 + + def is_line_in_try_block(self, line): + return self.try_line <= line < self.except_line + + def is_line_in_except_block(self, line): + return self.except_line <= line <= self.except_end_line + + def __str__(self): + lst = [ + '{try:', + str(self.try_line), + ' except ', + str(self.except_line), + ' end block ', + str(self.except_end_line), + ] + if self.raise_lines_in_except: + lst.append(' raises: %s' % (', '.join(str(x) for x in self.raise_lines_in_except),)) + + lst.append('}') + return ''.join(lst) + + __repr__ = __str__ + + +class ReturnInfo(object): + + def __init__(self, return_line): + self.return_line = return_line + + def __str__(self): + return '{return: %s}' % (self.return_line,) + + __repr__ = __str__ + + +def _get_line(op_offset_to_line, op_offset, firstlineno, search=False): + op_offset_original = op_offset + while op_offset >= 0: + ret = op_offset_to_line.get(op_offset) + if ret is not None: + return ret - firstlineno + if not search: + return ret + else: + op_offset -= 1 + raise AssertionError('Unable to find line for offset: %s.Info: %s' % ( + op_offset_original, op_offset_to_line)) + + +def debug(s): + pass + + +_Instruction = namedtuple('_Instruction', 'opname, opcode, starts_line, argval, is_jump_target, offset, argrepr') + + +def _iter_as_bytecode_as_instructions_py2(co): + code = co.co_code + op_offset_to_line = dict(dis.findlinestarts(co)) + labels = set(dis.findlabels(code)) + bytecode_len = len(code) + i = 0 + extended_arg = 0 + free = None + + op_to_name = opname + + while i < bytecode_len: + c = code[i] + op = ord(c) + is_jump_target = i in labels + + curr_op_name = op_to_name[op] + initial_bytecode_offset = i + + i = i + 1 + if op < HAVE_ARGUMENT: + yield _Instruction(curr_op_name, op, _get_line(op_offset_to_line, initial_bytecode_offset, 0), None, is_jump_target, initial_bytecode_offset, '') + + else: + oparg = ord(code[i]) + ord(code[i + 1]) * 256 + extended_arg + + extended_arg = 0 + i = i + 2 + if op == EXTENDED_ARG: + extended_arg = oparg * 65536 + + if op in hasconst: + yield _Instruction(curr_op_name, op, _get_line(op_offset_to_line, initial_bytecode_offset, 0), co.co_consts[oparg], is_jump_target, initial_bytecode_offset, repr(co.co_consts[oparg])) + elif op in hasname: + yield _Instruction(curr_op_name, op, _get_line(op_offset_to_line, initial_bytecode_offset, 0), co.co_names[oparg], is_jump_target, initial_bytecode_offset, str(co.co_names[oparg])) + elif op in hasjrel: + argval = i + oparg + yield _Instruction(curr_op_name, op, _get_line(op_offset_to_line, initial_bytecode_offset, 0), argval, is_jump_target, initial_bytecode_offset, "to " + repr(argval)) + elif op in haslocal: + yield _Instruction(curr_op_name, op, _get_line(op_offset_to_line, initial_bytecode_offset, 0), co.co_varnames[oparg], is_jump_target, initial_bytecode_offset, str(co.co_varnames[oparg])) + elif op in hascompare: + yield _Instruction(curr_op_name, op, _get_line(op_offset_to_line, initial_bytecode_offset, 0), cmp_op[oparg], is_jump_target, initial_bytecode_offset, cmp_op[oparg]) + elif op in hasfree: + if free is None: + free = co.co_cellvars + co.co_freevars + yield _Instruction(curr_op_name, op, _get_line(op_offset_to_line, initial_bytecode_offset, 0), free[oparg], is_jump_target, initial_bytecode_offset, str(free[oparg])) + else: + yield _Instruction(curr_op_name, op, _get_line(op_offset_to_line, initial_bytecode_offset, 0), oparg, is_jump_target, initial_bytecode_offset, str(oparg)) + + +def iter_instructions(co): + if sys.version_info[0] < 3: + iter_in = _iter_as_bytecode_as_instructions_py2(co) + else: + iter_in = dis.Bytecode(co) + iter_in = list(iter_in) + + bytecode_to_instruction = {} + for instruction in iter_in: + bytecode_to_instruction[instruction.offset] = instruction + + if iter_in: + for instruction in iter_in: + yield instruction + + +def collect_return_info(co, use_func_first_line=False): + if not hasattr(co, 'co_lnotab'): + return [] + + if use_func_first_line: + firstlineno = co.co_firstlineno + else: + firstlineno = 0 + + lst = [] + op_offset_to_line = dict(dis.findlinestarts(co)) + for instruction in iter_instructions(co): + curr_op_name = instruction.opname + if curr_op_name == 'RETURN_VALUE': + lst.append(ReturnInfo(_get_line(op_offset_to_line, instruction.offset, firstlineno, search=True))) + + return lst + + +if sys.version_info[:2] <= (3, 9): + + class _TargetInfo(object): + + def __init__(self, except_end_instruction, jump_if_not_exc_instruction=None): + self.except_end_instruction = except_end_instruction + self.jump_if_not_exc_instruction = jump_if_not_exc_instruction + + def __str__(self): + msg = ['_TargetInfo('] + msg.append(self.except_end_instruction.opname) + if self.jump_if_not_exc_instruction: + msg.append(' - ') + msg.append(self.jump_if_not_exc_instruction.opname) + msg.append('(') + msg.append(str(self.jump_if_not_exc_instruction.argval)) + msg.append(')') + msg.append(')') + return ''.join(msg) + + def _get_except_target_info(instructions, exception_end_instruction_index, offset_to_instruction_idx): + next_3 = [j_instruction.opname for j_instruction in instructions[exception_end_instruction_index:exception_end_instruction_index + 3]] + # print('next_3:', [(j_instruction.opname, j_instruction.argval) for j_instruction in instructions[exception_end_instruction_index:exception_end_instruction_index + 3]]) + if next_3 == ['POP_TOP', 'POP_TOP', 'POP_TOP']: # try..except without checking exception. + try: + jump_instruction = instructions[exception_end_instruction_index - 1] + if jump_instruction.opname not in ('JUMP_FORWARD', 'JUMP_ABSOLUTE'): + return None + except IndexError: + pass + + if jump_instruction.opname == 'JUMP_ABSOLUTE': + # On latest versions of Python 3 the interpreter has a go-backwards step, + # used to show the initial line of a for/while, etc (which is this + # JUMP_ABSOLUTE)... we're not really interested in it, but rather on where + # it points to. + except_end_instruction = instructions[offset_to_instruction_idx[jump_instruction.argval]] + idx = offset_to_instruction_idx[except_end_instruction.argval] + # Search for the POP_EXCEPT which should be at the end of the block. + for pop_except_instruction in reversed(instructions[:idx]): + if pop_except_instruction.opname == 'POP_EXCEPT': + except_end_instruction = pop_except_instruction + return _TargetInfo(except_end_instruction) + else: + return None # i.e.: Continue outer loop + + else: + # JUMP_FORWARD + i = offset_to_instruction_idx[jump_instruction.argval] + try: + # i.e.: the jump is to the instruction after the block finishes (so, we need to + # get the previous instruction as that should be the place where the exception + # block finishes). + except_end_instruction = instructions[i - 1] + except: + pydev_log.critical('Error when computing try..except block end.') + return None + return _TargetInfo(except_end_instruction) + + elif next_3 and next_3[0] == 'DUP_TOP': # try..except AssertionError. + iter_in = instructions[exception_end_instruction_index + 1:] + for j, jump_if_not_exc_instruction in enumerate(iter_in): + if jump_if_not_exc_instruction.opname == 'JUMP_IF_NOT_EXC_MATCH': + # Python 3.9 + except_end_instruction = instructions[offset_to_instruction_idx[jump_if_not_exc_instruction.argval]] + return _TargetInfo(except_end_instruction, jump_if_not_exc_instruction) + + elif jump_if_not_exc_instruction.opname == 'COMPARE_OP' and jump_if_not_exc_instruction.argval == 'exception match': + # Python 3.8 and before + try: + next_instruction = iter_in[j + 1] + except: + continue + if next_instruction.opname == 'POP_JUMP_IF_FALSE': + except_end_instruction = instructions[offset_to_instruction_idx[next_instruction.argval]] + return _TargetInfo(except_end_instruction, next_instruction) + else: + return None # i.e.: Continue outer loop + + else: + # i.e.: we're not interested in try..finally statements, only try..except. + return None + + def collect_try_except_info(co, use_func_first_line=False): + # We no longer have 'END_FINALLY', so, we need to do things differently in Python 3.9 + if not hasattr(co, 'co_lnotab'): + return [] + + if use_func_first_line: + firstlineno = co.co_firstlineno + else: + firstlineno = 0 + + try_except_info_lst = [] + + op_offset_to_line = dict(dis.findlinestarts(co)) + + offset_to_instruction_idx = {} + + instructions = list(iter_instructions(co)) + + for i, instruction in enumerate(instructions): + offset_to_instruction_idx[instruction.offset] = i + + for i, instruction in enumerate(instructions): + curr_op_name = instruction.opname + if curr_op_name in ('SETUP_FINALLY', 'SETUP_EXCEPT'): # SETUP_EXCEPT before Python 3.8, SETUP_FINALLY Python 3.8 onwards. + exception_end_instruction_index = offset_to_instruction_idx[instruction.argval] + + jump_instruction = instructions[exception_end_instruction_index - 1] + if jump_instruction.opname not in ('JUMP_FORWARD', 'JUMP_ABSOLUTE'): + continue + + except_end_instruction = None + indexes_checked = set() + indexes_checked.add(exception_end_instruction_index) + target_info = _get_except_target_info(instructions, exception_end_instruction_index, offset_to_instruction_idx) + while target_info is not None: + # Handle a try..except..except..except. + jump_instruction = target_info.jump_if_not_exc_instruction + except_end_instruction = target_info.except_end_instruction + + if jump_instruction is not None: + check_index = offset_to_instruction_idx[jump_instruction.argval] + if check_index in indexes_checked: + break + indexes_checked.add(check_index) + target_info = _get_except_target_info(instructions, check_index, offset_to_instruction_idx) + else: + break + + if except_end_instruction is not None: + try_except_info = TryExceptInfo( + _get_line(op_offset_to_line, instruction.offset, firstlineno, search=True), + ignore=False + ) + try_except_info.except_bytecode_offset = instruction.argval + try_except_info.except_line = _get_line( + op_offset_to_line, + try_except_info.except_bytecode_offset, + firstlineno, + search=True + ) + + try_except_info.except_end_bytecode_offset = except_end_instruction.offset + try_except_info.except_end_line = _get_line(op_offset_to_line, except_end_instruction.offset, firstlineno, search=True) + try_except_info_lst.append(try_except_info) + + for raise_instruction in instructions[i:offset_to_instruction_idx[try_except_info.except_end_bytecode_offset]]: + if raise_instruction.opname == 'RAISE_VARARGS': + if raise_instruction.argval == 0: + try_except_info.raise_lines_in_except.append( + _get_line(op_offset_to_line, raise_instruction.offset, firstlineno, search=True)) + + return try_except_info_lst + +elif sys.version_info[:2] == (3, 10): + + class _TargetInfo(object): + + def __init__(self, except_end_instruction, jump_if_not_exc_instruction=None): + self.except_end_instruction = except_end_instruction + self.jump_if_not_exc_instruction = jump_if_not_exc_instruction + + def __str__(self): + msg = ['_TargetInfo('] + msg.append(self.except_end_instruction.opname) + if self.jump_if_not_exc_instruction: + msg.append(' - ') + msg.append(self.jump_if_not_exc_instruction.opname) + msg.append('(') + msg.append(str(self.jump_if_not_exc_instruction.argval)) + msg.append(')') + msg.append(')') + return ''.join(msg) + + def _get_except_target_info(instructions, exception_end_instruction_index, offset_to_instruction_idx): + next_3 = [j_instruction.opname for j_instruction in instructions[exception_end_instruction_index:exception_end_instruction_index + 3]] + # print('next_3:', [(j_instruction.opname, j_instruction.argval) for j_instruction in instructions[exception_end_instruction_index:exception_end_instruction_index + 3]]) + if next_3 == ['POP_TOP', 'POP_TOP', 'POP_TOP']: # try..except without checking exception. + # Previously there was a jump which was able to point where the exception would end. This + # is no longer true, now a bare except doesn't really have any indication in the bytecode + # where the end would be expected if the exception wasn't raised, so, we just blindly + # search for a POP_EXCEPT from the current position. + for pop_except_instruction in instructions[exception_end_instruction_index + 3:]: + if pop_except_instruction.opname == 'POP_EXCEPT': + except_end_instruction = pop_except_instruction + return _TargetInfo(except_end_instruction) + + elif next_3 and next_3[0] == 'DUP_TOP': # try..except AssertionError. + iter_in = instructions[exception_end_instruction_index + 1:] + for jump_if_not_exc_instruction in iter_in: + if jump_if_not_exc_instruction.opname == 'JUMP_IF_NOT_EXC_MATCH': + # Python 3.9 + except_end_instruction = instructions[offset_to_instruction_idx[jump_if_not_exc_instruction.argval]] + return _TargetInfo(except_end_instruction, jump_if_not_exc_instruction) + else: + return None # i.e.: Continue outer loop + + else: + # i.e.: we're not interested in try..finally statements, only try..except. + return None + + def collect_try_except_info(co, use_func_first_line=False): + # We no longer have 'END_FINALLY', so, we need to do things differently in Python 3.9 + if not hasattr(co, 'co_lnotab'): + return [] + + if use_func_first_line: + firstlineno = co.co_firstlineno + else: + firstlineno = 0 + + try_except_info_lst = [] + + op_offset_to_line = dict(dis.findlinestarts(co)) + + offset_to_instruction_idx = {} + + instructions = list(iter_instructions(co)) + + for i, instruction in enumerate(instructions): + offset_to_instruction_idx[instruction.offset] = i + + for i, instruction in enumerate(instructions): + curr_op_name = instruction.opname + if curr_op_name == 'SETUP_FINALLY': + exception_end_instruction_index = offset_to_instruction_idx[instruction.argval] + + jump_instruction = instructions[exception_end_instruction_index] + if jump_instruction.opname != 'DUP_TOP': + continue + + except_end_instruction = None + indexes_checked = set() + indexes_checked.add(exception_end_instruction_index) + target_info = _get_except_target_info(instructions, exception_end_instruction_index, offset_to_instruction_idx) + while target_info is not None: + # Handle a try..except..except..except. + jump_instruction = target_info.jump_if_not_exc_instruction + except_end_instruction = target_info.except_end_instruction + + if jump_instruction is not None: + check_index = offset_to_instruction_idx[jump_instruction.argval] + if check_index in indexes_checked: + break + indexes_checked.add(check_index) + target_info = _get_except_target_info(instructions, check_index, offset_to_instruction_idx) + else: + break + + if except_end_instruction is not None: + try_except_info = TryExceptInfo( + _get_line(op_offset_to_line, instruction.offset, firstlineno, search=True), + ignore=False + ) + try_except_info.except_bytecode_offset = instruction.argval + try_except_info.except_line = _get_line( + op_offset_to_line, + try_except_info.except_bytecode_offset, + firstlineno, + search=True + ) + + try_except_info.except_end_bytecode_offset = except_end_instruction.offset + + # On Python 3.10 the final line of the except end isn't really correct, rather, + # it's engineered to be the same line of the except and not the end line of the + # block, so, the approach taken is to search for the biggest line between the + # except and the end instruction + except_end_line = -1 + start_i = offset_to_instruction_idx[try_except_info.except_bytecode_offset] + end_i = offset_to_instruction_idx[except_end_instruction.offset] + for instruction in instructions[start_i: end_i + 1]: + found_at_line = op_offset_to_line.get(instruction.offset) + if found_at_line is not None and found_at_line > except_end_line: + except_end_line = found_at_line + try_except_info.except_end_line = except_end_line - firstlineno + + try_except_info_lst.append(try_except_info) + + for raise_instruction in instructions[i:offset_to_instruction_idx[try_except_info.except_end_bytecode_offset]]: + if raise_instruction.opname == 'RAISE_VARARGS': + if raise_instruction.argval == 0: + try_except_info.raise_lines_in_except.append( + _get_line(op_offset_to_line, raise_instruction.offset, firstlineno, search=True)) + + return try_except_info_lst + +elif sys.version_info[:2] >= (3, 11): + + def collect_try_except_info(co, use_func_first_line=False): + ''' + Note: if the filename is available and we can get the source, + `collect_try_except_info_from_source` is preferred (this is kept as + a fallback for cases where sources aren't available). + ''' + return [] + +import ast as ast_module + + +class _Visitor(ast_module.NodeVisitor): + + def __init__(self): + self.try_except_infos = [] + self._stack = [] + self._in_except_stack = [] + self.max_line = -1 + + def generic_visit(self, node): + if hasattr(node, 'lineno'): + if node.lineno > self.max_line: + self.max_line = node.lineno + return ast_module.NodeVisitor.generic_visit(self, node) + + def visit_Try(self, node): + info = TryExceptInfo(node.lineno, ignore=True) + self._stack.append(info) + self.generic_visit(node) + assert info is self._stack.pop() + if not info.ignore: + self.try_except_infos.insert(0, info) + + if sys.version_info[0] < 3: + visit_TryExcept = visit_Try + + def visit_ExceptHandler(self, node): + info = self._stack[-1] + info.ignore = False + if info.except_line == -1: + info.except_line = node.lineno + self._in_except_stack.append(info) + self.generic_visit(node) + if hasattr(node, 'end_lineno'): + info.except_end_line = node.end_lineno + else: + info.except_end_line = self.max_line + self._in_except_stack.pop() + + if sys.version_info[0] >= 3: + + def visit_Raise(self, node): + for info in self._in_except_stack: + if node.exc is None: + info.raise_lines_in_except.append(node.lineno) + self.generic_visit(node) + + else: + + def visit_Raise(self, node): + for info in self._in_except_stack: + if node.type is None and node.tback is None: + info.raise_lines_in_except.append(node.lineno) + self.generic_visit(node) + + +def collect_try_except_info_from_source(filename): + with open(filename, 'rb') as stream: + contents = stream.read() + return collect_try_except_info_from_contents(contents, filename) + + +def collect_try_except_info_from_contents(contents, filename=''): + ast = ast_module.parse(contents, filename) + visitor = _Visitor() + visitor.visit(ast) + return visitor.try_except_infos + + +RESTART_FROM_LOOKAHEAD = object() +SEPARATOR = object() + + +class _MsgPart(object): + + def __init__(self, line, tok): + assert line >= 0 + self.line = line + self.tok = tok + + @classmethod + def add_to_line_to_contents(cls, obj, line_to_contents, line=None): + if isinstance(obj, (list, tuple)): + for o in obj: + cls.add_to_line_to_contents(o, line_to_contents, line=line) + return + + if isinstance(obj, str): + assert line is not None + line = int(line) + lst = line_to_contents.setdefault(line, []) + lst.append(obj) + return + + if isinstance(obj, _MsgPart): + if isinstance(obj.tok, (list, tuple)): + cls.add_to_line_to_contents(obj.tok, line_to_contents, line=obj.line) + return + + if isinstance(obj.tok, str): + lst = line_to_contents.setdefault(obj.line, []) + lst.append(obj.tok) + return + + raise AssertionError("Unhandled: %" % (obj,)) + + +class _Disassembler(object): + + def __init__(self, co, firstlineno, level=0): + self.co = co + self.firstlineno = firstlineno + self.level = level + self.instructions = list(iter_instructions(co)) + op_offset_to_line = self.op_offset_to_line = dict(dis.findlinestarts(co)) + + # Update offsets so that all offsets have the line index (and update it based on + # the passed firstlineno). + line_index = co.co_firstlineno - firstlineno + for instruction in self.instructions: + new_line_index = op_offset_to_line.get(instruction.offset) + if new_line_index is not None: + line_index = new_line_index - firstlineno + op_offset_to_line[instruction.offset] = line_index + else: + op_offset_to_line[instruction.offset] = line_index + + BIG_LINE_INT = 9999999 + SMALL_LINE_INT = -1 + + def min_line(self, *args): + m = self.BIG_LINE_INT + for arg in args: + if isinstance(arg, (list, tuple)): + m = min(m, self.min_line(*arg)) + + elif isinstance(arg, _MsgPart): + m = min(m, arg.line) + + elif hasattr(arg, 'offset'): + m = min(m, self.op_offset_to_line[arg.offset]) + return m + + def max_line(self, *args): + m = self.SMALL_LINE_INT + for arg in args: + if isinstance(arg, (list, tuple)): + m = max(m, self.max_line(*arg)) + + elif isinstance(arg, _MsgPart): + m = max(m, arg.line) + + elif hasattr(arg, 'offset'): + m = max(m, self.op_offset_to_line[arg.offset]) + return m + + def _lookahead(self): + ''' + This handles and converts some common constructs from bytecode to actual source code. + + It may change the list of instructions. + ''' + msg = self._create_msg_part + found = [] + fullrepr = None + + # Collect all the load instructions + for next_instruction in self.instructions: + if next_instruction.opname in ('LOAD_GLOBAL', 'LOAD_FAST', 'LOAD_CONST', 'LOAD_NAME'): + found.append(next_instruction) + else: + break + + if not found: + return None + + if next_instruction.opname == 'LOAD_ATTR': + prev_instruction = found[-1] + # Remove the current LOAD_ATTR + assert self.instructions.pop(len(found)) is next_instruction + + # Add the LOAD_ATTR to the previous LOAD + self.instructions[len(found) - 1] = _Instruction( + prev_instruction.opname, + prev_instruction.opcode, + prev_instruction.starts_line, + prev_instruction.argval, + False, # prev_instruction.is_jump_target, + prev_instruction.offset, + ( + msg(prev_instruction), + msg(prev_instruction, '.'), + msg(next_instruction) + ), + ) + return RESTART_FROM_LOOKAHEAD + + if next_instruction.opname in ('CALL_FUNCTION', 'PRECALL'): + if len(found) == next_instruction.argval + 1: + force_restart = False + delta = 0 + else: + force_restart = True + if len(found) > next_instruction.argval + 1: + delta = len(found) - (next_instruction.argval + 1) + else: + return None # This is odd + + del_upto = delta + next_instruction.argval + 2 # +2 = NAME / CALL_FUNCTION + if next_instruction.opname == 'PRECALL': + del_upto += 1 # Also remove the CALL right after the PRECALL. + del self.instructions[delta:del_upto] + + found = iter(found[delta:]) + call_func = next(found) + args = list(found) + fullrepr = [ + msg(call_func), + msg(call_func, '('), + ] + prev = call_func + for i, arg in enumerate(args): + if i > 0: + fullrepr.append(msg(prev, ', ')) + prev = arg + fullrepr.append(msg(arg)) + + fullrepr.append(msg(prev, ')')) + + if force_restart: + self.instructions.insert(delta, _Instruction( + call_func.opname, + call_func.opcode, + call_func.starts_line, + call_func.argval, + False, # call_func.is_jump_target, + call_func.offset, + tuple(fullrepr), + )) + return RESTART_FROM_LOOKAHEAD + + elif next_instruction.opname == 'BUILD_TUPLE': + + if len(found) == next_instruction.argval: + force_restart = False + delta = 0 + else: + force_restart = True + if len(found) > next_instruction.argval: + delta = len(found) - (next_instruction.argval) + else: + return None # This is odd + + del self.instructions[delta:delta + next_instruction.argval + 1] # +1 = BUILD_TUPLE + + found = iter(found[delta:]) + + args = [instruction for instruction in found] + if args: + first_instruction = args[0] + else: + first_instruction = next_instruction + prev = first_instruction + + fullrepr = [] + fullrepr.append(msg(prev, '(')) + for i, arg in enumerate(args): + if i > 0: + fullrepr.append(msg(prev, ', ')) + prev = arg + fullrepr.append(msg(arg)) + + fullrepr.append(msg(prev, ')')) + + if force_restart: + self.instructions.insert(delta, _Instruction( + first_instruction.opname, + first_instruction.opcode, + first_instruction.starts_line, + first_instruction.argval, + False, # first_instruction.is_jump_target, + first_instruction.offset, + tuple(fullrepr), + )) + return RESTART_FROM_LOOKAHEAD + + if fullrepr is not None and self.instructions: + if self.instructions[0].opname == 'POP_TOP': + self.instructions.pop(0) + + if self.instructions[0].opname in ('STORE_FAST', 'STORE_NAME'): + next_instruction = self.instructions.pop(0) + return msg(next_instruction), msg(next_instruction, ' = '), fullrepr + + if self.instructions[0].opname == 'RETURN_VALUE': + next_instruction = self.instructions.pop(0) + return msg(next_instruction, 'return ', line=self.min_line(next_instruction, fullrepr)), fullrepr + + return fullrepr + + def _decorate_jump_target(self, instruction, instruction_repr): + if instruction.is_jump_target: + return ('|', str(instruction.offset), '|', instruction_repr) + + return instruction_repr + + def _create_msg_part(self, instruction, tok=None, line=None): + dec = self._decorate_jump_target + if line is None or line in (self.BIG_LINE_INT, self.SMALL_LINE_INT): + line = self.op_offset_to_line[instruction.offset] + + argrepr = instruction.argrepr + if isinstance(argrepr, str) and argrepr.startswith('NULL + '): + argrepr = argrepr[7:] + return _MsgPart( + line, tok if tok is not None else dec(instruction, argrepr)) + + def _next_instruction_to_str(self, line_to_contents): + # indent = '' + # if self.level > 0: + # indent += ' ' * self.level + # print(indent, 'handle', self.instructions[0]) + + if self.instructions: + ret = self._lookahead() + if ret: + return ret + + msg = self._create_msg_part + + instruction = self.instructions.pop(0) + + if instruction.opname in 'RESUME': + return None + + if instruction.opname in ('LOAD_GLOBAL', 'LOAD_FAST', 'LOAD_CONST', 'LOAD_NAME'): + next_instruction = self.instructions[0] + if next_instruction.opname in ('STORE_FAST', 'STORE_NAME'): + self.instructions.pop(0) + return ( + msg(next_instruction), + msg(next_instruction, ' = '), + msg(instruction)) + + if next_instruction.opname == 'RETURN_VALUE': + self.instructions.pop(0) + return (msg(instruction, 'return ', line=self.min_line(instruction)), msg(instruction)) + + if next_instruction.opname == 'RAISE_VARARGS' and next_instruction.argval == 1: + self.instructions.pop(0) + return (msg(instruction, 'raise ', line=self.min_line(instruction)), msg(instruction)) + + if instruction.opname == 'LOAD_CONST': + if inspect.iscode(instruction.argval): + + code_line_to_contents = _Disassembler( + instruction.argval, self.firstlineno, self.level + 1 + ).build_line_to_contents() + + for contents in code_line_to_contents.values(): + contents.insert(0, ' ') + for line, contents in code_line_to_contents.items(): + line_to_contents.setdefault(line, []).extend(contents) + return msg(instruction, 'LOAD_CONST(code)') + + if instruction.opname == 'RAISE_VARARGS': + if instruction.argval == 0: + return msg(instruction, 'raise') + + if instruction.opname == 'SETUP_FINALLY': + return msg(instruction, ('try(', instruction.argrepr, '):')) + + if instruction.argrepr: + return msg(instruction, (instruction.opname, '(', instruction.argrepr, ')')) + + if instruction.argval: + return msg(instruction, '%s{%s}' % (instruction.opname, instruction.argval,)) + + return msg(instruction, instruction.opname) + + def build_line_to_contents(self): + # print('----') + # for instruction in self.instructions: + # print(instruction) + # print('----\n\n') + + line_to_contents = {} + + instructions = self.instructions + while instructions: + s = self._next_instruction_to_str(line_to_contents) + if s is RESTART_FROM_LOOKAHEAD: + continue + if s is None: + continue + + _MsgPart.add_to_line_to_contents(s, line_to_contents) + m = self.max_line(s) + if m != self.SMALL_LINE_INT: + line_to_contents.setdefault(m, []).append(SEPARATOR) + return line_to_contents + + def disassemble(self): + line_to_contents = self.build_line_to_contents() + stream = StringIO() + last_line = 0 + show_lines = False + for line, contents in sorted(line_to_contents.items()): + while last_line < line - 1: + if show_lines: + stream.write('%s.\n' % (last_line + 1,)) + else: + stream.write('\n') + last_line += 1 + + if show_lines: + stream.write('%s. ' % (line,)) + + for i, content in enumerate(contents): + if content == SEPARATOR: + if i != len(contents) - 1: + stream.write(', ') + else: + stream.write(content) + + stream.write('\n') + + last_line = line + + return stream.getvalue() + + +def code_to_bytecode_representation(co, use_func_first_line=False): + ''' + A simple disassemble of bytecode. + + It does not attempt to provide the full Python source code, rather, it provides a low-level + representation of the bytecode, respecting the lines (so, its target is making the bytecode + easier to grasp and not providing the original source code). + + Note that it does show jump locations/targets and converts some common bytecode constructs to + Python code to make it a bit easier to understand. + ''' + # Reference for bytecodes: + # https://docs.python.org/3/library/dis.html + if use_func_first_line: + firstlineno = co.co_firstlineno + else: + firstlineno = 0 + + return _Disassembler(co, firstlineno).disassemble() diff --git a/_pydevd_bundle/pydevd_comm.py b/_pydevd_bundle/pydevd_comm.py new file mode 100644 index 0000000..163fd7a --- /dev/null +++ b/_pydevd_bundle/pydevd_comm.py @@ -0,0 +1,1823 @@ +''' pydevd - a debugging daemon +This is the daemon you launch for python remote debugging. + +Protocol: +each command has a format: + id\tsequence-num\ttext + id: protocol command number + sequence-num: each request has a sequence number. Sequence numbers + originating at the debugger are odd, sequence numbers originating + at the daemon are even. Every response uses the same sequence number + as the request. + payload: it is protocol dependent. When response is a complex structure, it + is returned as XML. Each attribute value is urlencoded, and then the whole + payload is urlencoded again to prevent stray characters corrupting protocol/xml encodings + + Commands: + + NUMBER NAME FROM* ARGUMENTS RESPONSE NOTE +100 series: program execution + 101 RUN JAVA - - + 102 LIST_THREADS JAVA RETURN with XML listing of all threads + 103 THREAD_CREATE PYDB - XML with thread information + 104 THREAD_KILL JAVA id (or * to exit) kills the thread + PYDB id nofies JAVA that thread was killed + 105 THREAD_SUSPEND JAVA XML of the stack, suspends the thread + reason for suspension + PYDB id notifies JAVA that thread was suspended + + 106 CMD_THREAD_RUN JAVA id resume the thread + PYDB id \t reason notifies JAVA that thread was resumed + + 107 STEP_INTO JAVA thread_id + 108 STEP_OVER JAVA thread_id + 109 STEP_RETURN JAVA thread_id + + 110 GET_VARIABLE JAVA thread_id \t frame_id \t GET_VARIABLE with XML of var content + FRAME|GLOBAL \t attributes* + + 111 SET_BREAK JAVA file/line of the breakpoint + 112 REMOVE_BREAK JAVA file/line of the return + 113 CMD_EVALUATE_EXPRESSION JAVA expression result of evaluating the expression + 114 CMD_GET_FRAME JAVA request for frame contents + 115 CMD_EXEC_EXPRESSION JAVA + 116 CMD_WRITE_TO_CONSOLE PYDB + 117 CMD_CHANGE_VARIABLE + 118 CMD_RUN_TO_LINE + 119 CMD_RELOAD_CODE + 120 CMD_GET_COMPLETIONS JAVA + + 200 CMD_REDIRECT_OUTPUT JAVA streams to redirect as string - + 'STDOUT' (redirect only STDOUT) + 'STDERR' (redirect only STDERR) + 'STDOUT STDERR' (redirect both streams) + +500 series diagnostics/ok + 501 VERSION either Version string (1.0) Currently just used at startup + 502 RETURN either Depends on caller - + +900 series: errors + 901 ERROR either - This is reserved for unexpected errors. + + * JAVA - remote debugger, the java end + * PYDB - pydevd, the python end +''' + +import linecache +import os + +from _pydev_bundle.pydev_imports import _queue +from _pydev_bundle._pydev_saved_modules import time +from _pydev_bundle._pydev_saved_modules import threading +from _pydev_bundle._pydev_saved_modules import socket as socket_module +from _pydevd_bundle.pydevd_constants import (DebugInfoHolder, IS_WINDOWS, IS_JYTHON, + IS_PY36_OR_GREATER, STATE_RUN, ASYNC_EVAL_TIMEOUT_SEC, + get_global_debugger, GetGlobalDebugger, set_global_debugger, # Keep for backward compatibility @UnusedImport + silence_warnings_decorator, filter_all_warnings) +from _pydev_bundle.pydev_override import overrides +import weakref +from _pydev_bundle._pydev_completer import extract_token_and_qualifier +from _pydevd_bundle._debug_adapter.pydevd_schema import VariablesResponseBody, \ + SetVariableResponseBody, StepInTarget, StepInTargetsResponseBody +from _pydevd_bundle._debug_adapter import pydevd_base_schema, pydevd_schema +from _pydevd_bundle.pydevd_net_command import NetCommand +from _pydevd_bundle.pydevd_xml import ExceptionOnEvaluate +from _pydevd_bundle.pydevd_constants import ForkSafeLock, NULL +from _pydevd_bundle.pydevd_daemon_thread import PyDBDaemonThread +from _pydevd_bundle.pydevd_thread_lifecycle import pydevd_find_thread_by_id, resume_threads +from _pydevd_bundle.pydevd_dont_trace_files import PYDEV_FILE +import dis +from _pydevd_bundle.pydevd_frame_utils import create_frames_list_from_exception_cause +import pydevd_file_utils +import itertools +from urllib.parse import quote_plus, unquote_plus +import pydevconsole +from _pydevd_bundle import pydevd_vars, pydevd_io, pydevd_reload +from _pydevd_bundle import pydevd_bytecode_utils +from _pydevd_bundle import pydevd_xml +from _pydevd_bundle import pydevd_vm_type +import sys +import traceback +from _pydevd_bundle.pydevd_utils import quote_smart as quote, compare_object_attrs_key, \ + notify_about_gevent_if_needed, isinstance_checked, ScopeRequest, getattr_checked, Timer +from _pydev_bundle import pydev_log, fsnotify +from _pydev_bundle.pydev_log import exception as pydev_log_exception +from _pydev_bundle import _pydev_completer + +from pydevd_tracing import get_exception_traceback_str +from _pydevd_bundle import pydevd_console +from _pydev_bundle.pydev_monkey import disable_trace_thread_modules, enable_trace_thread_modules +from io import StringIO + +# CMD_XXX constants imported for backward compatibility +from _pydevd_bundle.pydevd_comm_constants import * # @UnusedWildImport + +# Socket import aliases: +AF_INET, SOCK_STREAM, SHUT_WR, SOL_SOCKET, SO_REUSEADDR, IPPROTO_TCP, socket = ( + socket_module.AF_INET, + socket_module.SOCK_STREAM, + socket_module.SHUT_WR, + socket_module.SOL_SOCKET, + socket_module.SO_REUSEADDR, + socket_module.IPPROTO_TCP, + socket_module.socket, +) + +if IS_WINDOWS and not IS_JYTHON: + SO_EXCLUSIVEADDRUSE = socket_module.SO_EXCLUSIVEADDRUSE + + +class ReaderThread(PyDBDaemonThread): + ''' reader thread reads and dispatches commands in an infinite loop ''' + + def __init__(self, sock, py_db, PyDevJsonCommandProcessor, process_net_command, terminate_on_socket_close=True): + assert sock is not None + PyDBDaemonThread.__init__(self, py_db) + self.__terminate_on_socket_close = terminate_on_socket_close + + self.sock = sock + self._buffer = b'' + self.name = "pydevd.Reader" + self.process_net_command = process_net_command + self.process_net_command_json = PyDevJsonCommandProcessor(self._from_json).process_net_command_json + + def _from_json(self, json_msg, update_ids_from_dap=False): + return pydevd_base_schema.from_json(json_msg, update_ids_from_dap, on_dict_loaded=self._on_dict_loaded) + + def _on_dict_loaded(self, dct): + for listener in self.py_db.dap_messages_listeners: + listener.after_receive(dct) + + @overrides(PyDBDaemonThread.do_kill_pydev_thread) + def do_kill_pydev_thread(self): + PyDBDaemonThread.do_kill_pydev_thread(self) + # Note that we no longer shutdown the reader, just the writer. The idea is that we shutdown + # the writer to send that the communication has finished, then, the client will shutdown its + # own writer when it receives an empty read, at which point this reader will also shutdown. + + # That way, we can *almost* guarantee that all messages have been properly sent -- it's not + # completely guaranteed because it's possible that the process exits before the whole + # message was sent as having this thread alive won't stop the process from exiting -- we + # have a timeout when exiting the process waiting for this thread to finish -- see: + # PyDB.dispose_and_kill_all_pydevd_threads()). + + # try: + # self.sock.shutdown(SHUT_RD) + # except: + # pass + # try: + # self.sock.close() + # except: + # pass + + def _read(self, size): + while True: + buffer_len = len(self._buffer) + if buffer_len == size: + ret = self._buffer + self._buffer = b'' + return ret + + if buffer_len > size: + ret = self._buffer[:size] + self._buffer = self._buffer[size:] + return ret + + try: + r = self.sock.recv(max(size - buffer_len, 1024)) + except OSError: + return b'' + if not r: + return b'' + self._buffer += r + + def _read_line(self): + while True: + i = self._buffer.find(b'\n') + if i != -1: + i += 1 # Add the newline to the return + ret = self._buffer[:i] + self._buffer = self._buffer[i:] + return ret + else: + try: + r = self.sock.recv(1024) + except OSError: + return b'' + if not r: + return b'' + self._buffer += r + + @overrides(PyDBDaemonThread._on_run) + def _on_run(self): + try: + content_len = -1 + + while True: + # i.e.: even if we received a kill, we should only exit the ReaderThread when the + # client itself closes the connection (although on kill received we stop actually + # processing anything read). + try: + notify_about_gevent_if_needed() + line = self._read_line() + + if len(line) == 0: + pydev_log.debug('ReaderThread: empty contents received (len(line) == 0).') + self._terminate_on_socket_close() + return # Finished communication. + + if self._kill_received: + continue + + if line.startswith(b'Content-Length:'): + content_len = int(line.strip().split(b':', 1)[1]) + continue + + if content_len != -1: + # If we previously received a content length, read until a '\r\n'. + if line == b'\r\n': + json_contents = self._read(content_len) + + content_len = -1 + + if len(json_contents) == 0: + pydev_log.debug('ReaderThread: empty contents received (len(json_contents) == 0).') + self._terminate_on_socket_close() + return # Finished communication. + + if self._kill_received: + continue + + # We just received a json message, let's process it. + self.process_net_command_json(self.py_db, json_contents) + + continue + else: + # No content len, regular line-based protocol message (remove trailing new-line). + if line.endswith(b'\n\n'): + line = line[:-2] + + elif line.endswith(b'\n'): + line = line[:-1] + + elif line.endswith(b'\r'): + line = line[:-1] + except: + if not self._kill_received: + pydev_log_exception() + self._terminate_on_socket_close() + return # Finished communication. + + # Note: the java backend is always expected to pass utf-8 encoded strings. We now work with str + # internally and thus, we may need to convert to the actual encoding where needed (i.e.: filenames + # on python 2 may need to be converted to the filesystem encoding). + if hasattr(line, 'decode'): + line = line.decode('utf-8') + + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 3: + pydev_log.debug('debugger: received >>%s<<\n', line) + + args = line.split('\t', 2) + try: + cmd_id = int(args[0]) + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 3: + pydev_log.debug('Received command: %s %s\n', ID_TO_MEANING.get(str(cmd_id), '???'), line) + self.process_command(cmd_id, int(args[1]), args[2]) + except: + if sys is not None and pydev_log_exception is not None: # Could happen at interpreter shutdown + pydev_log_exception("Can't process net command: %s.", line) + + except: + if not self._kill_received: + if sys is not None and pydev_log_exception is not None: # Could happen at interpreter shutdown + pydev_log_exception() + + self._terminate_on_socket_close() + finally: + pydev_log.debug('ReaderThread: exit') + + def _terminate_on_socket_close(self): + if self.__terminate_on_socket_close: + self.py_db.dispose_and_kill_all_pydevd_threads() + + def process_command(self, cmd_id, seq, text): + self.process_net_command(self.py_db, cmd_id, seq, text) + + +class FSNotifyThread(PyDBDaemonThread): + + def __init__(self, py_db, api, watch_dirs): + PyDBDaemonThread.__init__(self, py_db) + self.api = api + self.name = "pydevd.FSNotifyThread" + self.watcher = fsnotify.Watcher() + self.watch_dirs = watch_dirs + + @overrides(PyDBDaemonThread._on_run) + def _on_run(self): + try: + pydev_log.info('Watching directories for code reload:\n---\n%s\n---' % ('\n'.join(sorted(self.watch_dirs)))) + + # i.e.: The first call to set_tracked_paths will do a full scan, so, do it in the thread + # too (after everything is configured). + self.watcher.set_tracked_paths(self.watch_dirs) + while not self._kill_received: + for change_enum, change_path in self.watcher.iter_changes(): + # We're only interested in modified events + if change_enum == fsnotify.Change.modified: + pydev_log.info('Modified: %s', change_path) + self.api.request_reload_code(self.py_db, -1, None, change_path) + else: + pydev_log.info('Ignored (add or remove) change in: %s', change_path) + except: + pydev_log.exception('Error when waiting for filesystem changes in FSNotifyThread.') + + @overrides(PyDBDaemonThread.do_kill_pydev_thread) + def do_kill_pydev_thread(self): + self.watcher.dispose() + PyDBDaemonThread.do_kill_pydev_thread(self) + + +class WriterThread(PyDBDaemonThread): + ''' writer thread writes out the commands in an infinite loop ''' + + def __init__(self, sock, py_db, terminate_on_socket_close=True): + PyDBDaemonThread.__init__(self, py_db) + self.sock = sock + self.__terminate_on_socket_close = terminate_on_socket_close + self.name = "pydevd.Writer" + self._cmd_queue = _queue.Queue() + if pydevd_vm_type.get_vm_type() == 'python': + self.timeout = 0 + else: + self.timeout = 0.1 + + def add_command(self, cmd): + ''' cmd is NetCommand ''' + if not self._kill_received: # we don't take new data after everybody die + self._cmd_queue.put(cmd, False) + + @overrides(PyDBDaemonThread._on_run) + def _on_run(self): + ''' just loop and write responses ''' + + try: + while True: + try: + try: + cmd = self._cmd_queue.get(True, 0.1) + except _queue.Empty: + if self._kill_received: + pydev_log.debug('WriterThread: kill_received (sock.shutdown(SHUT_WR))') + try: + self.sock.shutdown(SHUT_WR) + except: + pass + # Note: don't close the socket, just send the shutdown, + # then, when no data is received on the reader, it can close + # the socket. + # See: https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable + + # try: + # self.sock.close() + # except: + # pass + + return # break if queue is empty and _kill_received + else: + continue + except: + # pydev_log.info('Finishing debug communication...(1)') + # when liberating the thread here, we could have errors because we were shutting down + # but the thread was still not liberated + return + + if cmd.as_dict is not None: + for listener in self.py_db.dap_messages_listeners: + listener.before_send(cmd.as_dict) + + notify_about_gevent_if_needed() + cmd.send(self.sock) + + if cmd.id == CMD_EXIT: + pydev_log.debug('WriterThread: CMD_EXIT received') + break + if time is None: + break # interpreter shutdown + time.sleep(self.timeout) + except Exception: + if self.__terminate_on_socket_close: + self.py_db.dispose_and_kill_all_pydevd_threads() + if DebugInfoHolder.DEBUG_TRACE_LEVEL > 0: + pydev_log_exception() + finally: + pydev_log.debug('WriterThread: exit') + + def empty(self): + return self._cmd_queue.empty() + + @overrides(PyDBDaemonThread.do_kill_pydev_thread) + def do_kill_pydev_thread(self): + if not self._kill_received: + # Add command before setting the kill flag (otherwise the command may not be added). + exit_cmd = self.py_db.cmd_factory.make_exit_command(self.py_db) + self.add_command(exit_cmd) + + PyDBDaemonThread.do_kill_pydev_thread(self) + + +def create_server_socket(host, port): + try: + server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) + if IS_WINDOWS and not IS_JYTHON: + server.setsockopt(SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1) + else: + server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) + + server.bind((host, port)) + server.settimeout(None) + except Exception: + server.close() + raise + + return server + + +def start_server(port): + ''' binds to a port, waits for the debugger to connect ''' + s = create_server_socket(host='', port=port) + + try: + s.listen(1) + new_socket, _addr = s.accept() + pydev_log.info("Connection accepted") + # closing server socket is not necessary but we don't need it + s.close() + return new_socket + except: + pydev_log.exception("Could not bind to port: %s\n", port) + raise + + +def start_client(host, port): + ''' connects to a host/port ''' + pydev_log.info("Connecting to %s:%s", host, port) + + s = socket(AF_INET, SOCK_STREAM) + + # Set TCP keepalive on an open socket. + # It activates after 1 second (TCP_KEEPIDLE,) of idleness, + # then sends a keepalive ping once every 3 seconds (TCP_KEEPINTVL), + # and closes the connection after 5 failed ping (TCP_KEEPCNT), or 15 seconds + try: + s.setsockopt(SOL_SOCKET, socket_module.SO_KEEPALIVE, 1) + except (AttributeError, OSError): + pass # May not be available everywhere. + try: + s.setsockopt(socket_module.IPPROTO_TCP, socket_module.TCP_KEEPIDLE, 1) + except (AttributeError, OSError): + pass # May not be available everywhere. + try: + s.setsockopt(socket_module.IPPROTO_TCP, socket_module.TCP_KEEPINTVL, 3) + except (AttributeError, OSError): + pass # May not be available everywhere. + try: + s.setsockopt(socket_module.IPPROTO_TCP, socket_module.TCP_KEEPCNT, 5) + except (AttributeError, OSError): + pass # May not be available everywhere. + + try: + # 10 seconds default timeout + timeout = int(os.environ.get('PYDEVD_CONNECT_TIMEOUT', 10)) + s.settimeout(timeout) + s.connect((host, port)) + s.settimeout(None) # no timeout after connected + pydev_log.info("Connected.") + return s + except: + pydev_log.exception("Could not connect to %s: %s", host, port) + raise + + +INTERNAL_TERMINATE_THREAD = 1 +INTERNAL_SUSPEND_THREAD = 2 + + +class InternalThreadCommand(object): + ''' internal commands are generated/executed by the debugger. + + The reason for their existence is that some commands have to be executed + on specific threads. These are the InternalThreadCommands that get + get posted to PyDB. + ''' + + def __init__(self, thread_id, method=None, *args, **kwargs): + self.thread_id = thread_id + self.method = method + self.args = args + self.kwargs = kwargs + + def can_be_executed_by(self, thread_id): + '''By default, it must be in the same thread to be executed + ''' + return self.thread_id == thread_id or self.thread_id.endswith('|' + thread_id) + + def do_it(self, dbg): + try: + if self.method is not None: + self.method(dbg, *self.args, **self.kwargs) + else: + raise NotImplementedError("you have to override do_it") + finally: + self.args = None + self.kwargs = None + + def __str__(self): + return 'InternalThreadCommands(%s, %s, %s)' % (self.method, self.args, self.kwargs) + + __repr__ = __str__ + + +class InternalThreadCommandForAnyThread(InternalThreadCommand): + + def __init__(self, thread_id, method=None, *args, **kwargs): + assert thread_id == '*' + + InternalThreadCommand.__init__(self, thread_id, method, *args, **kwargs) + + self.executed = False + self.lock = ForkSafeLock() + + def can_be_executed_by(self, thread_id): + return True # Can be executed by any thread. + + def do_it(self, dbg): + with self.lock: + if self.executed: + return + self.executed = True + + InternalThreadCommand.do_it(self, dbg) + + +def _send_io_message(py_db, s): + cmd = py_db.cmd_factory.make_io_message(s, 2) + if py_db.writer is not None: + py_db.writer.add_command(cmd) + + +def internal_reload_code(dbg, seq, module_name, filename): + try: + found_module_to_reload = False + if module_name is not None: + module_name = module_name + if module_name not in sys.modules: + if '.' in module_name: + new_module_name = module_name.split('.')[-1] + if new_module_name in sys.modules: + module_name = new_module_name + + modules_to_reload = {} + module = sys.modules.get(module_name) + if module is not None: + modules_to_reload[id(module)] = (module, module_name) + + if filename: + filename = pydevd_file_utils.normcase(filename) + for module_name, module in sys.modules.copy().items(): + f = getattr_checked(module, '__file__') + if f is not None: + if f.endswith(('.pyc', '.pyo')): + f = f[:-1] + + if pydevd_file_utils.normcase(f) == filename: + modules_to_reload[id(module)] = (module, module_name) + + if not modules_to_reload: + if filename and module_name: + _send_io_message(dbg, 'code reload: Unable to find module %s to reload for path: %s\n' % (module_name, filename)) + elif filename: + _send_io_message(dbg, 'code reload: Unable to find module to reload for path: %s\n' % (filename,)) + elif module_name: + _send_io_message(dbg, 'code reload: Unable to find module to reload: %s\n' % (module_name,)) + + else: + # Too much info... + # _send_io_message(dbg, 'code reload: This usually means you are trying to reload the __main__ module (which cannot be reloaded).\n') + for module, module_name in modules_to_reload.values(): + _send_io_message(dbg, 'code reload: Start reloading module: "' + module_name + '" ... \n') + found_module_to_reload = True + + if pydevd_reload.xreload(module): + _send_io_message(dbg, 'code reload: reload finished\n') + else: + _send_io_message(dbg, 'code reload: reload finished without applying any change\n') + + cmd = dbg.cmd_factory.make_reloaded_code_message(seq, found_module_to_reload) + dbg.writer.add_command(cmd) + except: + pydev_log.exception('Error reloading code') + + +class InternalGetThreadStack(InternalThreadCommand): + ''' + This command will either wait for a given thread to be paused to get its stack or will provide + it anyways after a timeout (in which case the stack will be gotten but local variables won't + be available and it'll not be possible to interact with the frame as it's not actually + stopped in a breakpoint). + ''' + + def __init__(self, seq, thread_id, py_db, set_additional_thread_info, fmt, timeout=.5, start_frame=0, levels=0): + InternalThreadCommand.__init__(self, thread_id) + self._py_db = weakref.ref(py_db) + self._timeout = time.time() + timeout + self.seq = seq + self._cmd = None + self._fmt = fmt + self._start_frame = start_frame + self._levels = levels + + # Note: receives set_additional_thread_info to avoid a circular import + # in this module. + self._set_additional_thread_info = set_additional_thread_info + + @overrides(InternalThreadCommand.can_be_executed_by) + def can_be_executed_by(self, _thread_id): + timed_out = time.time() >= self._timeout + + py_db = self._py_db() + t = pydevd_find_thread_by_id(self.thread_id) + frame = None + if t and not getattr(t, 'pydev_do_not_trace', None): + additional_info = self._set_additional_thread_info(t) + frame = additional_info.get_topmost_frame(t) + try: + self._cmd = py_db.cmd_factory.make_get_thread_stack_message( + py_db, self.seq, self.thread_id, frame, self._fmt, must_be_suspended=not timed_out, start_frame=self._start_frame, levels=self._levels) + finally: + frame = None + t = None + + return self._cmd is not None or timed_out + + @overrides(InternalThreadCommand.do_it) + def do_it(self, dbg): + if self._cmd is not None: + dbg.writer.add_command(self._cmd) + self._cmd = None + + +def internal_step_in_thread(py_db, thread_id, cmd_id, set_additional_thread_info): + thread_to_step = pydevd_find_thread_by_id(thread_id) + if thread_to_step: + info = set_additional_thread_info(thread_to_step) + info.pydev_original_step_cmd = cmd_id + info.pydev_step_cmd = cmd_id + info.pydev_step_stop = None + info.pydev_state = STATE_RUN + + if py_db.stepping_resumes_all_threads: + resume_threads('*', except_thread=thread_to_step) + + +def internal_smart_step_into(py_db, thread_id, offset, child_offset, set_additional_thread_info): + thread_to_step = pydevd_find_thread_by_id(thread_id) + if thread_to_step: + info = set_additional_thread_info(thread_to_step) + info.pydev_original_step_cmd = CMD_SMART_STEP_INTO + info.pydev_step_cmd = CMD_SMART_STEP_INTO + info.pydev_step_stop = None + info.pydev_smart_parent_offset = int(offset) + info.pydev_smart_child_offset = int(child_offset) + info.pydev_state = STATE_RUN + + if py_db.stepping_resumes_all_threads: + resume_threads('*', except_thread=thread_to_step) + + +class InternalSetNextStatementThread(InternalThreadCommand): + + def __init__(self, thread_id, cmd_id, line, func_name, seq=0): + ''' + cmd_id may actually be one of: + + CMD_RUN_TO_LINE + CMD_SET_NEXT_STATEMENT + CMD_SMART_STEP_INTO + ''' + self.thread_id = thread_id + self.cmd_id = cmd_id + self.line = line + self.seq = seq + + self.func_name = func_name + + def do_it(self, dbg): + t = pydevd_find_thread_by_id(self.thread_id) + if t: + info = t.additional_info + info.pydev_original_step_cmd = self.cmd_id + info.pydev_step_cmd = self.cmd_id + info.pydev_step_stop = None + info.pydev_next_line = int(self.line) + info.pydev_func_name = self.func_name + info.pydev_message = str(self.seq) + info.pydev_smart_parent_offset = -1 + info.pydev_smart_child_offset = -1 + info.pydev_state = STATE_RUN + + +@silence_warnings_decorator +def internal_get_variable_json(py_db, request): + ''' + :param VariablesRequest request: + ''' + arguments = request.arguments # : :type arguments: VariablesArguments + variables_reference = arguments.variablesReference + scope = None + if isinstance_checked(variables_reference, ScopeRequest): + scope = variables_reference + variables_reference = variables_reference.variable_reference + + fmt = arguments.format + if hasattr(fmt, 'to_dict'): + fmt = fmt.to_dict() + + variables = [] + try: + try: + variable = py_db.suspended_frames_manager.get_variable(variables_reference) + except KeyError: + pass + else: + for child_var in variable.get_children_variables(fmt=fmt, scope=scope): + variables.append(child_var.get_var_data(fmt=fmt)) + except: + try: + exc, exc_type, tb = sys.exc_info() + err = ''.join(traceback.format_exception(exc, exc_type, tb)) + variables = [{ + 'name': '', + 'value': err, + 'type': '', + 'variablesReference': 0 + }] + except: + err = '' + pydev_log.exception(err) + variables = [] + + body = VariablesResponseBody(variables) + variables_response = pydevd_base_schema.build_response(request, kwargs={'body':body}) + py_db.writer.add_command(NetCommand(CMD_RETURN, 0, variables_response, is_json=True)) + + +class InternalGetVariable(InternalThreadCommand): + ''' gets the value of a variable ''' + + def __init__(self, seq, thread_id, frame_id, scope, attrs): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.scope = scope + self.attributes = attrs + + @silence_warnings_decorator + def do_it(self, dbg): + ''' Converts request into python variable ''' + try: + xml = StringIO() + xml.write("") + type_name, val_dict = pydevd_vars.resolve_compound_variable_fields( + dbg, self.thread_id, self.frame_id, self.scope, self.attributes) + if val_dict is None: + val_dict = {} + + # assume properly ordered if resolver returns 'OrderedDict' + # check type as string to support OrderedDict backport for older Python + keys = list(val_dict) + if not (type_name == "OrderedDict" or val_dict.__class__.__name__ == "OrderedDict" or IS_PY36_OR_GREATER): + keys = sorted(keys, key=compare_object_attrs_key) + + timer = Timer() + for k in keys: + val = val_dict[k] + evaluate_full_value = pydevd_xml.should_evaluate_full_value(val) + xml.write(pydevd_xml.var_to_xml(val, k, evaluate_full_value=evaluate_full_value)) + timer.report_if_compute_repr_attr_slow(self.attributes, k, type(val)) + + xml.write("") + cmd = dbg.cmd_factory.make_get_variable_message(self.sequence, xml.getvalue()) + xml.close() + dbg.writer.add_command(cmd) + except Exception: + cmd = dbg.cmd_factory.make_error_message( + self.sequence, "Error resolving variables %s" % (get_exception_traceback_str(),)) + dbg.writer.add_command(cmd) + + +class InternalGetArray(InternalThreadCommand): + + def __init__(self, seq, roffset, coffset, rows, cols, format, thread_id, frame_id, scope, attrs): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.scope = scope + self.name = attrs.split("\t")[-1] + self.attrs = attrs + self.roffset = int(roffset) + self.coffset = int(coffset) + self.rows = int(rows) + self.cols = int(cols) + self.format = format + + def do_it(self, dbg): + try: + frame = dbg.find_frame(self.thread_id, self.frame_id) + var = pydevd_vars.eval_in_context(self.name, frame.f_globals, frame.f_locals, py_db=dbg) + xml = pydevd_vars.table_like_struct_to_xml(var, self.name, self.roffset, self.coffset, self.rows, self.cols, self.format) + cmd = dbg.cmd_factory.make_get_array_message(self.sequence, xml) + dbg.writer.add_command(cmd) + except: + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error resolving array: " + get_exception_traceback_str()) + dbg.writer.add_command(cmd) + + +def internal_change_variable(dbg, seq, thread_id, frame_id, scope, attr, value): + ''' Changes the value of a variable ''' + try: + frame = dbg.find_frame(thread_id, frame_id) + if frame is not None: + result = pydevd_vars.change_attr_expression(frame, attr, value, dbg) + else: + result = None + xml = "" + xml += pydevd_xml.var_to_xml(result, "") + xml += "" + cmd = dbg.cmd_factory.make_variable_changed_message(seq, xml) + dbg.writer.add_command(cmd) + except Exception: + cmd = dbg.cmd_factory.make_error_message(seq, "Error changing variable attr:%s expression:%s traceback:%s" % (attr, value, get_exception_traceback_str())) + dbg.writer.add_command(cmd) + + +def internal_change_variable_json(py_db, request): + ''' + The pydevd_vars.change_attr_expression(thread_id, frame_id, attr, value, dbg) can only + deal with changing at a frame level, so, currently changing the contents of something + in a different scope is currently not supported. + + :param SetVariableRequest request: + ''' + # : :type arguments: SetVariableArguments + arguments = request.arguments + variables_reference = arguments.variablesReference + scope = None + if isinstance_checked(variables_reference, ScopeRequest): + scope = variables_reference + variables_reference = variables_reference.variable_reference + + fmt = arguments.format + if hasattr(fmt, 'to_dict'): + fmt = fmt.to_dict() + + try: + variable = py_db.suspended_frames_manager.get_variable(variables_reference) + except KeyError: + variable = None + + if variable is None: + _write_variable_response( + py_db, request, value='', success=False, message='Unable to find variable container to change: %s.' % (variables_reference,)) + return + + child_var = variable.change_variable(arguments.name, arguments.value, py_db, fmt=fmt) + + if child_var is None: + _write_variable_response( + py_db, request, value='', success=False, message='Unable to change: %s.' % (arguments.name,)) + return + + var_data = child_var.get_var_data(fmt=fmt) + body = SetVariableResponseBody( + value=var_data['value'], + type=var_data['type'], + variablesReference=var_data.get('variablesReference'), + namedVariables=var_data.get('namedVariables'), + indexedVariables=var_data.get('indexedVariables'), + ) + variables_response = pydevd_base_schema.build_response(request, kwargs={'body':body}) + py_db.writer.add_command(NetCommand(CMD_RETURN, 0, variables_response, is_json=True)) + + +def _write_variable_response(py_db, request, value, success, message): + body = SetVariableResponseBody('') + variables_response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body':body, + 'success': False, + 'message': message + }) + cmd = NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + py_db.writer.add_command(cmd) + + +@silence_warnings_decorator +def internal_get_frame(dbg, seq, thread_id, frame_id): + ''' Converts request into python variable ''' + try: + frame = dbg.find_frame(thread_id, frame_id) + if frame is not None: + hidden_ns = pydevconsole.get_ipython_hidden_vars() + xml = "" + xml += pydevd_xml.frame_vars_to_xml(frame.f_locals, hidden_ns) + del frame + xml += "" + cmd = dbg.cmd_factory.make_get_frame_message(seq, xml) + dbg.writer.add_command(cmd) + else: + # pydevd_vars.dump_frames(thread_id) + # don't print this error: frame not found: means that the client is not synchronized (but that's ok) + cmd = dbg.cmd_factory.make_error_message(seq, "Frame not found: %s from thread: %s" % (frame_id, thread_id)) + dbg.writer.add_command(cmd) + except: + cmd = dbg.cmd_factory.make_error_message(seq, "Error resolving frame: %s from thread: %s" % (frame_id, thread_id)) + dbg.writer.add_command(cmd) + + +def internal_get_smart_step_into_variants(dbg, seq, thread_id, frame_id, start_line, end_line, set_additional_thread_info): + try: + thread = pydevd_find_thread_by_id(thread_id) + frame = dbg.find_frame(thread_id, frame_id) + + if thread is None or frame is None: + cmd = dbg.cmd_factory.make_error_message(seq, "Frame not found: %s from thread: %s" % (frame_id, thread_id)) + dbg.writer.add_command(cmd) + return + + if pydevd_bytecode_utils is None: + variants = [] + else: + variants = pydevd_bytecode_utils.calculate_smart_step_into_variants(frame, int(start_line), int(end_line)) + + info = set_additional_thread_info(thread) + + # Store the last request (may be used afterwards when stepping). + info.pydev_smart_step_into_variants = tuple(variants) + xml = "" + + for variant in variants: + if variant.children_variants: + for child_variant in variant.children_variants: + # If there are child variants, the current one is just an intermediary, so, + # just create variants for the child (notifying properly about the parent too). + xml += '' % ( + quote(child_variant.name), + str(child_variant.is_visited).lower(), + child_variant.line, + variant.offset, + child_variant.offset, + child_variant.call_order, + ) + else: + xml += '' % ( + quote(variant.name), + str(variant.is_visited).lower(), + variant.line, + variant.offset, + variant.call_order, + ) + + xml += "" + cmd = NetCommand(CMD_GET_SMART_STEP_INTO_VARIANTS, seq, xml) + dbg.writer.add_command(cmd) + except: + # Error is expected (if `dis` module cannot be used -- i.e.: Jython). + pydev_log.exception('Error calculating Smart Step Into Variants.') + cmd = dbg.cmd_factory.make_error_message( + seq, "Error getting smart step into variants for frame: %s from thread: %s" + % (frame_id, thread_id)) + dbg.writer.add_command(cmd) + + +def internal_get_step_in_targets_json(dbg, seq, thread_id, frame_id, request, set_additional_thread_info): + try: + thread = pydevd_find_thread_by_id(thread_id) + frame = dbg.find_frame(thread_id, frame_id) + + if thread is None or frame is None: + body = StepInTargetsResponseBody([]) + variables_response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': body, + 'success': False, + 'message': 'Thread to get step in targets seems to have resumed already.' + }) + cmd = NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + dbg.writer.add_command(cmd) + return + + start_line = 0 + end_line = 99999999 + if pydevd_bytecode_utils is None: + variants = [] + else: + variants = pydevd_bytecode_utils.calculate_smart_step_into_variants(frame, start_line, end_line) + + info = set_additional_thread_info(thread) + targets = [] + counter = itertools.count(0) + target_id_to_variant = {} + for variant in variants: + if not variant.is_visited: + if variant.children_variants: + for child_variant in variant.children_variants: + target_id = next(counter) + + if child_variant.call_order > 1: + targets.append(StepInTarget(id=target_id, label='%s (call %s)' % (child_variant.name, child_variant.call_order),)) + else: + targets.append(StepInTarget(id=target_id, label=child_variant.name)) + target_id_to_variant[target_id] = child_variant + + if len(targets) >= 15: # Show at most 15 targets. + break + else: + target_id = next(counter) + if variant.call_order > 1: + targets.append(StepInTarget(id=target_id, label='%s (call %s)' % (variant.name, variant.call_order),)) + else: + targets.append(StepInTarget(id=target_id, label=variant.name)) + target_id_to_variant[target_id] = variant + + if len(targets) >= 15: # Show at most 15 targets. + break + + # Store the last request (may be used afterwards when stepping). + info.pydev_smart_step_into_variants = tuple(variants) + info.target_id_to_smart_step_into_variant = target_id_to_variant + + body = StepInTargetsResponseBody(targets=targets) + response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + cmd = NetCommand(CMD_RETURN, 0, response, is_json=True) + dbg.writer.add_command(cmd) + except Exception as e: + # Error is expected (if `dis` module cannot be used -- i.e.: Jython). + pydev_log.exception('Error calculating Smart Step Into Variants.') + body = StepInTargetsResponseBody([]) + variables_response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': body, + 'success': False, + 'message': str(e) + }) + cmd = NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + dbg.writer.add_command(cmd) + + +def internal_get_next_statement_targets(dbg, seq, thread_id, frame_id): + ''' gets the valid line numbers for use with set next statement ''' + try: + frame = dbg.find_frame(thread_id, frame_id) + if frame is not None: + code = frame.f_code + xml = "" + try: + linestarts = dis.findlinestarts(code) + except: + # i.e.: jython doesn't provide co_lnotab, so, we can only keep at the current line. + xml += "%d" % (frame.f_lineno,) + else: + for _, line in linestarts: + xml += "%d" % (line,) + del frame + xml += "" + cmd = dbg.cmd_factory.make_get_next_statement_targets_message(seq, xml) + dbg.writer.add_command(cmd) + else: + cmd = dbg.cmd_factory.make_error_message(seq, "Frame not found: %s from thread: %s" % (frame_id, thread_id)) + dbg.writer.add_command(cmd) + except: + cmd = dbg.cmd_factory.make_error_message(seq, "Error resolving frame: %s from thread: %s" % (frame_id, thread_id)) + dbg.writer.add_command(cmd) + + +def _evaluate_response(py_db, request, result, error_message=''): + is_error = isinstance(result, ExceptionOnEvaluate) + if is_error: + result = result.result + if not error_message: + body = pydevd_schema.EvaluateResponseBody(result=result, variablesReference=0) + variables_response = pydevd_base_schema.build_response(request, kwargs={'body':body}) + py_db.writer.add_command(NetCommand(CMD_RETURN, 0, variables_response, is_json=True)) + else: + body = pydevd_schema.EvaluateResponseBody(result=result, variablesReference=0) + variables_response = pydevd_base_schema.build_response(request, kwargs={ + 'body':body, 'success':False, 'message': error_message}) + py_db.writer.add_command(NetCommand(CMD_RETURN, 0, variables_response, is_json=True)) + + +_global_frame = None + + +def internal_evaluate_expression_json(py_db, request, thread_id): + ''' + :param EvaluateRequest request: + ''' + global _global_frame + # : :type arguments: EvaluateArguments + + arguments = request.arguments + expression = arguments.expression + frame_id = arguments.frameId + context = arguments.context + fmt = arguments.format + if hasattr(fmt, 'to_dict'): + fmt = fmt.to_dict() + + ctx = NULL + if context == 'repl': + if not py_db.is_output_redirected: + ctx = pydevd_io.redirect_stream_to_pydb_io_messages_context() + else: + # If we're not in a repl (watch, hover, ...) don't show warnings. + ctx = filter_all_warnings() + + with ctx: + try_exec = False + if frame_id is None: + if _global_frame is None: + # Lazily create a frame to be used for evaluation with no frame id. + + def __create_frame(): + yield sys._getframe() + + _global_frame = next(__create_frame()) + + frame = _global_frame + try_exec = True # Always exec in this case + eval_result = None + else: + frame = py_db.find_frame(thread_id, frame_id) + + eval_result = pydevd_vars.evaluate_expression(py_db, frame, expression, is_exec=False) + is_error = isinstance_checked(eval_result, ExceptionOnEvaluate) + if is_error: + if context == 'hover': # In a hover it doesn't make sense to do an exec. + _evaluate_response(py_db, request, result='', error_message='Exception occurred during evaluation.') + return + elif context == 'watch': + # If it's a watch, don't show it as an exception object, rather, format + # it and show it as a string (with success=False). + msg = '%s: %s' % ( + eval_result.result.__class__.__name__, eval_result.result,) + _evaluate_response(py_db, request, result=msg, error_message=msg) + return + else: + # We only try the exec if the failure we had was due to not being able + # to evaluate the expression. + try: + pydevd_vars.compile_as_eval(expression) + except Exception: + try_exec = context == 'repl' + else: + try_exec = False + if context == 'repl': + # In the repl we should show the exception to the user. + _evaluate_response_return_exception(py_db, request, eval_result.etype, eval_result.result, eval_result.tb) + return + + if try_exec: + try: + pydevd_vars.evaluate_expression(py_db, frame, expression, is_exec=True) + except (Exception, KeyboardInterrupt): + _evaluate_response_return_exception(py_db, request, *sys.exc_info()) + return + # No result on exec. + _evaluate_response(py_db, request, result='') + return + + # Ok, we have the result (could be an error), let's put it into the saved variables. + frame_tracker = py_db.suspended_frames_manager.get_frame_tracker(thread_id) + if frame_tracker is None: + # This is not really expected. + _evaluate_response(py_db, request, result='', error_message='Thread id: %s is not current thread id.' % (thread_id,)) + return + + safe_repr_custom_attrs = {} + if context == 'clipboard': + safe_repr_custom_attrs = dict( + maxstring_outer=2 ** 64, + maxstring_inner=2 ** 64, + maxother_outer=2 ** 64, + maxother_inner=2 ** 64, + ) + + if context == 'repl' and eval_result is None: + # We don't want "None" to appear when typing in the repl. + body = pydevd_schema.EvaluateResponseBody( + result=None, + variablesReference=0, + ) + + else: + variable = frame_tracker.obtain_as_variable(expression, eval_result, frame=frame) + var_data = variable.get_var_data(fmt=fmt, **safe_repr_custom_attrs) + + body = pydevd_schema.EvaluateResponseBody( + result=var_data['value'], + variablesReference=var_data.get('variablesReference', 0), + type=var_data.get('type'), + presentationHint=var_data.get('presentationHint'), + namedVariables=var_data.get('namedVariables'), + indexedVariables=var_data.get('indexedVariables'), + ) + variables_response = pydevd_base_schema.build_response(request, kwargs={'body':body}) + py_db.writer.add_command(NetCommand(CMD_RETURN, 0, variables_response, is_json=True)) + + +def _evaluate_response_return_exception(py_db, request, exc_type, exc, initial_tb): + try: + tb = initial_tb + + # Show the traceback without pydevd frames. + temp_tb = tb + while temp_tb: + if py_db.get_file_type(temp_tb.tb_frame) == PYDEV_FILE: + tb = temp_tb.tb_next + temp_tb = temp_tb.tb_next + + if tb is None: + tb = initial_tb + err = ''.join(traceback.format_exception(exc_type, exc, tb)) + + # Make sure we don't keep references to them. + exc = None + exc_type = None + tb = None + temp_tb = None + initial_tb = None + except: + err = '' + pydev_log.exception(err) + + # Currently there is an issue in VSC where returning success=false for an + # eval request, in repl context, VSC does not show the error response in + # the debug console. So return the error message in result as well. + _evaluate_response(py_db, request, result=err, error_message=err) + + +@silence_warnings_decorator +def internal_evaluate_expression(dbg, seq, thread_id, frame_id, expression, is_exec, trim_if_too_big, attr_to_set_result): + ''' gets the value of a variable ''' + try: + frame = dbg.find_frame(thread_id, frame_id) + if frame is not None: + result = pydevd_vars.evaluate_expression(dbg, frame, expression, is_exec) + if attr_to_set_result != "": + pydevd_vars.change_attr_expression(frame, attr_to_set_result, expression, dbg, result) + else: + result = None + + xml = "" + xml += pydevd_xml.var_to_xml(result, expression, trim_if_too_big) + xml += "" + cmd = dbg.cmd_factory.make_evaluate_expression_message(seq, xml) + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + cmd = dbg.cmd_factory.make_error_message(seq, "Error evaluating expression " + exc) + dbg.writer.add_command(cmd) + + +def _set_expression_response(py_db, request, result, error_message): + body = pydevd_schema.SetExpressionResponseBody(result='', variablesReference=0) + variables_response = pydevd_base_schema.build_response(request, kwargs={ + 'body':body, 'success':False, 'message': error_message}) + py_db.writer.add_command(NetCommand(CMD_RETURN, 0, variables_response, is_json=True)) + + +def internal_set_expression_json(py_db, request, thread_id): + # : :type arguments: SetExpressionArguments + + arguments = request.arguments + expression = arguments.expression + frame_id = arguments.frameId + value = arguments.value + fmt = arguments.format + if hasattr(fmt, 'to_dict'): + fmt = fmt.to_dict() + + frame = py_db.find_frame(thread_id, frame_id) + exec_code = '%s = (%s)' % (expression, value) + result = pydevd_vars.evaluate_expression(py_db, frame, exec_code, is_exec=True) + is_error = isinstance(result, ExceptionOnEvaluate) + + if is_error: + _set_expression_response(py_db, request, result, error_message='Error executing: %s' % (exec_code,)) + return + + # Ok, we have the result (could be an error), let's put it into the saved variables. + frame_tracker = py_db.suspended_frames_manager.get_frame_tracker(thread_id) + if frame_tracker is None: + # This is not really expected. + _set_expression_response(py_db, request, result, error_message='Thread id: %s is not current thread id.' % (thread_id,)) + return + + # Now that the exec is done, get the actual value changed to return. + result = pydevd_vars.evaluate_expression(py_db, frame, expression, is_exec=False) + variable = frame_tracker.obtain_as_variable(expression, result, frame=frame) + var_data = variable.get_var_data(fmt=fmt) + + body = pydevd_schema.SetExpressionResponseBody( + value=var_data['value'], + variablesReference=var_data.get('variablesReference', 0), + type=var_data.get('type'), + presentationHint=var_data.get('presentationHint'), + namedVariables=var_data.get('namedVariables'), + indexedVariables=var_data.get('indexedVariables'), + ) + variables_response = pydevd_base_schema.build_response(request, kwargs={'body':body}) + py_db.writer.add_command(NetCommand(CMD_RETURN, 0, variables_response, is_json=True)) + + +def internal_get_completions(dbg, seq, thread_id, frame_id, act_tok, line=-1, column=-1): + ''' + Note that if the column is >= 0, the act_tok is considered text and the actual + activation token/qualifier is computed in this command. + ''' + try: + remove_path = None + try: + qualifier = '' + if column >= 0: + token_and_qualifier = extract_token_and_qualifier(act_tok, line, column) + act_tok = token_and_qualifier[0] + if act_tok: + act_tok += '.' + qualifier = token_and_qualifier[1] + + frame = dbg.find_frame(thread_id, frame_id) + if frame is not None: + completions = _pydev_completer.generate_completions(frame, act_tok) + + # Note that qualifier and start are only actually valid for the + # Debug Adapter Protocol (for the line-based protocol, the IDE + # is required to filter the completions returned). + cmd = dbg.cmd_factory.make_get_completions_message( + seq, completions, qualifier, start=column - len(qualifier)) + dbg.writer.add_command(cmd) + else: + cmd = dbg.cmd_factory.make_error_message(seq, "internal_get_completions: Frame not found: %s from thread: %s" % (frame_id, thread_id)) + dbg.writer.add_command(cmd) + + finally: + if remove_path is not None: + sys.path.remove(remove_path) + + except: + exc = get_exception_traceback_str() + sys.stderr.write('%s\n' % (exc,)) + cmd = dbg.cmd_factory.make_error_message(seq, "Error evaluating expression " + exc) + dbg.writer.add_command(cmd) + + +def internal_get_description(dbg, seq, thread_id, frame_id, expression): + ''' Fetch the variable description stub from the debug console + ''' + try: + frame = dbg.find_frame(thread_id, frame_id) + description = pydevd_console.get_description(frame, thread_id, frame_id, expression) + description = pydevd_xml.make_valid_xml_value(quote(description, '/>_= \t')) + description_xml = '' % description + cmd = dbg.cmd_factory.make_get_description_message(seq, description_xml) + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + cmd = dbg.cmd_factory.make_error_message(seq, "Error in fetching description" + exc) + dbg.writer.add_command(cmd) + + +def build_exception_info_response(dbg, thread_id, request_seq, set_additional_thread_info, iter_visible_frames_info, max_frames): + ''' + :return ExceptionInfoResponse + ''' + thread = pydevd_find_thread_by_id(thread_id) + additional_info = set_additional_thread_info(thread) + topmost_frame = additional_info.get_topmost_frame(thread) + + current_paused_frame_name = '' + + source_path = '' # This is an extra bit of data used by Visual Studio + stack_str_lst = [] + name = None + description = None + + if topmost_frame is not None: + try: + try: + frames_list = dbg.suspended_frames_manager.get_frames_list(thread_id) + memo = set() + while frames_list is not None and len(frames_list): + frames = [] + + frame = None + + if not name: + exc_type = frames_list.exc_type + if exc_type is not None: + try: + name = exc_type.__qualname__ + except: + try: + name = exc_type.__name__ + except: + try: + name = str(exc_type) + except: + pass + + if not description: + exc_desc = frames_list.exc_desc + if exc_desc is not None: + try: + description = str(exc_desc) + except: + pass + + for frame_id, frame, method_name, original_filename, filename_in_utf8, lineno, _applied_mapping, show_as_current_frame in \ + iter_visible_frames_info(dbg, frames_list): + + line_text = linecache.getline(original_filename, lineno) + + # Never filter out plugin frames! + if not getattr(frame, 'IS_PLUGIN_FRAME', False): + if dbg.is_files_filter_enabled and dbg.apply_files_filter(frame, original_filename, False): + continue + + if show_as_current_frame: + current_paused_frame_name = method_name + method_name += ' (Current frame)' + frames.append((filename_in_utf8, lineno, method_name, line_text)) + + if not source_path and frames: + source_path = frames[0][0] + + stack_str = ''.join(traceback.format_list(frames[-max_frames:])) + stack_str += frames_list.exc_context_msg + stack_str_lst.append(stack_str) + + frames_list = create_frames_list_from_exception_cause( + frames_list.trace_obj, None, frames_list.exc_type, frames_list.exc_desc, memo) + if frames_list is None or not frames_list: + break + + except: + pydev_log.exception('Error on build_exception_info_response.') + finally: + topmost_frame = None + full_stack_str = ''.join(reversed(stack_str_lst)) + + if not name: + name = 'exception: type unknown' + if not description: + description = 'exception: no description' + + if current_paused_frame_name: + name += ' (note: full exception trace is shown but execution is paused at: %s)' % (current_paused_frame_name,) + + if thread.stop_reason == CMD_STEP_CAUGHT_EXCEPTION: + break_mode = pydevd_schema.ExceptionBreakMode.ALWAYS + else: + break_mode = pydevd_schema.ExceptionBreakMode.UNHANDLED + + response = pydevd_schema.ExceptionInfoResponse( + request_seq=request_seq, + success=True, + command='exceptionInfo', + body=pydevd_schema.ExceptionInfoResponseBody( + exceptionId=name, + description=description, + breakMode=break_mode, + details=pydevd_schema.ExceptionDetails( + message=description, + typeName=name, + stackTrace=full_stack_str, + source=source_path, + # Note: ExceptionDetails actually accepts an 'innerException', but + # when passing it, VSCode is not showing the stack trace at all. + ) + ) + ) + return response + + +def internal_get_exception_details_json(dbg, request, thread_id, max_frames, set_additional_thread_info=None, iter_visible_frames_info=None): + ''' Fetch exception details + ''' + try: + response = build_exception_info_response(dbg, thread_id, request.seq, set_additional_thread_info, iter_visible_frames_info, max_frames) + except: + exc = get_exception_traceback_str() + response = pydevd_base_schema.build_response(request, kwargs={ + 'success': False, + 'message': exc, + 'body':{} + }) + dbg.writer.add_command(NetCommand(CMD_RETURN, 0, response, is_json=True)) + + +class InternalGetBreakpointException(InternalThreadCommand): + ''' Send details of exception raised while evaluating conditional breakpoint ''' + + def __init__(self, thread_id, exc_type, stacktrace): + self.sequence = 0 + self.thread_id = thread_id + self.stacktrace = stacktrace + self.exc_type = exc_type + + def do_it(self, dbg): + try: + callstack = "" + + makeValid = pydevd_xml.make_valid_xml_value + + for filename, line, methodname, methodobj in self.stacktrace: + if not filesystem_encoding_is_utf8 and hasattr(filename, "decode"): + # filename is a byte string encoded using the file system encoding + # convert it to utf8 + filename = filename.decode(file_system_encoding).encode("utf-8") + + callstack += '' \ + % (self.thread_id, makeValid(filename), line, makeValid(methodname), makeValid(methodobj)) + callstack += "" + + cmd = dbg.cmd_factory.make_send_breakpoint_exception_message(self.sequence, self.exc_type + "\t" + callstack) + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + sys.stderr.write('%s\n' % (exc,)) + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error Sending Exception: " + exc) + dbg.writer.add_command(cmd) + + +class InternalSendCurrExceptionTrace(InternalThreadCommand): + ''' Send details of the exception that was caught and where we've broken in. + ''' + + def __init__(self, thread_id, arg, curr_frame_id): + ''' + :param arg: exception type, description, traceback object + ''' + self.sequence = 0 + self.thread_id = thread_id + self.curr_frame_id = curr_frame_id + self.arg = arg + + def do_it(self, dbg): + try: + cmd = dbg.cmd_factory.make_send_curr_exception_trace_message(dbg, self.sequence, self.thread_id, self.curr_frame_id, *self.arg) + del self.arg + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + sys.stderr.write('%s\n' % (exc,)) + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error Sending Current Exception Trace: " + exc) + dbg.writer.add_command(cmd) + + +class InternalSendCurrExceptionTraceProceeded(InternalThreadCommand): + ''' Send details of the exception that was caught and where we've broken in. + ''' + + def __init__(self, thread_id): + self.sequence = 0 + self.thread_id = thread_id + + def do_it(self, dbg): + try: + cmd = dbg.cmd_factory.make_send_curr_exception_trace_proceeded_message(self.sequence, self.thread_id) + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + sys.stderr.write('%s\n' % (exc,)) + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error Sending Current Exception Trace Proceeded: " + exc) + dbg.writer.add_command(cmd) + + +class InternalEvaluateConsoleExpression(InternalThreadCommand): + ''' Execute the given command in the debug console ''' + + def __init__(self, seq, thread_id, frame_id, line, buffer_output=True): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.line = line + self.buffer_output = buffer_output + + def do_it(self, dbg): + ''' Create an XML for console output, error and more (true/false) + + + + true/false + + ''' + try: + frame = dbg.find_frame(self.thread_id, self.frame_id) + if frame is not None: + console_message = pydevd_console.execute_console_command( + frame, self.thread_id, self.frame_id, self.line, self.buffer_output) + + cmd = dbg.cmd_factory.make_send_console_message(self.sequence, console_message.to_xml()) + else: + from _pydevd_bundle.pydevd_console import ConsoleMessage + console_message = ConsoleMessage() + console_message.add_console_message( + pydevd_console.CONSOLE_ERROR, + "Select the valid frame in the debug view (thread: %s, frame: %s invalid)" % (self.thread_id, self.frame_id), + ) + cmd = dbg.cmd_factory.make_error_message(self.sequence, console_message.to_xml()) + except: + exc = get_exception_traceback_str() + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating expression " + exc) + dbg.writer.add_command(cmd) + + +class InternalRunCustomOperation(InternalThreadCommand): + ''' Run a custom command on an expression + ''' + + def __init__(self, seq, thread_id, frame_id, scope, attrs, style, encoded_code_or_file, fnname): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.scope = scope + self.attrs = attrs + self.style = style + self.code_or_file = unquote_plus(encoded_code_or_file) + self.fnname = fnname + + def do_it(self, dbg): + try: + res = pydevd_vars.custom_operation(dbg, self.thread_id, self.frame_id, self.scope, self.attrs, + self.style, self.code_or_file, self.fnname) + resEncoded = quote_plus(res) + cmd = dbg.cmd_factory.make_custom_operation_message(self.sequence, resEncoded) + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in running custom operation" + exc) + dbg.writer.add_command(cmd) + + +class InternalConsoleGetCompletions(InternalThreadCommand): + ''' Fetch the completions in the debug console + ''' + + def __init__(self, seq, thread_id, frame_id, act_tok): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.act_tok = act_tok + + def do_it(self, dbg): + ''' Get completions and write back to the client + ''' + try: + frame = dbg.find_frame(self.thread_id, self.frame_id) + completions_xml = pydevd_console.get_completions(frame, self.act_tok) + cmd = dbg.cmd_factory.make_send_console_message(self.sequence, completions_xml) + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in fetching completions" + exc) + dbg.writer.add_command(cmd) + + +class InternalConsoleExec(InternalThreadCommand): + ''' gets the value of a variable ''' + + def __init__(self, seq, thread_id, frame_id, expression): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.expression = expression + + def do_it(self, dbg): + ''' Converts request into python variable ''' + try: + try: + # don't trace new threads created by console command + disable_trace_thread_modules() + + result = pydevconsole.console_exec(self.thread_id, self.frame_id, self.expression, dbg) + xml = "" + xml += pydevd_xml.var_to_xml(result, "") + xml += "" + cmd = dbg.cmd_factory.make_evaluate_expression_message(self.sequence, xml) + dbg.writer.add_command(cmd) + except: + exc = get_exception_traceback_str() + sys.stderr.write('%s\n' % (exc,)) + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating console expression " + exc) + dbg.writer.add_command(cmd) + finally: + enable_trace_thread_modules() + + sys.stderr.flush() + sys.stdout.flush() + + +class InternalLoadFullValue(InternalThreadCommand): + ''' + Loads values asynchronously + ''' + + def __init__(self, seq, thread_id, frame_id, vars): + self.sequence = seq + self.thread_id = thread_id + self.frame_id = frame_id + self.vars = vars + + @silence_warnings_decorator + def do_it(self, dbg): + '''Starts a thread that will load values asynchronously''' + try: + var_objects = [] + for variable in self.vars: + variable = variable.strip() + if len(variable) > 0: + if '\t' in variable: # there are attributes beyond scope + scope, attrs = variable.split('\t', 1) + name = attrs[0] + else: + scope, attrs = (variable, None) + name = scope + var_obj = pydevd_vars.getVariable(dbg, self.thread_id, self.frame_id, scope, attrs) + var_objects.append((var_obj, name)) + + t = GetValueAsyncThreadDebug(dbg, dbg, self.sequence, var_objects) + t.start() + except: + exc = get_exception_traceback_str() + sys.stderr.write('%s\n' % (exc,)) + cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating variable %s " % exc) + dbg.writer.add_command(cmd) + + +class AbstractGetValueAsyncThread(PyDBDaemonThread): + ''' + Abstract class for a thread, which evaluates values for async variables + ''' + + def __init__(self, py_db, frame_accessor, seq, var_objects): + PyDBDaemonThread.__init__(self, py_db) + self.frame_accessor = frame_accessor + self.seq = seq + self.var_objs = var_objects + self.cancel_event = threading.Event() + + def send_result(self, xml): + raise NotImplementedError() + + @overrides(PyDBDaemonThread._on_run) + def _on_run(self): + start = time.time() + xml = StringIO() + xml.write("") + for (var_obj, name) in self.var_objs: + current_time = time.time() + if current_time - start > ASYNC_EVAL_TIMEOUT_SEC or self.cancel_event.is_set(): + break + xml.write(pydevd_xml.var_to_xml(var_obj, name, evaluate_full_value=True)) + xml.write("") + self.send_result(xml) + xml.close() + + +class GetValueAsyncThreadDebug(AbstractGetValueAsyncThread): + ''' + A thread for evaluation async values, which returns result for debugger + Create message and send it via writer thread + ''' + + def send_result(self, xml): + if self.frame_accessor is not None: + cmd = self.frame_accessor.cmd_factory.make_load_full_value_message(self.seq, xml.getvalue()) + self.frame_accessor.writer.add_command(cmd) + + +class GetValueAsyncThreadConsole(AbstractGetValueAsyncThread): + ''' + A thread for evaluation async values, which returns result for Console + Send result directly to Console's server + ''' + + def send_result(self, xml): + if self.frame_accessor is not None: + self.frame_accessor.ReturnFullValue(self.seq, xml.getvalue()) + diff --git a/_pydevd_bundle/pydevd_comm_constants.py b/_pydevd_bundle/pydevd_comm_constants.py new file mode 100644 index 0000000..ad05a32 --- /dev/null +++ b/_pydevd_bundle/pydevd_comm_constants.py @@ -0,0 +1,208 @@ +CMD_RUN = 101 +CMD_LIST_THREADS = 102 +CMD_THREAD_CREATE = 103 +CMD_THREAD_KILL = 104 +CMD_THREAD_SUSPEND = 105 +CMD_THREAD_RUN = 106 +CMD_STEP_INTO = 107 +CMD_STEP_OVER = 108 +CMD_STEP_RETURN = 109 +CMD_GET_VARIABLE = 110 +CMD_SET_BREAK = 111 +CMD_REMOVE_BREAK = 112 +CMD_EVALUATE_EXPRESSION = 113 +CMD_GET_FRAME = 114 +CMD_EXEC_EXPRESSION = 115 +CMD_WRITE_TO_CONSOLE = 116 +CMD_CHANGE_VARIABLE = 117 +CMD_RUN_TO_LINE = 118 +CMD_RELOAD_CODE = 119 +CMD_GET_COMPLETIONS = 120 + +# Note: renumbered (conflicted on merge) +CMD_CONSOLE_EXEC = 121 +CMD_ADD_EXCEPTION_BREAK = 122 +CMD_REMOVE_EXCEPTION_BREAK = 123 +CMD_LOAD_SOURCE = 124 +CMD_ADD_DJANGO_EXCEPTION_BREAK = 125 +CMD_REMOVE_DJANGO_EXCEPTION_BREAK = 126 +CMD_SET_NEXT_STATEMENT = 127 +CMD_SMART_STEP_INTO = 128 +CMD_EXIT = 129 +CMD_SIGNATURE_CALL_TRACE = 130 + +CMD_SET_PY_EXCEPTION = 131 +CMD_GET_FILE_CONTENTS = 132 +CMD_SET_PROPERTY_TRACE = 133 +# Pydev debug console commands +CMD_EVALUATE_CONSOLE_EXPRESSION = 134 +CMD_RUN_CUSTOM_OPERATION = 135 +CMD_GET_BREAKPOINT_EXCEPTION = 136 +CMD_STEP_CAUGHT_EXCEPTION = 137 +CMD_SEND_CURR_EXCEPTION_TRACE = 138 +CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED = 139 +CMD_IGNORE_THROWN_EXCEPTION_AT = 140 +CMD_ENABLE_DONT_TRACE = 141 +CMD_SHOW_CONSOLE = 142 + +CMD_GET_ARRAY = 143 +CMD_STEP_INTO_MY_CODE = 144 +CMD_GET_CONCURRENCY_EVENT = 145 +CMD_SHOW_RETURN_VALUES = 146 +CMD_INPUT_REQUESTED = 147 +CMD_GET_DESCRIPTION = 148 + +CMD_PROCESS_CREATED = 149 +CMD_SHOW_CYTHON_WARNING = 150 +CMD_LOAD_FULL_VALUE = 151 + +CMD_GET_THREAD_STACK = 152 + +# This is mostly for unit-tests to diagnose errors on ci. +CMD_THREAD_DUMP_TO_STDERR = 153 + +# Sent from the client to signal that we should stop when we start executing user code. +CMD_STOP_ON_START = 154 + +# When the debugger is stopped in an exception, this command will provide the details of the current exception (in the current thread). +CMD_GET_EXCEPTION_DETAILS = 155 + +# Allows configuring pydevd settings (can be called multiple times and only keys +# available in the json will be configured -- keys not passed will not change the +# previous configuration). +CMD_PYDEVD_JSON_CONFIG = 156 + +CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION = 157 +CMD_THREAD_RESUME_SINGLE_NOTIFICATION = 158 + +CMD_STEP_OVER_MY_CODE = 159 +CMD_STEP_RETURN_MY_CODE = 160 + +CMD_SET_PY_EXCEPTION_JSON = 161 +CMD_SET_PATH_MAPPING_JSON = 162 + +CMD_GET_SMART_STEP_INTO_VARIANTS = 163 # XXX: PyCharm has 160 for this (we're currently incompatible anyways). + +CMD_REDIRECT_OUTPUT = 200 +CMD_GET_NEXT_STATEMENT_TARGETS = 201 +CMD_SET_PROJECT_ROOTS = 202 + +CMD_MODULE_EVENT = 203 +CMD_PROCESS_EVENT = 204 + +CMD_AUTHENTICATE = 205 + +CMD_STEP_INTO_COROUTINE = 206 + +CMD_LOAD_SOURCE_FROM_FRAME_ID = 207 + +CMD_SET_FUNCTION_BREAK = 208 + +CMD_VERSION = 501 +CMD_RETURN = 502 +CMD_SET_PROTOCOL = 503 +CMD_ERROR = 901 + +# this number can be changed if there's need to do so +# if the io is too big, we'll not send all (could make the debugger too non-responsive) +MAX_IO_MSG_SIZE = 10000 + +VERSION_STRING = "@@BUILD_NUMBER@@" + +from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding +file_system_encoding = getfilesystemencoding() +filesystem_encoding_is_utf8 = file_system_encoding.lower() in ('utf-8', 'utf_8', 'utf8') + +ID_TO_MEANING = { + '101': 'CMD_RUN', + '102': 'CMD_LIST_THREADS', + '103': 'CMD_THREAD_CREATE', + '104': 'CMD_THREAD_KILL', + '105': 'CMD_THREAD_SUSPEND', + '106': 'CMD_THREAD_RUN', + '107': 'CMD_STEP_INTO', + '108': 'CMD_STEP_OVER', + '109': 'CMD_STEP_RETURN', + '110': 'CMD_GET_VARIABLE', + '111': 'CMD_SET_BREAK', + '112': 'CMD_REMOVE_BREAK', + '113': 'CMD_EVALUATE_EXPRESSION', + '114': 'CMD_GET_FRAME', + '115': 'CMD_EXEC_EXPRESSION', + '116': 'CMD_WRITE_TO_CONSOLE', + '117': 'CMD_CHANGE_VARIABLE', + '118': 'CMD_RUN_TO_LINE', + '119': 'CMD_RELOAD_CODE', + '120': 'CMD_GET_COMPLETIONS', + '121': 'CMD_CONSOLE_EXEC', + '122': 'CMD_ADD_EXCEPTION_BREAK', + '123': 'CMD_REMOVE_EXCEPTION_BREAK', + '124': 'CMD_LOAD_SOURCE', + '125': 'CMD_ADD_DJANGO_EXCEPTION_BREAK', + '126': 'CMD_REMOVE_DJANGO_EXCEPTION_BREAK', + '127': 'CMD_SET_NEXT_STATEMENT', + '128': 'CMD_SMART_STEP_INTO', + '129': 'CMD_EXIT', + '130': 'CMD_SIGNATURE_CALL_TRACE', + + '131': 'CMD_SET_PY_EXCEPTION', + '132': 'CMD_GET_FILE_CONTENTS', + '133': 'CMD_SET_PROPERTY_TRACE', + '134': 'CMD_EVALUATE_CONSOLE_EXPRESSION', + '135': 'CMD_RUN_CUSTOM_OPERATION', + '136': 'CMD_GET_BREAKPOINT_EXCEPTION', + '137': 'CMD_STEP_CAUGHT_EXCEPTION', + '138': 'CMD_SEND_CURR_EXCEPTION_TRACE', + '139': 'CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED', + '140': 'CMD_IGNORE_THROWN_EXCEPTION_AT', + '141': 'CMD_ENABLE_DONT_TRACE', + '142': 'CMD_SHOW_CONSOLE', + '143': 'CMD_GET_ARRAY', + '144': 'CMD_STEP_INTO_MY_CODE', + '145': 'CMD_GET_CONCURRENCY_EVENT', + '146': 'CMD_SHOW_RETURN_VALUES', + '147': 'CMD_INPUT_REQUESTED', + '148': 'CMD_GET_DESCRIPTION', + + '149': 'CMD_PROCESS_CREATED', # Note: this is actually a notification of a sub-process created. + '150': 'CMD_SHOW_CYTHON_WARNING', + '151': 'CMD_LOAD_FULL_VALUE', + '152': 'CMD_GET_THREAD_STACK', + '153': 'CMD_THREAD_DUMP_TO_STDERR', + '154': 'CMD_STOP_ON_START', + '155': 'CMD_GET_EXCEPTION_DETAILS', + '156': 'CMD_PYDEVD_JSON_CONFIG', + '157': 'CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION', + '158': 'CMD_THREAD_RESUME_SINGLE_NOTIFICATION', + + '159': 'CMD_STEP_OVER_MY_CODE', + '160': 'CMD_STEP_RETURN_MY_CODE', + + '161': 'CMD_SET_PY_EXCEPTION_JSON', + '162': 'CMD_SET_PATH_MAPPING_JSON', + '163': 'CMD_GET_SMART_STEP_INTO_VARIANTS', + + '200': 'CMD_REDIRECT_OUTPUT', + '201': 'CMD_GET_NEXT_STATEMENT_TARGETS', + '202': 'CMD_SET_PROJECT_ROOTS', + '203': 'CMD_MODULE_EVENT', + '204': 'CMD_PROCESS_EVENT', # DAP process event. + + '205': 'CMD_AUTHENTICATE', + + '206': 'CMD_STEP_INTO_COROUTINE', + + '207': 'CMD_LOAD_SOURCE_FROM_FRAME_ID', + + '501': 'CMD_VERSION', + '502': 'CMD_RETURN', + '503': 'CMD_SET_PROTOCOL', + '901': 'CMD_ERROR', +} + + +def constant_to_str(constant): + s = ID_TO_MEANING.get(str(constant)) + if not s: + s = '' % (constant,) + return s diff --git a/_pydevd_bundle/pydevd_command_line_handling.py b/_pydevd_bundle/pydevd_command_line_handling.py new file mode 100644 index 0000000..ea7f745 --- /dev/null +++ b/_pydevd_bundle/pydevd_command_line_handling.py @@ -0,0 +1,183 @@ +import os +import sys + + +class ArgHandlerWithParam: + ''' + Handler for some arguments which needs a value + ''' + + def __init__(self, arg_name, convert_val=None, default_val=None): + self.arg_name = arg_name + self.arg_v_rep = '--%s' % (arg_name,) + self.convert_val = convert_val + self.default_val = default_val + + def to_argv(self, lst, setup): + v = setup.get(self.arg_name) + if v is not None and v != self.default_val: + lst.append(self.arg_v_rep) + lst.append('%s' % (v,)) + + def handle_argv(self, argv, i, setup): + assert argv[i] == self.arg_v_rep + del argv[i] + + val = argv[i] + if self.convert_val: + val = self.convert_val(val) + + setup[self.arg_name] = val + del argv[i] + + +class ArgHandlerBool: + ''' + If a given flag is received, mark it as 'True' in setup. + ''' + + def __init__(self, arg_name, default_val=False): + self.arg_name = arg_name + self.arg_v_rep = '--%s' % (arg_name,) + self.default_val = default_val + + def to_argv(self, lst, setup): + v = setup.get(self.arg_name) + if v: + lst.append(self.arg_v_rep) + + def handle_argv(self, argv, i, setup): + assert argv[i] == self.arg_v_rep + del argv[i] + setup[self.arg_name] = True + + +def convert_ppid(ppid): + ret = int(ppid) + if ret != 0: + if ret == os.getpid(): + raise AssertionError( + 'ppid passed is the same as the current process pid (%s)!' % (ret,)) + return ret + + +ACCEPTED_ARG_HANDLERS = [ + ArgHandlerWithParam('port', int, 0), + ArgHandlerWithParam('ppid', convert_ppid, 0), + ArgHandlerWithParam('vm_type'), + ArgHandlerWithParam('client'), + ArgHandlerWithParam('access-token'), + ArgHandlerWithParam('client-access-token'), + + # Logging + ArgHandlerWithParam('log-file'), + ArgHandlerWithParam('log-level', int, 0), + + ArgHandlerBool('server'), + ArgHandlerBool('multiproc'), # Used by PyCharm (reuses connection: ssh tunneling) + ArgHandlerBool('multiprocess'), # Used by PyDev (creates new connection to ide) + ArgHandlerBool('save-signatures'), + ArgHandlerBool('save-threading'), + ArgHandlerBool('save-asyncio'), + ArgHandlerBool('print-in-debugger-startup'), + ArgHandlerBool('cmd-line'), + ArgHandlerBool('module'), + ArgHandlerBool('skip-notify-stdin'), + + # The ones below should've been just one setting to specify the protocol, but for compatibility + # reasons they're passed as a flag but are mutually exclusive. + ArgHandlerBool('json-dap'), # Protocol used by ptvsd to communicate with pydevd (a single json message in each read) + ArgHandlerBool('json-dap-http'), # Actual DAP (json messages over http protocol). + ArgHandlerBool('protocol-quoted-line'), # Custom protocol with quoted lines. + ArgHandlerBool('protocol-http'), # Custom protocol with http. +] + +ARGV_REP_TO_HANDLER = {} +for handler in ACCEPTED_ARG_HANDLERS: + ARGV_REP_TO_HANDLER[handler.arg_v_rep] = handler + + +def get_pydevd_file(): + import pydevd + f = pydevd.__file__ + if f.endswith('.pyc'): + f = f[:-1] + elif f.endswith('$py.class'): + f = f[:-len('$py.class')] + '.py' + return f + + +def setup_to_argv(setup, skip_names=None): + ''' + :param dict setup: + A dict previously gotten from process_command_line. + + :param set skip_names: + The names in the setup which shouldn't be converted to argv. + + :note: does not handle --file nor --DEBUG. + ''' + if skip_names is None: + skip_names = set() + ret = [get_pydevd_file()] + + for handler in ACCEPTED_ARG_HANDLERS: + if handler.arg_name in setup and handler.arg_name not in skip_names: + handler.to_argv(ret, setup) + return ret + + +def process_command_line(argv): + """ parses the arguments. + removes our arguments from the command line """ + setup = {} + for handler in ACCEPTED_ARG_HANDLERS: + setup[handler.arg_name] = handler.default_val + setup['file'] = '' + setup['qt-support'] = '' + + initial_argv = tuple(argv) + + i = 0 + del argv[0] + while i < len(argv): + handler = ARGV_REP_TO_HANDLER.get(argv[i]) + if handler is not None: + handler.handle_argv(argv, i, setup) + + elif argv[i].startswith('--qt-support'): + # The --qt-support is special because we want to keep backward compatibility: + # Previously, just passing '--qt-support' meant that we should use the auto-discovery mode + # whereas now, if --qt-support is passed, it should be passed as --qt-support=, where + # mode can be one of 'auto', 'none', 'pyqt5', 'pyqt4', 'pyside', 'pyside2'. + if argv[i] == '--qt-support': + setup['qt-support'] = 'auto' + + elif argv[i].startswith('--qt-support='): + qt_support = argv[i][len('--qt-support='):] + valid_modes = ('none', 'auto', 'pyqt5', 'pyqt4', 'pyside', 'pyside2') + if qt_support not in valid_modes: + raise ValueError("qt-support mode invalid: " + qt_support) + if qt_support == 'none': + # On none, actually set an empty string to evaluate to False. + setup['qt-support'] = '' + else: + setup['qt-support'] = qt_support + else: + raise ValueError("Unexpected definition for qt-support flag: " + argv[i]) + + del argv[i] + + elif argv[i] == '--file': + # --file is special because it's the last one (so, no handler for it). + del argv[i] + setup['file'] = argv[i] + i = len(argv) # pop out, file is our last argument + + elif argv[i] == '--DEBUG': + sys.stderr.write('pydevd: --DEBUG parameter deprecated. Use `--debug-level=3` instead.\n') + + else: + raise ValueError("Unexpected option: %s when processing: %s" % (argv[i], initial_argv)) + return setup + diff --git a/_pydevd_bundle/pydevd_concurrency_analyser/__init__.py b/_pydevd_bundle/pydevd_concurrency_analyser/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/_pydevd_bundle/pydevd_concurrency_analyser/pydevd_concurrency_logger.py b/_pydevd_bundle/pydevd_concurrency_analyser/pydevd_concurrency_logger.py new file mode 100644 index 0000000..95fc054 --- /dev/null +++ b/_pydevd_bundle/pydevd_concurrency_analyser/pydevd_concurrency_logger.py @@ -0,0 +1,346 @@ +import time + +from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle import pydevd_xml +from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder +from _pydevd_bundle.pydevd_constants import get_thread_id +from _pydevd_bundle.pydevd_net_command import NetCommand +from _pydevd_bundle.pydevd_concurrency_analyser.pydevd_thread_wrappers import ObjectWrapper, wrap_attr +import pydevd_file_utils +from _pydev_bundle import pydev_log +import sys + +file_system_encoding = getfilesystemencoding() + +from urllib.parse import quote + +threadingCurrentThread = threading.current_thread + +DONT_TRACE_THREADING = ['threading.py', 'pydevd.py'] +INNER_METHODS = ['_stop'] +INNER_FILES = ['threading.py'] +THREAD_METHODS = ['start', '_stop', 'join'] +LOCK_METHODS = ['__init__', 'acquire', 'release', '__enter__', '__exit__'] +QUEUE_METHODS = ['put', 'get'] + +# return time since epoch in milliseconds +cur_time = lambda: int(round(time.time() * 1000000)) + + +def get_text_list_for_frame(frame): + # partial copy-paste from make_thread_suspend_str + curFrame = frame + cmdTextList = [] + try: + while curFrame: + # print cmdText + myId = str(id(curFrame)) + # print "id is ", myId + + if curFrame.f_code is None: + break # Iron Python sometimes does not have it! + + myName = curFrame.f_code.co_name # method name (if in method) or ? if global + if myName is None: + break # Iron Python sometimes does not have it! + + # print "name is ", myName + + absolute_filename = pydevd_file_utils.get_abs_path_real_path_and_base_from_frame(curFrame)[0] + + my_file, _applied_mapping = pydevd_file_utils.map_file_to_client(absolute_filename) + + # print "file is ", my_file + # my_file = inspect.getsourcefile(curFrame) or inspect.getfile(frame) + + myLine = str(curFrame.f_lineno) + # print "line is ", myLine + + # the variables are all gotten 'on-demand' + # variables = pydevd_xml.frame_vars_to_xml(curFrame.f_locals) + + variables = '' + cmdTextList.append('' % (quote(my_file, '/>_= \t'), myLine)) + cmdTextList.append(variables) + cmdTextList.append("") + curFrame = curFrame.f_back + except: + pydev_log.exception() + + return cmdTextList + + +def send_concurrency_message(event_class, time, name, thread_id, type, event, file, line, frame, lock_id=0, parent=None): + dbg = GlobalDebuggerHolder.global_dbg + if dbg is None: + return + cmdTextList = [''] + + cmdTextList.append('<' + event_class) + cmdTextList.append(' time="%s"' % pydevd_xml.make_valid_xml_value(str(time))) + cmdTextList.append(' name="%s"' % pydevd_xml.make_valid_xml_value(name)) + cmdTextList.append(' thread_id="%s"' % pydevd_xml.make_valid_xml_value(thread_id)) + cmdTextList.append(' type="%s"' % pydevd_xml.make_valid_xml_value(type)) + if type == "lock": + cmdTextList.append(' lock_id="%s"' % pydevd_xml.make_valid_xml_value(str(lock_id))) + if parent is not None: + cmdTextList.append(' parent="%s"' % pydevd_xml.make_valid_xml_value(parent)) + cmdTextList.append(' event="%s"' % pydevd_xml.make_valid_xml_value(event)) + cmdTextList.append(' file="%s"' % pydevd_xml.make_valid_xml_value(file)) + cmdTextList.append(' line="%s"' % pydevd_xml.make_valid_xml_value(str(line))) + cmdTextList.append('>') + + cmdTextList += get_text_list_for_frame(frame) + cmdTextList.append('') + + text = ''.join(cmdTextList) + if dbg.writer is not None: + dbg.writer.add_command(NetCommand(145, 0, text)) + + +def log_new_thread(global_debugger, t): + event_time = cur_time() - global_debugger.thread_analyser.start_time + send_concurrency_message("threading_event", event_time, t.name, get_thread_id(t), "thread", + "start", "code_name", 0, None, parent=get_thread_id(t)) + + +class ThreadingLogger: + + def __init__(self): + self.start_time = cur_time() + + def set_start_time(self, time): + self.start_time = time + + def log_event(self, frame): + write_log = False + self_obj = None + if "self" in frame.f_locals: + self_obj = frame.f_locals["self"] + if isinstance(self_obj, threading.Thread) or self_obj.__class__ == ObjectWrapper: + write_log = True + if hasattr(frame, "f_back") and frame.f_back is not None: + back = frame.f_back + if hasattr(back, "f_back") and back.f_back is not None: + back = back.f_back + if "self" in back.f_locals: + if isinstance(back.f_locals["self"], threading.Thread): + write_log = True + try: + if write_log: + t = threadingCurrentThread() + back = frame.f_back + if not back: + return + name, _, back_base = pydevd_file_utils.get_abs_path_real_path_and_base_from_frame(back) + event_time = cur_time() - self.start_time + method_name = frame.f_code.co_name + + if isinstance(self_obj, threading.Thread): + if not hasattr(self_obj, "_pydev_run_patched"): + wrap_attr(self_obj, "run") + if (method_name in THREAD_METHODS) and (back_base not in DONT_TRACE_THREADING or \ + (method_name in INNER_METHODS and back_base in INNER_FILES)): + thread_id = get_thread_id(self_obj) + name = self_obj.getName() + real_method = frame.f_code.co_name + parent = None + if real_method == "_stop": + if back_base in INNER_FILES and \ + back.f_code.co_name == "_wait_for_tstate_lock": + back = back.f_back.f_back + real_method = "stop" + if hasattr(self_obj, "_pydev_join_called"): + parent = get_thread_id(t) + elif real_method == "join": + # join called in the current thread, not in self object + if not self_obj.is_alive(): + return + thread_id = get_thread_id(t) + name = t.name + self_obj._pydev_join_called = True + + if real_method == "start": + parent = get_thread_id(t) + send_concurrency_message("threading_event", event_time, name, thread_id, "thread", + real_method, back.f_code.co_filename, back.f_lineno, back, parent=parent) + # print(event_time, self_obj.getName(), thread_id, "thread", + # real_method, back.f_code.co_filename, back.f_lineno) + + if method_name == "pydev_after_run_call": + if hasattr(frame, "f_back") and frame.f_back is not None: + back = frame.f_back + if hasattr(back, "f_back") and back.f_back is not None: + back = back.f_back + if "self" in back.f_locals: + if isinstance(back.f_locals["self"], threading.Thread): + my_self_obj = frame.f_back.f_back.f_locals["self"] + my_back = frame.f_back.f_back + my_thread_id = get_thread_id(my_self_obj) + send_massage = True + if hasattr(my_self_obj, "_pydev_join_called"): + send_massage = False + # we can't detect stop after join in Python 2 yet + if send_massage: + send_concurrency_message("threading_event", event_time, "Thread", my_thread_id, "thread", + "stop", my_back.f_code.co_filename, my_back.f_lineno, my_back, parent=None) + + if self_obj.__class__ == ObjectWrapper: + if back_base in DONT_TRACE_THREADING: + # do not trace methods called from threading + return + back_back_base = pydevd_file_utils.get_abs_path_real_path_and_base_from_frame(back.f_back)[2] + back = back.f_back + if back_back_base in DONT_TRACE_THREADING: + # back_back_base is the file, where the method was called froms + return + if method_name == "__init__": + send_concurrency_message("threading_event", event_time, t.name, get_thread_id(t), "lock", + method_name, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(frame.f_locals["self"]))) + if "attr" in frame.f_locals and \ + (frame.f_locals["attr"] in LOCK_METHODS or + frame.f_locals["attr"] in QUEUE_METHODS): + real_method = frame.f_locals["attr"] + if method_name == "call_begin": + real_method += "_begin" + elif method_name == "call_end": + real_method += "_end" + else: + return + if real_method == "release_end": + # do not log release end. Maybe use it later + return + send_concurrency_message("threading_event", event_time, t.name, get_thread_id(t), "lock", + real_method, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj))) + + if real_method in ("put_end", "get_end"): + # fake release for queue, cause we don't call it directly + send_concurrency_message("threading_event", event_time, t.name, get_thread_id(t), "lock", + "release", back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj))) + # print(event_time, t.name, get_thread_id(t), "lock", + # real_method, back.f_code.co_filename, back.f_lineno) + + except Exception: + pydev_log.exception() + + +class NameManager: + + def __init__(self, name_prefix): + self.tasks = {} + self.last = 0 + self.prefix = name_prefix + + def get(self, id): + if id not in self.tasks: + self.last += 1 + self.tasks[id] = self.prefix + "-" + str(self.last) + return self.tasks[id] + + +class AsyncioLogger: + + def __init__(self): + self.task_mgr = NameManager("Task") + self.coro_mgr = NameManager("Coro") + self.start_time = cur_time() + + def get_task_id(self, frame): + asyncio = sys.modules.get('asyncio') + if asyncio is None: + # If asyncio was not imported, there's nothing to be done + # (also fixes issue where multiprocessing is imported due + # to asyncio). + return None + while frame is not None: + if "self" in frame.f_locals: + self_obj = frame.f_locals["self"] + if isinstance(self_obj, asyncio.Task): + method_name = frame.f_code.co_name + if method_name == "_step": + return id(self_obj) + frame = frame.f_back + return None + + def log_event(self, frame): + event_time = cur_time() - self.start_time + + # Debug loop iterations + # if isinstance(self_obj, asyncio.base_events.BaseEventLoop): + # if method_name == "_run_once": + # print("Loop iteration") + + if not hasattr(frame, "f_back") or frame.f_back is None: + return + + asyncio = sys.modules.get('asyncio') + if asyncio is None: + # If asyncio was not imported, there's nothing to be done + # (also fixes issue where multiprocessing is imported due + # to asyncio). + return + + back = frame.f_back + + if "self" in frame.f_locals: + self_obj = frame.f_locals["self"] + if isinstance(self_obj, asyncio.Task): + method_name = frame.f_code.co_name + if method_name == "set_result": + task_id = id(self_obj) + task_name = self.task_mgr.get(str(task_id)) + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "thread", "stop", frame.f_code.co_filename, + frame.f_lineno, frame) + + method_name = back.f_code.co_name + if method_name == "__init__": + task_id = id(self_obj) + task_name = self.task_mgr.get(str(task_id)) + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "thread", "start", frame.f_code.co_filename, + frame.f_lineno, frame) + + method_name = frame.f_code.co_name + if isinstance(self_obj, asyncio.Lock): + if method_name in ("acquire", "release"): + task_id = self.get_task_id(frame) + task_name = self.task_mgr.get(str(task_id)) + + if method_name == "acquire": + if not self_obj._waiters and not self_obj.locked(): + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "lock", + method_name + "_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) + if self_obj.locked(): + method_name += "_begin" + else: + method_name += "_end" + elif method_name == "release": + method_name += "_end" + + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "lock", + method_name, frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) + + if isinstance(self_obj, asyncio.Queue): + if method_name in ("put", "get", "_put", "_get"): + task_id = self.get_task_id(frame) + task_name = self.task_mgr.get(str(task_id)) + + if method_name == "put": + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "lock", + "acquire_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) + elif method_name == "_put": + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "lock", + "acquire_end", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "lock", + "release", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) + elif method_name == "get": + back = frame.f_back + if back.f_code.co_name != "send": + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "lock", + "acquire_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) + else: + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "lock", + "acquire_end", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) + send_concurrency_message("asyncio_event", event_time, task_name, task_name, "lock", + "release", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) diff --git a/_pydevd_bundle/pydevd_concurrency_analyser/pydevd_thread_wrappers.py b/_pydevd_bundle/pydevd_concurrency_analyser/pydevd_thread_wrappers.py new file mode 100644 index 0000000..526bb0c --- /dev/null +++ b/_pydevd_bundle/pydevd_concurrency_analyser/pydevd_thread_wrappers.py @@ -0,0 +1,83 @@ +from _pydev_bundle._pydev_saved_modules import threading + + +def wrapper(fun): + + def pydev_after_run_call(): + pass + + def inner(*args, **kwargs): + fun(*args, **kwargs) + pydev_after_run_call() + + return inner + + +def wrap_attr(obj, attr): + t_save_start = getattr(obj, attr) + setattr(obj, attr, wrapper(t_save_start)) + obj._pydev_run_patched = True + + +class ObjectWrapper(object): + + def __init__(self, obj): + self.wrapped_object = obj + try: + import functools + functools.update_wrapper(self, obj) + except: + pass + + def __getattr__(self, attr): + orig_attr = getattr(self.wrapped_object, attr) # .__getattribute__(attr) + if callable(orig_attr): + + def patched_attr(*args, **kwargs): + self.call_begin(attr) + result = orig_attr(*args, **kwargs) + self.call_end(attr) + if result == self.wrapped_object: + return self + return result + + return patched_attr + else: + return orig_attr + + def call_begin(self, attr): + pass + + def call_end(self, attr): + pass + + def __enter__(self): + self.call_begin("__enter__") + self.wrapped_object.__enter__() + self.call_end("__enter__") + + def __exit__(self, exc_type, exc_val, exc_tb): + self.call_begin("__exit__") + self.wrapped_object.__exit__(exc_type, exc_val, exc_tb) + + +def factory_wrapper(fun): + + def inner(*args, **kwargs): + obj = fun(*args, **kwargs) + return ObjectWrapper(obj) + + return inner + + +def wrap_threads(): + # TODO: add wrappers for thread and _thread + # import _thread as mod + # print("Thread imported") + # mod.start_new_thread = wrapper(mod.start_new_thread) + threading.Lock = factory_wrapper(threading.Lock) + threading.RLock = factory_wrapper(threading.RLock) + + # queue patching + import queue # @UnresolvedImport + queue.Queue = factory_wrapper(queue.Queue) diff --git a/_pydevd_bundle/pydevd_console.py b/_pydevd_bundle/pydevd_console.py new file mode 100644 index 0000000..925e010 --- /dev/null +++ b/_pydevd_bundle/pydevd_console.py @@ -0,0 +1,270 @@ +'''An helper file for the pydev debugger (REPL) console +''' +import sys +import traceback +from _pydevd_bundle.pydevconsole_code import InteractiveConsole, _EvalAwaitInNewEventLoop +from _pydev_bundle import _pydev_completer +from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface, BaseStdIn +from _pydev_bundle.pydev_imports import Exec +from _pydev_bundle.pydev_override import overrides +from _pydevd_bundle import pydevd_save_locals +from _pydevd_bundle.pydevd_io import IOBuf +from pydevd_tracing import get_exception_traceback_str +from _pydevd_bundle.pydevd_xml import make_valid_xml_value +import inspect +from _pydevd_bundle.pydevd_save_locals import update_globals_and_locals + +CONSOLE_OUTPUT = "output" +CONSOLE_ERROR = "error" + + +#======================================================================================================================= +# ConsoleMessage +#======================================================================================================================= +class ConsoleMessage: + """Console Messages + """ + + def __init__(self): + self.more = False + # List of tuple [('error', 'error_message'), ('message_list', 'output_message')] + self.console_messages = [] + + def add_console_message(self, message_type, message): + """add messages in the console_messages list + """ + for m in message.split("\n"): + if m.strip(): + self.console_messages.append((message_type, m)) + + def update_more(self, more): + """more is set to true if further input is required from the user + else more is set to false + """ + self.more = more + + def to_xml(self): + """Create an XML for console message_list, error and more (true/false) + + console message_list + console error + true/false + + """ + makeValid = make_valid_xml_value + + xml = '%s' % (self.more) + + for message_type, message in self.console_messages: + xml += '<%s message="%s">' % (message_type, makeValid(message), message_type) + + xml += '' + + return xml + + +#======================================================================================================================= +# _DebugConsoleStdIn +#======================================================================================================================= +class _DebugConsoleStdIn(BaseStdIn): + + @overrides(BaseStdIn.readline) + def readline(self, *args, **kwargs): + sys.stderr.write('Warning: Reading from stdin is still not supported in this console.\n') + return '\n' + + +#======================================================================================================================= +# DebugConsole +#======================================================================================================================= +class DebugConsole(InteractiveConsole, BaseInterpreterInterface): + """Wrapper around code.InteractiveConsole, in order to send + errors and outputs to the debug console + """ + + @overrides(BaseInterpreterInterface.create_std_in) + def create_std_in(self, *args, **kwargs): + try: + if not self.__buffer_output: + return sys.stdin + except: + pass + + return _DebugConsoleStdIn() # If buffered, raw_input is not supported in this console. + + @overrides(InteractiveConsole.push) + def push(self, line, frame, buffer_output=True): + """Change built-in stdout and stderr methods by the + new custom StdMessage. + execute the InteractiveConsole.push. + Change the stdout and stderr back be the original built-ins + + :param buffer_output: if False won't redirect the output. + + Return boolean (True if more input is required else False), + output_messages and input_messages + """ + self.__buffer_output = buffer_output + more = False + if buffer_output: + original_stdout = sys.stdout + original_stderr = sys.stderr + try: + try: + self.frame = frame + if buffer_output: + out = sys.stdout = IOBuf() + err = sys.stderr = IOBuf() + more = self.add_exec(line) + except Exception: + exc = get_exception_traceback_str() + if buffer_output: + err.buflist.append("Internal Error: %s" % (exc,)) + else: + sys.stderr.write("Internal Error: %s\n" % (exc,)) + finally: + # Remove frame references. + self.frame = None + frame = None + if buffer_output: + sys.stdout = original_stdout + sys.stderr = original_stderr + + if buffer_output: + return more, out.buflist, err.buflist + else: + return more, [], [] + + @overrides(BaseInterpreterInterface.do_add_exec) + def do_add_exec(self, line): + return InteractiveConsole.push(self, line) + + @overrides(InteractiveConsole.runcode) + def runcode(self, code): + """Execute a code object. + + When an exception occurs, self.showtraceback() is called to + display a traceback. All exceptions are caught except + SystemExit, which is reraised. + + A note about KeyboardInterrupt: this exception may occur + elsewhere in this code, and may not always be caught. The + caller should be prepared to deal with it. + + """ + try: + updated_globals = self.get_namespace() + initial_globals = updated_globals.copy() + + updated_locals = None + + is_async = False + if hasattr(inspect, 'CO_COROUTINE'): + is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE + + if is_async: + t = _EvalAwaitInNewEventLoop(code, updated_globals, updated_locals) + t.start() + t.join() + + update_globals_and_locals(updated_globals, initial_globals, self.frame) + if t.exc: + raise t.exc[1].with_traceback(t.exc[2]) + + else: + try: + exec(code, updated_globals, updated_locals) + finally: + update_globals_and_locals(updated_globals, initial_globals, self.frame) + except SystemExit: + raise + except: + # In case sys.excepthook called, use original excepthook #PyDev-877: Debug console freezes with Python 3.5+ + # (showtraceback does it on python 3.5 onwards) + sys.excepthook = sys.__excepthook__ + try: + self.showtraceback() + finally: + sys.__excepthook__ = sys.excepthook + + def get_namespace(self): + dbg_namespace = {} + dbg_namespace.update(self.frame.f_globals) + dbg_namespace.update(self.frame.f_locals) # locals later because it has precedence over the actual globals + return dbg_namespace + + +#======================================================================================================================= +# InteractiveConsoleCache +#======================================================================================================================= +class InteractiveConsoleCache: + + thread_id = None + frame_id = None + interactive_console_instance = None + + +# Note: On Jython 2.1 we can't use classmethod or staticmethod, so, just make the functions below free-functions. +def get_interactive_console(thread_id, frame_id, frame, console_message): + """returns the global interactive console. + interactive console should have been initialized by this time + :rtype: DebugConsole + """ + if InteractiveConsoleCache.thread_id == thread_id and InteractiveConsoleCache.frame_id == frame_id: + return InteractiveConsoleCache.interactive_console_instance + + InteractiveConsoleCache.interactive_console_instance = DebugConsole() + InteractiveConsoleCache.thread_id = thread_id + InteractiveConsoleCache.frame_id = frame_id + + console_stacktrace = traceback.extract_stack(frame, limit=1) + if console_stacktrace: + current_context = console_stacktrace[0] # top entry from stacktrace + context_message = 'File "%s", line %s, in %s' % (current_context[0], current_context[1], current_context[2]) + console_message.add_console_message(CONSOLE_OUTPUT, "[Current context]: %s" % (context_message,)) + return InteractiveConsoleCache.interactive_console_instance + + +def clear_interactive_console(): + InteractiveConsoleCache.thread_id = None + InteractiveConsoleCache.frame_id = None + InteractiveConsoleCache.interactive_console_instance = None + + +def execute_console_command(frame, thread_id, frame_id, line, buffer_output=True): + """fetch an interactive console instance from the cache and + push the received command to the console. + + create and return an instance of console_message + """ + console_message = ConsoleMessage() + + interpreter = get_interactive_console(thread_id, frame_id, frame, console_message) + more, output_messages, error_messages = interpreter.push(line, frame, buffer_output) + console_message.update_more(more) + + for message in output_messages: + console_message.add_console_message(CONSOLE_OUTPUT, message) + + for message in error_messages: + console_message.add_console_message(CONSOLE_ERROR, message) + + return console_message + + +def get_description(frame, thread_id, frame_id, expression): + console_message = ConsoleMessage() + interpreter = get_interactive_console(thread_id, frame_id, frame, console_message) + try: + interpreter.frame = frame + return interpreter.getDescription(expression) + finally: + interpreter.frame = None + + +def get_completions(frame, act_tok): + """ fetch all completions, create xml for the same + return the completions xml + """ + return _pydev_completer.generate_completions_as_xml(frame, act_tok) + diff --git a/_pydevd_bundle/pydevd_constants.py b/_pydevd_bundle/pydevd_constants.py new file mode 100644 index 0000000..013b6cf --- /dev/null +++ b/_pydevd_bundle/pydevd_constants.py @@ -0,0 +1,787 @@ +''' +This module holds the constants used for specifying the states of the debugger. +''' +from __future__ import nested_scopes +import platform +import weakref +import struct +import warnings +import functools +from contextlib import contextmanager + +STATE_RUN = 1 +STATE_SUSPEND = 2 + +PYTHON_SUSPEND = 1 +DJANGO_SUSPEND = 2 +JINJA2_SUSPEND = 3 + +int_types = (int,) + +# types does not include a MethodWrapperType +try: + MethodWrapperType = type([].__str__) +except: + MethodWrapperType = None + +import sys # Note: the sys import must be here anyways (others depend on it) + +# Preload codecs to avoid imports to them later on which can potentially halt the debugger. +import codecs as _codecs +for _codec in ["ascii", "utf8", "utf-8", "latin1", "latin-1", "idna"]: + _codecs.lookup(_codec) + + +class DebugInfoHolder: + # we have to put it here because it can be set through the command line (so, the + # already imported references would not have it). + + # General information + DEBUG_TRACE_LEVEL = 0 # 0 = critical, 1 = info, 2 = debug, 3 = verbose + + PYDEVD_DEBUG_FILE = None + + +# Any filename that starts with these strings is not traced nor shown to the user. +# In Python 3.7 " ..." can appear and should be ignored for the user. +# has special heuristics to know whether it should be traced or not (it's part of +# user code when it's the used in python -c and part of the library otherwise). + +# Any filename that starts with these strings is considered user (project) code. Note +# that files for which we have a source mapping are also considered as a part of the project. +USER_CODE_BASENAMES_STARTING_WITH = (' (2 ** 32) + +IS_JYTHON = pydevd_vm_type.get_vm_type() == pydevd_vm_type.PydevdVmType.JYTHON + +IS_PYPY = platform.python_implementation() == 'PyPy' + +if IS_JYTHON: + import java.lang.System # @UnresolvedImport + IS_WINDOWS = java.lang.System.getProperty("os.name").lower().startswith("windows") + +USE_CUSTOM_SYS_CURRENT_FRAMES = not hasattr(sys, '_current_frames') or IS_PYPY +USE_CUSTOM_SYS_CURRENT_FRAMES_MAP = USE_CUSTOM_SYS_CURRENT_FRAMES and (IS_PYPY or IS_IRONPYTHON) + +if USE_CUSTOM_SYS_CURRENT_FRAMES: + + # Some versions of Jython don't have it (but we can provide a replacement) + if IS_JYTHON: + from java.lang import NoSuchFieldException + from org.python.core import ThreadStateMapping + try: + cachedThreadState = ThreadStateMapping.getDeclaredField('globalThreadStates') # Dev version + except NoSuchFieldException: + cachedThreadState = ThreadStateMapping.getDeclaredField('cachedThreadState') # Release Jython 2.7.0 + cachedThreadState.accessible = True + thread_states = cachedThreadState.get(ThreadStateMapping) + + def _current_frames(): + as_array = thread_states.entrySet().toArray() + ret = {} + for thread_to_state in as_array: + thread = thread_to_state.getKey() + if thread is None: + continue + thread_state = thread_to_state.getValue() + if thread_state is None: + continue + + frame = thread_state.frame + if frame is None: + continue + + ret[thread.getId()] = frame + return ret + + elif USE_CUSTOM_SYS_CURRENT_FRAMES_MAP: + constructed_tid_to_last_frame = {} + + # IronPython doesn't have it. Let's use our workaround... + def _current_frames(): + return constructed_tid_to_last_frame + + else: + raise RuntimeError('Unable to proceed (sys._current_frames not available in this Python implementation).') +else: + _current_frames = sys._current_frames + +IS_PYTHON_STACKLESS = "stackless" in sys.version.lower() +CYTHON_SUPPORTED = False + +python_implementation = platform.python_implementation() +if python_implementation == 'CPython': + # Only available for CPython! + CYTHON_SUPPORTED = True + +#======================================================================================================================= +# Python 3? +#======================================================================================================================= +IS_PY36_OR_GREATER = sys.version_info >= (3, 6) +IS_PY37_OR_GREATER = sys.version_info >= (3, 7) +IS_PY38_OR_GREATER = sys.version_info >= (3, 8) +IS_PY39_OR_GREATER = sys.version_info >= (3, 9) +IS_PY310_OR_GREATER = sys.version_info >= (3, 10) +IS_PY311_OR_GREATER = sys.version_info >= (3, 11) + + +def version_str(v): + return '.'.join((str(x) for x in v[:3])) + ''.join((str(x) for x in v[3:])) + + +PY_VERSION_STR = version_str(sys.version_info) +try: + PY_IMPL_VERSION_STR = version_str(sys.implementation.version) +except AttributeError: + PY_IMPL_VERSION_STR = '' + +try: + PY_IMPL_NAME = sys.implementation.name +except AttributeError: + PY_IMPL_NAME = '' + +ENV_TRUE_LOWER_VALUES = ('yes', 'true', '1') +ENV_FALSE_LOWER_VALUES = ('no', 'false', '0') + + +def is_true_in_env(env_key): + if isinstance(env_key, tuple): + # If a tuple, return True if any of those ends up being true. + for v in env_key: + if is_true_in_env(v): + return True + return False + else: + return os.getenv(env_key, '').lower() in ENV_TRUE_LOWER_VALUES + + +def as_float_in_env(env_key, default): + value = os.getenv(env_key) + if value is None: + return default + try: + return float(value) + except Exception: + raise RuntimeError( + 'Error: expected the env variable: %s to be set to a float value. Found: %s' % ( + env_key, value)) + + +def as_int_in_env(env_key, default): + value = os.getenv(env_key) + if value is None: + return default + try: + return int(value) + except Exception: + raise RuntimeError( + 'Error: expected the env variable: %s to be set to a int value. Found: %s' % ( + env_key, value)) + + +# If true in env, use gevent mode. +SUPPORT_GEVENT = is_true_in_env('GEVENT_SUPPORT') + +# Opt-in support to show gevent paused greenlets. False by default because if too many greenlets are +# paused the UI can slow-down (i.e.: if 1000 greenlets are paused, each one would be shown separate +# as a different thread, but if the UI isn't optimized for that the experience is lacking...). +GEVENT_SHOW_PAUSED_GREENLETS = is_true_in_env('GEVENT_SHOW_PAUSED_GREENLETS') + +DISABLE_FILE_VALIDATION = is_true_in_env('PYDEVD_DISABLE_FILE_VALIDATION') + +GEVENT_SUPPORT_NOT_SET_MSG = os.getenv( + 'GEVENT_SUPPORT_NOT_SET_MSG', + 'It seems that the gevent monkey-patching is being used.\n' + 'Please set an environment variable with:\n' + 'GEVENT_SUPPORT=True\n' + 'to enable gevent support in the debugger.' +) + +USE_LIB_COPY = SUPPORT_GEVENT + +INTERACTIVE_MODE_AVAILABLE = sys.platform in ('darwin', 'win32') or os.getenv('DISPLAY') is not None + +# If true in env, forces cython to be used (raises error if not available). +# If false in env, disables it. +# If not specified, uses default heuristic to determine if it should be loaded. +USE_CYTHON_FLAG = os.getenv('PYDEVD_USE_CYTHON') + +if USE_CYTHON_FLAG is not None: + USE_CYTHON_FLAG = USE_CYTHON_FLAG.lower() + if USE_CYTHON_FLAG not in ENV_TRUE_LOWER_VALUES and USE_CYTHON_FLAG not in ENV_FALSE_LOWER_VALUES: + raise RuntimeError('Unexpected value for PYDEVD_USE_CYTHON: %s (enable with one of: %s, disable with one of: %s)' % ( + USE_CYTHON_FLAG, ENV_TRUE_LOWER_VALUES, ENV_FALSE_LOWER_VALUES)) + +else: + if not CYTHON_SUPPORTED: + USE_CYTHON_FLAG = 'no' + +# If true in env, forces frame eval to be used (raises error if not available). +# If false in env, disables it. +# If not specified, uses default heuristic to determine if it should be loaded. +PYDEVD_USE_FRAME_EVAL = os.getenv('PYDEVD_USE_FRAME_EVAL', '').lower() + +PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING = is_true_in_env('PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING') + +# If specified in PYDEVD_IPYTHON_CONTEXT it must be a string with the basename +# and then the name of 2 methods in which the evaluate is done. +PYDEVD_IPYTHON_CONTEXT = ('interactiveshell.py', 'run_code', 'run_ast_nodes') +_ipython_ctx = os.getenv('PYDEVD_IPYTHON_CONTEXT') +if _ipython_ctx: + PYDEVD_IPYTHON_CONTEXT = tuple(x.strip() for x in _ipython_ctx.split(',')) + assert len(PYDEVD_IPYTHON_CONTEXT) == 3, 'Invalid PYDEVD_IPYTHON_CONTEXT: %s' % (_ipython_ctx,) + +# Use to disable loading the lib to set tracing to all threads (default is using heuristics based on where we're running). +LOAD_NATIVE_LIB_FLAG = os.getenv('PYDEVD_LOAD_NATIVE_LIB', '').lower() + +LOG_TIME = os.getenv('PYDEVD_LOG_TIME', 'true').lower() in ENV_TRUE_LOWER_VALUES + +SHOW_COMPILE_CYTHON_COMMAND_LINE = is_true_in_env('PYDEVD_SHOW_COMPILE_CYTHON_COMMAND_LINE') + +LOAD_VALUES_ASYNC = is_true_in_env('PYDEVD_LOAD_VALUES_ASYNC') +DEFAULT_VALUE = "__pydevd_value_async" +ASYNC_EVAL_TIMEOUT_SEC = 60 +NEXT_VALUE_SEPARATOR = "__pydev_val__" +BUILTINS_MODULE_NAME = 'builtins' + +# Pandas customization. +PANDAS_MAX_ROWS = as_int_in_env('PYDEVD_PANDAS_MAX_ROWS', 60) +PANDAS_MAX_COLS = as_int_in_env('PYDEVD_PANDAS_MAX_COLS', 10) +PANDAS_MAX_COLWIDTH = as_int_in_env('PYDEVD_PANDAS_MAX_COLWIDTH', 50) + +# If getting an attribute or computing some value is too slow, let the user know if the given timeout elapses. +PYDEVD_WARN_SLOW_RESOLVE_TIMEOUT = as_float_in_env('PYDEVD_WARN_SLOW_RESOLVE_TIMEOUT', 0.15) + +# This timeout is used to track the time to send a message saying that the evaluation +# is taking too long and possible mitigations. +PYDEVD_WARN_EVALUATION_TIMEOUT = as_float_in_env('PYDEVD_WARN_EVALUATION_TIMEOUT', 3.) + +# If True in env shows a thread dump when the evaluation times out. +PYDEVD_THREAD_DUMP_ON_WARN_EVALUATION_TIMEOUT = is_true_in_env('PYDEVD_THREAD_DUMP_ON_WARN_EVALUATION_TIMEOUT') + +# This timeout is used only when the mode that all threads are stopped/resumed at once is used +# (i.e.: multi_threads_single_notification) +# +# In this mode, if some evaluation doesn't finish until this timeout, we notify the user +# and then resume all threads until the evaluation finishes. +# +# A negative value will disable the timeout and a value of 0 will automatically run all threads +# (without any notification) when the evaluation is started and pause all threads when the +# evaluation is finished. A positive value will run run all threads after the timeout +# elapses. +PYDEVD_UNBLOCK_THREADS_TIMEOUT = as_float_in_env('PYDEVD_UNBLOCK_THREADS_TIMEOUT', -1.) + +# Timeout to interrupt a thread (so, if some evaluation doesn't finish until this +# timeout, the thread doing the evaluation is interrupted). +# A value <= 0 means this is disabled. +# See: _pydevd_bundle.pydevd_timeout.create_interrupt_this_thread_callback for details +# on how the thread interruption works (there are some caveats related to it). +PYDEVD_INTERRUPT_THREAD_TIMEOUT = as_float_in_env('PYDEVD_INTERRUPT_THREAD_TIMEOUT', -1) + +# If PYDEVD_APPLY_PATCHING_TO_HIDE_PYDEVD_THREADS is set to False, the patching to hide pydevd threads won't be applied. +PYDEVD_APPLY_PATCHING_TO_HIDE_PYDEVD_THREADS = os.getenv('PYDEVD_APPLY_PATCHING_TO_HIDE_PYDEVD_THREADS', 'true').lower() in ENV_TRUE_LOWER_VALUES + +EXCEPTION_TYPE_UNHANDLED = 'UNHANDLED' +EXCEPTION_TYPE_USER_UNHANDLED = 'USER_UNHANDLED' +EXCEPTION_TYPE_HANDLED = 'HANDLED' + +SHOW_DEBUG_INFO_ENV = is_true_in_env(('PYCHARM_DEBUG', 'PYDEV_DEBUG', 'PYDEVD_DEBUG')) + +if SHOW_DEBUG_INFO_ENV: + # show debug info before the debugger start + DebugInfoHolder.DEBUG_TRACE_LEVEL = 3 + +DebugInfoHolder.PYDEVD_DEBUG_FILE = os.getenv('PYDEVD_DEBUG_FILE') + + +def protect_libraries_from_patching(): + """ + In this function we delete some modules from `sys.modules` dictionary and import them again inside + `_pydev_saved_modules` in order to save their original copies there. After that we can use these + saved modules within the debugger to protect them from patching by external libraries (e.g. gevent). + """ + patched = ['threading', 'thread', '_thread', 'time', 'socket', 'queue', 'select', + 'xmlrpclib', 'SimpleXMLRPCServer', 'BaseHTTPServer', 'SocketServer', + 'xmlrpc.client', 'xmlrpc.server', 'http.server', 'socketserver'] + + for name in patched: + try: + __import__(name) + except: + pass + + patched_modules = dict([(k, v) for k, v in sys.modules.items() + if k in patched]) + + for name in patched_modules: + del sys.modules[name] + + # import for side effects + import _pydev_bundle._pydev_saved_modules + + for name in patched_modules: + sys.modules[name] = patched_modules[name] + + +if USE_LIB_COPY: + protect_libraries_from_patching() + +from _pydev_bundle._pydev_saved_modules import thread, threading + +_fork_safe_locks = [] + +if IS_JYTHON: + + def ForkSafeLock(rlock=False): + if rlock: + return threading.RLock() + else: + return threading.Lock() + +else: + + class ForkSafeLock(object): + ''' + A lock which is fork-safe (when a fork is done, `pydevd_constants.after_fork()` + should be called to reset the locks in the new process to avoid deadlocks + from a lock which was locked during the fork). + + Note: + Unlike `threading.Lock` this class is not completely atomic, so, doing: + + lock = ForkSafeLock() + with lock: + ... + + is different than using `threading.Lock` directly because the tracing may + find an additional function call on `__enter__` and on `__exit__`, so, it's + not recommended to use this in all places, only where the forking may be important + (so, for instance, the locks on PyDB should not be changed to this lock because + of that -- and those should all be collected in the new process because PyDB itself + should be completely cleared anyways). + + It's possible to overcome this limitation by using `ForkSafeLock.acquire` and + `ForkSafeLock.release` instead of the context manager (as acquire/release are + bound to the original implementation, whereas __enter__/__exit__ is not due to Python + limitations). + ''' + + def __init__(self, rlock=False): + self._rlock = rlock + self._init() + _fork_safe_locks.append(weakref.ref(self)) + + def __enter__(self): + return self._lock.__enter__() + + def __exit__(self, exc_type, exc_val, exc_tb): + return self._lock.__exit__(exc_type, exc_val, exc_tb) + + def _init(self): + if self._rlock: + self._lock = threading.RLock() + else: + self._lock = thread.allocate_lock() + + self.acquire = self._lock.acquire + self.release = self._lock.release + _fork_safe_locks.append(weakref.ref(self)) + + +def after_fork(): + ''' + Must be called after a fork operation (will reset the ForkSafeLock). + ''' + global _fork_safe_locks + locks = _fork_safe_locks[:] + _fork_safe_locks = [] + for lock in locks: + lock = lock() + if lock is not None: + lock._init() + + +_thread_id_lock = ForkSafeLock() +thread_get_ident = thread.get_ident + + +def as_str(s): + assert isinstance(s, str) + return s + + +@contextmanager +def filter_all_warnings(): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + yield + + +def silence_warnings_decorator(func): + + @functools.wraps(func) + def new_func(*args, **kwargs): + with filter_all_warnings(): + return func(*args, **kwargs) + + return new_func + + +def sorted_dict_repr(d): + s = sorted(d.items(), key=lambda x:str(x[0])) + return '{' + ', '.join(('%r: %r' % x) for x in s) + '}' + + +def iter_chars(b): + # In Python 2, we can iterate bytes or str with individual characters, but Python 3 onwards + # changed that behavior so that when iterating bytes we actually get ints! + if isinstance(b, bytes): + # i.e.: do something as struct.unpack('3c', b) + return iter(struct.unpack(str(len(b)) + 'c', b)) + return iter(b) + + +if IS_JYTHON: + + def NO_FTRACE(frame, event, arg): + return None + +else: + _curr_trace = sys.gettrace() + + # Set a temporary trace which does nothing for us to test (otherwise setting frame.f_trace has no + # effect). + def _temp_trace(frame, event, arg): + return None + + sys.settrace(_temp_trace) + + def _check_ftrace_set_none(): + ''' + Will throw an error when executing a line event + ''' + sys._getframe().f_trace = None + _line_event = 1 + _line_event = 2 + + try: + _check_ftrace_set_none() + + def NO_FTRACE(frame, event, arg): + frame.f_trace = None + return None + + except TypeError: + + def NO_FTRACE(frame, event, arg): + # In Python <= 2.6 and <= 3.4, if we're tracing a method, frame.f_trace may not be set + # to None, it must always be set to a tracing function. + # See: tests_python.test_tracing_gotchas.test_tracing_gotchas + # + # Note: Python 2.7 sometimes works and sometimes it doesn't depending on the minor + # version because of https://bugs.python.org/issue20041 (although bug reports didn't + # include the minor version, so, mark for any Python 2.7 as I'm not completely sure + # the fix in later 2.7 versions is the same one we're dealing with). + return None + + sys.settrace(_curr_trace) + + +#======================================================================================================================= +# get_pid +#======================================================================================================================= +def get_pid(): + try: + return os.getpid() + except AttributeError: + try: + # Jython does not have it! + import java.lang.management.ManagementFactory # @UnresolvedImport -- just for jython + pid = java.lang.management.ManagementFactory.getRuntimeMXBean().getName() + return pid.replace('@', '_') + except: + # ok, no pid available (will be unable to debug multiple processes) + return '000001' + + +def clear_cached_thread_id(thread): + with _thread_id_lock: + try: + if thread.__pydevd_id__ != 'console_main': + # The console_main is a special thread id used in the console and its id should never be reset + # (otherwise we may no longer be able to get its variables -- see: https://www.brainwy.com/tracker/PyDev/776). + del thread.__pydevd_id__ + except AttributeError: + pass + + +# Don't let threads be collected (so that id(thread) is guaranteed to be unique). +_thread_id_to_thread_found = {} + + +def _get_or_compute_thread_id_with_lock(thread, is_current_thread): + with _thread_id_lock: + # We do a new check with the lock in place just to be sure that nothing changed + tid = getattr(thread, '__pydevd_id__', None) + if tid is not None: + return tid + + _thread_id_to_thread_found[id(thread)] = thread + + # Note: don't use thread.ident because a new thread may have the + # same id from an old thread. + pid = get_pid() + tid = 'pid_%s_id_%s' % (pid, id(thread)) + + thread.__pydevd_id__ = tid + + return tid + + +def get_current_thread_id(thread): + ''' + Note: the difference from get_current_thread_id to get_thread_id is that + for the current thread we can get the thread id while the thread.ident + is still not set in the Thread instance. + ''' + try: + # Fast path without getting lock. + tid = thread.__pydevd_id__ + if tid is None: + # Fix for https://www.brainwy.com/tracker/PyDev/645 + # if __pydevd_id__ is None, recalculate it... also, use an heuristic + # that gives us always the same id for the thread (using thread.ident or id(thread)). + raise AttributeError() + except AttributeError: + tid = _get_or_compute_thread_id_with_lock(thread, is_current_thread=True) + + return tid + + +def get_thread_id(thread): + try: + # Fast path without getting lock. + tid = thread.__pydevd_id__ + if tid is None: + # Fix for https://www.brainwy.com/tracker/PyDev/645 + # if __pydevd_id__ is None, recalculate it... also, use an heuristic + # that gives us always the same id for the thread (using thread.ident or id(thread)). + raise AttributeError() + except AttributeError: + tid = _get_or_compute_thread_id_with_lock(thread, is_current_thread=False) + + return tid + + +def set_thread_id(thread, thread_id): + with _thread_id_lock: + thread.__pydevd_id__ = thread_id + + +#======================================================================================================================= +# Null +#======================================================================================================================= +class Null: + """ + Gotten from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205 + """ + + def __init__(self, *args, **kwargs): + return None + + def __call__(self, *args, **kwargs): + return self + + def __enter__(self, *args, **kwargs): + return self + + def __exit__(self, *args, **kwargs): + return self + + def __getattr__(self, mname): + if len(mname) > 4 and mname[:2] == '__' and mname[-2:] == '__': + # Don't pretend to implement special method names. + raise AttributeError(mname) + return self + + def __setattr__(self, name, value): + return self + + def __delattr__(self, name): + return self + + def __repr__(self): + return "" + + def __str__(self): + return "Null" + + def __len__(self): + return 0 + + def __getitem__(self): + return self + + def __setitem__(self, *args, **kwargs): + pass + + def write(self, *args, **kwargs): + pass + + def __nonzero__(self): + return 0 + + def __iter__(self): + return iter(()) + + +# Default instance +NULL = Null() + + +class KeyifyList(object): + + def __init__(self, inner, key): + self.inner = inner + self.key = key + + def __len__(self): + return len(self.inner) + + def __getitem__(self, k): + return self.key(self.inner[k]) + + +def call_only_once(func): + ''' + To be used as a decorator + + @call_only_once + def func(): + print 'Calling func only this time' + + Actually, in PyDev it must be called as: + + func = call_only_once(func) to support older versions of Python. + ''' + + def new_func(*args, **kwargs): + if not new_func._called: + new_func._called = True + return func(*args, **kwargs) + + new_func._called = False + return new_func + + +# Protocol where each line is a new message (text is quoted to prevent new lines). +# payload is xml +QUOTED_LINE_PROTOCOL = 'quoted-line' +ARGUMENT_QUOTED_LINE_PROTOCOL = 'protocol-quoted-line' + +# Uses http protocol to provide a new message. +# i.e.: Content-Length:xxx\r\n\r\npayload +# payload is xml +HTTP_PROTOCOL = 'http' +ARGUMENT_HTTP_PROTOCOL = 'protocol-http' + +# Message is sent without any header. +# payload is json +JSON_PROTOCOL = 'json' +ARGUMENT_JSON_PROTOCOL = 'json-dap' + +# Same header as the HTTP_PROTOCOL +# payload is json +HTTP_JSON_PROTOCOL = 'http_json' +ARGUMENT_HTTP_JSON_PROTOCOL = 'json-dap-http' + +ARGUMENT_PPID = 'ppid' + + +class _GlobalSettings: + protocol = QUOTED_LINE_PROTOCOL + + +def set_protocol(protocol): + expected = (HTTP_PROTOCOL, QUOTED_LINE_PROTOCOL, JSON_PROTOCOL, HTTP_JSON_PROTOCOL) + assert protocol in expected, 'Protocol (%s) should be one of: %s' % ( + protocol, expected) + + _GlobalSettings.protocol = protocol + + +def get_protocol(): + return _GlobalSettings.protocol + + +def is_json_protocol(): + return _GlobalSettings.protocol in (JSON_PROTOCOL, HTTP_JSON_PROTOCOL) + + +class GlobalDebuggerHolder: + ''' + Holder for the global debugger. + ''' + global_dbg = None # Note: don't rename (the name is used in our attach to process) + + +def get_global_debugger(): + return GlobalDebuggerHolder.global_dbg + + +GetGlobalDebugger = get_global_debugger # Backward-compatibility + + +def set_global_debugger(dbg): + GlobalDebuggerHolder.global_dbg = dbg + + +if __name__ == '__main__': + if Null(): + sys.stdout.write('here\n') + diff --git a/_pydevd_bundle/pydevd_custom_frames.py b/_pydevd_bundle/pydevd_custom_frames.py new file mode 100644 index 0000000..66e400f --- /dev/null +++ b/_pydevd_bundle/pydevd_custom_frames.py @@ -0,0 +1,116 @@ +from _pydevd_bundle.pydevd_constants import get_current_thread_id, Null, ForkSafeLock +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame +from _pydev_bundle._pydev_saved_modules import thread, threading +import sys +from _pydev_bundle import pydev_log + +DEBUG = False + + +class CustomFramesContainer: + + # Actual Values initialized later on. + custom_frames_lock = None # : :type custom_frames_lock: threading.Lock + + custom_frames = None + + _next_frame_id = None + + _py_db_command_thread_event = None + + +def custom_frames_container_init(): # Note: no staticmethod on jython 2.1 (so, use free-function) + + CustomFramesContainer.custom_frames_lock = ForkSafeLock() + + # custom_frames can only be accessed if properly locked with custom_frames_lock! + # Key is a string identifying the frame (as well as the thread it belongs to). + # Value is a CustomFrame. + # + CustomFramesContainer.custom_frames = {} + + # Only to be used in this module + CustomFramesContainer._next_frame_id = 0 + + # This is the event we must set to release an internal process events. It's later set by the actual debugger + # when we do create the debugger. + CustomFramesContainer._py_db_command_thread_event = Null() + + +# Initialize it the first time (it may be reinitialized later on when dealing with a fork). +custom_frames_container_init() + + +class CustomFrame: + + def __init__(self, name, frame, thread_id): + # 0 = string with the representation of that frame + self.name = name + + # 1 = the frame to show + self.frame = frame + + # 2 = an integer identifying the last time the frame was changed. + self.mod_time = 0 + + # 3 = the thread id of the given frame + self.thread_id = thread_id + + +def add_custom_frame(frame, name, thread_id): + ''' + It's possible to show paused frames by adding a custom frame through this API (it's + intended to be used for coroutines, but could potentially be used for generators too). + + :param frame: + The topmost frame to be shown paused when a thread with thread.ident == thread_id is paused. + + :param name: + The name to be shown for the custom thread in the UI. + + :param thread_id: + The thread id to which this frame is related (must match thread.ident). + + :return: str + Returns the custom thread id which will be used to show the given frame paused. + ''' + with CustomFramesContainer.custom_frames_lock: + curr_thread_id = get_current_thread_id(threading.current_thread()) + next_id = CustomFramesContainer._next_frame_id = CustomFramesContainer._next_frame_id + 1 + + # Note: the frame id kept contains an id and thread information on the thread where the frame was added + # so that later on we can check if the frame is from the current thread by doing frame_id.endswith('|'+thread_id). + frame_custom_thread_id = '__frame__:%s|%s' % (next_id, curr_thread_id) + if DEBUG: + sys.stderr.write('add_custom_frame: %s (%s) %s %s\n' % ( + frame_custom_thread_id, get_abs_path_real_path_and_base_from_frame(frame)[-1], frame.f_lineno, frame.f_code.co_name)) + + CustomFramesContainer.custom_frames[frame_custom_thread_id] = CustomFrame(name, frame, thread_id) + CustomFramesContainer._py_db_command_thread_event.set() + return frame_custom_thread_id + + +def update_custom_frame(frame_custom_thread_id, frame, thread_id, name=None): + with CustomFramesContainer.custom_frames_lock: + if DEBUG: + sys.stderr.write('update_custom_frame: %s\n' % frame_custom_thread_id) + try: + old = CustomFramesContainer.custom_frames[frame_custom_thread_id] + if name is not None: + old.name = name + old.mod_time += 1 + old.thread_id = thread_id + except: + sys.stderr.write('Unable to get frame to replace: %s\n' % (frame_custom_thread_id,)) + pydev_log.exception() + + CustomFramesContainer._py_db_command_thread_event.set() + + +def remove_custom_frame(frame_custom_thread_id): + with CustomFramesContainer.custom_frames_lock: + if DEBUG: + sys.stderr.write('remove_custom_frame: %s\n' % frame_custom_thread_id) + CustomFramesContainer.custom_frames.pop(frame_custom_thread_id, None) + CustomFramesContainer._py_db_command_thread_event.set() + diff --git a/_pydevd_bundle/pydevd_cython.c b/_pydevd_bundle/pydevd_cython.c new file mode 100644 index 0000000..e50c22c --- /dev/null +++ b/_pydevd_bundle/pydevd_cython.c @@ -0,0 +1,43164 @@ +/* Generated by Cython 0.29.32 */ + +/* BEGIN: Cython Metadata +{ + "distutils": { + "depends": [], + "name": "_pydevd_bundle.pydevd_cython", + "sources": [ + "_pydevd_bundle/pydevd_cython.pyx" + ] + }, + "module_name": "_pydevd_bundle.pydevd_cython" +} +END: Cython Metadata */ + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ +#include "Python.h" +#if PY_VERSION_HEX >= 0x03090000 +#include "internal/pycore_gc.h" +#include "internal/pycore_interp.h" +#endif + +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. +#else +#define CYTHON_ABI "0_29_32" +#define CYTHON_HEX_VERSION 0x001D20F0 +#define CYTHON_FUTURE_DIVISION 0 +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_HEX >= 0x07030900) + #endif +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif +#elif defined(PY_NOGIL) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #ifndef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_NOGIL 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif + +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #elif defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif +#endif + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } +#else + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) + #endif +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact +#ifndef PyObject_Unicode + #define PyObject_Unicode PyObject_Str +#endif +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif +#else + #define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; +#endif + +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #if !defined(_USE_MATH_DEFINES) + #define _USE_MATH_DEFINES + #endif +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#define __PYX_MARK_ERR_POS(f_index, lineno) \ + { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE___pydevd_bundle__pydevd_cython +#define __PYX_HAVE_API___pydevd_bundle__pydevd_cython +/* Early includes */ +#include +#include +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); +#if CYTHON_ASSUME_SAFE_MACROS +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + + +static const char *__pyx_f[] = { + "_pydevd_bundle/pydevd_cython.pyx", + "_pydevd_bundle/pydevd_cython.pxd", + "stringsource", + "type.pxd", +}; + +/*--- Type declarations ---*/ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo; +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj; +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame; +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper; +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions; +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame; +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer; + +/* "_pydevd_bundle/pydevd_cython.pxd":1 + * cdef class PyDBAdditionalThreadInfo: # <<<<<<<<<<<<<< + * cdef public int pydev_state + * cdef public object pydev_step_stop # Actually, it's a frame or None + */ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo { + PyObject_HEAD + int pydev_state; + PyObject *pydev_step_stop; + int pydev_original_step_cmd; + int pydev_step_cmd; + int pydev_notify_kill; + PyObject *pydev_smart_step_stop; + int pydev_django_resolve_frame; + PyObject *pydev_call_from_jinja2; + PyObject *pydev_call_inside_jinja2; + int is_tracing; + PyObject *conditional_breakpoint_exception; + PyObject *pydev_message; + int suspend_type; + int pydev_next_line; + PyObject *pydev_func_name; + int suspended_at_unhandled; + PyObject *trace_suspend_type; + PyObject *top_level_thread_tracer_no_back_frames; + PyObject *top_level_thread_tracer_unhandled; + PyObject *thread_tracer; + PyObject *step_in_initial_location; + int pydev_smart_parent_offset; + int pydev_smart_child_offset; + PyObject *pydev_smart_step_into_variants; + PyObject *target_id_to_smart_step_into_variant; + int pydev_use_scoped_step_frame; +}; + + +/* "_pydevd_bundle/pydevd_cython.pyx":255 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class _TryExceptContainerObj: # <<<<<<<<<<<<<< + * cdef public list try_except_infos; + * def __init__(self): + */ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj { + PyObject_HEAD + PyObject *try_except_infos; +}; + + +/* "_pydevd_bundle/pydevd_cython.pyx":273 + * #======================================================================================================================= + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class PyDBFrame: # <<<<<<<<<<<<<< + * # ELSE + * # class PyDBFrame: + */ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame { + PyObject_HEAD + struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_vtab; + PyObject *_args; + int should_skip; + PyObject *exc_info; +}; + + +/* "_pydevd_bundle/pydevd_cython.pyx":1434 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class SafeCallWrapper: # <<<<<<<<<<<<<< + * cdef method_object + * def __init__(self, method_object): + */ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper { + PyObject_HEAD + PyObject *method_object; +}; + + +/* "_pydevd_bundle/pydevd_cython.pyx":1590 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class TopLevelThreadTracerOnlyUnhandledExceptions: # <<<<<<<<<<<<<< + * cdef public tuple _args; + * def __init__(self, tuple args): + */ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions { + PyObject_HEAD + PyObject *_args; +}; + + +/* "_pydevd_bundle/pydevd_cython.pyx":1620 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class TopLevelThreadTracerNoBackFrame: # <<<<<<<<<<<<<< + * cdef public object _frame_trace_dispatch; + * cdef public tuple _args; + */ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame { + PyObject_HEAD + PyObject *_frame_trace_dispatch; + PyObject *_args; + PyObject *try_except_infos; + PyObject *_last_exc_arg; + PyObject *_raise_lines; + int _last_raise_line; +}; + + +/* "_pydevd_bundle/pydevd_cython.pyx":1695 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class ThreadTracer: # <<<<<<<<<<<<<< + * cdef public tuple _args; + * def __init__(self, tuple args): + */ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer { + PyObject_HEAD + PyObject *_args; +}; + + + +/* "_pydevd_bundle/pydevd_cython.pyx":273 + * #======================================================================================================================= + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class PyDBFrame: # <<<<<<<<<<<<<< + * # ELSE + * # class PyDBFrame: + */ + +struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame { + PyObject *(*_should_stop_on_exception)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *, PyObject *); + PyObject *(*_handle_exception)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *, PyObject *, PyObject *); + PyObject *(*get_func_name)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *); + PyObject *(*_show_return_values)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *); + PyObject *(*_remove_return_values)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *); + PyObject *(*_get_unfiltered_back_frame)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *); + PyObject *(*_is_same_frame)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *); + PyObject *(*trace_dispatch)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *, PyObject *, int __pyx_skip_dispatch); +}; +static struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_vtabptr_14_pydevd_bundle_13pydevd_cython_PyDBFrame; + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* KeywordStringCheck.proto */ +static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* GetModuleGlobalName.proto */ +#if CYTHON_USE_DICT_VERSIONS +#define __Pyx_GetModuleGlobalName(var, name) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ + (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ + __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ + PY_UINT64_T __pyx_dict_version;\ + PyObject *__pyx_dict_cached_value;\ + (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); +#else +#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) +#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); +#endif + +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif +#if CYTHON_FAST_PYCALL + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL +#endif + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallNoArg.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); +#else +#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) +#endif + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyObjectCall2Args.proto */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); + +/* PyErrExceptionMatches.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) +static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); +#else +#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) +#endif + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* GetAttr.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *); + +/* GetAttr3.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); + +/* RaiseException.proto */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* GetTopmostException.proto */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); +#endif + +/* SaveResetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +#else +#define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) +#define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) +#endif + +/* GetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* PyObjectLookupSpecial.proto */ +#if CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name) { + PyObject *res; + PyTypeObject *tp = Py_TYPE(obj); +#if PY_MAJOR_VERSION < 3 + if (unlikely(PyInstance_Check(obj))) + return __Pyx_PyObject_GetAttrStr(obj, attr_name); +#endif + res = _PyType_Lookup(tp, attr_name); + if (likely(res)) { + descrgetfunc f = Py_TYPE(res)->tp_descr_get; + if (!f) { + Py_INCREF(res); + } else { + res = f(res, obj, (PyObject *)tp); + } + } else { + PyErr_SetObject(PyExc_AttributeError, attr_name); + } + return res; +} +#else +#define __Pyx_PyObject_LookupSpecial(o,n) __Pyx_PyObject_GetAttrStr(o,n) +#endif + +/* PyObjectSetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +#define __Pyx_PyObject_DelAttrStr(o,n) __Pyx_PyObject_SetAttrStr(o, n, NULL) +static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value); +#else +#define __Pyx_PyObject_DelAttrStr(o,n) PyObject_DelAttr(o,n) +#define __Pyx_PyObject_SetAttrStr(o,n,v) PyObject_SetAttr(o,n,v) +#endif + +/* None.proto */ +static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname); + +/* pyfrozenset_new.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it); + +/* PySetContains.proto */ +static CYTHON_INLINE int __Pyx_PySet_ContainsTF(PyObject* key, PyObject* set, int eq); + +/* ListAppend.proto */ +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { + PyListObject* L = (PyListObject*) list; + Py_ssize_t len = Py_SIZE(list); + if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { + Py_INCREF(x); + PyList_SET_ITEM(list, len, x); + __Pyx_SET_SIZE(list, len + 1); + return 0; + } + return PyList_Append(list, x); +} +#else +#define __Pyx_PyList_Append(L,x) PyList_Append(L,x) +#endif + +/* PySequenceContains.proto */ +static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) { + int result = PySequence_Contains(seq, item); + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* ArgTypeTest.proto */ +#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\ + ((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 :\ + __Pyx__ArgTypeTest(obj, type, name, exact)) +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); + +/* GetItemInt.proto */ +#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ + __Pyx_GetItemInt_Generic(o, to_py_func(i)))) +#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, + int is_list, int wraparound, int boundscheck); + +/* IncludeStringH.proto */ +#include + +/* BytesEquals.proto */ +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); + +/* UnicodeEquals.proto */ +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); + +/* StrEquals.proto */ +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyString_Equals __Pyx_PyUnicode_Equals +#else +#define __Pyx_PyString_Equals __Pyx_PyBytes_Equals +#endif + +/* RaiseTooManyValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); + +/* RaiseNeedMoreValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +/* IterFinish.proto */ +static CYTHON_INLINE int __Pyx_IterFinish(void); + +/* UnpackItemEndCheck.proto */ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); + +/* ExtTypeTest.proto */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); + +/* HasAttr.proto */ +static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); + +/* dict_getitem_default.proto */ +static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value); + +/* UnpackUnboundCMethod.proto */ +typedef struct { + PyObject *type; + PyObject **method_name; + PyCFunction func; + PyObject *method; + int flag; +} __Pyx_CachedCFunction; + +/* CallUnboundCMethod1.proto */ +static PyObject* __Pyx__CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg); +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg); +#else +#define __Pyx_CallUnboundCMethod1(cfunc, self, arg) __Pyx__CallUnboundCMethod1(cfunc, self, arg) +#endif + +/* CallUnboundCMethod2.proto */ +static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2); +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030600B1 +static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2); +#else +#define __Pyx_CallUnboundCMethod2(cfunc, self, arg1, arg2) __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2) +#endif + +/* py_dict_clear.proto */ +#define __Pyx_PyDict_Clear(d) (PyDict_Clear(d), 0) + +/* PyDictContains.proto */ +static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict, int eq) { + int result = PyDict_Contains(dict, item); + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + +/* SwapException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSwap(type, value, tb) __Pyx__ExceptionSwap(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* RaiseNoneIterError.proto */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); + +/* PyIntBinop.proto */ +#if !CYTHON_COMPILING_IN_PYPY +static PyObject* __Pyx_PyInt_AndObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); +#else +#define __Pyx_PyInt_AndObjC(op1, op2, intval, inplace, zerodivision_check)\ + (inplace ? PyNumber_InPlaceAnd(op1, op2) : PyNumber_And(op1, op2)) +#endif + +/* PyObjectGetMethod.proto */ +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); + +/* PyObjectCallMethod0.proto */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); + +/* UnpackTupleError.proto */ +static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); + +/* UnpackTuple2.proto */ +#define __Pyx_unpack_tuple2(tuple, value1, value2, is_tuple, has_known_size, decref_tuple)\ + (likely(is_tuple || PyTuple_Check(tuple)) ?\ + (likely(has_known_size || PyTuple_GET_SIZE(tuple) == 2) ?\ + __Pyx_unpack_tuple2_exact(tuple, value1, value2, decref_tuple) :\ + (__Pyx_UnpackTupleError(tuple, 2), -1)) :\ + __Pyx_unpack_tuple2_generic(tuple, value1, value2, has_known_size, decref_tuple)) +static CYTHON_INLINE int __Pyx_unpack_tuple2_exact( + PyObject* tuple, PyObject** value1, PyObject** value2, int decref_tuple); +static int __Pyx_unpack_tuple2_generic( + PyObject* tuple, PyObject** value1, PyObject** value2, int has_known_size, int decref_tuple); + +/* dict_iter.proto */ +static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* dict, int is_dict, PyObject* method_name, + Py_ssize_t* p_orig_length, int* p_is_dict); +static CYTHON_INLINE int __Pyx_dict_iter_next(PyObject* dict_or_iter, Py_ssize_t orig_length, Py_ssize_t* ppos, + PyObject** pkey, PyObject** pvalue, PyObject** pitem, int is_dict); + +/* py_dict_values.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d); + +/* CallUnboundCMethod0.proto */ +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_CallUnboundCMethod0(cfunc, self)\ + (likely((cfunc)->func) ?\ + (likely((cfunc)->flag == METH_NOARGS) ? (*((cfunc)->func))(self, NULL) :\ + (PY_VERSION_HEX >= 0x030600B1 && likely((cfunc)->flag == METH_FASTCALL) ?\ + (PY_VERSION_HEX >= 0x030700A0 ?\ + (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0) :\ + (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0, NULL)) :\ + (PY_VERSION_HEX >= 0x030700A0 && (cfunc)->flag == (METH_FASTCALL | METH_KEYWORDS) ?\ + (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0, NULL) :\ + (likely((cfunc)->flag == (METH_VARARGS | METH_KEYWORDS)) ? ((*(PyCFunctionWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, __pyx_empty_tuple, NULL)) :\ + ((cfunc)->flag == METH_VARARGS ? (*((cfunc)->func))(self, __pyx_empty_tuple) :\ + __Pyx__CallUnboundCMethod0(cfunc, self)))))) :\ + __Pyx__CallUnboundCMethod0(cfunc, self)) +#else +#define __Pyx_CallUnboundCMethod0(cfunc, self) __Pyx__CallUnboundCMethod0(cfunc, self) +#endif + +/* DictGetItem.proto */ +#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY +static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key); +#define __Pyx_PyObject_Dict_GetItem(obj, name)\ + (likely(PyDict_CheckExact(obj)) ?\ + __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) +#else +#define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) +#define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) +#endif + +/* SliceObject.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice( + PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop, + PyObject** py_start, PyObject** py_stop, PyObject** py_slice, + int has_cstart, int has_cstop, int wraparound); + +/* PyIntBinop.proto */ +#if !CYTHON_COMPILING_IN_PYPY +static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); +#else +#define __Pyx_PyInt_AddObjC(op1, op2, intval, inplace, zerodivision_check)\ + (inplace ? PyNumber_InPlaceAdd(op1, op2) : PyNumber_Add(op1, op2)) +#endif + +/* PyObjectCallMethod1.proto */ +static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg); + +/* append.proto */ +static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x); + +/* SliceTupleAndList.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); +static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); +#else +#define __Pyx_PyList_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) +#define __Pyx_PyTuple_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) +#endif + +/* PyIntCompare.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_EqObjC(PyObject *op1, PyObject *op2, long intval, long inplace); + +/* ObjectGetItem.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); +#else +#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) +#endif + +/* Import.proto */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); + +/* ImportFrom.proto */ +static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); + +/* PyObject_GenericGetAttrNoDict.proto */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GenericGetAttrNoDict PyObject_GenericGetAttr +#endif + +/* PyObject_GenericGetAttr.proto */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GenericGetAttr PyObject_GenericGetAttr +#endif + +/* PyObjectGetAttrStrNoError.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name); + +/* SetupReduce.proto */ +static int __Pyx_setup_reduce(PyObject* type_obj); + +/* SetVTable.proto */ +static int __Pyx_SetVtable(PyObject *dict, void *vtable); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto +#define __PYX_HAVE_RT_ImportType_proto +enum __Pyx_ImportType_CheckSize { + __Pyx_ImportType_CheckSize_Error = 0, + __Pyx_ImportType_CheckSize_Warn = 1, + __Pyx_ImportType_CheckSize_Ignore = 2 +}; +static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); +#endif + +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__should_stop_on_exception(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, CYTHON_UNUSED PyObject *__pyx_v_event, PyObject *__pyx_v_arg); /* proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__handle_exception(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg, PyObject *__pyx_v_exception_type); /* proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_get_func_name(CYTHON_UNUSED struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame); /* proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__show_return_values(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_arg); /* proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__remove_return_values(CYTHON_UNUSED struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v_main_debugger, PyObject *__pyx_v_frame); /* proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__get_unfiltered_back_frame(CYTHON_UNUSED struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_main_debugger, PyObject *__pyx_v_frame); /* proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__is_same_frame(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_target_frame, PyObject *__pyx_v_current_frame); /* proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_trace_dispatch(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg, int __pyx_skip_dispatch); /* proto*/ + +/* Module declarations from 'libc.string' */ + +/* Module declarations from 'libc.stdio' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.type' */ +static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; + +/* Module declarations from 'cpython' */ + +/* Module declarations from 'cpython.object' */ + +/* Module declarations from 'cpython.ref' */ + +/* Module declarations from '_pydevd_bundle.pydevd_cython' */ +static PyTypeObject *__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo = 0; +static PyTypeObject *__pyx_ptype_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj = 0; +static PyTypeObject *__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBFrame = 0; +static PyTypeObject *__pyx_ptype_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper = 0; +static PyTypeObject *__pyx_ptype_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions = 0; +static PyTypeObject *__pyx_ptype_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame = 0; +static PyTypeObject *__pyx_ptype_14_pydevd_bundle_13pydevd_cython_ThreadTracer = 0; +static PyObject *__pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in = 0; +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_is_unhandled_exception(PyObject *, PyObject *, PyObject *, int, PyObject *); /*proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_PyDBAdditionalThreadInfo__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *, PyObject *); /*proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle__TryExceptContainerObj__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *, PyObject *); /*proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_PyDBFrame__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *); /*proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_SafeCallWrapper__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *, PyObject *); /*proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *, PyObject *); /*proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *, PyObject *); /*proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_ThreadTracer__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *, PyObject *); /*proto*/ +#define __Pyx_MODULE_NAME "_pydevd_bundle.pydevd_cython" +extern int __pyx_module_is_main__pydevd_bundle__pydevd_cython; +int __pyx_module_is_main__pydevd_bundle__pydevd_cython = 0; + +/* Implementation of '_pydevd_bundle.pydevd_cython' */ +static PyObject *__pyx_builtin_ImportError; +static PyObject *__pyx_builtin_NameError; +static PyObject *__pyx_builtin_StopIteration; +static PyObject *__pyx_builtin_id; +static PyObject *__pyx_builtin_AttributeError; +static PyObject *__pyx_builtin_SystemExit; +static PyObject *__pyx_builtin_GeneratorExit; +static PyObject *__pyx_builtin_KeyboardInterrupt; +static const char __pyx_k_[] = ""; +static const char __pyx_k_1[] = "1"; +static const char __pyx_k_i[] = "i"; +static const char __pyx_k_j[] = "j"; +static const char __pyx_k_t[] = "t"; +static const char __pyx_k__3[] = "?"; +static const char __pyx_k__5[] = "/"; +static const char __pyx_k__6[] = "\\"; +static const char __pyx_k__7[] = "."; +static const char __pyx_k_id[] = "id"; +static const char __pyx_k_os[] = "os"; +static const char __pyx_k_re[] = "re"; +static const char __pyx_k_ALL[] = "ALL"; +static const char __pyx_k_add[] = "add"; +static const char __pyx_k_arg[] = "arg"; +static const char __pyx_k_dis[] = "dis"; +static const char __pyx_k_get[] = "get"; +static const char __pyx_k_new[] = "__new__"; +static const char __pyx_k_pop[] = "pop"; +static const char __pyx_k_pyc[] = ".pyc"; +static const char __pyx_k_run[] = "run"; +static const char __pyx_k_s_s[] = "%s.%s"; +static const char __pyx_k_None[] = "None"; +static const char __pyx_k_args[] = "args"; +static const char __pyx_k_call[] = "call"; +static const char __pyx_k_cell[] = " 0)) { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;} + if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__init__", 0))) return -1; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo___init__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo___init__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":68 + * + * def __init__(self): + * self.pydev_state = STATE_RUN # STATE_RUN or STATE_SUSPEND # <<<<<<<<<<<<<< + * self.pydev_step_stop = None + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_STATE_RUN); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_self->pydev_state = __pyx_t_2; + + /* "_pydevd_bundle/pydevd_cython.pyx":69 + * def __init__(self): + * self.pydev_state = STATE_RUN # STATE_RUN or STATE_SUSPEND + * self.pydev_step_stop = None # <<<<<<<<<<<<<< + * + * # Note: we have `pydev_original_step_cmd` and `pydev_step_cmd` because the original is to + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_step_stop); + __Pyx_DECREF(__pyx_v_self->pydev_step_stop); + __pyx_v_self->pydev_step_stop = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":77 + * # method the strategy is changed to a step in). + * + * self.pydev_original_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. # <<<<<<<<<<<<<< + * self.pydev_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. + * + */ + __pyx_v_self->pydev_original_step_cmd = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":78 + * + * self.pydev_original_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. + * self.pydev_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. # <<<<<<<<<<<<<< + * + * self.pydev_notify_kill = False + */ + __pyx_v_self->pydev_step_cmd = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":80 + * self.pydev_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. + * + * self.pydev_notify_kill = False # <<<<<<<<<<<<<< + * self.pydev_django_resolve_frame = False + * self.pydev_call_from_jinja2 = None + */ + __pyx_v_self->pydev_notify_kill = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":81 + * + * self.pydev_notify_kill = False + * self.pydev_django_resolve_frame = False # <<<<<<<<<<<<<< + * self.pydev_call_from_jinja2 = None + * self.pydev_call_inside_jinja2 = None + */ + __pyx_v_self->pydev_django_resolve_frame = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":82 + * self.pydev_notify_kill = False + * self.pydev_django_resolve_frame = False + * self.pydev_call_from_jinja2 = None # <<<<<<<<<<<<<< + * self.pydev_call_inside_jinja2 = None + * self.is_tracing = 0 + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_call_from_jinja2); + __Pyx_DECREF(__pyx_v_self->pydev_call_from_jinja2); + __pyx_v_self->pydev_call_from_jinja2 = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":83 + * self.pydev_django_resolve_frame = False + * self.pydev_call_from_jinja2 = None + * self.pydev_call_inside_jinja2 = None # <<<<<<<<<<<<<< + * self.is_tracing = 0 + * self.conditional_breakpoint_exception = None + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_call_inside_jinja2); + __Pyx_DECREF(__pyx_v_self->pydev_call_inside_jinja2); + __pyx_v_self->pydev_call_inside_jinja2 = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":84 + * self.pydev_call_from_jinja2 = None + * self.pydev_call_inside_jinja2 = None + * self.is_tracing = 0 # <<<<<<<<<<<<<< + * self.conditional_breakpoint_exception = None + * self.pydev_message = '' + */ + __pyx_v_self->is_tracing = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":85 + * self.pydev_call_inside_jinja2 = None + * self.is_tracing = 0 + * self.conditional_breakpoint_exception = None # <<<<<<<<<<<<<< + * self.pydev_message = '' + * self.suspend_type = PYTHON_SUSPEND + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->conditional_breakpoint_exception); + __Pyx_DECREF(__pyx_v_self->conditional_breakpoint_exception); + __pyx_v_self->conditional_breakpoint_exception = ((PyObject*)Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":86 + * self.is_tracing = 0 + * self.conditional_breakpoint_exception = None + * self.pydev_message = '' # <<<<<<<<<<<<<< + * self.suspend_type = PYTHON_SUSPEND + * self.pydev_next_line = -1 + */ + __Pyx_INCREF(__pyx_kp_s_); + __Pyx_GIVEREF(__pyx_kp_s_); + __Pyx_GOTREF(__pyx_v_self->pydev_message); + __Pyx_DECREF(__pyx_v_self->pydev_message); + __pyx_v_self->pydev_message = __pyx_kp_s_; + + /* "_pydevd_bundle/pydevd_cython.pyx":87 + * self.conditional_breakpoint_exception = None + * self.pydev_message = '' + * self.suspend_type = PYTHON_SUSPEND # <<<<<<<<<<<<<< + * self.pydev_next_line = -1 + * self.pydev_func_name = '.invalid.' # Must match the type in cython + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_PYTHON_SUSPEND); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 87, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 87, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_self->suspend_type = __pyx_t_2; + + /* "_pydevd_bundle/pydevd_cython.pyx":88 + * self.pydev_message = '' + * self.suspend_type = PYTHON_SUSPEND + * self.pydev_next_line = -1 # <<<<<<<<<<<<<< + * self.pydev_func_name = '.invalid.' # Must match the type in cython + * self.suspended_at_unhandled = False + */ + __pyx_v_self->pydev_next_line = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":89 + * self.suspend_type = PYTHON_SUSPEND + * self.pydev_next_line = -1 + * self.pydev_func_name = '.invalid.' # Must match the type in cython # <<<<<<<<<<<<<< + * self.suspended_at_unhandled = False + * self.trace_suspend_type = 'trace' # 'trace' or 'frame_eval' + */ + __Pyx_INCREF(__pyx_kp_s_invalid); + __Pyx_GIVEREF(__pyx_kp_s_invalid); + __Pyx_GOTREF(__pyx_v_self->pydev_func_name); + __Pyx_DECREF(__pyx_v_self->pydev_func_name); + __pyx_v_self->pydev_func_name = __pyx_kp_s_invalid; + + /* "_pydevd_bundle/pydevd_cython.pyx":90 + * self.pydev_next_line = -1 + * self.pydev_func_name = '.invalid.' # Must match the type in cython + * self.suspended_at_unhandled = False # <<<<<<<<<<<<<< + * self.trace_suspend_type = 'trace' # 'trace' or 'frame_eval' + * self.top_level_thread_tracer_no_back_frames = [] + */ + __pyx_v_self->suspended_at_unhandled = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":91 + * self.pydev_func_name = '.invalid.' # Must match the type in cython + * self.suspended_at_unhandled = False + * self.trace_suspend_type = 'trace' # 'trace' or 'frame_eval' # <<<<<<<<<<<<<< + * self.top_level_thread_tracer_no_back_frames = [] + * self.top_level_thread_tracer_unhandled = None + */ + __Pyx_INCREF(__pyx_n_s_trace); + __Pyx_GIVEREF(__pyx_n_s_trace); + __Pyx_GOTREF(__pyx_v_self->trace_suspend_type); + __Pyx_DECREF(__pyx_v_self->trace_suspend_type); + __pyx_v_self->trace_suspend_type = __pyx_n_s_trace; + + /* "_pydevd_bundle/pydevd_cython.pyx":92 + * self.suspended_at_unhandled = False + * self.trace_suspend_type = 'trace' # 'trace' or 'frame_eval' + * self.top_level_thread_tracer_no_back_frames = [] # <<<<<<<<<<<<<< + * self.top_level_thread_tracer_unhandled = None + * self.thread_tracer = None + */ + __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 92, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + __Pyx_DECREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + __pyx_v_self->top_level_thread_tracer_no_back_frames = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":93 + * self.trace_suspend_type = 'trace' # 'trace' or 'frame_eval' + * self.top_level_thread_tracer_no_back_frames = [] + * self.top_level_thread_tracer_unhandled = None # <<<<<<<<<<<<<< + * self.thread_tracer = None + * self.step_in_initial_location = None + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->top_level_thread_tracer_unhandled); + __Pyx_DECREF(__pyx_v_self->top_level_thread_tracer_unhandled); + __pyx_v_self->top_level_thread_tracer_unhandled = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":94 + * self.top_level_thread_tracer_no_back_frames = [] + * self.top_level_thread_tracer_unhandled = None + * self.thread_tracer = None # <<<<<<<<<<<<<< + * self.step_in_initial_location = None + * self.pydev_smart_parent_offset = -1 + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->thread_tracer); + __Pyx_DECREF(__pyx_v_self->thread_tracer); + __pyx_v_self->thread_tracer = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":95 + * self.top_level_thread_tracer_unhandled = None + * self.thread_tracer = None + * self.step_in_initial_location = None # <<<<<<<<<<<<<< + * self.pydev_smart_parent_offset = -1 + * self.pydev_smart_child_offset = -1 + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->step_in_initial_location); + __Pyx_DECREF(__pyx_v_self->step_in_initial_location); + __pyx_v_self->step_in_initial_location = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":96 + * self.thread_tracer = None + * self.step_in_initial_location = None + * self.pydev_smart_parent_offset = -1 # <<<<<<<<<<<<<< + * self.pydev_smart_child_offset = -1 + * self.pydev_smart_step_into_variants = () + */ + __pyx_v_self->pydev_smart_parent_offset = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":97 + * self.step_in_initial_location = None + * self.pydev_smart_parent_offset = -1 + * self.pydev_smart_child_offset = -1 # <<<<<<<<<<<<<< + * self.pydev_smart_step_into_variants = () + * self.target_id_to_smart_step_into_variant = {} + */ + __pyx_v_self->pydev_smart_child_offset = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":98 + * self.pydev_smart_parent_offset = -1 + * self.pydev_smart_child_offset = -1 + * self.pydev_smart_step_into_variants = () # <<<<<<<<<<<<<< + * self.target_id_to_smart_step_into_variant = {} + * + */ + __Pyx_INCREF(__pyx_empty_tuple); + __Pyx_GIVEREF(__pyx_empty_tuple); + __Pyx_GOTREF(__pyx_v_self->pydev_smart_step_into_variants); + __Pyx_DECREF(__pyx_v_self->pydev_smart_step_into_variants); + __pyx_v_self->pydev_smart_step_into_variants = __pyx_empty_tuple; + + /* "_pydevd_bundle/pydevd_cython.pyx":99 + * self.pydev_smart_child_offset = -1 + * self.pydev_smart_step_into_variants = () + * self.target_id_to_smart_step_into_variant = {} # <<<<<<<<<<<<<< + * + * # Flag to indicate ipython use-case where each line will be executed as a call/line/return + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 99, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->target_id_to_smart_step_into_variant); + __Pyx_DECREF(__pyx_v_self->target_id_to_smart_step_into_variant); + __pyx_v_self->target_id_to_smart_step_into_variant = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":111 + * # + * # See: https://github.com/microsoft/debugpy/issues/869#issuecomment-1132141003 + * self.pydev_use_scoped_step_frame = False # <<<<<<<<<<<<<< + * + * def get_topmost_frame(self, thread): + */ + __pyx_v_self->pydev_use_scoped_step_frame = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":67 + * # ENDIF + * + * def __init__(self): # <<<<<<<<<<<<<< + * self.pydev_state = STATE_RUN # STATE_RUN or STATE_SUSPEND + * self.pydev_step_stop = None + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":113 + * self.pydev_use_scoped_step_frame = False + * + * def get_topmost_frame(self, thread): # <<<<<<<<<<<<<< + * ''' + * Gets the topmost frame for the given thread. Note that it may be None + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_3get_topmost_frame(PyObject *__pyx_v_self, PyObject *__pyx_v_thread); /*proto*/ +static char __pyx_doc_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_2get_topmost_frame[] = "\n Gets the topmost frame for the given thread. Note that it may be None\n and callers should remove the reference to the frame as soon as possible\n to avoid disturbing user code.\n "; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_3get_topmost_frame(PyObject *__pyx_v_self, PyObject *__pyx_v_thread) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_topmost_frame (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_2get_topmost_frame(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_thread)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_2get_topmost_frame(CYTHON_UNUSED struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_thread) { + PyObject *__pyx_v_current_frames = NULL; + PyObject *__pyx_v_topmost_frame = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_t_9; + PyObject *__pyx_t_10 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_topmost_frame", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":120 + * ''' + * # sys._current_frames(): dictionary with thread id -> topmost frame + * current_frames = _current_frames() # <<<<<<<<<<<<<< + * topmost_frame = current_frames.get(thread.ident) + * if topmost_frame is None: + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_current_frames); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 120, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + } + } + __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 120, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_current_frames = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":121 + * # sys._current_frames(): dictionary with thread id -> topmost frame + * current_frames = _current_frames() + * topmost_frame = current_frames.get(thread.ident) # <<<<<<<<<<<<<< + * if topmost_frame is None: + * # Note: this is expected for dummy threads (so, getting the topmost frame should be + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_current_frames, __pyx_n_s_get); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 121, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_thread, __pyx_n_s_ident); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 121, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + } + } + __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 121, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_topmost_frame = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":122 + * current_frames = _current_frames() + * topmost_frame = current_frames.get(thread.ident) + * if topmost_frame is None: # <<<<<<<<<<<<<< + * # Note: this is expected for dummy threads (so, getting the topmost frame should be + * # treated as optional). + */ + __pyx_t_5 = (__pyx_v_topmost_frame == Py_None); + __pyx_t_6 = (__pyx_t_5 != 0); + if (__pyx_t_6) { + + /* "_pydevd_bundle/pydevd_cython.pyx":125 + * # Note: this is expected for dummy threads (so, getting the topmost frame should be + * # treated as optional). + * pydev_log.info( # <<<<<<<<<<<<<< + * 'Unable to get topmost frame for thread: %s, thread.ident: %s, id(thread): %s\nCurrent frames: %s.\n' + * 'GEVENT_SUPPORT: %s', + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 125, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 125, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":129 + * 'GEVENT_SUPPORT: %s', + * thread, + * thread.ident, # <<<<<<<<<<<<<< + * id(thread), + * current_frames, + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_thread, __pyx_n_s_ident); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 129, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + + /* "_pydevd_bundle/pydevd_cython.pyx":130 + * thread, + * thread.ident, + * id(thread), # <<<<<<<<<<<<<< + * current_frames, + * SUPPORT_GEVENT, + */ + __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, __pyx_v_thread); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 130, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + + /* "_pydevd_bundle/pydevd_cython.pyx":132 + * id(thread), + * current_frames, + * SUPPORT_GEVENT, # <<<<<<<<<<<<<< + * ) + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_SUPPORT_GEVENT); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 132, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = NULL; + __pyx_t_9 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_9 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[7] = {__pyx_t_8, __pyx_kp_s_Unable_to_get_topmost_frame_for, __pyx_v_thread, __pyx_t_2, __pyx_t_4, __pyx_v_current_frames, __pyx_t_7}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_9, 6+__pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 125, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[7] = {__pyx_t_8, __pyx_kp_s_Unable_to_get_topmost_frame_for, __pyx_v_thread, __pyx_t_2, __pyx_t_4, __pyx_v_current_frames, __pyx_t_7}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_9, 6+__pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 125, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_10 = PyTuple_New(6+__pyx_t_9); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 125, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_10); + if (__pyx_t_8) { + __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); __pyx_t_8 = NULL; + } + __Pyx_INCREF(__pyx_kp_s_Unable_to_get_topmost_frame_for); + __Pyx_GIVEREF(__pyx_kp_s_Unable_to_get_topmost_frame_for); + PyTuple_SET_ITEM(__pyx_t_10, 0+__pyx_t_9, __pyx_kp_s_Unable_to_get_topmost_frame_for); + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_10, 1+__pyx_t_9, __pyx_v_thread); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_10, 2+__pyx_t_9, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_10, 3+__pyx_t_9, __pyx_t_4); + __Pyx_INCREF(__pyx_v_current_frames); + __Pyx_GIVEREF(__pyx_v_current_frames); + PyTuple_SET_ITEM(__pyx_t_10, 4+__pyx_t_9, __pyx_v_current_frames); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_10, 5+__pyx_t_9, __pyx_t_7); + __pyx_t_2 = 0; + __pyx_t_4 = 0; + __pyx_t_7 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_10, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 125, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":122 + * current_frames = _current_frames() + * topmost_frame = current_frames.get(thread.ident) + * if topmost_frame is None: # <<<<<<<<<<<<<< + * # Note: this is expected for dummy threads (so, getting the topmost frame should be + * # treated as optional). + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":135 + * ) + * + * return topmost_frame # <<<<<<<<<<<<<< + * + * def __str__(self): + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_topmost_frame); + __pyx_r = __pyx_v_topmost_frame; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":113 + * self.pydev_use_scoped_step_frame = False + * + * def get_topmost_frame(self, thread): # <<<<<<<<<<<<<< + * ''' + * Gets the topmost frame for the given thread. Note that it may be None + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.get_topmost_frame", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_current_frames); + __Pyx_XDECREF(__pyx_v_topmost_frame); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":137 + * return topmost_frame + * + * def __str__(self): # <<<<<<<<<<<<<< + * return 'State:%s Stop:%s Cmd: %s Kill:%s' % ( + * self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_5__str__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_5__str__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__str__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_4__str__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_4__str__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__str__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":138 + * + * def __str__(self): + * return 'State:%s Stop:%s Cmd: %s Kill:%s' % ( # <<<<<<<<<<<<<< + * self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill) + * + */ + __Pyx_XDECREF(__pyx_r); + + /* "_pydevd_bundle/pydevd_cython.pyx":139 + * def __str__(self): + * return 'State:%s Stop:%s Cmd: %s Kill:%s' % ( + * self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill) # <<<<<<<<<<<<<< + * + * + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_state); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 139, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_step_cmd); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 139, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_self->pydev_notify_kill); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 139, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 139, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); + __Pyx_INCREF(__pyx_v_self->pydev_step_stop); + __Pyx_GIVEREF(__pyx_v_self->pydev_step_stop); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_self->pydev_step_stop); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_t_3); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":138 + * + * def __str__(self): + * return 'State:%s Stop:%s Cmd: %s Kill:%s' % ( # <<<<<<<<<<<<<< + * self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill) + * + */ + __pyx_t_3 = __Pyx_PyString_Format(__pyx_kp_s_State_s_Stop_s_Cmd_s_Kill_s, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 138, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":137 + * return topmost_frame + * + * def __str__(self): # <<<<<<<<<<<<<< + * return 'State:%s Stop:%s Cmd: %s Kill:%s' % ( + * self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill) + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.__str__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":2 + * cdef class PyDBAdditionalThreadInfo: + * cdef public int pydev_state # <<<<<<<<<<<<<< + * cdef public object pydev_step_stop # Actually, it's a frame or None + * cdef public int pydev_original_step_cmd + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_state); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_state.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 2, __pyx_L1_error) + __pyx_v_self->pydev_state = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_state.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":3 + * cdef class PyDBAdditionalThreadInfo: + * cdef public int pydev_state + * cdef public object pydev_step_stop # Actually, it's a frame or None # <<<<<<<<<<<<<< + * cdef public int pydev_original_step_cmd + * cdef public int pydev_step_cmd + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->pydev_step_stop); + __pyx_r = __pyx_v_self->pydev_step_stop; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->pydev_step_stop); + __Pyx_DECREF(__pyx_v_self->pydev_step_stop); + __pyx_v_self->pydev_step_stop = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_step_stop); + __Pyx_DECREF(__pyx_v_self->pydev_step_stop); + __pyx_v_self->pydev_step_stop = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":4 + * cdef public int pydev_state + * cdef public object pydev_step_stop # Actually, it's a frame or None + * cdef public int pydev_original_step_cmd # <<<<<<<<<<<<<< + * cdef public int pydev_step_cmd + * cdef public bint pydev_notify_kill + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_original_step_cmd); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_original_step_cmd.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 4, __pyx_L1_error) + __pyx_v_self->pydev_original_step_cmd = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_original_step_cmd.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":5 + * cdef public object pydev_step_stop # Actually, it's a frame or None + * cdef public int pydev_original_step_cmd + * cdef public int pydev_step_cmd # <<<<<<<<<<<<<< + * cdef public bint pydev_notify_kill + * cdef public object pydev_smart_step_stop # Actually, it's a frame or None + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_step_cmd); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_step_cmd.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 5, __pyx_L1_error) + __pyx_v_self->pydev_step_cmd = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_step_cmd.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":6 + * cdef public int pydev_original_step_cmd + * cdef public int pydev_step_cmd + * cdef public bint pydev_notify_kill # <<<<<<<<<<<<<< + * cdef public object pydev_smart_step_stop # Actually, it's a frame or None + * cdef public bint pydev_django_resolve_frame + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->pydev_notify_kill); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_notify_kill.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 6, __pyx_L1_error) + __pyx_v_self->pydev_notify_kill = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_notify_kill.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":7 + * cdef public int pydev_step_cmd + * cdef public bint pydev_notify_kill + * cdef public object pydev_smart_step_stop # Actually, it's a frame or None # <<<<<<<<<<<<<< + * cdef public bint pydev_django_resolve_frame + * cdef public object pydev_call_from_jinja2 + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->pydev_smart_step_stop); + __pyx_r = __pyx_v_self->pydev_smart_step_stop; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->pydev_smart_step_stop); + __Pyx_DECREF(__pyx_v_self->pydev_smart_step_stop); + __pyx_v_self->pydev_smart_step_stop = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_smart_step_stop); + __Pyx_DECREF(__pyx_v_self->pydev_smart_step_stop); + __pyx_v_self->pydev_smart_step_stop = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":8 + * cdef public bint pydev_notify_kill + * cdef public object pydev_smart_step_stop # Actually, it's a frame or None + * cdef public bint pydev_django_resolve_frame # <<<<<<<<<<<<<< + * cdef public object pydev_call_from_jinja2 + * cdef public object pydev_call_inside_jinja2 + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->pydev_django_resolve_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_django_resolve_frame.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 8, __pyx_L1_error) + __pyx_v_self->pydev_django_resolve_frame = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_django_resolve_frame.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":9 + * cdef public object pydev_smart_step_stop # Actually, it's a frame or None + * cdef public bint pydev_django_resolve_frame + * cdef public object pydev_call_from_jinja2 # <<<<<<<<<<<<<< + * cdef public object pydev_call_inside_jinja2 + * cdef public int is_tracing + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->pydev_call_from_jinja2); + __pyx_r = __pyx_v_self->pydev_call_from_jinja2; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->pydev_call_from_jinja2); + __Pyx_DECREF(__pyx_v_self->pydev_call_from_jinja2); + __pyx_v_self->pydev_call_from_jinja2 = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_call_from_jinja2); + __Pyx_DECREF(__pyx_v_self->pydev_call_from_jinja2); + __pyx_v_self->pydev_call_from_jinja2 = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":10 + * cdef public bint pydev_django_resolve_frame + * cdef public object pydev_call_from_jinja2 + * cdef public object pydev_call_inside_jinja2 # <<<<<<<<<<<<<< + * cdef public int is_tracing + * cdef public tuple conditional_breakpoint_exception + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->pydev_call_inside_jinja2); + __pyx_r = __pyx_v_self->pydev_call_inside_jinja2; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->pydev_call_inside_jinja2); + __Pyx_DECREF(__pyx_v_self->pydev_call_inside_jinja2); + __pyx_v_self->pydev_call_inside_jinja2 = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_call_inside_jinja2); + __Pyx_DECREF(__pyx_v_self->pydev_call_inside_jinja2); + __pyx_v_self->pydev_call_inside_jinja2 = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":11 + * cdef public object pydev_call_from_jinja2 + * cdef public object pydev_call_inside_jinja2 + * cdef public int is_tracing # <<<<<<<<<<<<<< + * cdef public tuple conditional_breakpoint_exception + * cdef public str pydev_message + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->is_tracing); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.is_tracing.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 11, __pyx_L1_error) + __pyx_v_self->is_tracing = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.is_tracing.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":12 + * cdef public object pydev_call_inside_jinja2 + * cdef public int is_tracing + * cdef public tuple conditional_breakpoint_exception # <<<<<<<<<<<<<< + * cdef public str pydev_message + * cdef public int suspend_type + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->conditional_breakpoint_exception); + __pyx_r = __pyx_v_self->conditional_breakpoint_exception; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyTuple_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->conditional_breakpoint_exception); + __Pyx_DECREF(__pyx_v_self->conditional_breakpoint_exception); + __pyx_v_self->conditional_breakpoint_exception = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.conditional_breakpoint_exception.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->conditional_breakpoint_exception); + __Pyx_DECREF(__pyx_v_self->conditional_breakpoint_exception); + __pyx_v_self->conditional_breakpoint_exception = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":13 + * cdef public int is_tracing + * cdef public tuple conditional_breakpoint_exception + * cdef public str pydev_message # <<<<<<<<<<<<<< + * cdef public int suspend_type + * cdef public int pydev_next_line + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->pydev_message); + __pyx_r = __pyx_v_self->pydev_message; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyString_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->pydev_message); + __Pyx_DECREF(__pyx_v_self->pydev_message); + __pyx_v_self->pydev_message = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_message.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_message); + __Pyx_DECREF(__pyx_v_self->pydev_message); + __pyx_v_self->pydev_message = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":14 + * cdef public tuple conditional_breakpoint_exception + * cdef public str pydev_message + * cdef public int suspend_type # <<<<<<<<<<<<<< + * cdef public int pydev_next_line + * cdef public str pydev_func_name + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->suspend_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.suspend_type.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 14, __pyx_L1_error) + __pyx_v_self->suspend_type = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.suspend_type.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":15 + * cdef public str pydev_message + * cdef public int suspend_type + * cdef public int pydev_next_line # <<<<<<<<<<<<<< + * cdef public str pydev_func_name + * cdef public bint suspended_at_unhandled + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_next_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_next_line.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 15, __pyx_L1_error) + __pyx_v_self->pydev_next_line = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_next_line.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":16 + * cdef public int suspend_type + * cdef public int pydev_next_line + * cdef public str pydev_func_name # <<<<<<<<<<<<<< + * cdef public bint suspended_at_unhandled + * cdef public str trace_suspend_type + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->pydev_func_name); + __pyx_r = __pyx_v_self->pydev_func_name; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyString_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(1, 16, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->pydev_func_name); + __Pyx_DECREF(__pyx_v_self->pydev_func_name); + __pyx_v_self->pydev_func_name = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_func_name.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_func_name); + __Pyx_DECREF(__pyx_v_self->pydev_func_name); + __pyx_v_self->pydev_func_name = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":17 + * cdef public int pydev_next_line + * cdef public str pydev_func_name + * cdef public bint suspended_at_unhandled # <<<<<<<<<<<<<< + * cdef public str trace_suspend_type + * cdef public object top_level_thread_tracer_no_back_frames + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->suspended_at_unhandled); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.suspended_at_unhandled.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 17, __pyx_L1_error) + __pyx_v_self->suspended_at_unhandled = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.suspended_at_unhandled.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":18 + * cdef public str pydev_func_name + * cdef public bint suspended_at_unhandled + * cdef public str trace_suspend_type # <<<<<<<<<<<<<< + * cdef public object top_level_thread_tracer_no_back_frames + * cdef public object top_level_thread_tracer_unhandled + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->trace_suspend_type); + __pyx_r = __pyx_v_self->trace_suspend_type; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyString_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(1, 18, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->trace_suspend_type); + __Pyx_DECREF(__pyx_v_self->trace_suspend_type); + __pyx_v_self->trace_suspend_type = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.trace_suspend_type.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->trace_suspend_type); + __Pyx_DECREF(__pyx_v_self->trace_suspend_type); + __pyx_v_self->trace_suspend_type = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":19 + * cdef public bint suspended_at_unhandled + * cdef public str trace_suspend_type + * cdef public object top_level_thread_tracer_no_back_frames # <<<<<<<<<<<<<< + * cdef public object top_level_thread_tracer_unhandled + * cdef public object thread_tracer + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + __pyx_r = __pyx_v_self->top_level_thread_tracer_no_back_frames; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + __Pyx_DECREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + __pyx_v_self->top_level_thread_tracer_no_back_frames = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + __Pyx_DECREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + __pyx_v_self->top_level_thread_tracer_no_back_frames = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":20 + * cdef public str trace_suspend_type + * cdef public object top_level_thread_tracer_no_back_frames + * cdef public object top_level_thread_tracer_unhandled # <<<<<<<<<<<<<< + * cdef public object thread_tracer + * cdef public object step_in_initial_location + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->top_level_thread_tracer_unhandled); + __pyx_r = __pyx_v_self->top_level_thread_tracer_unhandled; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->top_level_thread_tracer_unhandled); + __Pyx_DECREF(__pyx_v_self->top_level_thread_tracer_unhandled); + __pyx_v_self->top_level_thread_tracer_unhandled = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->top_level_thread_tracer_unhandled); + __Pyx_DECREF(__pyx_v_self->top_level_thread_tracer_unhandled); + __pyx_v_self->top_level_thread_tracer_unhandled = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":21 + * cdef public object top_level_thread_tracer_no_back_frames + * cdef public object top_level_thread_tracer_unhandled + * cdef public object thread_tracer # <<<<<<<<<<<<<< + * cdef public object step_in_initial_location + * cdef public int pydev_smart_parent_offset + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->thread_tracer); + __pyx_r = __pyx_v_self->thread_tracer; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->thread_tracer); + __Pyx_DECREF(__pyx_v_self->thread_tracer); + __pyx_v_self->thread_tracer = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->thread_tracer); + __Pyx_DECREF(__pyx_v_self->thread_tracer); + __pyx_v_self->thread_tracer = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":22 + * cdef public object top_level_thread_tracer_unhandled + * cdef public object thread_tracer + * cdef public object step_in_initial_location # <<<<<<<<<<<<<< + * cdef public int pydev_smart_parent_offset + * cdef public int pydev_smart_child_offset + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->step_in_initial_location); + __pyx_r = __pyx_v_self->step_in_initial_location; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->step_in_initial_location); + __Pyx_DECREF(__pyx_v_self->step_in_initial_location); + __pyx_v_self->step_in_initial_location = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->step_in_initial_location); + __Pyx_DECREF(__pyx_v_self->step_in_initial_location); + __pyx_v_self->step_in_initial_location = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":23 + * cdef public object thread_tracer + * cdef public object step_in_initial_location + * cdef public int pydev_smart_parent_offset # <<<<<<<<<<<<<< + * cdef public int pydev_smart_child_offset + * cdef public tuple pydev_smart_step_into_variants + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_smart_parent_offset); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 23, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_smart_parent_offset.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 23, __pyx_L1_error) + __pyx_v_self->pydev_smart_parent_offset = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_smart_parent_offset.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":24 + * cdef public object step_in_initial_location + * cdef public int pydev_smart_parent_offset + * cdef public int pydev_smart_child_offset # <<<<<<<<<<<<<< + * cdef public tuple pydev_smart_step_into_variants + * cdef public dict target_id_to_smart_step_into_variant + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_smart_child_offset); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_smart_child_offset.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 24, __pyx_L1_error) + __pyx_v_self->pydev_smart_child_offset = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_smart_child_offset.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":25 + * cdef public int pydev_smart_parent_offset + * cdef public int pydev_smart_child_offset + * cdef public tuple pydev_smart_step_into_variants # <<<<<<<<<<<<<< + * cdef public dict target_id_to_smart_step_into_variant + * cdef public bint pydev_use_scoped_step_frame + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->pydev_smart_step_into_variants); + __pyx_r = __pyx_v_self->pydev_smart_step_into_variants; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyTuple_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(1, 25, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->pydev_smart_step_into_variants); + __Pyx_DECREF(__pyx_v_self->pydev_smart_step_into_variants); + __pyx_v_self->pydev_smart_step_into_variants = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_smart_step_into_variants.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->pydev_smart_step_into_variants); + __Pyx_DECREF(__pyx_v_self->pydev_smart_step_into_variants); + __pyx_v_self->pydev_smart_step_into_variants = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":26 + * cdef public int pydev_smart_child_offset + * cdef public tuple pydev_smart_step_into_variants + * cdef public dict target_id_to_smart_step_into_variant # <<<<<<<<<<<<<< + * cdef public bint pydev_use_scoped_step_frame + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->target_id_to_smart_step_into_variant); + __pyx_r = __pyx_v_self->target_id_to_smart_step_into_variant; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyDict_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(1, 26, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->target_id_to_smart_step_into_variant); + __Pyx_DECREF(__pyx_v_self->target_id_to_smart_step_into_variant); + __pyx_v_self->target_id_to_smart_step_into_variant = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.target_id_to_smart_step_into_variant.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->target_id_to_smart_step_into_variant); + __Pyx_DECREF(__pyx_v_self->target_id_to_smart_step_into_variant); + __pyx_v_self->target_id_to_smart_step_into_variant = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pxd":27 + * cdef public tuple pydev_smart_step_into_variants + * cdef public dict target_id_to_smart_step_into_variant + * cdef public bint pydev_use_scoped_step_frame # <<<<<<<<<<<<<< + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->pydev_use_scoped_step_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_use_scoped_step_frame.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 27, __pyx_L1_error) + __pyx_v_self->pydev_use_scoped_step_frame = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.pydev_use_scoped_step_frame.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_6__reduce_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_6__reduce_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + int __pyx_t_14; + int __pyx_t_15; + int __pyx_t_16; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self.conditional_breakpoint_exception, self.is_tracing, self.pydev_call_from_jinja2, self.pydev_call_inside_jinja2, self.pydev_django_resolve_frame, self.pydev_func_name, self.pydev_message, self.pydev_next_line, self.pydev_notify_kill, self.pydev_original_step_cmd, self.pydev_smart_child_offset, self.pydev_smart_parent_offset, self.pydev_smart_step_into_variants, self.pydev_smart_step_stop, self.pydev_state, self.pydev_step_cmd, self.pydev_step_stop, self.pydev_use_scoped_step_frame, self.step_in_initial_location, self.suspend_type, self.suspended_at_unhandled, self.target_id_to_smart_step_into_variant, self.thread_tracer, self.top_level_thread_tracer_no_back_frames, self.top_level_thread_tracer_unhandled, self.trace_suspend_type) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->is_tracing); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_self->pydev_django_resolve_frame); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_next_line); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_self->pydev_notify_kill); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_original_step_cmd); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_smart_child_offset); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_smart_parent_offset); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_state); if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_9 = __Pyx_PyInt_From_int(__pyx_v_self->pydev_step_cmd); if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = __Pyx_PyBool_FromLong(__pyx_v_self->pydev_use_scoped_step_frame); if (unlikely(!__pyx_t_10)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_11 = __Pyx_PyInt_From_int(__pyx_v_self->suspend_type); if (unlikely(!__pyx_t_11)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_11); + __pyx_t_12 = __Pyx_PyBool_FromLong(__pyx_v_self->suspended_at_unhandled); if (unlikely(!__pyx_t_12)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_13 = PyTuple_New(26); if (unlikely(!__pyx_t_13)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_INCREF(__pyx_v_self->conditional_breakpoint_exception); + __Pyx_GIVEREF(__pyx_v_self->conditional_breakpoint_exception); + PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_v_self->conditional_breakpoint_exception); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_t_1); + __Pyx_INCREF(__pyx_v_self->pydev_call_from_jinja2); + __Pyx_GIVEREF(__pyx_v_self->pydev_call_from_jinja2); + PyTuple_SET_ITEM(__pyx_t_13, 2, __pyx_v_self->pydev_call_from_jinja2); + __Pyx_INCREF(__pyx_v_self->pydev_call_inside_jinja2); + __Pyx_GIVEREF(__pyx_v_self->pydev_call_inside_jinja2); + PyTuple_SET_ITEM(__pyx_t_13, 3, __pyx_v_self->pydev_call_inside_jinja2); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_13, 4, __pyx_t_2); + __Pyx_INCREF(__pyx_v_self->pydev_func_name); + __Pyx_GIVEREF(__pyx_v_self->pydev_func_name); + PyTuple_SET_ITEM(__pyx_t_13, 5, __pyx_v_self->pydev_func_name); + __Pyx_INCREF(__pyx_v_self->pydev_message); + __Pyx_GIVEREF(__pyx_v_self->pydev_message); + PyTuple_SET_ITEM(__pyx_t_13, 6, __pyx_v_self->pydev_message); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_13, 7, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_13, 8, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_13, 9, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_13, 10, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_13, 11, __pyx_t_7); + __Pyx_INCREF(__pyx_v_self->pydev_smart_step_into_variants); + __Pyx_GIVEREF(__pyx_v_self->pydev_smart_step_into_variants); + PyTuple_SET_ITEM(__pyx_t_13, 12, __pyx_v_self->pydev_smart_step_into_variants); + __Pyx_INCREF(__pyx_v_self->pydev_smart_step_stop); + __Pyx_GIVEREF(__pyx_v_self->pydev_smart_step_stop); + PyTuple_SET_ITEM(__pyx_t_13, 13, __pyx_v_self->pydev_smart_step_stop); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_13, 14, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_13, 15, __pyx_t_9); + __Pyx_INCREF(__pyx_v_self->pydev_step_stop); + __Pyx_GIVEREF(__pyx_v_self->pydev_step_stop); + PyTuple_SET_ITEM(__pyx_t_13, 16, __pyx_v_self->pydev_step_stop); + __Pyx_GIVEREF(__pyx_t_10); + PyTuple_SET_ITEM(__pyx_t_13, 17, __pyx_t_10); + __Pyx_INCREF(__pyx_v_self->step_in_initial_location); + __Pyx_GIVEREF(__pyx_v_self->step_in_initial_location); + PyTuple_SET_ITEM(__pyx_t_13, 18, __pyx_v_self->step_in_initial_location); + __Pyx_GIVEREF(__pyx_t_11); + PyTuple_SET_ITEM(__pyx_t_13, 19, __pyx_t_11); + __Pyx_GIVEREF(__pyx_t_12); + PyTuple_SET_ITEM(__pyx_t_13, 20, __pyx_t_12); + __Pyx_INCREF(__pyx_v_self->target_id_to_smart_step_into_variant); + __Pyx_GIVEREF(__pyx_v_self->target_id_to_smart_step_into_variant); + PyTuple_SET_ITEM(__pyx_t_13, 21, __pyx_v_self->target_id_to_smart_step_into_variant); + __Pyx_INCREF(__pyx_v_self->thread_tracer); + __Pyx_GIVEREF(__pyx_v_self->thread_tracer); + PyTuple_SET_ITEM(__pyx_t_13, 22, __pyx_v_self->thread_tracer); + __Pyx_INCREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + __Pyx_GIVEREF(__pyx_v_self->top_level_thread_tracer_no_back_frames); + PyTuple_SET_ITEM(__pyx_t_13, 23, __pyx_v_self->top_level_thread_tracer_no_back_frames); + __Pyx_INCREF(__pyx_v_self->top_level_thread_tracer_unhandled); + __Pyx_GIVEREF(__pyx_v_self->top_level_thread_tracer_unhandled); + PyTuple_SET_ITEM(__pyx_t_13, 24, __pyx_v_self->top_level_thread_tracer_unhandled); + __Pyx_INCREF(__pyx_v_self->trace_suspend_type); + __Pyx_GIVEREF(__pyx_v_self->trace_suspend_type); + PyTuple_SET_ITEM(__pyx_t_13, 25, __pyx_v_self->trace_suspend_type); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_t_3 = 0; + __pyx_t_4 = 0; + __pyx_t_5 = 0; + __pyx_t_6 = 0; + __pyx_t_7 = 0; + __pyx_t_8 = 0; + __pyx_t_9 = 0; + __pyx_t_10 = 0; + __pyx_t_11 = 0; + __pyx_t_12 = 0; + __pyx_v_state = ((PyObject*)__pyx_t_13); + __pyx_t_13 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self.conditional_breakpoint_exception, self.is_tracing, self.pydev_call_from_jinja2, self.pydev_call_inside_jinja2, self.pydev_django_resolve_frame, self.pydev_func_name, self.pydev_message, self.pydev_next_line, self.pydev_notify_kill, self.pydev_original_step_cmd, self.pydev_smart_child_offset, self.pydev_smart_parent_offset, self.pydev_smart_step_into_variants, self.pydev_smart_step_stop, self.pydev_state, self.pydev_step_cmd, self.pydev_step_stop, self.pydev_use_scoped_step_frame, self.step_in_initial_location, self.suspend_type, self.suspended_at_unhandled, self.target_id_to_smart_step_into_variant, self.thread_tracer, self.top_level_thread_tracer_no_back_frames, self.top_level_thread_tracer_unhandled, self.trace_suspend_type) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_13 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_13)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __pyx_v__dict = __pyx_t_13; + __pyx_t_13 = 0; + + /* "(tree fragment)":7 + * state = (self.conditional_breakpoint_exception, self.is_tracing, self.pydev_call_from_jinja2, self.pydev_call_inside_jinja2, self.pydev_django_resolve_frame, self.pydev_func_name, self.pydev_message, self.pydev_next_line, self.pydev_notify_kill, self.pydev_original_step_cmd, self.pydev_smart_child_offset, self.pydev_smart_parent_offset, self.pydev_smart_step_into_variants, self.pydev_smart_step_stop, self.pydev_state, self.pydev_step_cmd, self.pydev_step_stop, self.pydev_use_scoped_step_frame, self.step_in_initial_location, self.suspend_type, self.suspended_at_unhandled, self.target_id_to_smart_step_into_variant, self.thread_tracer, self.top_level_thread_tracer_no_back_frames, self.top_level_thread_tracer_unhandled, self.trace_suspend_type) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_14 = (__pyx_v__dict != Py_None); + __pyx_t_15 = (__pyx_t_14 != 0); + if (__pyx_t_15) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_13 = PyTuple_New(1); if (unlikely(!__pyx_t_13)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_v__dict); + __pyx_t_12 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_13); if (unlikely(!__pyx_t_12)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_12)); + __pyx_t_12 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self.conditional_breakpoint_exception is not None or self.pydev_call_from_jinja2 is not None or self.pydev_call_inside_jinja2 is not None or self.pydev_func_name is not None or self.pydev_message is not None or self.pydev_smart_step_into_variants is not None or self.pydev_smart_step_stop is not None or self.pydev_step_stop is not None or self.step_in_initial_location is not None or self.target_id_to_smart_step_into_variant is not None or self.thread_tracer is not None or self.top_level_thread_tracer_no_back_frames is not None or self.top_level_thread_tracer_unhandled is not None or self.trace_suspend_type is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self.conditional_breakpoint_exception, self.is_tracing, self.pydev_call_from_jinja2, self.pydev_call_inside_jinja2, self.pydev_django_resolve_frame, self.pydev_func_name, self.pydev_message, self.pydev_next_line, self.pydev_notify_kill, self.pydev_original_step_cmd, self.pydev_smart_child_offset, self.pydev_smart_parent_offset, self.pydev_smart_step_into_variants, self.pydev_smart_step_stop, self.pydev_state, self.pydev_step_cmd, self.pydev_step_stop, self.pydev_use_scoped_step_frame, self.step_in_initial_location, self.suspend_type, self.suspended_at_unhandled, self.target_id_to_smart_step_into_variant, self.thread_tracer, self.top_level_thread_tracer_no_back_frames, self.top_level_thread_tracer_unhandled, self.trace_suspend_type) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self.conditional_breakpoint_exception is not None or self.pydev_call_from_jinja2 is not None or self.pydev_call_inside_jinja2 is not None or self.pydev_func_name is not None or self.pydev_message is not None or self.pydev_smart_step_into_variants is not None or self.pydev_smart_step_stop is not None or self.pydev_step_stop is not None or self.step_in_initial_location is not None or self.target_id_to_smart_step_into_variant is not None or self.thread_tracer is not None or self.top_level_thread_tracer_no_back_frames is not None or self.top_level_thread_tracer_unhandled is not None or self.trace_suspend_type is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, None), state + */ + /*else*/ { + __pyx_t_14 = (__pyx_v_self->conditional_breakpoint_exception != ((PyObject*)Py_None)); + __pyx_t_16 = (__pyx_t_14 != 0); + if (!__pyx_t_16) { + } else { + __pyx_t_15 = __pyx_t_16; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_16 = (__pyx_v_self->pydev_call_from_jinja2 != Py_None); + __pyx_t_14 = (__pyx_t_16 != 0); + if (!__pyx_t_14) { + } else { + __pyx_t_15 = __pyx_t_14; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_self->pydev_call_inside_jinja2 != Py_None); + __pyx_t_16 = (__pyx_t_14 != 0); + if (!__pyx_t_16) { + } else { + __pyx_t_15 = __pyx_t_16; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_16 = (__pyx_v_self->pydev_func_name != ((PyObject*)Py_None)); + __pyx_t_14 = (__pyx_t_16 != 0); + if (!__pyx_t_14) { + } else { + __pyx_t_15 = __pyx_t_14; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_self->pydev_message != ((PyObject*)Py_None)); + __pyx_t_16 = (__pyx_t_14 != 0); + if (!__pyx_t_16) { + } else { + __pyx_t_15 = __pyx_t_16; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_16 = (__pyx_v_self->pydev_smart_step_into_variants != ((PyObject*)Py_None)); + __pyx_t_14 = (__pyx_t_16 != 0); + if (!__pyx_t_14) { + } else { + __pyx_t_15 = __pyx_t_14; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_self->pydev_smart_step_stop != Py_None); + __pyx_t_16 = (__pyx_t_14 != 0); + if (!__pyx_t_16) { + } else { + __pyx_t_15 = __pyx_t_16; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_16 = (__pyx_v_self->pydev_step_stop != Py_None); + __pyx_t_14 = (__pyx_t_16 != 0); + if (!__pyx_t_14) { + } else { + __pyx_t_15 = __pyx_t_14; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_self->step_in_initial_location != Py_None); + __pyx_t_16 = (__pyx_t_14 != 0); + if (!__pyx_t_16) { + } else { + __pyx_t_15 = __pyx_t_16; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_16 = (__pyx_v_self->target_id_to_smart_step_into_variant != ((PyObject*)Py_None)); + __pyx_t_14 = (__pyx_t_16 != 0); + if (!__pyx_t_14) { + } else { + __pyx_t_15 = __pyx_t_14; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_self->thread_tracer != Py_None); + __pyx_t_16 = (__pyx_t_14 != 0); + if (!__pyx_t_16) { + } else { + __pyx_t_15 = __pyx_t_16; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_16 = (__pyx_v_self->top_level_thread_tracer_no_back_frames != Py_None); + __pyx_t_14 = (__pyx_t_16 != 0); + if (!__pyx_t_14) { + } else { + __pyx_t_15 = __pyx_t_14; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_self->top_level_thread_tracer_unhandled != Py_None); + __pyx_t_16 = (__pyx_t_14 != 0); + if (!__pyx_t_16) { + } else { + __pyx_t_15 = __pyx_t_16; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_16 = (__pyx_v_self->trace_suspend_type != ((PyObject*)Py_None)); + __pyx_t_14 = (__pyx_t_16 != 0); + __pyx_t_15 = __pyx_t_14; + __pyx_L4_bool_binop_done:; + __pyx_v_use_setstate = __pyx_t_15; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.conditional_breakpoint_exception is not None or self.pydev_call_from_jinja2 is not None or self.pydev_call_inside_jinja2 is not None or self.pydev_func_name is not None or self.pydev_message is not None or self.pydev_smart_step_into_variants is not None or self.pydev_smart_step_stop is not None or self.pydev_step_stop is not None or self.step_in_initial_location is not None or self.target_id_to_smart_step_into_variant is not None or self.thread_tracer is not None or self.top_level_thread_tracer_no_back_frames is not None or self.top_level_thread_tracer_unhandled is not None or self.trace_suspend_type is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, None), state + * else: + */ + __pyx_t_15 = (__pyx_v_use_setstate != 0); + if (__pyx_t_15) { + + /* "(tree fragment)":13 + * use_setstate = self.conditional_breakpoint_exception is not None or self.pydev_call_from_jinja2 is not None or self.pydev_call_inside_jinja2 is not None or self.pydev_func_name is not None or self.pydev_message is not None or self.pydev_smart_step_into_variants is not None or self.pydev_smart_step_stop is not None or self.pydev_step_stop is not None or self.step_in_initial_location is not None or self.target_id_to_smart_step_into_variant is not None or self.thread_tracer is not None or self.top_level_thread_tracer_no_back_frames is not None or self.top_level_thread_tracer_unhandled is not None or self.trace_suspend_type is not None + * if use_setstate: + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_n_s_pyx_unpickle_PyDBAdditionalThr); if (unlikely(!__pyx_t_12)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_13 = PyTuple_New(3); if (unlikely(!__pyx_t_13)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_13, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_123419394); + __Pyx_GIVEREF(__pyx_int_123419394); + PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_int_123419394); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_13, 2, Py_None); + __pyx_t_11 = PyTuple_New(3); if (unlikely(!__pyx_t_11)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_11); + __Pyx_GIVEREF(__pyx_t_12); + PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_12); + __Pyx_GIVEREF(__pyx_t_13); + PyTuple_SET_ITEM(__pyx_t_11, 1, __pyx_t_13); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_11, 2, __pyx_v_state); + __pyx_t_12 = 0; + __pyx_t_13 = 0; + __pyx_r = __pyx_t_11; + __pyx_t_11 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.conditional_breakpoint_exception is not None or self.pydev_call_from_jinja2 is not None or self.pydev_call_inside_jinja2 is not None or self.pydev_func_name is not None or self.pydev_message is not None or self.pydev_smart_step_into_variants is not None or self.pydev_smart_step_stop is not None or self.pydev_step_stop is not None or self.step_in_initial_location is not None or self.target_id_to_smart_step_into_variant is not None or self.thread_tracer is not None or self.top_level_thread_tracer_no_back_frames is not None or self.top_level_thread_tracer_unhandled is not None or self.trace_suspend_type is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, None), state + * else: + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_pyx_unpickle_PyDBAdditionalThr); if (unlikely(!__pyx_t_11)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_11); + __pyx_t_13 = PyTuple_New(3); if (unlikely(!__pyx_t_13)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_13, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_123419394); + __Pyx_GIVEREF(__pyx_int_123419394); + PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_int_123419394); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_13, 2, __pyx_v_state); + __pyx_t_12 = PyTuple_New(2); if (unlikely(!__pyx_t_12)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_GIVEREF(__pyx_t_11); + PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_11); + __Pyx_GIVEREF(__pyx_t_13); + PyTuple_SET_ITEM(__pyx_t_12, 1, __pyx_t_13); + __pyx_t_11 = 0; + __pyx_t_13 = 0; + __pyx_r = __pyx_t_12; + __pyx_t_12 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_XDECREF(__pyx_t_11); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_13); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_8__setstate_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_8__setstate_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_PyDBAdditionalThreadInfo__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_PyDBAdditionalThreadInfo, (type(self), 0x75b3b02, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":145 + * + * + * def set_additional_thread_info(thread): # <<<<<<<<<<<<<< + * try: + * additional_info = thread.additional_info + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_1set_additional_thread_info(PyObject *__pyx_self, PyObject *__pyx_v_thread); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_1set_additional_thread_info = {"set_additional_thread_info", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_1set_additional_thread_info, METH_O, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_1set_additional_thread_info(PyObject *__pyx_self, PyObject *__pyx_v_thread) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("set_additional_thread_info (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_set_additional_thread_info(__pyx_self, ((PyObject *)__pyx_v_thread)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_set_additional_thread_info(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_thread) { + PyObject *__pyx_v_additional_info = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("set_additional_thread_info", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":146 + * + * def set_additional_thread_info(thread): + * try: # <<<<<<<<<<<<<< + * additional_info = thread.additional_info + * if additional_info is None: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":147 + * def set_additional_thread_info(thread): + * try: + * additional_info = thread.additional_info # <<<<<<<<<<<<<< + * if additional_info is None: + * raise AttributeError() + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_thread, __pyx_n_s_additional_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 147, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_additional_info = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":148 + * try: + * additional_info = thread.additional_info + * if additional_info is None: # <<<<<<<<<<<<<< + * raise AttributeError() + * except: + */ + __pyx_t_5 = (__pyx_v_additional_info == Py_None); + __pyx_t_6 = (__pyx_t_5 != 0); + if (unlikely(__pyx_t_6)) { + + /* "_pydevd_bundle/pydevd_cython.pyx":149 + * additional_info = thread.additional_info + * if additional_info is None: + * raise AttributeError() # <<<<<<<<<<<<<< + * except: + * with _set_additional_thread_info_lock: + */ + __pyx_t_4 = __Pyx_PyObject_CallNoArg(__pyx_builtin_AttributeError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 149, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(0, 149, __pyx_L3_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":148 + * try: + * additional_info = thread.additional_info + * if additional_info is None: # <<<<<<<<<<<<<< + * raise AttributeError() + * except: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":146 + * + * def set_additional_thread_info(thread): + * try: # <<<<<<<<<<<<<< + * additional_info = thread.additional_info + * if additional_info is None: + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":150 + * if additional_info is None: + * raise AttributeError() + * except: # <<<<<<<<<<<<<< + * with _set_additional_thread_info_lock: + * # If it's not there, set it within a lock to avoid any racing + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.set_additional_thread_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_4, &__pyx_t_7, &__pyx_t_8) < 0) __PYX_ERR(0, 150, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_8); + + /* "_pydevd_bundle/pydevd_cython.pyx":151 + * raise AttributeError() + * except: + * with _set_additional_thread_info_lock: # <<<<<<<<<<<<<< + * # If it's not there, set it within a lock to avoid any racing + * # conditions. + */ + /*with:*/ { + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_set_additional_thread_info_lock); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 151, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = __Pyx_PyObject_LookupSpecial(__pyx_t_9, __pyx_n_s_exit); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 151, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_12 = __Pyx_PyObject_LookupSpecial(__pyx_t_9, __pyx_n_s_enter); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 151, __pyx_L12_error) + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_13 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_12))) { + __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_12); + if (likely(__pyx_t_13)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_12); + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_12, function); + } + } + __pyx_t_11 = (__pyx_t_13) ? __Pyx_PyObject_CallOneArg(__pyx_t_12, __pyx_t_13) : __Pyx_PyObject_CallNoArg(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 151, __pyx_L12_error) + __Pyx_GOTREF(__pyx_t_11); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + /*try:*/ { + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":154 + * # If it's not there, set it within a lock to avoid any racing + * # conditions. + * additional_info = getattr(thread, 'additional_info', None) # <<<<<<<<<<<<<< + * if additional_info is None: + * additional_info = PyDBAdditionalThreadInfo() + */ + __pyx_t_9 = __Pyx_GetAttr3(__pyx_v_thread, __pyx_n_s_additional_info, Py_None); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 154, __pyx_L18_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_XDECREF_SET(__pyx_v_additional_info, __pyx_t_9); + __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":155 + * # conditions. + * additional_info = getattr(thread, 'additional_info', None) + * if additional_info is None: # <<<<<<<<<<<<<< + * additional_info = PyDBAdditionalThreadInfo() + * thread.additional_info = additional_info + */ + __pyx_t_6 = (__pyx_v_additional_info == Py_None); + __pyx_t_5 = (__pyx_t_6 != 0); + if (__pyx_t_5) { + + /* "_pydevd_bundle/pydevd_cython.pyx":156 + * additional_info = getattr(thread, 'additional_info', None) + * if additional_info is None: + * additional_info = PyDBAdditionalThreadInfo() # <<<<<<<<<<<<<< + * thread.additional_info = additional_info + * + */ + __pyx_t_9 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo)); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 156, __pyx_L18_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF_SET(__pyx_v_additional_info, __pyx_t_9); + __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":155 + * # conditions. + * additional_info = getattr(thread, 'additional_info', None) + * if additional_info is None: # <<<<<<<<<<<<<< + * additional_info = PyDBAdditionalThreadInfo() + * thread.additional_info = additional_info + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":157 + * if additional_info is None: + * additional_info = PyDBAdditionalThreadInfo() + * thread.additional_info = additional_info # <<<<<<<<<<<<<< + * + * return additional_info + */ + if (__Pyx_PyObject_SetAttrStr(__pyx_v_thread, __pyx_n_s_additional_info, __pyx_v_additional_info) < 0) __PYX_ERR(0, 157, __pyx_L18_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":151 + * raise AttributeError() + * except: + * with _set_additional_thread_info_lock: # <<<<<<<<<<<<<< + * # If it's not there, set it within a lock to avoid any racing + * # conditions. + */ + } + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; + goto __pyx_L25_try_end; + __pyx_L18_error:; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.set_additional_thread_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_9, &__pyx_t_11, &__pyx_t_12) < 0) __PYX_ERR(0, 151, __pyx_L20_except_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_GOTREF(__pyx_t_11); + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_13 = PyTuple_Pack(3, __pyx_t_9, __pyx_t_11, __pyx_t_12); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 151, __pyx_L20_except_error) + __Pyx_GOTREF(__pyx_t_13); + __pyx_t_17 = __Pyx_PyObject_Call(__pyx_t_10, __pyx_t_13, NULL); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 151, __pyx_L20_except_error) + __Pyx_GOTREF(__pyx_t_17); + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_17); + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + if (__pyx_t_5 < 0) __PYX_ERR(0, 151, __pyx_L20_except_error) + __pyx_t_6 = ((!(__pyx_t_5 != 0)) != 0); + if (__pyx_t_6) { + __Pyx_GIVEREF(__pyx_t_9); + __Pyx_GIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ErrRestoreWithState(__pyx_t_9, __pyx_t_11, __pyx_t_12); + __pyx_t_9 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; + __PYX_ERR(0, 151, __pyx_L20_except_error) + } + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + goto __pyx_L19_exception_handled; + } + __pyx_L20_except_error:; + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_14, __pyx_t_15, __pyx_t_16); + goto __pyx_L5_except_error; + __pyx_L19_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_14, __pyx_t_15, __pyx_t_16); + __pyx_L25_try_end:; + } + } + /*finally:*/ { + /*normal exit:*/{ + if (__pyx_t_10) { + __pyx_t_16 = __Pyx_PyObject_Call(__pyx_t_10, __pyx_tuple__2, NULL); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 151, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_16); + __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0; + } + goto __pyx_L17; + } + __pyx_L17:; + } + goto __pyx_L30; + __pyx_L12_error:; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + goto __pyx_L5_except_error; + __pyx_L30:; + } + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L4_exception_handled; + } + __pyx_L5_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":146 + * + * def set_additional_thread_info(thread): + * try: # <<<<<<<<<<<<<< + * additional_info = thread.additional_info + * if additional_info is None: + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L4_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + __pyx_L8_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":159 + * thread.additional_info = additional_info + * + * return additional_info # <<<<<<<<<<<<<< + * import linecache + * import os.path + */ + __Pyx_XDECREF(__pyx_r); + if (unlikely(!__pyx_v_additional_info)) { __Pyx_RaiseUnboundLocalError("additional_info"); __PYX_ERR(0, 159, __pyx_L1_error) } + __Pyx_INCREF(__pyx_v_additional_info); + __pyx_r = __pyx_v_additional_info; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":145 + * + * + * def set_additional_thread_info(thread): # <<<<<<<<<<<<<< + * try: + * additional_info = thread.additional_info + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_11); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_13); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.set_additional_thread_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_additional_info); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":176 + * except ImportError: + * + * def get_smart_step_into_variant_from_frame_offset(*args, **kwargs): # <<<<<<<<<<<<<< + * return None + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_3get_smart_step_into_variant_from_frame_offset(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_3get_smart_step_into_variant_from_frame_offset = {"get_smart_step_into_variant_from_frame_offset", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_3get_smart_step_into_variant_from_frame_offset, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_3get_smart_step_into_variant_from_frame_offset(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + CYTHON_UNUSED PyObject *__pyx_v_args = 0; + CYTHON_UNUSED PyObject *__pyx_v_kwargs = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_smart_step_into_variant_from_frame_offset (wrapper)", 0); + if (unlikely(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "get_smart_step_into_variant_from_frame_offset", 1))) return NULL; + __Pyx_INCREF(__pyx_args); + __pyx_v_args = __pyx_args; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_2get_smart_step_into_variant_from_frame_offset(__pyx_self, __pyx_v_args, __pyx_v_kwargs); + + /* function exit code */ + __Pyx_XDECREF(__pyx_v_args); + __Pyx_XDECREF(__pyx_v_kwargs); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_2get_smart_step_into_variant_from_frame_offset(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_args, CYTHON_UNUSED PyObject *__pyx_v_kwargs) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_smart_step_into_variant_from_frame_offset", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":177 + * + * def get_smart_step_into_variant_from_frame_offset(*args, **kwargs): + * return None # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":176 + * except ImportError: + * + * def get_smart_step_into_variant_from_frame_offset(*args, **kwargs): # <<<<<<<<<<<<<< + * return None + * + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":212 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef is_unhandled_exception(container_obj, py_db, frame, int last_raise_line, set raise_lines): # <<<<<<<<<<<<<< + * # ELSE + * # def is_unhandled_exception(container_obj, py_db, frame, last_raise_line, raise_lines): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_is_unhandled_exception(PyObject *__pyx_v_container_obj, PyObject *__pyx_v_py_db, PyObject *__pyx_v_frame, int __pyx_v_last_raise_line, PyObject *__pyx_v_raise_lines) { + PyObject *__pyx_v_try_except_infos = NULL; + PyObject *__pyx_v_valid_try_except_infos = NULL; + PyObject *__pyx_v_try_except_info = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + Py_ssize_t __pyx_t_7; + PyObject *(*__pyx_t_8)(PyObject *); + PyObject *__pyx_t_9 = NULL; + int __pyx_t_10; + int __pyx_t_11; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("is_unhandled_exception", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":216 + * # def is_unhandled_exception(container_obj, py_db, frame, last_raise_line, raise_lines): + * # ENDIF + * if frame.f_lineno in raise_lines: # <<<<<<<<<<<<<< + * return True + * + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 216, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (unlikely(__pyx_v_raise_lines == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 216, __pyx_L1_error) + } + __pyx_t_2 = (__Pyx_PySet_ContainsTF(__pyx_t_1, __pyx_v_raise_lines, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 216, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":217 + * # ENDIF + * if frame.f_lineno in raise_lines: + * return True # <<<<<<<<<<<<<< + * + * else: + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_True); + __pyx_r = Py_True; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":216 + * # def is_unhandled_exception(container_obj, py_db, frame, last_raise_line, raise_lines): + * # ENDIF + * if frame.f_lineno in raise_lines: # <<<<<<<<<<<<<< + * return True + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":220 + * + * else: + * try_except_infos = container_obj.try_except_infos # <<<<<<<<<<<<<< + * if try_except_infos is None: + * container_obj.try_except_infos = try_except_infos = py_db.collect_try_except_info(frame.f_code) + */ + /*else*/ { + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_container_obj, __pyx_n_s_try_except_infos); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 220, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_try_except_infos = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":221 + * else: + * try_except_infos = container_obj.try_except_infos + * if try_except_infos is None: # <<<<<<<<<<<<<< + * container_obj.try_except_infos = try_except_infos = py_db.collect_try_except_info(frame.f_code) + * + */ + __pyx_t_3 = (__pyx_v_try_except_infos == Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":222 + * try_except_infos = container_obj.try_except_infos + * if try_except_infos is None: + * container_obj.try_except_infos = try_except_infos = py_db.collect_try_except_info(frame.f_code) # <<<<<<<<<<<<<< + * + * if not try_except_infos: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_collect_try_except_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__Pyx_PyObject_SetAttrStr(__pyx_v_container_obj, __pyx_n_s_try_except_infos, __pyx_t_1) < 0) __PYX_ERR(0, 222, __pyx_L1_error) + __Pyx_INCREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_try_except_infos, __pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":221 + * else: + * try_except_infos = container_obj.try_except_infos + * if try_except_infos is None: # <<<<<<<<<<<<<< + * container_obj.try_except_infos = try_except_infos = py_db.collect_try_except_info(frame.f_code) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":224 + * container_obj.try_except_infos = try_except_infos = py_db.collect_try_except_info(frame.f_code) + * + * if not try_except_infos: # <<<<<<<<<<<<<< + * # Consider the last exception as unhandled because there's no try..except in it. + * return True + */ + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_try_except_infos); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 224, __pyx_L1_error) + __pyx_t_3 = ((!__pyx_t_2) != 0); + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":226 + * if not try_except_infos: + * # Consider the last exception as unhandled because there's no try..except in it. + * return True # <<<<<<<<<<<<<< + * else: + * # Now, consider only the try..except for the raise + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_True); + __pyx_r = Py_True; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":224 + * container_obj.try_except_infos = try_except_infos = py_db.collect_try_except_info(frame.f_code) + * + * if not try_except_infos: # <<<<<<<<<<<<<< + * # Consider the last exception as unhandled because there's no try..except in it. + * return True + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":229 + * else: + * # Now, consider only the try..except for the raise + * valid_try_except_infos = [] # <<<<<<<<<<<<<< + * for try_except_info in try_except_infos: + * if try_except_info.is_line_in_try_block(last_raise_line): + */ + /*else*/ { + __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 229, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_valid_try_except_infos = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":230 + * # Now, consider only the try..except for the raise + * valid_try_except_infos = [] + * for try_except_info in try_except_infos: # <<<<<<<<<<<<<< + * if try_except_info.is_line_in_try_block(last_raise_line): + * valid_try_except_infos.append(try_except_info) + */ + if (likely(PyList_CheckExact(__pyx_v_try_except_infos)) || PyTuple_CheckExact(__pyx_v_try_except_infos)) { + __pyx_t_1 = __pyx_v_try_except_infos; __Pyx_INCREF(__pyx_t_1); __pyx_t_7 = 0; + __pyx_t_8 = NULL; + } else { + __pyx_t_7 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_try_except_infos); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 230, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 230, __pyx_L1_error) + } + for (;;) { + if (likely(!__pyx_t_8)) { + if (likely(PyList_CheckExact(__pyx_t_1))) { + if (__pyx_t_7 >= PyList_GET_SIZE(__pyx_t_1)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_7); __Pyx_INCREF(__pyx_t_4); __pyx_t_7++; if (unlikely(0 < 0)) __PYX_ERR(0, 230, __pyx_L1_error) + #else + __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 230, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } else { + if (__pyx_t_7 >= PyTuple_GET_SIZE(__pyx_t_1)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_7); __Pyx_INCREF(__pyx_t_4); __pyx_t_7++; if (unlikely(0 < 0)) __PYX_ERR(0, 230, __pyx_L1_error) + #else + __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 230, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } + } else { + __pyx_t_4 = __pyx_t_8(__pyx_t_1); + if (unlikely(!__pyx_t_4)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 230, __pyx_L1_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_4); + } + __Pyx_XDECREF_SET(__pyx_v_try_except_info, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":231 + * valid_try_except_infos = [] + * for try_except_info in try_except_infos: + * if try_except_info.is_line_in_try_block(last_raise_line): # <<<<<<<<<<<<<< + * valid_try_except_infos.append(try_except_info) + * + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_try_except_info, __pyx_n_s_is_line_in_try_block); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 231, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = __Pyx_PyInt_From_int(__pyx_v_last_raise_line); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 231, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_4 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_9, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 231, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 231, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":232 + * for try_except_info in try_except_infos: + * if try_except_info.is_line_in_try_block(last_raise_line): + * valid_try_except_infos.append(try_except_info) # <<<<<<<<<<<<<< + * + * if not valid_try_except_infos: + */ + __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_valid_try_except_infos, __pyx_v_try_except_info); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 232, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":231 + * valid_try_except_infos = [] + * for try_except_info in try_except_infos: + * if try_except_info.is_line_in_try_block(last_raise_line): # <<<<<<<<<<<<<< + * valid_try_except_infos.append(try_except_info) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":230 + * # Now, consider only the try..except for the raise + * valid_try_except_infos = [] + * for try_except_info in try_except_infos: # <<<<<<<<<<<<<< + * if try_except_info.is_line_in_try_block(last_raise_line): + * valid_try_except_infos.append(try_except_info) + */ + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":234 + * valid_try_except_infos.append(try_except_info) + * + * if not valid_try_except_infos: # <<<<<<<<<<<<<< + * return True + * + */ + __pyx_t_3 = (PyList_GET_SIZE(__pyx_v_valid_try_except_infos) != 0); + __pyx_t_2 = ((!__pyx_t_3) != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":235 + * + * if not valid_try_except_infos: + * return True # <<<<<<<<<<<<<< + * + * else: + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_True); + __pyx_r = Py_True; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":234 + * valid_try_except_infos.append(try_except_info) + * + * if not valid_try_except_infos: # <<<<<<<<<<<<<< + * return True + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":242 + * # where one try..except is inside the other with only a raise + * # and it's gotten in the except line. + * for try_except_info in try_except_infos: # <<<<<<<<<<<<<< + * if try_except_info.is_line_in_except_block(frame.f_lineno): + * if ( + */ + /*else*/ { + if (likely(PyList_CheckExact(__pyx_v_try_except_infos)) || PyTuple_CheckExact(__pyx_v_try_except_infos)) { + __pyx_t_1 = __pyx_v_try_except_infos; __Pyx_INCREF(__pyx_t_1); __pyx_t_7 = 0; + __pyx_t_8 = NULL; + } else { + __pyx_t_7 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_try_except_infos); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 242, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 242, __pyx_L1_error) + } + for (;;) { + if (likely(!__pyx_t_8)) { + if (likely(PyList_CheckExact(__pyx_t_1))) { + if (__pyx_t_7 >= PyList_GET_SIZE(__pyx_t_1)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_7); __Pyx_INCREF(__pyx_t_4); __pyx_t_7++; if (unlikely(0 < 0)) __PYX_ERR(0, 242, __pyx_L1_error) + #else + __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 242, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } else { + if (__pyx_t_7 >= PyTuple_GET_SIZE(__pyx_t_1)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_7); __Pyx_INCREF(__pyx_t_4); __pyx_t_7++; if (unlikely(0 < 0)) __PYX_ERR(0, 242, __pyx_L1_error) + #else + __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 242, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } + } else { + __pyx_t_4 = __pyx_t_8(__pyx_t_1); + if (unlikely(!__pyx_t_4)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 242, __pyx_L1_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_4); + } + __Pyx_XDECREF_SET(__pyx_v_try_except_info, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":243 + * # and it's gotten in the except line. + * for try_except_info in try_except_infos: + * if try_except_info.is_line_in_except_block(frame.f_lineno): # <<<<<<<<<<<<<< + * if ( + * frame.f_lineno == try_except_info.except_line or + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_try_except_info, __pyx_n_s_is_line_in_except_block); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 243, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 243, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_4 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_9, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 243, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 243, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":245 + * if try_except_info.is_line_in_except_block(frame.f_lineno): + * if ( + * frame.f_lineno == try_except_info.except_line or # <<<<<<<<<<<<<< + * frame.f_lineno in try_except_info.raise_lines_in_except + * ): + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 245, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_try_except_info, __pyx_n_s_except_line); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 245, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = PyObject_RichCompare(__pyx_t_4, __pyx_t_5, Py_EQ); __Pyx_XGOTREF(__pyx_t_6); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 245, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 245, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (!__pyx_t_3) { + } else { + __pyx_t_2 = __pyx_t_3; + goto __pyx_L14_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":246 + * if ( + * frame.f_lineno == try_except_info.except_line or + * frame.f_lineno in try_except_info.raise_lines_in_except # <<<<<<<<<<<<<< + * ): + * # In a raise inside a try..except block or some except which doesn't + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 246, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_try_except_info, __pyx_n_s_raise_lines_in_except); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 246, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = (__Pyx_PySequence_ContainsTF(__pyx_t_6, __pyx_t_5, Py_EQ)); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 246, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_11 = (__pyx_t_3 != 0); + __pyx_t_2 = __pyx_t_11; + __pyx_L14_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":244 + * for try_except_info in try_except_infos: + * if try_except_info.is_line_in_except_block(frame.f_lineno): + * if ( # <<<<<<<<<<<<<< + * frame.f_lineno == try_except_info.except_line or + * frame.f_lineno in try_except_info.raise_lines_in_except + */ + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":250 + * # In a raise inside a try..except block or some except which doesn't + * # match the raised exception. + * return True # <<<<<<<<<<<<<< + * return False + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_True); + __pyx_r = Py_True; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":244 + * for try_except_info in try_except_infos: + * if try_except_info.is_line_in_except_block(frame.f_lineno): + * if ( # <<<<<<<<<<<<<< + * frame.f_lineno == try_except_info.except_line or + * frame.f_lineno in try_except_info.raise_lines_in_except + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":243 + * # and it's gotten in the except line. + * for try_except_info in try_except_infos: + * if try_except_info.is_line_in_except_block(frame.f_lineno): # <<<<<<<<<<<<<< + * if ( + * frame.f_lineno == try_except_info.except_line or + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":242 + * # where one try..except is inside the other with only a raise + * # and it's gotten in the except line. + * for try_except_info in try_except_infos: # <<<<<<<<<<<<<< + * if try_except_info.is_line_in_except_block(frame.f_lineno): + * if ( + */ + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":251 + * # match the raised exception. + * return True + * return False # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_False); + __pyx_r = Py_False; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":212 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef is_unhandled_exception(container_obj, py_db, frame, int last_raise_line, set raise_lines): # <<<<<<<<<<<<<< + * # ELSE + * # def is_unhandled_exception(container_obj, py_db, frame, last_raise_line, raise_lines): + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.is_unhandled_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_try_except_infos); + __Pyx_XDECREF(__pyx_v_valid_try_except_infos); + __Pyx_XDECREF(__pyx_v_try_except_info); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":257 + * cdef class _TryExceptContainerObj: + * cdef public list try_except_infos; + * def __init__(self): # <<<<<<<<<<<<<< + * self.try_except_infos = None + * # ELSE + */ + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;} + if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__init__", 0))) return -1; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj___init__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj___init__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":258 + * cdef public list try_except_infos; + * def __init__(self): + * self.try_except_infos = None # <<<<<<<<<<<<<< + * # ELSE + * # class _TryExceptContainerObj(object): + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->try_except_infos); + __Pyx_DECREF(__pyx_v_self->try_except_infos); + __pyx_v_self->try_except_infos = ((PyObject*)Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":257 + * cdef class _TryExceptContainerObj: + * cdef public list try_except_infos; + * def __init__(self): # <<<<<<<<<<<<<< + * self.try_except_infos = None + * # ELSE + */ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":256 + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class _TryExceptContainerObj: + * cdef public list try_except_infos; # <<<<<<<<<<<<<< + * def __init__(self): + * self.try_except_infos = None + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->try_except_infos); + __pyx_r = __pyx_v_self->try_except_infos; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyList_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 256, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->try_except_infos); + __Pyx_DECREF(__pyx_v_self->try_except_infos); + __pyx_v_self->try_except_infos = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython._TryExceptContainerObj.try_except_infos.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->try_except_infos); + __Pyx_DECREF(__pyx_v_self->try_except_infos); + __pyx_v_self->try_except_infos = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_2__reduce_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_2__reduce_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self.try_except_infos,) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_self->try_except_infos); + __Pyx_GIVEREF(__pyx_v_self->try_except_infos); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->try_except_infos); + __pyx_v_state = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self.try_except_infos,) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v__dict = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":7 + * state = (self.try_except_infos,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_2 = (__pyx_v__dict != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict); + __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self.try_except_infos is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self.try_except_infos,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self.try_except_infos is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, None), state + */ + /*else*/ { + __pyx_t_3 = (__pyx_v_self->try_except_infos != ((PyObject*)Py_None)); + __pyx_v_use_setstate = __pyx_t_3; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.try_except_infos is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, None), state + * else: + */ + __pyx_t_3 = (__pyx_v_use_setstate != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":13 + * use_setstate = self.try_except_infos is not None + * if use_setstate: + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle__TryExceptContain); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_210464433); + __Pyx_GIVEREF(__pyx_int_210464433); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_210464433); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None); + __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state); + __pyx_t_4 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.try_except_infos is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, None), state + * else: + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle__TryExceptContainerObj__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle__TryExceptContain); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_210464433); + __Pyx_GIVEREF(__pyx_int_210464433); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_210464433); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1); + __pyx_t_5 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython._TryExceptContainerObj.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle__TryExceptContainerObj__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_4__setstate_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_4__setstate_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle__TryExceptContainerObj__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle__TryExceptContainerObj__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle__TryExceptContainerObj, (type(self), 0xc8b6eb1, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle__TryExceptContainerObj__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython._TryExceptContainerObj.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":293 + * cdef int should_skip + * cdef object exc_info + * def __init__(self, tuple args): # <<<<<<<<<<<<<< + * self._args = args # In the cython version we don't need to pass the frame + * self.should_skip = -1 # On cythonized version, put in instance. + */ + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_args = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_args,0}; + PyObject* values[1] = {0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_args)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 293, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 1) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + } + __pyx_v_args = ((PyObject*)values[0]); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 293, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_args), (&PyTuple_Type), 1, "args", 1))) __PYX_ERR(0, 293, __pyx_L1_error) + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame___init__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self), __pyx_v_args); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame___init__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_args) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":294 + * cdef object exc_info + * def __init__(self, tuple args): + * self._args = args # In the cython version we don't need to pass the frame # <<<<<<<<<<<<<< + * self.should_skip = -1 # On cythonized version, put in instance. + * self.exc_info = () + */ + __Pyx_INCREF(__pyx_v_args); + __Pyx_GIVEREF(__pyx_v_args); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = __pyx_v_args; + + /* "_pydevd_bundle/pydevd_cython.pyx":295 + * def __init__(self, tuple args): + * self._args = args # In the cython version we don't need to pass the frame + * self.should_skip = -1 # On cythonized version, put in instance. # <<<<<<<<<<<<<< + * self.exc_info = () + * # ELSE + */ + __pyx_v_self->should_skip = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":296 + * self._args = args # In the cython version we don't need to pass the frame + * self.should_skip = -1 # On cythonized version, put in instance. + * self.exc_info = () # <<<<<<<<<<<<<< + * # ELSE + * # should_skip = -1 # Default value in class (put in instance on set). + */ + __Pyx_INCREF(__pyx_empty_tuple); + __Pyx_GIVEREF(__pyx_empty_tuple); + __Pyx_GOTREF(__pyx_v_self->exc_info); + __Pyx_DECREF(__pyx_v_self->exc_info); + __pyx_v_self->exc_info = __pyx_empty_tuple; + + /* "_pydevd_bundle/pydevd_cython.pyx":293 + * cdef int should_skip + * cdef object exc_info + * def __init__(self, tuple args): # <<<<<<<<<<<<<< + * self._args = args # In the cython version we don't need to pass the frame + * self.should_skip = -1 # On cythonized version, put in instance. + */ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":307 + * # ENDIF + * + * def set_suspend(self, *args, **kwargs): # <<<<<<<<<<<<<< + * self._args[0].set_suspend(*args, **kwargs) + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_3set_suspend(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_3set_suspend(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_args = 0; + PyObject *__pyx_v_kwargs = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("set_suspend (wrapper)", 0); + if (unlikely(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "set_suspend", 1))) return NULL; + __pyx_v_kwargs = (__pyx_kwds) ? PyDict_Copy(__pyx_kwds) : PyDict_New(); if (unlikely(!__pyx_v_kwargs)) return NULL; + __Pyx_GOTREF(__pyx_v_kwargs); + __Pyx_INCREF(__pyx_args); + __pyx_v_args = __pyx_args; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_2set_suspend(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self), __pyx_v_args, __pyx_v_kwargs); + + /* function exit code */ + __Pyx_XDECREF(__pyx_v_args); + __Pyx_XDECREF(__pyx_v_kwargs); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_2set_suspend(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_args, PyObject *__pyx_v_kwargs) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("set_suspend", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":308 + * + * def set_suspend(self, *args, **kwargs): + * self._args[0].set_suspend(*args, **kwargs) # <<<<<<<<<<<<<< + * + * def do_wait_suspend(self, *args, **kwargs): + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 308, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 308, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_set_suspend); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 308, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyDict_Copy(__pyx_v_kwargs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 308, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_v_args, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 308, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":307 + * # ENDIF + * + * def set_suspend(self, *args, **kwargs): # <<<<<<<<<<<<<< + * self._args[0].set_suspend(*args, **kwargs) + * + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.set_suspend", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":310 + * self._args[0].set_suspend(*args, **kwargs) + * + * def do_wait_suspend(self, *args, **kwargs): # <<<<<<<<<<<<<< + * self._args[0].do_wait_suspend(*args, **kwargs) + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_5do_wait_suspend(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_5do_wait_suspend(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_args = 0; + PyObject *__pyx_v_kwargs = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("do_wait_suspend (wrapper)", 0); + if (unlikely(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "do_wait_suspend", 1))) return NULL; + __pyx_v_kwargs = (__pyx_kwds) ? PyDict_Copy(__pyx_kwds) : PyDict_New(); if (unlikely(!__pyx_v_kwargs)) return NULL; + __Pyx_GOTREF(__pyx_v_kwargs); + __Pyx_INCREF(__pyx_args); + __pyx_v_args = __pyx_args; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_4do_wait_suspend(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self), __pyx_v_args, __pyx_v_kwargs); + + /* function exit code */ + __Pyx_XDECREF(__pyx_v_args); + __Pyx_XDECREF(__pyx_v_kwargs); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_4do_wait_suspend(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_args, PyObject *__pyx_v_kwargs) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("do_wait_suspend", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":311 + * + * def do_wait_suspend(self, *args, **kwargs): + * self._args[0].do_wait_suspend(*args, **kwargs) # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 311, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 311, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_do_wait_suspend); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 311, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyDict_Copy(__pyx_v_kwargs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 311, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_v_args, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 311, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":310 + * self._args[0].set_suspend(*args, **kwargs) + * + * def do_wait_suspend(self, *args, **kwargs): # <<<<<<<<<<<<<< + * self._args[0].do_wait_suspend(*args, **kwargs) + * + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.do_wait_suspend", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":314 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * def trace_exception(self, frame, str event, arg): # <<<<<<<<<<<<<< + * cdef bint should_stop; + * cdef tuple exc_info; + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_7trace_exception(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_7trace_exception(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_event = 0; + PyObject *__pyx_v_arg = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("trace_exception (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_frame,&__pyx_n_s_event,&__pyx_n_s_arg,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_exception", 1, 3, 3, 1); __PYX_ERR(0, 314, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arg)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_exception", 1, 3, 3, 2); __PYX_ERR(0, 314, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "trace_exception") < 0)) __PYX_ERR(0, 314, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_frame = values[0]; + __pyx_v_event = ((PyObject*)values[1]); + __pyx_v_arg = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("trace_exception", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 314, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_event), (&PyString_Type), 1, "event", 1))) __PYX_ERR(0, 314, __pyx_L1_error) + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_6trace_exception(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self), __pyx_v_frame, __pyx_v_event, __pyx_v_arg); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_6trace_exception(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + int __pyx_v_should_stop; + PyObject *__pyx_v_exc_info = 0; + PyObject *__pyx_v_frame_skips_cache = NULL; + PyObject *__pyx_v_frame_cache_key = NULL; + PyObject *__pyx_v_custom_key = NULL; + PyObject *__pyx_v_container_obj = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *(*__pyx_t_7)(PyObject *); + int __pyx_t_8; + int __pyx_t_9; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("trace_exception", 0); + __Pyx_INCREF(__pyx_v_frame); + + /* "_pydevd_bundle/pydevd_cython.pyx":320 + * # def trace_exception(self, frame, event, arg): + * # ENDIF + * if event == 'exception': # <<<<<<<<<<<<<< + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * + */ + __pyx_t_1 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_exception, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 320, __pyx_L1_error) + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":321 + * # ENDIF + * if event == 'exception': + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) # <<<<<<<<<<<<<< + * + * if should_stop: + */ + __pyx_t_3 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_should_stop_on_exception(__pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 321, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { + PyObject* sequence = __pyx_t_3; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 321, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_4 = PyList_GET_ITEM(sequence, 0); + __pyx_t_5 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + #else + __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 321, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 321, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + #endif + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_6 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 321, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_7 = Py_TYPE(__pyx_t_6)->tp_iternext; + index = 0; __pyx_t_4 = __pyx_t_7(__pyx_t_6); if (unlikely(!__pyx_t_4)) goto __pyx_L4_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + index = 1; __pyx_t_5 = __pyx_t_7(__pyx_t_6); if (unlikely(!__pyx_t_5)) goto __pyx_L4_unpacking_failed; + __Pyx_GOTREF(__pyx_t_5); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_6), 2) < 0) __PYX_ERR(0, 321, __pyx_L1_error) + __pyx_t_7 = NULL; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L5_unpacking_done; + __pyx_L4_unpacking_failed:; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_7 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 321, __pyx_L1_error) + __pyx_L5_unpacking_done:; + } + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 321, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_should_stop = __pyx_t_2; + __Pyx_DECREF_SET(__pyx_v_frame, __pyx_t_5); + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":323 + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * + * if should_stop: # <<<<<<<<<<<<<< + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch + */ + __pyx_t_2 = (__pyx_v_should_stop != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":324 + * + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_EXCEPTION_TYPE_HANDLED); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 324, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (!(likely(PyString_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 324, __pyx_L1_error) + __pyx_t_5 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_handle_exception(__pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg, ((PyObject*)__pyx_t_3)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 324, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 324, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":325 + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * elif event == 'return': + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 325, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":324 + * + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":323 + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * + * if should_stop: # <<<<<<<<<<<<<< + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":320 + * # def trace_exception(self, frame, event, arg): + * # ENDIF + * if event == 'exception': # <<<<<<<<<<<<<< + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * + */ + goto __pyx_L3; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":327 + * return self.trace_dispatch + * + * elif event == 'return': # <<<<<<<<<<<<<< + * exc_info = self.exc_info + * if exc_info and arg is None: + */ + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_return, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 327, __pyx_L1_error) + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":328 + * + * elif event == 'return': + * exc_info = self.exc_info # <<<<<<<<<<<<<< + * if exc_info and arg is None: + * frame_skips_cache, frame_cache_key = self._args[4], self._args[5] + */ + if (!(likely(PyTuple_CheckExact(__pyx_v_self->exc_info))||((__pyx_v_self->exc_info) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v_self->exc_info)->tp_name), 0))) __PYX_ERR(0, 328, __pyx_L1_error) + __pyx_t_5 = __pyx_v_self->exc_info; + __Pyx_INCREF(__pyx_t_5); + __pyx_v_exc_info = ((PyObject*)__pyx_t_5); + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":329 + * elif event == 'return': + * exc_info = self.exc_info + * if exc_info and arg is None: # <<<<<<<<<<<<<< + * frame_skips_cache, frame_cache_key = self._args[4], self._args[5] + * custom_key = (frame_cache_key, 'try_exc_info') + */ + __pyx_t_2 = (__pyx_v_exc_info != Py_None)&&(PyTuple_GET_SIZE(__pyx_v_exc_info) != 0); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L9_bool_binop_done; + } + __pyx_t_2 = (__pyx_v_arg == Py_None); + __pyx_t_8 = (__pyx_t_2 != 0); + __pyx_t_1 = __pyx_t_8; + __pyx_L9_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":330 + * exc_info = self.exc_info + * if exc_info and arg is None: + * frame_skips_cache, frame_cache_key = self._args[4], self._args[5] # <<<<<<<<<<<<<< + * custom_key = (frame_cache_key, 'try_exc_info') + * container_obj = frame_skips_cache.get(custom_key) + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 330, __pyx_L1_error) + } + __pyx_t_5 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 4, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 330, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 330, __pyx_L1_error) + } + __pyx_t_3 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 5, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 330, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_v_frame_skips_cache = __pyx_t_5; + __pyx_t_5 = 0; + __pyx_v_frame_cache_key = __pyx_t_3; + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":331 + * if exc_info and arg is None: + * frame_skips_cache, frame_cache_key = self._args[4], self._args[5] + * custom_key = (frame_cache_key, 'try_exc_info') # <<<<<<<<<<<<<< + * container_obj = frame_skips_cache.get(custom_key) + * if container_obj is None: + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 331, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_frame_cache_key); + __Pyx_GIVEREF(__pyx_v_frame_cache_key); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_frame_cache_key); + __Pyx_INCREF(__pyx_n_s_try_exc_info); + __Pyx_GIVEREF(__pyx_n_s_try_exc_info); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_n_s_try_exc_info); + __pyx_v_custom_key = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":332 + * frame_skips_cache, frame_cache_key = self._args[4], self._args[5] + * custom_key = (frame_cache_key, 'try_exc_info') + * container_obj = frame_skips_cache.get(custom_key) # <<<<<<<<<<<<<< + * if container_obj is None: + * container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame_skips_cache, __pyx_n_s_get); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 332, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_4, __pyx_v_custom_key) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_custom_key); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 332, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_v_container_obj = __pyx_t_3; + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":333 + * custom_key = (frame_cache_key, 'try_exc_info') + * container_obj = frame_skips_cache.get(custom_key) + * if container_obj is None: # <<<<<<<<<<<<<< + * container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + * if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ + */ + __pyx_t_1 = (__pyx_v_container_obj == Py_None); + __pyx_t_8 = (__pyx_t_1 != 0); + if (__pyx_t_8) { + + /* "_pydevd_bundle/pydevd_cython.pyx":334 + * container_obj = frame_skips_cache.get(custom_key) + * if container_obj is None: + * container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() # <<<<<<<<<<<<<< + * if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ + * self.handle_user_exception(frame): + */ + __pyx_t_3 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 334, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_3); + __Pyx_DECREF_SET(__pyx_v_container_obj, __pyx_t_3); + if (unlikely(PyObject_SetItem(__pyx_v_frame_skips_cache, __pyx_v_custom_key, __pyx_t_3) < 0)) __PYX_ERR(0, 334, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":333 + * custom_key = (frame_cache_key, 'try_exc_info') + * container_obj = frame_skips_cache.get(custom_key) + * if container_obj is None: # <<<<<<<<<<<<<< + * container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + * if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":335 + * if container_obj is None: + * container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + * if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ # <<<<<<<<<<<<<< + * self.handle_user_exception(frame): + * return self.trace_dispatch + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 335, __pyx_L1_error) + } + __pyx_t_3 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 335, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (unlikely(__pyx_v_exc_info == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 335, __pyx_L1_error) + } + __pyx_t_5 = __Pyx_GetItemInt_Tuple(__pyx_v_exc_info, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 335, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_9 = __Pyx_PyInt_As_int(__pyx_t_5); if (unlikely((__pyx_t_9 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 335, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(__pyx_v_exc_info == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 335, __pyx_L1_error) + } + __pyx_t_5 = __Pyx_GetItemInt_Tuple(__pyx_v_exc_info, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 335, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (!(likely(PySet_CheckExact(__pyx_t_5))||((__pyx_t_5) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "set", Py_TYPE(__pyx_t_5)->tp_name), 0))) __PYX_ERR(0, 335, __pyx_L1_error) + __pyx_t_4 = __pyx_f_14_pydevd_bundle_13pydevd_cython_is_unhandled_exception(__pyx_v_container_obj, __pyx_t_3, __pyx_v_frame, __pyx_t_9, ((PyObject*)__pyx_t_5)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 335, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 335, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_1) { + } else { + __pyx_t_8 = __pyx_t_1; + goto __pyx_L13_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":336 + * container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + * if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ + * self.handle_user_exception(frame): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_handle_user_exception); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 336, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_4 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_3, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 336, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 336, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_8 = __pyx_t_1; + __pyx_L13_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":335 + * if container_obj is None: + * container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + * if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ # <<<<<<<<<<<<<< + * self.handle_user_exception(frame): + * return self.trace_dispatch + */ + if (__pyx_t_8) { + + /* "_pydevd_bundle/pydevd_cython.pyx":337 + * if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ + * self.handle_user_exception(frame): + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * return self.trace_exception + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":335 + * if container_obj is None: + * container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + * if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ # <<<<<<<<<<<<<< + * self.handle_user_exception(frame): + * return self.trace_dispatch + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":329 + * elif event == 'return': + * exc_info = self.exc_info + * if exc_info and arg is None: # <<<<<<<<<<<<<< + * frame_skips_cache, frame_cache_key = self._args[4], self._args[5] + * custom_key = (frame_cache_key, 'try_exc_info') + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":327 + * return self.trace_dispatch + * + * elif event == 'return': # <<<<<<<<<<<<<< + * exc_info = self.exc_info + * if exc_info and arg is None: + */ + } + __pyx_L3:; + + /* "_pydevd_bundle/pydevd_cython.pyx":339 + * return self.trace_dispatch + * + * return self.trace_exception # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_exception); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 339, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":314 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * def trace_exception(self, frame, str event, arg): # <<<<<<<<<<<<<< + * cdef bint should_stop; + * cdef tuple exc_info; + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_exc_info); + __Pyx_XDECREF(__pyx_v_frame_skips_cache); + __Pyx_XDECREF(__pyx_v_frame_cache_key); + __Pyx_XDECREF(__pyx_v_custom_key); + __Pyx_XDECREF(__pyx_v_container_obj); + __Pyx_XDECREF(__pyx_v_frame); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":342 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _should_stop_on_exception(self, frame, str event, arg): # <<<<<<<<<<<<<< + * cdef PyDBAdditionalThreadInfo info; + * cdef bint should_stop; + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__should_stop_on_exception(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, CYTHON_UNUSED PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_info = 0; + int __pyx_v_should_stop; + int __pyx_v_was_just_raised; + PyObject *__pyx_v_check_excs = 0; + PyObject *__pyx_v_main_debugger = NULL; + PyObject *__pyx_v_exception = NULL; + PyObject *__pyx_v_value = NULL; + PyObject *__pyx_v_trace = NULL; + PyObject *__pyx_v_exception_breakpoint = NULL; + PyObject *__pyx_v_result = NULL; + PyObject *__pyx_v_exc_break_user = NULL; + PyObject *__pyx_v_exc_break_caught = NULL; + PyObject *__pyx_v_exc_break = NULL; + PyObject *__pyx_v_is_user_uncaught = NULL; + PyObject *__pyx_v_exc_info = NULL; + PyObject *__pyx_v_lines = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *(*__pyx_t_6)(PyObject *); + int __pyx_t_7; + int __pyx_t_8; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + int __pyx_t_12; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + int __pyx_t_15; + Py_ssize_t __pyx_t_16; + PyObject *__pyx_t_17 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_should_stop_on_exception", 0); + __Pyx_INCREF(__pyx_v_frame); + + /* "_pydevd_bundle/pydevd_cython.pyx":352 + * + * # main_debugger, _filename, info, _thread = self._args + * main_debugger = self._args[0] # <<<<<<<<<<<<<< + * info = self._args[2] + * should_stop = False + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 352, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 352, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_main_debugger = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":353 + * # main_debugger, _filename, info, _thread = self._args + * main_debugger = self._args[0] + * info = self._args[2] # <<<<<<<<<<<<<< + * should_stop = False + * + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 353, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 353, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo))))) __PYX_ERR(0, 353, __pyx_L1_error) + __pyx_v_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":354 + * main_debugger = self._args[0] + * info = self._args[2] + * should_stop = False # <<<<<<<<<<<<<< + * + * # 2 = 2 + */ + __pyx_v_should_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":357 + * + * # 2 = 2 + * if info.pydev_state != 2: # and breakpoint is not None: # <<<<<<<<<<<<<< + * exception, value, trace = arg + * + */ + __pyx_t_2 = ((__pyx_v_info->pydev_state != 2) != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":358 + * # 2 = 2 + * if info.pydev_state != 2: # and breakpoint is not None: + * exception, value, trace = arg # <<<<<<<<<<<<<< + * + * if trace is not None and hasattr(trace, 'tb_next'): + */ + if ((likely(PyTuple_CheckExact(__pyx_v_arg))) || (PyList_CheckExact(__pyx_v_arg))) { + PyObject* sequence = __pyx_v_arg; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 3)) { + if (size > 3) __Pyx_RaiseTooManyValuesError(3); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 358, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); + } else { + __pyx_t_1 = PyList_GET_ITEM(sequence, 0); + __pyx_t_3 = PyList_GET_ITEM(sequence, 1); + __pyx_t_4 = PyList_GET_ITEM(sequence, 2); + } + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + #else + __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 358, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 358, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 358, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_5 = PyObject_GetIter(__pyx_v_arg); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 358, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = Py_TYPE(__pyx_t_5)->tp_iternext; + index = 0; __pyx_t_1 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_1)) goto __pyx_L4_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + index = 1; __pyx_t_3 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L4_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 2; __pyx_t_4 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L4_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_5), 3) < 0) __PYX_ERR(0, 358, __pyx_L1_error) + __pyx_t_6 = NULL; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L5_unpacking_done; + __pyx_L4_unpacking_failed:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 358, __pyx_L1_error) + __pyx_L5_unpacking_done:; + } + __pyx_v_exception = __pyx_t_1; + __pyx_t_1 = 0; + __pyx_v_value = __pyx_t_3; + __pyx_t_3 = 0; + __pyx_v_trace = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":360 + * exception, value, trace = arg + * + * if trace is not None and hasattr(trace, 'tb_next'): # <<<<<<<<<<<<<< + * # on jython trace is None on the first event and it may not have a tb_next. + * + */ + __pyx_t_7 = (__pyx_v_trace != Py_None); + __pyx_t_8 = (__pyx_t_7 != 0); + if (__pyx_t_8) { + } else { + __pyx_t_2 = __pyx_t_8; + goto __pyx_L7_bool_binop_done; + } + __pyx_t_8 = __Pyx_HasAttr(__pyx_v_trace, __pyx_n_s_tb_next); if (unlikely(__pyx_t_8 == ((int)-1))) __PYX_ERR(0, 360, __pyx_L1_error) + __pyx_t_7 = (__pyx_t_8 != 0); + __pyx_t_2 = __pyx_t_7; + __pyx_L7_bool_binop_done:; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":363 + * # on jython trace is None on the first event and it may not have a tb_next. + * + * should_stop = False # <<<<<<<<<<<<<< + * exception_breakpoint = None + * try: + */ + __pyx_v_should_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":364 + * + * should_stop = False + * exception_breakpoint = None # <<<<<<<<<<<<<< + * try: + * if main_debugger.plugin is not None: + */ + __Pyx_INCREF(Py_None); + __pyx_v_exception_breakpoint = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":365 + * should_stop = False + * exception_breakpoint = None + * try: # <<<<<<<<<<<<<< + * if main_debugger.plugin is not None: + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_9); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_11); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":366 + * exception_breakpoint = None + * try: + * if main_debugger.plugin is not None: # <<<<<<<<<<<<<< + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + * if result: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_plugin); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 366, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = (__pyx_t_4 != Py_None); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_7 = (__pyx_t_2 != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":367 + * try: + * if main_debugger.plugin is not None: + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) # <<<<<<<<<<<<<< + * if result: + * should_stop, frame = result + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_plugin); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 367, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_exception_break); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 367, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[6] = {__pyx_t_3, __pyx_v_main_debugger, ((PyObject *)__pyx_v_self), __pyx_v_frame, __pyx_v_self->_args, __pyx_v_arg}; + __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 5+__pyx_t_12); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 367, __pyx_L9_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[6] = {__pyx_t_3, __pyx_v_main_debugger, ((PyObject *)__pyx_v_self), __pyx_v_frame, __pyx_v_self->_args, __pyx_v_arg}; + __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 5+__pyx_t_12); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 367, __pyx_L9_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + { + __pyx_t_5 = PyTuple_New(5+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 367, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_5); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_12, __pyx_v_main_debugger); + __Pyx_INCREF(((PyObject *)__pyx_v_self)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); + PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_12, ((PyObject *)__pyx_v_self)); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_5, 2+__pyx_t_12, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_5, 3+__pyx_t_12, __pyx_v_self->_args); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_5, 4+__pyx_t_12, __pyx_v_arg); + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 367, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":368 + * if main_debugger.plugin is not None: + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + * if result: # <<<<<<<<<<<<<< + * should_stop, frame = result + * except: + */ + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_v_result); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 368, __pyx_L9_error) + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":369 + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + * if result: + * should_stop, frame = result # <<<<<<<<<<<<<< + * except: + * pydev_log.exception() + */ + if ((likely(PyTuple_CheckExact(__pyx_v_result))) || (PyList_CheckExact(__pyx_v_result))) { + PyObject* sequence = __pyx_v_result; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 369, __pyx_L9_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_4 = PyList_GET_ITEM(sequence, 0); + __pyx_t_1 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_1); + #else + __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 369, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 369, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_5 = PyObject_GetIter(__pyx_v_result); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 369, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = Py_TYPE(__pyx_t_5)->tp_iternext; + index = 0; __pyx_t_4 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L17_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + index = 1; __pyx_t_1 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_1)) goto __pyx_L17_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_5), 2) < 0) __PYX_ERR(0, 369, __pyx_L9_error) + __pyx_t_6 = NULL; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L18_unpacking_done; + __pyx_L17_unpacking_failed:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 369, __pyx_L9_error) + __pyx_L18_unpacking_done:; + } + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 369, __pyx_L9_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_should_stop = __pyx_t_7; + __Pyx_DECREF_SET(__pyx_v_frame, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":368 + * if main_debugger.plugin is not None: + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + * if result: # <<<<<<<<<<<<<< + * should_stop, frame = result + * except: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":366 + * exception_breakpoint = None + * try: + * if main_debugger.plugin is not None: # <<<<<<<<<<<<<< + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + * if result: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":365 + * should_stop = False + * exception_breakpoint = None + * try: # <<<<<<<<<<<<<< + * if main_debugger.plugin is not None: + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + */ + } + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + goto __pyx_L14_try_end; + __pyx_L9_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":370 + * if result: + * should_stop, frame = result + * except: # <<<<<<<<<<<<<< + * pydev_log.exception() + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._should_stop_on_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_4, &__pyx_t_5) < 0) __PYX_ERR(0, 370, __pyx_L11_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_5); + + /* "_pydevd_bundle/pydevd_cython.pyx":371 + * should_stop, frame = result + * except: + * pydev_log.exception() # <<<<<<<<<<<<<< + * + * if not should_stop: + */ + __Pyx_GetModuleGlobalName(__pyx_t_13, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 371, __pyx_L11_except_error) + __Pyx_GOTREF(__pyx_t_13); + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_n_s_exception); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 371, __pyx_L11_except_error) + __Pyx_GOTREF(__pyx_t_14); + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + __pyx_t_13 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_14))) { + __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_14); + if (likely(__pyx_t_13)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_14); + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_14, function); + } + } + __pyx_t_3 = (__pyx_t_13) ? __Pyx_PyObject_CallOneArg(__pyx_t_14, __pyx_t_13) : __Pyx_PyObject_CallNoArg(__pyx_t_14); + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 371, __pyx_L11_except_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L10_exception_handled; + } + __pyx_L11_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":365 + * should_stop = False + * exception_breakpoint = None + * try: # <<<<<<<<<<<<<< + * if main_debugger.plugin is not None: + * result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + */ + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_ExceptionReset(__pyx_t_9, __pyx_t_10, __pyx_t_11); + goto __pyx_L1_error; + __pyx_L10_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_ExceptionReset(__pyx_t_9, __pyx_t_10, __pyx_t_11); + __pyx_L14_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":373 + * pydev_log.exception() + * + * if not should_stop: # <<<<<<<<<<<<<< + * # Apply checks that don't need the exception breakpoint (where we shouldn't ever stop). + * if exception == SystemExit and main_debugger.ignore_system_exit_code(value): + */ + __pyx_t_7 = ((!(__pyx_v_should_stop != 0)) != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":375 + * if not should_stop: + * # Apply checks that don't need the exception breakpoint (where we shouldn't ever stop). + * if exception == SystemExit and main_debugger.ignore_system_exit_code(value): # <<<<<<<<<<<<<< + * pass + * + */ + __pyx_t_5 = PyObject_RichCompare(__pyx_v_exception, __pyx_builtin_SystemExit, Py_EQ); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 375, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 375, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_2) { + } else { + __pyx_t_7 = __pyx_t_2; + goto __pyx_L23_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_ignore_system_exit_code); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 375, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_5 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_1, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_value); + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 375, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 375, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_7 = __pyx_t_2; + __pyx_L23_bool_binop_done:; + if (__pyx_t_7) { + goto __pyx_L22; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":378 + * pass + * + * elif exception in (GeneratorExit, StopIteration, StopAsyncIteration): # <<<<<<<<<<<<<< + * # These exceptions are control-flow related (they work as a generator + * # pause), so, we shouldn't stop on them. + */ + __Pyx_INCREF(__pyx_v_exception); + __pyx_t_5 = __pyx_v_exception; + __pyx_t_4 = PyObject_RichCompare(__pyx_t_5, __pyx_builtin_GeneratorExit, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 378, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 378, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (!__pyx_t_2) { + } else { + __pyx_t_7 = __pyx_t_2; + goto __pyx_L25_bool_binop_done; + } + __pyx_t_4 = PyObject_RichCompare(__pyx_t_5, __pyx_builtin_StopIteration, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 378, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 378, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (!__pyx_t_2) { + } else { + __pyx_t_7 = __pyx_t_2; + goto __pyx_L25_bool_binop_done; + } + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_StopAsyncIteration); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 378, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyObject_RichCompare(__pyx_t_5, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 378, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 378, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_7 = __pyx_t_2; + __pyx_L25_bool_binop_done:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_2 = (__pyx_t_7 != 0); + if (__pyx_t_2) { + goto __pyx_L22; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":383 + * pass + * + * elif ignore_exception_trace(trace): # <<<<<<<<<<<<<< + * pass + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_ignore_exception_trace); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 383, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_5 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_4, __pyx_v_trace) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_trace); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 383, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 383, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_2) { + goto __pyx_L22; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":387 + * + * else: + * was_just_raised = trace.tb_next is None # <<<<<<<<<<<<<< + * + * # It was not handled by any plugin, lets check exception breakpoints. + */ + /*else*/ { + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_trace, __pyx_n_s_tb_next); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 387, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = (__pyx_t_5 == Py_None); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_v_was_just_raised = __pyx_t_2; + + /* "_pydevd_bundle/pydevd_cython.pyx":390 + * + * # It was not handled by any plugin, lets check exception breakpoints. + * check_excs = [] # <<<<<<<<<<<<<< + * + * # Note: check user unhandled before regular exceptions. + */ + __pyx_t_5 = PyList_New(0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 390, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_check_excs = ((PyObject*)__pyx_t_5); + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":393 + * + * # Note: check user unhandled before regular exceptions. + * exc_break_user = main_debugger.get_exception_breakpoint( # <<<<<<<<<<<<<< + * exception, main_debugger.break_on_user_uncaught_exceptions) + * if exc_break_user is not None: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_get_exception_breakpoint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 393, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + + /* "_pydevd_bundle/pydevd_cython.pyx":394 + * # Note: check user unhandled before regular exceptions. + * exc_break_user = main_debugger.get_exception_breakpoint( + * exception, main_debugger.break_on_user_uncaught_exceptions) # <<<<<<<<<<<<<< + * if exc_break_user is not None: + * check_excs.append((exc_break_user, True)) + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_break_on_user_uncaught_exception); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 394, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_exception, __pyx_t_4}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 2+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 393, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_exception, __pyx_t_4}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 2+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 393, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else + #endif + { + __pyx_t_14 = PyTuple_New(2+__pyx_t_12); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 393, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_exception); + __Pyx_GIVEREF(__pyx_v_exception); + PyTuple_SET_ITEM(__pyx_t_14, 0+__pyx_t_12, __pyx_v_exception); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_14, 1+__pyx_t_12, __pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_14, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 393, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_exc_break_user = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":395 + * exc_break_user = main_debugger.get_exception_breakpoint( + * exception, main_debugger.break_on_user_uncaught_exceptions) + * if exc_break_user is not None: # <<<<<<<<<<<<<< + * check_excs.append((exc_break_user, True)) + * + */ + __pyx_t_2 = (__pyx_v_exc_break_user != Py_None); + __pyx_t_7 = (__pyx_t_2 != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":396 + * exception, main_debugger.break_on_user_uncaught_exceptions) + * if exc_break_user is not None: + * check_excs.append((exc_break_user, True)) # <<<<<<<<<<<<<< + * + * exc_break_caught = main_debugger.get_exception_breakpoint( + */ + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 396, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_v_exc_break_user); + __Pyx_GIVEREF(__pyx_v_exc_break_user); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_exc_break_user); + __Pyx_INCREF(Py_True); + __Pyx_GIVEREF(Py_True); + PyTuple_SET_ITEM(__pyx_t_5, 1, Py_True); + __pyx_t_15 = __Pyx_PyList_Append(__pyx_v_check_excs, __pyx_t_5); if (unlikely(__pyx_t_15 == ((int)-1))) __PYX_ERR(0, 396, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":395 + * exc_break_user = main_debugger.get_exception_breakpoint( + * exception, main_debugger.break_on_user_uncaught_exceptions) + * if exc_break_user is not None: # <<<<<<<<<<<<<< + * check_excs.append((exc_break_user, True)) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":398 + * check_excs.append((exc_break_user, True)) + * + * exc_break_caught = main_debugger.get_exception_breakpoint( # <<<<<<<<<<<<<< + * exception, main_debugger.break_on_caught_exceptions) + * if exc_break_caught is not None: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_get_exception_breakpoint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 398, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + + /* "_pydevd_bundle/pydevd_cython.pyx":399 + * + * exc_break_caught = main_debugger.get_exception_breakpoint( + * exception, main_debugger.break_on_caught_exceptions) # <<<<<<<<<<<<<< + * if exc_break_caught is not None: + * check_excs.append((exc_break_caught, False)) + */ + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_break_on_caught_exceptions); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 399, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __pyx_t_4 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_exception, __pyx_t_14}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 2+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 398, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_exception, __pyx_t_14}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 2+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 398, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + } else + #endif + { + __pyx_t_3 = PyTuple_New(2+__pyx_t_12); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 398, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); __pyx_t_4 = NULL; + } + __Pyx_INCREF(__pyx_v_exception); + __Pyx_GIVEREF(__pyx_v_exception); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_12, __pyx_v_exception); + __Pyx_GIVEREF(__pyx_t_14); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_12, __pyx_t_14); + __pyx_t_14 = 0; + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 398, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_exc_break_caught = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":400 + * exc_break_caught = main_debugger.get_exception_breakpoint( + * exception, main_debugger.break_on_caught_exceptions) + * if exc_break_caught is not None: # <<<<<<<<<<<<<< + * check_excs.append((exc_break_caught, False)) + * + */ + __pyx_t_7 = (__pyx_v_exc_break_caught != Py_None); + __pyx_t_2 = (__pyx_t_7 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":401 + * exception, main_debugger.break_on_caught_exceptions) + * if exc_break_caught is not None: + * check_excs.append((exc_break_caught, False)) # <<<<<<<<<<<<<< + * + * for exc_break, is_user_uncaught in check_excs: + */ + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 401, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_v_exc_break_caught); + __Pyx_GIVEREF(__pyx_v_exc_break_caught); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_exc_break_caught); + __Pyx_INCREF(Py_False); + __Pyx_GIVEREF(Py_False); + PyTuple_SET_ITEM(__pyx_t_5, 1, Py_False); + __pyx_t_15 = __Pyx_PyList_Append(__pyx_v_check_excs, __pyx_t_5); if (unlikely(__pyx_t_15 == ((int)-1))) __PYX_ERR(0, 401, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":400 + * exc_break_caught = main_debugger.get_exception_breakpoint( + * exception, main_debugger.break_on_caught_exceptions) + * if exc_break_caught is not None: # <<<<<<<<<<<<<< + * check_excs.append((exc_break_caught, False)) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":403 + * check_excs.append((exc_break_caught, False)) + * + * for exc_break, is_user_uncaught in check_excs: # <<<<<<<<<<<<<< + * # Initially mark that it should stop and then go into exclusions. + * should_stop = True + */ + __pyx_t_5 = __pyx_v_check_excs; __Pyx_INCREF(__pyx_t_5); __pyx_t_16 = 0; + for (;;) { + if (__pyx_t_16 >= PyList_GET_SIZE(__pyx_t_5)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_1 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_16); __Pyx_INCREF(__pyx_t_1); __pyx_t_16++; if (unlikely(0 < 0)) __PYX_ERR(0, 403, __pyx_L1_error) + #else + __pyx_t_1 = PySequence_ITEM(__pyx_t_5, __pyx_t_16); __pyx_t_16++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 403, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 403, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_14 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_14 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_14); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 403, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_14 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 403, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 403, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; + index = 0; __pyx_t_3 = __pyx_t_6(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L32_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 1; __pyx_t_14 = __pyx_t_6(__pyx_t_4); if (unlikely(!__pyx_t_14)) goto __pyx_L32_unpacking_failed; + __Pyx_GOTREF(__pyx_t_14); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_4), 2) < 0) __PYX_ERR(0, 403, __pyx_L1_error) + __pyx_t_6 = NULL; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + goto __pyx_L33_unpacking_done; + __pyx_L32_unpacking_failed:; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 403, __pyx_L1_error) + __pyx_L33_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_exc_break, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_is_user_uncaught, __pyx_t_14); + __pyx_t_14 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":405 + * for exc_break, is_user_uncaught in check_excs: + * # Initially mark that it should stop and then go into exclusions. + * should_stop = True # <<<<<<<<<<<<<< + * + * if main_debugger.exclude_exception_by_filter(exc_break, trace): + */ + __pyx_v_should_stop = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":407 + * should_stop = True + * + * if main_debugger.exclude_exception_by_filter(exc_break, trace): # <<<<<<<<<<<<<< + * pydev_log.debug("Ignore exception %s in library %s -- (%s)" % (exception, frame.f_code.co_filename, frame.f_code.co_name)) + * should_stop = False + */ + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_exclude_exception_by_filter); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 407, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __pyx_t_3 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_14))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_14); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_14); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_14, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_14)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_exc_break, __pyx_v_trace}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_14, __pyx_temp+1-__pyx_t_12, 2+__pyx_t_12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 407, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_14)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_exc_break, __pyx_v_trace}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_14, __pyx_temp+1-__pyx_t_12, 2+__pyx_t_12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 407, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_4 = PyTuple_New(2+__pyx_t_12); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 407, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_exc_break); + __Pyx_GIVEREF(__pyx_v_exc_break); + PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_12, __pyx_v_exc_break); + __Pyx_INCREF(__pyx_v_trace); + __Pyx_GIVEREF(__pyx_v_trace); + PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_12, __pyx_v_trace); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_14, __pyx_t_4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 407, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 407, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":408 + * + * if main_debugger.exclude_exception_by_filter(exc_break, trace): + * pydev_log.debug("Ignore exception %s in library %s -- (%s)" % (exception, frame.f_code.co_filename, frame.f_code.co_name)) # <<<<<<<<<<<<<< + * should_stop = False + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_n_s_debug); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_n_s_co_name); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_14 = PyTuple_New(3); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __Pyx_INCREF(__pyx_v_exception); + __Pyx_GIVEREF(__pyx_v_exception); + PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_v_exception); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_14, 1, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_13); + PyTuple_SET_ITEM(__pyx_t_14, 2, __pyx_t_13); + __pyx_t_3 = 0; + __pyx_t_13 = 0; + __pyx_t_13 = __Pyx_PyString_Format(__pyx_kp_s_Ignore_exception_s_in_library_s, __pyx_t_14); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_14 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_14)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_14); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_1 = (__pyx_t_14) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_14, __pyx_t_13) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_13); + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 408, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":409 + * if main_debugger.exclude_exception_by_filter(exc_break, trace): + * pydev_log.debug("Ignore exception %s in library %s -- (%s)" % (exception, frame.f_code.co_filename, frame.f_code.co_name)) + * should_stop = False # <<<<<<<<<<<<<< + * + * elif exc_break.condition is not None and \ + */ + __pyx_v_should_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":407 + * should_stop = True + * + * if main_debugger.exclude_exception_by_filter(exc_break, trace): # <<<<<<<<<<<<<< + * pydev_log.debug("Ignore exception %s in library %s -- (%s)" % (exception, frame.f_code.co_filename, frame.f_code.co_name)) + * should_stop = False + */ + goto __pyx_L34; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":411 + * should_stop = False + * + * elif exc_break.condition is not None and \ # <<<<<<<<<<<<<< + * not main_debugger.handle_breakpoint_condition(info, exc_break, frame): + * should_stop = False + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_exc_break, __pyx_n_s_condition); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 411, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = (__pyx_t_1 != Py_None); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_8 = (__pyx_t_7 != 0); + if (__pyx_t_8) { + } else { + __pyx_t_2 = __pyx_t_8; + goto __pyx_L35_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":412 + * + * elif exc_break.condition is not None and \ + * not main_debugger.handle_breakpoint_condition(info, exc_break, frame): # <<<<<<<<<<<<<< + * should_stop = False + * + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_handle_breakpoint_condition); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 412, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_13 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_13)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_13, ((PyObject *)__pyx_v_info), __pyx_v_exc_break, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_12, 3+__pyx_t_12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 412, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_13, ((PyObject *)__pyx_v_info), __pyx_v_exc_break, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_12, 3+__pyx_t_12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 412, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_14 = PyTuple_New(3+__pyx_t_12); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 412, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + if (__pyx_t_13) { + __Pyx_GIVEREF(__pyx_t_13); PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_t_13); __pyx_t_13 = NULL; + } + __Pyx_INCREF(((PyObject *)__pyx_v_info)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_info)); + PyTuple_SET_ITEM(__pyx_t_14, 0+__pyx_t_12, ((PyObject *)__pyx_v_info)); + __Pyx_INCREF(__pyx_v_exc_break); + __Pyx_GIVEREF(__pyx_v_exc_break); + PyTuple_SET_ITEM(__pyx_t_14, 1+__pyx_t_12, __pyx_v_exc_break); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_14, 2+__pyx_t_12, __pyx_v_frame); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_14, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 412, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_8 < 0)) __PYX_ERR(0, 412, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_7 = ((!__pyx_t_8) != 0); + __pyx_t_2 = __pyx_t_7; + __pyx_L35_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":411 + * should_stop = False + * + * elif exc_break.condition is not None and \ # <<<<<<<<<<<<<< + * not main_debugger.handle_breakpoint_condition(info, exc_break, frame): + * should_stop = False + */ + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":413 + * elif exc_break.condition is not None and \ + * not main_debugger.handle_breakpoint_condition(info, exc_break, frame): + * should_stop = False # <<<<<<<<<<<<<< + * + * elif is_user_uncaught: + */ + __pyx_v_should_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":411 + * should_stop = False + * + * elif exc_break.condition is not None and \ # <<<<<<<<<<<<<< + * not main_debugger.handle_breakpoint_condition(info, exc_break, frame): + * should_stop = False + */ + goto __pyx_L34; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":415 + * should_stop = False + * + * elif is_user_uncaught: # <<<<<<<<<<<<<< + * # Note: we don't stop here, we just collect the exc_info to use later on... + * should_stop = False + */ + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_is_user_uncaught); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 415, __pyx_L1_error) + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":417 + * elif is_user_uncaught: + * # Note: we don't stop here, we just collect the exc_info to use later on... + * should_stop = False # <<<<<<<<<<<<<< + * if not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) \ + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)): + */ + __pyx_v_should_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":418 + * # Note: we don't stop here, we just collect the exc_info to use later on... + * should_stop = False + * if not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) \ # <<<<<<<<<<<<<< + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)): + * # User uncaught means that we're currently in user code but the code + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 418, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 418, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 418, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_14 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_14)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_14); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_14, __pyx_v_frame, __pyx_t_13, Py_True}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_12, 3+__pyx_t_12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 418, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_14, __pyx_v_frame, __pyx_t_13, Py_True}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_12, 3+__pyx_t_12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 418, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + } else + #endif + { + __pyx_t_3 = PyTuple_New(3+__pyx_t_12); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 418, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_14) { + __Pyx_GIVEREF(__pyx_t_14); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_14); __pyx_t_14 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_12, __pyx_v_frame); + __Pyx_GIVEREF(__pyx_t_13); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_12, __pyx_t_13); + __Pyx_INCREF(Py_True); + __Pyx_GIVEREF(Py_True); + PyTuple_SET_ITEM(__pyx_t_3, 2+__pyx_t_12, Py_True); + __pyx_t_13 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 418, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 418, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_8 = ((!__pyx_t_7) != 0); + if (__pyx_t_8) { + } else { + __pyx_t_2 = __pyx_t_8; + goto __pyx_L38_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":419 + * should_stop = False + * if not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) \ + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)): # <<<<<<<<<<<<<< + * # User uncaught means that we're currently in user code but the code + * # up the stack is library code. + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = (__pyx_t_1 == Py_None); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_7 = (__pyx_t_8 != 0); + if (!__pyx_t_7) { + } else { + __pyx_t_2 = __pyx_t_7; + goto __pyx_L38_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_n_s_f_code); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_14 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_14)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_14); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_14, __pyx_t_3, __pyx_t_13, Py_True}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_12, 3+__pyx_t_12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_14, __pyx_t_3, __pyx_t_13, Py_True}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_12, 3+__pyx_t_12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + } else + #endif + { + __pyx_t_17 = PyTuple_New(3+__pyx_t_12); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + if (__pyx_t_14) { + __Pyx_GIVEREF(__pyx_t_14); PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_14); __pyx_t_14 = NULL; + } + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_17, 0+__pyx_t_12, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_13); + PyTuple_SET_ITEM(__pyx_t_17, 1+__pyx_t_12, __pyx_t_13); + __Pyx_INCREF(Py_True); + __Pyx_GIVEREF(Py_True); + PyTuple_SET_ITEM(__pyx_t_17, 2+__pyx_t_12, Py_True); + __pyx_t_3 = 0; + __pyx_t_13 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_17, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 419, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_2 = __pyx_t_7; + __pyx_L38_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":418 + * # Note: we don't stop here, we just collect the exc_info to use later on... + * should_stop = False + * if not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) \ # <<<<<<<<<<<<<< + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)): + * # User uncaught means that we're currently in user code but the code + */ + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":422 + * # User uncaught means that we're currently in user code but the code + * # up the stack is library code. + * exc_info = self.exc_info # <<<<<<<<<<<<<< + * if not exc_info: + * exc_info = (arg, frame.f_lineno, set([frame.f_lineno])) + */ + __pyx_t_1 = __pyx_v_self->exc_info; + __Pyx_INCREF(__pyx_t_1); + __Pyx_XDECREF_SET(__pyx_v_exc_info, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":423 + * # up the stack is library code. + * exc_info = self.exc_info + * if not exc_info: # <<<<<<<<<<<<<< + * exc_info = (arg, frame.f_lineno, set([frame.f_lineno])) + * else: + */ + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_exc_info); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 423, __pyx_L1_error) + __pyx_t_7 = ((!__pyx_t_2) != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":424 + * exc_info = self.exc_info + * if not exc_info: + * exc_info = (arg, frame.f_lineno, set([frame.f_lineno])) # <<<<<<<<<<<<<< + * else: + * lines = exc_info[2] + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 424, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 424, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_17 = PySet_New(0); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 424, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + if (PySet_Add(__pyx_t_17, __pyx_t_4) < 0) __PYX_ERR(0, 424, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 424, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_arg); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_17); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_17); + __pyx_t_1 = 0; + __pyx_t_17 = 0; + __Pyx_DECREF_SET(__pyx_v_exc_info, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":423 + * # up the stack is library code. + * exc_info = self.exc_info + * if not exc_info: # <<<<<<<<<<<<<< + * exc_info = (arg, frame.f_lineno, set([frame.f_lineno])) + * else: + */ + goto __pyx_L41; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":426 + * exc_info = (arg, frame.f_lineno, set([frame.f_lineno])) + * else: + * lines = exc_info[2] # <<<<<<<<<<<<<< + * lines.add(frame.f_lineno) + * exc_info = (arg, frame.f_lineno, lines) + */ + /*else*/ { + __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_exc_info, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 426, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF_SET(__pyx_v_lines, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":427 + * else: + * lines = exc_info[2] + * lines.add(frame.f_lineno) # <<<<<<<<<<<<<< + * exc_info = (arg, frame.f_lineno, lines) + * self.exc_info = exc_info + */ + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_v_lines, __pyx_n_s_add); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 427, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 427, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_13 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_17))) { + __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_17); + if (likely(__pyx_t_13)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_17); + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_17, function); + } + } + __pyx_t_4 = (__pyx_t_13) ? __Pyx_PyObject_Call2Args(__pyx_t_17, __pyx_t_13, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_17, __pyx_t_1); + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 427, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":428 + * lines = exc_info[2] + * lines.add(frame.f_lineno) + * exc_info = (arg, frame.f_lineno, lines) # <<<<<<<<<<<<<< + * self.exc_info = exc_info + * else: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 428, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_17 = PyTuple_New(3); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 428, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_v_arg); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_17, 1, __pyx_t_4); + __Pyx_INCREF(__pyx_v_lines); + __Pyx_GIVEREF(__pyx_v_lines); + PyTuple_SET_ITEM(__pyx_t_17, 2, __pyx_v_lines); + __pyx_t_4 = 0; + __Pyx_DECREF_SET(__pyx_v_exc_info, __pyx_t_17); + __pyx_t_17 = 0; + } + __pyx_L41:; + + /* "_pydevd_bundle/pydevd_cython.pyx":429 + * lines.add(frame.f_lineno) + * exc_info = (arg, frame.f_lineno, lines) + * self.exc_info = exc_info # <<<<<<<<<<<<<< + * else: + * # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + */ + __Pyx_INCREF(__pyx_v_exc_info); + __Pyx_GIVEREF(__pyx_v_exc_info); + __Pyx_GOTREF(__pyx_v_self->exc_info); + __Pyx_DECREF(__pyx_v_self->exc_info); + __pyx_v_self->exc_info = __pyx_v_exc_info; + + /* "_pydevd_bundle/pydevd_cython.pyx":418 + * # Note: we don't stop here, we just collect the exc_info to use later on... + * should_stop = False + * if not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) \ # <<<<<<<<<<<<<< + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)): + * # User uncaught means that we're currently in user code but the code + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":415 + * should_stop = False + * + * elif is_user_uncaught: # <<<<<<<<<<<<<< + * # Note: we don't stop here, we just collect the exc_info to use later on... + * should_stop = False + */ + goto __pyx_L34; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":432 + * else: + * # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + * if exc_break.notify_on_first_raise_only and main_debugger.skip_on_exceptions_thrown_in_same_context \ # <<<<<<<<<<<<<< + * and not was_just_raised and not just_raised(trace.tb_next): + * # In this case we never stop if it was just raised, so, to know if it was the first we + */ + /*else*/ { + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_v_exc_break, __pyx_n_s_notify_on_first_raise_only); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 432, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_17); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 432, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + if (__pyx_t_2) { + } else { + __pyx_t_7 = __pyx_t_2; + goto __pyx_L43_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":433 + * # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + * if exc_break.notify_on_first_raise_only and main_debugger.skip_on_exceptions_thrown_in_same_context \ + * and not was_just_raised and not just_raised(trace.tb_next): # <<<<<<<<<<<<<< + * # In this case we never stop if it was just raised, so, to know if it was the first we + * # need to check if we're in the 2nd method. + */ + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_skip_on_exceptions_thrown_in_sam); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 432, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + + /* "_pydevd_bundle/pydevd_cython.pyx":432 + * else: + * # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + * if exc_break.notify_on_first_raise_only and main_debugger.skip_on_exceptions_thrown_in_same_context \ # <<<<<<<<<<<<<< + * and not was_just_raised and not just_raised(trace.tb_next): + * # In this case we never stop if it was just raised, so, to know if it was the first we + */ + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_17); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 432, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + if (__pyx_t_2) { + } else { + __pyx_t_7 = __pyx_t_2; + goto __pyx_L43_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":433 + * # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + * if exc_break.notify_on_first_raise_only and main_debugger.skip_on_exceptions_thrown_in_same_context \ + * and not was_just_raised and not just_raised(trace.tb_next): # <<<<<<<<<<<<<< + * # In this case we never stop if it was just raised, so, to know if it was the first we + * # need to check if we're in the 2nd method. + */ + __pyx_t_2 = ((!(__pyx_v_was_just_raised != 0)) != 0); + if (__pyx_t_2) { + } else { + __pyx_t_7 = __pyx_t_2; + goto __pyx_L43_bool_binop_done; + } + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_just_raised); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 433, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trace, __pyx_n_s_tb_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 433, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_13 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_13)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_17 = (__pyx_t_13) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_13, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_1); + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 433, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_17); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 433, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __pyx_t_8 = ((!__pyx_t_2) != 0); + __pyx_t_7 = __pyx_t_8; + __pyx_L43_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":432 + * else: + * # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + * if exc_break.notify_on_first_raise_only and main_debugger.skip_on_exceptions_thrown_in_same_context \ # <<<<<<<<<<<<<< + * and not was_just_raised and not just_raised(trace.tb_next): + * # In this case we never stop if it was just raised, so, to know if it was the first we + */ + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":436 + * # In this case we never stop if it was just raised, so, to know if it was the first we + * # need to check if we're in the 2nd method. + * should_stop = False # I.e.: we stop only when we're at the caller of a method that throws an exception # <<<<<<<<<<<<<< + * + * elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ + */ + __pyx_v_should_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":432 + * else: + * # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + * if exc_break.notify_on_first_raise_only and main_debugger.skip_on_exceptions_thrown_in_same_context \ # <<<<<<<<<<<<<< + * and not was_just_raised and not just_raised(trace.tb_next): + * # In this case we never stop if it was just raised, so, to know if it was the first we + */ + goto __pyx_L42; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":438 + * should_stop = False # I.e.: we stop only when we're at the caller of a method that throws an exception + * + * elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ # <<<<<<<<<<<<<< + * and not was_just_raised: + * should_stop = False # I.e.: we stop only when it was just raised + */ + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_v_exc_break, __pyx_n_s_notify_on_first_raise_only); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 438, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_17); if (unlikely(__pyx_t_8 < 0)) __PYX_ERR(0, 438, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + if (__pyx_t_8) { + } else { + __pyx_t_7 = __pyx_t_8; + goto __pyx_L47_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":439 + * + * elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ + * and not was_just_raised: # <<<<<<<<<<<<<< + * should_stop = False # I.e.: we stop only when it was just raised + * + */ + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_skip_on_exceptions_thrown_in_sam); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 438, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + + /* "_pydevd_bundle/pydevd_cython.pyx":438 + * should_stop = False # I.e.: we stop only when we're at the caller of a method that throws an exception + * + * elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ # <<<<<<<<<<<<<< + * and not was_just_raised: + * should_stop = False # I.e.: we stop only when it was just raised + */ + __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_17); if (unlikely(__pyx_t_8 < 0)) __PYX_ERR(0, 438, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __pyx_t_2 = ((!__pyx_t_8) != 0); + if (__pyx_t_2) { + } else { + __pyx_t_7 = __pyx_t_2; + goto __pyx_L47_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":439 + * + * elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ + * and not was_just_raised: # <<<<<<<<<<<<<< + * should_stop = False # I.e.: we stop only when it was just raised + * + */ + __pyx_t_2 = ((!(__pyx_v_was_just_raised != 0)) != 0); + __pyx_t_7 = __pyx_t_2; + __pyx_L47_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":438 + * should_stop = False # I.e.: we stop only when we're at the caller of a method that throws an exception + * + * elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ # <<<<<<<<<<<<<< + * and not was_just_raised: + * should_stop = False # I.e.: we stop only when it was just raised + */ + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":440 + * elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ + * and not was_just_raised: + * should_stop = False # I.e.: we stop only when it was just raised # <<<<<<<<<<<<<< + * + * elif was_just_raised and main_debugger.skip_on_exceptions_thrown_in_same_context: + */ + __pyx_v_should_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":438 + * should_stop = False # I.e.: we stop only when we're at the caller of a method that throws an exception + * + * elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ # <<<<<<<<<<<<<< + * and not was_just_raised: + * should_stop = False # I.e.: we stop only when it was just raised + */ + goto __pyx_L42; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":442 + * should_stop = False # I.e.: we stop only when it was just raised + * + * elif was_just_raised and main_debugger.skip_on_exceptions_thrown_in_same_context: # <<<<<<<<<<<<<< + * # Option: Don't break if an exception is caught in the same function from which it is thrown + * should_stop = False + */ + __pyx_t_2 = (__pyx_v_was_just_raised != 0); + if (__pyx_t_2) { + } else { + __pyx_t_7 = __pyx_t_2; + goto __pyx_L50_bool_binop_done; + } + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_skip_on_exceptions_thrown_in_sam); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 442, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_17); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 442, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __pyx_t_7 = __pyx_t_2; + __pyx_L50_bool_binop_done:; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":444 + * elif was_just_raised and main_debugger.skip_on_exceptions_thrown_in_same_context: + * # Option: Don't break if an exception is caught in the same function from which it is thrown + * should_stop = False # <<<<<<<<<<<<<< + * + * if should_stop: + */ + __pyx_v_should_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":442 + * should_stop = False # I.e.: we stop only when it was just raised + * + * elif was_just_raised and main_debugger.skip_on_exceptions_thrown_in_same_context: # <<<<<<<<<<<<<< + * # Option: Don't break if an exception is caught in the same function from which it is thrown + * should_stop = False + */ + } + __pyx_L42:; + } + __pyx_L34:; + + /* "_pydevd_bundle/pydevd_cython.pyx":446 + * should_stop = False + * + * if should_stop: # <<<<<<<<<<<<<< + * exception_breakpoint = exc_break + * try: + */ + __pyx_t_7 = (__pyx_v_should_stop != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":447 + * + * if should_stop: + * exception_breakpoint = exc_break # <<<<<<<<<<<<<< + * try: + * info.pydev_message = exc_break.qname + */ + __Pyx_INCREF(__pyx_v_exc_break); + __Pyx_DECREF_SET(__pyx_v_exception_breakpoint, __pyx_v_exc_break); + + /* "_pydevd_bundle/pydevd_cython.pyx":448 + * if should_stop: + * exception_breakpoint = exc_break + * try: # <<<<<<<<<<<<<< + * info.pydev_message = exc_break.qname + * except: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_11, &__pyx_t_10, &__pyx_t_9); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_9); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":449 + * exception_breakpoint = exc_break + * try: + * info.pydev_message = exc_break.qname # <<<<<<<<<<<<<< + * except: + * info.pydev_message = exc_break.qname.encode('utf-8') + */ + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_v_exc_break, __pyx_n_s_qname); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 449, __pyx_L53_error) + __Pyx_GOTREF(__pyx_t_17); + if (!(likely(PyString_CheckExact(__pyx_t_17))||((__pyx_t_17) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_17)->tp_name), 0))) __PYX_ERR(0, 449, __pyx_L53_error) + __Pyx_GIVEREF(__pyx_t_17); + __Pyx_GOTREF(__pyx_v_info->pydev_message); + __Pyx_DECREF(__pyx_v_info->pydev_message); + __pyx_v_info->pydev_message = ((PyObject*)__pyx_t_17); + __pyx_t_17 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":448 + * if should_stop: + * exception_breakpoint = exc_break + * try: # <<<<<<<<<<<<<< + * info.pydev_message = exc_break.qname + * except: + */ + } + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L60_try_end; + __pyx_L53_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":450 + * try: + * info.pydev_message = exc_break.qname + * except: # <<<<<<<<<<<<<< + * info.pydev_message = exc_break.qname.encode('utf-8') + * break + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._should_stop_on_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_17, &__pyx_t_4, &__pyx_t_1) < 0) __PYX_ERR(0, 450, __pyx_L55_except_error) + __Pyx_GOTREF(__pyx_t_17); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_1); + + /* "_pydevd_bundle/pydevd_cython.pyx":451 + * info.pydev_message = exc_break.qname + * except: + * info.pydev_message = exc_break.qname.encode('utf-8') # <<<<<<<<<<<<<< + * break + * + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_exc_break, __pyx_n_s_qname); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 451, __pyx_L55_except_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_encode); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 451, __pyx_L55_except_error) + __Pyx_GOTREF(__pyx_t_14); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_14))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_14); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_14); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_14, function); + } + } + __pyx_t_13 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_14, __pyx_t_3, __pyx_kp_s_utf_8) : __Pyx_PyObject_CallOneArg(__pyx_t_14, __pyx_kp_s_utf_8); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 451, __pyx_L55_except_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + if (!(likely(PyString_CheckExact(__pyx_t_13))||((__pyx_t_13) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_13)->tp_name), 0))) __PYX_ERR(0, 451, __pyx_L55_except_error) + __Pyx_GIVEREF(__pyx_t_13); + __Pyx_GOTREF(__pyx_v_info->pydev_message); + __Pyx_DECREF(__pyx_v_info->pydev_message); + __pyx_v_info->pydev_message = ((PyObject*)__pyx_t_13); + __pyx_t_13 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L54_exception_handled; + } + __pyx_L55_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":448 + * if should_stop: + * exception_breakpoint = exc_break + * try: # <<<<<<<<<<<<<< + * info.pydev_message = exc_break.qname + * except: + */ + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_ExceptionReset(__pyx_t_11, __pyx_t_10, __pyx_t_9); + goto __pyx_L1_error; + __pyx_L54_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_ExceptionReset(__pyx_t_11, __pyx_t_10, __pyx_t_9); + __pyx_L60_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":452 + * except: + * info.pydev_message = exc_break.qname.encode('utf-8') + * break # <<<<<<<<<<<<<< + * + * if should_stop: + */ + goto __pyx_L31_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":446 + * should_stop = False + * + * if should_stop: # <<<<<<<<<<<<<< + * exception_breakpoint = exc_break + * try: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":403 + * check_excs.append((exc_break_caught, False)) + * + * for exc_break, is_user_uncaught in check_excs: # <<<<<<<<<<<<<< + * # Initially mark that it should stop and then go into exclusions. + * should_stop = True + */ + } + __pyx_L31_break:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + __pyx_L22:; + + /* "_pydevd_bundle/pydevd_cython.pyx":373 + * pydev_log.exception() + * + * if not should_stop: # <<<<<<<<<<<<<< + * # Apply checks that don't need the exception breakpoint (where we shouldn't ever stop). + * if exception == SystemExit and main_debugger.ignore_system_exit_code(value): + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":454 + * break + * + * if should_stop: # <<<<<<<<<<<<<< + * # Always add exception to frame (must remove later after we proceed). + * add_exception_to_frame(frame, (exception, value, trace)) + */ + __pyx_t_7 = (__pyx_v_should_stop != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":456 + * if should_stop: + * # Always add exception to frame (must remove later after we proceed). + * add_exception_to_frame(frame, (exception, value, trace)) # <<<<<<<<<<<<<< + * + * if exception_breakpoint is not None and exception_breakpoint.expression is not None: + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_add_exception_to_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 456, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 456, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_exception); + __Pyx_GIVEREF(__pyx_v_exception); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_exception); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_value); + __Pyx_INCREF(__pyx_v_trace); + __Pyx_GIVEREF(__pyx_v_trace); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_trace); + __pyx_t_17 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_17)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_17); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_17, __pyx_v_frame, __pyx_t_4}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 2+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 456, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_17, __pyx_v_frame, __pyx_t_4}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 2+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 456, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else + #endif + { + __pyx_t_13 = PyTuple_New(2+__pyx_t_12); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 456, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + if (__pyx_t_17) { + __Pyx_GIVEREF(__pyx_t_17); PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_t_17); __pyx_t_17 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_13, 0+__pyx_t_12, __pyx_v_frame); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_13, 1+__pyx_t_12, __pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_13, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 456, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":458 + * add_exception_to_frame(frame, (exception, value, trace)) + * + * if exception_breakpoint is not None and exception_breakpoint.expression is not None: # <<<<<<<<<<<<<< + * main_debugger.handle_breakpoint_expression(exception_breakpoint, info, frame) + * + */ + __pyx_t_2 = (__pyx_v_exception_breakpoint != Py_None); + __pyx_t_8 = (__pyx_t_2 != 0); + if (__pyx_t_8) { + } else { + __pyx_t_7 = __pyx_t_8; + goto __pyx_L65_bool_binop_done; + } + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_exception_breakpoint, __pyx_n_s_expression); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 458, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_8 = (__pyx_t_5 != Py_None); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_2 = (__pyx_t_8 != 0); + __pyx_t_7 = __pyx_t_2; + __pyx_L65_bool_binop_done:; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":459 + * + * if exception_breakpoint is not None and exception_breakpoint.expression is not None: + * main_debugger.handle_breakpoint_expression(exception_breakpoint, info, frame) # <<<<<<<<<<<<<< + * + * return should_stop, frame + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_handle_breakpoint_expression); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 459, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_13 = NULL; + __pyx_t_12 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_13)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_12 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[4] = {__pyx_t_13, __pyx_v_exception_breakpoint, ((PyObject *)__pyx_v_info), __pyx_v_frame}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 3+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 459, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_GOTREF(__pyx_t_5); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[4] = {__pyx_t_13, __pyx_v_exception_breakpoint, ((PyObject *)__pyx_v_info), __pyx_v_frame}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_12, 3+__pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 459, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_GOTREF(__pyx_t_5); + } else + #endif + { + __pyx_t_4 = PyTuple_New(3+__pyx_t_12); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 459, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if (__pyx_t_13) { + __Pyx_GIVEREF(__pyx_t_13); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_13); __pyx_t_13 = NULL; + } + __Pyx_INCREF(__pyx_v_exception_breakpoint); + __Pyx_GIVEREF(__pyx_v_exception_breakpoint); + PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_12, __pyx_v_exception_breakpoint); + __Pyx_INCREF(((PyObject *)__pyx_v_info)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_info)); + PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_12, ((PyObject *)__pyx_v_info)); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_4, 2+__pyx_t_12, __pyx_v_frame); + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 459, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":458 + * add_exception_to_frame(frame, (exception, value, trace)) + * + * if exception_breakpoint is not None and exception_breakpoint.expression is not None: # <<<<<<<<<<<<<< + * main_debugger.handle_breakpoint_expression(exception_breakpoint, info, frame) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":454 + * break + * + * if should_stop: # <<<<<<<<<<<<<< + * # Always add exception to frame (must remove later after we proceed). + * add_exception_to_frame(frame, (exception, value, trace)) + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":360 + * exception, value, trace = arg + * + * if trace is not None and hasattr(trace, 'tb_next'): # <<<<<<<<<<<<<< + * # on jython trace is None on the first event and it may not have a tb_next. + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":357 + * + * # 2 = 2 + * if info.pydev_state != 2: # and breakpoint is not None: # <<<<<<<<<<<<<< + * exception, value, trace = arg + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":461 + * main_debugger.handle_breakpoint_expression(exception_breakpoint, info, frame) + * + * return should_stop, frame # <<<<<<<<<<<<<< + * + * def handle_user_exception(self, frame): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_5 = __Pyx_PyBool_FromLong(__pyx_v_should_stop); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 461, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 461, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_frame); + __pyx_t_5 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":342 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _should_stop_on_exception(self, frame, str event, arg): # <<<<<<<<<<<<<< + * cdef PyDBAdditionalThreadInfo info; + * cdef bint should_stop; + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_13); + __Pyx_XDECREF(__pyx_t_14); + __Pyx_XDECREF(__pyx_t_17); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._should_stop_on_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_info); + __Pyx_XDECREF(__pyx_v_check_excs); + __Pyx_XDECREF(__pyx_v_main_debugger); + __Pyx_XDECREF(__pyx_v_exception); + __Pyx_XDECREF(__pyx_v_value); + __Pyx_XDECREF(__pyx_v_trace); + __Pyx_XDECREF(__pyx_v_exception_breakpoint); + __Pyx_XDECREF(__pyx_v_result); + __Pyx_XDECREF(__pyx_v_exc_break_user); + __Pyx_XDECREF(__pyx_v_exc_break_caught); + __Pyx_XDECREF(__pyx_v_exc_break); + __Pyx_XDECREF(__pyx_v_is_user_uncaught); + __Pyx_XDECREF(__pyx_v_exc_info); + __Pyx_XDECREF(__pyx_v_lines); + __Pyx_XDECREF(__pyx_v_frame); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":463 + * return should_stop, frame + * + * def handle_user_exception(self, frame): # <<<<<<<<<<<<<< + * exc_info = self.exc_info + * if exc_info: + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_9handle_user_exception(PyObject *__pyx_v_self, PyObject *__pyx_v_frame); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_9handle_user_exception(PyObject *__pyx_v_self, PyObject *__pyx_v_frame) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("handle_user_exception (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_8handle_user_exception(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self), ((PyObject *)__pyx_v_frame)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_8handle_user_exception(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame) { + PyObject *__pyx_v_exc_info = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("handle_user_exception", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":464 + * + * def handle_user_exception(self, frame): + * exc_info = self.exc_info # <<<<<<<<<<<<<< + * if exc_info: + * return self._handle_exception(frame, 'exception', exc_info[0], EXCEPTION_TYPE_USER_UNHANDLED) + */ + __pyx_t_1 = __pyx_v_self->exc_info; + __Pyx_INCREF(__pyx_t_1); + __pyx_v_exc_info = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":465 + * def handle_user_exception(self, frame): + * exc_info = self.exc_info + * if exc_info: # <<<<<<<<<<<<<< + * return self._handle_exception(frame, 'exception', exc_info[0], EXCEPTION_TYPE_USER_UNHANDLED) + * return False + */ + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_exc_info); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 465, __pyx_L1_error) + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":466 + * exc_info = self.exc_info + * if exc_info: + * return self._handle_exception(frame, 'exception', exc_info[0], EXCEPTION_TYPE_USER_UNHANDLED) # <<<<<<<<<<<<<< + * return False + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_exc_info, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 466, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_EXCEPTION_TYPE_USER_UNHANDLED); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 466, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (!(likely(PyString_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 466, __pyx_L1_error) + __pyx_t_4 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_handle_exception(__pyx_v_self, __pyx_v_frame, __pyx_n_s_exception, __pyx_t_1, ((PyObject*)__pyx_t_3)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 466, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":465 + * def handle_user_exception(self, frame): + * exc_info = self.exc_info + * if exc_info: # <<<<<<<<<<<<<< + * return self._handle_exception(frame, 'exception', exc_info[0], EXCEPTION_TYPE_USER_UNHANDLED) + * return False + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":467 + * if exc_info: + * return self._handle_exception(frame, 'exception', exc_info[0], EXCEPTION_TYPE_USER_UNHANDLED) + * return False # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_False); + __pyx_r = Py_False; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":463 + * return should_stop, frame + * + * def handle_user_exception(self, frame): # <<<<<<<<<<<<<< + * exc_info = self.exc_info + * if exc_info: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.handle_user_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_exc_info); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":470 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _handle_exception(self, frame, str event, arg, str exception_type): # <<<<<<<<<<<<<< + * cdef bint stopped; + * cdef tuple abs_real_path_and_base; + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__handle_exception(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg, PyObject *__pyx_v_exception_type) { + int __pyx_v_stopped; + PyObject *__pyx_v_abs_real_path_and_base = 0; + PyObject *__pyx_v_absolute_filename = 0; + PyObject *__pyx_v_canonical_normalized_filename = 0; + PyObject *__pyx_v_filename_to_lines_where_exceptions_are_ignored = 0; + PyObject *__pyx_v_lines_ignored = 0; + PyObject *__pyx_v_frame_id_to_frame = 0; + PyObject *__pyx_v_merged = 0; + PyObject *__pyx_v_trace_obj = 0; + PyObject *__pyx_v_main_debugger = 0; + PyObject *__pyx_v_initial_trace_obj = NULL; + PyObject *__pyx_v_check_trace_obj = NULL; + PyObject *__pyx_v_curr_stat = NULL; + PyObject *__pyx_v_last_stat = NULL; + PyObject *__pyx_v_from_user_input = NULL; + PyObject *__pyx_v_exc_lineno = NULL; + PyObject *__pyx_v_line = NULL; + PyObject *__pyx_v_thread = NULL; + PyObject *__pyx_v_f = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + Py_ssize_t __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + int __pyx_t_13; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + int __pyx_t_16; + PyObject *__pyx_t_17 = NULL; + int __pyx_t_18; + char const *__pyx_t_19; + PyObject *__pyx_t_20 = NULL; + PyObject *__pyx_t_21 = NULL; + PyObject *__pyx_t_22 = NULL; + PyObject *__pyx_t_23 = NULL; + PyObject *__pyx_t_24 = NULL; + PyObject *__pyx_t_25 = NULL; + char const *__pyx_t_26; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_handle_exception", 0); + __Pyx_INCREF(__pyx_v_frame); + + /* "_pydevd_bundle/pydevd_cython.pyx":484 + * # def _handle_exception(self, frame, event, arg, exception_type): + * # ENDIF + * stopped = False # <<<<<<<<<<<<<< + * try: + * # print('_handle_exception', frame.f_lineno, frame.f_code.co_name) + */ + __pyx_v_stopped = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":485 + * # ENDIF + * stopped = False + * try: # <<<<<<<<<<<<<< + * # print('_handle_exception', frame.f_lineno, frame.f_code.co_name) + * + */ + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":489 + * + * # We have 3 things in arg: exception type, description, traceback object + * trace_obj = arg[2] # <<<<<<<<<<<<<< + * main_debugger = self._args[0] + * + */ + __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_arg, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 489, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_trace_obj = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":490 + * # We have 3 things in arg: exception type, description, traceback object + * trace_obj = arg[2] + * main_debugger = self._args[0] # <<<<<<<<<<<<<< + * + * initial_trace_obj = trace_obj + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 490, __pyx_L4_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 490, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_main_debugger = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":492 + * main_debugger = self._args[0] + * + * initial_trace_obj = trace_obj # <<<<<<<<<<<<<< + * if trace_obj.tb_next is None and trace_obj.tb_frame is frame: + * # I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check). + */ + __Pyx_INCREF(__pyx_v_trace_obj); + __pyx_v_initial_trace_obj = __pyx_v_trace_obj; + + /* "_pydevd_bundle/pydevd_cython.pyx":493 + * + * initial_trace_obj = trace_obj + * if trace_obj.tb_next is None and trace_obj.tb_frame is frame: # <<<<<<<<<<<<<< + * # I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check). + * pass + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trace_obj, __pyx_n_s_tb_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 493, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = (__pyx_t_1 == Py_None); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_4 = (__pyx_t_3 != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L7_bool_binop_done; + } + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trace_obj, __pyx_n_s_tb_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 493, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = (__pyx_t_1 == __pyx_v_frame); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_4 != 0); + __pyx_t_2 = __pyx_t_3; + __pyx_L7_bool_binop_done:; + if (__pyx_t_2) { + goto __pyx_L6; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":498 + * else: + * # Get the trace_obj from where the exception was raised... + * while trace_obj.tb_next is not None: # <<<<<<<<<<<<<< + * trace_obj = trace_obj.tb_next + * + */ + /*else*/ { + while (1) { + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trace_obj, __pyx_n_s_tb_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 498, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__pyx_t_1 != Py_None); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (!__pyx_t_3) break; + + /* "_pydevd_bundle/pydevd_cython.pyx":499 + * # Get the trace_obj from where the exception was raised... + * while trace_obj.tb_next is not None: + * trace_obj = trace_obj.tb_next # <<<<<<<<<<<<<< + * + * if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trace_obj, __pyx_n_s_tb_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 499, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_trace_obj, __pyx_t_1); + __pyx_t_1 = 0; + } + } + __pyx_L6:; + + /* "_pydevd_bundle/pydevd_cython.pyx":501 + * trace_obj = trace_obj.tb_next + * + * if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: # <<<<<<<<<<<<<< + * for check_trace_obj in (initial_trace_obj, trace_obj): + * abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_ignore_exceptions_thrown_in_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 501, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 501, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":502 + * + * if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: + * for check_trace_obj in (initial_trace_obj, trace_obj): # <<<<<<<<<<<<<< + * abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) + * absolute_filename = abs_real_path_and_base[0] + */ + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 502, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_initial_trace_obj); + __Pyx_GIVEREF(__pyx_v_initial_trace_obj); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_initial_trace_obj); + __Pyx_INCREF(__pyx_v_trace_obj); + __Pyx_GIVEREF(__pyx_v_trace_obj); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_trace_obj); + __pyx_t_5 = __pyx_t_1; __Pyx_INCREF(__pyx_t_5); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + for (;;) { + if (__pyx_t_6 >= 2) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_6); __Pyx_INCREF(__pyx_t_1); __pyx_t_6++; if (unlikely(0 < 0)) __PYX_ERR(0, 502, __pyx_L4_error) + #else + __pyx_t_1 = PySequence_ITEM(__pyx_t_5, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 502, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + __Pyx_XDECREF_SET(__pyx_v_check_trace_obj, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":503 + * if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: + * for check_trace_obj in (initial_trace_obj, trace_obj): + * abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) # <<<<<<<<<<<<<< + * absolute_filename = abs_real_path_and_base[0] + * canonical_normalized_filename = abs_real_path_and_base[1] + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_get_abs_path_real_path_and_base); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 503, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_check_trace_obj, __pyx_n_s_tb_frame); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 503, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_1 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_9, __pyx_t_8) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 503, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 503, __pyx_L4_error) + __Pyx_XDECREF_SET(__pyx_v_abs_real_path_and_base, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":504 + * for check_trace_obj in (initial_trace_obj, trace_obj): + * abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) + * absolute_filename = abs_real_path_and_base[0] # <<<<<<<<<<<<<< + * canonical_normalized_filename = abs_real_path_and_base[1] + * + */ + if (unlikely(__pyx_v_abs_real_path_and_base == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 504, __pyx_L4_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v_abs_real_path_and_base, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 504, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 504, __pyx_L4_error) + __Pyx_XDECREF_SET(__pyx_v_absolute_filename, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":505 + * abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) + * absolute_filename = abs_real_path_and_base[0] + * canonical_normalized_filename = abs_real_path_and_base[1] # <<<<<<<<<<<<<< + * + * filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored + */ + if (unlikely(__pyx_v_abs_real_path_and_base == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 505, __pyx_L4_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v_abs_real_path_and_base, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 505, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 505, __pyx_L4_error) + __Pyx_XDECREF_SET(__pyx_v_canonical_normalized_filename, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":507 + * canonical_normalized_filename = abs_real_path_and_base[1] + * + * filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored # <<<<<<<<<<<<<< + * + * lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_filename_to_lines_where_exceptio); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 507, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyDict_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 507, __pyx_L4_error) + __Pyx_XDECREF_SET(__pyx_v_filename_to_lines_where_exceptions_are_ignored, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":509 + * filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored + * + * lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) # <<<<<<<<<<<<<< + * if lines_ignored is None: + * lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + */ + if (unlikely(__pyx_v_filename_to_lines_where_exceptions_are_ignored == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get"); + __PYX_ERR(0, 509, __pyx_L4_error) + } + __pyx_t_1 = __Pyx_PyDict_GetItemDefault(__pyx_v_filename_to_lines_where_exceptions_are_ignored, __pyx_v_canonical_normalized_filename, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 509, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyDict_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 509, __pyx_L4_error) + __Pyx_XDECREF_SET(__pyx_v_lines_ignored, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":510 + * + * lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + * if lines_ignored is None: # <<<<<<<<<<<<<< + * lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + * + */ + __pyx_t_3 = (__pyx_v_lines_ignored == ((PyObject*)Py_None)); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":511 + * lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + * if lines_ignored is None: + * lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} # <<<<<<<<<<<<<< + * + * try: + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 511, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_lines_ignored, __pyx_t_1); + if (unlikely(__pyx_v_filename_to_lines_where_exceptions_are_ignored == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 511, __pyx_L4_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_filename_to_lines_where_exceptions_are_ignored, __pyx_v_canonical_normalized_filename, __pyx_t_1) < 0)) __PYX_ERR(0, 511, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":510 + * + * lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + * if lines_ignored is None: # <<<<<<<<<<<<<< + * lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":513 + * lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + * + * try: # <<<<<<<<<<<<<< + * curr_stat = os.stat(absolute_filename) + * curr_stat = (curr_stat.st_size, curr_stat.st_mtime) + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_12); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":514 + * + * try: + * curr_stat = os.stat(absolute_filename) # <<<<<<<<<<<<<< + * curr_stat = (curr_stat.st_size, curr_stat.st_mtime) + * except: + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_os); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 514, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_stat); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 514, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_7, __pyx_v_absolute_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_v_absolute_filename); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 514, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_curr_stat, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":515 + * try: + * curr_stat = os.stat(absolute_filename) + * curr_stat = (curr_stat.st_size, curr_stat.st_mtime) # <<<<<<<<<<<<<< + * except: + * curr_stat = None + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_curr_stat, __pyx_n_s_st_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 515, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_curr_stat, __pyx_n_s_st_mtime); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 515, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 515, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8); + __pyx_t_1 = 0; + __pyx_t_8 = 0; + __Pyx_DECREF_SET(__pyx_v_curr_stat, __pyx_t_7); + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":513 + * lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + * + * try: # <<<<<<<<<<<<<< + * curr_stat = os.stat(absolute_filename) + * curr_stat = (curr_stat.st_size, curr_stat.st_mtime) + */ + } + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + goto __pyx_L22_try_end; + __pyx_L15_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":516 + * curr_stat = os.stat(absolute_filename) + * curr_stat = (curr_stat.st_size, curr_stat.st_mtime) + * except: # <<<<<<<<<<<<<< + * curr_stat = None + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._handle_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_8, &__pyx_t_1) < 0) __PYX_ERR(0, 516, __pyx_L17_except_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GOTREF(__pyx_t_1); + + /* "_pydevd_bundle/pydevd_cython.pyx":517 + * curr_stat = (curr_stat.st_size, curr_stat.st_mtime) + * except: + * curr_stat = None # <<<<<<<<<<<<<< + * + * last_stat = self.filename_to_stat_info.get(absolute_filename) + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_curr_stat, Py_None); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L16_exception_handled; + } + __pyx_L17_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":513 + * lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + * + * try: # <<<<<<<<<<<<<< + * curr_stat = os.stat(absolute_filename) + * curr_stat = (curr_stat.st_size, curr_stat.st_mtime) + */ + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ExceptionReset(__pyx_t_10, __pyx_t_11, __pyx_t_12); + goto __pyx_L4_error; + __pyx_L16_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ExceptionReset(__pyx_t_10, __pyx_t_11, __pyx_t_12); + __pyx_L22_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":519 + * curr_stat = None + * + * last_stat = self.filename_to_stat_info.get(absolute_filename) # <<<<<<<<<<<<<< + * if last_stat != curr_stat: + * self.filename_to_stat_info[absolute_filename] = curr_stat + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_filename_to_stat_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 519, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_get); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 519, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_absolute_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_absolute_filename); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 519, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_last_stat, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":520 + * + * last_stat = self.filename_to_stat_info.get(absolute_filename) + * if last_stat != curr_stat: # <<<<<<<<<<<<<< + * self.filename_to_stat_info[absolute_filename] = curr_stat + * lines_ignored.clear() + */ + __pyx_t_1 = PyObject_RichCompare(__pyx_v_last_stat, __pyx_v_curr_stat, Py_NE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 520, __pyx_L4_error) + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 520, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":521 + * last_stat = self.filename_to_stat_info.get(absolute_filename) + * if last_stat != curr_stat: + * self.filename_to_stat_info[absolute_filename] = curr_stat # <<<<<<<<<<<<<< + * lines_ignored.clear() + * try: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_filename_to_stat_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 521, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + if (unlikely(PyObject_SetItem(__pyx_t_1, __pyx_v_absolute_filename, __pyx_v_curr_stat) < 0)) __PYX_ERR(0, 521, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":522 + * if last_stat != curr_stat: + * self.filename_to_stat_info[absolute_filename] = curr_stat + * lines_ignored.clear() # <<<<<<<<<<<<<< + * try: + * linecache.checkcache(absolute_filename) + */ + if (unlikely(__pyx_v_lines_ignored == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "clear"); + __PYX_ERR(0, 522, __pyx_L4_error) + } + __pyx_t_13 = __Pyx_PyDict_Clear(__pyx_v_lines_ignored); if (unlikely(__pyx_t_13 == ((int)-1))) __PYX_ERR(0, 522, __pyx_L4_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":523 + * self.filename_to_stat_info[absolute_filename] = curr_stat + * lines_ignored.clear() + * try: # <<<<<<<<<<<<<< + * linecache.checkcache(absolute_filename) + * except: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_10); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":524 + * lines_ignored.clear() + * try: + * linecache.checkcache(absolute_filename) # <<<<<<<<<<<<<< + * except: + * pydev_log.exception('Error in linecache.checkcache(%r)', absolute_filename) + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_linecache); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 524, __pyx_L26_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_checkcache); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 524, __pyx_L26_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_7, __pyx_v_absolute_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_v_absolute_filename); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 524, __pyx_L26_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":523 + * self.filename_to_stat_info[absolute_filename] = curr_stat + * lines_ignored.clear() + * try: # <<<<<<<<<<<<<< + * linecache.checkcache(absolute_filename) + * except: + */ + } + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + goto __pyx_L33_try_end; + __pyx_L26_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":525 + * try: + * linecache.checkcache(absolute_filename) + * except: # <<<<<<<<<<<<<< + * pydev_log.exception('Error in linecache.checkcache(%r)', absolute_filename) + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._handle_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_8, &__pyx_t_7) < 0) __PYX_ERR(0, 525, __pyx_L28_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GOTREF(__pyx_t_7); + + /* "_pydevd_bundle/pydevd_cython.pyx":526 + * linecache.checkcache(absolute_filename) + * except: + * pydev_log.exception('Error in linecache.checkcache(%r)', absolute_filename) # <<<<<<<<<<<<<< + * + * from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + */ + __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 526, __pyx_L28_except_error) + __Pyx_GOTREF(__pyx_t_14); + __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_n_s_exception); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 526, __pyx_L28_except_error) + __Pyx_GOTREF(__pyx_t_15); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_14 = NULL; + __pyx_t_16 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_15))) { + __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_15); + if (likely(__pyx_t_14)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_15); + __Pyx_INCREF(__pyx_t_14); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_15, function); + __pyx_t_16 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_15)) { + PyObject *__pyx_temp[3] = {__pyx_t_14, __pyx_kp_s_Error_in_linecache_checkcache_r, __pyx_v_absolute_filename}; + __pyx_t_9 = __Pyx_PyFunction_FastCall(__pyx_t_15, __pyx_temp+1-__pyx_t_16, 2+__pyx_t_16); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 526, __pyx_L28_except_error) + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_GOTREF(__pyx_t_9); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_15)) { + PyObject *__pyx_temp[3] = {__pyx_t_14, __pyx_kp_s_Error_in_linecache_checkcache_r, __pyx_v_absolute_filename}; + __pyx_t_9 = __Pyx_PyCFunction_FastCall(__pyx_t_15, __pyx_temp+1-__pyx_t_16, 2+__pyx_t_16); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 526, __pyx_L28_except_error) + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_GOTREF(__pyx_t_9); + } else + #endif + { + __pyx_t_17 = PyTuple_New(2+__pyx_t_16); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 526, __pyx_L28_except_error) + __Pyx_GOTREF(__pyx_t_17); + if (__pyx_t_14) { + __Pyx_GIVEREF(__pyx_t_14); PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_14); __pyx_t_14 = NULL; + } + __Pyx_INCREF(__pyx_kp_s_Error_in_linecache_checkcache_r); + __Pyx_GIVEREF(__pyx_kp_s_Error_in_linecache_checkcache_r); + PyTuple_SET_ITEM(__pyx_t_17, 0+__pyx_t_16, __pyx_kp_s_Error_in_linecache_checkcache_r); + __Pyx_INCREF(__pyx_v_absolute_filename); + __Pyx_GIVEREF(__pyx_v_absolute_filename); + PyTuple_SET_ITEM(__pyx_t_17, 1+__pyx_t_16, __pyx_v_absolute_filename); + __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_15, __pyx_t_17, NULL); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 526, __pyx_L28_except_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + } + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L27_exception_handled; + } + __pyx_L28_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":523 + * self.filename_to_stat_info[absolute_filename] = curr_stat + * lines_ignored.clear() + * try: # <<<<<<<<<<<<<< + * linecache.checkcache(absolute_filename) + * except: + */ + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_11, __pyx_t_10); + goto __pyx_L4_error; + __pyx_L27_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_11, __pyx_t_10); + __pyx_L33_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":520 + * + * last_stat = self.filename_to_stat_info.get(absolute_filename) + * if last_stat != curr_stat: # <<<<<<<<<<<<<< + * self.filename_to_stat_info[absolute_filename] = curr_stat + * lines_ignored.clear() + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":528 + * pydev_log.exception('Error in linecache.checkcache(%r)', absolute_filename) + * + * from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) # <<<<<<<<<<<<<< + * if from_user_input: + * merged = {} + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_filename_to_lines_where_exceptio); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 528, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_get); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 528, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_7 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_8, __pyx_v_canonical_normalized_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_canonical_normalized_filename); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 528, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF_SET(__pyx_v_from_user_input, __pyx_t_7); + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":529 + * + * from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + * if from_user_input: # <<<<<<<<<<<<<< + * merged = {} + * merged.update(lines_ignored) + */ + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_user_input); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 529, __pyx_L4_error) + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":530 + * from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + * if from_user_input: + * merged = {} # <<<<<<<<<<<<<< + * merged.update(lines_ignored) + * # Override what we have with the related entries that the user entered + */ + __pyx_t_7 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 530, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_XDECREF_SET(__pyx_v_merged, ((PyObject*)__pyx_t_7)); + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":531 + * if from_user_input: + * merged = {} + * merged.update(lines_ignored) # <<<<<<<<<<<<<< + * # Override what we have with the related entries that the user entered + * merged.update(from_user_input) + */ + __pyx_t_7 = __Pyx_CallUnboundCMethod1(&__pyx_umethod_PyDict_Type_update, __pyx_v_merged, __pyx_v_lines_ignored); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 531, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":533 + * merged.update(lines_ignored) + * # Override what we have with the related entries that the user entered + * merged.update(from_user_input) # <<<<<<<<<<<<<< + * else: + * merged = lines_ignored + */ + __pyx_t_7 = __Pyx_CallUnboundCMethod1(&__pyx_umethod_PyDict_Type_update, __pyx_v_merged, __pyx_v_from_user_input); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 533, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":529 + * + * from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + * if from_user_input: # <<<<<<<<<<<<<< + * merged = {} + * merged.update(lines_ignored) + */ + goto __pyx_L36; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":535 + * merged.update(from_user_input) + * else: + * merged = lines_ignored # <<<<<<<<<<<<<< + * + * exc_lineno = check_trace_obj.tb_lineno + */ + /*else*/ { + __Pyx_INCREF(__pyx_v_lines_ignored); + __Pyx_XDECREF_SET(__pyx_v_merged, __pyx_v_lines_ignored); + } + __pyx_L36:; + + /* "_pydevd_bundle/pydevd_cython.pyx":537 + * merged = lines_ignored + * + * exc_lineno = check_trace_obj.tb_lineno # <<<<<<<<<<<<<< + * + * # print ('lines ignored', lines_ignored) + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_check_trace_obj, __pyx_n_s_tb_lineno); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 537, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_XDECREF_SET(__pyx_v_exc_lineno, __pyx_t_7); + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":543 + * # print ('merged', merged, 'curr', exc_lineno) + * + * if exc_lineno not in merged: # Note: check on merged but update lines_ignored. # <<<<<<<<<<<<<< + * try: + * line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + */ + if (unlikely(__pyx_v_merged == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 543, __pyx_L4_error) + } + __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_exc_lineno, __pyx_v_merged, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 543, __pyx_L4_error) + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":544 + * + * if exc_lineno not in merged: # Note: check on merged but update lines_ignored. + * try: # <<<<<<<<<<<<<< + * line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + * except: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_12); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":545 + * if exc_lineno not in merged: # Note: check on merged but update lines_ignored. + * try: + * line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) # <<<<<<<<<<<<<< + * except: + * pydev_log.exception('Error in linecache.getline(%r, %s, f_globals)', absolute_filename, exc_lineno) + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_linecache); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 545, __pyx_L38_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_getline); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 545, __pyx_L38_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_check_trace_obj, __pyx_n_s_tb_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 545, __pyx_L38_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_f_globals); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 545, __pyx_L38_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = NULL; + __pyx_t_16 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + __pyx_t_16 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[4] = {__pyx_t_1, __pyx_v_absolute_filename, __pyx_v_exc_lineno, __pyx_t_9}; + __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_16, 3+__pyx_t_16); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 545, __pyx_L38_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[4] = {__pyx_t_1, __pyx_v_absolute_filename, __pyx_v_exc_lineno, __pyx_t_9}; + __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_16, 3+__pyx_t_16); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 545, __pyx_L38_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } else + #endif + { + __pyx_t_15 = PyTuple_New(3+__pyx_t_16); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 545, __pyx_L38_error) + __Pyx_GOTREF(__pyx_t_15); + if (__pyx_t_1) { + __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_15, 0, __pyx_t_1); __pyx_t_1 = NULL; + } + __Pyx_INCREF(__pyx_v_absolute_filename); + __Pyx_GIVEREF(__pyx_v_absolute_filename); + PyTuple_SET_ITEM(__pyx_t_15, 0+__pyx_t_16, __pyx_v_absolute_filename); + __Pyx_INCREF(__pyx_v_exc_lineno); + __Pyx_GIVEREF(__pyx_v_exc_lineno); + PyTuple_SET_ITEM(__pyx_t_15, 1+__pyx_t_16, __pyx_v_exc_lineno); + __Pyx_GIVEREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_15, 2+__pyx_t_16, __pyx_t_9); + __pyx_t_9 = 0; + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_15, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 545, __pyx_L38_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_line, __pyx_t_7); + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":544 + * + * if exc_lineno not in merged: # Note: check on merged but update lines_ignored. + * try: # <<<<<<<<<<<<<< + * line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + * except: + */ + } + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + goto __pyx_L45_try_end; + __pyx_L38_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":546 + * try: + * line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + * except: # <<<<<<<<<<<<<< + * pydev_log.exception('Error in linecache.getline(%r, %s, f_globals)', absolute_filename, exc_lineno) + * line = '' + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._handle_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_8, &__pyx_t_15) < 0) __PYX_ERR(0, 546, __pyx_L40_except_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GOTREF(__pyx_t_15); + + /* "_pydevd_bundle/pydevd_cython.pyx":547 + * line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + * except: + * pydev_log.exception('Error in linecache.getline(%r, %s, f_globals)', absolute_filename, exc_lineno) # <<<<<<<<<<<<<< + * line = '' + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 547, __pyx_L40_except_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_exception); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 547, __pyx_L40_except_error) + __Pyx_GOTREF(__pyx_t_17); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = NULL; + __pyx_t_16 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_17))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_17); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_17); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_17, function); + __pyx_t_16 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_17)) { + PyObject *__pyx_temp[4] = {__pyx_t_1, __pyx_kp_s_Error_in_linecache_getline_r_s_f, __pyx_v_absolute_filename, __pyx_v_exc_lineno}; + __pyx_t_9 = __Pyx_PyFunction_FastCall(__pyx_t_17, __pyx_temp+1-__pyx_t_16, 3+__pyx_t_16); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 547, __pyx_L40_except_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_9); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_17)) { + PyObject *__pyx_temp[4] = {__pyx_t_1, __pyx_kp_s_Error_in_linecache_getline_r_s_f, __pyx_v_absolute_filename, __pyx_v_exc_lineno}; + __pyx_t_9 = __Pyx_PyCFunction_FastCall(__pyx_t_17, __pyx_temp+1-__pyx_t_16, 3+__pyx_t_16); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 547, __pyx_L40_except_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_9); + } else + #endif + { + __pyx_t_14 = PyTuple_New(3+__pyx_t_16); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 547, __pyx_L40_except_error) + __Pyx_GOTREF(__pyx_t_14); + if (__pyx_t_1) { + __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_t_1); __pyx_t_1 = NULL; + } + __Pyx_INCREF(__pyx_kp_s_Error_in_linecache_getline_r_s_f); + __Pyx_GIVEREF(__pyx_kp_s_Error_in_linecache_getline_r_s_f); + PyTuple_SET_ITEM(__pyx_t_14, 0+__pyx_t_16, __pyx_kp_s_Error_in_linecache_getline_r_s_f); + __Pyx_INCREF(__pyx_v_absolute_filename); + __Pyx_GIVEREF(__pyx_v_absolute_filename); + PyTuple_SET_ITEM(__pyx_t_14, 1+__pyx_t_16, __pyx_v_absolute_filename); + __Pyx_INCREF(__pyx_v_exc_lineno); + __Pyx_GIVEREF(__pyx_v_exc_lineno); + PyTuple_SET_ITEM(__pyx_t_14, 2+__pyx_t_16, __pyx_v_exc_lineno); + __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_17, __pyx_t_14, NULL); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 547, __pyx_L40_except_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + } + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":548 + * except: + * pydev_log.exception('Error in linecache.getline(%r, %s, f_globals)', absolute_filename, exc_lineno) + * line = '' # <<<<<<<<<<<<<< + * + * if IGNORE_EXCEPTION_TAG.match(line) is not None: + */ + __Pyx_INCREF(__pyx_kp_s_); + __Pyx_XDECREF_SET(__pyx_v_line, __pyx_kp_s_); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + goto __pyx_L39_exception_handled; + } + __pyx_L40_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":544 + * + * if exc_lineno not in merged: # Note: check on merged but update lines_ignored. + * try: # <<<<<<<<<<<<<< + * line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + * except: + */ + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ExceptionReset(__pyx_t_10, __pyx_t_11, __pyx_t_12); + goto __pyx_L4_error; + __pyx_L39_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ExceptionReset(__pyx_t_10, __pyx_t_11, __pyx_t_12); + __pyx_L45_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":550 + * line = '' + * + * if IGNORE_EXCEPTION_TAG.match(line) is not None: # <<<<<<<<<<<<<< + * lines_ignored[exc_lineno] = 1 + * return False + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_IGNORE_EXCEPTION_TAG); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 550, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_match); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 550, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_15 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_line) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_line); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 550, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_15); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_3 = (__pyx_t_15 != Py_None); + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":551 + * + * if IGNORE_EXCEPTION_TAG.match(line) is not None: + * lines_ignored[exc_lineno] = 1 # <<<<<<<<<<<<<< + * return False + * else: + */ + if (unlikely(__pyx_v_lines_ignored == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 551, __pyx_L4_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_lines_ignored, __pyx_v_exc_lineno, __pyx_int_1) < 0)) __PYX_ERR(0, 551, __pyx_L4_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":552 + * if IGNORE_EXCEPTION_TAG.match(line) is not None: + * lines_ignored[exc_lineno] = 1 + * return False # <<<<<<<<<<<<<< + * else: + * # Put in the cache saying not to ignore + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_False); + __pyx_r = Py_False; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":550 + * line = '' + * + * if IGNORE_EXCEPTION_TAG.match(line) is not None: # <<<<<<<<<<<<<< + * lines_ignored[exc_lineno] = 1 + * return False + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":555 + * else: + * # Put in the cache saying not to ignore + * lines_ignored[exc_lineno] = 0 # <<<<<<<<<<<<<< + * else: + * # Ok, dict has it already cached, so, let's check it... + */ + /*else*/ { + if (unlikely(__pyx_v_lines_ignored == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 555, __pyx_L4_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_lines_ignored, __pyx_v_exc_lineno, __pyx_int_0) < 0)) __PYX_ERR(0, 555, __pyx_L4_error) + } + + /* "_pydevd_bundle/pydevd_cython.pyx":543 + * # print ('merged', merged, 'curr', exc_lineno) + * + * if exc_lineno not in merged: # Note: check on merged but update lines_ignored. # <<<<<<<<<<<<<< + * try: + * line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + */ + goto __pyx_L37; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":558 + * else: + * # Ok, dict has it already cached, so, let's check it... + * if merged.get(exc_lineno, 0): # <<<<<<<<<<<<<< + * return False + * + */ + /*else*/ { + if (unlikely(__pyx_v_merged == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get"); + __PYX_ERR(0, 558, __pyx_L4_error) + } + __pyx_t_15 = __Pyx_PyDict_GetItemDefault(__pyx_v_merged, __pyx_v_exc_lineno, __pyx_int_0); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 558, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_15); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_15); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 558, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":559 + * # Ok, dict has it already cached, so, let's check it... + * if merged.get(exc_lineno, 0): + * return False # <<<<<<<<<<<<<< + * + * thread = self._args[3] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_False); + __pyx_r = Py_False; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":558 + * else: + * # Ok, dict has it already cached, so, let's check it... + * if merged.get(exc_lineno, 0): # <<<<<<<<<<<<<< + * return False + * + */ + } + } + __pyx_L37:; + + /* "_pydevd_bundle/pydevd_cython.pyx":502 + * + * if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: + * for check_trace_obj in (initial_trace_obj, trace_obj): # <<<<<<<<<<<<<< + * abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) + * absolute_filename = abs_real_path_and_base[0] + */ + } + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":501 + * trace_obj = trace_obj.tb_next + * + * if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: # <<<<<<<<<<<<<< + * for check_trace_obj in (initial_trace_obj, trace_obj): + * abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":561 + * return False + * + * thread = self._args[3] # <<<<<<<<<<<<<< + * + * try: + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 561, __pyx_L4_error) + } + __pyx_t_5 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 561, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_thread = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":563 + * thread = self._args[3] + * + * try: # <<<<<<<<<<<<<< + * frame_id_to_frame = {} + * frame_id_to_frame[id(frame)] = frame + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_10); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":564 + * + * try: + * frame_id_to_frame = {} # <<<<<<<<<<<<<< + * frame_id_to_frame[id(frame)] = frame + * f = trace_obj.tb_frame + */ + __pyx_t_5 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 564, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_frame_id_to_frame = ((PyObject*)__pyx_t_5); + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":565 + * try: + * frame_id_to_frame = {} + * frame_id_to_frame[id(frame)] = frame # <<<<<<<<<<<<<< + * f = trace_obj.tb_frame + * while f is not None: + */ + __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, __pyx_v_frame); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 565, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_5); + if (unlikely(PyDict_SetItem(__pyx_v_frame_id_to_frame, __pyx_t_5, __pyx_v_frame) < 0)) __PYX_ERR(0, 565, __pyx_L50_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":566 + * frame_id_to_frame = {} + * frame_id_to_frame[id(frame)] = frame + * f = trace_obj.tb_frame # <<<<<<<<<<<<<< + * while f is not None: + * frame_id_to_frame[id(f)] = f + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_trace_obj, __pyx_n_s_tb_frame); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 566, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_f = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":567 + * frame_id_to_frame[id(frame)] = frame + * f = trace_obj.tb_frame + * while f is not None: # <<<<<<<<<<<<<< + * frame_id_to_frame[id(f)] = f + * f = f.f_back + */ + while (1) { + __pyx_t_2 = (__pyx_v_f != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (!__pyx_t_3) break; + + /* "_pydevd_bundle/pydevd_cython.pyx":568 + * f = trace_obj.tb_frame + * while f is not None: + * frame_id_to_frame[id(f)] = f # <<<<<<<<<<<<<< + * f = f.f_back + * f = None + */ + __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, __pyx_v_f); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 568, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_5); + if (unlikely(PyDict_SetItem(__pyx_v_frame_id_to_frame, __pyx_t_5, __pyx_v_f) < 0)) __PYX_ERR(0, 568, __pyx_L50_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":569 + * while f is not None: + * frame_id_to_frame[id(f)] = f + * f = f.f_back # <<<<<<<<<<<<<< + * f = None + * + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_back); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 569, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF_SET(__pyx_v_f, __pyx_t_5); + __pyx_t_5 = 0; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":570 + * frame_id_to_frame[id(f)] = f + * f = f.f_back + * f = None # <<<<<<<<<<<<<< + * + * stopped = True + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_f, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":572 + * f = None + * + * stopped = True # <<<<<<<<<<<<<< + * main_debugger.send_caught_exception_stack(thread, arg, id(frame)) + * try: + */ + __pyx_v_stopped = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":573 + * + * stopped = True + * main_debugger.send_caught_exception_stack(thread, arg, id(frame)) # <<<<<<<<<<<<<< + * try: + * self.set_suspend(thread, 137) + */ + __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_send_caught_exception_stack); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 573, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_15); + __pyx_t_7 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, __pyx_v_frame); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 573, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = NULL; + __pyx_t_16 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_15))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_15); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_15); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_15, function); + __pyx_t_16 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_15)) { + PyObject *__pyx_temp[4] = {__pyx_t_8, __pyx_v_thread, __pyx_v_arg, __pyx_t_7}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_15, __pyx_temp+1-__pyx_t_16, 3+__pyx_t_16); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 573, __pyx_L50_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_15)) { + PyObject *__pyx_temp[4] = {__pyx_t_8, __pyx_v_thread, __pyx_v_arg, __pyx_t_7}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_15, __pyx_temp+1-__pyx_t_16, 3+__pyx_t_16); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 573, __pyx_L50_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_9 = PyTuple_New(3+__pyx_t_16); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 573, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_9); + if (__pyx_t_8) { + __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_8); __pyx_t_8 = NULL; + } + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_9, 0+__pyx_t_16, __pyx_v_thread); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_16, __pyx_v_arg); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_9, 2+__pyx_t_16, __pyx_t_7); + __pyx_t_7 = 0; + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_15, __pyx_t_9, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 573, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":574 + * stopped = True + * main_debugger.send_caught_exception_stack(thread, arg, id(frame)) + * try: # <<<<<<<<<<<<<< + * self.set_suspend(thread, 137) + * self.do_wait_suspend(thread, frame, event, arg, exception_type=exception_type) + */ + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":575 + * main_debugger.send_caught_exception_stack(thread, arg, id(frame)) + * try: + * self.set_suspend(thread, 137) # <<<<<<<<<<<<<< + * self.do_wait_suspend(thread, frame, event, arg, exception_type=exception_type) + * finally: + */ + __pyx_t_15 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_suspend); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 575, __pyx_L59_error) + __Pyx_GOTREF(__pyx_t_15); + __pyx_t_9 = NULL; + __pyx_t_16 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_15))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_15); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_15); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_15, function); + __pyx_t_16 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_15)) { + PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_v_thread, __pyx_int_137}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_15, __pyx_temp+1-__pyx_t_16, 2+__pyx_t_16); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 575, __pyx_L59_error) + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_GOTREF(__pyx_t_5); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_15)) { + PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_v_thread, __pyx_int_137}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_15, __pyx_temp+1-__pyx_t_16, 2+__pyx_t_16); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 575, __pyx_L59_error) + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_GOTREF(__pyx_t_5); + } else + #endif + { + __pyx_t_7 = PyTuple_New(2+__pyx_t_16); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 575, __pyx_L59_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_9) { + __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_9); __pyx_t_9 = NULL; + } + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_16, __pyx_v_thread); + __Pyx_INCREF(__pyx_int_137); + __Pyx_GIVEREF(__pyx_int_137); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_16, __pyx_int_137); + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_15, __pyx_t_7, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 575, __pyx_L59_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":576 + * try: + * self.set_suspend(thread, 137) + * self.do_wait_suspend(thread, frame, event, arg, exception_type=exception_type) # <<<<<<<<<<<<<< + * finally: + * main_debugger.send_caught_exception_stack_proceeded(thread) + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_do_wait_suspend); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 576, __pyx_L59_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_15 = PyTuple_New(4); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 576, __pyx_L59_error) + __Pyx_GOTREF(__pyx_t_15); + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_15, 0, __pyx_v_thread); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_15, 1, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_15, 2, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_15, 3, __pyx_v_arg); + __pyx_t_7 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 576, __pyx_L59_error) + __Pyx_GOTREF(__pyx_t_7); + if (PyDict_SetItem(__pyx_t_7, __pyx_n_s_exception_type, __pyx_v_exception_type) < 0) __PYX_ERR(0, 576, __pyx_L59_error) + __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_15, __pyx_t_7); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 576, __pyx_L59_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":578 + * self.do_wait_suspend(thread, frame, event, arg, exception_type=exception_type) + * finally: + * main_debugger.send_caught_exception_stack_proceeded(thread) # <<<<<<<<<<<<<< + * except: + * pydev_log.exception() + */ + /*finally:*/ { + /*normal exit:*/{ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_send_caught_exception_stack_proc); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 578, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_15 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_15 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_15)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_15); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_9 = (__pyx_t_15) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_15, __pyx_v_thread) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_thread); + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 578, __pyx_L50_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L60; + } + __pyx_L59_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_20 = 0; __pyx_t_21 = 0; __pyx_t_22 = 0; __pyx_t_23 = 0; __pyx_t_24 = 0; __pyx_t_25 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_23, &__pyx_t_24, &__pyx_t_25); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_20, &__pyx_t_21, &__pyx_t_22) < 0)) __Pyx_ErrFetch(&__pyx_t_20, &__pyx_t_21, &__pyx_t_22); + __Pyx_XGOTREF(__pyx_t_20); + __Pyx_XGOTREF(__pyx_t_21); + __Pyx_XGOTREF(__pyx_t_22); + __Pyx_XGOTREF(__pyx_t_23); + __Pyx_XGOTREF(__pyx_t_24); + __Pyx_XGOTREF(__pyx_t_25); + __pyx_t_16 = __pyx_lineno; __pyx_t_18 = __pyx_clineno; __pyx_t_19 = __pyx_filename; + { + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_send_caught_exception_stack_proc); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 578, __pyx_L62_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_15 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_15 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_15)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_15); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_9 = (__pyx_t_15) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_15, __pyx_v_thread) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_thread); + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 578, __pyx_L62_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_23); + __Pyx_XGIVEREF(__pyx_t_24); + __Pyx_XGIVEREF(__pyx_t_25); + __Pyx_ExceptionReset(__pyx_t_23, __pyx_t_24, __pyx_t_25); + } + __Pyx_XGIVEREF(__pyx_t_20); + __Pyx_XGIVEREF(__pyx_t_21); + __Pyx_XGIVEREF(__pyx_t_22); + __Pyx_ErrRestore(__pyx_t_20, __pyx_t_21, __pyx_t_22); + __pyx_t_20 = 0; __pyx_t_21 = 0; __pyx_t_22 = 0; __pyx_t_23 = 0; __pyx_t_24 = 0; __pyx_t_25 = 0; + __pyx_lineno = __pyx_t_16; __pyx_clineno = __pyx_t_18; __pyx_filename = __pyx_t_19; + goto __pyx_L50_error; + __pyx_L62_error:; + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_23); + __Pyx_XGIVEREF(__pyx_t_24); + __Pyx_XGIVEREF(__pyx_t_25); + __Pyx_ExceptionReset(__pyx_t_23, __pyx_t_24, __pyx_t_25); + } + __Pyx_XDECREF(__pyx_t_20); __pyx_t_20 = 0; + __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0; + __Pyx_XDECREF(__pyx_t_22); __pyx_t_22 = 0; + __pyx_t_23 = 0; __pyx_t_24 = 0; __pyx_t_25 = 0; + goto __pyx_L50_error; + } + __pyx_L60:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":563 + * thread = self._args[3] + * + * try: # <<<<<<<<<<<<<< + * frame_id_to_frame = {} + * frame_id_to_frame[id(frame)] = frame + */ + } + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + goto __pyx_L55_try_end; + __pyx_L50_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":579 + * finally: + * main_debugger.send_caught_exception_stack_proceeded(thread) + * except: # <<<<<<<<<<<<<< + * pydev_log.exception() + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._handle_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_9, &__pyx_t_7, &__pyx_t_15) < 0) __PYX_ERR(0, 579, __pyx_L52_except_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_15); + + /* "_pydevd_bundle/pydevd_cython.pyx":580 + * main_debugger.send_caught_exception_stack_proceeded(thread) + * except: + * pydev_log.exception() # <<<<<<<<<<<<<< + * + * main_debugger.set_trace_for_frame_and_parents(frame) + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 580, __pyx_L52_except_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_exception); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 580, __pyx_L52_except_error) + __Pyx_GOTREF(__pyx_t_17); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_17))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_17); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_17); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_17, function); + } + } + __pyx_t_5 = (__pyx_t_8) ? __Pyx_PyObject_CallOneArg(__pyx_t_17, __pyx_t_8) : __Pyx_PyObject_CallNoArg(__pyx_t_17); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 580, __pyx_L52_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + goto __pyx_L51_exception_handled; + } + __pyx_L52_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":563 + * thread = self._args[3] + * + * try: # <<<<<<<<<<<<<< + * frame_id_to_frame = {} + * frame_id_to_frame[id(frame)] = frame + */ + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_11, __pyx_t_10); + goto __pyx_L4_error; + __pyx_L51_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_11, __pyx_t_10); + __pyx_L55_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":582 + * pydev_log.exception() + * + * main_debugger.set_trace_for_frame_and_parents(frame) # <<<<<<<<<<<<<< + * finally: + * # Make sure the user cannot see the '__exception__' we added after we leave the suspend state. + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_set_trace_for_frame_and_parents); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 582, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_15 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_9, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 582, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_15); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":585 + * finally: + * # Make sure the user cannot see the '__exception__' we added after we leave the suspend state. + * remove_exception_from_frame(frame) # <<<<<<<<<<<<<< + * # Clear some local variables... + * frame = None + */ + /*finally:*/ { + /*normal exit:*/{ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_remove_exception_from_frame); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 585, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_15 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_9, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 585, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_15); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":587 + * remove_exception_from_frame(frame) + * # Clear some local variables... + * frame = None # <<<<<<<<<<<<<< + * trace_obj = None + * initial_trace_obj = None + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_frame, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":588 + * # Clear some local variables... + * frame = None + * trace_obj = None # <<<<<<<<<<<<<< + * initial_trace_obj = None + * check_trace_obj = None + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":589 + * frame = None + * trace_obj = None + * initial_trace_obj = None # <<<<<<<<<<<<<< + * check_trace_obj = None + * f = None + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_initial_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":590 + * trace_obj = None + * initial_trace_obj = None + * check_trace_obj = None # <<<<<<<<<<<<<< + * f = None + * frame_id_to_frame = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_check_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":591 + * initial_trace_obj = None + * check_trace_obj = None + * f = None # <<<<<<<<<<<<<< + * frame_id_to_frame = None + * main_debugger = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_f, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":592 + * check_trace_obj = None + * f = None + * frame_id_to_frame = None # <<<<<<<<<<<<<< + * main_debugger = None + * thread = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_frame_id_to_frame, ((PyObject*)Py_None)); + + /* "_pydevd_bundle/pydevd_cython.pyx":593 + * f = None + * frame_id_to_frame = None + * main_debugger = None # <<<<<<<<<<<<<< + * thread = None + * + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_main_debugger, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":594 + * frame_id_to_frame = None + * main_debugger = None + * thread = None # <<<<<<<<<<<<<< + * + * return stopped + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_thread, Py_None); + goto __pyx_L5; + } + __pyx_L4_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_25 = 0; __pyx_t_24 = 0; __pyx_t_23 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_25, &__pyx_t_24, &__pyx_t_23); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_25); + __Pyx_XGOTREF(__pyx_t_24); + __Pyx_XGOTREF(__pyx_t_23); + __pyx_t_18 = __pyx_lineno; __pyx_t_16 = __pyx_clineno; __pyx_t_26 = __pyx_filename; + { + + /* "_pydevd_bundle/pydevd_cython.pyx":585 + * finally: + * # Make sure the user cannot see the '__exception__' we added after we leave the suspend state. + * remove_exception_from_frame(frame) # <<<<<<<<<<<<<< + * # Clear some local variables... + * frame = None + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_remove_exception_from_frame); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 585, __pyx_L66_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_15 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_9, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 585, __pyx_L66_error) + __Pyx_GOTREF(__pyx_t_15); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":587 + * remove_exception_from_frame(frame) + * # Clear some local variables... + * frame = None # <<<<<<<<<<<<<< + * trace_obj = None + * initial_trace_obj = None + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_frame, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":588 + * # Clear some local variables... + * frame = None + * trace_obj = None # <<<<<<<<<<<<<< + * initial_trace_obj = None + * check_trace_obj = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":589 + * frame = None + * trace_obj = None + * initial_trace_obj = None # <<<<<<<<<<<<<< + * check_trace_obj = None + * f = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_initial_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":590 + * trace_obj = None + * initial_trace_obj = None + * check_trace_obj = None # <<<<<<<<<<<<<< + * f = None + * frame_id_to_frame = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_check_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":591 + * initial_trace_obj = None + * check_trace_obj = None + * f = None # <<<<<<<<<<<<<< + * frame_id_to_frame = None + * main_debugger = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_f, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":592 + * check_trace_obj = None + * f = None + * frame_id_to_frame = None # <<<<<<<<<<<<<< + * main_debugger = None + * thread = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_frame_id_to_frame, ((PyObject*)Py_None)); + + /* "_pydevd_bundle/pydevd_cython.pyx":593 + * f = None + * frame_id_to_frame = None + * main_debugger = None # <<<<<<<<<<<<<< + * thread = None + * + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_main_debugger, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":594 + * frame_id_to_frame = None + * main_debugger = None + * thread = None # <<<<<<<<<<<<<< + * + * return stopped + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_thread, Py_None); + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_25); + __Pyx_XGIVEREF(__pyx_t_24); + __Pyx_XGIVEREF(__pyx_t_23); + __Pyx_ExceptionReset(__pyx_t_25, __pyx_t_24, __pyx_t_23); + } + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ErrRestore(__pyx_t_10, __pyx_t_11, __pyx_t_12); + __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_25 = 0; __pyx_t_24 = 0; __pyx_t_23 = 0; + __pyx_lineno = __pyx_t_18; __pyx_clineno = __pyx_t_16; __pyx_filename = __pyx_t_26; + goto __pyx_L1_error; + __pyx_L66_error:; + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_25); + __Pyx_XGIVEREF(__pyx_t_24); + __Pyx_XGIVEREF(__pyx_t_23); + __Pyx_ExceptionReset(__pyx_t_25, __pyx_t_24, __pyx_t_23); + } + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __pyx_t_25 = 0; __pyx_t_24 = 0; __pyx_t_23 = 0; + goto __pyx_L1_error; + } + __pyx_L3_return: { + __pyx_t_23 = __pyx_r; + __pyx_r = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":585 + * finally: + * # Make sure the user cannot see the '__exception__' we added after we leave the suspend state. + * remove_exception_from_frame(frame) # <<<<<<<<<<<<<< + * # Clear some local variables... + * frame = None + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_remove_exception_from_frame); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 585, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_15 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_9, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 585, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_15); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":587 + * remove_exception_from_frame(frame) + * # Clear some local variables... + * frame = None # <<<<<<<<<<<<<< + * trace_obj = None + * initial_trace_obj = None + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_frame, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":588 + * # Clear some local variables... + * frame = None + * trace_obj = None # <<<<<<<<<<<<<< + * initial_trace_obj = None + * check_trace_obj = None + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":589 + * frame = None + * trace_obj = None + * initial_trace_obj = None # <<<<<<<<<<<<<< + * check_trace_obj = None + * f = None + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_initial_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":590 + * trace_obj = None + * initial_trace_obj = None + * check_trace_obj = None # <<<<<<<<<<<<<< + * f = None + * frame_id_to_frame = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_check_trace_obj, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":591 + * initial_trace_obj = None + * check_trace_obj = None + * f = None # <<<<<<<<<<<<<< + * frame_id_to_frame = None + * main_debugger = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_f, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":592 + * check_trace_obj = None + * f = None + * frame_id_to_frame = None # <<<<<<<<<<<<<< + * main_debugger = None + * thread = None + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_frame_id_to_frame, ((PyObject*)Py_None)); + + /* "_pydevd_bundle/pydevd_cython.pyx":593 + * f = None + * frame_id_to_frame = None + * main_debugger = None # <<<<<<<<<<<<<< + * thread = None + * + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_main_debugger, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":594 + * frame_id_to_frame = None + * main_debugger = None + * thread = None # <<<<<<<<<<<<<< + * + * return stopped + */ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_thread, Py_None); + __pyx_r = __pyx_t_23; + __pyx_t_23 = 0; + goto __pyx_L0; + } + __pyx_L5:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":596 + * thread = None + * + * return stopped # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_15 = __Pyx_PyBool_FromLong(__pyx_v_stopped); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 596, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_15); + __pyx_r = __pyx_t_15; + __pyx_t_15 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":470 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _handle_exception(self, frame, str event, arg, str exception_type): # <<<<<<<<<<<<<< + * cdef bint stopped; + * cdef tuple abs_real_path_and_base; + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_14); + __Pyx_XDECREF(__pyx_t_15); + __Pyx_XDECREF(__pyx_t_17); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._handle_exception", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_abs_real_path_and_base); + __Pyx_XDECREF(__pyx_v_absolute_filename); + __Pyx_XDECREF(__pyx_v_canonical_normalized_filename); + __Pyx_XDECREF(__pyx_v_filename_to_lines_where_exceptions_are_ignored); + __Pyx_XDECREF(__pyx_v_lines_ignored); + __Pyx_XDECREF(__pyx_v_frame_id_to_frame); + __Pyx_XDECREF(__pyx_v_merged); + __Pyx_XDECREF(__pyx_v_trace_obj); + __Pyx_XDECREF(__pyx_v_main_debugger); + __Pyx_XDECREF(__pyx_v_initial_trace_obj); + __Pyx_XDECREF(__pyx_v_check_trace_obj); + __Pyx_XDECREF(__pyx_v_curr_stat); + __Pyx_XDECREF(__pyx_v_last_stat); + __Pyx_XDECREF(__pyx_v_from_user_input); + __Pyx_XDECREF(__pyx_v_exc_lineno); + __Pyx_XDECREF(__pyx_v_line); + __Pyx_XDECREF(__pyx_v_thread); + __Pyx_XDECREF(__pyx_v_f); + __Pyx_XDECREF(__pyx_v_frame); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":599 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef get_func_name(self, frame): # <<<<<<<<<<<<<< + * cdef str func_name + * # ELSE + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_get_func_name(CYTHON_UNUSED struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame) { + PyObject *__pyx_v_func_name = 0; + PyObject *__pyx_v_code_obj = NULL; + PyObject *__pyx_v_cls_name = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + int __pyx_t_9; + int __pyx_t_10; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_func_name", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":604 + * # def get_func_name(self, frame): + * # ENDIF + * code_obj = frame.f_code # <<<<<<<<<<<<<< + * func_name = code_obj.co_name + * try: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 604, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_code_obj = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":605 + * # ENDIF + * code_obj = frame.f_code + * func_name = code_obj.co_name # <<<<<<<<<<<<<< + * try: + * cls_name = get_clsname_for_code(code_obj, frame) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_code_obj, __pyx_n_s_co_name); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 605, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 605, __pyx_L1_error) + __pyx_v_func_name = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":606 + * code_obj = frame.f_code + * func_name = code_obj.co_name + * try: # <<<<<<<<<<<<<< + * cls_name = get_clsname_for_code(code_obj, frame) + * if cls_name is not None: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":607 + * func_name = code_obj.co_name + * try: + * cls_name = get_clsname_for_code(code_obj, frame) # <<<<<<<<<<<<<< + * if cls_name is not None: + * return "%s.%s" % (cls_name, func_name) + */ + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_get_clsname_for_code); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 607, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = NULL; + __pyx_t_7 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + __pyx_t_7 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_5)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_code_obj, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 607, __pyx_L3_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_code_obj, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 607, __pyx_L3_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 607, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_6) { + __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL; + } + __Pyx_INCREF(__pyx_v_code_obj); + __Pyx_GIVEREF(__pyx_v_code_obj); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_v_code_obj); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_v_frame); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 607, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_v_cls_name = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":608 + * try: + * cls_name = get_clsname_for_code(code_obj, frame) + * if cls_name is not None: # <<<<<<<<<<<<<< + * return "%s.%s" % (cls_name, func_name) + * else: + */ + __pyx_t_9 = (__pyx_v_cls_name != Py_None); + __pyx_t_10 = (__pyx_t_9 != 0); + if (__pyx_t_10) { + + /* "_pydevd_bundle/pydevd_cython.pyx":609 + * cls_name = get_clsname_for_code(code_obj, frame) + * if cls_name is not None: + * return "%s.%s" % (cls_name, func_name) # <<<<<<<<<<<<<< + * else: + * return func_name + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 609, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_cls_name); + __Pyx_GIVEREF(__pyx_v_cls_name); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_cls_name); + __Pyx_INCREF(__pyx_v_func_name); + __Pyx_GIVEREF(__pyx_v_func_name); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_func_name); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_s_s, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 609, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L7_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":608 + * try: + * cls_name = get_clsname_for_code(code_obj, frame) + * if cls_name is not None: # <<<<<<<<<<<<<< + * return "%s.%s" % (cls_name, func_name) + * else: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":611 + * return "%s.%s" % (cls_name, func_name) + * else: + * return func_name # <<<<<<<<<<<<<< + * except: + * pydev_log.exception() + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_func_name); + __pyx_r = __pyx_v_func_name; + goto __pyx_L7_try_return; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":606 + * code_obj = frame.f_code + * func_name = code_obj.co_name + * try: # <<<<<<<<<<<<<< + * cls_name = get_clsname_for_code(code_obj, frame) + * if cls_name is not None: + */ + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":612 + * else: + * return func_name + * except: # <<<<<<<<<<<<<< + * pydev_log.exception() + * return func_name + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.get_func_name", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_1, &__pyx_t_8) < 0) __PYX_ERR(0, 612, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_8); + + /* "_pydevd_bundle/pydevd_cython.pyx":613 + * return func_name + * except: + * pydev_log.exception() # <<<<<<<<<<<<<< + * return func_name + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 613, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_11); + __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_n_s_exception); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 613, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; + __pyx_t_11 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_12))) { + __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_12); + if (likely(__pyx_t_11)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_12); + __Pyx_INCREF(__pyx_t_11); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_12, function); + } + } + __pyx_t_6 = (__pyx_t_11) ? __Pyx_PyObject_CallOneArg(__pyx_t_12, __pyx_t_11) : __Pyx_PyObject_CallNoArg(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 613, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":614 + * except: + * pydev_log.exception() + * return func_name # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_func_name); + __pyx_r = __pyx_v_func_name; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L6_except_return; + } + __pyx_L5_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":606 + * code_obj = frame.f_code + * func_name = code_obj.co_name + * try: # <<<<<<<<<<<<<< + * cls_name = get_clsname_for_code(code_obj, frame) + * if cls_name is not None: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L7_try_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":599 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef get_func_name(self, frame): # <<<<<<<<<<<<<< + * cdef str func_name + * # ELSE + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_11); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.get_func_name", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_func_name); + __Pyx_XDECREF(__pyx_v_code_obj); + __Pyx_XDECREF(__pyx_v_cls_name); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":617 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _show_return_values(self, frame, arg): # <<<<<<<<<<<<<< + * # ELSE + * # def _show_return_values(self, frame, arg): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__show_return_values(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_arg) { + PyObject *__pyx_v_f_locals_back = NULL; + PyObject *__pyx_v_return_values_dict = NULL; + PyObject *__pyx_v_name = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + int __pyx_t_10; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + int __pyx_t_13; + char const *__pyx_t_14; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_show_return_values", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":621 + * # def _show_return_values(self, frame, arg): + * # ENDIF + * try: # <<<<<<<<<<<<<< + * try: + * f_locals_back = getattr(frame.f_back, "f_locals", None) + */ + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":622 + * # ENDIF + * try: + * try: # <<<<<<<<<<<<<< + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":623 + * try: + * try: + * f_locals_back = getattr(frame.f_back, "f_locals", None) # <<<<<<<<<<<<<< + * if f_locals_back is not None: + * return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 623, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_GetAttr3(__pyx_t_4, __pyx_n_s_f_locals, Py_None); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 623, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_f_locals_back = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":624 + * try: + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: # <<<<<<<<<<<<<< + * return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) + * if return_values_dict is None: + */ + __pyx_t_6 = (__pyx_v_f_locals_back != Py_None); + __pyx_t_7 = (__pyx_t_6 != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":625 + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: + * return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) # <<<<<<<<<<<<<< + * if return_values_dict is None: + * return_values_dict = {} + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_locals_back, __pyx_n_s_get); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 625, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_RETURN_VALUES_DICT); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 625, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_9 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_8, Py_None}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 625, __pyx_L6_error) + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_8, Py_None}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 625, __pyx_L6_error) + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else + #endif + { + __pyx_t_11 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 625, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_11); + if (__pyx_t_9) { + __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_9); __pyx_t_9 = NULL; + } + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_11, 0+__pyx_t_10, __pyx_t_8); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_11, 1+__pyx_t_10, Py_None); + __pyx_t_8 = 0; + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_11, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 625, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_return_values_dict = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":626 + * if f_locals_back is not None: + * return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) + * if return_values_dict is None: # <<<<<<<<<<<<<< + * return_values_dict = {} + * f_locals_back[RETURN_VALUES_DICT] = return_values_dict + */ + __pyx_t_7 = (__pyx_v_return_values_dict == Py_None); + __pyx_t_6 = (__pyx_t_7 != 0); + if (__pyx_t_6) { + + /* "_pydevd_bundle/pydevd_cython.pyx":627 + * return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) + * if return_values_dict is None: + * return_values_dict = {} # <<<<<<<<<<<<<< + * f_locals_back[RETURN_VALUES_DICT] = return_values_dict + * name = self.get_func_name(frame) + */ + __pyx_t_5 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 627, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF_SET(__pyx_v_return_values_dict, __pyx_t_5); + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":628 + * if return_values_dict is None: + * return_values_dict = {} + * f_locals_back[RETURN_VALUES_DICT] = return_values_dict # <<<<<<<<<<<<<< + * name = self.get_func_name(frame) + * return_values_dict[name] = arg + */ + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_RETURN_VALUES_DICT); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 628, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + if (unlikely(PyObject_SetItem(__pyx_v_f_locals_back, __pyx_t_5, __pyx_v_return_values_dict) < 0)) __PYX_ERR(0, 628, __pyx_L6_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":626 + * if f_locals_back is not None: + * return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) + * if return_values_dict is None: # <<<<<<<<<<<<<< + * return_values_dict = {} + * f_locals_back[RETURN_VALUES_DICT] = return_values_dict + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":629 + * return_values_dict = {} + * f_locals_back[RETURN_VALUES_DICT] = return_values_dict + * name = self.get_func_name(frame) # <<<<<<<<<<<<<< + * return_values_dict[name] = arg + * except: + */ + __pyx_t_5 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->get_func_name(__pyx_v_self, __pyx_v_frame); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 629, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_name = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":630 + * f_locals_back[RETURN_VALUES_DICT] = return_values_dict + * name = self.get_func_name(frame) + * return_values_dict[name] = arg # <<<<<<<<<<<<<< + * except: + * pydev_log.exception() + */ + if (unlikely(PyObject_SetItem(__pyx_v_return_values_dict, __pyx_v_name, __pyx_v_arg) < 0)) __PYX_ERR(0, 630, __pyx_L6_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":624 + * try: + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: # <<<<<<<<<<<<<< + * return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) + * if return_values_dict is None: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":622 + * # ENDIF + * try: + * try: # <<<<<<<<<<<<<< + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L11_try_end; + __pyx_L6_error:; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":631 + * name = self.get_func_name(frame) + * return_values_dict[name] = arg + * except: # <<<<<<<<<<<<<< + * pydev_log.exception() + * finally: + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._show_return_values", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_4, &__pyx_t_11) < 0) __PYX_ERR(0, 631, __pyx_L8_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_11); + + /* "_pydevd_bundle/pydevd_cython.pyx":632 + * return_values_dict[name] = arg + * except: + * pydev_log.exception() # <<<<<<<<<<<<<< + * finally: + * f_locals_back = None + */ + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 632, __pyx_L8_except_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_exception); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 632, __pyx_L8_except_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_12))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_12); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_12); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_12, function); + } + } + __pyx_t_8 = (__pyx_t_9) ? __Pyx_PyObject_CallOneArg(__pyx_t_12, __pyx_t_9) : __Pyx_PyObject_CallNoArg(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 632, __pyx_L8_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + goto __pyx_L7_exception_handled; + } + __pyx_L8_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":622 + * # ENDIF + * try: + * try: # <<<<<<<<<<<<<< + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L4_error; + __pyx_L7_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + __pyx_L11_try_end:; + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":634 + * pydev_log.exception() + * finally: + * f_locals_back = None # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + /*finally:*/ { + /*normal exit:*/{ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_f_locals_back, Py_None); + goto __pyx_L5; + } + __pyx_L4_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_3 = 0; __pyx_t_2 = 0; __pyx_t_1 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1) < 0)) __Pyx_ErrFetch(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __pyx_t_10 = __pyx_lineno; __pyx_t_13 = __pyx_clineno; __pyx_t_14 = __pyx_filename; + { + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_f_locals_back, Py_None); + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_ExceptionReset(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_ErrRestore(__pyx_t_3, __pyx_t_2, __pyx_t_1); + __pyx_t_3 = 0; __pyx_t_2 = 0; __pyx_t_1 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __pyx_lineno = __pyx_t_10; __pyx_clineno = __pyx_t_13; __pyx_filename = __pyx_t_14; + goto __pyx_L1_error; + } + __pyx_L5:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":617 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _show_return_values(self, frame, arg): # <<<<<<<<<<<<<< + * # ELSE + * # def _show_return_values(self, frame, arg): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_11); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._show_return_values", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_f_locals_back); + __Pyx_XDECREF(__pyx_v_return_values_dict); + __Pyx_XDECREF(__pyx_v_name); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":637 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _remove_return_values(self, main_debugger, frame): # <<<<<<<<<<<<<< + * # ELSE + * # def _remove_return_values(self, main_debugger, frame): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__remove_return_values(CYTHON_UNUSED struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v_main_debugger, PyObject *__pyx_v_frame) { + PyObject *__pyx_v_f_locals_back = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + int __pyx_t_8; + PyObject *__pyx_t_9 = NULL; + int __pyx_t_10; + int __pyx_t_11; + PyObject *__pyx_t_12 = NULL; + int __pyx_t_13; + char const *__pyx_t_14; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_remove_return_values", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":641 + * # def _remove_return_values(self, main_debugger, frame): + * # ENDIF + * try: # <<<<<<<<<<<<<< + * try: + * # Showing return values was turned off, we should remove them from locals dict. + */ + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":642 + * # ENDIF + * try: + * try: # <<<<<<<<<<<<<< + * # Showing return values was turned off, we should remove them from locals dict. + * # The values can be in the current frame or in the back one + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":645 + * # Showing return values was turned off, we should remove them from locals dict. + * # The values can be in the current frame or in the back one + * frame.f_locals.pop(RETURN_VALUES_DICT, None) # <<<<<<<<<<<<<< + * + * f_locals_back = getattr(frame.f_back, "f_locals", None) + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_locals); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 645, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_pop); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 645, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_RETURN_VALUES_DICT); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 645, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_7 = NULL; + __pyx_t_8 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + __pyx_t_8 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_t_5, Py_None}; + __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 645, __pyx_L6_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_t_5, Py_None}; + __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 645, __pyx_L6_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } else + #endif + { + __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 645, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_9); + if (__pyx_t_7) { + __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL; + } + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_9, 0+__pyx_t_8, __pyx_t_5); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_8, Py_None); + __pyx_t_5 = 0; + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_9, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 645, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":647 + * frame.f_locals.pop(RETURN_VALUES_DICT, None) + * + * f_locals_back = getattr(frame.f_back, "f_locals", None) # <<<<<<<<<<<<<< + * if f_locals_back is not None: + * f_locals_back.pop(RETURN_VALUES_DICT, None) + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 647, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = __Pyx_GetAttr3(__pyx_t_4, __pyx_n_s_f_locals, Py_None); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 647, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_f_locals_back = __pyx_t_6; + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":648 + * + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: # <<<<<<<<<<<<<< + * f_locals_back.pop(RETURN_VALUES_DICT, None) + * except: + */ + __pyx_t_10 = (__pyx_v_f_locals_back != Py_None); + __pyx_t_11 = (__pyx_t_10 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":649 + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: + * f_locals_back.pop(RETURN_VALUES_DICT, None) # <<<<<<<<<<<<<< + * except: + * pydev_log.exception() + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_locals_back, __pyx_n_s_pop); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 649, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_RETURN_VALUES_DICT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 649, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_5 = NULL; + __pyx_t_8 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_8 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_9, Py_None}; + __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 649, __pyx_L6_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_9, Py_None}; + __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 649, __pyx_L6_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } else + #endif + { + __pyx_t_7 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 649, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_5) { + __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL; + } + __Pyx_GIVEREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_8, __pyx_t_9); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_8, Py_None); + __pyx_t_9 = 0; + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 649, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":648 + * + * f_locals_back = getattr(frame.f_back, "f_locals", None) + * if f_locals_back is not None: # <<<<<<<<<<<<<< + * f_locals_back.pop(RETURN_VALUES_DICT, None) + * except: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":642 + * # ENDIF + * try: + * try: # <<<<<<<<<<<<<< + * # Showing return values was turned off, we should remove them from locals dict. + * # The values can be in the current frame or in the back one + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L11_try_end; + __pyx_L6_error:; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":650 + * if f_locals_back is not None: + * f_locals_back.pop(RETURN_VALUES_DICT, None) + * except: # <<<<<<<<<<<<<< + * pydev_log.exception() + * finally: + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._remove_return_values", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_4, &__pyx_t_7) < 0) __PYX_ERR(0, 650, __pyx_L8_except_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_7); + + /* "_pydevd_bundle/pydevd_cython.pyx":651 + * f_locals_back.pop(RETURN_VALUES_DICT, None) + * except: + * pydev_log.exception() # <<<<<<<<<<<<<< + * finally: + * f_locals_back = None + */ + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 651, __pyx_L8_except_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_exception); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 651, __pyx_L8_except_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_12))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_12); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_12); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_12, function); + } + } + __pyx_t_9 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_12, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 651, __pyx_L8_except_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L7_exception_handled; + } + __pyx_L8_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":642 + * # ENDIF + * try: + * try: # <<<<<<<<<<<<<< + * # Showing return values was turned off, we should remove them from locals dict. + * # The values can be in the current frame or in the back one + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L4_error; + __pyx_L7_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + __pyx_L11_try_end:; + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":653 + * pydev_log.exception() + * finally: + * f_locals_back = None # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + /*finally:*/ { + /*normal exit:*/{ + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_f_locals_back, Py_None); + goto __pyx_L5; + } + __pyx_L4_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_3 = 0; __pyx_t_2 = 0; __pyx_t_1 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1) < 0)) __Pyx_ErrFetch(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __pyx_t_8 = __pyx_lineno; __pyx_t_13 = __pyx_clineno; __pyx_t_14 = __pyx_filename; + { + __Pyx_INCREF(Py_None); + __Pyx_XDECREF_SET(__pyx_v_f_locals_back, Py_None); + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_ExceptionReset(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_ErrRestore(__pyx_t_3, __pyx_t_2, __pyx_t_1); + __pyx_t_3 = 0; __pyx_t_2 = 0; __pyx_t_1 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __pyx_lineno = __pyx_t_8; __pyx_clineno = __pyx_t_13; __pyx_filename = __pyx_t_14; + goto __pyx_L1_error; + } + __pyx_L5:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":637 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _remove_return_values(self, main_debugger, frame): # <<<<<<<<<<<<<< + * # ELSE + * # def _remove_return_values(self, main_debugger, frame): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._remove_return_values", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_f_locals_back); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":656 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _get_unfiltered_back_frame(self, main_debugger, frame): # <<<<<<<<<<<<<< + * # ELSE + * # def _get_unfiltered_back_frame(self, main_debugger, frame): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__get_unfiltered_back_frame(CYTHON_UNUSED struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_main_debugger, PyObject *__pyx_v_frame) { + PyObject *__pyx_v_f = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_get_unfiltered_back_frame", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":660 + * # def _get_unfiltered_back_frame(self, main_debugger, frame): + * # ENDIF + * f = frame.f_back # <<<<<<<<<<<<<< + * while f is not None: + * if not main_debugger.is_files_filter_enabled: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 660, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_f = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":661 + * # ENDIF + * f = frame.f_back + * while f is not None: # <<<<<<<<<<<<<< + * if not main_debugger.is_files_filter_enabled: + * return f + */ + while (1) { + __pyx_t_2 = (__pyx_v_f != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (!__pyx_t_3) break; + + /* "_pydevd_bundle/pydevd_cython.pyx":662 + * f = frame.f_back + * while f is not None: + * if not main_debugger.is_files_filter_enabled: # <<<<<<<<<<<<<< + * return f + * + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_is_files_filter_enabled); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 662, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 662, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_2 = ((!__pyx_t_3) != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":663 + * while f is not None: + * if not main_debugger.is_files_filter_enabled: + * return f # <<<<<<<<<<<<<< + * + * else: + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_f); + __pyx_r = __pyx_v_f; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":662 + * f = frame.f_back + * while f is not None: + * if not main_debugger.is_files_filter_enabled: # <<<<<<<<<<<<<< + * return f + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":666 + * + * else: + * if main_debugger.apply_files_filter(f, f.f_code.co_filename, False): # <<<<<<<<<<<<<< + * f = f.f_back + * + */ + /*else*/ { + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 666, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_code); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 666, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 666, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = NULL; + __pyx_t_7 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_7 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_v_f, __pyx_t_6, Py_False}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 666, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_v_f, __pyx_t_6, Py_False}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 666, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + { + __pyx_t_8 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 666, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_5) { + __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL; + } + __Pyx_INCREF(__pyx_v_f); + __Pyx_GIVEREF(__pyx_v_f); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_v_f); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_6); + __Pyx_INCREF(Py_False); + __Pyx_GIVEREF(Py_False); + PyTuple_SET_ITEM(__pyx_t_8, 2+__pyx_t_7, Py_False); + __pyx_t_6 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 666, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 666, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":667 + * else: + * if main_debugger.apply_files_filter(f, f.f_code.co_filename, False): + * f = f.f_back # <<<<<<<<<<<<<< + * + * else: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 667, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_f, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":666 + * + * else: + * if main_debugger.apply_files_filter(f, f.f_code.co_filename, False): # <<<<<<<<<<<<<< + * f = f.f_back + * + */ + goto __pyx_L6; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":670 + * + * else: + * return f # <<<<<<<<<<<<<< + * + * return f + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_f); + __pyx_r = __pyx_v_f; + goto __pyx_L0; + } + __pyx_L6:; + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":672 + * return f + * + * return f # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_f); + __pyx_r = __pyx_v_f; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":656 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _get_unfiltered_back_frame(self, main_debugger, frame): # <<<<<<<<<<<<<< + * # ELSE + * # def _get_unfiltered_back_frame(self, main_debugger, frame): + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._get_unfiltered_back_frame", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_f); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":675 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _is_same_frame(self, target_frame, current_frame): # <<<<<<<<<<<<<< + * cdef PyDBAdditionalThreadInfo info; + * # ELSE + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__is_same_frame(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_target_frame, PyObject *__pyx_v_current_frame) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_info = 0; + PyObject *__pyx_v_f = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_is_same_frame", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":680 + * # def _is_same_frame(self, target_frame, current_frame): + * # ENDIF + * if target_frame is current_frame: # <<<<<<<<<<<<<< + * return True + * + */ + __pyx_t_1 = (__pyx_v_target_frame == __pyx_v_current_frame); + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":681 + * # ENDIF + * if target_frame is current_frame: + * return True # <<<<<<<<<<<<<< + * + * info = self._args[2] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_True); + __pyx_r = Py_True; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":680 + * # def _is_same_frame(self, target_frame, current_frame): + * # ENDIF + * if target_frame is current_frame: # <<<<<<<<<<<<<< + * return True + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":683 + * return True + * + * info = self._args[2] # <<<<<<<<<<<<<< + * if info.pydev_use_scoped_step_frame: + * # If using scoped step we don't check the target, we just need to check + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 683, __pyx_L1_error) + } + __pyx_t_3 = __Pyx_GetItemInt_Tuple(__pyx_v_self->_args, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 683, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo))))) __PYX_ERR(0, 683, __pyx_L1_error) + __pyx_v_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_3); + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":684 + * + * info = self._args[2] + * if info.pydev_use_scoped_step_frame: # <<<<<<<<<<<<<< + * # If using scoped step we don't check the target, we just need to check + * # if the current matches the same heuristic where the target was defined. + */ + __pyx_t_2 = (__pyx_v_info->pydev_use_scoped_step_frame != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":687 + * # If using scoped step we don't check the target, we just need to check + * # if the current matches the same heuristic where the target was defined. + * if target_frame is not None and current_frame is not None: # <<<<<<<<<<<<<< + * if target_frame.f_code.co_filename == current_frame.f_code.co_filename: + * # The co_name may be different (it may include the line number), but + */ + __pyx_t_1 = (__pyx_v_target_frame != Py_None); + __pyx_t_4 = (__pyx_t_1 != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L6_bool_binop_done; + } + __pyx_t_4 = (__pyx_v_current_frame != Py_None); + __pyx_t_1 = (__pyx_t_4 != 0); + __pyx_t_2 = __pyx_t_1; + __pyx_L6_bool_binop_done:; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":688 + * # if the current matches the same heuristic where the target was defined. + * if target_frame is not None and current_frame is not None: + * if target_frame.f_code.co_filename == current_frame.f_code.co_filename: # <<<<<<<<<<<<<< + * # The co_name may be different (it may include the line number), but + * # the filename must still be the same. + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_target_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 688, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 688, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_current_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 688, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 688, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_t_6, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 688, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 688, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":691 + * # The co_name may be different (it may include the line number), but + * # the filename must still be the same. + * f = current_frame.f_back # <<<<<<<<<<<<<< + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + * f = f.f_back + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_current_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 691, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_v_f = __pyx_t_3; + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":692 + * # the filename must still be the same. + * f = current_frame.f_back + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: # <<<<<<<<<<<<<< + * f = f.f_back + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + */ + __pyx_t_1 = (__pyx_v_f != Py_None); + __pyx_t_4 = (__pyx_t_1 != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L10_bool_binop_done; + } + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 692, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 692, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_PYDEVD_IPYTHON_CONTEXT); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 692, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = __Pyx_GetItemInt(__pyx_t_3, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 692, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_RichCompare(__pyx_t_6, __pyx_t_5, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 692, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 692, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = __pyx_t_4; + __pyx_L10_bool_binop_done:; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":693 + * f = current_frame.f_back + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + * f = f.f_back # <<<<<<<<<<<<<< + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + * return True + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_back); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 693, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF_SET(__pyx_v_f, __pyx_t_3); + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":694 + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + * f = f.f_back + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: # <<<<<<<<<<<<<< + * return True + * + */ + __pyx_t_4 = (__pyx_v_f != Py_None); + __pyx_t_1 = (__pyx_t_4 != 0); + if (__pyx_t_1) { + } else { + __pyx_t_2 = __pyx_t_1; + goto __pyx_L13_bool_binop_done; + } + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 694, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_name); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 694, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_PYDEVD_IPYTHON_CONTEXT); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 694, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_3, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 694, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_t_6, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 694, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 694, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = __pyx_t_1; + __pyx_L13_bool_binop_done:; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":695 + * f = f.f_back + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + * return True # <<<<<<<<<<<<<< + * + * return False + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_True); + __pyx_r = Py_True; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":694 + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + * f = f.f_back + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: # <<<<<<<<<<<<<< + * return True + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":692 + * # the filename must still be the same. + * f = current_frame.f_back + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: # <<<<<<<<<<<<<< + * f = f.f_back + * if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":688 + * # if the current matches the same heuristic where the target was defined. + * if target_frame is not None and current_frame is not None: + * if target_frame.f_code.co_filename == current_frame.f_code.co_filename: # <<<<<<<<<<<<<< + * # The co_name may be different (it may include the line number), but + * # the filename must still be the same. + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":687 + * # If using scoped step we don't check the target, we just need to check + * # if the current matches the same heuristic where the target was defined. + * if target_frame is not None and current_frame is not None: # <<<<<<<<<<<<<< + * if target_frame.f_code.co_filename == current_frame.f_code.co_filename: + * # The co_name may be different (it may include the line number), but + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":684 + * + * info = self._args[2] + * if info.pydev_use_scoped_step_frame: # <<<<<<<<<<<<<< + * # If using scoped step we don't check the target, we just need to check + * # if the current matches the same heuristic where the target was defined. + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":697 + * return True + * + * return False # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_False); + __pyx_r = Py_False; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":675 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef _is_same_frame(self, target_frame, current_frame): # <<<<<<<<<<<<<< + * cdef PyDBAdditionalThreadInfo info; + * # ELSE + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame._is_same_frame", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_info); + __Pyx_XDECREF(__pyx_v_f); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":700 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cpdef trace_dispatch(self, frame, str event, arg): # <<<<<<<<<<<<<< + * cdef tuple abs_path_canonical_path_and_base; + * cdef bint is_exception_event; + */ + +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_11trace_dispatch(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_trace_dispatch(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg, int __pyx_skip_dispatch) { + PyObject *__pyx_v_abs_path_canonical_path_and_base = 0; + int __pyx_v_is_exception_event; + int __pyx_v_has_exception_breakpoints; + int __pyx_v_can_skip; + int __pyx_v_stop; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_info = 0; + int __pyx_v_step_cmd; + int __pyx_v_line; + int __pyx_v_is_line; + int __pyx_v_is_call; + int __pyx_v_is_return; + int __pyx_v_should_stop; + PyObject *__pyx_v_breakpoints_for_file = 0; + PyObject *__pyx_v_stop_info = 0; + PyObject *__pyx_v_curr_func_name = 0; + int __pyx_v_exist_result; + PyObject *__pyx_v_frame_skips_cache = 0; + PyObject *__pyx_v_frame_cache_key = 0; + PyObject *__pyx_v_line_cache_key = 0; + int __pyx_v_breakpoints_in_line_cache; + int __pyx_v_breakpoints_in_frame_cache; + int __pyx_v_has_breakpoint_in_frame; + int __pyx_v_bp_line; + PyObject *__pyx_v_bp = 0; + int __pyx_v_pydev_smart_parent_offset; + int __pyx_v_pydev_smart_child_offset; + PyObject *__pyx_v_pydev_smart_step_into_variants = 0; + PyObject *__pyx_v_main_debugger = NULL; + PyObject *__pyx_v_thread = NULL; + PyObject *__pyx_v_plugin_manager = NULL; + PyObject *__pyx_v_stop_frame = NULL; + PyObject *__pyx_v_function_breakpoint_on_call_event = NULL; + PyObject *__pyx_v_returns_cache_key = NULL; + PyObject *__pyx_v_return_lines = NULL; + PyObject *__pyx_v_x = NULL; + PyObject *__pyx_v_f = NULL; + PyObject *__pyx_v_func_lines = NULL; + PyObject *__pyx_v_offset_and_lineno = NULL; + PyObject *__pyx_v_flag = NULL; + PyObject *__pyx_v_breakpoint = NULL; + PyObject *__pyx_v_stop_reason = NULL; + PyObject *__pyx_v_bp_type = NULL; + PyObject *__pyx_v_new_frame = NULL; + PyObject *__pyx_v_result = NULL; + PyObject *__pyx_v_cmd = NULL; + PyObject *__pyx_v_eval_result = NULL; + long __pyx_v_should_skip; + PyObject *__pyx_v_plugin_stop = NULL; + PyObject *__pyx_v_force_check_project_scope = NULL; + PyObject *__pyx_v_filename = NULL; + PyObject *__pyx_v_f2 = NULL; + PyObject *__pyx_v_back = NULL; + PyObject *__pyx_v_smart_step_into_variant = NULL; + PyObject *__pyx_v_children_variants = NULL; + PyObject *__pyx_v_f_code = NULL; + CYTHON_UNUSED PyObject *__pyx_v_stopped_on_plugin = NULL; + PyObject *__pyx_v_back_absolute_filename = NULL; + CYTHON_UNUSED PyObject *__pyx_v__ = NULL; + PyObject *__pyx_v_base = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_t_9; + int __pyx_t_10; + int __pyx_t_11; + Py_ssize_t __pyx_t_12; + PyObject *(*__pyx_t_13)(PyObject *); + int __pyx_t_14; + PyObject *(*__pyx_t_15)(PyObject *); + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + PyObject *__pyx_t_18 = NULL; + int __pyx_t_19; + Py_ssize_t __pyx_t_20; + PyObject *__pyx_t_21 = NULL; + char const *__pyx_t_22; + PyObject *__pyx_t_23 = NULL; + PyObject *__pyx_t_24 = NULL; + PyObject *__pyx_t_25 = NULL; + PyObject *__pyx_t_26 = NULL; + PyObject *__pyx_t_27 = NULL; + PyObject *__pyx_t_28 = NULL; + int __pyx_t_29; + PyObject *__pyx_t_30 = NULL; + char const *__pyx_t_31; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("trace_dispatch", 0); + __Pyx_INCREF(__pyx_v_frame); + /* Check if called by wrapper */ + if (unlikely(__pyx_skip_dispatch)) ; + /* Check if overridden in Python */ + else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) { + #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS + static PY_UINT64_T __pyx_tp_dict_version = __PYX_DICT_VERSION_INIT, __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT; + if (unlikely(!__Pyx_object_dict_version_matches(((PyObject *)__pyx_v_self), __pyx_tp_dict_version, __pyx_obj_dict_version))) { + PY_UINT64_T __pyx_type_dict_guard = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self)); + #endif + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 700, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_11trace_dispatch)) { + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_t_1); + __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[4] = {__pyx_t_4, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 700, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_2); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[4] = {__pyx_t_4, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 700, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_2); + } else + #endif + { + __pyx_t_6 = PyTuple_New(3+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 700, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __pyx_t_4 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_5, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_6, 2+__pyx_t_5, __pyx_v_arg); + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 700, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L0; + } + #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS + __pyx_tp_dict_version = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self)); + __pyx_obj_dict_version = __Pyx_get_object_dict_version(((PyObject *)__pyx_v_self)); + if (unlikely(__pyx_type_dict_guard != __pyx_tp_dict_version)) { + __pyx_tp_dict_version = __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT; + } + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS + } + #endif + } + + /* "_pydevd_bundle/pydevd_cython.pyx":741 + * + * # DEBUG = '_debugger_case_generator.py' in frame.f_code.co_filename + * main_debugger, abs_path_canonical_path_and_base, info, thread, frame_skips_cache, frame_cache_key = self._args # <<<<<<<<<<<<<< + * # if DEBUG: print('frame trace_dispatch %s %s %s %s %s %s, stop: %s' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event, constant_to_str(info.pydev_step_cmd), arg, info.pydev_step_stop)) + * try: + */ + __pyx_t_1 = __pyx_v_self->_args; + __Pyx_INCREF(__pyx_t_1); + if (likely(__pyx_t_1 != Py_None)) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 6)) { + if (size > 6) __Pyx_RaiseTooManyValuesError(6); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 741, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 4); + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 5); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + #else + { + Py_ssize_t i; + PyObject** temps[6] = {&__pyx_t_2,&__pyx_t_3,&__pyx_t_6,&__pyx_t_4,&__pyx_t_7,&__pyx_t_8}; + for (i=0; i < 6; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 741, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 741, __pyx_L1_error) + } + if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 741, __pyx_L1_error) + if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo))))) __PYX_ERR(0, 741, __pyx_L1_error) + if (!(likely(PyDict_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 741, __pyx_L1_error) + __pyx_v_main_debugger = __pyx_t_2; + __pyx_t_2 = 0; + __pyx_v_abs_path_canonical_path_and_base = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + __pyx_v_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_6); + __pyx_t_6 = 0; + __pyx_v_thread = __pyx_t_4; + __pyx_t_4 = 0; + __pyx_v_frame_skips_cache = ((PyObject*)__pyx_t_7); + __pyx_t_7 = 0; + __pyx_v_frame_cache_key = __pyx_t_8; + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":743 + * main_debugger, abs_path_canonical_path_and_base, info, thread, frame_skips_cache, frame_cache_key = self._args + * # if DEBUG: print('frame trace_dispatch %s %s %s %s %s %s, stop: %s' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event, constant_to_str(info.pydev_step_cmd), arg, info.pydev_step_stop)) + * try: # <<<<<<<<<<<<<< + * info.is_tracing += 1 + * + */ + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":744 + * # if DEBUG: print('frame trace_dispatch %s %s %s %s %s %s, stop: %s' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event, constant_to_str(info.pydev_step_cmd), arg, info.pydev_step_stop)) + * try: + * info.is_tracing += 1 # <<<<<<<<<<<<<< + * + * # TODO: This shouldn't be needed. The fact that frame.f_lineno + */ + __pyx_v_info->is_tracing = (__pyx_v_info->is_tracing + 1); + + /* "_pydevd_bundle/pydevd_cython.pyx":749 + * # is None seems like a bug in Python 3.11. + * # Reported in: https://github.com/python/cpython/issues/94485 + * line = frame.f_lineno or 0 # Workaround or case where frame.f_lineno is None # <<<<<<<<<<<<<< + * line_cache_key = (frame_cache_key, line) + * + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 749, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 749, __pyx_L4_error) + if (!__pyx_t_9) { + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + __pyx_t_10 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_10 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 749, __pyx_L4_error) + __pyx_t_5 = __pyx_t_10; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L6_bool_binop_done; + } + __pyx_t_5 = 0; + __pyx_L6_bool_binop_done:; + __pyx_v_line = __pyx_t_5; + + /* "_pydevd_bundle/pydevd_cython.pyx":750 + * # Reported in: https://github.com/python/cpython/issues/94485 + * line = frame.f_lineno or 0 # Workaround or case where frame.f_lineno is None + * line_cache_key = (frame_cache_key, line) # <<<<<<<<<<<<<< + * + * if main_debugger.pydb_disposed: + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 750, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 750, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_INCREF(__pyx_v_frame_cache_key); + __Pyx_GIVEREF(__pyx_v_frame_cache_key); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_frame_cache_key); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1); + __pyx_t_1 = 0; + __pyx_v_line_cache_key = ((PyObject*)__pyx_t_8); + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":752 + * line_cache_key = (frame_cache_key, line) + * + * if main_debugger.pydb_disposed: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_pydb_disposed); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 752, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 752, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":753 + * + * if main_debugger.pydb_disposed: + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * + * plugin_manager = main_debugger.plugin + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_9 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 753, __pyx_L4_error) + if ((__pyx_t_9 != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_8 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 753, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = __pyx_t_1; + __pyx_t_1 = 0; + } + __pyx_r = __pyx_t_8; + __pyx_t_8 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":752 + * line_cache_key = (frame_cache_key, line) + * + * if main_debugger.pydb_disposed: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":755 + * return None if event == 'call' else NO_FTRACE + * + * plugin_manager = main_debugger.plugin # <<<<<<<<<<<<<< + * has_exception_breakpoints = ( + * main_debugger.break_on_caught_exceptions + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_plugin); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 755, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_v_plugin_manager = __pyx_t_8; + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":757 + * plugin_manager = main_debugger.plugin + * has_exception_breakpoints = ( + * main_debugger.break_on_caught_exceptions # <<<<<<<<<<<<<< + * or main_debugger.break_on_user_uncaught_exceptions + * or main_debugger.has_plugin_exception_breaks) + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_break_on_caught_exceptions); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 757, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 757, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (!__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L9_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":758 + * has_exception_breakpoints = ( + * main_debugger.break_on_caught_exceptions + * or main_debugger.break_on_user_uncaught_exceptions # <<<<<<<<<<<<<< + * or main_debugger.has_plugin_exception_breaks) + * + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_break_on_user_uncaught_exception); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 758, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 758, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (!__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L9_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":759 + * main_debugger.break_on_caught_exceptions + * or main_debugger.break_on_user_uncaught_exceptions + * or main_debugger.has_plugin_exception_breaks) # <<<<<<<<<<<<<< + * + * stop_frame = info.pydev_step_stop + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_exception_breaks); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 759, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 759, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_9 = __pyx_t_11; + __pyx_L9_bool_binop_done:; + __pyx_v_has_exception_breakpoints = __pyx_t_9; + + /* "_pydevd_bundle/pydevd_cython.pyx":761 + * or main_debugger.has_plugin_exception_breaks) + * + * stop_frame = info.pydev_step_stop # <<<<<<<<<<<<<< + * step_cmd = info.pydev_step_cmd + * function_breakpoint_on_call_event = None + */ + __pyx_t_8 = __pyx_v_info->pydev_step_stop; + __Pyx_INCREF(__pyx_t_8); + __pyx_v_stop_frame = __pyx_t_8; + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":762 + * + * stop_frame = info.pydev_step_stop + * step_cmd = info.pydev_step_cmd # <<<<<<<<<<<<<< + * function_breakpoint_on_call_event = None + * + */ + __pyx_t_5 = __pyx_v_info->pydev_step_cmd; + __pyx_v_step_cmd = __pyx_t_5; + + /* "_pydevd_bundle/pydevd_cython.pyx":763 + * stop_frame = info.pydev_step_stop + * step_cmd = info.pydev_step_cmd + * function_breakpoint_on_call_event = None # <<<<<<<<<<<<<< + * + * if frame.f_code.co_flags & 0xa0: # 0xa0 == CO_GENERATOR = 0x20 | CO_COROUTINE = 0x80 + */ + __Pyx_INCREF(Py_None); + __pyx_v_function_breakpoint_on_call_event = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":765 + * function_breakpoint_on_call_event = None + * + * if frame.f_code.co_flags & 0xa0: # 0xa0 == CO_GENERATOR = 0x20 | CO_COROUTINE = 0x80 # <<<<<<<<<<<<<< + * # Dealing with coroutines and generators: + * # When in a coroutine we change the perceived event to the debugger because + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 765, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_co_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 765, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = __Pyx_PyInt_AndObjC(__pyx_t_1, __pyx_int_160, 0xa0, 0, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 765, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 765, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":769 + * # When in a coroutine we change the perceived event to the debugger because + * # a call, StopIteration exception and return are usually just pausing/unpausing it. + * if event == 'line': # <<<<<<<<<<<<<< + * is_line = True + * is_call = False + */ + __pyx_t_9 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_line, Py_EQ)); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 769, __pyx_L4_error) + __pyx_t_11 = (__pyx_t_9 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":770 + * # a call, StopIteration exception and return are usually just pausing/unpausing it. + * if event == 'line': + * is_line = True # <<<<<<<<<<<<<< + * is_call = False + * is_return = False + */ + __pyx_v_is_line = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":771 + * if event == 'line': + * is_line = True + * is_call = False # <<<<<<<<<<<<<< + * is_return = False + * is_exception_event = False + */ + __pyx_v_is_call = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":772 + * is_line = True + * is_call = False + * is_return = False # <<<<<<<<<<<<<< + * is_exception_event = False + * + */ + __pyx_v_is_return = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":773 + * is_call = False + * is_return = False + * is_exception_event = False # <<<<<<<<<<<<<< + * + * elif event == 'return': + */ + __pyx_v_is_exception_event = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":769 + * # When in a coroutine we change the perceived event to the debugger because + * # a call, StopIteration exception and return are usually just pausing/unpausing it. + * if event == 'line': # <<<<<<<<<<<<<< + * is_line = True + * is_call = False + */ + goto __pyx_L13; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":775 + * is_exception_event = False + * + * elif event == 'return': # <<<<<<<<<<<<<< + * is_line = False + * is_call = False + */ + __pyx_t_11 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_return, Py_EQ)); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 775, __pyx_L4_error) + __pyx_t_9 = (__pyx_t_11 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":776 + * + * elif event == 'return': + * is_line = False # <<<<<<<<<<<<<< + * is_call = False + * is_return = True + */ + __pyx_v_is_line = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":777 + * elif event == 'return': + * is_line = False + * is_call = False # <<<<<<<<<<<<<< + * is_return = True + * is_exception_event = False + */ + __pyx_v_is_call = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":778 + * is_line = False + * is_call = False + * is_return = True # <<<<<<<<<<<<<< + * is_exception_event = False + * + */ + __pyx_v_is_return = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":779 + * is_call = False + * is_return = True + * is_exception_event = False # <<<<<<<<<<<<<< + * + * returns_cache_key = (frame_cache_key, 'returns') + */ + __pyx_v_is_exception_event = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":781 + * is_exception_event = False + * + * returns_cache_key = (frame_cache_key, 'returns') # <<<<<<<<<<<<<< + * return_lines = frame_skips_cache.get(returns_cache_key) + * if return_lines is None: + */ + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 781, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_INCREF(__pyx_v_frame_cache_key); + __Pyx_GIVEREF(__pyx_v_frame_cache_key); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_frame_cache_key); + __Pyx_INCREF(__pyx_n_s_returns); + __Pyx_GIVEREF(__pyx_n_s_returns); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_n_s_returns); + __pyx_v_returns_cache_key = ((PyObject*)__pyx_t_8); + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":782 + * + * returns_cache_key = (frame_cache_key, 'returns') + * return_lines = frame_skips_cache.get(returns_cache_key) # <<<<<<<<<<<<<< + * if return_lines is None: + * # Note: we're collecting the return lines by inspecting the bytecode as + */ + if (unlikely(__pyx_v_frame_skips_cache == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get"); + __PYX_ERR(0, 782, __pyx_L4_error) + } + __pyx_t_8 = __Pyx_PyDict_GetItemDefault(__pyx_v_frame_skips_cache, __pyx_v_returns_cache_key, Py_None); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 782, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_v_return_lines = __pyx_t_8; + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":783 + * returns_cache_key = (frame_cache_key, 'returns') + * return_lines = frame_skips_cache.get(returns_cache_key) + * if return_lines is None: # <<<<<<<<<<<<<< + * # Note: we're collecting the return lines by inspecting the bytecode as + * # there are multiple returns and multiple stop iterations when awaiting and + */ + __pyx_t_9 = (__pyx_v_return_lines == Py_None); + __pyx_t_11 = (__pyx_t_9 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":788 + * # it doesn't give any clear indication when a coroutine or generator is + * # finishing or just pausing. + * return_lines = set() # <<<<<<<<<<<<<< + * for x in main_debugger.collect_return_info(frame.f_code): + * # Note: cython does not support closures in cpdefs (so we can't use + */ + __pyx_t_8 = PySet_New(0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 788, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF_SET(__pyx_v_return_lines, __pyx_t_8); + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":789 + * # finishing or just pausing. + * return_lines = set() + * for x in main_debugger.collect_return_info(frame.f_code): # <<<<<<<<<<<<<< + * # Note: cython does not support closures in cpdefs (so we can't use + * # a list comprehension). + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_collect_return_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 789, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 789, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_8 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_4, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_7); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 789, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (likely(PyList_CheckExact(__pyx_t_8)) || PyTuple_CheckExact(__pyx_t_8)) { + __pyx_t_1 = __pyx_t_8; __Pyx_INCREF(__pyx_t_1); __pyx_t_12 = 0; + __pyx_t_13 = NULL; + } else { + __pyx_t_12 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 789, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_13 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 789, __pyx_L4_error) + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + for (;;) { + if (likely(!__pyx_t_13)) { + if (likely(PyList_CheckExact(__pyx_t_1))) { + if (__pyx_t_12 >= PyList_GET_SIZE(__pyx_t_1)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_8 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_12); __Pyx_INCREF(__pyx_t_8); __pyx_t_12++; if (unlikely(0 < 0)) __PYX_ERR(0, 789, __pyx_L4_error) + #else + __pyx_t_8 = PySequence_ITEM(__pyx_t_1, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 789, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + #endif + } else { + if (__pyx_t_12 >= PyTuple_GET_SIZE(__pyx_t_1)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_8 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_12); __Pyx_INCREF(__pyx_t_8); __pyx_t_12++; if (unlikely(0 < 0)) __PYX_ERR(0, 789, __pyx_L4_error) + #else + __pyx_t_8 = PySequence_ITEM(__pyx_t_1, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 789, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + #endif + } + } else { + __pyx_t_8 = __pyx_t_13(__pyx_t_1); + if (unlikely(!__pyx_t_8)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 789, __pyx_L4_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_8); + } + __Pyx_XDECREF_SET(__pyx_v_x, __pyx_t_8); + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":792 + * # Note: cython does not support closures in cpdefs (so we can't use + * # a list comprehension). + * return_lines.add(x.return_line) # <<<<<<<<<<<<<< + * + * frame_skips_cache[returns_cache_key] = return_lines + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_return_lines, __pyx_n_s_add); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 792, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_x, __pyx_n_s_return_line); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 792, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_8 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_6, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_4); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 792, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":789 + * # finishing or just pausing. + * return_lines = set() + * for x in main_debugger.collect_return_info(frame.f_code): # <<<<<<<<<<<<<< + * # Note: cython does not support closures in cpdefs (so we can't use + * # a list comprehension). + */ + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":794 + * return_lines.add(x.return_line) + * + * frame_skips_cache[returns_cache_key] = return_lines # <<<<<<<<<<<<<< + * + * if line not in return_lines: + */ + if (unlikely(__pyx_v_frame_skips_cache == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 794, __pyx_L4_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_frame_skips_cache, __pyx_v_returns_cache_key, __pyx_v_return_lines) < 0)) __PYX_ERR(0, 794, __pyx_L4_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":783 + * returns_cache_key = (frame_cache_key, 'returns') + * return_lines = frame_skips_cache.get(returns_cache_key) + * if return_lines is None: # <<<<<<<<<<<<<< + * # Note: we're collecting the return lines by inspecting the bytecode as + * # there are multiple returns and multiple stop iterations when awaiting and + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":796 + * frame_skips_cache[returns_cache_key] = return_lines + * + * if line not in return_lines: # <<<<<<<<<<<<<< + * # Not really a return (coroutine/generator paused). + * return self.trace_dispatch + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 796, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_11 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_v_return_lines, Py_NE)); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 796, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = (__pyx_t_11 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":798 + * if line not in return_lines: + * # Not really a return (coroutine/generator paused). + * return self.trace_dispatch # <<<<<<<<<<<<<< + * else: + * if self.exc_info: + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 798, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":796 + * frame_skips_cache[returns_cache_key] = return_lines + * + * if line not in return_lines: # <<<<<<<<<<<<<< + * # Not really a return (coroutine/generator paused). + * return self.trace_dispatch + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":800 + * return self.trace_dispatch + * else: + * if self.exc_info: # <<<<<<<<<<<<<< + * self.handle_user_exception(frame) + * return self.trace_dispatch + */ + /*else*/ { + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_v_self->exc_info); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 800, __pyx_L4_error) + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":801 + * else: + * if self.exc_info: + * self.handle_user_exception(frame) # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_handle_user_exception); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 801, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_7, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 801, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":802 + * if self.exc_info: + * self.handle_user_exception(frame) + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * # Tricky handling: usually when we're on a frame which is about to exit + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 802, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":800 + * return self.trace_dispatch + * else: + * if self.exc_info: # <<<<<<<<<<<<<< + * self.handle_user_exception(frame) + * return self.trace_dispatch + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":820 + * # as the return shouldn't mean that we've actually completed executing a + * # frame in this case). + * if stop_frame is frame and not info.pydev_use_scoped_step_frame: # <<<<<<<<<<<<<< + * if step_cmd in (108, 159, 107, 144): + * f = self._get_unfiltered_back_frame(main_debugger, frame) + */ + __pyx_t_11 = (__pyx_v_stop_frame == __pyx_v_frame); + __pyx_t_14 = (__pyx_t_11 != 0); + if (__pyx_t_14) { + } else { + __pyx_t_9 = __pyx_t_14; + goto __pyx_L20_bool_binop_done; + } + __pyx_t_14 = ((!(__pyx_v_info->pydev_use_scoped_step_frame != 0)) != 0); + __pyx_t_9 = __pyx_t_14; + __pyx_L20_bool_binop_done:; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":821 + * # frame in this case). + * if stop_frame is frame and not info.pydev_use_scoped_step_frame: + * if step_cmd in (108, 159, 107, 144): # <<<<<<<<<<<<<< + * f = self._get_unfiltered_back_frame(main_debugger, frame) + * if f is not None: + */ + switch (__pyx_v_step_cmd) { + case 0x6C: + case 0x9F: + case 0x6B: + case 0x90: + + /* "_pydevd_bundle/pydevd_cython.pyx":822 + * if stop_frame is frame and not info.pydev_use_scoped_step_frame: + * if step_cmd in (108, 159, 107, 144): + * f = self._get_unfiltered_back_frame(main_debugger, frame) # <<<<<<<<<<<<<< + * if f is not None: + * info.pydev_step_cmd = 206 + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_get_unfiltered_back_frame(__pyx_v_self, __pyx_v_main_debugger, __pyx_v_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 822, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_f = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":823 + * if step_cmd in (108, 159, 107, 144): + * f = self._get_unfiltered_back_frame(main_debugger, frame) + * if f is not None: # <<<<<<<<<<<<<< + * info.pydev_step_cmd = 206 + * info.pydev_step_stop = f + */ + __pyx_t_9 = (__pyx_v_f != Py_None); + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":824 + * f = self._get_unfiltered_back_frame(main_debugger, frame) + * if f is not None: + * info.pydev_step_cmd = 206 # <<<<<<<<<<<<<< + * info.pydev_step_stop = f + * else: + */ + __pyx_v_info->pydev_step_cmd = 0xCE; + + /* "_pydevd_bundle/pydevd_cython.pyx":825 + * if f is not None: + * info.pydev_step_cmd = 206 + * info.pydev_step_stop = f # <<<<<<<<<<<<<< + * else: + * if step_cmd == 108: + */ + __Pyx_INCREF(__pyx_v_f); + __Pyx_GIVEREF(__pyx_v_f); + __Pyx_GOTREF(__pyx_v_info->pydev_step_stop); + __Pyx_DECREF(__pyx_v_info->pydev_step_stop); + __pyx_v_info->pydev_step_stop = __pyx_v_f; + + /* "_pydevd_bundle/pydevd_cython.pyx":823 + * if step_cmd in (108, 159, 107, 144): + * f = self._get_unfiltered_back_frame(main_debugger, frame) + * if f is not None: # <<<<<<<<<<<<<< + * info.pydev_step_cmd = 206 + * info.pydev_step_stop = f + */ + goto __pyx_L22; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":827 + * info.pydev_step_stop = f + * else: + * if step_cmd == 108: # <<<<<<<<<<<<<< + * info.pydev_step_cmd = 107 + * info.pydev_step_stop = None + */ + /*else*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":831 + * info.pydev_step_stop = None + * + * elif step_cmd == 159: # <<<<<<<<<<<<<< + * info.pydev_step_cmd = 144 + * info.pydev_step_stop = None + */ + switch (__pyx_v_step_cmd) { + case 0x6C: + + /* "_pydevd_bundle/pydevd_cython.pyx":828 + * else: + * if step_cmd == 108: + * info.pydev_step_cmd = 107 # <<<<<<<<<<<<<< + * info.pydev_step_stop = None + * + */ + __pyx_v_info->pydev_step_cmd = 0x6B; + + /* "_pydevd_bundle/pydevd_cython.pyx":829 + * if step_cmd == 108: + * info.pydev_step_cmd = 107 + * info.pydev_step_stop = None # <<<<<<<<<<<<<< + * + * elif step_cmd == 159: + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->pydev_step_stop); + __Pyx_DECREF(__pyx_v_info->pydev_step_stop); + __pyx_v_info->pydev_step_stop = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":827 + * info.pydev_step_stop = f + * else: + * if step_cmd == 108: # <<<<<<<<<<<<<< + * info.pydev_step_cmd = 107 + * info.pydev_step_stop = None + */ + break; + case 0x9F: + + /* "_pydevd_bundle/pydevd_cython.pyx":832 + * + * elif step_cmd == 159: + * info.pydev_step_cmd = 144 # <<<<<<<<<<<<<< + * info.pydev_step_stop = None + * + */ + __pyx_v_info->pydev_step_cmd = 0x90; + + /* "_pydevd_bundle/pydevd_cython.pyx":833 + * elif step_cmd == 159: + * info.pydev_step_cmd = 144 + * info.pydev_step_stop = None # <<<<<<<<<<<<<< + * + * elif step_cmd == 206: + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->pydev_step_stop); + __Pyx_DECREF(__pyx_v_info->pydev_step_stop); + __pyx_v_info->pydev_step_stop = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":831 + * info.pydev_step_stop = None + * + * elif step_cmd == 159: # <<<<<<<<<<<<<< + * info.pydev_step_cmd = 144 + * info.pydev_step_stop = None + */ + break; + default: break; + } + } + __pyx_L22:; + + /* "_pydevd_bundle/pydevd_cython.pyx":821 + * # frame in this case). + * if stop_frame is frame and not info.pydev_use_scoped_step_frame: + * if step_cmd in (108, 159, 107, 144): # <<<<<<<<<<<<<< + * f = self._get_unfiltered_back_frame(main_debugger, frame) + * if f is not None: + */ + break; + case 0xCE: + + /* "_pydevd_bundle/pydevd_cython.pyx":837 + * elif step_cmd == 206: + * # We're exiting this one, so, mark the new coroutine context. + * f = self._get_unfiltered_back_frame(main_debugger, frame) # <<<<<<<<<<<<<< + * if f is not None: + * info.pydev_step_stop = f + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_get_unfiltered_back_frame(__pyx_v_self, __pyx_v_main_debugger, __pyx_v_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 837, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_f = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":838 + * # We're exiting this one, so, mark the new coroutine context. + * f = self._get_unfiltered_back_frame(main_debugger, frame) + * if f is not None: # <<<<<<<<<<<<<< + * info.pydev_step_stop = f + * else: + */ + __pyx_t_14 = (__pyx_v_f != Py_None); + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":839 + * f = self._get_unfiltered_back_frame(main_debugger, frame) + * if f is not None: + * info.pydev_step_stop = f # <<<<<<<<<<<<<< + * else: + * info.pydev_step_cmd = 107 + */ + __Pyx_INCREF(__pyx_v_f); + __Pyx_GIVEREF(__pyx_v_f); + __Pyx_GOTREF(__pyx_v_info->pydev_step_stop); + __Pyx_DECREF(__pyx_v_info->pydev_step_stop); + __pyx_v_info->pydev_step_stop = __pyx_v_f; + + /* "_pydevd_bundle/pydevd_cython.pyx":838 + * # We're exiting this one, so, mark the new coroutine context. + * f = self._get_unfiltered_back_frame(main_debugger, frame) + * if f is not None: # <<<<<<<<<<<<<< + * info.pydev_step_stop = f + * else: + */ + goto __pyx_L23; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":841 + * info.pydev_step_stop = f + * else: + * info.pydev_step_cmd = 107 # <<<<<<<<<<<<<< + * info.pydev_step_stop = None + * + */ + /*else*/ { + __pyx_v_info->pydev_step_cmd = 0x6B; + + /* "_pydevd_bundle/pydevd_cython.pyx":842 + * else: + * info.pydev_step_cmd = 107 + * info.pydev_step_stop = None # <<<<<<<<<<<<<< + * + * elif event == 'exception': + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->pydev_step_stop); + __Pyx_DECREF(__pyx_v_info->pydev_step_stop); + __pyx_v_info->pydev_step_stop = Py_None; + } + __pyx_L23:; + + /* "_pydevd_bundle/pydevd_cython.pyx":835 + * info.pydev_step_stop = None + * + * elif step_cmd == 206: # <<<<<<<<<<<<<< + * # We're exiting this one, so, mark the new coroutine context. + * f = self._get_unfiltered_back_frame(main_debugger, frame) + */ + break; + default: break; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":820 + * # as the return shouldn't mean that we've actually completed executing a + * # frame in this case). + * if stop_frame is frame and not info.pydev_use_scoped_step_frame: # <<<<<<<<<<<<<< + * if step_cmd in (108, 159, 107, 144): + * f = self._get_unfiltered_back_frame(main_debugger, frame) + */ + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":775 + * is_exception_event = False + * + * elif event == 'return': # <<<<<<<<<<<<<< + * is_line = False + * is_call = False + */ + goto __pyx_L13; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":844 + * info.pydev_step_stop = None + * + * elif event == 'exception': # <<<<<<<<<<<<<< + * breakpoints_for_file = None + * if has_exception_breakpoints: + */ + __pyx_t_9 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_exception, Py_EQ)); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 844, __pyx_L4_error) + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":845 + * + * elif event == 'exception': + * breakpoints_for_file = None # <<<<<<<<<<<<<< + * if has_exception_breakpoints: + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + */ + __Pyx_INCREF(Py_None); + __pyx_v_breakpoints_for_file = ((PyObject*)Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":846 + * elif event == 'exception': + * breakpoints_for_file = None + * if has_exception_breakpoints: # <<<<<<<<<<<<<< + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: + */ + __pyx_t_14 = (__pyx_v_has_exception_breakpoints != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":847 + * breakpoints_for_file = None + * if has_exception_breakpoints: + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) # <<<<<<<<<<<<<< + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_should_stop_on_exception(__pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 847, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 847, __pyx_L4_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_8 = PyList_GET_ITEM(sequence, 0); + __pyx_t_7 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + #else + __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 847, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 847, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 847, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_4)->tp_iternext; + index = 0; __pyx_t_8 = __pyx_t_15(__pyx_t_4); if (unlikely(!__pyx_t_8)) goto __pyx_L25_unpacking_failed; + __Pyx_GOTREF(__pyx_t_8); + index = 1; __pyx_t_7 = __pyx_t_15(__pyx_t_4); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_4), 2) < 0) __PYX_ERR(0, 847, __pyx_L4_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + goto __pyx_L26_unpacking_done; + __pyx_L25_unpacking_failed:; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 847, __pyx_L4_error) + __pyx_L26_unpacking_done:; + } + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 847, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_should_stop = __pyx_t_14; + __Pyx_DECREF_SET(__pyx_v_frame, __pyx_t_7); + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":848 + * if has_exception_breakpoints: + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: # <<<<<<<<<<<<<< + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch + */ + __pyx_t_14 = (__pyx_v_should_stop != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":849 + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_EXCEPTION_TYPE_HANDLED); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 849, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 849, __pyx_L4_error) + __pyx_t_7 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_handle_exception(__pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg, ((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 849, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 849, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":850 + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * return self.trace_dispatch + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 850, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_r = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":849 + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":848 + * if has_exception_breakpoints: + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: # <<<<<<<<<<<<<< + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":846 + * elif event == 'exception': + * breakpoints_for_file = None + * if has_exception_breakpoints: # <<<<<<<<<<<<<< + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":852 + * return self.trace_dispatch + * + * return self.trace_dispatch # <<<<<<<<<<<<<< + * else: + * # event == 'call' or event == 'c_XXX' + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 852, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_r = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":844 + * info.pydev_step_stop = None + * + * elif event == 'exception': # <<<<<<<<<<<<<< + * breakpoints_for_file = None + * if has_exception_breakpoints: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":855 + * else: + * # event == 'call' or event == 'c_XXX' + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * else: # Not coroutine nor generator + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 855, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_r = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L3_return; + } + __pyx_L13:; + + /* "_pydevd_bundle/pydevd_cython.pyx":765 + * function_breakpoint_on_call_event = None + * + * if frame.f_code.co_flags & 0xa0: # 0xa0 == CO_GENERATOR = 0x20 | CO_COROUTINE = 0x80 # <<<<<<<<<<<<<< + * # Dealing with coroutines and generators: + * # When in a coroutine we change the perceived event to the debugger because + */ + goto __pyx_L12; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":858 + * + * else: # Not coroutine nor generator + * if event == 'line': # <<<<<<<<<<<<<< + * is_line = True + * is_call = False + */ + /*else*/ { + __pyx_t_14 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_line, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 858, __pyx_L4_error) + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":859 + * else: # Not coroutine nor generator + * if event == 'line': + * is_line = True # <<<<<<<<<<<<<< + * is_call = False + * is_return = False + */ + __pyx_v_is_line = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":860 + * if event == 'line': + * is_line = True + * is_call = False # <<<<<<<<<<<<<< + * is_return = False + * is_exception_event = False + */ + __pyx_v_is_call = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":861 + * is_line = True + * is_call = False + * is_return = False # <<<<<<<<<<<<<< + * is_exception_event = False + * + */ + __pyx_v_is_return = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":862 + * is_call = False + * is_return = False + * is_exception_event = False # <<<<<<<<<<<<<< + * + * elif event == 'return': + */ + __pyx_v_is_exception_event = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":858 + * + * else: # Not coroutine nor generator + * if event == 'line': # <<<<<<<<<<<<<< + * is_line = True + * is_call = False + */ + goto __pyx_L29; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":864 + * is_exception_event = False + * + * elif event == 'return': # <<<<<<<<<<<<<< + * is_line = False + * is_return = True + */ + __pyx_t_9 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_return, Py_EQ)); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 864, __pyx_L4_error) + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":865 + * + * elif event == 'return': + * is_line = False # <<<<<<<<<<<<<< + * is_return = True + * is_call = False + */ + __pyx_v_is_line = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":866 + * elif event == 'return': + * is_line = False + * is_return = True # <<<<<<<<<<<<<< + * is_call = False + * is_exception_event = False + */ + __pyx_v_is_return = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":867 + * is_line = False + * is_return = True + * is_call = False # <<<<<<<<<<<<<< + * is_exception_event = False + * + */ + __pyx_v_is_call = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":868 + * is_return = True + * is_call = False + * is_exception_event = False # <<<<<<<<<<<<<< + * + * # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break + */ + __pyx_v_is_exception_event = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":877 + * # @DontTrace comment. + * if ( + * stop_frame is frame and # <<<<<<<<<<<<<< + * not info.pydev_use_scoped_step_frame and is_return and + * step_cmd in (108, 109, 159, 160, 128) + */ + __pyx_t_9 = (__pyx_v_stop_frame == __pyx_v_frame); + __pyx_t_11 = (__pyx_t_9 != 0); + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":878 + * if ( + * stop_frame is frame and + * not info.pydev_use_scoped_step_frame and is_return and # <<<<<<<<<<<<<< + * step_cmd in (108, 109, 159, 160, 128) + * ): + */ + __pyx_t_11 = ((!(__pyx_v_info->pydev_use_scoped_step_frame != 0)) != 0); + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L31_bool_binop_done; + } + __pyx_t_11 = (__pyx_v_is_return != 0); + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":879 + * stop_frame is frame and + * not info.pydev_use_scoped_step_frame and is_return and + * step_cmd in (108, 109, 159, 160, 128) # <<<<<<<<<<<<<< + * ): + * + */ + switch (__pyx_v_step_cmd) { + case 0x6C: + case 0x6D: + case 0x9F: + case 0xA0: + case 0x80: + __pyx_t_11 = 1; + break; + default: + __pyx_t_11 = 0; + break; + } + __pyx_t_9 = (__pyx_t_11 != 0); + __pyx_t_14 = __pyx_t_9; + __pyx_L31_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":876 + * # Note: this is especially troublesome when we're skipping code with the + * # @DontTrace comment. + * if ( # <<<<<<<<<<<<<< + * stop_frame is frame and + * not info.pydev_use_scoped_step_frame and is_return and + */ + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":882 + * ): + * + * if step_cmd in (108, 109, 128): # <<<<<<<<<<<<<< + * info.pydev_step_cmd = 107 + * else: + */ + switch (__pyx_v_step_cmd) { + case 0x6C: + case 0x6D: + case 0x80: + + /* "_pydevd_bundle/pydevd_cython.pyx":883 + * + * if step_cmd in (108, 109, 128): + * info.pydev_step_cmd = 107 # <<<<<<<<<<<<<< + * else: + * info.pydev_step_cmd = 144 + */ + __pyx_v_info->pydev_step_cmd = 0x6B; + + /* "_pydevd_bundle/pydevd_cython.pyx":882 + * ): + * + * if step_cmd in (108, 109, 128): # <<<<<<<<<<<<<< + * info.pydev_step_cmd = 107 + * else: + */ + break; + default: + + /* "_pydevd_bundle/pydevd_cython.pyx":885 + * info.pydev_step_cmd = 107 + * else: + * info.pydev_step_cmd = 144 # <<<<<<<<<<<<<< + * info.pydev_step_stop = None + * + */ + __pyx_v_info->pydev_step_cmd = 0x90; + break; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":886 + * else: + * info.pydev_step_cmd = 144 + * info.pydev_step_stop = None # <<<<<<<<<<<<<< + * + * if self.exc_info: + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->pydev_step_stop); + __Pyx_DECREF(__pyx_v_info->pydev_step_stop); + __pyx_v_info->pydev_step_stop = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":876 + * # Note: this is especially troublesome when we're skipping code with the + * # @DontTrace comment. + * if ( # <<<<<<<<<<<<<< + * stop_frame is frame and + * not info.pydev_use_scoped_step_frame and is_return and + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":888 + * info.pydev_step_stop = None + * + * if self.exc_info: # <<<<<<<<<<<<<< + * if self.handle_user_exception(frame): + * return self.trace_dispatch + */ + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_self->exc_info); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 888, __pyx_L4_error) + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":889 + * + * if self.exc_info: + * if self.handle_user_exception(frame): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_handle_user_exception); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 889, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_7 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_8, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 889, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 889, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":890 + * if self.exc_info: + * if self.handle_user_exception(frame): + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * elif event == 'call': + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 890, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_r = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":889 + * + * if self.exc_info: + * if self.handle_user_exception(frame): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":888 + * info.pydev_step_stop = None + * + * if self.exc_info: # <<<<<<<<<<<<<< + * if self.handle_user_exception(frame): + * return self.trace_dispatch + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":864 + * is_exception_event = False + * + * elif event == 'return': # <<<<<<<<<<<<<< + * is_line = False + * is_return = True + */ + goto __pyx_L29; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":892 + * return self.trace_dispatch + * + * elif event == 'call': # <<<<<<<<<<<<<< + * is_line = False + * is_call = True + */ + __pyx_t_14 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 892, __pyx_L4_error) + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":893 + * + * elif event == 'call': + * is_line = False # <<<<<<<<<<<<<< + * is_call = True + * is_return = False + */ + __pyx_v_is_line = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":894 + * elif event == 'call': + * is_line = False + * is_call = True # <<<<<<<<<<<<<< + * is_return = False + * is_exception_event = False + */ + __pyx_v_is_call = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":895 + * is_line = False + * is_call = True + * is_return = False # <<<<<<<<<<<<<< + * is_exception_event = False + * if frame.f_code.co_firstlineno == frame.f_lineno: # Check line to deal with async/await. + */ + __pyx_v_is_return = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":896 + * is_call = True + * is_return = False + * is_exception_event = False # <<<<<<<<<<<<<< + * if frame.f_code.co_firstlineno == frame.f_lineno: # Check line to deal with async/await. + * function_breakpoint_on_call_event = main_debugger.function_breakpoint_name_to_breakpoint.get(frame.f_code.co_name) + */ + __pyx_v_is_exception_event = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":897 + * is_return = False + * is_exception_event = False + * if frame.f_code.co_firstlineno == frame.f_lineno: # Check line to deal with async/await. # <<<<<<<<<<<<<< + * function_breakpoint_on_call_event = main_debugger.function_breakpoint_name_to_breakpoint.get(frame.f_code.co_name) + * + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 897, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_co_firstlineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 897, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 897, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = PyObject_RichCompare(__pyx_t_1, __pyx_t_7, Py_EQ); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 897, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 897, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":898 + * is_exception_event = False + * if frame.f_code.co_firstlineno == frame.f_lineno: # Check line to deal with async/await. + * function_breakpoint_on_call_event = main_debugger.function_breakpoint_name_to_breakpoint.get(frame.f_code.co_name) # <<<<<<<<<<<<<< + * + * elif event == 'exception': + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_function_breakpoint_name_to_brea); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 898, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_get); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 898, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 898, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_co_name); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 898, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_8 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_7, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_4); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 898, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_function_breakpoint_on_call_event, __pyx_t_8); + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":897 + * is_return = False + * is_exception_event = False + * if frame.f_code.co_firstlineno == frame.f_lineno: # Check line to deal with async/await. # <<<<<<<<<<<<<< + * function_breakpoint_on_call_event = main_debugger.function_breakpoint_name_to_breakpoint.get(frame.f_code.co_name) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":892 + * return self.trace_dispatch + * + * elif event == 'call': # <<<<<<<<<<<<<< + * is_line = False + * is_call = True + */ + goto __pyx_L29; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":900 + * function_breakpoint_on_call_event = main_debugger.function_breakpoint_name_to_breakpoint.get(frame.f_code.co_name) + * + * elif event == 'exception': # <<<<<<<<<<<<<< + * is_exception_event = True + * breakpoints_for_file = None + */ + __pyx_t_9 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_exception, Py_EQ)); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 900, __pyx_L4_error) + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":901 + * + * elif event == 'exception': + * is_exception_event = True # <<<<<<<<<<<<<< + * breakpoints_for_file = None + * if has_exception_breakpoints: + */ + __pyx_v_is_exception_event = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":902 + * elif event == 'exception': + * is_exception_event = True + * breakpoints_for_file = None # <<<<<<<<<<<<<< + * if has_exception_breakpoints: + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + */ + __Pyx_INCREF(Py_None); + __pyx_v_breakpoints_for_file = ((PyObject*)Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":903 + * is_exception_event = True + * breakpoints_for_file = None + * if has_exception_breakpoints: # <<<<<<<<<<<<<< + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: + */ + __pyx_t_14 = (__pyx_v_has_exception_breakpoints != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":904 + * breakpoints_for_file = None + * if has_exception_breakpoints: + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) # <<<<<<<<<<<<<< + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + */ + __pyx_t_8 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_should_stop_on_exception(__pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 904, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) { + PyObject* sequence = __pyx_t_8; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 904, __pyx_L4_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_1 = PyList_GET_ITEM(sequence, 0); + __pyx_t_4 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + #else + __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 904, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 904, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_7 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 904, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext; + index = 0; __pyx_t_1 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_1)) goto __pyx_L39_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L39_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 904, __pyx_L4_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L40_unpacking_done; + __pyx_L39_unpacking_failed:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 904, __pyx_L4_error) + __pyx_L40_unpacking_done:; + } + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 904, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_should_stop = __pyx_t_14; + __Pyx_DECREF_SET(__pyx_v_frame, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":905 + * if has_exception_breakpoints: + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: # <<<<<<<<<<<<<< + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch + */ + __pyx_t_14 = (__pyx_v_should_stop != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":906 + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * is_line = False + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_EXCEPTION_TYPE_HANDLED); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 906, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + if (!(likely(PyString_CheckExact(__pyx_t_8))||((__pyx_t_8) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_8)->tp_name), 0))) __PYX_ERR(0, 906, __pyx_L4_error) + __pyx_t_4 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_handle_exception(__pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg, ((PyObject*)__pyx_t_8)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 906, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 906, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":907 + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch # <<<<<<<<<<<<<< + * is_line = False + * is_return = False + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 907, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":906 + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): # <<<<<<<<<<<<<< + * return self.trace_dispatch + * is_line = False + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":905 + * if has_exception_breakpoints: + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: # <<<<<<<<<<<<<< + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":903 + * is_exception_event = True + * breakpoints_for_file = None + * if has_exception_breakpoints: # <<<<<<<<<<<<<< + * should_stop, frame = self._should_stop_on_exception(frame, event, arg) + * if should_stop: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":908 + * if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + * return self.trace_dispatch + * is_line = False # <<<<<<<<<<<<<< + * is_return = False + * is_call = False + */ + __pyx_v_is_line = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":909 + * return self.trace_dispatch + * is_line = False + * is_return = False # <<<<<<<<<<<<<< + * is_call = False + * + */ + __pyx_v_is_return = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":910 + * is_line = False + * is_return = False + * is_call = False # <<<<<<<<<<<<<< + * + * else: + */ + __pyx_v_is_call = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":900 + * function_breakpoint_on_call_event = main_debugger.function_breakpoint_name_to_breakpoint.get(frame.f_code.co_name) + * + * elif event == 'exception': # <<<<<<<<<<<<<< + * is_exception_event = True + * breakpoints_for_file = None + */ + goto __pyx_L29; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":914 + * else: + * # Unexpected: just keep the same trace func (i.e.: event == 'c_XXX'). + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * if not is_exception_event: + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 914, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L3_return; + } + __pyx_L29:; + } + __pyx_L12:; + + /* "_pydevd_bundle/pydevd_cython.pyx":916 + * return self.trace_dispatch + * + * if not is_exception_event: # <<<<<<<<<<<<<< + * breakpoints_for_file = main_debugger.breakpoints.get(abs_path_canonical_path_and_base[1]) + * + */ + __pyx_t_14 = ((!(__pyx_v_is_exception_event != 0)) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":917 + * + * if not is_exception_event: + * breakpoints_for_file = main_debugger.breakpoints.get(abs_path_canonical_path_and_base[1]) # <<<<<<<<<<<<<< + * + * can_skip = False + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_breakpoints); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 917, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_get); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 917, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(__pyx_v_abs_path_canonical_path_and_base == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 917, __pyx_L4_error) + } + __pyx_t_8 = __Pyx_GetItemInt_Tuple(__pyx_v_abs_path_canonical_path_and_base, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 917, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_7, __pyx_t_8) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_8); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 917, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(PyDict_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(0, 917, __pyx_L4_error) + __Pyx_XDECREF_SET(__pyx_v_breakpoints_for_file, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":919 + * breakpoints_for_file = main_debugger.breakpoints.get(abs_path_canonical_path_and_base[1]) + * + * can_skip = False # <<<<<<<<<<<<<< + * + * if info.pydev_state == 1: # 1 = 1 + */ + __pyx_v_can_skip = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":921 + * can_skip = False + * + * if info.pydev_state == 1: # 1 = 1 # <<<<<<<<<<<<<< + * # we can skip if: + * # - we have no stop marked + */ + __pyx_t_14 = ((__pyx_v_info->pydev_state == 1) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":926 + * # - we should make a step return/step over and we're not in the current frame + * # - we're stepping into a coroutine context and we're not in that context + * if step_cmd == -1: # <<<<<<<<<<<<<< + * can_skip = True + * + */ + __pyx_t_14 = ((__pyx_v_step_cmd == -1L) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":927 + * # - we're stepping into a coroutine context and we're not in that context + * if step_cmd == -1: + * can_skip = True # <<<<<<<<<<<<<< + * + * elif step_cmd in (108, 109, 159, 160) and not self._is_same_frame(stop_frame, frame): + */ + __pyx_v_can_skip = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":926 + * # - we should make a step return/step over and we're not in the current frame + * # - we're stepping into a coroutine context and we're not in that context + * if step_cmd == -1: # <<<<<<<<<<<<<< + * can_skip = True + * + */ + goto __pyx_L45; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":929 + * can_skip = True + * + * elif step_cmd in (108, 109, 159, 160) and not self._is_same_frame(stop_frame, frame): # <<<<<<<<<<<<<< + * can_skip = True + * + */ + switch (__pyx_v_step_cmd) { + case 0x6C: + case 0x6D: + case 0x9F: + case 0xA0: + __pyx_t_9 = 1; + break; + default: + __pyx_t_9 = 0; + break; + } + __pyx_t_11 = (__pyx_t_9 != 0); + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L46_bool_binop_done; + } + __pyx_t_4 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_frame); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 929, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 929, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = ((!__pyx_t_11) != 0); + __pyx_t_14 = __pyx_t_9; + __pyx_L46_bool_binop_done:; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":930 + * + * elif step_cmd in (108, 109, 159, 160) and not self._is_same_frame(stop_frame, frame): + * can_skip = True # <<<<<<<<<<<<<< + * + * elif step_cmd == 128 and ( + */ + __pyx_v_can_skip = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":929 + * can_skip = True + * + * elif step_cmd in (108, 109, 159, 160) and not self._is_same_frame(stop_frame, frame): # <<<<<<<<<<<<<< + * can_skip = True + * + */ + goto __pyx_L45; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":932 + * can_skip = True + * + * elif step_cmd == 128 and ( # <<<<<<<<<<<<<< + * stop_frame is not None and + * stop_frame is not frame and + */ + __pyx_t_9 = ((__pyx_v_step_cmd == 0x80) != 0); + if (__pyx_t_9) { + } else { + __pyx_t_14 = __pyx_t_9; + goto __pyx_L48_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":933 + * + * elif step_cmd == 128 and ( + * stop_frame is not None and # <<<<<<<<<<<<<< + * stop_frame is not frame and + * stop_frame is not frame.f_back and + */ + __pyx_t_9 = (__pyx_v_stop_frame != Py_None); + __pyx_t_11 = (__pyx_t_9 != 0); + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L48_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":934 + * elif step_cmd == 128 and ( + * stop_frame is not None and + * stop_frame is not frame and # <<<<<<<<<<<<<< + * stop_frame is not frame.f_back and + * (frame.f_back is None or stop_frame is not frame.f_back.f_back)): + */ + __pyx_t_11 = (__pyx_v_stop_frame != __pyx_v_frame); + __pyx_t_9 = (__pyx_t_11 != 0); + if (__pyx_t_9) { + } else { + __pyx_t_14 = __pyx_t_9; + goto __pyx_L48_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":935 + * stop_frame is not None and + * stop_frame is not frame and + * stop_frame is not frame.f_back and # <<<<<<<<<<<<<< + * (frame.f_back is None or stop_frame is not frame.f_back.f_back)): + * can_skip = True + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 935, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_9 = (__pyx_v_stop_frame != __pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_11 = (__pyx_t_9 != 0); + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L48_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":936 + * stop_frame is not frame and + * stop_frame is not frame.f_back and + * (frame.f_back is None or stop_frame is not frame.f_back.f_back)): # <<<<<<<<<<<<<< + * can_skip = True + * + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 936, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_11 = (__pyx_t_4 == Py_None); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = (__pyx_t_11 != 0); + if (!__pyx_t_9) { + } else { + __pyx_t_14 = __pyx_t_9; + goto __pyx_L48_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 936, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 936, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = (__pyx_v_stop_frame != __pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_11 = (__pyx_t_9 != 0); + __pyx_t_14 = __pyx_t_11; + __pyx_L48_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":932 + * can_skip = True + * + * elif step_cmd == 128 and ( # <<<<<<<<<<<<<< + * stop_frame is not None and + * stop_frame is not frame and + */ + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":937 + * stop_frame is not frame.f_back and + * (frame.f_back is None or stop_frame is not frame.f_back.f_back)): + * can_skip = True # <<<<<<<<<<<<<< + * + * elif step_cmd == 144: + */ + __pyx_v_can_skip = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":932 + * can_skip = True + * + * elif step_cmd == 128 and ( # <<<<<<<<<<<<<< + * stop_frame is not None and + * stop_frame is not frame and + */ + goto __pyx_L45; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":939 + * can_skip = True + * + * elif step_cmd == 144: # <<<<<<<<<<<<<< + * if ( + * main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) + */ + __pyx_t_14 = ((__pyx_v_step_cmd == 0x90) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":941 + * elif step_cmd == 144: + * if ( + * main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) # <<<<<<<<<<<<<< + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)) + * ): + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 941, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 941, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 941, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_8, __pyx_v_frame, __pyx_t_7, Py_True}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 941, __pyx_L4_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_8, __pyx_v_frame, __pyx_t_7, Py_True}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 941, __pyx_L4_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_6 = PyTuple_New(3+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 941, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_6); + if (__pyx_t_8) { + __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_8); __pyx_t_8 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_5, __pyx_v_frame); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, __pyx_t_7); + __Pyx_INCREF(Py_True); + __Pyx_GIVEREF(Py_True); + PyTuple_SET_ITEM(__pyx_t_6, 2+__pyx_t_5, Py_True); + __pyx_t_7 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 941, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 941, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L55_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":942 + * if ( + * main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)) # <<<<<<<<<<<<<< + * ): + * can_skip = True + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_11 = (__pyx_t_1 == Py_None); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = (__pyx_t_11 != 0); + if (!__pyx_t_9) { + } else { + __pyx_t_14 = __pyx_t_9; + goto __pyx_L55_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_f_code); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_8, __pyx_t_6, __pyx_t_7, Py_True}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_8, __pyx_t_6, __pyx_t_7, Py_True}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_3 = PyTuple_New(3+__pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_8) { + __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8); __pyx_t_8 = NULL; + } + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_5, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_5, __pyx_t_7); + __Pyx_INCREF(Py_True); + __Pyx_GIVEREF(Py_True); + PyTuple_SET_ITEM(__pyx_t_3, 2+__pyx_t_5, Py_True); + __pyx_t_6 = 0; + __pyx_t_7 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 942, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_14 = __pyx_t_9; + __pyx_L55_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":940 + * + * elif step_cmd == 144: + * if ( # <<<<<<<<<<<<<< + * main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)) + */ + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":944 + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)) + * ): + * can_skip = True # <<<<<<<<<<<<<< + * + * elif step_cmd == 206: + */ + __pyx_v_can_skip = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":940 + * + * elif step_cmd == 144: + * if ( # <<<<<<<<<<<<<< + * main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) + * and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)) + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":939 + * can_skip = True + * + * elif step_cmd == 144: # <<<<<<<<<<<<<< + * if ( + * main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) + */ + goto __pyx_L45; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":946 + * can_skip = True + * + * elif step_cmd == 206: # <<<<<<<<<<<<<< + * f = frame + * while f is not None: + */ + __pyx_t_14 = ((__pyx_v_step_cmd == 0xCE) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":947 + * + * elif step_cmd == 206: + * f = frame # <<<<<<<<<<<<<< + * while f is not None: + * if self._is_same_frame(stop_frame, f): + */ + __Pyx_INCREF(__pyx_v_frame); + __Pyx_XDECREF_SET(__pyx_v_f, __pyx_v_frame); + + /* "_pydevd_bundle/pydevd_cython.pyx":948 + * elif step_cmd == 206: + * f = frame + * while f is not None: # <<<<<<<<<<<<<< + * if self._is_same_frame(stop_frame, f): + * break + */ + while (1) { + __pyx_t_14 = (__pyx_v_f != Py_None); + __pyx_t_9 = (__pyx_t_14 != 0); + if (!__pyx_t_9) break; + + /* "_pydevd_bundle/pydevd_cython.pyx":949 + * f = frame + * while f is not None: + * if self._is_same_frame(stop_frame, f): # <<<<<<<<<<<<<< + * break + * f = f.f_back + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_f); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 949, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 949, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":950 + * while f is not None: + * if self._is_same_frame(stop_frame, f): + * break # <<<<<<<<<<<<<< + * f = f.f_back + * else: + */ + goto __pyx_L59_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":949 + * f = frame + * while f is not None: + * if self._is_same_frame(stop_frame, f): # <<<<<<<<<<<<<< + * break + * f = f.f_back + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":951 + * if self._is_same_frame(stop_frame, f): + * break + * f = f.f_back # <<<<<<<<<<<<<< + * else: + * can_skip = True + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 951, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_f, __pyx_t_1); + __pyx_t_1 = 0; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":953 + * f = f.f_back + * else: + * can_skip = True # <<<<<<<<<<<<<< + * + * if can_skip: + */ + /*else*/ { + __pyx_v_can_skip = 1; + } + __pyx_L59_break:; + + /* "_pydevd_bundle/pydevd_cython.pyx":946 + * can_skip = True + * + * elif step_cmd == 206: # <<<<<<<<<<<<<< + * f = frame + * while f is not None: + */ + } + __pyx_L45:; + + /* "_pydevd_bundle/pydevd_cython.pyx":955 + * can_skip = True + * + * if can_skip: # <<<<<<<<<<<<<< + * if plugin_manager is not None and ( + * main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): + */ + __pyx_t_9 = (__pyx_v_can_skip != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":956 + * + * if can_skip: + * if plugin_manager is not None and ( # <<<<<<<<<<<<<< + * main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): + * can_skip = plugin_manager.can_skip(main_debugger, frame) + */ + __pyx_t_14 = (__pyx_v_plugin_manager != Py_None); + __pyx_t_11 = (__pyx_t_14 != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L63_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":957 + * if can_skip: + * if plugin_manager is not None and ( + * main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): # <<<<<<<<<<<<<< + * can_skip = plugin_manager.can_skip(main_debugger, frame) + * + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_line_breaks); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 957, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 957, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L63_bool_binop_done; + } + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_exception_breaks); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 957, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 957, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = __pyx_t_11; + __pyx_L63_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":956 + * + * if can_skip: + * if plugin_manager is not None and ( # <<<<<<<<<<<<<< + * main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): + * can_skip = plugin_manager.can_skip(main_debugger, frame) + */ + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":958 + * if plugin_manager is not None and ( + * main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): + * can_skip = plugin_manager.can_skip(main_debugger, frame) # <<<<<<<<<<<<<< + * + * if can_skip and main_debugger.show_return_values and info.pydev_step_cmd in (108, 159) and self._is_same_frame(stop_frame, frame.f_back): + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_plugin_manager, __pyx_n_s_can_skip); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 958, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_main_debugger, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 958, __pyx_L4_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_main_debugger, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 958, __pyx_L4_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_7 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 958, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_5, __pyx_v_main_debugger); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_5, __pyx_v_frame); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 958, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_9 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 958, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_can_skip = __pyx_t_9; + + /* "_pydevd_bundle/pydevd_cython.pyx":956 + * + * if can_skip: + * if plugin_manager is not None and ( # <<<<<<<<<<<<<< + * main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): + * can_skip = plugin_manager.can_skip(main_debugger, frame) + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":960 + * can_skip = plugin_manager.can_skip(main_debugger, frame) + * + * if can_skip and main_debugger.show_return_values and info.pydev_step_cmd in (108, 159) and self._is_same_frame(stop_frame, frame.f_back): # <<<<<<<<<<<<<< + * # trace function for showing return values after step over + * can_skip = False + */ + __pyx_t_11 = (__pyx_v_can_skip != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L67_bool_binop_done; + } + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_show_return_values); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 960, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 960, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L67_bool_binop_done; + } + switch (__pyx_v_info->pydev_step_cmd) { + case 0x6C: + case 0x9F: + __pyx_t_11 = 1; + break; + default: + __pyx_t_11 = 0; + break; + } + __pyx_t_14 = (__pyx_t_11 != 0); + if (__pyx_t_14) { + } else { + __pyx_t_9 = __pyx_t_14; + goto __pyx_L67_bool_binop_done; + } + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 960, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 960, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 960, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = __pyx_t_14; + __pyx_L67_bool_binop_done:; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":962 + * if can_skip and main_debugger.show_return_values and info.pydev_step_cmd in (108, 159) and self._is_same_frame(stop_frame, frame.f_back): + * # trace function for showing return values after step over + * can_skip = False # <<<<<<<<<<<<<< + * + * # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint, + */ + __pyx_v_can_skip = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":960 + * can_skip = plugin_manager.can_skip(main_debugger, frame) + * + * if can_skip and main_debugger.show_return_values and info.pydev_step_cmd in (108, 159) and self._is_same_frame(stop_frame, frame.f_back): # <<<<<<<<<<<<<< + * # trace function for showing return values after step over + * can_skip = False + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":955 + * can_skip = True + * + * if can_skip: # <<<<<<<<<<<<<< + * if plugin_manager is not None and ( + * main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":921 + * can_skip = False + * + * if info.pydev_state == 1: # 1 = 1 # <<<<<<<<<<<<<< + * # we can skip if: + * # - we have no stop marked + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":969 + * # so, that's why the additional checks are there. + * + * if function_breakpoint_on_call_event: # <<<<<<<<<<<<<< + * pass # Do nothing here (just keep on going as we can't skip it). + * + */ + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_v_function_breakpoint_on_call_event); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 969, __pyx_L4_error) + if (__pyx_t_9) { + goto __pyx_L71; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":972 + * pass # Do nothing here (just keep on going as we can't skip it). + * + * elif not breakpoints_for_file: # <<<<<<<<<<<<<< + * if can_skip: + * if has_exception_breakpoints: + */ + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_v_breakpoints_for_file); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 972, __pyx_L4_error) + __pyx_t_14 = ((!__pyx_t_9) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":973 + * + * elif not breakpoints_for_file: + * if can_skip: # <<<<<<<<<<<<<< + * if has_exception_breakpoints: + * return self.trace_exception + */ + __pyx_t_14 = (__pyx_v_can_skip != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":974 + * elif not breakpoints_for_file: + * if can_skip: + * if has_exception_breakpoints: # <<<<<<<<<<<<<< + * return self.trace_exception + * else: + */ + __pyx_t_14 = (__pyx_v_has_exception_breakpoints != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":975 + * if can_skip: + * if has_exception_breakpoints: + * return self.trace_exception # <<<<<<<<<<<<<< + * else: + * return None if is_call else NO_FTRACE + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_exception); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 975, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":974 + * elif not breakpoints_for_file: + * if can_skip: + * if has_exception_breakpoints: # <<<<<<<<<<<<<< + * return self.trace_exception + * else: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":977 + * return self.trace_exception + * else: + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * else: + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_4 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 977, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __pyx_t_1; + __pyx_t_1 = 0; + } + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L3_return; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":973 + * + * elif not breakpoints_for_file: + * if can_skip: # <<<<<<<<<<<<<< + * if has_exception_breakpoints: + * return self.trace_exception + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":972 + * pass # Do nothing here (just keep on going as we can't skip it). + * + * elif not breakpoints_for_file: # <<<<<<<<<<<<<< + * if can_skip: + * if has_exception_breakpoints: + */ + goto __pyx_L71; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":981 + * else: + * # When cached, 0 means we don't have a breakpoint and 1 means we have. + * if can_skip: # <<<<<<<<<<<<<< + * breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1) + * if breakpoints_in_line_cache == 0: + */ + /*else*/ { + __pyx_t_14 = (__pyx_v_can_skip != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":982 + * # When cached, 0 means we don't have a breakpoint and 1 means we have. + * if can_skip: + * breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1) # <<<<<<<<<<<<<< + * if breakpoints_in_line_cache == 0: + * return self.trace_dispatch + */ + if (unlikely(__pyx_v_frame_skips_cache == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get"); + __PYX_ERR(0, 982, __pyx_L4_error) + } + __pyx_t_4 = __Pyx_PyDict_GetItemDefault(__pyx_v_frame_skips_cache, __pyx_v_line_cache_key, __pyx_int_neg_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 982, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_4); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 982, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_breakpoints_in_line_cache = __pyx_t_5; + + /* "_pydevd_bundle/pydevd_cython.pyx":983 + * if can_skip: + * breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1) + * if breakpoints_in_line_cache == 0: # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + __pyx_t_14 = ((__pyx_v_breakpoints_in_line_cache == 0) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":984 + * breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1) + * if breakpoints_in_line_cache == 0: + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * breakpoints_in_frame_cache = frame_skips_cache.get(frame_cache_key, -1) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 984, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":983 + * if can_skip: + * breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1) + * if breakpoints_in_line_cache == 0: # <<<<<<<<<<<<<< + * return self.trace_dispatch + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":981 + * else: + * # When cached, 0 means we don't have a breakpoint and 1 means we have. + * if can_skip: # <<<<<<<<<<<<<< + * breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1) + * if breakpoints_in_line_cache == 0: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":986 + * return self.trace_dispatch + * + * breakpoints_in_frame_cache = frame_skips_cache.get(frame_cache_key, -1) # <<<<<<<<<<<<<< + * if breakpoints_in_frame_cache != -1: + * # Gotten from cache. + */ + if (unlikely(__pyx_v_frame_skips_cache == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get"); + __PYX_ERR(0, 986, __pyx_L4_error) + } + __pyx_t_4 = __Pyx_PyDict_GetItemDefault(__pyx_v_frame_skips_cache, __pyx_v_frame_cache_key, __pyx_int_neg_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 986, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_4); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 986, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_breakpoints_in_frame_cache = __pyx_t_5; + + /* "_pydevd_bundle/pydevd_cython.pyx":987 + * + * breakpoints_in_frame_cache = frame_skips_cache.get(frame_cache_key, -1) + * if breakpoints_in_frame_cache != -1: # <<<<<<<<<<<<<< + * # Gotten from cache. + * has_breakpoint_in_frame = breakpoints_in_frame_cache == 1 + */ + __pyx_t_14 = ((__pyx_v_breakpoints_in_frame_cache != -1L) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":989 + * if breakpoints_in_frame_cache != -1: + * # Gotten from cache. + * has_breakpoint_in_frame = breakpoints_in_frame_cache == 1 # <<<<<<<<<<<<<< + * + * else: + */ + __pyx_v_has_breakpoint_in_frame = (__pyx_v_breakpoints_in_frame_cache == 1); + + /* "_pydevd_bundle/pydevd_cython.pyx":987 + * + * breakpoints_in_frame_cache = frame_skips_cache.get(frame_cache_key, -1) + * if breakpoints_in_frame_cache != -1: # <<<<<<<<<<<<<< + * # Gotten from cache. + * has_breakpoint_in_frame = breakpoints_in_frame_cache == 1 + */ + goto __pyx_L76; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":992 + * + * else: + * has_breakpoint_in_frame = False # <<<<<<<<<<<<<< + * + * try: + */ + /*else*/ { + __pyx_v_has_breakpoint_in_frame = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":994 + * has_breakpoint_in_frame = False + * + * try: # <<<<<<<<<<<<<< + * func_lines = set() + * for offset_and_lineno in dis.findlinestarts(frame.f_code): + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_16, &__pyx_t_17, &__pyx_t_18); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __Pyx_XGOTREF(__pyx_t_18); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":995 + * + * try: + * func_lines = set() # <<<<<<<<<<<<<< + * for offset_and_lineno in dis.findlinestarts(frame.f_code): + * func_lines.add(offset_and_lineno[1]) + */ + __pyx_t_4 = PySet_New(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 995, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_func_lines = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":996 + * try: + * func_lines = set() + * for offset_and_lineno in dis.findlinestarts(frame.f_code): # <<<<<<<<<<<<<< + * func_lines.add(offset_and_lineno[1]) + * except: + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_dis); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 996, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_findlinestarts); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 996, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 996, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_4 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_3, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 996, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (likely(PyList_CheckExact(__pyx_t_4)) || PyTuple_CheckExact(__pyx_t_4)) { + __pyx_t_7 = __pyx_t_4; __Pyx_INCREF(__pyx_t_7); __pyx_t_12 = 0; + __pyx_t_13 = NULL; + } else { + __pyx_t_12 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 996, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_13 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 996, __pyx_L77_error) + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + for (;;) { + if (likely(!__pyx_t_13)) { + if (likely(PyList_CheckExact(__pyx_t_7))) { + if (__pyx_t_12 >= PyList_GET_SIZE(__pyx_t_7)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_4); __pyx_t_12++; if (unlikely(0 < 0)) __PYX_ERR(0, 996, __pyx_L77_error) + #else + __pyx_t_4 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 996, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } else { + if (__pyx_t_12 >= PyTuple_GET_SIZE(__pyx_t_7)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_4); __pyx_t_12++; if (unlikely(0 < 0)) __PYX_ERR(0, 996, __pyx_L77_error) + #else + __pyx_t_4 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 996, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } + } else { + __pyx_t_4 = __pyx_t_13(__pyx_t_7); + if (unlikely(!__pyx_t_4)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 996, __pyx_L77_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_4); + } + __Pyx_XDECREF_SET(__pyx_v_offset_and_lineno, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":997 + * func_lines = set() + * for offset_and_lineno in dis.findlinestarts(frame.f_code): + * func_lines.add(offset_and_lineno[1]) # <<<<<<<<<<<<<< + * except: + * # This is a fallback for implementations where we can't get the function + */ + __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_offset_and_lineno, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 997, __pyx_L77_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_19 = PySet_Add(__pyx_v_func_lines, __pyx_t_4); if (unlikely(__pyx_t_19 == ((int)-1))) __PYX_ERR(0, 997, __pyx_L77_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":996 + * try: + * func_lines = set() + * for offset_and_lineno in dis.findlinestarts(frame.f_code): # <<<<<<<<<<<<<< + * func_lines.add(offset_and_lineno[1]) + * except: + */ + } + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":994 + * has_breakpoint_in_frame = False + * + * try: # <<<<<<<<<<<<<< + * func_lines = set() + * for offset_and_lineno in dis.findlinestarts(frame.f_code): + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1017 + * break + * else: + * for bp_line in breakpoints_for_file: # iterate on keys # <<<<<<<<<<<<<< + * if bp_line in func_lines: + * has_breakpoint_in_frame = True + */ + /*else:*/ { + __pyx_t_12 = 0; + if (unlikely(__pyx_v_breakpoints_for_file == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 1017, __pyx_L79_except_error) + } + __pyx_t_4 = __Pyx_dict_iterator(__pyx_v_breakpoints_for_file, 1, ((PyObject *)NULL), (&__pyx_t_20), (&__pyx_t_5)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1017, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_7); + __pyx_t_7 = __pyx_t_4; + __pyx_t_4 = 0; + while (1) { + __pyx_t_10 = __Pyx_dict_iter_next(__pyx_t_7, __pyx_t_20, &__pyx_t_12, &__pyx_t_4, NULL, NULL, __pyx_t_5); + if (unlikely(__pyx_t_10 == 0)) break; + if (unlikely(__pyx_t_10 == -1)) __PYX_ERR(0, 1017, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_10 = __Pyx_PyInt_As_int(__pyx_t_4); if (unlikely((__pyx_t_10 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1017, __pyx_L79_except_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_bp_line = __pyx_t_10; + + /* "_pydevd_bundle/pydevd_cython.pyx":1018 + * else: + * for bp_line in breakpoints_for_file: # iterate on keys + * if bp_line in func_lines: # <<<<<<<<<<<<<< + * has_breakpoint_in_frame = True + * break + */ + __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_bp_line); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1018, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_14 = (__Pyx_PySet_ContainsTF(__pyx_t_4, __pyx_v_func_lines, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1018, __pyx_L79_except_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1019 + * for bp_line in breakpoints_for_file: # iterate on keys + * if bp_line in func_lines: + * has_breakpoint_in_frame = True # <<<<<<<<<<<<<< + * break + * + */ + __pyx_v_has_breakpoint_in_frame = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1020 + * if bp_line in func_lines: + * has_breakpoint_in_frame = True + * break # <<<<<<<<<<<<<< + * + * # Cache the value (1 or 0 or -1 for default because of cython). + */ + goto __pyx_L86_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1018 + * else: + * for bp_line in breakpoints_for_file: # iterate on keys + * if bp_line in func_lines: # <<<<<<<<<<<<<< + * has_breakpoint_in_frame = True + * break + */ + } + } + __pyx_L86_break:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_18); __pyx_t_18 = 0; + goto __pyx_L82_try_end; + __pyx_L77_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":998 + * for offset_and_lineno in dis.findlinestarts(frame.f_code): + * func_lines.add(offset_and_lineno[1]) + * except: # <<<<<<<<<<<<<< + * # This is a fallback for implementations where we can't get the function + * # lines -- i.e.: jython (in this case clients need to provide the function + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_4, &__pyx_t_1) < 0) __PYX_ERR(0, 998, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_1); + + /* "_pydevd_bundle/pydevd_cython.pyx":1005 + * + * # Checks the breakpoint to see if there is a context match in some function. + * curr_func_name = frame.f_code.co_name # <<<<<<<<<<<<<< + * + * # global context is set with an empty name + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1005, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1005, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (!(likely(PyString_CheckExact(__pyx_t_6))||((__pyx_t_6) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_6)->tp_name), 0))) __PYX_ERR(0, 1005, __pyx_L79_except_error) + __pyx_v_curr_func_name = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1008 + * + * # global context is set with an empty name + * if curr_func_name in ('?', '', ''): # <<<<<<<<<<<<<< + * curr_func_name = '' + * + */ + __Pyx_INCREF(__pyx_v_curr_func_name); + __pyx_t_21 = __pyx_v_curr_func_name; + __pyx_t_14 = (__Pyx_PyString_Equals(__pyx_t_21, __pyx_kp_s__3, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1008, __pyx_L79_except_error) + __pyx_t_11 = (__pyx_t_14 != 0); + if (!__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L91_bool_binop_done; + } + __pyx_t_11 = (__Pyx_PyString_Equals(__pyx_t_21, __pyx_kp_s_module, Py_EQ)); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1008, __pyx_L79_except_error) + __pyx_t_14 = (__pyx_t_11 != 0); + if (!__pyx_t_14) { + } else { + __pyx_t_9 = __pyx_t_14; + goto __pyx_L91_bool_binop_done; + } + __pyx_t_14 = (__Pyx_PyString_Equals(__pyx_t_21, __pyx_kp_s_lambda, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1008, __pyx_L79_except_error) + __pyx_t_11 = (__pyx_t_14 != 0); + __pyx_t_9 = __pyx_t_11; + __pyx_L91_bool_binop_done:; + __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0; + __pyx_t_11 = (__pyx_t_9 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1009 + * # global context is set with an empty name + * if curr_func_name in ('?', '', ''): + * curr_func_name = '' # <<<<<<<<<<<<<< + * + * for bp in breakpoints_for_file.values(): + */ + __Pyx_INCREF(__pyx_kp_s_); + __Pyx_DECREF_SET(__pyx_v_curr_func_name, __pyx_kp_s_); + + /* "_pydevd_bundle/pydevd_cython.pyx":1008 + * + * # global context is set with an empty name + * if curr_func_name in ('?', '', ''): # <<<<<<<<<<<<<< + * curr_func_name = '' + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1011 + * curr_func_name = '' + * + * for bp in breakpoints_for_file.values(): # <<<<<<<<<<<<<< + * # will match either global or some function + * if bp.func_name in ('None', curr_func_name): + */ + if (unlikely(__pyx_v_breakpoints_for_file == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "values"); + __PYX_ERR(0, 1011, __pyx_L79_except_error) + } + __pyx_t_6 = __Pyx_PyDict_Values(__pyx_v_breakpoints_for_file); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1011, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_6); + if (likely(PyList_CheckExact(__pyx_t_6)) || PyTuple_CheckExact(__pyx_t_6)) { + __pyx_t_3 = __pyx_t_6; __Pyx_INCREF(__pyx_t_3); __pyx_t_20 = 0; + __pyx_t_13 = NULL; + } else { + __pyx_t_20 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1011, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_13 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 1011, __pyx_L79_except_error) + } + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + for (;;) { + if (likely(!__pyx_t_13)) { + if (likely(PyList_CheckExact(__pyx_t_3))) { + if (__pyx_t_20 >= PyList_GET_SIZE(__pyx_t_3)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_6 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_20); __Pyx_INCREF(__pyx_t_6); __pyx_t_20++; if (unlikely(0 < 0)) __PYX_ERR(0, 1011, __pyx_L79_except_error) + #else + __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_20); __pyx_t_20++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1011, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_6); + #endif + } else { + if (__pyx_t_20 >= PyTuple_GET_SIZE(__pyx_t_3)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_20); __Pyx_INCREF(__pyx_t_6); __pyx_t_20++; if (unlikely(0 < 0)) __PYX_ERR(0, 1011, __pyx_L79_except_error) + #else + __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_20); __pyx_t_20++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1011, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_6); + #endif + } + } else { + __pyx_t_6 = __pyx_t_13(__pyx_t_3); + if (unlikely(!__pyx_t_6)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 1011, __pyx_L79_except_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_6); + } + __Pyx_XDECREF_SET(__pyx_v_bp, __pyx_t_6); + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1013 + * for bp in breakpoints_for_file.values(): + * # will match either global or some function + * if bp.func_name in ('None', curr_func_name): # <<<<<<<<<<<<<< + * has_breakpoint_in_frame = True + * break + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_bp, __pyx_n_s_func_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1013, __pyx_L79_except_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_9 = (__Pyx_PyString_Equals(__pyx_t_6, __pyx_n_s_None, Py_EQ)); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1013, __pyx_L79_except_error) + if (!__pyx_t_9) { + } else { + __pyx_t_11 = __pyx_t_9; + goto __pyx_L97_bool_binop_done; + } + __pyx_t_9 = (__Pyx_PyString_Equals(__pyx_t_6, __pyx_v_curr_func_name, Py_EQ)); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1013, __pyx_L79_except_error) + __pyx_t_11 = __pyx_t_9; + __pyx_L97_bool_binop_done:; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_9 = (__pyx_t_11 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1014 + * # will match either global or some function + * if bp.func_name in ('None', curr_func_name): + * has_breakpoint_in_frame = True # <<<<<<<<<<<<<< + * break + * else: + */ + __pyx_v_has_breakpoint_in_frame = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1015 + * if bp.func_name in ('None', curr_func_name): + * has_breakpoint_in_frame = True + * break # <<<<<<<<<<<<<< + * else: + * for bp_line in breakpoints_for_file: # iterate on keys + */ + goto __pyx_L95_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1013 + * for bp in breakpoints_for_file.values(): + * # will match either global or some function + * if bp.func_name in ('None', curr_func_name): # <<<<<<<<<<<<<< + * has_breakpoint_in_frame = True + * break + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1011 + * curr_func_name = '' + * + * for bp in breakpoints_for_file.values(): # <<<<<<<<<<<<<< + * # will match either global or some function + * if bp.func_name in ('None', curr_func_name): + */ + } + __pyx_L95_break:; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L78_exception_handled; + } + __pyx_L79_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":994 + * has_breakpoint_in_frame = False + * + * try: # <<<<<<<<<<<<<< + * func_lines = set() + * for offset_and_lineno in dis.findlinestarts(frame.f_code): + */ + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_ExceptionReset(__pyx_t_16, __pyx_t_17, __pyx_t_18); + goto __pyx_L4_error; + __pyx_L78_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_ExceptionReset(__pyx_t_16, __pyx_t_17, __pyx_t_18); + __pyx_L82_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1023 + * + * # Cache the value (1 or 0 or -1 for default because of cython). + * if has_breakpoint_in_frame: # <<<<<<<<<<<<<< + * frame_skips_cache[frame_cache_key] = 1 + * else: + */ + __pyx_t_9 = (__pyx_v_has_breakpoint_in_frame != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1024 + * # Cache the value (1 or 0 or -1 for default because of cython). + * if has_breakpoint_in_frame: + * frame_skips_cache[frame_cache_key] = 1 # <<<<<<<<<<<<<< + * else: + * frame_skips_cache[frame_cache_key] = 0 + */ + if (unlikely(__pyx_v_frame_skips_cache == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1024, __pyx_L4_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_frame_skips_cache, __pyx_v_frame_cache_key, __pyx_int_1) < 0)) __PYX_ERR(0, 1024, __pyx_L4_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1023 + * + * # Cache the value (1 or 0 or -1 for default because of cython). + * if has_breakpoint_in_frame: # <<<<<<<<<<<<<< + * frame_skips_cache[frame_cache_key] = 1 + * else: + */ + goto __pyx_L99; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1026 + * frame_skips_cache[frame_cache_key] = 1 + * else: + * frame_skips_cache[frame_cache_key] = 0 # <<<<<<<<<<<<<< + * + * if can_skip and not has_breakpoint_in_frame: + */ + /*else*/ { + if (unlikely(__pyx_v_frame_skips_cache == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1026, __pyx_L4_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_frame_skips_cache, __pyx_v_frame_cache_key, __pyx_int_0) < 0)) __PYX_ERR(0, 1026, __pyx_L4_error) + } + __pyx_L99:; + } + __pyx_L76:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1028 + * frame_skips_cache[frame_cache_key] = 0 + * + * if can_skip and not has_breakpoint_in_frame: # <<<<<<<<<<<<<< + * if has_exception_breakpoints: + * return self.trace_exception + */ + __pyx_t_11 = (__pyx_v_can_skip != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L101_bool_binop_done; + } + __pyx_t_11 = ((!(__pyx_v_has_breakpoint_in_frame != 0)) != 0); + __pyx_t_9 = __pyx_t_11; + __pyx_L101_bool_binop_done:; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1029 + * + * if can_skip and not has_breakpoint_in_frame: + * if has_exception_breakpoints: # <<<<<<<<<<<<<< + * return self.trace_exception + * else: + */ + __pyx_t_9 = (__pyx_v_has_exception_breakpoints != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1030 + * if can_skip and not has_breakpoint_in_frame: + * if has_exception_breakpoints: + * return self.trace_exception # <<<<<<<<<<<<<< + * else: + * return None if is_call else NO_FTRACE + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_exception); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1030, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1029 + * + * if can_skip and not has_breakpoint_in_frame: + * if has_exception_breakpoints: # <<<<<<<<<<<<<< + * return self.trace_exception + * else: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1032 + * return self.trace_exception + * else: + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * # We may have hit a breakpoint or we are already in step mode. Either way, let's check what we should do in this frame + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1032, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __pyx_t_4; + __pyx_t_4 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L3_return; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1028 + * frame_skips_cache[frame_cache_key] = 0 + * + * if can_skip and not has_breakpoint_in_frame: # <<<<<<<<<<<<<< + * if has_exception_breakpoints: + * return self.trace_exception + */ + } + } + __pyx_L71:; + + /* "_pydevd_bundle/pydevd_cython.pyx":916 + * return self.trace_dispatch + * + * if not is_exception_event: # <<<<<<<<<<<<<< + * breakpoints_for_file = main_debugger.breakpoints.get(abs_path_canonical_path_and_base[1]) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1037 + * # if DEBUG: print('NOT skipped: %s %s %s %s' % (frame.f_lineno, frame.f_code.co_name, event, frame.__class__.__name__)) + * + * try: # <<<<<<<<<<<<<< + * flag = False + * # return is not taken into account for breakpoint hit because we'd have a double-hit in this case + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_18, &__pyx_t_17, &__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_18); + __Pyx_XGOTREF(__pyx_t_17); + __Pyx_XGOTREF(__pyx_t_16); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1038 + * + * try: + * flag = False # <<<<<<<<<<<<<< + * # return is not taken into account for breakpoint hit because we'd have a double-hit in this case + * # (one for the line and the other for the return). + */ + __Pyx_INCREF(Py_False); + __pyx_v_flag = Py_False; + + /* "_pydevd_bundle/pydevd_cython.pyx":1042 + * # (one for the line and the other for the return). + * + * stop_info = {} # <<<<<<<<<<<<<< + * breakpoint = None + * exist_result = False + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1042, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_stop_info = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1043 + * + * stop_info = {} + * breakpoint = None # <<<<<<<<<<<<<< + * exist_result = False + * stop = False + */ + __Pyx_INCREF(Py_None); + __pyx_v_breakpoint = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":1044 + * stop_info = {} + * breakpoint = None + * exist_result = False # <<<<<<<<<<<<<< + * stop = False + * stop_reason = 111 + */ + __pyx_v_exist_result = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1045 + * breakpoint = None + * exist_result = False + * stop = False # <<<<<<<<<<<<<< + * stop_reason = 111 + * bp_type = None + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1046 + * exist_result = False + * stop = False + * stop_reason = 111 # <<<<<<<<<<<<<< + * bp_type = None + * + */ + __Pyx_INCREF(__pyx_int_111); + __pyx_v_stop_reason = __pyx_int_111; + + /* "_pydevd_bundle/pydevd_cython.pyx":1047 + * stop = False + * stop_reason = 111 + * bp_type = None # <<<<<<<<<<<<<< + * + * if function_breakpoint_on_call_event: + */ + __Pyx_INCREF(Py_None); + __pyx_v_bp_type = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":1049 + * bp_type = None + * + * if function_breakpoint_on_call_event: # <<<<<<<<<<<<<< + * breakpoint = function_breakpoint_on_call_event + * stop = True + */ + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_v_function_breakpoint_on_call_event); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1049, __pyx_L104_error) + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1050 + * + * if function_breakpoint_on_call_event: + * breakpoint = function_breakpoint_on_call_event # <<<<<<<<<<<<<< + * stop = True + * new_frame = frame + */ + __Pyx_INCREF(__pyx_v_function_breakpoint_on_call_event); + __Pyx_DECREF_SET(__pyx_v_breakpoint, __pyx_v_function_breakpoint_on_call_event); + + /* "_pydevd_bundle/pydevd_cython.pyx":1051 + * if function_breakpoint_on_call_event: + * breakpoint = function_breakpoint_on_call_event + * stop = True # <<<<<<<<<<<<<< + * new_frame = frame + * stop_reason = CMD_SET_FUNCTION_BREAK + */ + __pyx_v_stop = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1052 + * breakpoint = function_breakpoint_on_call_event + * stop = True + * new_frame = frame # <<<<<<<<<<<<<< + * stop_reason = CMD_SET_FUNCTION_BREAK + * + */ + __Pyx_INCREF(__pyx_v_frame); + __pyx_v_new_frame = __pyx_v_frame; + + /* "_pydevd_bundle/pydevd_cython.pyx":1053 + * stop = True + * new_frame = frame + * stop_reason = CMD_SET_FUNCTION_BREAK # <<<<<<<<<<<<<< + * + * elif is_line and info.pydev_state != 2 and breakpoints_for_file is not None and line in breakpoints_for_file: + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_CMD_SET_FUNCTION_BREAK); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1053, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_stop_reason, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1049 + * bp_type = None + * + * if function_breakpoint_on_call_event: # <<<<<<<<<<<<<< + * breakpoint = function_breakpoint_on_call_event + * stop = True + */ + goto __pyx_L110; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1055 + * stop_reason = CMD_SET_FUNCTION_BREAK + * + * elif is_line and info.pydev_state != 2 and breakpoints_for_file is not None and line in breakpoints_for_file: # <<<<<<<<<<<<<< + * breakpoint = breakpoints_for_file[line] + * new_frame = frame + */ + __pyx_t_11 = (__pyx_v_is_line != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L111_bool_binop_done; + } + __pyx_t_11 = ((__pyx_v_info->pydev_state != 2) != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L111_bool_binop_done; + } + if (unlikely(!__pyx_v_breakpoints_for_file)) { __Pyx_RaiseUnboundLocalError("breakpoints_for_file"); __PYX_ERR(0, 1055, __pyx_L104_error) } + __pyx_t_11 = (__pyx_v_breakpoints_for_file != ((PyObject*)Py_None)); + __pyx_t_14 = (__pyx_t_11 != 0); + if (__pyx_t_14) { + } else { + __pyx_t_9 = __pyx_t_14; + goto __pyx_L111_bool_binop_done; + } + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1055, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_1); + if (unlikely(!__pyx_v_breakpoints_for_file)) { __Pyx_RaiseUnboundLocalError("breakpoints_for_file"); __PYX_ERR(0, 1055, __pyx_L104_error) } + if (unlikely(__pyx_v_breakpoints_for_file == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 1055, __pyx_L104_error) + } + __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_t_1, __pyx_v_breakpoints_for_file, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1055, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_11 = (__pyx_t_14 != 0); + __pyx_t_9 = __pyx_t_11; + __pyx_L111_bool_binop_done:; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1056 + * + * elif is_line and info.pydev_state != 2 and breakpoints_for_file is not None and line in breakpoints_for_file: + * breakpoint = breakpoints_for_file[line] # <<<<<<<<<<<<<< + * new_frame = frame + * stop = True + */ + if (unlikely(!__pyx_v_breakpoints_for_file)) { __Pyx_RaiseUnboundLocalError("breakpoints_for_file"); __PYX_ERR(0, 1056, __pyx_L104_error) } + if (unlikely(__pyx_v_breakpoints_for_file == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1056, __pyx_L104_error) + } + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1056, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v_breakpoints_for_file, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1056, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_breakpoint, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1057 + * elif is_line and info.pydev_state != 2 and breakpoints_for_file is not None and line in breakpoints_for_file: + * breakpoint = breakpoints_for_file[line] + * new_frame = frame # <<<<<<<<<<<<<< + * stop = True + * if step_cmd in (108, 159) and (self._is_same_frame(stop_frame, frame) and is_line): + */ + __Pyx_INCREF(__pyx_v_frame); + __pyx_v_new_frame = __pyx_v_frame; + + /* "_pydevd_bundle/pydevd_cython.pyx":1058 + * breakpoint = breakpoints_for_file[line] + * new_frame = frame + * stop = True # <<<<<<<<<<<<<< + * if step_cmd in (108, 159) and (self._is_same_frame(stop_frame, frame) and is_line): + * stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) + */ + __pyx_v_stop = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1059 + * new_frame = frame + * stop = True + * if step_cmd in (108, 159) and (self._is_same_frame(stop_frame, frame) and is_line): # <<<<<<<<<<<<<< + * stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) + * elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: + */ + switch (__pyx_v_step_cmd) { + case 0x6C: + case 0x9F: + __pyx_t_11 = 1; + break; + default: + __pyx_t_11 = 0; + break; + } + __pyx_t_14 = (__pyx_t_11 != 0); + if (__pyx_t_14) { + } else { + __pyx_t_9 = __pyx_t_14; + goto __pyx_L116_bool_binop_done; + } + __pyx_t_4 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_frame); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1059, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1059, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_14) { + } else { + __pyx_t_9 = __pyx_t_14; + goto __pyx_L116_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_is_line != 0); + __pyx_t_9 = __pyx_t_14; + __pyx_L116_bool_binop_done:; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1060 + * stop = True + * if step_cmd in (108, 159) and (self._is_same_frame(stop_frame, frame) and is_line): + * stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) # <<<<<<<<<<<<<< + * elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: + * result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1059 + * new_frame = frame + * stop = True + * if step_cmd in (108, 159) and (self._is_same_frame(stop_frame, frame) and is_line): # <<<<<<<<<<<<<< + * stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) + * elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1055 + * stop_reason = CMD_SET_FUNCTION_BREAK + * + * elif is_line and info.pydev_state != 2 and breakpoints_for_file is not None and line in breakpoints_for_file: # <<<<<<<<<<<<<< + * breakpoint = breakpoints_for_file[line] + * new_frame = frame + */ + goto __pyx_L110; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1061 + * if step_cmd in (108, 159) and (self._is_same_frame(stop_frame, frame) and is_line): + * stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) + * elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: # <<<<<<<<<<<<<< + * result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) + * if result: + */ + __pyx_t_14 = (__pyx_v_plugin_manager != Py_None); + __pyx_t_11 = (__pyx_t_14 != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L119_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_line_breaks); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1061, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1061, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = __pyx_t_11; + __pyx_L119_bool_binop_done:; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1062 + * stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) + * elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: + * result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) # <<<<<<<<<<<<<< + * if result: + * exist_result = True + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_plugin_manager, __pyx_n_s_get_breakpoint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1062, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[6] = {__pyx_t_7, __pyx_v_main_debugger, ((PyObject *)__pyx_v_self), __pyx_v_frame, __pyx_v_event, __pyx_v_self->_args}; + __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_5, 5+__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1062, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[6] = {__pyx_t_7, __pyx_v_main_debugger, ((PyObject *)__pyx_v_self), __pyx_v_frame, __pyx_v_event, __pyx_v_self->_args}; + __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_5, 5+__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1062, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + { + __pyx_t_3 = PyTuple_New(5+__pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1062, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_7) { + __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7); __pyx_t_7 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_5, __pyx_v_main_debugger); + __Pyx_INCREF(((PyObject *)__pyx_v_self)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_5, ((PyObject *)__pyx_v_self)); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_3, 2+__pyx_t_5, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_3, 3+__pyx_t_5, __pyx_v_event); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_3, 4+__pyx_t_5, __pyx_v_self->_args); + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1062, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1063 + * elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: + * result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) + * if result: # <<<<<<<<<<<<<< + * exist_result = True + * flag, breakpoint, new_frame, bp_type = result + */ + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_v_result); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1063, __pyx_L104_error) + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1064 + * result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) + * if result: + * exist_result = True # <<<<<<<<<<<<<< + * flag, breakpoint, new_frame, bp_type = result + * + */ + __pyx_v_exist_result = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1065 + * if result: + * exist_result = True + * flag, breakpoint, new_frame, bp_type = result # <<<<<<<<<<<<<< + * + * if breakpoint: + */ + if ((likely(PyTuple_CheckExact(__pyx_v_result))) || (PyList_CheckExact(__pyx_v_result))) { + PyObject* sequence = __pyx_v_result; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 4)) { + if (size > 4) __Pyx_RaiseTooManyValuesError(4); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 1065, __pyx_L104_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 3); + } else { + __pyx_t_4 = PyList_GET_ITEM(sequence, 0); + __pyx_t_1 = PyList_GET_ITEM(sequence, 1); + __pyx_t_3 = PyList_GET_ITEM(sequence, 2); + __pyx_t_7 = PyList_GET_ITEM(sequence, 3); + } + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + #else + { + Py_ssize_t i; + PyObject** temps[4] = {&__pyx_t_4,&__pyx_t_1,&__pyx_t_3,&__pyx_t_7}; + for (i=0; i < 4; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 1065, __pyx_L104_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + } else { + Py_ssize_t index = -1; + PyObject** temps[4] = {&__pyx_t_4,&__pyx_t_1,&__pyx_t_3,&__pyx_t_7}; + __pyx_t_6 = PyObject_GetIter(__pyx_v_result); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1065, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_15 = Py_TYPE(__pyx_t_6)->tp_iternext; + for (index=0; index < 4; index++) { + PyObject* item = __pyx_t_15(__pyx_t_6); if (unlikely(!item)) goto __pyx_L122_unpacking_failed; + __Pyx_GOTREF(item); + *(temps[index]) = item; + } + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_6), 4) < 0) __PYX_ERR(0, 1065, __pyx_L104_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L123_unpacking_done; + __pyx_L122_unpacking_failed:; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 1065, __pyx_L104_error) + __pyx_L123_unpacking_done:; + } + __Pyx_DECREF_SET(__pyx_v_flag, __pyx_t_4); + __pyx_t_4 = 0; + __Pyx_DECREF_SET(__pyx_v_breakpoint, __pyx_t_1); + __pyx_t_1 = 0; + __pyx_v_new_frame = __pyx_t_3; + __pyx_t_3 = 0; + __Pyx_DECREF_SET(__pyx_v_bp_type, __pyx_t_7); + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1063 + * elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: + * result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) + * if result: # <<<<<<<<<<<<<< + * exist_result = True + * flag, breakpoint, new_frame, bp_type = result + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1061 + * if step_cmd in (108, 159) and (self._is_same_frame(stop_frame, frame) and is_line): + * stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) + * elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: # <<<<<<<<<<<<<< + * result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) + * if result: + */ + } + __pyx_L110:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1067 + * flag, breakpoint, new_frame, bp_type = result + * + * if breakpoint: # <<<<<<<<<<<<<< + * # ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint + * # lets do the conditional stuff here + */ + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_v_breakpoint); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1067, __pyx_L104_error) + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1070 + * # ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint + * # lets do the conditional stuff here + * if breakpoint.expression is not None: # <<<<<<<<<<<<<< + * main_debugger.handle_breakpoint_expression(breakpoint, info, new_frame) + * if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_breakpoint, __pyx_n_s_expression); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1070, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = (__pyx_t_7 != Py_None); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_11 = (__pyx_t_9 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1071 + * # lets do the conditional stuff here + * if breakpoint.expression is not None: + * main_debugger.handle_breakpoint_expression(breakpoint, info, new_frame) # <<<<<<<<<<<<<< + * if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: + * cmd = main_debugger.cmd_factory.make_io_message(info.pydev_message + os.linesep, '1') + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_handle_breakpoint_expression); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1071, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_3); + if (unlikely(!__pyx_v_new_frame)) { __Pyx_RaiseUnboundLocalError("new_frame"); __PYX_ERR(0, 1071, __pyx_L104_error) } + __pyx_t_1 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[4] = {__pyx_t_1, __pyx_v_breakpoint, ((PyObject *)__pyx_v_info), __pyx_v_new_frame}; + __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1071, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[4] = {__pyx_t_1, __pyx_v_breakpoint, ((PyObject *)__pyx_v_info), __pyx_v_new_frame}; + __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1071, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + } else + #endif + { + __pyx_t_4 = PyTuple_New(3+__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1071, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + if (__pyx_t_1) { + __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); __pyx_t_1 = NULL; + } + __Pyx_INCREF(__pyx_v_breakpoint); + __Pyx_GIVEREF(__pyx_v_breakpoint); + PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_5, __pyx_v_breakpoint); + __Pyx_INCREF(((PyObject *)__pyx_v_info)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_info)); + PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_5, ((PyObject *)__pyx_v_info)); + __Pyx_INCREF(__pyx_v_new_frame); + __Pyx_GIVEREF(__pyx_v_new_frame); + PyTuple_SET_ITEM(__pyx_t_4, 2+__pyx_t_5, __pyx_v_new_frame); + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1071, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1072 + * if breakpoint.expression is not None: + * main_debugger.handle_breakpoint_expression(breakpoint, info, new_frame) + * if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: # <<<<<<<<<<<<<< + * cmd = main_debugger.cmd_factory.make_io_message(info.pydev_message + os.linesep, '1') + * main_debugger.writer.add_command(cmd) + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_breakpoint, __pyx_n_s_is_logpoint); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1072, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1072, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_9) { + } else { + __pyx_t_11 = __pyx_t_9; + goto __pyx_L127_bool_binop_done; + } + __pyx_t_9 = (__pyx_v_info->pydev_message != ((PyObject*)Py_None)); + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L127_bool_binop_done; + } + __pyx_t_7 = __pyx_v_info->pydev_message; + __Pyx_INCREF(__pyx_t_7); + __pyx_t_20 = PyObject_Length(__pyx_t_7); if (unlikely(__pyx_t_20 == ((Py_ssize_t)-1))) __PYX_ERR(0, 1072, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_14 = ((__pyx_t_20 > 0) != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L127_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1073 + * main_debugger.handle_breakpoint_expression(breakpoint, info, new_frame) + * if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: + * cmd = main_debugger.cmd_factory.make_io_message(info.pydev_message + os.linesep, '1') # <<<<<<<<<<<<<< + * main_debugger.writer.add_command(cmd) + * + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_cmd_factory); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_make_io_message); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_os); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_linesep); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyNumber_Add(__pyx_v_info->pydev_message, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_3, __pyx_kp_s_1}; + __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_3, __pyx_kp_s_1}; + __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else + #endif + { + __pyx_t_6 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + if (__pyx_t_1) { + __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1); __pyx_t_1 = NULL; + } + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_5, __pyx_t_3); + __Pyx_INCREF(__pyx_kp_s_1); + __Pyx_GIVEREF(__pyx_kp_s_1); + PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, __pyx_kp_s_1); + __pyx_t_3 = 0; + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1073, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_cmd = __pyx_t_7; + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1074 + * if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: + * cmd = main_debugger.cmd_factory.make_io_message(info.pydev_message + os.linesep, '1') + * main_debugger.writer.add_command(cmd) # <<<<<<<<<<<<<< + * + * if stop or exist_result: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_writer); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1074, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_add_command); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1074, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + } + } + __pyx_t_7 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_4, __pyx_v_cmd) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_cmd); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1074, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1072 + * if breakpoint.expression is not None: + * main_debugger.handle_breakpoint_expression(breakpoint, info, new_frame) + * if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: # <<<<<<<<<<<<<< + * cmd = main_debugger.cmd_factory.make_io_message(info.pydev_message + os.linesep, '1') + * main_debugger.writer.add_command(cmd) + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1070 + * # ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint + * # lets do the conditional stuff here + * if breakpoint.expression is not None: # <<<<<<<<<<<<<< + * main_debugger.handle_breakpoint_expression(breakpoint, info, new_frame) + * if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1076 + * main_debugger.writer.add_command(cmd) + * + * if stop or exist_result: # <<<<<<<<<<<<<< + * eval_result = False + * if breakpoint.has_condition: + */ + __pyx_t_14 = (__pyx_v_stop != 0); + if (!__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L131_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_exist_result != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L131_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1077 + * + * if stop or exist_result: + * eval_result = False # <<<<<<<<<<<<<< + * if breakpoint.has_condition: + * eval_result = main_debugger.handle_breakpoint_condition(info, breakpoint, new_frame) + */ + __Pyx_INCREF(Py_False); + __pyx_v_eval_result = Py_False; + + /* "_pydevd_bundle/pydevd_cython.pyx":1078 + * if stop or exist_result: + * eval_result = False + * if breakpoint.has_condition: # <<<<<<<<<<<<<< + * eval_result = main_debugger.handle_breakpoint_condition(info, breakpoint, new_frame) + * + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_breakpoint, __pyx_n_s_has_condition); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1078, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1078, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1079 + * eval_result = False + * if breakpoint.has_condition: + * eval_result = main_debugger.handle_breakpoint_condition(info, breakpoint, new_frame) # <<<<<<<<<<<<<< + * + * if breakpoint.has_condition: + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_handle_breakpoint_condition); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1079, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + if (unlikely(!__pyx_v_new_frame)) { __Pyx_RaiseUnboundLocalError("new_frame"); __PYX_ERR(0, 1079, __pyx_L104_error) } + __pyx_t_4 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[4] = {__pyx_t_4, ((PyObject *)__pyx_v_info), __pyx_v_breakpoint, __pyx_v_new_frame}; + __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1079, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_7); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[4] = {__pyx_t_4, ((PyObject *)__pyx_v_info), __pyx_v_breakpoint, __pyx_v_new_frame}; + __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1079, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_7); + } else + #endif + { + __pyx_t_3 = PyTuple_New(3+__pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1079, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); __pyx_t_4 = NULL; + } + __Pyx_INCREF(((PyObject *)__pyx_v_info)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_info)); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_5, ((PyObject *)__pyx_v_info)); + __Pyx_INCREF(__pyx_v_breakpoint); + __Pyx_GIVEREF(__pyx_v_breakpoint); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_5, __pyx_v_breakpoint); + __Pyx_INCREF(__pyx_v_new_frame); + __Pyx_GIVEREF(__pyx_v_new_frame); + PyTuple_SET_ITEM(__pyx_t_3, 2+__pyx_t_5, __pyx_v_new_frame); + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_3, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1079, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF_SET(__pyx_v_eval_result, __pyx_t_7); + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1078 + * if stop or exist_result: + * eval_result = False + * if breakpoint.has_condition: # <<<<<<<<<<<<<< + * eval_result = main_debugger.handle_breakpoint_condition(info, breakpoint, new_frame) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1081 + * eval_result = main_debugger.handle_breakpoint_condition(info, breakpoint, new_frame) + * + * if breakpoint.has_condition: # <<<<<<<<<<<<<< + * if not eval_result: + * stop = False + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_breakpoint, __pyx_n_s_has_condition); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1081, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1081, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1082 + * + * if breakpoint.has_condition: + * if not eval_result: # <<<<<<<<<<<<<< + * stop = False + * elif breakpoint.is_logpoint: + */ + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_v_eval_result); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1082, __pyx_L104_error) + __pyx_t_14 = ((!__pyx_t_11) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1083 + * if breakpoint.has_condition: + * if not eval_result: + * stop = False # <<<<<<<<<<<<<< + * elif breakpoint.is_logpoint: + * stop = False + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1082 + * + * if breakpoint.has_condition: + * if not eval_result: # <<<<<<<<<<<<<< + * stop = False + * elif breakpoint.is_logpoint: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1081 + * eval_result = main_debugger.handle_breakpoint_condition(info, breakpoint, new_frame) + * + * if breakpoint.has_condition: # <<<<<<<<<<<<<< + * if not eval_result: + * stop = False + */ + goto __pyx_L134; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1084 + * if not eval_result: + * stop = False + * elif breakpoint.is_logpoint: # <<<<<<<<<<<<<< + * stop = False + * + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_breakpoint, __pyx_n_s_is_logpoint); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1084, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1084, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1085 + * stop = False + * elif breakpoint.is_logpoint: + * stop = False # <<<<<<<<<<<<<< + * + * if is_call and (frame.f_code.co_name in ('', '') or (line == 1 and frame.f_code.co_name.startswith('', '') or (line == 1 and frame.f_code.co_name.startswith('. + * + * return self.trace_dispatch # <<<<<<<<<<<<<< + * + * if main_debugger.show_return_values: + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1099, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L108_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1087 + * stop = False + * + * if is_call and (frame.f_code.co_name in ('', '') or (line == 1 and frame.f_code.co_name.startswith('pydev_step_cmd) { + case 0x6C: + case 0x9F: + case 0x80: + __pyx_t_9 = 1; + break; + default: + __pyx_t_9 = 0; + break; + } + __pyx_t_11 = (__pyx_t_9 != 0); + if (!__pyx_t_11) { + goto __pyx_L147_next_or; + } else { + } + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1103, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1103, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1103, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (!__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L145_bool_binop_done; + } + __pyx_L147_next_or:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1104 + * if is_return and ( + * (info.pydev_step_cmd in (108, 159, 128) and (self._is_same_frame(stop_frame, frame.f_back))) or + * (info.pydev_step_cmd in (109, 160) and (self._is_same_frame(stop_frame, frame))) or # <<<<<<<<<<<<<< + * (info.pydev_step_cmd in (107, 206)) or + * ( + */ + switch (__pyx_v_info->pydev_step_cmd) { + case 0x6D: + case 0xA0: + __pyx_t_11 = 1; + break; + default: + __pyx_t_11 = 0; + break; + } + __pyx_t_9 = (__pyx_t_11 != 0); + if (!__pyx_t_9) { + goto __pyx_L149_next_or; + } else { + } + __pyx_t_7 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_frame); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1104, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1104, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (!__pyx_t_9) { + } else { + __pyx_t_14 = __pyx_t_9; + goto __pyx_L145_bool_binop_done; + } + __pyx_L149_next_or:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1105 + * (info.pydev_step_cmd in (108, 159, 128) and (self._is_same_frame(stop_frame, frame.f_back))) or + * (info.pydev_step_cmd in (109, 160) and (self._is_same_frame(stop_frame, frame))) or + * (info.pydev_step_cmd in (107, 206)) or # <<<<<<<<<<<<<< + * ( + * info.pydev_step_cmd == 144 + */ + switch (__pyx_v_info->pydev_step_cmd) { + case 0x6B: + case 0xCE: + __pyx_t_9 = 1; + break; + default: + __pyx_t_9 = 0; + break; + } + __pyx_t_11 = (__pyx_t_9 != 0); + if (!__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L145_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1107 + * (info.pydev_step_cmd in (107, 206)) or + * ( + * info.pydev_step_cmd == 144 # <<<<<<<<<<<<<< + * and frame.f_back is not None + * and not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True) + */ + __pyx_t_11 = ((__pyx_v_info->pydev_step_cmd == 0x90) != 0); + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L145_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1108 + * ( + * info.pydev_step_cmd == 144 + * and frame.f_back is not None # <<<<<<<<<<<<<< + * and not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True) + * ) + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1108, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_11 = (__pyx_t_7 != Py_None); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_9 = (__pyx_t_11 != 0); + if (__pyx_t_9) { + } else { + __pyx_t_14 = __pyx_t_9; + goto __pyx_L145_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1109 + * info.pydev_step_cmd == 144 + * and frame.f_back is not None + * and not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True) # <<<<<<<<<<<<<< + * ) + * ): + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_f_code); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[4] = {__pyx_t_1, __pyx_t_3, __pyx_t_4, Py_True}; + __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[4] = {__pyx_t_1, __pyx_t_3, __pyx_t_4, Py_True}; + __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else + #endif + { + __pyx_t_8 = PyTuple_New(3+__pyx_t_5); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_1) { + __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_1); __pyx_t_1 = NULL; + } + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_5, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_5, __pyx_t_4); + __Pyx_INCREF(Py_True); + __Pyx_GIVEREF(Py_True); + PyTuple_SET_ITEM(__pyx_t_8, 2+__pyx_t_5, Py_True); + __pyx_t_3 = 0; + __pyx_t_4 = 0; + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1109, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_11 = ((!__pyx_t_9) != 0); + __pyx_t_14 = __pyx_t_11; + __pyx_L145_bool_binop_done:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1102 + * + * if main_debugger.show_return_values: + * if is_return and ( # <<<<<<<<<<<<<< + * (info.pydev_step_cmd in (108, 159, 128) and (self._is_same_frame(stop_frame, frame.f_back))) or + * (info.pydev_step_cmd in (109, 160) and (self._is_same_frame(stop_frame, frame))) or + */ + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1112 + * ) + * ): + * self._show_return_values(frame, arg) # <<<<<<<<<<<<<< + * + * elif main_debugger.remove_return_values_flag: + */ + __pyx_t_7 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_show_return_values(__pyx_v_self, __pyx_v_frame, __pyx_v_arg); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1112, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1102 + * + * if main_debugger.show_return_values: + * if is_return and ( # <<<<<<<<<<<<<< + * (info.pydev_step_cmd in (108, 159, 128) and (self._is_same_frame(stop_frame, frame.f_back))) or + * (info.pydev_step_cmd in (109, 160) and (self._is_same_frame(stop_frame, frame))) or + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1101 + * return self.trace_dispatch + * + * if main_debugger.show_return_values: # <<<<<<<<<<<<<< + * if is_return and ( + * (info.pydev_step_cmd in (108, 159, 128) and (self._is_same_frame(stop_frame, frame.f_back))) or + */ + goto __pyx_L143; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1114 + * self._show_return_values(frame, arg) + * + * elif main_debugger.remove_return_values_flag: # <<<<<<<<<<<<<< + * try: + * self._remove_return_values(main_debugger, frame) + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_remove_return_values_flag); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1114, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1114, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1115 + * + * elif main_debugger.remove_return_values_flag: + * try: # <<<<<<<<<<<<<< + * self._remove_return_values(main_debugger, frame) + * finally: + */ + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1116 + * elif main_debugger.remove_return_values_flag: + * try: + * self._remove_return_values(main_debugger, frame) # <<<<<<<<<<<<<< + * finally: + * main_debugger.remove_return_values_flag = False + */ + __pyx_t_7 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_remove_return_values(__pyx_v_self, __pyx_v_main_debugger, __pyx_v_frame); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1116, __pyx_L155_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1118 + * self._remove_return_values(main_debugger, frame) + * finally: + * main_debugger.remove_return_values_flag = False # <<<<<<<<<<<<<< + * + * if stop: + */ + /*finally:*/ { + /*normal exit:*/{ + if (__Pyx_PyObject_SetAttrStr(__pyx_v_main_debugger, __pyx_n_s_remove_return_values_flag, Py_False) < 0) __PYX_ERR(0, 1118, __pyx_L104_error) + goto __pyx_L156; + } + __pyx_L155_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_23 = 0; __pyx_t_24 = 0; __pyx_t_25 = 0; __pyx_t_26 = 0; __pyx_t_27 = 0; __pyx_t_28 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_26, &__pyx_t_27, &__pyx_t_28); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_23, &__pyx_t_24, &__pyx_t_25) < 0)) __Pyx_ErrFetch(&__pyx_t_23, &__pyx_t_24, &__pyx_t_25); + __Pyx_XGOTREF(__pyx_t_23); + __Pyx_XGOTREF(__pyx_t_24); + __Pyx_XGOTREF(__pyx_t_25); + __Pyx_XGOTREF(__pyx_t_26); + __Pyx_XGOTREF(__pyx_t_27); + __Pyx_XGOTREF(__pyx_t_28); + __pyx_t_5 = __pyx_lineno; __pyx_t_10 = __pyx_clineno; __pyx_t_22 = __pyx_filename; + { + if (__Pyx_PyObject_SetAttrStr(__pyx_v_main_debugger, __pyx_n_s_remove_return_values_flag, Py_False) < 0) __PYX_ERR(0, 1118, __pyx_L158_error) + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_26); + __Pyx_XGIVEREF(__pyx_t_27); + __Pyx_XGIVEREF(__pyx_t_28); + __Pyx_ExceptionReset(__pyx_t_26, __pyx_t_27, __pyx_t_28); + } + __Pyx_XGIVEREF(__pyx_t_23); + __Pyx_XGIVEREF(__pyx_t_24); + __Pyx_XGIVEREF(__pyx_t_25); + __Pyx_ErrRestore(__pyx_t_23, __pyx_t_24, __pyx_t_25); + __pyx_t_23 = 0; __pyx_t_24 = 0; __pyx_t_25 = 0; __pyx_t_26 = 0; __pyx_t_27 = 0; __pyx_t_28 = 0; + __pyx_lineno = __pyx_t_5; __pyx_clineno = __pyx_t_10; __pyx_filename = __pyx_t_22; + goto __pyx_L104_error; + __pyx_L158_error:; + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_26); + __Pyx_XGIVEREF(__pyx_t_27); + __Pyx_XGIVEREF(__pyx_t_28); + __Pyx_ExceptionReset(__pyx_t_26, __pyx_t_27, __pyx_t_28); + } + __Pyx_XDECREF(__pyx_t_23); __pyx_t_23 = 0; + __Pyx_XDECREF(__pyx_t_24); __pyx_t_24 = 0; + __Pyx_XDECREF(__pyx_t_25); __pyx_t_25 = 0; + __pyx_t_26 = 0; __pyx_t_27 = 0; __pyx_t_28 = 0; + goto __pyx_L104_error; + } + __pyx_L156:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1114 + * self._show_return_values(frame, arg) + * + * elif main_debugger.remove_return_values_flag: # <<<<<<<<<<<<<< + * try: + * self._remove_return_values(main_debugger, frame) + */ + } + __pyx_L143:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1120 + * main_debugger.remove_return_values_flag = False + * + * if stop: # <<<<<<<<<<<<<< + * self.set_suspend( + * thread, + */ + __pyx_t_14 = (__pyx_v_stop != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1121 + * + * if stop: + * self.set_suspend( # <<<<<<<<<<<<<< + * thread, + * stop_reason, + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_suspend); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1121, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + + /* "_pydevd_bundle/pydevd_cython.pyx":1123 + * self.set_suspend( + * thread, + * stop_reason, # <<<<<<<<<<<<<< + * suspend_other_threads=breakpoint and breakpoint.suspend_policy == "ALL", + * ) + */ + __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1121, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v_thread); + __Pyx_INCREF(__pyx_v_stop_reason); + __Pyx_GIVEREF(__pyx_v_stop_reason); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_v_stop_reason); + + /* "_pydevd_bundle/pydevd_cython.pyx":1124 + * thread, + * stop_reason, + * suspend_other_threads=breakpoint and breakpoint.suspend_policy == "ALL", # <<<<<<<<<<<<<< + * ) + * + */ + __pyx_t_8 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1124, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_breakpoint); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1124, __pyx_L104_error) + if (__pyx_t_14) { + } else { + __Pyx_INCREF(__pyx_v_breakpoint); + __pyx_t_4 = __pyx_v_breakpoint; + goto __pyx_L160_bool_binop_done; + } + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_breakpoint, __pyx_n_s_suspend_policy); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1124, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_n_s_ALL, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1124, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_INCREF(__pyx_t_1); + __pyx_t_4 = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_L160_bool_binop_done:; + if (PyDict_SetItem(__pyx_t_8, __pyx_n_s_suspend_other_threads, __pyx_t_4) < 0) __PYX_ERR(0, 1124, __pyx_L104_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1121 + * + * if stop: + * self.set_suspend( # <<<<<<<<<<<<<< + * thread, + * stop_reason, + */ + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_6, __pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1121, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1120 + * main_debugger.remove_return_values_flag = False + * + * if stop: # <<<<<<<<<<<<<< + * self.set_suspend( + * thread, + */ + goto __pyx_L159; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1127 + * ) + * + * elif flag and plugin_manager is not None: # <<<<<<<<<<<<<< + * result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) + * if result: + */ + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_v_flag); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1127, __pyx_L104_error) + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L162_bool_binop_done; + } + __pyx_t_11 = (__pyx_v_plugin_manager != Py_None); + __pyx_t_9 = (__pyx_t_11 != 0); + __pyx_t_14 = __pyx_t_9; + __pyx_L162_bool_binop_done:; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1128 + * + * elif flag and plugin_manager is not None: + * result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) # <<<<<<<<<<<<<< + * if result: + * frame = result + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_plugin_manager, __pyx_n_s_suspend); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1128, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_6 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[5] = {__pyx_t_6, __pyx_v_main_debugger, __pyx_v_thread, __pyx_v_frame, __pyx_v_bp_type}; + __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 4+__pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1128, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[5] = {__pyx_t_6, __pyx_v_main_debugger, __pyx_v_thread, __pyx_v_frame, __pyx_v_bp_type}; + __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 4+__pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1128, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + { + __pyx_t_7 = PyTuple_New(4+__pyx_t_10); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1128, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_6) { + __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_6); __pyx_t_6 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_10, __pyx_v_main_debugger); + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_10, __pyx_v_thread); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_7, 2+__pyx_t_10, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_bp_type); + __Pyx_GIVEREF(__pyx_v_bp_type); + PyTuple_SET_ITEM(__pyx_t_7, 3+__pyx_t_10, __pyx_v_bp_type); + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1128, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_result, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1129 + * elif flag and plugin_manager is not None: + * result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) + * if result: # <<<<<<<<<<<<<< + * frame = result + * + */ + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_result); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1129, __pyx_L104_error) + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1130 + * result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) + * if result: + * frame = result # <<<<<<<<<<<<<< + * + * # if thread has a suspend flag, we suspend with a busy wait + */ + __Pyx_INCREF(__pyx_v_result); + __Pyx_DECREF_SET(__pyx_v_frame, __pyx_v_result); + + /* "_pydevd_bundle/pydevd_cython.pyx":1129 + * elif flag and plugin_manager is not None: + * result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) + * if result: # <<<<<<<<<<<<<< + * frame = result + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1127 + * ) + * + * elif flag and plugin_manager is not None: # <<<<<<<<<<<<<< + * result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) + * if result: + */ + } + __pyx_L159:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1133 + * + * # if thread has a suspend flag, we suspend with a busy wait + * if info.pydev_state == 2: # <<<<<<<<<<<<<< + * self.do_wait_suspend(thread, frame, event, arg) + * return self.trace_dispatch + */ + __pyx_t_14 = ((__pyx_v_info->pydev_state == 2) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1134 + * # if thread has a suspend flag, we suspend with a busy wait + * if info.pydev_state == 2: + * self.do_wait_suspend(thread, frame, event, arg) # <<<<<<<<<<<<<< + * return self.trace_dispatch + * else: + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_do_wait_suspend); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1134, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[5] = {__pyx_t_7, __pyx_v_thread, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 4+__pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1134, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[5] = {__pyx_t_7, __pyx_v_thread, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 4+__pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1134, __pyx_L104_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + { + __pyx_t_6 = PyTuple_New(4+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1134, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_6); + if (__pyx_t_7) { + __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_7); __pyx_t_7 = NULL; + } + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_10, __pyx_v_thread); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_10, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_6, 2+__pyx_t_10, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_6, 3+__pyx_t_10, __pyx_v_arg); + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_6, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1134, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1135 + * if info.pydev_state == 2: + * self.do_wait_suspend(thread, frame, event, arg) + * return self.trace_dispatch # <<<<<<<<<<<<<< + * else: + * if not breakpoint and is_line: + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1135, __pyx_L104_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L108_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1133 + * + * # if thread has a suspend flag, we suspend with a busy wait + * if info.pydev_state == 2: # <<<<<<<<<<<<<< + * self.do_wait_suspend(thread, frame, event, arg) + * return self.trace_dispatch + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1137 + * return self.trace_dispatch + * else: + * if not breakpoint and is_line: # <<<<<<<<<<<<<< + * # No stop from anyone and no breakpoint found in line (cache that). + * frame_skips_cache[line_cache_key] = 0 + */ + /*else*/ { + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_v_breakpoint); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1137, __pyx_L104_error) + __pyx_t_11 = ((!__pyx_t_9) != 0); + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L167_bool_binop_done; + } + __pyx_t_11 = (__pyx_v_is_line != 0); + __pyx_t_14 = __pyx_t_11; + __pyx_L167_bool_binop_done:; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1139 + * if not breakpoint and is_line: + * # No stop from anyone and no breakpoint found in line (cache that). + * frame_skips_cache[line_cache_key] = 0 # <<<<<<<<<<<<<< + * + * except: + */ + if (unlikely(__pyx_v_frame_skips_cache == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1139, __pyx_L104_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_frame_skips_cache, __pyx_v_line_cache_key, __pyx_int_0) < 0)) __PYX_ERR(0, 1139, __pyx_L104_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1137 + * return self.trace_dispatch + * else: + * if not breakpoint and is_line: # <<<<<<<<<<<<<< + * # No stop from anyone and no breakpoint found in line (cache that). + * frame_skips_cache[line_cache_key] = 0 + */ + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1037 + * # if DEBUG: print('NOT skipped: %s %s %s %s' % (frame.f_lineno, frame.f_code.co_name, event, frame.__class__.__name__)) + * + * try: # <<<<<<<<<<<<<< + * flag = False + * # return is not taken into account for breakpoint hit because we'd have a double-hit in this case + */ + } + __Pyx_XDECREF(__pyx_t_18); __pyx_t_18 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; + goto __pyx_L109_try_end; + __pyx_L104_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1141 + * frame_skips_cache[line_cache_key] = 0 + * + * except: # <<<<<<<<<<<<<< + * pydev_log.exception() + * raise + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_4, &__pyx_t_8, &__pyx_t_6) < 0) __PYX_ERR(0, 1141, __pyx_L106_except_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GOTREF(__pyx_t_6); + + /* "_pydevd_bundle/pydevd_cython.pyx":1142 + * + * except: + * pydev_log.exception() # <<<<<<<<<<<<<< + * raise + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1142, __pyx_L106_except_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_exception); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1142, __pyx_L106_except_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_7 = (__pyx_t_1) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_1) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1142, __pyx_L106_except_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1143 + * except: + * pydev_log.exception() + * raise # <<<<<<<<<<<<<< + * + * # step handling. We stop when we hit the right frame + */ + __Pyx_GIVEREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_ErrRestoreWithState(__pyx_t_4, __pyx_t_8, __pyx_t_6); + __pyx_t_4 = 0; __pyx_t_8 = 0; __pyx_t_6 = 0; + __PYX_ERR(0, 1143, __pyx_L106_except_error) + } + __pyx_L106_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1037 + * # if DEBUG: print('NOT skipped: %s %s %s %s' % (frame.f_lineno, frame.f_code.co_name, event, frame.__class__.__name__)) + * + * try: # <<<<<<<<<<<<<< + * flag = False + * # return is not taken into account for breakpoint hit because we'd have a double-hit in this case + */ + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_18, __pyx_t_17, __pyx_t_16); + goto __pyx_L4_error; + __pyx_L108_try_return:; + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_18, __pyx_t_17, __pyx_t_16); + goto __pyx_L3_return; + __pyx_L109_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1146 + * + * # step handling. We stop when we hit the right frame + * try: # <<<<<<<<<<<<<< + * should_skip = 0 + * if pydevd_dont_trace.should_trace_hook is not None: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_16, &__pyx_t_17, &__pyx_t_18); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __Pyx_XGOTREF(__pyx_t_18); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1147 + * # step handling. We stop when we hit the right frame + * try: + * should_skip = 0 # <<<<<<<<<<<<<< + * if pydevd_dont_trace.should_trace_hook is not None: + * if self.should_skip == -1: + */ + __pyx_v_should_skip = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1148 + * try: + * should_skip = 0 + * if pydevd_dont_trace.should_trace_hook is not None: # <<<<<<<<<<<<<< + * if self.should_skip == -1: + * # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). + */ + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pydevd_dont_trace); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1148, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_should_trace_hook); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1148, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_14 = (__pyx_t_8 != Py_None); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_11 = (__pyx_t_14 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1149 + * should_skip = 0 + * if pydevd_dont_trace.should_trace_hook is not None: + * if self.should_skip == -1: # <<<<<<<<<<<<<< + * # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). + * # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code + */ + __pyx_t_11 = ((__pyx_v_self->should_skip == -1L) != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1153 + * # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code + * # Which will be handled by this frame is read-only, so, we can cache it safely. + * if not pydevd_dont_trace.should_trace_hook(frame, abs_path_canonical_path_and_base[0]): # <<<<<<<<<<<<<< + * # -1, 0, 1 to be Cython-friendly + * should_skip = self.should_skip = 1 + */ + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pydevd_dont_trace); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1153, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_should_trace_hook); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1153, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(__pyx_v_abs_path_canonical_path_and_base == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1153, __pyx_L171_error) + } + __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v_abs_path_canonical_path_and_base, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1153, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_v_frame, __pyx_t_6}; + __pyx_t_8 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1153, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_v_frame, __pyx_t_6}; + __pyx_t_8 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1153, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + { + __pyx_t_3 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1153, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_7) { + __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7); __pyx_t_7 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_10, __pyx_v_frame); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_10, __pyx_t_6); + __pyx_t_6 = 0; + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1153, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1153, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_14 = ((!__pyx_t_11) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1155 + * if not pydevd_dont_trace.should_trace_hook(frame, abs_path_canonical_path_and_base[0]): + * # -1, 0, 1 to be Cython-friendly + * should_skip = self.should_skip = 1 # <<<<<<<<<<<<<< + * else: + * should_skip = self.should_skip = 0 + */ + __pyx_v_should_skip = 1; + __pyx_v_self->should_skip = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1153 + * # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code + * # Which will be handled by this frame is read-only, so, we can cache it safely. + * if not pydevd_dont_trace.should_trace_hook(frame, abs_path_canonical_path_and_base[0]): # <<<<<<<<<<<<<< + * # -1, 0, 1 to be Cython-friendly + * should_skip = self.should_skip = 1 + */ + goto __pyx_L179; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1157 + * should_skip = self.should_skip = 1 + * else: + * should_skip = self.should_skip = 0 # <<<<<<<<<<<<<< + * else: + * should_skip = self.should_skip + */ + /*else*/ { + __pyx_v_should_skip = 0; + __pyx_v_self->should_skip = 0; + } + __pyx_L179:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1149 + * should_skip = 0 + * if pydevd_dont_trace.should_trace_hook is not None: + * if self.should_skip == -1: # <<<<<<<<<<<<<< + * # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). + * # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code + */ + goto __pyx_L178; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1159 + * should_skip = self.should_skip = 0 + * else: + * should_skip = self.should_skip # <<<<<<<<<<<<<< + * + * plugin_stop = False + */ + /*else*/ { + __pyx_t_10 = __pyx_v_self->should_skip; + __pyx_v_should_skip = __pyx_t_10; + } + __pyx_L178:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1148 + * try: + * should_skip = 0 + * if pydevd_dont_trace.should_trace_hook is not None: # <<<<<<<<<<<<<< + * if self.should_skip == -1: + * # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1161 + * should_skip = self.should_skip + * + * plugin_stop = False # <<<<<<<<<<<<<< + * if should_skip: + * stop = False + */ + __Pyx_INCREF(Py_False); + __pyx_v_plugin_stop = Py_False; + + /* "_pydevd_bundle/pydevd_cython.pyx":1162 + * + * plugin_stop = False + * if should_skip: # <<<<<<<<<<<<<< + * stop = False + * + */ + __pyx_t_14 = (__pyx_v_should_skip != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1163 + * plugin_stop = False + * if should_skip: + * stop = False # <<<<<<<<<<<<<< + * + * elif step_cmd in (107, 144, 206): + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1162 + * + * plugin_stop = False + * if should_skip: # <<<<<<<<<<<<<< + * stop = False + * + */ + goto __pyx_L180; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1165 + * stop = False + * + * elif step_cmd in (107, 144, 206): # <<<<<<<<<<<<<< + * force_check_project_scope = step_cmd == 144 + * if is_line: + */ + switch (__pyx_v_step_cmd) { + case 0x6B: + case 0x90: + case 0xCE: + __pyx_t_14 = 1; + break; + default: + __pyx_t_14 = 0; + break; + } + __pyx_t_11 = (__pyx_t_14 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1166 + * + * elif step_cmd in (107, 144, 206): + * force_check_project_scope = step_cmd == 144 # <<<<<<<<<<<<<< + * if is_line: + * if not info.pydev_use_scoped_step_frame: + */ + __pyx_t_8 = __Pyx_PyBool_FromLong((__pyx_v_step_cmd == 0x90)); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1166, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_v_force_check_project_scope = __pyx_t_8; + __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1167 + * elif step_cmd in (107, 144, 206): + * force_check_project_scope = step_cmd == 144 + * if is_line: # <<<<<<<<<<<<<< + * if not info.pydev_use_scoped_step_frame: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + */ + __pyx_t_11 = (__pyx_v_is_line != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1168 + * force_check_project_scope = step_cmd == 144 + * if is_line: + * if not info.pydev_use_scoped_step_frame: # <<<<<<<<<<<<<< + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + * stop = not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, force_check_project_scope) + */ + __pyx_t_11 = ((!(__pyx_v_info->pydev_use_scoped_step_frame != 0)) != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1169 + * if is_line: + * if not info.pydev_use_scoped_step_frame: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: # <<<<<<<<<<<<<< + * stop = not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, force_check_project_scope) + * else: + */ + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_force_check_project_scope); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1169, __pyx_L171_error) + if (!__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L184_bool_binop_done; + } + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_is_files_filter_enabled); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1169, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1169, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_11 = __pyx_t_14; + __pyx_L184_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1170 + * if not info.pydev_use_scoped_step_frame: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + * stop = not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, force_check_project_scope) # <<<<<<<<<<<<<< + * else: + * stop = True + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1170, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1170, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1170, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_3, __pyx_v_frame, __pyx_t_6, __pyx_v_force_check_project_scope}; + __pyx_t_8 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1170, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_3, __pyx_v_frame, __pyx_t_6, __pyx_v_force_check_project_scope}; + __pyx_t_8 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1170, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + { + __pyx_t_7 = PyTuple_New(3+__pyx_t_10); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1170, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_10, __pyx_v_frame); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_10, __pyx_t_6); + __Pyx_INCREF(__pyx_v_force_check_project_scope); + __Pyx_GIVEREF(__pyx_v_force_check_project_scope); + PyTuple_SET_ITEM(__pyx_t_7, 2+__pyx_t_10, __pyx_v_force_check_project_scope); + __pyx_t_6 = 0; + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1170, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1170, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_stop = (!__pyx_t_11); + + /* "_pydevd_bundle/pydevd_cython.pyx":1169 + * if is_line: + * if not info.pydev_use_scoped_step_frame: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: # <<<<<<<<<<<<<< + * stop = not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, force_check_project_scope) + * else: + */ + goto __pyx_L183; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1172 + * stop = not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, force_check_project_scope) + * else: + * stop = True # <<<<<<<<<<<<<< + * else: + * # We can only stop inside the ipython call. + */ + /*else*/ { + __pyx_v_stop = 1; + } + __pyx_L183:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1168 + * force_check_project_scope = step_cmd == 144 + * if is_line: + * if not info.pydev_use_scoped_step_frame: # <<<<<<<<<<<<<< + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + * stop = not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, force_check_project_scope) + */ + goto __pyx_L182; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1175 + * else: + * # We can only stop inside the ipython call. + * filename = frame.f_code.co_filename # <<<<<<<<<<<<<< + * if filename.endswith('.pyc'): + * filename = filename[:-1] + */ + /*else*/ { + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1175, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1175, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_filename = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1176 + * # We can only stop inside the ipython call. + * filename = frame.f_code.co_filename + * if filename.endswith('.pyc'): # <<<<<<<<<<<<<< + * filename = filename[:-1] + * + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_filename, __pyx_n_s_endswith); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1176, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_7, __pyx_kp_s_pyc) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_kp_s_pyc); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1176, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1176, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1177 + * filename = frame.f_code.co_filename + * if filename.endswith('.pyc'): + * filename = filename[:-1] # <<<<<<<<<<<<<< + * + * if not filename.endswith(PYDEVD_IPYTHON_CONTEXT[0]): + */ + __pyx_t_4 = __Pyx_PyObject_GetSlice(__pyx_v_filename, 0, -1L, NULL, NULL, &__pyx_slice__4, 0, 1, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1177, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_filename, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1176 + * # We can only stop inside the ipython call. + * filename = frame.f_code.co_filename + * if filename.endswith('.pyc'): # <<<<<<<<<<<<<< + * filename = filename[:-1] + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1179 + * filename = filename[:-1] + * + * if not filename.endswith(PYDEVD_IPYTHON_CONTEXT[0]): # <<<<<<<<<<<<<< + * f = frame.f_back + * while f is not None: + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_filename, __pyx_n_s_endswith); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1179, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_PYDEVD_IPYTHON_CONTEXT); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1179, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_7, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1179, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1179, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1179, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_14 = ((!__pyx_t_11) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1180 + * + * if not filename.endswith(PYDEVD_IPYTHON_CONTEXT[0]): + * f = frame.f_back # <<<<<<<<<<<<<< + * while f is not None: + * if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1180, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF_SET(__pyx_v_f, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1181 + * if not filename.endswith(PYDEVD_IPYTHON_CONTEXT[0]): + * f = frame.f_back + * while f is not None: # <<<<<<<<<<<<<< + * if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + * f2 = f.f_back + */ + while (1) { + __pyx_t_14 = (__pyx_v_f != Py_None); + __pyx_t_11 = (__pyx_t_14 != 0); + if (!__pyx_t_11) break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1182 + * f = frame.f_back + * while f is not None: + * if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: # <<<<<<<<<<<<<< + * f2 = f.f_back + * if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_code); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1182, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_co_name); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1182, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_PYDEVD_IPYTHON_CONTEXT); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1182, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_4, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1182, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyObject_RichCompare(__pyx_t_8, __pyx_t_6, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1182, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1182, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1183 + * while f is not None: + * if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + * f2 = f.f_back # <<<<<<<<<<<<<< + * if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + * pydev_log.debug('Stop inside ipython call') + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1183, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF_SET(__pyx_v_f2, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1184 + * if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + * f2 = f.f_back + * if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: # <<<<<<<<<<<<<< + * pydev_log.debug('Stop inside ipython call') + * stop = True + */ + __pyx_t_14 = (__pyx_v_f2 != Py_None); + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + } else { + __pyx_t_11 = __pyx_t_9; + goto __pyx_L192_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f2, __pyx_n_s_f_code); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1184, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_co_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1184, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_PYDEVD_IPYTHON_CONTEXT); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1184, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_8 = __Pyx_GetItemInt(__pyx_t_4, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1184, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyObject_RichCompare(__pyx_t_6, __pyx_t_8, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1184, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1184, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_11 = __pyx_t_9; + __pyx_L192_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1185 + * f2 = f.f_back + * if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + * pydev_log.debug('Stop inside ipython call') # <<<<<<<<<<<<<< + * stop = True + * break + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1185, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_debug); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1185, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + } + } + __pyx_t_4 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_8, __pyx_kp_s_Stop_inside_ipython_call) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_kp_s_Stop_inside_ipython_call); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1185, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1186 + * if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + * pydev_log.debug('Stop inside ipython call') + * stop = True # <<<<<<<<<<<<<< + * break + * f = f.f_back + */ + __pyx_v_stop = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1187 + * pydev_log.debug('Stop inside ipython call') + * stop = True + * break # <<<<<<<<<<<<<< + * f = f.f_back + * + */ + goto __pyx_L189_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1184 + * if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + * f2 = f.f_back + * if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: # <<<<<<<<<<<<<< + * pydev_log.debug('Stop inside ipython call') + * stop = True + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1182 + * f = frame.f_back + * while f is not None: + * if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: # <<<<<<<<<<<<<< + * f2 = f.f_back + * if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1188 + * stop = True + * break + * f = f.f_back # <<<<<<<<<<<<<< + * + * del f + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1188, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_f, __pyx_t_4); + __pyx_t_4 = 0; + } + __pyx_L189_break:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1190 + * f = f.f_back + * + * del f # <<<<<<<<<<<<<< + * + * if not stop: + */ + __Pyx_DECREF(__pyx_v_f); + __pyx_v_f = NULL; + + /* "_pydevd_bundle/pydevd_cython.pyx":1179 + * filename = filename[:-1] + * + * if not filename.endswith(PYDEVD_IPYTHON_CONTEXT[0]): # <<<<<<<<<<<<<< + * f = frame.f_back + * while f is not None: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1192 + * del f + * + * if not stop: # <<<<<<<<<<<<<< + * # In scoped mode if step in didn't work in this context it won't work + * # afterwards anyways. + */ + __pyx_t_11 = ((!(__pyx_v_stop != 0)) != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1195 + * # In scoped mode if step in didn't work in this context it won't work + * # afterwards anyways. + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * elif is_return and frame.f_back is not None and not info.pydev_use_scoped_step_frame: + */ + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_4 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1195, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L175_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1192 + * del f + * + * if not stop: # <<<<<<<<<<<<<< + * # In scoped mode if step in didn't work in this context it won't work + * # afterwards anyways. + */ + } + } + __pyx_L182:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1167 + * elif step_cmd in (107, 144, 206): + * force_check_project_scope = step_cmd == 144 + * if is_line: # <<<<<<<<<<<<<< + * if not info.pydev_use_scoped_step_frame: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + */ + goto __pyx_L181; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1197 + * return None if is_call else NO_FTRACE + * + * elif is_return and frame.f_back is not None and not info.pydev_use_scoped_step_frame: # <<<<<<<<<<<<<< + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + * stop = False + */ + __pyx_t_9 = (__pyx_v_is_return != 0); + if (__pyx_t_9) { + } else { + __pyx_t_11 = __pyx_t_9; + goto __pyx_L195_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1197, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_9 = (__pyx_t_4 != Py_None); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L195_bool_binop_done; + } + __pyx_t_14 = ((!(__pyx_v_info->pydev_use_scoped_step_frame != 0)) != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L195_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1198 + * + * elif is_return and frame.f_back is not None and not info.pydev_use_scoped_step_frame: + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: # <<<<<<<<<<<<<< + * stop = False + * else: + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_get_file_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1198, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1198, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_t_8) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_8); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1198, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_PYDEV_FILE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1198, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = PyObject_RichCompare(__pyx_t_4, __pyx_t_6, Py_EQ); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1198, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1198, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1199 + * elif is_return and frame.f_back is not None and not info.pydev_use_scoped_step_frame: + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + * stop = False # <<<<<<<<<<<<<< + * else: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1198 + * + * elif is_return and frame.f_back is not None and not info.pydev_use_scoped_step_frame: + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: # <<<<<<<<<<<<<< + * stop = False + * else: + */ + goto __pyx_L198; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1201 + * stop = False + * else: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: # <<<<<<<<<<<<<< + * stop = not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, force_check_project_scope) + * if stop: + */ + /*else*/ { + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_force_check_project_scope); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1201, __pyx_L171_error) + if (!__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L200_bool_binop_done; + } + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_is_files_filter_enabled); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1201, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1201, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_11 = __pyx_t_14; + __pyx_L200_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1202 + * else: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + * stop = not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, force_check_project_scope) # <<<<<<<<<<<<<< + * if stop: + * # Prevent stopping in a return to the same location we were initially + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[4] = {__pyx_t_3, __pyx_t_4, __pyx_t_7, __pyx_v_force_check_project_scope}; + __pyx_t_8 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[4] = {__pyx_t_3, __pyx_t_4, __pyx_t_7, __pyx_v_force_check_project_scope}; + __pyx_t_8 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_1 = PyTuple_New(3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_1, 0+__pyx_t_10, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_1, 1+__pyx_t_10, __pyx_t_7); + __Pyx_INCREF(__pyx_v_force_check_project_scope); + __Pyx_GIVEREF(__pyx_v_force_check_project_scope); + PyTuple_SET_ITEM(__pyx_t_1, 2+__pyx_t_10, __pyx_v_force_check_project_scope); + __pyx_t_4 = 0; + __pyx_t_7 = 0; + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_1, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1202, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_stop = (!__pyx_t_11); + + /* "_pydevd_bundle/pydevd_cython.pyx":1203 + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + * stop = not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, force_check_project_scope) + * if stop: # <<<<<<<<<<<<<< + * # Prevent stopping in a return to the same location we were initially + * # (i.e.: double-stop at the same place due to some filtering). + */ + __pyx_t_11 = (__pyx_v_stop != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1206 + * # Prevent stopping in a return to the same location we were initially + * # (i.e.: double-stop at the same place due to some filtering). + * if info.step_in_initial_location == (frame.f_back, frame.f_back.f_lineno): # <<<<<<<<<<<<<< + * stop = False + * else: + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1206, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1206, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1206, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1206, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_1); + __pyx_t_8 = 0; + __pyx_t_1 = 0; + __pyx_t_1 = PyObject_RichCompare(__pyx_v_info->step_in_initial_location, __pyx_t_6, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1206, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1206, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1207 + * # (i.e.: double-stop at the same place due to some filtering). + * if info.step_in_initial_location == (frame.f_back, frame.f_back.f_lineno): + * stop = False # <<<<<<<<<<<<<< + * else: + * stop = True + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1206 + * # Prevent stopping in a return to the same location we were initially + * # (i.e.: double-stop at the same place due to some filtering). + * if info.step_in_initial_location == (frame.f_back, frame.f_back.f_lineno): # <<<<<<<<<<<<<< + * stop = False + * else: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1203 + * if force_check_project_scope or main_debugger.is_files_filter_enabled: + * stop = not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, force_check_project_scope) + * if stop: # <<<<<<<<<<<<<< + * # Prevent stopping in a return to the same location we were initially + * # (i.e.: double-stop at the same place due to some filtering). + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1201 + * stop = False + * else: + * if force_check_project_scope or main_debugger.is_files_filter_enabled: # <<<<<<<<<<<<<< + * stop = not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, force_check_project_scope) + * if stop: + */ + goto __pyx_L199; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1209 + * stop = False + * else: + * stop = True # <<<<<<<<<<<<<< + * else: + * stop = False + */ + /*else*/ { + __pyx_v_stop = 1; + } + __pyx_L199:; + } + __pyx_L198:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1197 + * return None if is_call else NO_FTRACE + * + * elif is_return and frame.f_back is not None and not info.pydev_use_scoped_step_frame: # <<<<<<<<<<<<<< + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + * stop = False + */ + goto __pyx_L181; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1211 + * stop = True + * else: + * stop = False # <<<<<<<<<<<<<< + * + * if stop: + */ + /*else*/ { + __pyx_v_stop = 0; + } + __pyx_L181:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1213 + * stop = False + * + * if stop: # <<<<<<<<<<<<<< + * if step_cmd == 206: + * # i.e.: Check if we're stepping into the proper context. + */ + __pyx_t_11 = (__pyx_v_stop != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1214 + * + * if stop: + * if step_cmd == 206: # <<<<<<<<<<<<<< + * # i.e.: Check if we're stepping into the proper context. + * f = frame + */ + __pyx_t_11 = ((__pyx_v_step_cmd == 0xCE) != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1216 + * if step_cmd == 206: + * # i.e.: Check if we're stepping into the proper context. + * f = frame # <<<<<<<<<<<<<< + * while f is not None: + * if self._is_same_frame(stop_frame, f): + */ + __Pyx_INCREF(__pyx_v_frame); + __Pyx_XDECREF_SET(__pyx_v_f, __pyx_v_frame); + + /* "_pydevd_bundle/pydevd_cython.pyx":1217 + * # i.e.: Check if we're stepping into the proper context. + * f = frame + * while f is not None: # <<<<<<<<<<<<<< + * if self._is_same_frame(stop_frame, f): + * break + */ + while (1) { + __pyx_t_11 = (__pyx_v_f != Py_None); + __pyx_t_14 = (__pyx_t_11 != 0); + if (!__pyx_t_14) break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1218 + * f = frame + * while f is not None: + * if self._is_same_frame(stop_frame, f): # <<<<<<<<<<<<<< + * break + * f = f.f_back + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_f); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1218, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1218, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1219 + * while f is not None: + * if self._is_same_frame(stop_frame, f): + * break # <<<<<<<<<<<<<< + * f = f.f_back + * else: + */ + goto __pyx_L207_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1218 + * f = frame + * while f is not None: + * if self._is_same_frame(stop_frame, f): # <<<<<<<<<<<<<< + * break + * f = f.f_back + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1220 + * if self._is_same_frame(stop_frame, f): + * break + * f = f.f_back # <<<<<<<<<<<<<< + * else: + * stop = False + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_f, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1220, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_f, __pyx_t_1); + __pyx_t_1 = 0; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1222 + * f = f.f_back + * else: + * stop = False # <<<<<<<<<<<<<< + * + * if plugin_manager is not None: + */ + /*else*/ { + __pyx_v_stop = 0; + } + __pyx_L207_break:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1214 + * + * if stop: + * if step_cmd == 206: # <<<<<<<<<<<<<< + * # i.e.: Check if we're stepping into the proper context. + * f = frame + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1213 + * stop = False + * + * if stop: # <<<<<<<<<<<<<< + * if step_cmd == 206: + * # i.e.: Check if we're stepping into the proper context. + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1224 + * stop = False + * + * if plugin_manager is not None: # <<<<<<<<<<<<<< + * result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) + * if result: + */ + __pyx_t_14 = (__pyx_v_plugin_manager != Py_None); + __pyx_t_11 = (__pyx_t_14 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1225 + * + * if plugin_manager is not None: + * result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) # <<<<<<<<<<<<<< + * if result: + * stop, plugin_stop = result + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_plugin_manager, __pyx_n_s_cmd_step_into); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1225, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = __Pyx_PyBool_FromLong(__pyx_v_stop); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1225, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[7] = {__pyx_t_7, __pyx_v_main_debugger, __pyx_v_frame, __pyx_v_event, __pyx_v_self->_args, __pyx_v_stop_info, __pyx_t_8}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 6+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1225, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[7] = {__pyx_t_7, __pyx_v_main_debugger, __pyx_v_frame, __pyx_v_event, __pyx_v_self->_args, __pyx_v_stop_info, __pyx_t_8}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 6+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1225, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else + #endif + { + __pyx_t_4 = PyTuple_New(6+__pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1225, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + if (__pyx_t_7) { + __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_7); __pyx_t_7 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_10, __pyx_v_main_debugger); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_10, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_4, 2+__pyx_t_10, __pyx_v_event); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_4, 3+__pyx_t_10, __pyx_v_self->_args); + __Pyx_INCREF(__pyx_v_stop_info); + __Pyx_GIVEREF(__pyx_v_stop_info); + PyTuple_SET_ITEM(__pyx_t_4, 4+__pyx_t_10, __pyx_v_stop_info); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_4, 5+__pyx_t_10, __pyx_t_8); + __pyx_t_8 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1225, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF_SET(__pyx_v_result, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1226 + * if plugin_manager is not None: + * result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) + * if result: # <<<<<<<<<<<<<< + * stop, plugin_stop = result + * + */ + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_v_result); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1226, __pyx_L171_error) + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1227 + * result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) + * if result: + * stop, plugin_stop = result # <<<<<<<<<<<<<< + * + * elif step_cmd in (108, 159): + */ + if ((likely(PyTuple_CheckExact(__pyx_v_result))) || (PyList_CheckExact(__pyx_v_result))) { + PyObject* sequence = __pyx_v_result; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 1227, __pyx_L171_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_1 = PyList_GET_ITEM(sequence, 0); + __pyx_t_6 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + #else + __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1227, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1227, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_4 = PyObject_GetIter(__pyx_v_result); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1227, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_15 = Py_TYPE(__pyx_t_4)->tp_iternext; + index = 0; __pyx_t_1 = __pyx_t_15(__pyx_t_4); if (unlikely(!__pyx_t_1)) goto __pyx_L211_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + index = 1; __pyx_t_6 = __pyx_t_15(__pyx_t_4); if (unlikely(!__pyx_t_6)) goto __pyx_L211_unpacking_failed; + __Pyx_GOTREF(__pyx_t_6); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_4), 2) < 0) __PYX_ERR(0, 1227, __pyx_L171_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + goto __pyx_L212_unpacking_done; + __pyx_L211_unpacking_failed:; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 1227, __pyx_L171_error) + __pyx_L212_unpacking_done:; + } + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1227, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_stop = __pyx_t_11; + __Pyx_DECREF_SET(__pyx_v_plugin_stop, __pyx_t_6); + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1226 + * if plugin_manager is not None: + * result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) + * if result: # <<<<<<<<<<<<<< + * stop, plugin_stop = result + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1224 + * stop = False + * + * if plugin_manager is not None: # <<<<<<<<<<<<<< + * result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) + * if result: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1165 + * stop = False + * + * elif step_cmd in (107, 144, 206): # <<<<<<<<<<<<<< + * force_check_project_scope = step_cmd == 144 + * if is_line: + */ + goto __pyx_L180; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1229 + * stop, plugin_stop = result + * + * elif step_cmd in (108, 159): # <<<<<<<<<<<<<< + * # Note: when dealing with a step over my code it's the same as a step over (the + * # difference is that when we return from a frame in one we go to regular step + */ + switch (__pyx_v_step_cmd) { + case 0x6C: + case 0x9F: + __pyx_t_11 = 1; + break; + default: + __pyx_t_11 = 0; + break; + } + __pyx_t_14 = (__pyx_t_11 != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1233 + * # difference is that when we return from a frame in one we go to regular step + * # into and in the other we go to a step into my code). + * stop = self._is_same_frame(stop_frame, frame) and is_line # <<<<<<<<<<<<<< + * # Note: don't stop on a return for step over, only for line events + * # i.e.: don't stop in: (stop_frame is frame.f_back and is_return) as we'd stop twice in that line. + */ + __pyx_t_6 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_frame); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1233, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1233, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (__pyx_t_11) { + } else { + __pyx_t_14 = __pyx_t_11; + goto __pyx_L213_bool_binop_done; + } + __pyx_t_11 = (__pyx_v_is_line != 0); + __pyx_t_14 = __pyx_t_11; + __pyx_L213_bool_binop_done:; + __pyx_v_stop = __pyx_t_14; + + /* "_pydevd_bundle/pydevd_cython.pyx":1237 + * # i.e.: don't stop in: (stop_frame is frame.f_back and is_return) as we'd stop twice in that line. + * + * if plugin_manager is not None: # <<<<<<<<<<<<<< + * result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) + * if result: + */ + __pyx_t_14 = (__pyx_v_plugin_manager != Py_None); + __pyx_t_11 = (__pyx_t_14 != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1238 + * + * if plugin_manager is not None: + * result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) # <<<<<<<<<<<<<< + * if result: + * stop, plugin_stop = result + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_plugin_manager, __pyx_n_s_cmd_step_over); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1238, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_stop); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1238, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_8 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[7] = {__pyx_t_8, __pyx_v_main_debugger, __pyx_v_frame, __pyx_v_event, __pyx_v_self->_args, __pyx_v_stop_info, __pyx_t_4}; + __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_10, 6+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1238, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[7] = {__pyx_t_8, __pyx_v_main_debugger, __pyx_v_frame, __pyx_v_event, __pyx_v_self->_args, __pyx_v_stop_info, __pyx_t_4}; + __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_10, 6+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1238, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else + #endif + { + __pyx_t_7 = PyTuple_New(6+__pyx_t_10); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1238, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_8) { + __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_8); __pyx_t_8 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_10, __pyx_v_main_debugger); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_10, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_7, 2+__pyx_t_10, __pyx_v_event); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_7, 3+__pyx_t_10, __pyx_v_self->_args); + __Pyx_INCREF(__pyx_v_stop_info); + __Pyx_GIVEREF(__pyx_v_stop_info); + PyTuple_SET_ITEM(__pyx_t_7, 4+__pyx_t_10, __pyx_v_stop_info); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_7, 5+__pyx_t_10, __pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_7, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1238, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF_SET(__pyx_v_result, __pyx_t_6); + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1239 + * if plugin_manager is not None: + * result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) + * if result: # <<<<<<<<<<<<<< + * stop, plugin_stop = result + * + */ + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_v_result); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1239, __pyx_L171_error) + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1240 + * result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) + * if result: + * stop, plugin_stop = result # <<<<<<<<<<<<<< + * + * elif step_cmd == 128: + */ + if ((likely(PyTuple_CheckExact(__pyx_v_result))) || (PyList_CheckExact(__pyx_v_result))) { + PyObject* sequence = __pyx_v_result; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 1240, __pyx_L171_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_6 = PyList_GET_ITEM(sequence, 0); + __pyx_t_1 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(__pyx_t_1); + #else + __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1240, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1240, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_7 = PyObject_GetIter(__pyx_v_result); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1240, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext; + index = 0; __pyx_t_6 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_6)) goto __pyx_L217_unpacking_failed; + __Pyx_GOTREF(__pyx_t_6); + index = 1; __pyx_t_1 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_1)) goto __pyx_L217_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 1240, __pyx_L171_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L218_unpacking_done; + __pyx_L217_unpacking_failed:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 1240, __pyx_L171_error) + __pyx_L218_unpacking_done:; + } + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1240, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_v_stop = __pyx_t_11; + __Pyx_DECREF_SET(__pyx_v_plugin_stop, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1239 + * if plugin_manager is not None: + * result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) + * if result: # <<<<<<<<<<<<<< + * stop, plugin_stop = result + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1237 + * # i.e.: don't stop in: (stop_frame is frame.f_back and is_return) as we'd stop twice in that line. + * + * if plugin_manager is not None: # <<<<<<<<<<<<<< + * result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) + * if result: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1229 + * stop, plugin_stop = result + * + * elif step_cmd in (108, 159): # <<<<<<<<<<<<<< + * # Note: when dealing with a step over my code it's the same as a step over (the + * # difference is that when we return from a frame in one we go to regular step + */ + goto __pyx_L180; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1242 + * stop, plugin_stop = result + * + * elif step_cmd == 128: # <<<<<<<<<<<<<< + * stop = False + * back = frame.f_back + */ + __pyx_t_11 = ((__pyx_v_step_cmd == 0x80) != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1243 + * + * elif step_cmd == 128: + * stop = False # <<<<<<<<<<<<<< + * back = frame.f_back + * if self._is_same_frame(stop_frame, frame) and is_return: + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1244 + * elif step_cmd == 128: + * stop = False + * back = frame.f_back # <<<<<<<<<<<<<< + * if self._is_same_frame(stop_frame, frame) and is_return: + * # We're exiting the smart step into initial frame (so, we probably didn't find our target). + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1244, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_back = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1245 + * stop = False + * back = frame.f_back + * if self._is_same_frame(stop_frame, frame) and is_return: # <<<<<<<<<<<<<< + * # We're exiting the smart step into initial frame (so, we probably didn't find our target). + * stop = True + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1245, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1245, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L220_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_is_return != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L220_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1247 + * if self._is_same_frame(stop_frame, frame) and is_return: + * # We're exiting the smart step into initial frame (so, we probably didn't find our target). + * stop = True # <<<<<<<<<<<<<< + * + * elif self._is_same_frame(stop_frame, back) and is_line: + */ + __pyx_v_stop = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1245 + * stop = False + * back = frame.f_back + * if self._is_same_frame(stop_frame, frame) and is_return: # <<<<<<<<<<<<<< + * # We're exiting the smart step into initial frame (so, we probably didn't find our target). + * stop = True + */ + goto __pyx_L219; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1249 + * stop = True + * + * elif self._is_same_frame(stop_frame, back) and is_line: # <<<<<<<<<<<<<< + * if info.pydev_smart_child_offset != -1: + * # i.e.: in this case, we're not interested in the pause in the parent, rather + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1249, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1249, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L222_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_is_line != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L222_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1250 + * + * elif self._is_same_frame(stop_frame, back) and is_line: + * if info.pydev_smart_child_offset != -1: # <<<<<<<<<<<<<< + * # i.e.: in this case, we're not interested in the pause in the parent, rather + * # we're interested in the pause in the child (when the parent is at the proper place). + */ + __pyx_t_11 = ((__pyx_v_info->pydev_smart_child_offset != -1L) != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1253 + * # i.e.: in this case, we're not interested in the pause in the parent, rather + * # we're interested in the pause in the child (when the parent is at the proper place). + * stop = False # <<<<<<<<<<<<<< + * + * else: + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1250 + * + * elif self._is_same_frame(stop_frame, back) and is_line: + * if info.pydev_smart_child_offset != -1: # <<<<<<<<<<<<<< + * # i.e.: in this case, we're not interested in the pause in the parent, rather + * # we're interested in the pause in the child (when the parent is at the proper place). + */ + goto __pyx_L224; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1256 + * + * else: + * pydev_smart_parent_offset = info.pydev_smart_parent_offset # <<<<<<<<<<<<<< + * + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + */ + /*else*/ { + __pyx_t_10 = __pyx_v_info->pydev_smart_parent_offset; + __pyx_v_pydev_smart_parent_offset = __pyx_t_10; + + /* "_pydevd_bundle/pydevd_cython.pyx":1258 + * pydev_smart_parent_offset = info.pydev_smart_parent_offset + * + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants # <<<<<<<<<<<<<< + * if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: + * # Preferred mode (when the smart step into variants are available + */ + __pyx_t_1 = __pyx_v_info->pydev_smart_step_into_variants; + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pydev_smart_step_into_variants = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1259 + * + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + * if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: # <<<<<<<<<<<<<< + * # Preferred mode (when the smart step into variants are available + * # and the offset is set). + */ + __pyx_t_14 = ((__pyx_v_pydev_smart_parent_offset >= 0) != 0); + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L226_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_pydev_smart_step_into_variants != Py_None)&&(PyTuple_GET_SIZE(__pyx_v_pydev_smart_step_into_variants) != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L226_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1262 + * # Preferred mode (when the smart step into variants are available + * # and the offset is set). + * stop = get_smart_step_into_variant_from_frame_offset(back.f_lasti, pydev_smart_step_into_variants) is \ # <<<<<<<<<<<<<< + * get_smart_step_into_variant_from_frame_offset(pydev_smart_parent_offset, pydev_smart_step_into_variants) + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_get_smart_step_into_variant_from); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1262, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_back, __pyx_n_s_f_lasti); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1262, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_4 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_t_7, __pyx_v_pydev_smart_step_into_variants}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1262, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { + PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_t_7, __pyx_v_pydev_smart_step_into_variants}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1262, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_8 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1262, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_4); __pyx_t_4 = NULL; + } + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_10, __pyx_t_7); + __Pyx_INCREF(__pyx_v_pydev_smart_step_into_variants); + __Pyx_GIVEREF(__pyx_v_pydev_smart_step_into_variants); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_10, __pyx_v_pydev_smart_step_into_variants); + __pyx_t_7 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1262, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1263 + * # and the offset is set). + * stop = get_smart_step_into_variant_from_frame_offset(back.f_lasti, pydev_smart_step_into_variants) is \ + * get_smart_step_into_variant_from_frame_offset(pydev_smart_parent_offset, pydev_smart_step_into_variants) # <<<<<<<<<<<<<< + * + * else: + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_get_smart_step_into_variant_from); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1263, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_pydev_smart_parent_offset); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1263, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_4 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_t_7, __pyx_v_pydev_smart_step_into_variants}; + __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1263, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_t_7, __pyx_v_pydev_smart_step_into_variants}; + __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1263, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_3 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1263, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); __pyx_t_4 = NULL; + } + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_10, __pyx_t_7); + __Pyx_INCREF(__pyx_v_pydev_smart_step_into_variants); + __Pyx_GIVEREF(__pyx_v_pydev_smart_step_into_variants); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_10, __pyx_v_pydev_smart_step_into_variants); + __pyx_t_7 = 0; + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_3, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1263, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_11 = (__pyx_t_1 == __pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_v_stop = __pyx_t_11; + + /* "_pydevd_bundle/pydevd_cython.pyx":1259 + * + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + * if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: # <<<<<<<<<<<<<< + * # Preferred mode (when the smart step into variants are available + * # and the offset is set). + */ + goto __pyx_L225; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1267 + * else: + * # Only the name/line is available, so, check that. + * curr_func_name = frame.f_code.co_name # <<<<<<<<<<<<<< + * + * # global context is set with an empty name + */ + /*else*/ { + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1267, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_co_name); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1267, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 1267, __pyx_L171_error) + __Pyx_XDECREF_SET(__pyx_v_curr_func_name, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1270 + * + * # global context is set with an empty name + * if curr_func_name in ('?', '') or curr_func_name is None: # <<<<<<<<<<<<<< + * curr_func_name = '' + * if curr_func_name == info.pydev_func_name and stop_frame.f_lineno == info.pydev_next_line: + */ + __Pyx_INCREF(__pyx_v_curr_func_name); + __pyx_t_21 = __pyx_v_curr_func_name; + __pyx_t_9 = (__Pyx_PyString_Equals(__pyx_t_21, __pyx_kp_s__3, Py_EQ)); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1270, __pyx_L171_error) + __pyx_t_29 = (__pyx_t_9 != 0); + if (!__pyx_t_29) { + } else { + __pyx_t_14 = __pyx_t_29; + goto __pyx_L231_bool_binop_done; + } + __pyx_t_29 = (__Pyx_PyString_Equals(__pyx_t_21, __pyx_kp_s_module, Py_EQ)); if (unlikely(__pyx_t_29 < 0)) __PYX_ERR(0, 1270, __pyx_L171_error) + __pyx_t_9 = (__pyx_t_29 != 0); + __pyx_t_14 = __pyx_t_9; + __pyx_L231_bool_binop_done:; + __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0; + __pyx_t_9 = (__pyx_t_14 != 0); + if (!__pyx_t_9) { + } else { + __pyx_t_11 = __pyx_t_9; + goto __pyx_L229_bool_binop_done; + } + __pyx_t_9 = (__pyx_v_curr_func_name == ((PyObject*)Py_None)); + __pyx_t_14 = (__pyx_t_9 != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L229_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1271 + * # global context is set with an empty name + * if curr_func_name in ('?', '') or curr_func_name is None: + * curr_func_name = '' # <<<<<<<<<<<<<< + * if curr_func_name == info.pydev_func_name and stop_frame.f_lineno == info.pydev_next_line: + * stop = True + */ + __Pyx_INCREF(__pyx_kp_s_); + __Pyx_DECREF_SET(__pyx_v_curr_func_name, __pyx_kp_s_); + + /* "_pydevd_bundle/pydevd_cython.pyx":1270 + * + * # global context is set with an empty name + * if curr_func_name in ('?', '') or curr_func_name is None: # <<<<<<<<<<<<<< + * curr_func_name = '' + * if curr_func_name == info.pydev_func_name and stop_frame.f_lineno == info.pydev_next_line: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1272 + * if curr_func_name in ('?', '') or curr_func_name is None: + * curr_func_name = '' + * if curr_func_name == info.pydev_func_name and stop_frame.f_lineno == info.pydev_next_line: # <<<<<<<<<<<<<< + * stop = True + * + */ + __pyx_t_14 = (__Pyx_PyString_Equals(__pyx_v_curr_func_name, __pyx_v_info->pydev_func_name, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1272, __pyx_L171_error) + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + } else { + __pyx_t_11 = __pyx_t_9; + goto __pyx_L234_bool_binop_done; + } + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_stop_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1272, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_6 = __Pyx_PyInt_From_int(__pyx_v_info->pydev_next_line); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1272, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = PyObject_RichCompare(__pyx_t_1, __pyx_t_6, Py_EQ); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1272, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1272, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_11 = __pyx_t_9; + __pyx_L234_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1273 + * curr_func_name = '' + * if curr_func_name == info.pydev_func_name and stop_frame.f_lineno == info.pydev_next_line: + * stop = True # <<<<<<<<<<<<<< + * + * if not stop: + */ + __pyx_v_stop = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1272 + * if curr_func_name in ('?', '') or curr_func_name is None: + * curr_func_name = '' + * if curr_func_name == info.pydev_func_name and stop_frame.f_lineno == info.pydev_next_line: # <<<<<<<<<<<<<< + * stop = True + * + */ + } + } + __pyx_L225:; + } + __pyx_L224:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1275 + * stop = True + * + * if not stop: # <<<<<<<<<<<<<< + * # In smart step into, if we didn't hit it in this frame once, that'll + * # not be the case next time either, so, disable tracing for this frame. + */ + __pyx_t_11 = ((!(__pyx_v_stop != 0)) != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1278 + * # In smart step into, if we didn't hit it in this frame once, that'll + * # not be the case next time either, so, disable tracing for this frame. + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * elif back is not None and self._is_same_frame(stop_frame, back.f_back) and is_line: + */ + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_8 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1278, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_8; + __pyx_t_8 = 0; + goto __pyx_L175_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1275 + * stop = True + * + * if not stop: # <<<<<<<<<<<<<< + * # In smart step into, if we didn't hit it in this frame once, that'll + * # not be the case next time either, so, disable tracing for this frame. + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1249 + * stop = True + * + * elif self._is_same_frame(stop_frame, back) and is_line: # <<<<<<<<<<<<<< + * if info.pydev_smart_child_offset != -1: + * # i.e.: in this case, we're not interested in the pause in the parent, rather + */ + goto __pyx_L219; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1280 + * return None if is_call else NO_FTRACE + * + * elif back is not None and self._is_same_frame(stop_frame, back.f_back) and is_line: # <<<<<<<<<<<<<< + * # Ok, we have to track 2 stops at this point, the parent and the child offset. + * # This happens when handling a step into which targets a function inside a list comprehension + */ + __pyx_t_9 = (__pyx_v_back != Py_None); + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L237_bool_binop_done; + } + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_back, __pyx_n_s_f_back); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1280, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_6 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_t_8); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1280, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1280, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L237_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_is_line != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L237_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1284 + * # This happens when handling a step into which targets a function inside a list comprehension + * # or generator (in which case an intermediary frame is created due to an internal function call). + * pydev_smart_parent_offset = info.pydev_smart_parent_offset # <<<<<<<<<<<<<< + * pydev_smart_child_offset = info.pydev_smart_child_offset + * # print('matched back frame', pydev_smart_parent_offset, pydev_smart_child_offset) + */ + __pyx_t_10 = __pyx_v_info->pydev_smart_parent_offset; + __pyx_v_pydev_smart_parent_offset = __pyx_t_10; + + /* "_pydevd_bundle/pydevd_cython.pyx":1285 + * # or generator (in which case an intermediary frame is created due to an internal function call). + * pydev_smart_parent_offset = info.pydev_smart_parent_offset + * pydev_smart_child_offset = info.pydev_smart_child_offset # <<<<<<<<<<<<<< + * # print('matched back frame', pydev_smart_parent_offset, pydev_smart_child_offset) + * # print('parent f_lasti', back.f_back.f_lasti) + */ + __pyx_t_10 = __pyx_v_info->pydev_smart_child_offset; + __pyx_v_pydev_smart_child_offset = __pyx_t_10; + + /* "_pydevd_bundle/pydevd_cython.pyx":1289 + * # print('parent f_lasti', back.f_back.f_lasti) + * # print('child f_lasti', back.f_lasti) + * stop = False # <<<<<<<<<<<<<< + * if pydev_smart_child_offset >= 0 and pydev_smart_child_offset >= 0: + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1290 + * # print('child f_lasti', back.f_lasti) + * stop = False + * if pydev_smart_child_offset >= 0 and pydev_smart_child_offset >= 0: # <<<<<<<<<<<<<< + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + * + */ + __pyx_t_14 = ((__pyx_v_pydev_smart_child_offset >= 0) != 0); + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L241_bool_binop_done; + } + __pyx_t_14 = ((__pyx_v_pydev_smart_child_offset >= 0) != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L241_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1291 + * stop = False + * if pydev_smart_child_offset >= 0 and pydev_smart_child_offset >= 0: + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants # <<<<<<<<<<<<<< + * + * if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: + */ + __pyx_t_6 = __pyx_v_info->pydev_smart_step_into_variants; + __Pyx_INCREF(__pyx_t_6); + __pyx_v_pydev_smart_step_into_variants = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1293 + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + * + * if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: # <<<<<<<<<<<<<< + * # Note that we don't really check the parent offset, only the offset of + * # the child (because this is a generator, the parent may have moved forward + */ + __pyx_t_14 = ((__pyx_v_pydev_smart_parent_offset >= 0) != 0); + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L244_bool_binop_done; + } + __pyx_t_14 = (__pyx_v_pydev_smart_step_into_variants != Py_None)&&(PyTuple_GET_SIZE(__pyx_v_pydev_smart_step_into_variants) != 0); + __pyx_t_11 = __pyx_t_14; + __pyx_L244_bool_binop_done:; + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1298 + * # already -- and that's ok, so, we just check that the parent frame + * # matches in this case). + * smart_step_into_variant = get_smart_step_into_variant_from_frame_offset(pydev_smart_parent_offset, pydev_smart_step_into_variants) # <<<<<<<<<<<<<< + * # print('matched parent offset', pydev_smart_parent_offset) + * # Ok, now, check the child variant + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_get_smart_step_into_variant_from); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1298, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_pydev_smart_parent_offset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1298, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_t_1, __pyx_v_pydev_smart_step_into_variants}; + __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1298, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_t_1, __pyx_v_pydev_smart_step_into_variants}; + __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1298, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else + #endif + { + __pyx_t_7 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1298, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_10, __pyx_t_1); + __Pyx_INCREF(__pyx_v_pydev_smart_step_into_variants); + __Pyx_GIVEREF(__pyx_v_pydev_smart_step_into_variants); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_10, __pyx_v_pydev_smart_step_into_variants); + __pyx_t_1 = 0; + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_7, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1298, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_smart_step_into_variant = __pyx_t_6; + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1301 + * # print('matched parent offset', pydev_smart_parent_offset) + * # Ok, now, check the child variant + * children_variants = smart_step_into_variant.children_variants # <<<<<<<<<<<<<< + * stop = children_variants and ( + * get_smart_step_into_variant_from_frame_offset(back.f_lasti, children_variants) is \ + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_smart_step_into_variant, __pyx_n_s_children_variants); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1301, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_children_variants = __pyx_t_6; + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1302 + * # Ok, now, check the child variant + * children_variants = smart_step_into_variant.children_variants + * stop = children_variants and ( # <<<<<<<<<<<<<< + * get_smart_step_into_variant_from_frame_offset(back.f_lasti, children_variants) is \ + * get_smart_step_into_variant_from_frame_offset(pydev_smart_child_offset, children_variants) + */ + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_children_variants); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1302, __pyx_L171_error) + if (__pyx_t_14) { + } else { + __pyx_t_11 = __pyx_t_14; + goto __pyx_L246_bool_binop_done; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1303 + * children_variants = smart_step_into_variant.children_variants + * stop = children_variants and ( + * get_smart_step_into_variant_from_frame_offset(back.f_lasti, children_variants) is \ # <<<<<<<<<<<<<< + * get_smart_step_into_variant_from_frame_offset(pydev_smart_child_offset, children_variants) + * ) + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_get_smart_step_into_variant_from); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1303, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_back, __pyx_n_s_f_lasti); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1303, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_7, __pyx_v_children_variants}; + __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1303, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_7, __pyx_v_children_variants}; + __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1303, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_3 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1303, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_1) { + __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); __pyx_t_1 = NULL; + } + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_10, __pyx_t_7); + __Pyx_INCREF(__pyx_v_children_variants); + __Pyx_GIVEREF(__pyx_v_children_variants); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_10, __pyx_v_children_variants); + __pyx_t_7 = 0; + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_3, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1303, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1304 + * stop = children_variants and ( + * get_smart_step_into_variant_from_frame_offset(back.f_lasti, children_variants) is \ + * get_smart_step_into_variant_from_frame_offset(pydev_smart_child_offset, children_variants) # <<<<<<<<<<<<<< + * ) + * # print('stop at child', stop) + */ + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_get_smart_step_into_variant_from); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1304, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_pydev_smart_child_offset); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1304, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_7, __pyx_v_children_variants}; + __pyx_t_8 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1304, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_7, __pyx_v_children_variants}; + __pyx_t_8 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1304, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else + #endif + { + __pyx_t_4 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1304, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + if (__pyx_t_1) { + __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); __pyx_t_1 = NULL; + } + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_10, __pyx_t_7); + __Pyx_INCREF(__pyx_v_children_variants); + __Pyx_GIVEREF(__pyx_v_children_variants); + PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_10, __pyx_v_children_variants); + __pyx_t_7 = 0; + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1304, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_14 = (__pyx_t_6 == __pyx_t_8); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1303 + * children_variants = smart_step_into_variant.children_variants + * stop = children_variants and ( + * get_smart_step_into_variant_from_frame_offset(back.f_lasti, children_variants) is \ # <<<<<<<<<<<<<< + * get_smart_step_into_variant_from_frame_offset(pydev_smart_child_offset, children_variants) + * ) + */ + __pyx_t_9 = (__pyx_t_14 != 0); + __pyx_t_11 = __pyx_t_9; + __pyx_L246_bool_binop_done:; + __pyx_v_stop = __pyx_t_11; + + /* "_pydevd_bundle/pydevd_cython.pyx":1293 + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + * + * if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: # <<<<<<<<<<<<<< + * # Note that we don't really check the parent offset, only the offset of + * # the child (because this is a generator, the parent may have moved forward + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1290 + * # print('child f_lasti', back.f_lasti) + * stop = False + * if pydev_smart_child_offset >= 0 and pydev_smart_child_offset >= 0: # <<<<<<<<<<<<<< + * pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1308 + * # print('stop at child', stop) + * + * if not stop: # <<<<<<<<<<<<<< + * # In smart step into, if we didn't hit it in this frame once, that'll + * # not be the case next time either, so, disable tracing for this frame. + */ + __pyx_t_11 = ((!(__pyx_v_stop != 0)) != 0); + if (__pyx_t_11) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1311 + * # In smart step into, if we didn't hit it in this frame once, that'll + * # not be the case next time either, so, disable tracing for this frame. + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * elif step_cmd in (109, 160): + */ + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_8 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1311, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_8; + __pyx_t_8 = 0; + goto __pyx_L175_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1308 + * # print('stop at child', stop) + * + * if not stop: # <<<<<<<<<<<<<< + * # In smart step into, if we didn't hit it in this frame once, that'll + * # not be the case next time either, so, disable tracing for this frame. + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1280 + * return None if is_call else NO_FTRACE + * + * elif back is not None and self._is_same_frame(stop_frame, back.f_back) and is_line: # <<<<<<<<<<<<<< + * # Ok, we have to track 2 stops at this point, the parent and the child offset. + * # This happens when handling a step into which targets a function inside a list comprehension + */ + } + __pyx_L219:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1242 + * stop, plugin_stop = result + * + * elif step_cmd == 128: # <<<<<<<<<<<<<< + * stop = False + * back = frame.f_back + */ + goto __pyx_L180; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1313 + * return None if is_call else NO_FTRACE + * + * elif step_cmd in (109, 160): # <<<<<<<<<<<<<< + * stop = is_return and self._is_same_frame(stop_frame, frame) + * + */ + switch (__pyx_v_step_cmd) { + case 0x6D: + case 0xA0: + __pyx_t_11 = 1; + break; + default: + __pyx_t_11 = 0; + break; + } + __pyx_t_9 = (__pyx_t_11 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1314 + * + * elif step_cmd in (109, 160): + * stop = is_return and self._is_same_frame(stop_frame, frame) # <<<<<<<<<<<<<< + * + * else: + */ + __pyx_t_11 = (__pyx_v_is_return != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L249_bool_binop_done; + } + __pyx_t_8 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self->__pyx_vtab)->_is_same_frame(__pyx_v_self, __pyx_v_stop_frame, __pyx_v_frame); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1314, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 1314, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_9 = __pyx_t_11; + __pyx_L249_bool_binop_done:; + __pyx_v_stop = __pyx_t_9; + + /* "_pydevd_bundle/pydevd_cython.pyx":1313 + * return None if is_call else NO_FTRACE + * + * elif step_cmd in (109, 160): # <<<<<<<<<<<<<< + * stop = is_return and self._is_same_frame(stop_frame, frame) + * + */ + goto __pyx_L180; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1317 + * + * else: + * stop = False # <<<<<<<<<<<<<< + * + * if stop and step_cmd != -1 and is_return and hasattr(frame, "f_back"): + */ + /*else*/ { + __pyx_v_stop = 0; + } + __pyx_L180:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1319 + * stop = False + * + * if stop and step_cmd != -1 and is_return and hasattr(frame, "f_back"): # <<<<<<<<<<<<<< + * f_code = getattr(frame.f_back, 'f_code', None) + * if f_code is not None: + */ + __pyx_t_11 = (__pyx_v_stop != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L252_bool_binop_done; + } + __pyx_t_11 = ((__pyx_v_step_cmd != -1L) != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L252_bool_binop_done; + } + __pyx_t_11 = (__pyx_v_is_return != 0); + if (__pyx_t_11) { + } else { + __pyx_t_9 = __pyx_t_11; + goto __pyx_L252_bool_binop_done; + } + __pyx_t_11 = __Pyx_HasAttr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(__pyx_t_11 == ((int)-1))) __PYX_ERR(0, 1319, __pyx_L171_error) + __pyx_t_14 = (__pyx_t_11 != 0); + __pyx_t_9 = __pyx_t_14; + __pyx_L252_bool_binop_done:; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1320 + * + * if stop and step_cmd != -1 and is_return and hasattr(frame, "f_back"): + * f_code = getattr(frame.f_back, 'f_code', None) # <<<<<<<<<<<<<< + * if f_code is not None: + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1320, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_6 = __Pyx_GetAttr3(__pyx_t_8, __pyx_n_s_f_code, Py_None); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1320, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_f_code = __pyx_t_6; + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1321 + * if stop and step_cmd != -1 and is_return and hasattr(frame, "f_back"): + * f_code = getattr(frame.f_back, 'f_code', None) + * if f_code is not None: # <<<<<<<<<<<<<< + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + * stop = False + */ + __pyx_t_9 = (__pyx_v_f_code != Py_None); + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1322 + * f_code = getattr(frame.f_back, 'f_code', None) + * if f_code is not None: + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: # <<<<<<<<<<<<<< + * stop = False + * + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_get_file_type); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1322, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1322, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_6 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1322, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_PYDEV_FILE); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1322, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = PyObject_RichCompare(__pyx_t_6, __pyx_t_8, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1322, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1322, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1323 + * if f_code is not None: + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + * stop = False # <<<<<<<<<<<<<< + * + * if plugin_stop: + */ + __pyx_v_stop = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1322 + * f_code = getattr(frame.f_back, 'f_code', None) + * if f_code is not None: + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: # <<<<<<<<<<<<<< + * stop = False + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1321 + * if stop and step_cmd != -1 and is_return and hasattr(frame, "f_back"): + * f_code = getattr(frame.f_back, 'f_code', None) + * if f_code is not None: # <<<<<<<<<<<<<< + * if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + * stop = False + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1319 + * stop = False + * + * if stop and step_cmd != -1 and is_return and hasattr(frame, "f_back"): # <<<<<<<<<<<<<< + * f_code = getattr(frame.f_back, 'f_code', None) + * if f_code is not None: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1325 + * stop = False + * + * if plugin_stop: # <<<<<<<<<<<<<< + * stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) + * elif stop: + */ + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_plugin_stop); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1325, __pyx_L171_error) + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1326 + * + * if plugin_stop: + * stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) # <<<<<<<<<<<<<< + * elif stop: + * if is_line: + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_plugin_manager, __pyx_n_s_stop); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1326, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_6 = __Pyx_PyInt_From_int(__pyx_v_step_cmd); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1326, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[8] = {__pyx_t_4, __pyx_v_main_debugger, __pyx_v_frame, __pyx_v_event, __pyx_v_self->_args, __pyx_v_stop_info, __pyx_v_arg, __pyx_t_6}; + __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 7+__pyx_t_10); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1326, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[8] = {__pyx_t_4, __pyx_v_main_debugger, __pyx_v_frame, __pyx_v_event, __pyx_v_self->_args, __pyx_v_stop_info, __pyx_v_arg, __pyx_t_6}; + __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 7+__pyx_t_10); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1326, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + { + __pyx_t_7 = PyTuple_New(7+__pyx_t_10); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1326, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_4); __pyx_t_4 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_10, __pyx_v_main_debugger); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_10, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_7, 2+__pyx_t_10, __pyx_v_event); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_7, 3+__pyx_t_10, __pyx_v_self->_args); + __Pyx_INCREF(__pyx_v_stop_info); + __Pyx_GIVEREF(__pyx_v_stop_info); + PyTuple_SET_ITEM(__pyx_t_7, 4+__pyx_t_10, __pyx_v_stop_info); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_7, 5+__pyx_t_10, __pyx_v_arg); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_7, 6+__pyx_t_10, __pyx_t_6); + __pyx_t_6 = 0; + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1326, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_stopped_on_plugin = __pyx_t_3; + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1325 + * stop = False + * + * if plugin_stop: # <<<<<<<<<<<<<< + * stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) + * elif stop: + */ + goto __pyx_L258; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1327 + * if plugin_stop: + * stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) + * elif stop: # <<<<<<<<<<<<<< + * if is_line: + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + */ + __pyx_t_14 = (__pyx_v_stop != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1328 + * stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) + * elif stop: + * if is_line: # <<<<<<<<<<<<<< + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + * self.do_wait_suspend(thread, frame, event, arg) + */ + __pyx_t_14 = (__pyx_v_is_line != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1329 + * elif stop: + * if is_line: + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) # <<<<<<<<<<<<<< + * self.do_wait_suspend(thread, frame, event, arg) + * elif is_return: # return event + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_suspend); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1329, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = __Pyx_PyInt_From_int(__pyx_v_step_cmd); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1329, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1329, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_v_thread); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8); + __pyx_t_8 = 0; + __pyx_t_8 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1329, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_6 = __Pyx_PyInt_From_int(__pyx_v_info->pydev_original_step_cmd); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1329, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + if (PyDict_SetItem(__pyx_t_8, __pyx_n_s_original_step_cmd, __pyx_t_6) < 0) __PYX_ERR(0, 1329, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, __pyx_t_8); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1329, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1330 + * if is_line: + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + * self.do_wait_suspend(thread, frame, event, arg) # <<<<<<<<<<<<<< + * elif is_return: # return event + * back = frame.f_back + */ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_do_wait_suspend); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1330, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[5] = {__pyx_t_7, __pyx_v_thread, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 4+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1330, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_6); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) { + PyObject *__pyx_temp[5] = {__pyx_t_7, __pyx_v_thread, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_10, 4+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1330, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_6); + } else + #endif + { + __pyx_t_3 = PyTuple_New(4+__pyx_t_10); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1330, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_7) { + __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7); __pyx_t_7 = NULL; + } + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_10, __pyx_v_thread); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_10, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_3, 2+__pyx_t_10, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_3, 3+__pyx_t_10, __pyx_v_arg); + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_3, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1330, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1328 + * stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) + * elif stop: + * if is_line: # <<<<<<<<<<<<<< + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + * self.do_wait_suspend(thread, frame, event, arg) + */ + goto __pyx_L259; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1331 + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + * self.do_wait_suspend(thread, frame, event, arg) + * elif is_return: # return event # <<<<<<<<<<<<<< + * back = frame.f_back + * if back is not None: + */ + __pyx_t_14 = (__pyx_v_is_return != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1332 + * self.do_wait_suspend(thread, frame, event, arg) + * elif is_return: # return event + * back = frame.f_back # <<<<<<<<<<<<<< + * if back is not None: + * # When we get to the pydevd run function, the debugging has actually finished for the main thread + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1332, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_XDECREF_SET(__pyx_v_back, __pyx_t_6); + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1333 + * elif is_return: # return event + * back = frame.f_back + * if back is not None: # <<<<<<<<<<<<<< + * # When we get to the pydevd run function, the debugging has actually finished for the main thread + * # (note that it can still go on for other threads, but for this one, we just make it finish) + */ + __pyx_t_14 = (__pyx_v_back != Py_None); + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1337 + * # (note that it can still go on for other threads, but for this one, we just make it finish) + * # So, just setting it to None should be OK + * back_absolute_filename, _, base = get_abs_path_real_path_and_base_from_frame(back) # <<<<<<<<<<<<<< + * if (base, back.f_code.co_name) in (DEBUG_START, DEBUG_START_PY3K): + * back = None + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_get_abs_path_real_path_and_base); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1337, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_6 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_3, __pyx_v_back) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_v_back); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1337, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_6))) || (PyList_CheckExact(__pyx_t_6))) { + PyObject* sequence = __pyx_t_6; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 3)) { + if (size > 3) __Pyx_RaiseTooManyValuesError(3); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 1337, __pyx_L171_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); + } else { + __pyx_t_8 = PyList_GET_ITEM(sequence, 0); + __pyx_t_3 = PyList_GET_ITEM(sequence, 1); + __pyx_t_7 = PyList_GET_ITEM(sequence, 2); + } + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + #else + __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1337, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1337, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1337, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + #endif + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_4 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1337, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_4)->tp_iternext; + index = 0; __pyx_t_8 = __pyx_t_15(__pyx_t_4); if (unlikely(!__pyx_t_8)) goto __pyx_L261_unpacking_failed; + __Pyx_GOTREF(__pyx_t_8); + index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L261_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 2; __pyx_t_7 = __pyx_t_15(__pyx_t_4); if (unlikely(!__pyx_t_7)) goto __pyx_L261_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_4), 3) < 0) __PYX_ERR(0, 1337, __pyx_L171_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + goto __pyx_L262_unpacking_done; + __pyx_L261_unpacking_failed:; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 1337, __pyx_L171_error) + __pyx_L262_unpacking_done:; + } + __pyx_v_back_absolute_filename = __pyx_t_8; + __pyx_t_8 = 0; + __pyx_v__ = __pyx_t_3; + __pyx_t_3 = 0; + __pyx_v_base = __pyx_t_7; + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1338 + * # So, just setting it to None should be OK + * back_absolute_filename, _, base = get_abs_path_real_path_and_base_from_frame(back) + * if (base, back.f_code.co_name) in (DEBUG_START, DEBUG_START_PY3K): # <<<<<<<<<<<<<< + * back = None + * + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_back, __pyx_n_s_f_code); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_co_name); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(__pyx_v_base); + __Pyx_GIVEREF(__pyx_v_base); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v_base); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_DEBUG_START); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = PyObject_RichCompare(__pyx_t_6, __pyx_t_7, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (!__pyx_t_14) { + } else { + __pyx_t_9 = __pyx_t_14; + goto __pyx_L264_bool_binop_done; + } + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_DEBUG_START_PY3K); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = PyObject_RichCompare(__pyx_t_6, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_7); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1338, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_9 = __pyx_t_14; + __pyx_L264_bool_binop_done:; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_14 = (__pyx_t_9 != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1339 + * back_absolute_filename, _, base = get_abs_path_real_path_and_base_from_frame(back) + * if (base, back.f_code.co_name) in (DEBUG_START, DEBUG_START_PY3K): + * back = None # <<<<<<<<<<<<<< + * + * elif base == TRACE_PROPERTY: + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_back, Py_None); + + /* "_pydevd_bundle/pydevd_cython.pyx":1338 + * # So, just setting it to None should be OK + * back_absolute_filename, _, base = get_abs_path_real_path_and_base_from_frame(back) + * if (base, back.f_code.co_name) in (DEBUG_START, DEBUG_START_PY3K): # <<<<<<<<<<<<<< + * back = None + * + */ + goto __pyx_L263; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1341 + * back = None + * + * elif base == TRACE_PROPERTY: # <<<<<<<<<<<<<< + * # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging) + * # if we're in a return, we want it to appear to the user in the previous frame! + */ + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_TRACE_PROPERTY); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1341, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = PyObject_RichCompare(__pyx_v_base, __pyx_t_6, Py_EQ); __Pyx_XGOTREF(__pyx_t_7); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1341, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 1341, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1344 + * # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging) + * # if we're in a return, we want it to appear to the user in the previous frame! + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * elif pydevd_dont_trace.should_trace_hook is not None: + */ + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_7 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1344, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L175_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1341 + * back = None + * + * elif base == TRACE_PROPERTY: # <<<<<<<<<<<<<< + * # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging) + * # if we're in a return, we want it to appear to the user in the previous frame! + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1346 + * return None if is_call else NO_FTRACE + * + * elif pydevd_dont_trace.should_trace_hook is not None: # <<<<<<<<<<<<<< + * if not pydevd_dont_trace.should_trace_hook(back, back_absolute_filename): + * # In this case, we'll have to skip the previous one because it shouldn't be traced. + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_pydevd_dont_trace); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1346, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_should_trace_hook); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1346, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_14 = (__pyx_t_6 != Py_None); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1347 + * + * elif pydevd_dont_trace.should_trace_hook is not None: + * if not pydevd_dont_trace.should_trace_hook(back, back_absolute_filename): # <<<<<<<<<<<<<< + * # In this case, we'll have to skip the previous one because it shouldn't be traced. + * # Also, we have to reset the tracing, because if the parent's parent (or some + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_pydevd_dont_trace); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1347, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_should_trace_hook); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1347, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_v_back, __pyx_v_back_absolute_filename}; + __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1347, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_6); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_v_back, __pyx_v_back_absolute_filename}; + __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1347, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_6); + } else + #endif + { + __pyx_t_8 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1347, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_7) { + __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL; + } + __Pyx_INCREF(__pyx_v_back); + __Pyx_GIVEREF(__pyx_v_back); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_10, __pyx_v_back); + __Pyx_INCREF(__pyx_v_back_absolute_filename); + __Pyx_GIVEREF(__pyx_v_back_absolute_filename); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_10, __pyx_v_back_absolute_filename); + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1347, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1347, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_14 = ((!__pyx_t_9) != 0); + if (__pyx_t_14) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1353 + * # we should anymore (so, a step in/over/return may not stop anywhere if no parent is traced). + * # Related test: _debugger_case17a.py + * main_debugger.set_trace_for_frame_and_parents(back) # <<<<<<<<<<<<<< + * return None if is_call else NO_FTRACE + * + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_set_trace_for_frame_and_parents); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1353, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_6 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_8, __pyx_v_back) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_back); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1353, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1354 + * # Related test: _debugger_case17a.py + * main_debugger.set_trace_for_frame_and_parents(back) + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * if back is not None: + */ + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_6 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1354, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __pyx_t_3; + __pyx_t_3 = 0; + } + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L175_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1347 + * + * elif pydevd_dont_trace.should_trace_hook is not None: + * if not pydevd_dont_trace.should_trace_hook(back, back_absolute_filename): # <<<<<<<<<<<<<< + * # In this case, we'll have to skip the previous one because it shouldn't be traced. + * # Also, we have to reset the tracing, because if the parent's parent (or some + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1346 + * return None if is_call else NO_FTRACE + * + * elif pydevd_dont_trace.should_trace_hook is not None: # <<<<<<<<<<<<<< + * if not pydevd_dont_trace.should_trace_hook(back, back_absolute_filename): + * # In this case, we'll have to skip the previous one because it shouldn't be traced. + */ + } + __pyx_L263:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1333 + * elif is_return: # return event + * back = frame.f_back + * if back is not None: # <<<<<<<<<<<<<< + * # When we get to the pydevd run function, the debugging has actually finished for the main thread + * # (note that it can still go on for other threads, but for this one, we just make it finish) + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1356 + * return None if is_call else NO_FTRACE + * + * if back is not None: # <<<<<<<<<<<<<< + * # if we're in a return, we want it to appear to the user in the previous frame! + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + */ + __pyx_t_14 = (__pyx_v_back != Py_None); + __pyx_t_9 = (__pyx_t_14 != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1358 + * if back is not None: + * # if we're in a return, we want it to appear to the user in the previous frame! + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) # <<<<<<<<<<<<<< + * self.do_wait_suspend(thread, back, event, arg) + * else: + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_suspend); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1358, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_step_cmd); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1358, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1358, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_thread); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1358, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_info->pydev_original_step_cmd); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1358, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_original_step_cmd, __pyx_t_7) < 0) __PYX_ERR(0, 1358, __pyx_L171_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, __pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1358, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1359 + * # if we're in a return, we want it to appear to the user in the previous frame! + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + * self.do_wait_suspend(thread, back, event, arg) # <<<<<<<<<<<<<< + * else: + * # in jython we may not have a back frame + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_do_wait_suspend); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1359, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = NULL; + __pyx_t_10 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_10 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[5] = {__pyx_t_8, __pyx_v_thread, __pyx_v_back, __pyx_v_event, __pyx_v_arg}; + __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_10, 4+__pyx_t_10); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1359, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_7); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[5] = {__pyx_t_8, __pyx_v_thread, __pyx_v_back, __pyx_v_event, __pyx_v_arg}; + __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_10, 4+__pyx_t_10); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1359, __pyx_L171_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_7); + } else + #endif + { + __pyx_t_6 = PyTuple_New(4+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1359, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_6); + if (__pyx_t_8) { + __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_8); __pyx_t_8 = NULL; + } + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_10, __pyx_v_thread); + __Pyx_INCREF(__pyx_v_back); + __Pyx_GIVEREF(__pyx_v_back); + PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_10, __pyx_v_back); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_6, 2+__pyx_t_10, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_6, 3+__pyx_t_10, __pyx_v_arg); + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1359, __pyx_L171_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1356 + * return None if is_call else NO_FTRACE + * + * if back is not None: # <<<<<<<<<<<<<< + * # if we're in a return, we want it to appear to the user in the previous frame! + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + */ + goto __pyx_L267; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1362 + * else: + * # in jython we may not have a back frame + * info.pydev_step_stop = None # <<<<<<<<<<<<<< + * info.pydev_original_step_cmd = -1 + * info.pydev_step_cmd = -1 + */ + /*else*/ { + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->pydev_step_stop); + __Pyx_DECREF(__pyx_v_info->pydev_step_stop); + __pyx_v_info->pydev_step_stop = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":1363 + * # in jython we may not have a back frame + * info.pydev_step_stop = None + * info.pydev_original_step_cmd = -1 # <<<<<<<<<<<<<< + * info.pydev_step_cmd = -1 + * info.pydev_state = 1 + */ + __pyx_v_info->pydev_original_step_cmd = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1364 + * info.pydev_step_stop = None + * info.pydev_original_step_cmd = -1 + * info.pydev_step_cmd = -1 # <<<<<<<<<<<<<< + * info.pydev_state = 1 + * + */ + __pyx_v_info->pydev_step_cmd = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1365 + * info.pydev_original_step_cmd = -1 + * info.pydev_step_cmd = -1 + * info.pydev_state = 1 # <<<<<<<<<<<<<< + * + * except KeyboardInterrupt: + */ + __pyx_v_info->pydev_state = 1; + } + __pyx_L267:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1331 + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + * self.do_wait_suspend(thread, frame, event, arg) + * elif is_return: # return event # <<<<<<<<<<<<<< + * back = frame.f_back + * if back is not None: + */ + } + __pyx_L259:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1327 + * if plugin_stop: + * stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) + * elif stop: # <<<<<<<<<<<<<< + * if is_line: + * self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + */ + } + __pyx_L258:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1146 + * + * # step handling. We stop when we hit the right frame + * try: # <<<<<<<<<<<<<< + * should_skip = 0 + * if pydevd_dont_trace.should_trace_hook is not None: + */ + } + __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; + __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_18); __pyx_t_18 = 0; + goto __pyx_L176_try_end; + __pyx_L171_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1367 + * info.pydev_state = 1 + * + * except KeyboardInterrupt: # <<<<<<<<<<<<<< + * raise + * except: + */ + __pyx_t_10 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_KeyboardInterrupt); + if (__pyx_t_10) { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_3, &__pyx_t_6) < 0) __PYX_ERR(0, 1367, __pyx_L173_except_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GOTREF(__pyx_t_6); + + /* "_pydevd_bundle/pydevd_cython.pyx":1368 + * + * except KeyboardInterrupt: + * raise # <<<<<<<<<<<<<< + * except: + * try: + */ + __Pyx_GIVEREF(__pyx_t_7); + __Pyx_GIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_ErrRestoreWithState(__pyx_t_7, __pyx_t_3, __pyx_t_6); + __pyx_t_7 = 0; __pyx_t_3 = 0; __pyx_t_6 = 0; + __PYX_ERR(0, 1368, __pyx_L173_except_error) + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1369 + * except KeyboardInterrupt: + * raise + * except: # <<<<<<<<<<<<<< + * try: + * pydev_log.exception() + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_3, &__pyx_t_7) < 0) __PYX_ERR(0, 1369, __pyx_L173_except_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GOTREF(__pyx_t_7); + + /* "_pydevd_bundle/pydevd_cython.pyx":1370 + * raise + * except: + * try: # <<<<<<<<<<<<<< + * pydev_log.exception() + * info.pydev_original_step_cmd = -1 + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_28, &__pyx_t_27, &__pyx_t_26); + __Pyx_XGOTREF(__pyx_t_28); + __Pyx_XGOTREF(__pyx_t_27); + __Pyx_XGOTREF(__pyx_t_26); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1371 + * except: + * try: + * pydev_log.exception() # <<<<<<<<<<<<<< + * info.pydev_original_step_cmd = -1 + * info.pydev_step_cmd = -1 + */ + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1371, __pyx_L272_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_exception); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1371, __pyx_L272_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_8 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1371, __pyx_L272_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1372 + * try: + * pydev_log.exception() + * info.pydev_original_step_cmd = -1 # <<<<<<<<<<<<<< + * info.pydev_step_cmd = -1 + * info.pydev_step_stop = None + */ + __pyx_v_info->pydev_original_step_cmd = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1373 + * pydev_log.exception() + * info.pydev_original_step_cmd = -1 + * info.pydev_step_cmd = -1 # <<<<<<<<<<<<<< + * info.pydev_step_stop = None + * except: + */ + __pyx_v_info->pydev_step_cmd = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1374 + * info.pydev_original_step_cmd = -1 + * info.pydev_step_cmd = -1 + * info.pydev_step_stop = None # <<<<<<<<<<<<<< + * except: + * return None if is_call else NO_FTRACE + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->pydev_step_stop); + __Pyx_DECREF(__pyx_v_info->pydev_step_stop); + __pyx_v_info->pydev_step_stop = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":1370 + * raise + * except: + * try: # <<<<<<<<<<<<<< + * pydev_log.exception() + * info.pydev_original_step_cmd = -1 + */ + } + __Pyx_XDECREF(__pyx_t_28); __pyx_t_28 = 0; + __Pyx_XDECREF(__pyx_t_27); __pyx_t_27 = 0; + __Pyx_XDECREF(__pyx_t_26); __pyx_t_26 = 0; + goto __pyx_L279_try_end; + __pyx_L272_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1375 + * info.pydev_step_cmd = -1 + * info.pydev_step_stop = None + * except: # <<<<<<<<<<<<<< + * return None if is_call else NO_FTRACE + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_8, &__pyx_t_1, &__pyx_t_4) < 0) __PYX_ERR(0, 1375, __pyx_L274_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_4); + + /* "_pydevd_bundle/pydevd_cython.pyx":1376 + * info.pydev_step_stop = None + * except: + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * # if we are quitting, let's stop the tracing + */ + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_2 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_30, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_30)) __PYX_ERR(0, 1376, __pyx_L274_except_error) + __Pyx_GOTREF(__pyx_t_30); + __pyx_t_2 = __pyx_t_30; + __pyx_t_30 = 0; + } + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L275_except_return; + } + __pyx_L274_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1370 + * raise + * except: + * try: # <<<<<<<<<<<<<< + * pydev_log.exception() + * info.pydev_original_step_cmd = -1 + */ + __Pyx_XGIVEREF(__pyx_t_28); + __Pyx_XGIVEREF(__pyx_t_27); + __Pyx_XGIVEREF(__pyx_t_26); + __Pyx_ExceptionReset(__pyx_t_28, __pyx_t_27, __pyx_t_26); + goto __pyx_L173_except_error; + __pyx_L275_except_return:; + __Pyx_XGIVEREF(__pyx_t_28); + __Pyx_XGIVEREF(__pyx_t_27); + __Pyx_XGIVEREF(__pyx_t_26); + __Pyx_ExceptionReset(__pyx_t_28, __pyx_t_27, __pyx_t_26); + goto __pyx_L174_except_return; + __pyx_L279_try_end:; + } + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L172_exception_handled; + } + __pyx_L173_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1146 + * + * # step handling. We stop when we hit the right frame + * try: # <<<<<<<<<<<<<< + * should_skip = 0 + * if pydevd_dont_trace.should_trace_hook is not None: + */ + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_ExceptionReset(__pyx_t_16, __pyx_t_17, __pyx_t_18); + goto __pyx_L4_error; + __pyx_L175_try_return:; + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_ExceptionReset(__pyx_t_16, __pyx_t_17, __pyx_t_18); + goto __pyx_L3_return; + __pyx_L174_except_return:; + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_ExceptionReset(__pyx_t_16, __pyx_t_17, __pyx_t_18); + goto __pyx_L3_return; + __pyx_L172_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_ExceptionReset(__pyx_t_16, __pyx_t_17, __pyx_t_18); + __pyx_L176_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1379 + * + * # if we are quitting, let's stop the tracing + * if main_debugger.quitting: # <<<<<<<<<<<<<< + * return None if is_call else NO_FTRACE + * + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_quitting); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1379, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1379, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1380 + * # if we are quitting, let's stop the tracing + * if main_debugger.quitting: + * return None if is_call else NO_FTRACE # <<<<<<<<<<<<<< + * + * return self.trace_dispatch + */ + __Pyx_XDECREF(__pyx_r); + if ((__pyx_v_is_call != 0)) { + __Pyx_INCREF(Py_None); + __pyx_t_7 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1380, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = __pyx_t_3; + __pyx_t_3 = 0; + } + __pyx_r = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L3_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1379 + * + * # if we are quitting, let's stop the tracing + * if main_debugger.quitting: # <<<<<<<<<<<<<< + * return None if is_call else NO_FTRACE + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1382 + * return None if is_call else NO_FTRACE + * + * return self.trace_dispatch # <<<<<<<<<<<<<< + * finally: + * info.is_tracing -= 1 + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1382, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_r = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L3_return; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1384 + * return self.trace_dispatch + * finally: + * info.is_tracing -= 1 # <<<<<<<<<<<<<< + * + * # end trace_dispatch + */ + /*finally:*/ { + __pyx_L4_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_18 = 0; __pyx_t_17 = 0; __pyx_t_16 = 0; __pyx_t_26 = 0; __pyx_t_27 = 0; __pyx_t_28 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_30); __pyx_t_30 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_26, &__pyx_t_27, &__pyx_t_28); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_18, &__pyx_t_17, &__pyx_t_16) < 0)) __Pyx_ErrFetch(&__pyx_t_18, &__pyx_t_17, &__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_18); + __Pyx_XGOTREF(__pyx_t_17); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_26); + __Pyx_XGOTREF(__pyx_t_27); + __Pyx_XGOTREF(__pyx_t_28); + __pyx_t_10 = __pyx_lineno; __pyx_t_5 = __pyx_clineno; __pyx_t_31 = __pyx_filename; + { + __pyx_v_info->is_tracing = (__pyx_v_info->is_tracing - 1); + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_26); + __Pyx_XGIVEREF(__pyx_t_27); + __Pyx_XGIVEREF(__pyx_t_28); + __Pyx_ExceptionReset(__pyx_t_26, __pyx_t_27, __pyx_t_28); + } + __Pyx_XGIVEREF(__pyx_t_18); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ErrRestore(__pyx_t_18, __pyx_t_17, __pyx_t_16); + __pyx_t_18 = 0; __pyx_t_17 = 0; __pyx_t_16 = 0; __pyx_t_26 = 0; __pyx_t_27 = 0; __pyx_t_28 = 0; + __pyx_lineno = __pyx_t_10; __pyx_clineno = __pyx_t_5; __pyx_filename = __pyx_t_31; + goto __pyx_L1_error; + } + __pyx_L3_return: { + __pyx_t_28 = __pyx_r; + __pyx_r = 0; + __pyx_v_info->is_tracing = (__pyx_v_info->is_tracing - 1); + __pyx_r = __pyx_t_28; + __pyx_t_28 = 0; + goto __pyx_L0; + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":700 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cpdef trace_dispatch(self, frame, str event, arg): # <<<<<<<<<<<<<< + * cdef tuple abs_path_canonical_path_and_base; + * cdef bint is_exception_event; + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_21); + __Pyx_XDECREF(__pyx_t_30); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_abs_path_canonical_path_and_base); + __Pyx_XDECREF((PyObject *)__pyx_v_info); + __Pyx_XDECREF(__pyx_v_breakpoints_for_file); + __Pyx_XDECREF(__pyx_v_stop_info); + __Pyx_XDECREF(__pyx_v_curr_func_name); + __Pyx_XDECREF(__pyx_v_frame_skips_cache); + __Pyx_XDECREF(__pyx_v_frame_cache_key); + __Pyx_XDECREF(__pyx_v_line_cache_key); + __Pyx_XDECREF(__pyx_v_bp); + __Pyx_XDECREF(__pyx_v_pydev_smart_step_into_variants); + __Pyx_XDECREF(__pyx_v_main_debugger); + __Pyx_XDECREF(__pyx_v_thread); + __Pyx_XDECREF(__pyx_v_plugin_manager); + __Pyx_XDECREF(__pyx_v_stop_frame); + __Pyx_XDECREF(__pyx_v_function_breakpoint_on_call_event); + __Pyx_XDECREF(__pyx_v_returns_cache_key); + __Pyx_XDECREF(__pyx_v_return_lines); + __Pyx_XDECREF(__pyx_v_x); + __Pyx_XDECREF(__pyx_v_f); + __Pyx_XDECREF(__pyx_v_func_lines); + __Pyx_XDECREF(__pyx_v_offset_and_lineno); + __Pyx_XDECREF(__pyx_v_flag); + __Pyx_XDECREF(__pyx_v_breakpoint); + __Pyx_XDECREF(__pyx_v_stop_reason); + __Pyx_XDECREF(__pyx_v_bp_type); + __Pyx_XDECREF(__pyx_v_new_frame); + __Pyx_XDECREF(__pyx_v_result); + __Pyx_XDECREF(__pyx_v_cmd); + __Pyx_XDECREF(__pyx_v_eval_result); + __Pyx_XDECREF(__pyx_v_plugin_stop); + __Pyx_XDECREF(__pyx_v_force_check_project_scope); + __Pyx_XDECREF(__pyx_v_filename); + __Pyx_XDECREF(__pyx_v_f2); + __Pyx_XDECREF(__pyx_v_back); + __Pyx_XDECREF(__pyx_v_smart_step_into_variant); + __Pyx_XDECREF(__pyx_v_children_variants); + __Pyx_XDECREF(__pyx_v_f_code); + __Pyx_XDECREF(__pyx_v_stopped_on_plugin); + __Pyx_XDECREF(__pyx_v_back_absolute_filename); + __Pyx_XDECREF(__pyx_v__); + __Pyx_XDECREF(__pyx_v_base); + __Pyx_XDECREF(__pyx_v_frame); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_11trace_dispatch(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_11trace_dispatch(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_event = 0; + PyObject *__pyx_v_arg = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("trace_dispatch (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_frame,&__pyx_n_s_event,&__pyx_n_s_arg,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_dispatch", 1, 3, 3, 1); __PYX_ERR(0, 700, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arg)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_dispatch", 1, 3, 3, 2); __PYX_ERR(0, 700, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "trace_dispatch") < 0)) __PYX_ERR(0, 700, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_frame = values[0]; + __pyx_v_event = ((PyObject*)values[1]); + __pyx_v_arg = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("trace_dispatch", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 700, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_event), (&PyString_Type), 1, "event", 1))) __PYX_ERR(0, 700, __pyx_L1_error) + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_10trace_dispatch(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self), __pyx_v_frame, __pyx_v_event, __pyx_v_arg); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_10trace_dispatch(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("trace_dispatch", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_trace_dispatch(__pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 700, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_13__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_13__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_12__reduce_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_12__reduce_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self._args, self.exc_info, self.should_skip) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->should_skip); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_self->_args); + __Pyx_INCREF(__pyx_v_self->exc_info); + __Pyx_GIVEREF(__pyx_v_self->exc_info); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_self->exc_info); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_t_1); + __pyx_t_1 = 0; + __pyx_v_state = ((PyObject*)__pyx_t_2); + __pyx_t_2 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self._args, self.exc_info, self.should_skip) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_2 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_v__dict = __pyx_t_2; + __pyx_t_2 = 0; + + /* "(tree fragment)":7 + * state = (self._args, self.exc_info, self.should_skip) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_3 = (__pyx_v__dict != Py_None); + __pyx_t_4 = (__pyx_t_3 != 0); + if (__pyx_t_4) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v__dict); + __pyx_t_1 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self._args is not None or self.exc_info is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self._args, self.exc_info, self.should_skip) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self._args is not None or self.exc_info is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, None), state + */ + /*else*/ { + __pyx_t_3 = (__pyx_v_self->_args != ((PyObject*)Py_None)); + __pyx_t_5 = (__pyx_t_3 != 0); + if (!__pyx_t_5) { + } else { + __pyx_t_4 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = (__pyx_v_self->exc_info != Py_None); + __pyx_t_3 = (__pyx_t_5 != 0); + __pyx_t_4 = __pyx_t_3; + __pyx_L4_bool_binop_done:; + __pyx_v_use_setstate = __pyx_t_4; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self._args is not None or self.exc_info is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, None), state + * else: + */ + __pyx_t_4 = (__pyx_v_use_setstate != 0); + if (__pyx_t_4) { + + /* "(tree fragment)":13 + * use_setstate = self._args is not None or self.exc_info is not None + * if use_setstate: + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pyx_unpickle_PyDBFrame); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_84338306); + __Pyx_GIVEREF(__pyx_int_84338306); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_84338306); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_2, 2, Py_None); + __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_2); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_v_state); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self._args is not None or self.exc_info is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, None), state + * else: + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_PyDBFrame__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pyx_unpickle_PyDBFrame); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_84338306); + __Pyx_GIVEREF(__pyx_int_84338306); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_84338306); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_v_state); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_2); + __pyx_t_6 = 0; + __pyx_t_2 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_PyDBFrame__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_15__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_15__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_14__setstate_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_14__setstate_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_PyDBFrame__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_PyDBFrame__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_PyDBFrame, (type(self), 0x506e682, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_PyDBFrame__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.PyDBFrame.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1422 + * + * + * def notify_skipped_step_in_because_of_filters(py_db, frame): # <<<<<<<<<<<<<< + * global _global_notify_skipped_step_in + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_5notify_skipped_step_in_because_of_filters(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_5notify_skipped_step_in_because_of_filters = {"notify_skipped_step_in_because_of_filters", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_5notify_skipped_step_in_because_of_filters, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_5notify_skipped_step_in_because_of_filters(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_py_db = 0; + PyObject *__pyx_v_frame = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("notify_skipped_step_in_because_of_filters (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_py_db,&__pyx_n_s_frame,0}; + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_py_db)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("notify_skipped_step_in_because_of_filters", 1, 2, 2, 1); __PYX_ERR(0, 1422, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "notify_skipped_step_in_because_of_filters") < 0)) __PYX_ERR(0, 1422, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_py_db = values[0]; + __pyx_v_frame = values[1]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("notify_skipped_step_in_because_of_filters", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1422, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.notify_skipped_step_in_because_of_filters", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_4notify_skipped_step_in_because_of_filters(__pyx_self, __pyx_v_py_db, __pyx_v_frame); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_4notify_skipped_step_in_because_of_filters(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_py_db, PyObject *__pyx_v_frame) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_t_9; + PyObject *__pyx_t_10 = NULL; + int __pyx_t_11; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("notify_skipped_step_in_because_of_filters", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1425 + * global _global_notify_skipped_step_in + * + * with _global_notify_skipped_step_in_lock: # <<<<<<<<<<<<<< + * if _global_notify_skipped_step_in: + * # Check with lock in place (callers should actually have checked + */ + /*with:*/ { + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_global_notify_skipped_step_in_l); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1425, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_LookupSpecial(__pyx_t_1, __pyx_n_s_exit); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1425, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_LookupSpecial(__pyx_t_1, __pyx_n_s_enter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1425, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1425, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + /*try:*/ { + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_6, &__pyx_t_7, &__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_8); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1426 + * + * with _global_notify_skipped_step_in_lock: + * if _global_notify_skipped_step_in: # <<<<<<<<<<<<<< + * # Check with lock in place (callers should actually have checked + * # before without the lock in place due to performance). + */ + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1426, __pyx_L7_error) + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1429 + * # Check with lock in place (callers should actually have checked + * # before without the lock in place due to performance). + * return # <<<<<<<<<<<<<< + * _global_notify_skipped_step_in = True + * py_db.notify_skipped_step_in_because_of_filters(frame) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1426 + * + * with _global_notify_skipped_step_in_lock: + * if _global_notify_skipped_step_in: # <<<<<<<<<<<<<< + * # Check with lock in place (callers should actually have checked + * # before without the lock in place due to performance). + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1430 + * # before without the lock in place due to performance). + * return + * _global_notify_skipped_step_in = True # <<<<<<<<<<<<<< + * py_db.notify_skipped_step_in_because_of_filters(frame) + * + */ + __Pyx_INCREF(Py_True); + __Pyx_XGOTREF(__pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in); + __Pyx_DECREF_SET(__pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in, ((PyObject*)Py_True)); + __Pyx_GIVEREF(Py_True); + + /* "_pydevd_bundle/pydevd_cython.pyx":1431 + * return + * _global_notify_skipped_step_in = True + * py_db.notify_skipped_step_in_because_of_filters(frame) # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_notify_skipped_step_in_because_o); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1431, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1431, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1425 + * global _global_notify_skipped_step_in + * + * with _global_notify_skipped_step_in_lock: # <<<<<<<<<<<<<< + * if _global_notify_skipped_step_in: + * # Check with lock in place (callers should actually have checked + */ + } + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L12_try_end; + __pyx_L7_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.notify_skipped_step_in_because_of_filters", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_3, &__pyx_t_4) < 0) __PYX_ERR(0, 1425, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyTuple_Pack(3, __pyx_t_1, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1425, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_10 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1425, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_10); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (__pyx_t_9 < 0) __PYX_ERR(0, 1425, __pyx_L9_except_error) + __pyx_t_11 = ((!(__pyx_t_9 != 0)) != 0); + if (__pyx_t_11) { + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ErrRestoreWithState(__pyx_t_1, __pyx_t_3, __pyx_t_4); + __pyx_t_1 = 0; __pyx_t_3 = 0; __pyx_t_4 = 0; + __PYX_ERR(0, 1425, __pyx_L9_except_error) + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + goto __pyx_L8_exception_handled; + } + __pyx_L9_except_error:; + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_ExceptionReset(__pyx_t_6, __pyx_t_7, __pyx_t_8); + goto __pyx_L1_error; + __pyx_L11_try_return:; + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_ExceptionReset(__pyx_t_6, __pyx_t_7, __pyx_t_8); + goto __pyx_L4_return; + __pyx_L8_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_ExceptionReset(__pyx_t_6, __pyx_t_7, __pyx_t_8); + __pyx_L12_try_end:; + } + } + /*finally:*/ { + /*normal exit:*/{ + if (__pyx_t_2) { + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__2, NULL); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1425, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + goto __pyx_L6; + } + __pyx_L4_return: { + __pyx_t_8 = __pyx_r; + __pyx_r = 0; + if (__pyx_t_2) { + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__2, NULL); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1425, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __pyx_r = __pyx_t_8; + __pyx_t_8 = 0; + goto __pyx_L0; + } + __pyx_L6:; + } + goto __pyx_L17; + __pyx_L3_error:; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + goto __pyx_L1_error; + __pyx_L17:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1422 + * + * + * def notify_skipped_step_in_because_of_filters(py_db, frame): # <<<<<<<<<<<<<< + * global _global_notify_skipped_step_in + * + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.notify_skipped_step_in_because_of_filters", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1436 + * cdef class SafeCallWrapper: + * cdef method_object + * def __init__(self, method_object): # <<<<<<<<<<<<<< + * self.method_object = method_object + * def __call__(self, *args): + */ + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_method_object = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_method_object,0}; + PyObject* values[1] = {0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_method_object)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 1436, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 1) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + } + __pyx_v_method_object = values[0]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1436, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.SafeCallWrapper.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper___init__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)__pyx_v_self), __pyx_v_method_object); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper___init__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *__pyx_v_self, PyObject *__pyx_v_method_object) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1437 + * cdef method_object + * def __init__(self, method_object): + * self.method_object = method_object # <<<<<<<<<<<<<< + * def __call__(self, *args): + * #Cannot use 'self' once inside the delegate call since we are borrowing the self reference f_trace field + */ + __Pyx_INCREF(__pyx_v_method_object); + __Pyx_GIVEREF(__pyx_v_method_object); + __Pyx_GOTREF(__pyx_v_self->method_object); + __Pyx_DECREF(__pyx_v_self->method_object); + __pyx_v_self->method_object = __pyx_v_method_object; + + /* "_pydevd_bundle/pydevd_cython.pyx":1436 + * cdef class SafeCallWrapper: + * cdef method_object + * def __init__(self, method_object): # <<<<<<<<<<<<<< + * self.method_object = method_object + * def __call__(self, *args): + */ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1438 + * def __init__(self, method_object): + * self.method_object = method_object + * def __call__(self, *args): # <<<<<<<<<<<<<< + * #Cannot use 'self' once inside the delegate call since we are borrowing the self reference f_trace field + * #in the frame, and that reference might get destroyed by set trace on frame and parents + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_3__call__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_3__call__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_args = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__call__ (wrapper)", 0); + if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__call__", 0))) return NULL; + __Pyx_INCREF(__pyx_args); + __pyx_v_args = __pyx_args; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_2__call__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)__pyx_v_self), __pyx_v_args); + + /* function exit code */ + __Pyx_XDECREF(__pyx_v_args); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_2__call__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *__pyx_v_self, PyObject *__pyx_v_args) { + PyObject *__pyx_v_method_obj; + PyObject *__pyx_v_ret = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__call__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1441 + * #Cannot use 'self' once inside the delegate call since we are borrowing the self reference f_trace field + * #in the frame, and that reference might get destroyed by set trace on frame and parents + * cdef PyObject* method_obj = self.method_object # <<<<<<<<<<<<<< + * Py_INCREF(method_obj) + * ret = (method_obj)(*args) + */ + __pyx_v_method_obj = ((PyObject *)__pyx_v_self->method_object); + + /* "_pydevd_bundle/pydevd_cython.pyx":1442 + * #in the frame, and that reference might get destroyed by set trace on frame and parents + * cdef PyObject* method_obj = self.method_object + * Py_INCREF(method_obj) # <<<<<<<<<<<<<< + * ret = (method_obj)(*args) + * Py_XDECREF (method_obj) + */ + Py_INCREF(((PyObject *)__pyx_v_method_obj)); + + /* "_pydevd_bundle/pydevd_cython.pyx":1443 + * cdef PyObject* method_obj = self.method_object + * Py_INCREF(method_obj) + * ret = (method_obj)(*args) # <<<<<<<<<<<<<< + * Py_XDECREF (method_obj) + * return SafeCallWrapper(ret) if ret is not None else None + */ + __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_v_method_obj), __pyx_v_args, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1443, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_ret = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1444 + * Py_INCREF(method_obj) + * ret = (method_obj)(*args) + * Py_XDECREF (method_obj) # <<<<<<<<<<<<<< + * return SafeCallWrapper(ret) if ret is not None else None + * def get_method_object(self): + */ + Py_XDECREF(__pyx_v_method_obj); + + /* "_pydevd_bundle/pydevd_cython.pyx":1445 + * ret = (method_obj)(*args) + * Py_XDECREF (method_obj) + * return SafeCallWrapper(ret) if ret is not None else None # <<<<<<<<<<<<<< + * def get_method_object(self): + * return self.method_object + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = (__pyx_v_ret != Py_None); + if ((__pyx_t_2 != 0)) { + __pyx_t_3 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper), __pyx_v_ret); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1445, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __pyx_t_3; + __pyx_t_3 = 0; + } else { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1438 + * def __init__(self, method_object): + * self.method_object = method_object + * def __call__(self, *args): # <<<<<<<<<<<<<< + * #Cannot use 'self' once inside the delegate call since we are borrowing the self reference f_trace field + * #in the frame, and that reference might get destroyed by set trace on frame and parents + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.SafeCallWrapper.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_ret); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1446 + * Py_XDECREF (method_obj) + * return SafeCallWrapper(ret) if ret is not None else None + * def get_method_object(self): # <<<<<<<<<<<<<< + * return self.method_object + * # ELSE + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_5get_method_object(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_5get_method_object(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_method_object (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_4get_method_object(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_4get_method_object(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_method_object", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1447 + * return SafeCallWrapper(ret) if ret is not None else None + * def get_method_object(self): + * return self.method_object # <<<<<<<<<<<<<< + * # ELSE + * # ENDIF + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->method_object); + __pyx_r = __pyx_v_self->method_object; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1446 + * Py_XDECREF (method_obj) + * return SafeCallWrapper(ret) if ret is not None else None + * def get_method_object(self): # <<<<<<<<<<<<<< + * return self.method_object + * # ELSE + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_6__reduce_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_6__reduce_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self.method_object,) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_self->method_object); + __Pyx_GIVEREF(__pyx_v_self->method_object); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->method_object); + __pyx_v_state = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self.method_object,) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v__dict = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":7 + * state = (self.method_object,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_2 = (__pyx_v__dict != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict); + __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self.method_object is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self.method_object,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self.method_object is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, None), state + */ + /*else*/ { + __pyx_t_3 = (__pyx_v_self->method_object != Py_None); + __pyx_v_use_setstate = __pyx_t_3; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.method_object is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, None), state + * else: + */ + __pyx_t_3 = (__pyx_v_use_setstate != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":13 + * use_setstate = self.method_object is not None + * if use_setstate: + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_SafeCallWrapper); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_125568891); + __Pyx_GIVEREF(__pyx_int_125568891); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_125568891); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None); + __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state); + __pyx_t_4 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.method_object is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, None), state + * else: + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_SafeCallWrapper__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle_SafeCallWrapper); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_125568891); + __Pyx_GIVEREF(__pyx_int_125568891); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_125568891); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1); + __pyx_t_5 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.SafeCallWrapper.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_SafeCallWrapper__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_8__setstate_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_8__setstate_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_SafeCallWrapper__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_SafeCallWrapper__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_SafeCallWrapper, (type(self), 0x77c077b, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_SafeCallWrapper__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.SafeCallWrapper.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1452 + * + * + * def fix_top_level_trace_and_get_trace_func(py_db, frame): # <<<<<<<<<<<<<< + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef str filename; + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_7fix_top_level_trace_and_get_trace_func(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_7fix_top_level_trace_and_get_trace_func = {"fix_top_level_trace_and_get_trace_func", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_7fix_top_level_trace_and_get_trace_func, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_7fix_top_level_trace_and_get_trace_func(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_py_db = 0; + PyObject *__pyx_v_frame = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("fix_top_level_trace_and_get_trace_func (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_py_db,&__pyx_n_s_frame,0}; + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_py_db)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("fix_top_level_trace_and_get_trace_func", 1, 2, 2, 1); __PYX_ERR(0, 1452, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "fix_top_level_trace_and_get_trace_func") < 0)) __PYX_ERR(0, 1452, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_py_db = values[0]; + __pyx_v_frame = values[1]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("fix_top_level_trace_and_get_trace_func", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1452, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.fix_top_level_trace_and_get_trace_func", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_6fix_top_level_trace_and_get_trace_func(__pyx_self, __pyx_v_py_db, __pyx_v_frame); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_6fix_top_level_trace_and_get_trace_func(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_py_db, PyObject *__pyx_v_frame) { + PyObject *__pyx_v_name = 0; + PyObject *__pyx_v_args = 0; + PyObject *__pyx_v_thread = NULL; + PyObject *__pyx_v_f_unhandled = NULL; + int __pyx_v_force_only_unhandled_tracer; + PyObject *__pyx_v_i = NULL; + PyObject *__pyx_v_j = NULL; + PyObject *__pyx_v_t = NULL; + PyObject *__pyx_v_additional_info = NULL; + PyObject *__pyx_v_top_level_thread_tracer = NULL; + PyObject *__pyx_v_f_trace = NULL; + PyObject *__pyx_v_thread_tracer = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + Py_ssize_t __pyx_t_5; + Py_ssize_t __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + int __pyx_t_8; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + int __pyx_t_15; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("fix_top_level_trace_and_get_trace_func", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1463 + * # where more information is cached (and will also setup the tracing for + * # frames where we should deal with unhandled exceptions). + * thread = None # <<<<<<<<<<<<<< + * # Cache the frame which should be traced to deal with unhandled exceptions. + * # (i.e.: thread entry-points). + */ + __Pyx_INCREF(Py_None); + __pyx_v_thread = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":1467 + * # (i.e.: thread entry-points). + * + * f_unhandled = frame # <<<<<<<<<<<<<< + * # print('called at', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + * force_only_unhandled_tracer = False + */ + __Pyx_INCREF(__pyx_v_frame); + __pyx_v_f_unhandled = __pyx_v_frame; + + /* "_pydevd_bundle/pydevd_cython.pyx":1469 + * f_unhandled = frame + * # print('called at', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + * force_only_unhandled_tracer = False # <<<<<<<<<<<<<< + * while f_unhandled is not None: + * # name = splitext(basename(f_unhandled.f_code.co_filename))[0] + */ + __pyx_v_force_only_unhandled_tracer = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1470 + * # print('called at', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + * force_only_unhandled_tracer = False + * while f_unhandled is not None: # <<<<<<<<<<<<<< + * # name = splitext(basename(f_unhandled.f_code.co_filename))[0] + * + */ + while (1) { + __pyx_t_1 = (__pyx_v_f_unhandled != Py_None); + __pyx_t_2 = (__pyx_t_1 != 0); + if (!__pyx_t_2) break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1473 + * # name = splitext(basename(f_unhandled.f_code.co_filename))[0] + * + * name = f_unhandled.f_code.co_filename # <<<<<<<<<<<<<< + * # basename + * i = name.rfind('/') + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1473, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1473, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (!(likely(PyString_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(0, 1473, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_name, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1475 + * name = f_unhandled.f_code.co_filename + * # basename + * i = name.rfind('/') # <<<<<<<<<<<<<< + * j = name.rfind('\\') + * if j > i: + */ + __pyx_t_4 = __Pyx_CallUnboundCMethod1(&__pyx_umethod_PyString_Type_rfind, __pyx_v_name, __pyx_kp_s__5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1475, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1476 + * # basename + * i = name.rfind('/') + * j = name.rfind('\\') # <<<<<<<<<<<<<< + * if j > i: + * i = j + */ + __pyx_t_4 = __Pyx_CallUnboundCMethod1(&__pyx_umethod_PyString_Type_rfind, __pyx_v_name, __pyx_kp_s__6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1476, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF_SET(__pyx_v_j, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1477 + * i = name.rfind('/') + * j = name.rfind('\\') + * if j > i: # <<<<<<<<<<<<<< + * i = j + * if i >= 0: + */ + __pyx_t_4 = PyObject_RichCompare(__pyx_v_j, __pyx_v_i, Py_GT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1477, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1477, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1478 + * j = name.rfind('\\') + * if j > i: + * i = j # <<<<<<<<<<<<<< + * if i >= 0: + * name = name[i + 1:] + */ + __Pyx_INCREF(__pyx_v_j); + __Pyx_DECREF_SET(__pyx_v_i, __pyx_v_j); + + /* "_pydevd_bundle/pydevd_cython.pyx":1477 + * i = name.rfind('/') + * j = name.rfind('\\') + * if j > i: # <<<<<<<<<<<<<< + * i = j + * if i >= 0: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1479 + * if j > i: + * i = j + * if i >= 0: # <<<<<<<<<<<<<< + * name = name[i + 1:] + * # remove ext + */ + __pyx_t_4 = PyObject_RichCompare(__pyx_v_i, __pyx_int_0, Py_GE); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1479, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1479, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1480 + * i = j + * if i >= 0: + * name = name[i + 1:] # <<<<<<<<<<<<<< + * # remove ext + * i = name.rfind('.') + */ + if (unlikely(__pyx_v_name == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1480, __pyx_L1_error) + } + __pyx_t_4 = __Pyx_PyInt_AddObjC(__pyx_v_i, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1480, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = (__pyx_t_4 == Py_None); + if (__pyx_t_2) { + __pyx_t_5 = 0; + } else { + __pyx_t_6 = __Pyx_PyIndex_AsSsize_t(__pyx_t_4); if (unlikely((__pyx_t_6 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1480, __pyx_L1_error) + __pyx_t_5 = __pyx_t_6; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PySequence_GetSlice(__pyx_v_name, __pyx_t_5, PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1480, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_name, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1479 + * if j > i: + * i = j + * if i >= 0: # <<<<<<<<<<<<<< + * name = name[i + 1:] + * # remove ext + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1482 + * name = name[i + 1:] + * # remove ext + * i = name.rfind('.') # <<<<<<<<<<<<<< + * if i >= 0: + * name = name[:i] + */ + __pyx_t_4 = __Pyx_CallUnboundCMethod1(&__pyx_umethod_PyString_Type_rfind, __pyx_v_name, __pyx_kp_s__7); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1482, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_i, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1483 + * # remove ext + * i = name.rfind('.') + * if i >= 0: # <<<<<<<<<<<<<< + * name = name[:i] + * + */ + __pyx_t_4 = PyObject_RichCompare(__pyx_v_i, __pyx_int_0, Py_GE); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1483, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1483, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1484 + * i = name.rfind('.') + * if i >= 0: + * name = name[:i] # <<<<<<<<<<<<<< + * + * if name == 'threading': + */ + if (unlikely(__pyx_v_name == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1484, __pyx_L1_error) + } + __Pyx_INCREF(__pyx_v_i); + __pyx_t_4 = __pyx_v_i; + __pyx_t_2 = (__pyx_t_4 == Py_None); + if (__pyx_t_2) { + __pyx_t_5 = PY_SSIZE_T_MAX; + } else { + __pyx_t_6 = __Pyx_PyIndex_AsSsize_t(__pyx_t_4); if (unlikely((__pyx_t_6 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1484, __pyx_L1_error) + __pyx_t_5 = __pyx_t_6; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PySequence_GetSlice(__pyx_v_name, 0, __pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1484, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_name, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1483 + * # remove ext + * i = name.rfind('.') + * if i >= 0: # <<<<<<<<<<<<<< + * name = name[:i] + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1486 + * name = name[:i] + * + * if name == 'threading': # <<<<<<<<<<<<<< + * if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'): + * # We need __bootstrap_inner, not __bootstrap. + */ + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_v_name, __pyx_n_s_threading, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1486, __pyx_L1_error) + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1487 + * + * if name == 'threading': + * if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'): # <<<<<<<<<<<<<< + * # We need __bootstrap_inner, not __bootstrap. + * return None, False + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_code); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1487, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_co_name); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1487, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_t_3, __pyx_n_s_bootstrap, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1487, __pyx_L1_error) + if (!__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L10_bool_binop_done; + } + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_t_3, __pyx_n_s_bootstrap_2, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1487, __pyx_L1_error) + __pyx_t_1 = __pyx_t_2; + __pyx_L10_bool_binop_done:; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1489 + * if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'): + * # We need __bootstrap_inner, not __bootstrap. + * return None, False # <<<<<<<<<<<<<< + * + * elif f_unhandled.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'): + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_tuple__8); + __pyx_r = __pyx_tuple__8; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1487 + * + * if name == 'threading': + * if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'): # <<<<<<<<<<<<<< + * # We need __bootstrap_inner, not __bootstrap. + * return None, False + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1491 + * return None, False + * + * elif f_unhandled.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'): # <<<<<<<<<<<<<< + * # Note: be careful not to use threading.currentThread to avoid creating a dummy thread. + * t = f_unhandled.f_locals.get('self') + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1491, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_name); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1491, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_1 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_bootstrap_inner, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 1491, __pyx_L1_error) + if (!__pyx_t_1) { + } else { + __pyx_t_2 = __pyx_t_1; + goto __pyx_L12_bool_binop_done; + } + __pyx_t_1 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_bootstrap_inner_2, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 1491, __pyx_L1_error) + __pyx_t_2 = __pyx_t_1; + __pyx_L12_bool_binop_done:; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1493 + * elif f_unhandled.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'): + * # Note: be careful not to use threading.currentThread to avoid creating a dummy thread. + * t = f_unhandled.f_locals.get('self') # <<<<<<<<<<<<<< + * force_only_unhandled_tracer = True + * if t is not None and isinstance(t, threading.Thread): + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_locals); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1493, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_get); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1493, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_4 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_3, __pyx_n_s_self) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_n_s_self); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1493, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1494 + * # Note: be careful not to use threading.currentThread to avoid creating a dummy thread. + * t = f_unhandled.f_locals.get('self') + * force_only_unhandled_tracer = True # <<<<<<<<<<<<<< + * if t is not None and isinstance(t, threading.Thread): + * thread = t + */ + __pyx_v_force_only_unhandled_tracer = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1495 + * t = f_unhandled.f_locals.get('self') + * force_only_unhandled_tracer = True + * if t is not None and isinstance(t, threading.Thread): # <<<<<<<<<<<<<< + * thread = t + * break + */ + __pyx_t_2 = (__pyx_v_t != Py_None); + __pyx_t_8 = (__pyx_t_2 != 0); + if (__pyx_t_8) { + } else { + __pyx_t_1 = __pyx_t_8; + goto __pyx_L15_bool_binop_done; + } + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_threading); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1495, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_Thread); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1495, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_8 = PyObject_IsInstance(__pyx_v_t, __pyx_t_7); if (unlikely(__pyx_t_8 == ((int)-1))) __PYX_ERR(0, 1495, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_2 = (__pyx_t_8 != 0); + __pyx_t_1 = __pyx_t_2; + __pyx_L15_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1496 + * force_only_unhandled_tracer = True + * if t is not None and isinstance(t, threading.Thread): + * thread = t # <<<<<<<<<<<<<< + * break + * + */ + __Pyx_INCREF(__pyx_v_t); + __Pyx_DECREF_SET(__pyx_v_thread, __pyx_v_t); + + /* "_pydevd_bundle/pydevd_cython.pyx":1497 + * if t is not None and isinstance(t, threading.Thread): + * thread = t + * break # <<<<<<<<<<<<<< + * + * elif name == 'pydev_monkey': + */ + goto __pyx_L4_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1495 + * t = f_unhandled.f_locals.get('self') + * force_only_unhandled_tracer = True + * if t is not None and isinstance(t, threading.Thread): # <<<<<<<<<<<<<< + * thread = t + * break + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1491 + * return None, False + * + * elif f_unhandled.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'): # <<<<<<<<<<<<<< + * # Note: be careful not to use threading.currentThread to avoid creating a dummy thread. + * t = f_unhandled.f_locals.get('self') + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1486 + * name = name[:i] + * + * if name == 'threading': # <<<<<<<<<<<<<< + * if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'): + * # We need __bootstrap_inner, not __bootstrap. + */ + goto __pyx_L8; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1499 + * break + * + * elif name == 'pydev_monkey': # <<<<<<<<<<<<<< + * if f_unhandled.f_code.co_name == '__call__': + * force_only_unhandled_tracer = True + */ + __pyx_t_1 = (__Pyx_PyString_Equals(__pyx_v_name, __pyx_n_s_pydev_monkey, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 1499, __pyx_L1_error) + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1500 + * + * elif name == 'pydev_monkey': + * if f_unhandled.f_code.co_name == '__call__': # <<<<<<<<<<<<<< + * force_only_unhandled_tracer = True + * break + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_code); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1500, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_co_name); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1500, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_call_2, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1500, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1501 + * elif name == 'pydev_monkey': + * if f_unhandled.f_code.co_name == '__call__': + * force_only_unhandled_tracer = True # <<<<<<<<<<<<<< + * break + * + */ + __pyx_v_force_only_unhandled_tracer = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1502 + * if f_unhandled.f_code.co_name == '__call__': + * force_only_unhandled_tracer = True + * break # <<<<<<<<<<<<<< + * + * elif name == 'pydevd': + */ + goto __pyx_L4_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1500 + * + * elif name == 'pydev_monkey': + * if f_unhandled.f_code.co_name == '__call__': # <<<<<<<<<<<<<< + * force_only_unhandled_tracer = True + * break + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1499 + * break + * + * elif name == 'pydev_monkey': # <<<<<<<<<<<<<< + * if f_unhandled.f_code.co_name == '__call__': + * force_only_unhandled_tracer = True + */ + goto __pyx_L8; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1504 + * break + * + * elif name == 'pydevd': # <<<<<<<<<<<<<< + * if f_unhandled.f_code.co_name in ('run', 'main'): + * # We need to get to _exec + */ + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_v_name, __pyx_n_s_pydevd, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1504, __pyx_L1_error) + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1505 + * + * elif name == 'pydevd': + * if f_unhandled.f_code.co_name in ('run', 'main'): # <<<<<<<<<<<<<< + * # We need to get to _exec + * return None, False + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_code); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1505, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_co_name); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1505, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_t_7, __pyx_n_s_run, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1505, __pyx_L1_error) + if (!__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L19_bool_binop_done; + } + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_t_7, __pyx_n_s_main, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1505, __pyx_L1_error) + __pyx_t_1 = __pyx_t_2; + __pyx_L19_bool_binop_done:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1507 + * if f_unhandled.f_code.co_name in ('run', 'main'): + * # We need to get to _exec + * return None, False # <<<<<<<<<<<<<< + * + * if f_unhandled.f_code.co_name == '_exec': + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_tuple__8); + __pyx_r = __pyx_tuple__8; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1505 + * + * elif name == 'pydevd': + * if f_unhandled.f_code.co_name in ('run', 'main'): # <<<<<<<<<<<<<< + * # We need to get to _exec + * return None, False + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1509 + * return None, False + * + * if f_unhandled.f_code.co_name == '_exec': # <<<<<<<<<<<<<< + * force_only_unhandled_tracer = True + * break + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_code); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1509, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_co_name); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1509, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_exec, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1509, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1510 + * + * if f_unhandled.f_code.co_name == '_exec': + * force_only_unhandled_tracer = True # <<<<<<<<<<<<<< + * break + * + */ + __pyx_v_force_only_unhandled_tracer = 1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1511 + * if f_unhandled.f_code.co_name == '_exec': + * force_only_unhandled_tracer = True + * break # <<<<<<<<<<<<<< + * + * elif name == 'pydevd_tracing': + */ + goto __pyx_L4_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1509 + * return None, False + * + * if f_unhandled.f_code.co_name == '_exec': # <<<<<<<<<<<<<< + * force_only_unhandled_tracer = True + * break + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1504 + * break + * + * elif name == 'pydevd': # <<<<<<<<<<<<<< + * if f_unhandled.f_code.co_name in ('run', 'main'): + * # We need to get to _exec + */ + goto __pyx_L8; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1513 + * break + * + * elif name == 'pydevd_tracing': # <<<<<<<<<<<<<< + * return None, False + * + */ + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_v_name, __pyx_n_s_pydevd_tracing, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1513, __pyx_L1_error) + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1514 + * + * elif name == 'pydevd_tracing': + * return None, False # <<<<<<<<<<<<<< + * + * elif f_unhandled.f_back is None: + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_tuple__8); + __pyx_r = __pyx_tuple__8; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1513 + * break + * + * elif name == 'pydevd_tracing': # <<<<<<<<<<<<<< + * return None, False + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1516 + * return None, False + * + * elif f_unhandled.f_back is None: # <<<<<<<<<<<<<< + * break + * + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1516, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = (__pyx_t_4 == Py_None); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1517 + * + * elif f_unhandled.f_back is None: + * break # <<<<<<<<<<<<<< + * + * f_unhandled = f_unhandled.f_back + */ + goto __pyx_L4_break; + + /* "_pydevd_bundle/pydevd_cython.pyx":1516 + * return None, False + * + * elif f_unhandled.f_back is None: # <<<<<<<<<<<<<< + * break + * + */ + } + __pyx_L8:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1519 + * break + * + * f_unhandled = f_unhandled.f_back # <<<<<<<<<<<<<< + * + * if thread is None: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1519, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_f_unhandled, __pyx_t_4); + __pyx_t_4 = 0; + } + __pyx_L4_break:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1521 + * f_unhandled = f_unhandled.f_back + * + * if thread is None: # <<<<<<<<<<<<<< + * # Important: don't call threadingCurrentThread if we're in the threading module + * # to avoid creating dummy threads. + */ + __pyx_t_2 = (__pyx_v_thread == Py_None); + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1524 + * # Important: don't call threadingCurrentThread if we're in the threading module + * # to avoid creating dummy threads. + * if py_db.threading_get_ident is not None: # <<<<<<<<<<<<<< + * thread = py_db.threading_active.get(py_db.threading_get_ident()) + * if thread is None: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_threading_get_ident); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1524, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = (__pyx_t_4 != Py_None); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1525 + * # to avoid creating dummy threads. + * if py_db.threading_get_ident is not None: + * thread = py_db.threading_active.get(py_db.threading_get_ident()) # <<<<<<<<<<<<<< + * if thread is None: + * return None, False + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_threading_active); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1525, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_get); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1525, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_threading_get_ident); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1525, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_10)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_10); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + } + } + __pyx_t_7 = (__pyx_t_10) ? __Pyx_PyObject_CallOneArg(__pyx_t_9, __pyx_t_10) : __Pyx_PyObject_CallNoArg(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1525, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_4 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_9, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1525, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF_SET(__pyx_v_thread, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1526 + * if py_db.threading_get_ident is not None: + * thread = py_db.threading_active.get(py_db.threading_get_ident()) + * if thread is None: # <<<<<<<<<<<<<< + * return None, False + * else: + */ + __pyx_t_2 = (__pyx_v_thread == Py_None); + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1527 + * thread = py_db.threading_active.get(py_db.threading_get_ident()) + * if thread is None: + * return None, False # <<<<<<<<<<<<<< + * else: + * # Jython does not have threading.get_ident(). + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_tuple__8); + __pyx_r = __pyx_tuple__8; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1526 + * if py_db.threading_get_ident is not None: + * thread = py_db.threading_active.get(py_db.threading_get_ident()) + * if thread is None: # <<<<<<<<<<<<<< + * return None, False + * else: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1524 + * # Important: don't call threadingCurrentThread if we're in the threading module + * # to avoid creating dummy threads. + * if py_db.threading_get_ident is not None: # <<<<<<<<<<<<<< + * thread = py_db.threading_active.get(py_db.threading_get_ident()) + * if thread is None: + */ + goto __pyx_L23; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1530 + * else: + * # Jython does not have threading.get_ident(). + * thread = py_db.threading_current_thread() # <<<<<<<<<<<<<< + * + * if getattr(thread, 'pydev_do_not_trace', None): + */ + /*else*/ { + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_threading_current_thread); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1530, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1530, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF_SET(__pyx_v_thread, __pyx_t_4); + __pyx_t_4 = 0; + } + __pyx_L23:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1521 + * f_unhandled = f_unhandled.f_back + * + * if thread is None: # <<<<<<<<<<<<<< + * # Important: don't call threadingCurrentThread if we're in the threading module + * # to avoid creating dummy threads. + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1532 + * thread = py_db.threading_current_thread() + * + * if getattr(thread, 'pydev_do_not_trace', None): # <<<<<<<<<<<<<< + * py_db.disable_tracing() + * return None, False + */ + __pyx_t_4 = __Pyx_GetAttr3(__pyx_v_thread, __pyx_n_s_pydev_do_not_trace, Py_None); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1532, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 1532, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1533 + * + * if getattr(thread, 'pydev_do_not_trace', None): + * py_db.disable_tracing() # <<<<<<<<<<<<<< + * return None, False + * + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_disable_tracing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1533, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1533, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1534 + * if getattr(thread, 'pydev_do_not_trace', None): + * py_db.disable_tracing() + * return None, False # <<<<<<<<<<<<<< + * + * try: + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_tuple__8); + __pyx_r = __pyx_tuple__8; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1532 + * thread = py_db.threading_current_thread() + * + * if getattr(thread, 'pydev_do_not_trace', None): # <<<<<<<<<<<<<< + * py_db.disable_tracing() + * return None, False + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1536 + * return None, False + * + * try: # <<<<<<<<<<<<<< + * additional_info = thread.additional_info + * if additional_info is None: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_11, &__pyx_t_12, &__pyx_t_13); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_13); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1537 + * + * try: + * additional_info = thread.additional_info # <<<<<<<<<<<<<< + * if additional_info is None: + * raise AttributeError() + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_thread, __pyx_n_s_additional_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1537, __pyx_L26_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_additional_info = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1538 + * try: + * additional_info = thread.additional_info + * if additional_info is None: # <<<<<<<<<<<<<< + * raise AttributeError() + * except: + */ + __pyx_t_1 = (__pyx_v_additional_info == Py_None); + __pyx_t_2 = (__pyx_t_1 != 0); + if (unlikely(__pyx_t_2)) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1539 + * additional_info = thread.additional_info + * if additional_info is None: + * raise AttributeError() # <<<<<<<<<<<<<< + * except: + * additional_info = py_db.set_additional_thread_info(thread) + */ + __pyx_t_4 = __Pyx_PyObject_CallNoArg(__pyx_builtin_AttributeError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1539, __pyx_L26_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(0, 1539, __pyx_L26_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1538 + * try: + * additional_info = thread.additional_info + * if additional_info is None: # <<<<<<<<<<<<<< + * raise AttributeError() + * except: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1536 + * return None, False + * + * try: # <<<<<<<<<<<<<< + * additional_info = thread.additional_info + * if additional_info is None: + */ + } + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + goto __pyx_L31_try_end; + __pyx_L26_error:; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1540 + * if additional_info is None: + * raise AttributeError() + * except: # <<<<<<<<<<<<<< + * additional_info = py_db.set_additional_thread_info(thread) + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.fix_top_level_trace_and_get_trace_func", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_4, &__pyx_t_3, &__pyx_t_7) < 0) __PYX_ERR(0, 1540, __pyx_L28_except_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GOTREF(__pyx_t_7); + + /* "_pydevd_bundle/pydevd_cython.pyx":1541 + * raise AttributeError() + * except: + * additional_info = py_db.set_additional_thread_info(thread) # <<<<<<<<<<<<<< + * + * # print('enter thread tracer', thread, get_current_thread_id(thread)) + */ + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_set_additional_thread_info); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1541, __pyx_L28_except_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_14 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_10))) { + __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_10); + if (likely(__pyx_t_14)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10); + __Pyx_INCREF(__pyx_t_14); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_10, function); + } + } + __pyx_t_9 = (__pyx_t_14) ? __Pyx_PyObject_Call2Args(__pyx_t_10, __pyx_t_14, __pyx_v_thread) : __Pyx_PyObject_CallOneArg(__pyx_t_10, __pyx_v_thread); + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1541, __pyx_L28_except_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF_SET(__pyx_v_additional_info, __pyx_t_9); + __pyx_t_9 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L27_exception_handled; + } + __pyx_L28_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1536 + * return None, False + * + * try: # <<<<<<<<<<<<<< + * additional_info = thread.additional_info + * if additional_info is None: + */ + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_13); + __Pyx_ExceptionReset(__pyx_t_11, __pyx_t_12, __pyx_t_13); + goto __pyx_L1_error; + __pyx_L27_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_13); + __Pyx_ExceptionReset(__pyx_t_11, __pyx_t_12, __pyx_t_13); + __pyx_L31_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1544 + * + * # print('enter thread tracer', thread, get_current_thread_id(thread)) + * args = (py_db, thread, additional_info, global_cache_skips, global_cache_frame_skips) # <<<<<<<<<<<<<< + * + * if f_unhandled is not None: + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_global_cache_skips); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1544, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_global_cache_frame_skips); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1544, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1544, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_py_db); + __Pyx_GIVEREF(__pyx_v_py_db); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_py_db); + __Pyx_INCREF(__pyx_v_thread); + __Pyx_GIVEREF(__pyx_v_thread); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_thread); + __Pyx_INCREF(__pyx_v_additional_info); + __Pyx_GIVEREF(__pyx_v_additional_info); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_additional_info); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_4, 4, __pyx_t_3); + __pyx_t_7 = 0; + __pyx_t_3 = 0; + __pyx_v_args = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1546 + * args = (py_db, thread, additional_info, global_cache_skips, global_cache_frame_skips) + * + * if f_unhandled is not None: # <<<<<<<<<<<<<< + * if f_unhandled.f_back is None and not force_only_unhandled_tracer: + * # Happens when we attach to a running program (cannot reuse instance because it's mutable). + */ + __pyx_t_2 = (__pyx_v_f_unhandled != Py_None); + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1547 + * + * if f_unhandled is not None: + * if f_unhandled.f_back is None and not force_only_unhandled_tracer: # <<<<<<<<<<<<<< + * # Happens when we attach to a running program (cannot reuse instance because it's mutable). + * top_level_thread_tracer = TopLevelThreadTracerNoBackFrame(ThreadTracer(args), args) + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1547, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = (__pyx_t_4 == Py_None); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_8 = (__pyx_t_2 != 0); + if (__pyx_t_8) { + } else { + __pyx_t_1 = __pyx_t_8; + goto __pyx_L37_bool_binop_done; + } + __pyx_t_8 = ((!(__pyx_v_force_only_unhandled_tracer != 0)) != 0); + __pyx_t_1 = __pyx_t_8; + __pyx_L37_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1549 + * if f_unhandled.f_back is None and not force_only_unhandled_tracer: + * # Happens when we attach to a running program (cannot reuse instance because it's mutable). + * top_level_thread_tracer = TopLevelThreadTracerNoBackFrame(ThreadTracer(args), args) # <<<<<<<<<<<<<< + * additional_info.top_level_thread_tracer_no_back_frames.append(top_level_thread_tracer) # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). + * else: + */ + __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_ThreadTracer), __pyx_v_args); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1549, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1549, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); + __Pyx_INCREF(__pyx_v_args); + __Pyx_GIVEREF(__pyx_v_args); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_args); + __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame), __pyx_t_3, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1549, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_top_level_thread_tracer = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1550 + * # Happens when we attach to a running program (cannot reuse instance because it's mutable). + * top_level_thread_tracer = TopLevelThreadTracerNoBackFrame(ThreadTracer(args), args) + * additional_info.top_level_thread_tracer_no_back_frames.append(top_level_thread_tracer) # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). # <<<<<<<<<<<<<< + * else: + * top_level_thread_tracer = additional_info.top_level_thread_tracer_unhandled + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_additional_info, __pyx_n_s_top_level_thread_tracer_no_back); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1550, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_15 = __Pyx_PyObject_Append(__pyx_t_4, __pyx_v_top_level_thread_tracer); if (unlikely(__pyx_t_15 == ((int)-1))) __PYX_ERR(0, 1550, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1547 + * + * if f_unhandled is not None: + * if f_unhandled.f_back is None and not force_only_unhandled_tracer: # <<<<<<<<<<<<<< + * # Happens when we attach to a running program (cannot reuse instance because it's mutable). + * top_level_thread_tracer = TopLevelThreadTracerNoBackFrame(ThreadTracer(args), args) + */ + goto __pyx_L36; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1552 + * additional_info.top_level_thread_tracer_no_back_frames.append(top_level_thread_tracer) # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). + * else: + * top_level_thread_tracer = additional_info.top_level_thread_tracer_unhandled # <<<<<<<<<<<<<< + * if top_level_thread_tracer is None: + * # Stop in some internal place to report about unhandled exceptions + */ + /*else*/ { + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_additional_info, __pyx_n_s_top_level_thread_tracer_unhandle); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1552, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_top_level_thread_tracer = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1553 + * else: + * top_level_thread_tracer = additional_info.top_level_thread_tracer_unhandled + * if top_level_thread_tracer is None: # <<<<<<<<<<<<<< + * # Stop in some internal place to report about unhandled exceptions + * top_level_thread_tracer = TopLevelThreadTracerOnlyUnhandledExceptions(args) + */ + __pyx_t_1 = (__pyx_v_top_level_thread_tracer == Py_None); + __pyx_t_8 = (__pyx_t_1 != 0); + if (__pyx_t_8) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1555 + * if top_level_thread_tracer is None: + * # Stop in some internal place to report about unhandled exceptions + * top_level_thread_tracer = TopLevelThreadTracerOnlyUnhandledExceptions(args) # <<<<<<<<<<<<<< + * additional_info.top_level_thread_tracer_unhandled = top_level_thread_tracer # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). + * + */ + __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions), __pyx_v_args); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1555, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_top_level_thread_tracer, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1556 + * # Stop in some internal place to report about unhandled exceptions + * top_level_thread_tracer = TopLevelThreadTracerOnlyUnhandledExceptions(args) + * additional_info.top_level_thread_tracer_unhandled = top_level_thread_tracer # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). # <<<<<<<<<<<<<< + * + * # print(' --> found to trace unhandled', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + */ + if (__Pyx_PyObject_SetAttrStr(__pyx_v_additional_info, __pyx_n_s_top_level_thread_tracer_unhandle, __pyx_v_top_level_thread_tracer) < 0) __PYX_ERR(0, 1556, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1553 + * else: + * top_level_thread_tracer = additional_info.top_level_thread_tracer_unhandled + * if top_level_thread_tracer is None: # <<<<<<<<<<<<<< + * # Stop in some internal place to report about unhandled exceptions + * top_level_thread_tracer = TopLevelThreadTracerOnlyUnhandledExceptions(args) + */ + } + } + __pyx_L36:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1559 + * + * # print(' --> found to trace unhandled', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + * f_trace = top_level_thread_tracer.get_trace_dispatch_func() # <<<<<<<<<<<<<< + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * f_trace = SafeCallWrapper(f_trace) + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_top_level_thread_tracer, __pyx_n_s_get_trace_dispatch_func); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1559, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1559, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_f_trace = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1561 + * f_trace = top_level_thread_tracer.get_trace_dispatch_func() + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * f_trace = SafeCallWrapper(f_trace) # <<<<<<<<<<<<<< + * # ENDIF + * f_unhandled.f_trace = f_trace + */ + __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper), __pyx_v_f_trace); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1561, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_f_trace, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1563 + * f_trace = SafeCallWrapper(f_trace) + * # ENDIF + * f_unhandled.f_trace = f_trace # <<<<<<<<<<<<<< + * + * if frame is f_unhandled: + */ + if (__Pyx_PyObject_SetAttrStr(__pyx_v_f_unhandled, __pyx_n_s_f_trace, __pyx_v_f_trace) < 0) __PYX_ERR(0, 1563, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1565 + * f_unhandled.f_trace = f_trace + * + * if frame is f_unhandled: # <<<<<<<<<<<<<< + * return f_trace, False + * + */ + __pyx_t_8 = (__pyx_v_frame == __pyx_v_f_unhandled); + __pyx_t_1 = (__pyx_t_8 != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1566 + * + * if frame is f_unhandled: + * return f_trace, False # <<<<<<<<<<<<<< + * + * thread_tracer = additional_info.thread_tracer + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1566, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_f_trace); + __Pyx_GIVEREF(__pyx_v_f_trace); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_f_trace); + __Pyx_INCREF(Py_False); + __Pyx_GIVEREF(Py_False); + PyTuple_SET_ITEM(__pyx_t_4, 1, Py_False); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1565 + * f_unhandled.f_trace = f_trace + * + * if frame is f_unhandled: # <<<<<<<<<<<<<< + * return f_trace, False + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1546 + * args = (py_db, thread, additional_info, global_cache_skips, global_cache_frame_skips) + * + * if f_unhandled is not None: # <<<<<<<<<<<<<< + * if f_unhandled.f_back is None and not force_only_unhandled_tracer: + * # Happens when we attach to a running program (cannot reuse instance because it's mutable). + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1568 + * return f_trace, False + * + * thread_tracer = additional_info.thread_tracer # <<<<<<<<<<<<<< + * if thread_tracer is None or thread_tracer._args[0] is not py_db: + * thread_tracer = ThreadTracer(args) + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_additional_info, __pyx_n_s_thread_tracer); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1568, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_thread_tracer = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1569 + * + * thread_tracer = additional_info.thread_tracer + * if thread_tracer is None or thread_tracer._args[0] is not py_db: # <<<<<<<<<<<<<< + * thread_tracer = ThreadTracer(args) + * additional_info.thread_tracer = thread_tracer + */ + __pyx_t_8 = (__pyx_v_thread_tracer == Py_None); + __pyx_t_2 = (__pyx_t_8 != 0); + if (!__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L42_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_thread_tracer, __pyx_n_s_args_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1569, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1569, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = (__pyx_t_3 != __pyx_v_py_db); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_8 = (__pyx_t_2 != 0); + __pyx_t_1 = __pyx_t_8; + __pyx_L42_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1570 + * thread_tracer = additional_info.thread_tracer + * if thread_tracer is None or thread_tracer._args[0] is not py_db: + * thread_tracer = ThreadTracer(args) # <<<<<<<<<<<<<< + * additional_info.thread_tracer = thread_tracer + * + */ + __pyx_t_3 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_ThreadTracer), __pyx_v_args); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1570, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF_SET(__pyx_v_thread_tracer, __pyx_t_3); + __pyx_t_3 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1571 + * if thread_tracer is None or thread_tracer._args[0] is not py_db: + * thread_tracer = ThreadTracer(args) + * additional_info.thread_tracer = thread_tracer # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + if (__Pyx_PyObject_SetAttrStr(__pyx_v_additional_info, __pyx_n_s_thread_tracer, __pyx_v_thread_tracer) < 0) __PYX_ERR(0, 1571, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1569 + * + * thread_tracer = additional_info.thread_tracer + * if thread_tracer is None or thread_tracer._args[0] is not py_db: # <<<<<<<<<<<<<< + * thread_tracer = ThreadTracer(args) + * additional_info.thread_tracer = thread_tracer + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1574 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * return SafeCallWrapper(thread_tracer), True # <<<<<<<<<<<<<< + * # ELSE + * # return thread_tracer, True + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_3 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper), __pyx_v_thread_tracer); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1574, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1574, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3); + __Pyx_INCREF(Py_True); + __Pyx_GIVEREF(Py_True); + PyTuple_SET_ITEM(__pyx_t_4, 1, Py_True); + __pyx_t_3 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1452 + * + * + * def fix_top_level_trace_and_get_trace_func(py_db, frame): # <<<<<<<<<<<<<< + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef str filename; + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_XDECREF(__pyx_t_14); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.fix_top_level_trace_and_get_trace_func", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_name); + __Pyx_XDECREF(__pyx_v_args); + __Pyx_XDECREF(__pyx_v_thread); + __Pyx_XDECREF(__pyx_v_f_unhandled); + __Pyx_XDECREF(__pyx_v_i); + __Pyx_XDECREF(__pyx_v_j); + __Pyx_XDECREF(__pyx_v_t); + __Pyx_XDECREF(__pyx_v_additional_info); + __Pyx_XDECREF(__pyx_v_top_level_thread_tracer); + __Pyx_XDECREF(__pyx_v_f_trace); + __Pyx_XDECREF(__pyx_v_thread_tracer); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1580 + * + * + * def trace_dispatch(py_db, frame, event, arg): # <<<<<<<<<<<<<< + * thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + * if thread_trace_func is None: + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9trace_dispatch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_9trace_dispatch = {"trace_dispatch", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9trace_dispatch, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_9trace_dispatch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_py_db = 0; + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_event = 0; + PyObject *__pyx_v_arg = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("trace_dispatch (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_py_db,&__pyx_n_s_frame,&__pyx_n_s_event,&__pyx_n_s_arg,0}; + PyObject* values[4] = {0,0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + CYTHON_FALLTHROUGH; + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_py_db)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_dispatch", 1, 4, 4, 1); __PYX_ERR(0, 1580, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_dispatch", 1, 4, 4, 2); __PYX_ERR(0, 1580, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 3: + if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arg)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_dispatch", 1, 4, 4, 3); __PYX_ERR(0, 1580, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "trace_dispatch") < 0)) __PYX_ERR(0, 1580, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 4) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + } + __pyx_v_py_db = values[0]; + __pyx_v_frame = values[1]; + __pyx_v_event = values[2]; + __pyx_v_arg = values[3]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("trace_dispatch", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1580, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_8trace_dispatch(__pyx_self, __pyx_v_py_db, __pyx_v_frame, __pyx_v_event, __pyx_v_arg); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_8trace_dispatch(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_py_db, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + PyObject *__pyx_v_thread_trace_func = NULL; + PyObject *__pyx_v_apply_to_settrace = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *(*__pyx_t_6)(PyObject *); + int __pyx_t_7; + int __pyx_t_8; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("trace_dispatch", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1581 + * + * def trace_dispatch(py_db, frame, event, arg): + * thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) # <<<<<<<<<<<<<< + * if thread_trace_func is None: + * return None if event == 'call' else NO_FTRACE + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_fix_top_level_trace_and_get_trac); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1581, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = NULL; + __pyx_t_4 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + __pyx_t_4 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_2)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_py_db, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_4, 2+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1581, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) { + PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_py_db, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_4, 2+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1581, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_5 = PyTuple_New(2+__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1581, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_py_db); + __Pyx_GIVEREF(__pyx_v_py_db); + PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_4, __pyx_v_py_db); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_4, __pyx_v_frame); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1581, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 1581, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_2 = PyList_GET_ITEM(sequence, 0); + __pyx_t_5 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_5); + #else + __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1581, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1581, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_3 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1581, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_6 = Py_TYPE(__pyx_t_3)->tp_iternext; + index = 0; __pyx_t_2 = __pyx_t_6(__pyx_t_3); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed; + __Pyx_GOTREF(__pyx_t_2); + index = 1; __pyx_t_5 = __pyx_t_6(__pyx_t_3); if (unlikely(!__pyx_t_5)) goto __pyx_L3_unpacking_failed; + __Pyx_GOTREF(__pyx_t_5); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_3), 2) < 0) __PYX_ERR(0, 1581, __pyx_L1_error) + __pyx_t_6 = NULL; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L4_unpacking_done; + __pyx_L3_unpacking_failed:; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 1581, __pyx_L1_error) + __pyx_L4_unpacking_done:; + } + __pyx_v_thread_trace_func = __pyx_t_2; + __pyx_t_2 = 0; + __pyx_v_apply_to_settrace = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1582 + * def trace_dispatch(py_db, frame, event, arg): + * thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + * if thread_trace_func is None: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * if apply_to_settrace: + */ + __pyx_t_7 = (__pyx_v_thread_trace_func == Py_None); + __pyx_t_8 = (__pyx_t_7 != 0); + if (__pyx_t_8) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1583 + * thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + * if thread_trace_func is None: + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * if apply_to_settrace: + * py_db.enable_tracing(thread_trace_func) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_8 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_8 < 0)) __PYX_ERR(0, 1583, __pyx_L1_error) + if (__pyx_t_8) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1583, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = __pyx_t_5; + __pyx_t_5 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1582 + * def trace_dispatch(py_db, frame, event, arg): + * thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + * if thread_trace_func is None: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * if apply_to_settrace: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1584 + * if thread_trace_func is None: + * return None if event == 'call' else NO_FTRACE + * if apply_to_settrace: # <<<<<<<<<<<<<< + * py_db.enable_tracing(thread_trace_func) + * return thread_trace_func(frame, event, arg) + */ + __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_v_apply_to_settrace); if (unlikely(__pyx_t_8 < 0)) __PYX_ERR(0, 1584, __pyx_L1_error) + if (__pyx_t_8) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1585 + * return None if event == 'call' else NO_FTRACE + * if apply_to_settrace: + * py_db.enable_tracing(thread_trace_func) # <<<<<<<<<<<<<< + * return thread_trace_func(frame, event, arg) + * + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_enable_tracing); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1585, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_2, __pyx_v_thread_trace_func) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_thread_trace_func); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1585, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1584 + * if thread_trace_func is None: + * return None if event == 'call' else NO_FTRACE + * if apply_to_settrace: # <<<<<<<<<<<<<< + * py_db.enable_tracing(thread_trace_func) + * return thread_trace_func(frame, event, arg) + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1586 + * if apply_to_settrace: + * py_db.enable_tracing(thread_trace_func) + * return thread_trace_func(frame, event, arg) # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_thread_trace_func); + __pyx_t_5 = __pyx_v_thread_trace_func; __pyx_t_2 = NULL; + __pyx_t_4 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + __pyx_t_4 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_5)) { + PyObject *__pyx_temp[4] = {__pyx_t_2, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_4, 3+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1586, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) { + PyObject *__pyx_temp[4] = {__pyx_t_2, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_4, 3+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1586, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_3 = PyTuple_New(3+__pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1586, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_2) { + __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); __pyx_t_2 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_4, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_4, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_3, 2+__pyx_t_4, __pyx_v_arg); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1586, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1580 + * + * + * def trace_dispatch(py_db, frame, event, arg): # <<<<<<<<<<<<<< + * thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + * if thread_trace_func is None: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_thread_trace_func); + __Pyx_XDECREF(__pyx_v_apply_to_settrace); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1592 + * cdef class TopLevelThreadTracerOnlyUnhandledExceptions: + * cdef public tuple _args; + * def __init__(self, tuple args): # <<<<<<<<<<<<<< + * self._args = args + * # ELSE + */ + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_args = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_args,0}; + PyObject* values[1] = {0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_args)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 1592, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 1) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + } + __pyx_v_args = ((PyObject*)values[0]); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1592, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerOnlyUnhandledExceptions.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_args), (&PyTuple_Type), 1, "args", 1))) __PYX_ERR(0, 1592, __pyx_L1_error) + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions___init__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v_self), __pyx_v_args); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions___init__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v_self, PyObject *__pyx_v_args) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1593 + * cdef public tuple _args; + * def __init__(self, tuple args): + * self._args = args # <<<<<<<<<<<<<< + * # ELSE + * # class TopLevelThreadTracerOnlyUnhandledExceptions(object): + */ + __Pyx_INCREF(__pyx_v_args); + __Pyx_GIVEREF(__pyx_v_args); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = __pyx_v_args; + + /* "_pydevd_bundle/pydevd_cython.pyx":1592 + * cdef class TopLevelThreadTracerOnlyUnhandledExceptions: + * cdef public tuple _args; + * def __init__(self, tuple args): # <<<<<<<<<<<<<< + * self._args = args + * # ELSE + */ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1601 + * # ENDIF + * + * def trace_unhandled_exceptions(self, frame, event, arg): # <<<<<<<<<<<<<< + * # Note that we ignore the frame as this tracing method should only be put in topmost frames already. + * # print('trace_unhandled_exceptions', event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_3trace_unhandled_exceptions(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_3trace_unhandled_exceptions(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + CYTHON_UNUSED PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_event = 0; + PyObject *__pyx_v_arg = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("trace_unhandled_exceptions (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_frame,&__pyx_n_s_event,&__pyx_n_s_arg,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_unhandled_exceptions", 1, 3, 3, 1); __PYX_ERR(0, 1601, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arg)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_unhandled_exceptions", 1, 3, 3, 2); __PYX_ERR(0, 1601, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "trace_unhandled_exceptions") < 0)) __PYX_ERR(0, 1601, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_frame = values[0]; + __pyx_v_event = values[1]; + __pyx_v_arg = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("trace_unhandled_exceptions", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1601, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerOnlyUnhandledExceptions.trace_unhandled_exceptions", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_2trace_unhandled_exceptions(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v_self), __pyx_v_frame, __pyx_v_event, __pyx_v_arg); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_2trace_unhandled_exceptions(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + PyObject *__pyx_v_py_db = NULL; + PyObject *__pyx_v_t = NULL; + PyObject *__pyx_v_additional_info = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + int __pyx_t_8; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("trace_unhandled_exceptions", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1604 + * # Note that we ignore the frame as this tracing method should only be put in topmost frames already. + * # print('trace_unhandled_exceptions', event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno) + * if event == 'exception' and arg is not None: # <<<<<<<<<<<<<< + * py_db, t, additional_info = self._args[0:3] + * if arg is not None: + */ + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_exception, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1604, __pyx_L1_error) + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_2 = (__pyx_v_arg != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + __pyx_t_1 = __pyx_t_3; + __pyx_L4_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1605 + * # print('trace_unhandled_exceptions', event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno) + * if event == 'exception' and arg is not None: + * py_db, t, additional_info = self._args[0:3] # <<<<<<<<<<<<<< + * if arg is not None: + * if not additional_info.suspended_at_unhandled: + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1605, __pyx_L1_error) + } + __pyx_t_4 = __Pyx_PyTuple_GetSlice(__pyx_v_self->_args, 0, 3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1605, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if (1) { + PyObject* sequence = __pyx_t_4; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 3)) { + if (size > 3) __Pyx_RaiseTooManyValuesError(3); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 1605, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(__pyx_t_7); + #else + __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1605, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1605, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1605, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + #endif + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } + __pyx_v_py_db = __pyx_t_5; + __pyx_t_5 = 0; + __pyx_v_t = __pyx_t_6; + __pyx_t_6 = 0; + __pyx_v_additional_info = __pyx_t_7; + __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1606 + * if event == 'exception' and arg is not None: + * py_db, t, additional_info = self._args[0:3] + * if arg is not None: # <<<<<<<<<<<<<< + * if not additional_info.suspended_at_unhandled: + * additional_info.suspended_at_unhandled = True + */ + __pyx_t_1 = (__pyx_v_arg != Py_None); + __pyx_t_3 = (__pyx_t_1 != 0); + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1607 + * py_db, t, additional_info = self._args[0:3] + * if arg is not None: + * if not additional_info.suspended_at_unhandled: # <<<<<<<<<<<<<< + * additional_info.suspended_at_unhandled = True + * + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_additional_info, __pyx_n_s_suspended_at_unhandled); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1607, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 1607, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_1 = ((!__pyx_t_3) != 0); + if (__pyx_t_1) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1608 + * if arg is not None: + * if not additional_info.suspended_at_unhandled: + * additional_info.suspended_at_unhandled = True # <<<<<<<<<<<<<< + * + * py_db.stop_on_unhandled_exception(py_db, t, additional_info, arg) + */ + if (__Pyx_PyObject_SetAttrStr(__pyx_v_additional_info, __pyx_n_s_suspended_at_unhandled, Py_True) < 0) __PYX_ERR(0, 1608, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1610 + * additional_info.suspended_at_unhandled = True + * + * py_db.stop_on_unhandled_exception(py_db, t, additional_info, arg) # <<<<<<<<<<<<<< + * + * # No need to reset frame.f_trace to keep the same trace function. + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_stop_on_unhandled_exception); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1610, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_6 = NULL; + __pyx_t_8 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + __pyx_t_8 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_7)) { + PyObject *__pyx_temp[5] = {__pyx_t_6, __pyx_v_py_db, __pyx_v_t, __pyx_v_additional_info, __pyx_v_arg}; + __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_8, 4+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1610, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) { + PyObject *__pyx_temp[5] = {__pyx_t_6, __pyx_v_py_db, __pyx_v_t, __pyx_v_additional_info, __pyx_v_arg}; + __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_8, 4+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1610, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + { + __pyx_t_5 = PyTuple_New(4+__pyx_t_8); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1610, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (__pyx_t_6) { + __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_6); __pyx_t_6 = NULL; + } + __Pyx_INCREF(__pyx_v_py_db); + __Pyx_GIVEREF(__pyx_v_py_db); + PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_8, __pyx_v_py_db); + __Pyx_INCREF(__pyx_v_t); + __Pyx_GIVEREF(__pyx_v_t); + PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_8, __pyx_v_t); + __Pyx_INCREF(__pyx_v_additional_info); + __Pyx_GIVEREF(__pyx_v_additional_info); + PyTuple_SET_ITEM(__pyx_t_5, 2+__pyx_t_8, __pyx_v_additional_info); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_5, 3+__pyx_t_8, __pyx_v_arg); + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1610, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1607 + * py_db, t, additional_info = self._args[0:3] + * if arg is not None: + * if not additional_info.suspended_at_unhandled: # <<<<<<<<<<<<<< + * additional_info.suspended_at_unhandled = True + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1606 + * if event == 'exception' and arg is not None: + * py_db, t, additional_info = self._args[0:3] + * if arg is not None: # <<<<<<<<<<<<<< + * if not additional_info.suspended_at_unhandled: + * additional_info.suspended_at_unhandled = True + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1604 + * # Note that we ignore the frame as this tracing method should only be put in topmost frames already. + * # print('trace_unhandled_exceptions', event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno) + * if event == 'exception' and arg is not None: # <<<<<<<<<<<<<< + * py_db, t, additional_info = self._args[0:3] + * if arg is not None: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1613 + * + * # No need to reset frame.f_trace to keep the same trace function. + * return self.trace_unhandled_exceptions # <<<<<<<<<<<<<< + * + * def get_trace_dispatch_func(self): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_unhandled_exceptions); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1613, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1601 + * # ENDIF + * + * def trace_unhandled_exceptions(self, frame, event, arg): # <<<<<<<<<<<<<< + * # Note that we ignore the frame as this tracing method should only be put in topmost frames already. + * # print('trace_unhandled_exceptions', event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno) + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerOnlyUnhandledExceptions.trace_unhandled_exceptions", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_py_db); + __Pyx_XDECREF(__pyx_v_t); + __Pyx_XDECREF(__pyx_v_additional_info); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1615 + * return self.trace_unhandled_exceptions + * + * def get_trace_dispatch_func(self): # <<<<<<<<<<<<<< + * return self.trace_unhandled_exceptions + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5get_trace_dispatch_func(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5get_trace_dispatch_func(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_trace_dispatch_func (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_4get_trace_dispatch_func(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_4get_trace_dispatch_func(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_trace_dispatch_func", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1616 + * + * def get_trace_dispatch_func(self): + * return self.trace_unhandled_exceptions # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_unhandled_exceptions); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1616, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1615 + * return self.trace_unhandled_exceptions + * + * def get_trace_dispatch_func(self): # <<<<<<<<<<<<<< + * return self.trace_unhandled_exceptions + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerOnlyUnhandledExceptions.get_trace_dispatch_func", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1591 + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class TopLevelThreadTracerOnlyUnhandledExceptions: + * cdef public tuple _args; # <<<<<<<<<<<<<< + * def __init__(self, tuple args): + * self._args = args + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->_args); + __pyx_r = __pyx_v_self->_args; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyTuple_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 1591, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerOnlyUnhandledExceptions._args.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_6__reduce_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_6__reduce_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self._args,) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->_args); + __pyx_v_state = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self._args,) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v__dict = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":7 + * state = (self._args,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_2 = (__pyx_v__dict != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict); + __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self._args is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self._args,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self._args is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, None), state + */ + /*else*/ { + __pyx_t_3 = (__pyx_v_self->_args != ((PyObject*)Py_None)); + __pyx_v_use_setstate = __pyx_t_3; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self._args is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, None), state + * else: + */ + __pyx_t_3 = (__pyx_v_use_setstate != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":13 + * use_setstate = self._args is not None + * if use_setstate: + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_TopLevelThreadTra); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_64458794); + __Pyx_GIVEREF(__pyx_int_64458794); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_64458794); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None); + __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state); + __pyx_t_4 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self._args is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, None), state + * else: + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle_TopLevelThreadTra); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_64458794); + __Pyx_GIVEREF(__pyx_int_64458794); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_64458794); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1); + __pyx_t_5 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerOnlyUnhandledExceptions.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_8__setstate_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_8__setstate_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, (type(self), 0x3d7902a, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerOnlyUnhandledExceptions.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1627 + * cdef public set _raise_lines; + * cdef public int _last_raise_line; + * def __init__(self, frame_trace_dispatch, tuple args): # <<<<<<<<<<<<<< + * self._frame_trace_dispatch = frame_trace_dispatch + * self._args = args + */ + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_frame_trace_dispatch = 0; + PyObject *__pyx_v_args = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_frame_trace_dispatch,&__pyx_n_s_args,0}; + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame_trace_dispatch)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_args)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 1627, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 1627, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_frame_trace_dispatch = values[0]; + __pyx_v_args = ((PyObject*)values[1]); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1627, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_args), (&PyTuple_Type), 1, "args", 1))) __PYX_ERR(0, 1627, __pyx_L1_error) + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame___init__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), __pyx_v_frame_trace_dispatch, __pyx_v_args); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame___init__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v_frame_trace_dispatch, PyObject *__pyx_v_args) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1628 + * cdef public int _last_raise_line; + * def __init__(self, frame_trace_dispatch, tuple args): + * self._frame_trace_dispatch = frame_trace_dispatch # <<<<<<<<<<<<<< + * self._args = args + * self.try_except_infos = None + */ + __Pyx_INCREF(__pyx_v_frame_trace_dispatch); + __Pyx_GIVEREF(__pyx_v_frame_trace_dispatch); + __Pyx_GOTREF(__pyx_v_self->_frame_trace_dispatch); + __Pyx_DECREF(__pyx_v_self->_frame_trace_dispatch); + __pyx_v_self->_frame_trace_dispatch = __pyx_v_frame_trace_dispatch; + + /* "_pydevd_bundle/pydevd_cython.pyx":1629 + * def __init__(self, frame_trace_dispatch, tuple args): + * self._frame_trace_dispatch = frame_trace_dispatch + * self._args = args # <<<<<<<<<<<<<< + * self.try_except_infos = None + * self._last_exc_arg = None + */ + __Pyx_INCREF(__pyx_v_args); + __Pyx_GIVEREF(__pyx_v_args); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = __pyx_v_args; + + /* "_pydevd_bundle/pydevd_cython.pyx":1630 + * self._frame_trace_dispatch = frame_trace_dispatch + * self._args = args + * self.try_except_infos = None # <<<<<<<<<<<<<< + * self._last_exc_arg = None + * self._raise_lines = set() + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->try_except_infos); + __Pyx_DECREF(__pyx_v_self->try_except_infos); + __pyx_v_self->try_except_infos = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":1631 + * self._args = args + * self.try_except_infos = None + * self._last_exc_arg = None # <<<<<<<<<<<<<< + * self._raise_lines = set() + * self._last_raise_line = -1 + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_last_exc_arg); + __Pyx_DECREF(__pyx_v_self->_last_exc_arg); + __pyx_v_self->_last_exc_arg = Py_None; + + /* "_pydevd_bundle/pydevd_cython.pyx":1632 + * self.try_except_infos = None + * self._last_exc_arg = None + * self._raise_lines = set() # <<<<<<<<<<<<<< + * self._last_raise_line = -1 + * # ELSE + */ + __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1632, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_raise_lines); + __Pyx_DECREF(__pyx_v_self->_raise_lines); + __pyx_v_self->_raise_lines = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1633 + * self._last_exc_arg = None + * self._raise_lines = set() + * self._last_raise_line = -1 # <<<<<<<<<<<<<< + * # ELSE + * # class TopLevelThreadTracerNoBackFrame(object): + */ + __pyx_v_self->_last_raise_line = -1; + + /* "_pydevd_bundle/pydevd_cython.pyx":1627 + * cdef public set _raise_lines; + * cdef public int _last_raise_line; + * def __init__(self, frame_trace_dispatch, tuple args): # <<<<<<<<<<<<<< + * self._frame_trace_dispatch = frame_trace_dispatch + * self._args = args + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1657 + * # ENDIF + * + * def trace_dispatch_and_unhandled_exceptions(self, frame, event, arg): # <<<<<<<<<<<<<< + * # DEBUG = 'code_to_debug' in frame.f_code.co_filename + * # if DEBUG: print('trace_dispatch_and_unhandled_exceptions: %s %s %s %s %s %s' % (event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno, self._frame_trace_dispatch, frame.f_lineno)) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_3trace_dispatch_and_unhandled_exceptions(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_3trace_dispatch_and_unhandled_exceptions(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_event = 0; + PyObject *__pyx_v_arg = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("trace_dispatch_and_unhandled_exceptions (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_frame,&__pyx_n_s_event,&__pyx_n_s_arg,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_dispatch_and_unhandled_exceptions", 1, 3, 3, 1); __PYX_ERR(0, 1657, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arg)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("trace_dispatch_and_unhandled_exceptions", 1, 3, 3, 2); __PYX_ERR(0, 1657, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "trace_dispatch_and_unhandled_exceptions") < 0)) __PYX_ERR(0, 1657, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_frame = values[0]; + __pyx_v_event = values[1]; + __pyx_v_arg = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("trace_dispatch_and_unhandled_exceptions", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1657, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame.trace_dispatch_and_unhandled_exceptions", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_2trace_dispatch_and_unhandled_exceptions(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), __pyx_v_frame, __pyx_v_event, __pyx_v_arg); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_2trace_dispatch_and_unhandled_exceptions(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + PyObject *__pyx_v_frame_trace_dispatch = NULL; + PyObject *__pyx_v_py_db = NULL; + PyObject *__pyx_v_t = NULL; + PyObject *__pyx_v_additional_info = NULL; + PyObject *__pyx_v_ret = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + int __pyx_t_8; + int __pyx_t_9; + int __pyx_t_10; + char const *__pyx_t_11; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("trace_dispatch_and_unhandled_exceptions", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1660 + * # DEBUG = 'code_to_debug' in frame.f_code.co_filename + * # if DEBUG: print('trace_dispatch_and_unhandled_exceptions: %s %s %s %s %s %s' % (event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno, self._frame_trace_dispatch, frame.f_lineno)) + * frame_trace_dispatch = self._frame_trace_dispatch # <<<<<<<<<<<<<< + * if frame_trace_dispatch is not None: + * self._frame_trace_dispatch = frame_trace_dispatch(frame, event, arg) + */ + __pyx_t_1 = __pyx_v_self->_frame_trace_dispatch; + __Pyx_INCREF(__pyx_t_1); + __pyx_v_frame_trace_dispatch = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1661 + * # if DEBUG: print('trace_dispatch_and_unhandled_exceptions: %s %s %s %s %s %s' % (event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno, self._frame_trace_dispatch, frame.f_lineno)) + * frame_trace_dispatch = self._frame_trace_dispatch + * if frame_trace_dispatch is not None: # <<<<<<<<<<<<<< + * self._frame_trace_dispatch = frame_trace_dispatch(frame, event, arg) + * + */ + __pyx_t_2 = (__pyx_v_frame_trace_dispatch != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1662 + * frame_trace_dispatch = self._frame_trace_dispatch + * if frame_trace_dispatch is not None: + * self._frame_trace_dispatch = frame_trace_dispatch(frame, event, arg) # <<<<<<<<<<<<<< + * + * if event == 'exception': + */ + __Pyx_INCREF(__pyx_v_frame_trace_dispatch); + __pyx_t_4 = __pyx_v_frame_trace_dispatch; __pyx_t_5 = NULL; + __pyx_t_6 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_6 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 3+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1662, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 3+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1662, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_7 = PyTuple_New(3+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1662, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_5) { + __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_7, 2+__pyx_t_6, __pyx_v_arg); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1662, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_frame_trace_dispatch); + __Pyx_DECREF(__pyx_v_self->_frame_trace_dispatch); + __pyx_v_self->_frame_trace_dispatch = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1661 + * # if DEBUG: print('trace_dispatch_and_unhandled_exceptions: %s %s %s %s %s %s' % (event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno, self._frame_trace_dispatch, frame.f_lineno)) + * frame_trace_dispatch = self._frame_trace_dispatch + * if frame_trace_dispatch is not None: # <<<<<<<<<<<<<< + * self._frame_trace_dispatch = frame_trace_dispatch(frame, event, arg) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1664 + * self._frame_trace_dispatch = frame_trace_dispatch(frame, event, arg) + * + * if event == 'exception': # <<<<<<<<<<<<<< + * self._last_exc_arg = arg + * self._raise_lines.add(frame.f_lineno) + */ + __pyx_t_3 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_exception, Py_EQ)); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 1664, __pyx_L1_error) + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1665 + * + * if event == 'exception': + * self._last_exc_arg = arg # <<<<<<<<<<<<<< + * self._raise_lines.add(frame.f_lineno) + * self._last_raise_line = frame.f_lineno + */ + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + __Pyx_GOTREF(__pyx_v_self->_last_exc_arg); + __Pyx_DECREF(__pyx_v_self->_last_exc_arg); + __pyx_v_self->_last_exc_arg = __pyx_v_arg; + + /* "_pydevd_bundle/pydevd_cython.pyx":1666 + * if event == 'exception': + * self._last_exc_arg = arg + * self._raise_lines.add(frame.f_lineno) # <<<<<<<<<<<<<< + * self._last_raise_line = frame.f_lineno + * + */ + if (unlikely(__pyx_v_self->_raise_lines == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "add"); + __PYX_ERR(0, 1666, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1666, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = PySet_Add(__pyx_v_self->_raise_lines, __pyx_t_1); if (unlikely(__pyx_t_8 == ((int)-1))) __PYX_ERR(0, 1666, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1667 + * self._last_exc_arg = arg + * self._raise_lines.add(frame.f_lineno) + * self._last_raise_line = frame.f_lineno # <<<<<<<<<<<<<< + * + * elif event == 'return' and self._last_exc_arg is not None: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_lineno); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1667, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_6 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1667, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_self->_last_raise_line = __pyx_t_6; + + /* "_pydevd_bundle/pydevd_cython.pyx":1664 + * self._frame_trace_dispatch = frame_trace_dispatch(frame, event, arg) + * + * if event == 'exception': # <<<<<<<<<<<<<< + * self._last_exc_arg = arg + * self._raise_lines.add(frame.f_lineno) + */ + goto __pyx_L4; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1669 + * self._last_raise_line = frame.f_lineno + * + * elif event == 'return' and self._last_exc_arg is not None: # <<<<<<<<<<<<<< + * # For unhandled exceptions we actually track the return when at the topmost level. + * try: + */ + __pyx_t_2 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_return, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 1669, __pyx_L1_error) + if (__pyx_t_2) { + } else { + __pyx_t_3 = __pyx_t_2; + goto __pyx_L5_bool_binop_done; + } + __pyx_t_2 = (__pyx_v_self->_last_exc_arg != Py_None); + __pyx_t_9 = (__pyx_t_2 != 0); + __pyx_t_3 = __pyx_t_9; + __pyx_L5_bool_binop_done:; + if (__pyx_t_3) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1671 + * elif event == 'return' and self._last_exc_arg is not None: + * # For unhandled exceptions we actually track the return when at the topmost level. + * try: # <<<<<<<<<<<<<< + * py_db, t, additional_info = self._args[0:3] + * if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. + */ + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1672 + * # For unhandled exceptions we actually track the return when at the topmost level. + * try: + * py_db, t, additional_info = self._args[0:3] # <<<<<<<<<<<<<< + * if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. + * if is_unhandled_exception(self, py_db, frame, self._last_raise_line, self._raise_lines): + */ + if (unlikely(__pyx_v_self->_args == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1672, __pyx_L8_error) + } + __pyx_t_1 = __Pyx_PyTuple_GetSlice(__pyx_v_self->_args, 0, 3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1672, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_1); + if (1) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 3)) { + if (size > 3) __Pyx_RaiseTooManyValuesError(3); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 1672, __pyx_L8_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 2); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_5); + #else + __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1672, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1672, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_5 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1672, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_5); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } + __pyx_v_py_db = __pyx_t_4; + __pyx_t_4 = 0; + __pyx_v_t = __pyx_t_7; + __pyx_t_7 = 0; + __pyx_v_additional_info = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1673 + * try: + * py_db, t, additional_info = self._args[0:3] + * if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. # <<<<<<<<<<<<<< + * if is_unhandled_exception(self, py_db, frame, self._last_raise_line, self._raise_lines): + * py_db.stop_on_unhandled_exception(py_db, t, additional_info, self._last_exc_arg) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_additional_info, __pyx_n_s_suspended_at_unhandled); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1673, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 1673, __pyx_L8_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = ((!__pyx_t_3) != 0); + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1674 + * py_db, t, additional_info = self._args[0:3] + * if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. + * if is_unhandled_exception(self, py_db, frame, self._last_raise_line, self._raise_lines): # <<<<<<<<<<<<<< + * py_db.stop_on_unhandled_exception(py_db, t, additional_info, self._last_exc_arg) + * finally: + */ + __pyx_t_1 = __pyx_v_self->_raise_lines; + __Pyx_INCREF(__pyx_t_1); + __pyx_t_5 = __pyx_f_14_pydevd_bundle_13pydevd_cython_is_unhandled_exception(((PyObject *)__pyx_v_self), __pyx_v_py_db, __pyx_v_frame, __pyx_v_self->_last_raise_line, ((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1674, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1674, __pyx_L8_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1675 + * if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. + * if is_unhandled_exception(self, py_db, frame, self._last_raise_line, self._raise_lines): + * py_db.stop_on_unhandled_exception(py_db, t, additional_info, self._last_exc_arg) # <<<<<<<<<<<<<< + * finally: + * # Remove reference to exception after handling it. + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_stop_on_unhandled_exception); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1675, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = NULL; + __pyx_t_6 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_6 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[5] = {__pyx_t_7, __pyx_v_py_db, __pyx_v_t, __pyx_v_additional_info, __pyx_v_self->_last_exc_arg}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_6, 4+__pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1675, __pyx_L8_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_5); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[5] = {__pyx_t_7, __pyx_v_py_db, __pyx_v_t, __pyx_v_additional_info, __pyx_v_self->_last_exc_arg}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_6, 4+__pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1675, __pyx_L8_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_GOTREF(__pyx_t_5); + } else + #endif + { + __pyx_t_4 = PyTuple_New(4+__pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1675, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_4); + if (__pyx_t_7) { + __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_7); __pyx_t_7 = NULL; + } + __Pyx_INCREF(__pyx_v_py_db); + __Pyx_GIVEREF(__pyx_v_py_db); + PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_6, __pyx_v_py_db); + __Pyx_INCREF(__pyx_v_t); + __Pyx_GIVEREF(__pyx_v_t); + PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_6, __pyx_v_t); + __Pyx_INCREF(__pyx_v_additional_info); + __Pyx_GIVEREF(__pyx_v_additional_info); + PyTuple_SET_ITEM(__pyx_t_4, 2+__pyx_t_6, __pyx_v_additional_info); + __Pyx_INCREF(__pyx_v_self->_last_exc_arg); + __Pyx_GIVEREF(__pyx_v_self->_last_exc_arg); + PyTuple_SET_ITEM(__pyx_t_4, 3+__pyx_t_6, __pyx_v_self->_last_exc_arg); + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1675, __pyx_L8_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1674 + * py_db, t, additional_info = self._args[0:3] + * if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. + * if is_unhandled_exception(self, py_db, frame, self._last_raise_line, self._raise_lines): # <<<<<<<<<<<<<< + * py_db.stop_on_unhandled_exception(py_db, t, additional_info, self._last_exc_arg) + * finally: + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1673 + * try: + * py_db, t, additional_info = self._args[0:3] + * if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. # <<<<<<<<<<<<<< + * if is_unhandled_exception(self, py_db, frame, self._last_raise_line, self._raise_lines): + * py_db.stop_on_unhandled_exception(py_db, t, additional_info, self._last_exc_arg) + */ + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1678 + * finally: + * # Remove reference to exception after handling it. + * self._last_exc_arg = None # <<<<<<<<<<<<<< + * + * ret = self.trace_dispatch_and_unhandled_exceptions + */ + /*finally:*/ { + /*normal exit:*/{ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_last_exc_arg); + __Pyx_DECREF(__pyx_v_self->_last_exc_arg); + __pyx_v_self->_last_exc_arg = Py_None; + goto __pyx_L9; + } + __pyx_L8_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14) < 0)) __Pyx_ErrFetch(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_13); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __pyx_t_6 = __pyx_lineno; __pyx_t_10 = __pyx_clineno; __pyx_t_11 = __pyx_filename; + { + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_last_exc_arg); + __Pyx_DECREF(__pyx_v_self->_last_exc_arg); + __pyx_v_self->_last_exc_arg = Py_None; + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_ExceptionReset(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_13); + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_ErrRestore(__pyx_t_12, __pyx_t_13, __pyx_t_14); + __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __pyx_lineno = __pyx_t_6; __pyx_clineno = __pyx_t_10; __pyx_filename = __pyx_t_11; + goto __pyx_L1_error; + } + __pyx_L9:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1669 + * self._last_raise_line = frame.f_lineno + * + * elif event == 'return' and self._last_exc_arg is not None: # <<<<<<<<<<<<<< + * # For unhandled exceptions we actually track the return when at the topmost level. + * try: + */ + } + __pyx_L4:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1680 + * self._last_exc_arg = None + * + * ret = self.trace_dispatch_and_unhandled_exceptions # <<<<<<<<<<<<<< + * + * # Need to reset (the call to _frame_trace_dispatch may have changed it). + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch_and_unhandled_exc); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1680, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_ret = __pyx_t_5; + __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1684 + * # Need to reset (the call to _frame_trace_dispatch may have changed it). + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * frame.f_trace = SafeCallWrapper(ret) # <<<<<<<<<<<<<< + * # ELSE + * # frame.f_trace = ret + */ + __pyx_t_5 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper), __pyx_v_ret); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1684, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_5) < 0) __PYX_ERR(0, 1684, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1688 + * # frame.f_trace = ret + * # ENDIF + * return ret # <<<<<<<<<<<<<< + * + * def get_trace_dispatch_func(self): + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_ret); + __pyx_r = __pyx_v_ret; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1657 + * # ENDIF + * + * def trace_dispatch_and_unhandled_exceptions(self, frame, event, arg): # <<<<<<<<<<<<<< + * # DEBUG = 'code_to_debug' in frame.f_code.co_filename + * # if DEBUG: print('trace_dispatch_and_unhandled_exceptions: %s %s %s %s %s %s' % (event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno, self._frame_trace_dispatch, frame.f_lineno)) + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame.trace_dispatch_and_unhandled_exceptions", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_frame_trace_dispatch); + __Pyx_XDECREF(__pyx_v_py_db); + __Pyx_XDECREF(__pyx_v_t); + __Pyx_XDECREF(__pyx_v_additional_info); + __Pyx_XDECREF(__pyx_v_ret); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1690 + * return ret + * + * def get_trace_dispatch_func(self): # <<<<<<<<<<<<<< + * return self.trace_dispatch_and_unhandled_exceptions + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5get_trace_dispatch_func(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5get_trace_dispatch_func(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_trace_dispatch_func (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_4get_trace_dispatch_func(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_4get_trace_dispatch_func(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_trace_dispatch_func", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1691 + * + * def get_trace_dispatch_func(self): + * return self.trace_dispatch_and_unhandled_exceptions # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_trace_dispatch_and_unhandled_exc); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1691, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1690 + * return ret + * + * def get_trace_dispatch_func(self): # <<<<<<<<<<<<<< + * return self.trace_dispatch_and_unhandled_exceptions + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame.get_trace_dispatch_func", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1621 + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class TopLevelThreadTracerNoBackFrame: + * cdef public object _frame_trace_dispatch; # <<<<<<<<<<<<<< + * cdef public tuple _args; + * cdef public object try_except_infos; + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->_frame_trace_dispatch); + __pyx_r = __pyx_v_self->_frame_trace_dispatch; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->_frame_trace_dispatch); + __Pyx_DECREF(__pyx_v_self->_frame_trace_dispatch); + __pyx_v_self->_frame_trace_dispatch = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_frame_trace_dispatch); + __Pyx_DECREF(__pyx_v_self->_frame_trace_dispatch); + __pyx_v_self->_frame_trace_dispatch = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1622 + * cdef class TopLevelThreadTracerNoBackFrame: + * cdef public object _frame_trace_dispatch; + * cdef public tuple _args; # <<<<<<<<<<<<<< + * cdef public object try_except_infos; + * cdef public object _last_exc_arg; + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->_args); + __pyx_r = __pyx_v_self->_args; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyTuple_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 1622, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame._args.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1623 + * cdef public object _frame_trace_dispatch; + * cdef public tuple _args; + * cdef public object try_except_infos; # <<<<<<<<<<<<<< + * cdef public object _last_exc_arg; + * cdef public set _raise_lines; + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->try_except_infos); + __pyx_r = __pyx_v_self->try_except_infos; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->try_except_infos); + __Pyx_DECREF(__pyx_v_self->try_except_infos); + __pyx_v_self->try_except_infos = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->try_except_infos); + __Pyx_DECREF(__pyx_v_self->try_except_infos); + __pyx_v_self->try_except_infos = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1624 + * cdef public tuple _args; + * cdef public object try_except_infos; + * cdef public object _last_exc_arg; # <<<<<<<<<<<<<< + * cdef public set _raise_lines; + * cdef public int _last_raise_line; + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->_last_exc_arg); + __pyx_r = __pyx_v_self->_last_exc_arg; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->_last_exc_arg); + __Pyx_DECREF(__pyx_v_self->_last_exc_arg); + __pyx_v_self->_last_exc_arg = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_last_exc_arg); + __Pyx_DECREF(__pyx_v_self->_last_exc_arg); + __pyx_v_self->_last_exc_arg = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1625 + * cdef public object try_except_infos; + * cdef public object _last_exc_arg; + * cdef public set _raise_lines; # <<<<<<<<<<<<<< + * cdef public int _last_raise_line; + * def __init__(self, frame_trace_dispatch, tuple args): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->_raise_lines); + __pyx_r = __pyx_v_self->_raise_lines; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PySet_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "set", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 1625, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_raise_lines); + __Pyx_DECREF(__pyx_v_self->_raise_lines); + __pyx_v_self->_raise_lines = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame._raise_lines.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_raise_lines); + __Pyx_DECREF(__pyx_v_self->_raise_lines); + __pyx_v_self->_raise_lines = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1626 + * cdef public object _last_exc_arg; + * cdef public set _raise_lines; + * cdef public int _last_raise_line; # <<<<<<<<<<<<<< + * def __init__(self, frame_trace_dispatch, tuple args): + * self._frame_trace_dispatch = frame_trace_dispatch + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->_last_raise_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1626, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame._last_raise_line.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1626, __pyx_L1_error) + __pyx_v_self->_last_raise_line = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame._last_raise_line.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_6__reduce_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_6__reduce_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self._args, self._frame_trace_dispatch, self._last_exc_arg, self._last_raise_line, self._raise_lines, self.try_except_infos) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->_last_raise_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(6); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_self->_args); + __Pyx_INCREF(__pyx_v_self->_frame_trace_dispatch); + __Pyx_GIVEREF(__pyx_v_self->_frame_trace_dispatch); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_self->_frame_trace_dispatch); + __Pyx_INCREF(__pyx_v_self->_last_exc_arg); + __Pyx_GIVEREF(__pyx_v_self->_last_exc_arg); + PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_v_self->_last_exc_arg); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_2, 3, __pyx_t_1); + __Pyx_INCREF(__pyx_v_self->_raise_lines); + __Pyx_GIVEREF(__pyx_v_self->_raise_lines); + PyTuple_SET_ITEM(__pyx_t_2, 4, __pyx_v_self->_raise_lines); + __Pyx_INCREF(__pyx_v_self->try_except_infos); + __Pyx_GIVEREF(__pyx_v_self->try_except_infos); + PyTuple_SET_ITEM(__pyx_t_2, 5, __pyx_v_self->try_except_infos); + __pyx_t_1 = 0; + __pyx_v_state = ((PyObject*)__pyx_t_2); + __pyx_t_2 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self._args, self._frame_trace_dispatch, self._last_exc_arg, self._last_raise_line, self._raise_lines, self.try_except_infos) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_2 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_v__dict = __pyx_t_2; + __pyx_t_2 = 0; + + /* "(tree fragment)":7 + * state = (self._args, self._frame_trace_dispatch, self._last_exc_arg, self._last_raise_line, self._raise_lines, self.try_except_infos) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_3 = (__pyx_v__dict != Py_None); + __pyx_t_4 = (__pyx_t_3 != 0); + if (__pyx_t_4) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v__dict); + __pyx_t_1 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self._args is not None or self._frame_trace_dispatch is not None or self._last_exc_arg is not None or self._raise_lines is not None or self.try_except_infos is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self._args, self._frame_trace_dispatch, self._last_exc_arg, self._last_raise_line, self._raise_lines, self.try_except_infos) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self._args is not None or self._frame_trace_dispatch is not None or self._last_exc_arg is not None or self._raise_lines is not None or self.try_except_infos is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, None), state + */ + /*else*/ { + __pyx_t_3 = (__pyx_v_self->_args != ((PyObject*)Py_None)); + __pyx_t_5 = (__pyx_t_3 != 0); + if (!__pyx_t_5) { + } else { + __pyx_t_4 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = (__pyx_v_self->_frame_trace_dispatch != Py_None); + __pyx_t_3 = (__pyx_t_5 != 0); + if (!__pyx_t_3) { + } else { + __pyx_t_4 = __pyx_t_3; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_3 = (__pyx_v_self->_last_exc_arg != Py_None); + __pyx_t_5 = (__pyx_t_3 != 0); + if (!__pyx_t_5) { + } else { + __pyx_t_4 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = (__pyx_v_self->_raise_lines != ((PyObject*)Py_None)); + __pyx_t_3 = (__pyx_t_5 != 0); + if (!__pyx_t_3) { + } else { + __pyx_t_4 = __pyx_t_3; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_3 = (__pyx_v_self->try_except_infos != Py_None); + __pyx_t_5 = (__pyx_t_3 != 0); + __pyx_t_4 = __pyx_t_5; + __pyx_L4_bool_binop_done:; + __pyx_v_use_setstate = __pyx_t_4; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self._args is not None or self._frame_trace_dispatch is not None or self._last_exc_arg is not None or self._raise_lines is not None or self.try_except_infos is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, None), state + * else: + */ + __pyx_t_4 = (__pyx_v_use_setstate != 0); + if (__pyx_t_4) { + + /* "(tree fragment)":13 + * use_setstate = self._args is not None or self._frame_trace_dispatch is not None or self._last_exc_arg is not None or self._raise_lines is not None or self.try_except_infos is not None + * if use_setstate: + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pyx_unpickle_TopLevelThreadTra_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_171613889); + __Pyx_GIVEREF(__pyx_int_171613889); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_171613889); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_2, 2, Py_None); + __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_2); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_v_state); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self._args is not None or self._frame_trace_dispatch is not None or self._last_exc_arg is not None or self._raise_lines is not None or self.try_except_infos is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, None), state + * else: + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pyx_unpickle_TopLevelThreadTra_2); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_171613889); + __Pyx_GIVEREF(__pyx_int_171613889); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_171613889); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_v_state); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_2); + __pyx_t_6 = 0; + __pyx_t_2 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_8__setstate_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_8__setstate_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_TopLevelThreadTracerNoBackFrame, (type(self), 0xa3a9ec1, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1697 + * cdef class ThreadTracer: + * cdef public tuple _args; + * def __init__(self, tuple args): # <<<<<<<<<<<<<< + * self._args = args + * # ELSE + */ + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_args = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_args,0}; + PyObject* values[1] = {0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_args)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 1697, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 1) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + } + __pyx_v_args = ((PyObject*)values[0]); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1697, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_args), (&PyTuple_Type), 1, "args", 1))) __PYX_ERR(0, 1697, __pyx_L1_error) + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer___init__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)__pyx_v_self), __pyx_v_args); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer___init__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *__pyx_v_self, PyObject *__pyx_v_args) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1698 + * cdef public tuple _args; + * def __init__(self, tuple args): + * self._args = args # <<<<<<<<<<<<<< + * # ELSE + * # class ThreadTracer(object): + */ + __Pyx_INCREF(__pyx_v_args); + __Pyx_GIVEREF(__pyx_v_args); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = __pyx_v_args; + + /* "_pydevd_bundle/pydevd_cython.pyx":1697 + * cdef class ThreadTracer: + * cdef public tuple _args; + * def __init__(self, tuple args): # <<<<<<<<<<<<<< + * self._args = args + * # ELSE + */ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1706 + * # ENDIF + * + * def __call__(self, frame, event, arg): # <<<<<<<<<<<<<< + * ''' This is the callback used when we enter some context in the debugger. + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_3__call__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_2__call__[] = " This is the callback used when we enter some context in the debugger.\n\n We also decorate the thread we are in with info about the debugging.\n The attributes added are:\n pydev_state\n pydev_step_stop\n pydev_step_cmd\n pydev_notify_kill\n\n :param PyDB py_db:\n This is the global debugger (this method should actually be added as a method to it).\n "; +#if CYTHON_UPDATE_DESCRIPTOR_DOC +struct wrapperbase __pyx_wrapperbase_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_2__call__; +#endif +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_3__call__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_event = 0; + PyObject *__pyx_v_arg = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__call__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_frame,&__pyx_n_s_event,&__pyx_n_s_arg,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__call__", 1, 3, 3, 1); __PYX_ERR(0, 1706, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arg)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__call__", 1, 3, 3, 2); __PYX_ERR(0, 1706, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__call__") < 0)) __PYX_ERR(0, 1706, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_frame = values[0]; + __pyx_v_event = values[1]; + __pyx_v_arg = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__call__", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1706, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_2__call__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)__pyx_v_self), __pyx_v_frame, __pyx_v_event, __pyx_v_arg); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_2__call__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + int __pyx_v_pydev_step_cmd; + PyObject *__pyx_v_frame_cache_key = 0; + PyObject *__pyx_v_cache_skips = 0; + int __pyx_v_is_stepping; + PyObject *__pyx_v_abs_path_canonical_path_and_base = 0; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_additional_info = 0; + PyObject *__pyx_v_py_db = NULL; + PyObject *__pyx_v_t = NULL; + PyObject *__pyx_v_frame_skips_cache = NULL; + PyObject *__pyx_v_back_frame = NULL; + PyObject *__pyx_v_back_frame_cache_key = NULL; + PyObject *__pyx_v_file_type = NULL; + PyObject *__pyx_v_ret = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + int __pyx_t_11; + int __pyx_t_12; + int __pyx_t_13; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + int __pyx_t_17; + char const *__pyx_t_18; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__call__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1732 + * # DEBUG = 'code_to_debug' in frame.f_code.co_filename + * # if DEBUG: print('ENTER: trace_dispatch: %s %s %s %s' % (frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)) + * py_db, t, additional_info, cache_skips, frame_skips_cache = self._args # <<<<<<<<<<<<<< + * if additional_info.is_tracing: + * return None if event == 'call' else NO_FTRACE # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch + */ + __pyx_t_1 = __pyx_v_self->_args; + __Pyx_INCREF(__pyx_t_1); + if (likely(__pyx_t_1 != Py_None)) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 5)) { + if (size > 5) __Pyx_RaiseTooManyValuesError(5); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 1732, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 4); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + #else + { + Py_ssize_t i; + PyObject** temps[5] = {&__pyx_t_2,&__pyx_t_3,&__pyx_t_4,&__pyx_t_5,&__pyx_t_6}; + for (i=0; i < 5; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 1732, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 1732, __pyx_L1_error) + } + if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo))))) __PYX_ERR(0, 1732, __pyx_L1_error) + if (!(likely(PyDict_CheckExact(__pyx_t_5))||((__pyx_t_5) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_5)->tp_name), 0))) __PYX_ERR(0, 1732, __pyx_L1_error) + __pyx_v_py_db = __pyx_t_2; + __pyx_t_2 = 0; + __pyx_v_t = __pyx_t_3; + __pyx_t_3 = 0; + __pyx_v_additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_4); + __pyx_t_4 = 0; + __pyx_v_cache_skips = ((PyObject*)__pyx_t_5); + __pyx_t_5 = 0; + __pyx_v_frame_skips_cache = __pyx_t_6; + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1733 + * # if DEBUG: print('ENTER: trace_dispatch: %s %s %s %s' % (frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)) + * py_db, t, additional_info, cache_skips, frame_skips_cache = self._args + * if additional_info.is_tracing: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch + * + */ + __pyx_t_7 = (__pyx_v_additional_info->is_tracing != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1734 + * py_db, t, additional_info, cache_skips, frame_skips_cache = self._args + * if additional_info.is_tracing: + * return None if event == 'call' else NO_FTRACE # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch # <<<<<<<<<<<<<< + * + * additional_info.is_tracing += 1 + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1734, __pyx_L1_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1734, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1733 + * # if DEBUG: print('ENTER: trace_dispatch: %s %s %s %s' % (frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)) + * py_db, t, additional_info, cache_skips, frame_skips_cache = self._args + * if additional_info.is_tracing: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1736 + * return None if event == 'call' else NO_FTRACE # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch + * + * additional_info.is_tracing += 1 # <<<<<<<<<<<<<< + * try: + * pydev_step_cmd = additional_info.pydev_step_cmd + */ + __pyx_v_additional_info->is_tracing = (__pyx_v_additional_info->is_tracing + 1); + + /* "_pydevd_bundle/pydevd_cython.pyx":1737 + * + * additional_info.is_tracing += 1 + * try: # <<<<<<<<<<<<<< + * pydev_step_cmd = additional_info.pydev_step_cmd + * is_stepping = pydev_step_cmd != -1 + */ + /*try:*/ { + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_9); + __Pyx_XGOTREF(__pyx_t_10); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1738 + * additional_info.is_tracing += 1 + * try: + * pydev_step_cmd = additional_info.pydev_step_cmd # <<<<<<<<<<<<<< + * is_stepping = pydev_step_cmd != -1 + * if py_db.pydb_disposed: + */ + __pyx_t_11 = __pyx_v_additional_info->pydev_step_cmd; + __pyx_v_pydev_step_cmd = __pyx_t_11; + + /* "_pydevd_bundle/pydevd_cython.pyx":1739 + * try: + * pydev_step_cmd = additional_info.pydev_step_cmd + * is_stepping = pydev_step_cmd != -1 # <<<<<<<<<<<<<< + * if py_db.pydb_disposed: + * return None if event == 'call' else NO_FTRACE + */ + __pyx_v_is_stepping = (__pyx_v_pydev_step_cmd != -1L); + + /* "_pydevd_bundle/pydevd_cython.pyx":1740 + * pydev_step_cmd = additional_info.pydev_step_cmd + * is_stepping = pydev_step_cmd != -1 + * if py_db.pydb_disposed: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_pydb_disposed); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1740, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1740, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1741 + * is_stepping = pydev_step_cmd != -1 + * if py_db.pydb_disposed: + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * + * # if thread is not alive, cancel trace_dispatch processing + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1741, __pyx_L7_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1741, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1740 + * pydev_step_cmd = additional_info.pydev_step_cmd + * is_stepping = pydev_step_cmd != -1 + * if py_db.pydb_disposed: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1744 + * + * # if thread is not alive, cancel trace_dispatch processing + * if not is_thread_alive(t): # <<<<<<<<<<<<<< + * py_db.notify_thread_not_alive(get_current_thread_id(t)) + * return None if event == 'call' else NO_FTRACE + */ + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_is_thread_alive); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1744, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + } + } + __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_5, __pyx_v_t) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_t); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1744, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1744, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_12 = ((!__pyx_t_7) != 0); + if (__pyx_t_12) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1745 + * # if thread is not alive, cancel trace_dispatch processing + * if not is_thread_alive(t): + * py_db.notify_thread_not_alive(get_current_thread_id(t)) # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_notify_thread_not_alive); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1745, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_get_current_thread_id); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1745, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_5 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_3, __pyx_v_t) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_t); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1745, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + } + } + __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1745, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1746 + * if not is_thread_alive(t): + * py_db.notify_thread_not_alive(get_current_thread_id(t)) + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * + * # Note: it's important that the context name is also given because we may hit something once + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_12 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 1746, __pyx_L7_error) + if (__pyx_t_12) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1746, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1744 + * + * # if thread is not alive, cancel trace_dispatch processing + * if not is_thread_alive(t): # <<<<<<<<<<<<<< + * py_db.notify_thread_not_alive(get_current_thread_id(t)) + * return None if event == 'call' else NO_FTRACE + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1750 + * # Note: it's important that the context name is also given because we may hit something once + * # in the global context and another in the local context. + * frame_cache_key = frame.f_code # <<<<<<<<<<<<<< + * if frame_cache_key in cache_skips: + * if not is_stepping: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1750, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_frame_cache_key = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1751 + * # in the global context and another in the local context. + * frame_cache_key = frame.f_code + * if frame_cache_key in cache_skips: # <<<<<<<<<<<<<< + * if not is_stepping: + * # if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + */ + if (unlikely(__pyx_v_cache_skips == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 1751, __pyx_L7_error) + } + __pyx_t_12 = (__Pyx_PyDict_ContainsTF(__pyx_v_frame_cache_key, __pyx_v_cache_skips, Py_EQ)); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 1751, __pyx_L7_error) + __pyx_t_7 = (__pyx_t_12 != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1752 + * frame_cache_key = frame.f_code + * if frame_cache_key in cache_skips: + * if not is_stepping: # <<<<<<<<<<<<<< + * # if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE + */ + __pyx_t_7 = ((!(__pyx_v_is_stepping != 0)) != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1754 + * if not is_stepping: + * # if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * else: + * # When stepping we can't take into account caching based on the breakpoints (only global filtering). + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1754, __pyx_L7_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1754, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1752 + * frame_cache_key = frame.f_code + * if frame_cache_key in cache_skips: + * if not is_stepping: # <<<<<<<<<<<<<< + * # if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1757 + * else: + * # When stepping we can't take into account caching based on the breakpoints (only global filtering). + * if cache_skips.get(frame_cache_key) == 1: # <<<<<<<<<<<<<< + * + * if additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: + */ + /*else*/ { + if (unlikely(__pyx_v_cache_skips == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get"); + __PYX_ERR(0, 1757, __pyx_L7_error) + } + __pyx_t_1 = __Pyx_PyDict_GetItemDefault(__pyx_v_cache_skips, __pyx_v_frame_cache_key, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1757, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_6 = __Pyx_PyInt_EqObjC(__pyx_t_1, __pyx_int_1, 1, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1757, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1757, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1759 + * if cache_skips.get(frame_cache_key) == 1: + * + * if additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: # <<<<<<<<<<<<<< + * notify_skipped_step_in_because_of_filters(py_db, frame) + * + */ + switch (__pyx_v_additional_info->pydev_original_step_cmd) { + case 0x6B: + case 0x90: + __pyx_t_12 = 1; + break; + default: + __pyx_t_12 = 0; + break; + } + __pyx_t_13 = (__pyx_t_12 != 0); + if (__pyx_t_13) { + } else { + __pyx_t_7 = __pyx_t_13; + goto __pyx_L19_bool_binop_done; + } + __pyx_t_13 = __Pyx_PyObject_IsTrue(__pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 1759, __pyx_L7_error) + __pyx_t_12 = ((!__pyx_t_13) != 0); + __pyx_t_7 = __pyx_t_12; + __pyx_L19_bool_binop_done:; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1760 + * + * if additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: + * notify_skipped_step_in_because_of_filters(py_db, frame) # <<<<<<<<<<<<<< + * + * back_frame = frame.f_back + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_notify_skipped_step_in_because_o); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1760, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_py_db, __pyx_v_frame}; + __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1760, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_6); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_py_db, __pyx_v_frame}; + __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1760, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_6); + } else + #endif + { + __pyx_t_4 = PyTuple_New(2+__pyx_t_11); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1760, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + if (__pyx_t_5) { + __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); __pyx_t_5 = NULL; + } + __Pyx_INCREF(__pyx_v_py_db); + __Pyx_GIVEREF(__pyx_v_py_db); + PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_11, __pyx_v_py_db); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_11, __pyx_v_frame); + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_4, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1760, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1759 + * if cache_skips.get(frame_cache_key) == 1: + * + * if additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: # <<<<<<<<<<<<<< + * notify_skipped_step_in_because_of_filters(py_db, frame) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1762 + * notify_skipped_step_in_because_of_filters(py_db, frame) + * + * back_frame = frame.f_back # <<<<<<<<<<<<<< + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + * back_frame_cache_key = back_frame.f_code + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1762, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_back_frame = __pyx_t_6; + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1763 + * + * back_frame = frame.f_back + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): # <<<<<<<<<<<<<< + * back_frame_cache_key = back_frame.f_code + * if cache_skips.get(back_frame_cache_key) == 1: + */ + __pyx_t_12 = (__pyx_v_back_frame != Py_None); + __pyx_t_13 = (__pyx_t_12 != 0); + if (__pyx_t_13) { + } else { + __pyx_t_7 = __pyx_t_13; + goto __pyx_L22_bool_binop_done; + } + switch (__pyx_v_pydev_step_cmd) { + case 0x6B: + case 0x90: + case 0x6D: + case 0xA0: + __pyx_t_13 = 1; + break; + default: + __pyx_t_13 = 0; + break; + } + __pyx_t_12 = (__pyx_t_13 != 0); + __pyx_t_7 = __pyx_t_12; + __pyx_L22_bool_binop_done:; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1764 + * back_frame = frame.f_back + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + * back_frame_cache_key = back_frame.f_code # <<<<<<<<<<<<<< + * if cache_skips.get(back_frame_cache_key) == 1: + * # if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_back_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1764, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_back_frame_cache_key = __pyx_t_6; + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1765 + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + * back_frame_cache_key = back_frame.f_code + * if cache_skips.get(back_frame_cache_key) == 1: # <<<<<<<<<<<<<< + * # if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE + */ + if (unlikely(__pyx_v_cache_skips == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get"); + __PYX_ERR(0, 1765, __pyx_L7_error) + } + __pyx_t_6 = __Pyx_PyDict_GetItemDefault(__pyx_v_cache_skips, __pyx_v_back_frame_cache_key, Py_None); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1765, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __Pyx_PyInt_EqObjC(__pyx_t_6, __pyx_int_1, 1, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1765, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1765, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1767 + * if cache_skips.get(back_frame_cache_key) == 1: + * # if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * else: + * # if DEBUG: print('skipped: trace_dispatch (cache hit: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1767, __pyx_L7_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1767, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1765 + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + * back_frame_cache_key = back_frame.f_code + * if cache_skips.get(back_frame_cache_key) == 1: # <<<<<<<<<<<<<< + * # if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1763 + * + * back_frame = frame.f_back + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): # <<<<<<<<<<<<<< + * back_frame_cache_key = back_frame.f_code + * if cache_skips.get(back_frame_cache_key) == 1: + */ + goto __pyx_L21; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1770 + * else: + * # if DEBUG: print('skipped: trace_dispatch (cache hit: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * + * try: + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1770, __pyx_L7_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1770, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + } + __pyx_L21:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1757 + * else: + * # When stepping we can't take into account caching based on the breakpoints (only global filtering). + * if cache_skips.get(frame_cache_key) == 1: # <<<<<<<<<<<<<< + * + * if additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: + */ + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1751 + * # in the global context and another in the local context. + * frame_cache_key = frame.f_code + * if frame_cache_key in cache_skips: # <<<<<<<<<<<<<< + * if not is_stepping: + * # if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1772 + * return None if event == 'call' else NO_FTRACE + * + * try: # <<<<<<<<<<<<<< + * # Make fast path faster! + * abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1774 + * try: + * # Make fast path faster! + * abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] # <<<<<<<<<<<<<< + * except: + * abs_path_canonical_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1774, __pyx_L25_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1774, __pyx_L25_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1774, __pyx_L25_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_t_4); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1774, __pyx_L25_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (!(likely(PyTuple_CheckExact(__pyx_t_6))||((__pyx_t_6) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_6)->tp_name), 0))) __PYX_ERR(0, 1774, __pyx_L25_error) + __pyx_v_abs_path_canonical_path_and_base = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1772 + * return None if event == 'call' else NO_FTRACE + * + * try: # <<<<<<<<<<<<<< + * # Make fast path faster! + * abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + */ + } + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; + goto __pyx_L30_try_end; + __pyx_L25_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1775 + * # Make fast path faster! + * abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + * except: # <<<<<<<<<<<<<< + * abs_path_canonical_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_4, &__pyx_t_1) < 0) __PYX_ERR(0, 1775, __pyx_L27_except_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_1); + + /* "_pydevd_bundle/pydevd_cython.pyx":1776 + * abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + * except: + * abs_path_canonical_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) # <<<<<<<<<<<<<< + * + * file_type = py_db.get_file_type(frame, abs_path_canonical_path_and_base) # we don't want to debug threading or anything related to pydevd + */ + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_get_abs_path_real_path_and_base); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1776, __pyx_L27_except_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_5 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_v_frame) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_frame); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1776, __pyx_L27_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (!(likely(PyTuple_CheckExact(__pyx_t_5))||((__pyx_t_5) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_5)->tp_name), 0))) __PYX_ERR(0, 1776, __pyx_L27_except_error) + __Pyx_XDECREF_SET(__pyx_v_abs_path_canonical_path_and_base, ((PyObject*)__pyx_t_5)); + __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L26_exception_handled; + } + __pyx_L27_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1772 + * return None if event == 'call' else NO_FTRACE + * + * try: # <<<<<<<<<<<<<< + * # Make fast path faster! + * abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + */ + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_14, __pyx_t_15, __pyx_t_16); + goto __pyx_L7_error; + __pyx_L26_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_14, __pyx_t_15, __pyx_t_16); + __pyx_L30_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1778 + * abs_path_canonical_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) + * + * file_type = py_db.get_file_type(frame, abs_path_canonical_path_and_base) # we don't want to debug threading or anything related to pydevd # <<<<<<<<<<<<<< + * + * if file_type is not None: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_get_file_type); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1778, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_frame, __pyx_v_abs_path_canonical_path_and_base}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1778, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_frame, __pyx_v_abs_path_canonical_path_and_base}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1778, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_5 = PyTuple_New(2+__pyx_t_11); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1778, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_5); + if (__pyx_t_6) { + __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_6); __pyx_t_6 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_11, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_abs_path_canonical_path_and_base); + __Pyx_GIVEREF(__pyx_v_abs_path_canonical_path_and_base); + PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_11, __pyx_v_abs_path_canonical_path_and_base); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1778, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_file_type = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1780 + * file_type = py_db.get_file_type(frame, abs_path_canonical_path_and_base) # we don't want to debug threading or anything related to pydevd + * + * if file_type is not None: # <<<<<<<<<<<<<< + * if file_type == 1: # inlining LIB_FILE = 1 + * if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): + */ + __pyx_t_7 = (__pyx_v_file_type != Py_None); + __pyx_t_12 = (__pyx_t_7 != 0); + if (__pyx_t_12) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1781 + * + * if file_type is not None: + * if file_type == 1: # inlining LIB_FILE = 1 # <<<<<<<<<<<<<< + * if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): + * # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + */ + __pyx_t_1 = __Pyx_PyInt_EqObjC(__pyx_v_file_type, __pyx_int_1, 1, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1781, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_12 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 1781, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_12) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1782 + * if file_type is not None: + * if file_type == 1: # inlining LIB_FILE = 1 + * if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): # <<<<<<<<<<<<<< + * # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + * cache_skips[frame_cache_key] = 1 + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_in_project_scope); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1782, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + if (unlikely(__pyx_v_abs_path_canonical_path_and_base == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1782, __pyx_L7_error) + } + __pyx_t_5 = __Pyx_GetItemInt_Tuple(__pyx_v_abs_path_canonical_path_and_base, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1782, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_frame, __pyx_t_5}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1782, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_frame, __pyx_t_5}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1782, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } else + #endif + { + __pyx_t_3 = PyTuple_New(2+__pyx_t_11); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1782, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_6) { + __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_6); __pyx_t_6 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_11, __pyx_v_frame); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_11, __pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1782, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_12 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 1782, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_7 = ((!__pyx_t_12) != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1784 + * if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): + * # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + * cache_skips[frame_cache_key] = 1 # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * else: + */ + if (unlikely(__pyx_v_cache_skips == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1784, __pyx_L7_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_cache_skips, __pyx_v_frame_cache_key, __pyx_int_1) < 0)) __PYX_ERR(0, 1784, __pyx_L7_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1785 + * # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + * cache_skips[frame_cache_key] = 1 + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * else: + * # if DEBUG: print('skipped: trace_dispatch', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1785, __pyx_L7_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1785, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __pyx_t_4; + __pyx_t_4 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1782 + * if file_type is not None: + * if file_type == 1: # inlining LIB_FILE = 1 + * if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): # <<<<<<<<<<<<<< + * # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + * cache_skips[frame_cache_key] = 1 + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1781 + * + * if file_type is not None: + * if file_type == 1: # inlining LIB_FILE = 1 # <<<<<<<<<<<<<< + * if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): + * # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + */ + goto __pyx_L34; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1788 + * else: + * # if DEBUG: print('skipped: trace_dispatch', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + * cache_skips[frame_cache_key] = 1 # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * + */ + /*else*/ { + if (unlikely(__pyx_v_cache_skips == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1788, __pyx_L7_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_cache_skips, __pyx_v_frame_cache_key, __pyx_int_1) < 0)) __PYX_ERR(0, 1788, __pyx_L7_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1789 + * # if DEBUG: print('skipped: trace_dispatch', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + * cache_skips[frame_cache_key] = 1 + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * + * if py_db.is_files_filter_enabled: + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1789, __pyx_L7_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1789, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __pyx_t_4; + __pyx_t_4 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + } + __pyx_L34:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1780 + * file_type = py_db.get_file_type(frame, abs_path_canonical_path_and_base) # we don't want to debug threading or anything related to pydevd + * + * if file_type is not None: # <<<<<<<<<<<<<< + * if file_type == 1: # inlining LIB_FILE = 1 + * if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1791 + * return None if event == 'call' else NO_FTRACE + * + * if py_db.is_files_filter_enabled: # <<<<<<<<<<<<<< + * if py_db.apply_files_filter(frame, abs_path_canonical_path_and_base[0], False): + * cache_skips[frame_cache_key] = 1 + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_is_files_filter_enabled); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1791, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1791, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1792 + * + * if py_db.is_files_filter_enabled: + * if py_db.apply_files_filter(frame, abs_path_canonical_path_and_base[0], False): # <<<<<<<<<<<<<< + * cache_skips[frame_cache_key] = 1 + * + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1792, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + if (unlikely(__pyx_v_abs_path_canonical_path_and_base == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1792, __pyx_L7_error) + } + __pyx_t_3 = __Pyx_GetItemInt_Tuple(__pyx_v_abs_path_canonical_path_and_base, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1792, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_v_frame, __pyx_t_3, Py_False}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1792, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_v_frame, __pyx_t_3, Py_False}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1792, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else + #endif + { + __pyx_t_6 = PyTuple_New(3+__pyx_t_11); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1792, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + if (__pyx_t_5) { + __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_11, __pyx_v_frame); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_11, __pyx_t_3); + __Pyx_INCREF(Py_False); + __Pyx_GIVEREF(Py_False); + PyTuple_SET_ITEM(__pyx_t_6, 2+__pyx_t_11, Py_False); + __pyx_t_3 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1792, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1792, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1793 + * if py_db.is_files_filter_enabled: + * if py_db.apply_files_filter(frame, abs_path_canonical_path_and_base[0], False): + * cache_skips[frame_cache_key] = 1 # <<<<<<<<<<<<<< + * + * if is_stepping and additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: + */ + if (unlikely(__pyx_v_cache_skips == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1793, __pyx_L7_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_cache_skips, __pyx_v_frame_cache_key, __pyx_int_1) < 0)) __PYX_ERR(0, 1793, __pyx_L7_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1795 + * cache_skips[frame_cache_key] = 1 + * + * if is_stepping and additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: # <<<<<<<<<<<<<< + * notify_skipped_step_in_because_of_filters(py_db, frame) + * + */ + __pyx_t_12 = (__pyx_v_is_stepping != 0); + if (__pyx_t_12) { + } else { + __pyx_t_7 = __pyx_t_12; + goto __pyx_L39_bool_binop_done; + } + switch (__pyx_v_additional_info->pydev_original_step_cmd) { + case 0x6B: + case 0x90: + __pyx_t_12 = 1; + break; + default: + __pyx_t_12 = 0; + break; + } + __pyx_t_13 = (__pyx_t_12 != 0); + if (__pyx_t_13) { + } else { + __pyx_t_7 = __pyx_t_13; + goto __pyx_L39_bool_binop_done; + } + __pyx_t_13 = __Pyx_PyObject_IsTrue(__pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 1795, __pyx_L7_error) + __pyx_t_12 = ((!__pyx_t_13) != 0); + __pyx_t_7 = __pyx_t_12; + __pyx_L39_bool_binop_done:; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1796 + * + * if is_stepping and additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: + * notify_skipped_step_in_because_of_filters(py_db, frame) # <<<<<<<<<<<<<< + * + * # A little gotcha, sometimes when we're stepping in we have to stop in a + */ + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_notify_skipped_step_in_because_o); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1796, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_py_db, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1796, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_py_db, __pyx_v_frame}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1796, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_3 = PyTuple_New(2+__pyx_t_11); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1796, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_3); + if (__pyx_t_6) { + __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_6); __pyx_t_6 = NULL; + } + __Pyx_INCREF(__pyx_v_py_db); + __Pyx_GIVEREF(__pyx_v_py_db); + PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_11, __pyx_v_py_db); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_11, __pyx_v_frame); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1796, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1795 + * cache_skips[frame_cache_key] = 1 + * + * if is_stepping and additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: # <<<<<<<<<<<<<< + * notify_skipped_step_in_because_of_filters(py_db, frame) + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1801 + * # return event showing the back frame as the current frame, so, we need + * # to check not only the current frame but the back frame too. + * back_frame = frame.f_back # <<<<<<<<<<<<<< + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + * if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1801, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_XDECREF_SET(__pyx_v_back_frame, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1802 + * # to check not only the current frame but the back frame too. + * back_frame = frame.f_back + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): # <<<<<<<<<<<<<< + * if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): + * back_frame_cache_key = back_frame.f_code + */ + __pyx_t_12 = (__pyx_v_back_frame != Py_None); + __pyx_t_13 = (__pyx_t_12 != 0); + if (__pyx_t_13) { + } else { + __pyx_t_7 = __pyx_t_13; + goto __pyx_L43_bool_binop_done; + } + switch (__pyx_v_pydev_step_cmd) { + case 0x6B: + case 0x90: + case 0x6D: + case 0xA0: + __pyx_t_13 = 1; + break; + default: + __pyx_t_13 = 0; + break; + } + __pyx_t_12 = (__pyx_t_13 != 0); + __pyx_t_7 = __pyx_t_12; + __pyx_L43_bool_binop_done:; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1803 + * back_frame = frame.f_back + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + * if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): # <<<<<<<<<<<<<< + * back_frame_cache_key = back_frame.f_code + * cache_skips[back_frame_cache_key] = 1 + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_apply_files_filter); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1803, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_back_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1803, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_co_filename); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1803, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_3, __pyx_v_back_frame, __pyx_t_6, Py_False}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1803, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_3, __pyx_v_back_frame, __pyx_t_6, Py_False}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1803, __pyx_L7_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } else + #endif + { + __pyx_t_5 = PyTuple_New(3+__pyx_t_11); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1803, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_5); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_back_frame); + __Pyx_GIVEREF(__pyx_v_back_frame); + PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_11, __pyx_v_back_frame); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_11, __pyx_t_6); + __Pyx_INCREF(Py_False); + __Pyx_GIVEREF(Py_False); + PyTuple_SET_ITEM(__pyx_t_5, 2+__pyx_t_11, Py_False); + __pyx_t_6 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1803, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1803, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1804 + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + * if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): + * back_frame_cache_key = back_frame.f_code # <<<<<<<<<<<<<< + * cache_skips[back_frame_cache_key] = 1 + * # if DEBUG: print('skipped: trace_dispatch (filtered out: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_back_frame, __pyx_n_s_f_code); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1804, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_XDECREF_SET(__pyx_v_back_frame_cache_key, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1805 + * if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): + * back_frame_cache_key = back_frame.f_code + * cache_skips[back_frame_cache_key] = 1 # <<<<<<<<<<<<<< + * # if DEBUG: print('skipped: trace_dispatch (filtered out: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE + */ + if (unlikely(__pyx_v_cache_skips == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1805, __pyx_L7_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_cache_skips, __pyx_v_back_frame_cache_key, __pyx_int_1) < 0)) __PYX_ERR(0, 1805, __pyx_L7_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1807 + * cache_skips[back_frame_cache_key] = 1 + * # if DEBUG: print('skipped: trace_dispatch (filtered out: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * else: + * # if DEBUG: print('skipped: trace_dispatch (filtered out: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1807, __pyx_L7_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1807, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __pyx_t_4; + __pyx_t_4 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1803 + * back_frame = frame.f_back + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + * if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): # <<<<<<<<<<<<<< + * back_frame_cache_key = back_frame.f_code + * cache_skips[back_frame_cache_key] = 1 + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1802 + * # to check not only the current frame but the back frame too. + * back_frame = frame.f_back + * if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): # <<<<<<<<<<<<<< + * if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): + * back_frame_cache_key = back_frame.f_code + */ + goto __pyx_L42; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1810 + * else: + * # if DEBUG: print('skipped: trace_dispatch (filtered out: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * + * # if DEBUG: print('trace_dispatch', filename, frame.f_lineno, event, frame.f_code.co_name, file_type) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1810, __pyx_L7_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1810, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __pyx_t_4; + __pyx_t_4 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + } + __pyx_L42:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1792 + * + * if py_db.is_files_filter_enabled: + * if py_db.apply_files_filter(frame, abs_path_canonical_path_and_base[0], False): # <<<<<<<<<<<<<< + * cache_skips[frame_cache_key] = 1 + * + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1791 + * return None if event == 'call' else NO_FTRACE + * + * if py_db.is_files_filter_enabled: # <<<<<<<<<<<<<< + * if py_db.apply_files_filter(frame, abs_path_canonical_path_and_base[0], False): + * cache_skips[frame_cache_key] = 1 + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1818 + * ret = PyDBFrame( + * ( + * py_db, abs_path_canonical_path_and_base, additional_info, t, frame_skips_cache, frame_cache_key, # <<<<<<<<<<<<<< + * ) + * ).trace_dispatch(frame, event, arg) + */ + __pyx_t_1 = PyTuple_New(6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1818, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_py_db); + __Pyx_GIVEREF(__pyx_v_py_db); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_py_db); + __Pyx_INCREF(__pyx_v_abs_path_canonical_path_and_base); + __Pyx_GIVEREF(__pyx_v_abs_path_canonical_path_and_base); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_abs_path_canonical_path_and_base); + __Pyx_INCREF(((PyObject *)__pyx_v_additional_info)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_additional_info)); + PyTuple_SET_ITEM(__pyx_t_1, 2, ((PyObject *)__pyx_v_additional_info)); + __Pyx_INCREF(__pyx_v_t); + __Pyx_GIVEREF(__pyx_v_t); + PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_t); + __Pyx_INCREF(__pyx_v_frame_skips_cache); + __Pyx_GIVEREF(__pyx_v_frame_skips_cache); + PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_v_frame_skips_cache); + __Pyx_INCREF(__pyx_v_frame_cache_key); + __Pyx_GIVEREF(__pyx_v_frame_cache_key); + PyTuple_SET_ITEM(__pyx_t_1, 5, __pyx_v_frame_cache_key); + + /* "_pydevd_bundle/pydevd_cython.pyx":1816 + * # Just create PyDBFrame directly (removed support for Python versions < 2.5, which required keeping a weak + * # reference to the frame). + * ret = PyDBFrame( # <<<<<<<<<<<<<< + * ( + * py_db, abs_path_canonical_path_and_base, additional_info, t, frame_skips_cache, frame_cache_key, + */ + __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBFrame), __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1816, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1820 + * py_db, abs_path_canonical_path_and_base, additional_info, t, frame_skips_cache, frame_cache_key, + * ) + * ).trace_dispatch(frame, event, arg) # <<<<<<<<<<<<<< + * if ret is None: + * # 1 means skipped because of filters. + */ + if (!(likely(PyString_CheckExact(__pyx_v_event))||((__pyx_v_event) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_v_event)->tp_name), 0))) __PYX_ERR(0, 1820, __pyx_L7_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_t_4)->__pyx_vtab)->trace_dispatch(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_t_4), __pyx_v_frame, ((PyObject*)__pyx_v_event), __pyx_v_arg, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1820, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_ret = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1821 + * ) + * ).trace_dispatch(frame, event, arg) + * if ret is None: # <<<<<<<<<<<<<< + * # 1 means skipped because of filters. + * # 2 means skipped because no breakpoints were hit. + */ + __pyx_t_7 = (__pyx_v_ret == Py_None); + __pyx_t_12 = (__pyx_t_7 != 0); + if (__pyx_t_12) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1824 + * # 1 means skipped because of filters. + * # 2 means skipped because no breakpoints were hit. + * cache_skips[frame_cache_key] = 2 # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * + */ + if (unlikely(__pyx_v_cache_skips == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 1824, __pyx_L7_error) + } + if (unlikely(PyDict_SetItem(__pyx_v_cache_skips, __pyx_v_frame_cache_key, __pyx_int_2) < 0)) __PYX_ERR(0, 1824, __pyx_L7_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1825 + * # 2 means skipped because no breakpoints were hit. + * cache_skips[frame_cache_key] = 2 + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_12 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 1825, __pyx_L7_error) + if (__pyx_t_12) { + __Pyx_INCREF(Py_None); + __pyx_t_1 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1825, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __pyx_t_4; + __pyx_t_4 = 0; + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1821 + * ) + * ).trace_dispatch(frame, event, arg) + * if ret is None: # <<<<<<<<<<<<<< + * # 1 means skipped because of filters. + * # 2 means skipped because no breakpoints were hit. + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1828 + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * frame.f_trace = SafeCallWrapper(ret) # Make sure we keep the returned tracer. # <<<<<<<<<<<<<< + * # ELSE + * # frame.f_trace = ret # Make sure we keep the returned tracer. + */ + __pyx_t_1 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper), __pyx_v_ret); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1828, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_1) < 0) __PYX_ERR(0, 1828, __pyx_L7_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1832 + * # frame.f_trace = ret # Make sure we keep the returned tracer. + * # ENDIF + * return ret # <<<<<<<<<<<<<< + * + * except SystemExit: + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_ret); + __pyx_r = __pyx_v_ret; + goto __pyx_L11_try_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1737 + * + * additional_info.is_tracing += 1 + * try: # <<<<<<<<<<<<<< + * pydev_step_cmd = additional_info.pydev_step_cmd + * is_stepping = pydev_step_cmd != -1 + */ + } + __pyx_L7_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1834 + * return ret + * + * except SystemExit: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE + * + */ + __pyx_t_11 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_SystemExit); + if (__pyx_t_11) { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_4, &__pyx_t_5) < 0) __PYX_ERR(0, 1834, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_5); + + /* "_pydevd_bundle/pydevd_cython.pyx":1835 + * + * except SystemExit: + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * + * except Exception: + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_12 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 1835, __pyx_L9_except_error) + if (__pyx_t_12) { + __Pyx_INCREF(Py_None); + __pyx_t_6 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1835, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __pyx_t_3; + __pyx_t_3 = 0; + } + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L10_except_return; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1837 + * return None if event == 'call' else NO_FTRACE + * + * except Exception: # <<<<<<<<<<<<<< + * if py_db.pydb_disposed: + * return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. + */ + __pyx_t_11 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); + if (__pyx_t_11) { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_4, &__pyx_t_1) < 0) __PYX_ERR(0, 1837, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_1); + + /* "_pydevd_bundle/pydevd_cython.pyx":1838 + * + * except Exception: + * if py_db.pydb_disposed: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. + * # Log it + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_py_db, __pyx_n_s_pydb_disposed); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1838, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_12 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 1838, __pyx_L9_except_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (__pyx_t_12) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1839 + * except Exception: + * if py_db.pydb_disposed: + * return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. # <<<<<<<<<<<<<< + * # Log it + * try: + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_12 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_12 < 0)) __PYX_ERR(0, 1839, __pyx_L9_except_error) + if (__pyx_t_12) { + __Pyx_INCREF(Py_None); + __pyx_t_6 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1839, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __pyx_t_3; + __pyx_t_3 = 0; + } + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L10_except_return; + + /* "_pydevd_bundle/pydevd_cython.pyx":1838 + * + * except Exception: + * if py_db.pydb_disposed: # <<<<<<<<<<<<<< + * return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. + * # Log it + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1841 + * return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. + * # Log it + * try: # <<<<<<<<<<<<<< + * if pydev_log_exception is not None: + * # This can actually happen during the interpreter shutdown in Python 2.7 + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_16, &__pyx_t_15, &__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_14); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":1842 + * # Log it + * try: + * if pydev_log_exception is not None: # <<<<<<<<<<<<<< + * # This can actually happen during the interpreter shutdown in Python 2.7 + * pydev_log_exception() + */ + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pydev_log_exception); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1842, __pyx_L52_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_12 = (__pyx_t_6 != Py_None); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_7 = (__pyx_t_12 != 0); + if (__pyx_t_7) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1844 + * if pydev_log_exception is not None: + * # This can actually happen during the interpreter shutdown in Python 2.7 + * pydev_log_exception() # <<<<<<<<<<<<<< + * except: + * # Error logging? We're really in the interpreter shutdown... + */ + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_pydev_log_exception); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1844, __pyx_L52_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_6 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1844, __pyx_L52_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1842 + * # Log it + * try: + * if pydev_log_exception is not None: # <<<<<<<<<<<<<< + * # This can actually happen during the interpreter shutdown in Python 2.7 + * pydev_log_exception() + */ + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1841 + * return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. + * # Log it + * try: # <<<<<<<<<<<<<< + * if pydev_log_exception is not None: + * # This can actually happen during the interpreter shutdown in Python 2.7 + */ + } + __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + goto __pyx_L59_try_end; + __pyx_L52_error:; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1845 + * # This can actually happen during the interpreter shutdown in Python 2.7 + * pydev_log_exception() + * except: # <<<<<<<<<<<<<< + * # Error logging? We're really in the interpreter shutdown... + * # (https://github.com/fabioz/PyDev.Debugger/issues/8) + */ + /*except:*/ { + __Pyx_ErrRestore(0,0,0); + goto __pyx_L53_exception_handled; + } + __pyx_L53_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_ExceptionReset(__pyx_t_16, __pyx_t_15, __pyx_t_14); + __pyx_L59_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1849 + * # (https://github.com/fabioz/PyDev.Debugger/issues/8) + * pass + * return None if event == 'call' else NO_FTRACE # <<<<<<<<<<<<<< + * finally: + * additional_info.is_tracing -= 1 + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1849, __pyx_L9_except_error) + if (__pyx_t_7) { + __Pyx_INCREF(Py_None); + __pyx_t_6 = Py_None; + } else { + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1849, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __pyx_t_3; + __pyx_t_3 = 0; + } + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L10_except_return; + } + goto __pyx_L9_except_error; + __pyx_L9_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":1737 + * + * additional_info.is_tracing += 1 + * try: # <<<<<<<<<<<<<< + * pydev_step_cmd = additional_info.pydev_step_cmd + * is_stepping = pydev_step_cmd != -1 + */ + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_ExceptionReset(__pyx_t_8, __pyx_t_9, __pyx_t_10); + goto __pyx_L5_error; + __pyx_L11_try_return:; + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_ExceptionReset(__pyx_t_8, __pyx_t_9, __pyx_t_10); + goto __pyx_L4_return; + __pyx_L10_except_return:; + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_ExceptionReset(__pyx_t_8, __pyx_t_9, __pyx_t_10); + goto __pyx_L4_return; + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1851 + * return None if event == 'call' else NO_FTRACE + * finally: + * additional_info.is_tracing -= 1 # <<<<<<<<<<<<<< + * + * + */ + /*finally:*/ { + __pyx_L5_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_10 = 0; __pyx_t_9 = 0; __pyx_t_8 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_9); + __Pyx_XGOTREF(__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __pyx_t_11 = __pyx_lineno; __pyx_t_17 = __pyx_clineno; __pyx_t_18 = __pyx_filename; + { + __pyx_v_additional_info->is_tracing = (__pyx_v_additional_info->is_tracing - 1); + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_14, __pyx_t_15, __pyx_t_16); + } + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_ErrRestore(__pyx_t_10, __pyx_t_9, __pyx_t_8); + __pyx_t_10 = 0; __pyx_t_9 = 0; __pyx_t_8 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; + __pyx_lineno = __pyx_t_11; __pyx_clineno = __pyx_t_17; __pyx_filename = __pyx_t_18; + goto __pyx_L1_error; + } + __pyx_L4_return: { + __pyx_t_16 = __pyx_r; + __pyx_r = 0; + __pyx_v_additional_info->is_tracing = (__pyx_v_additional_info->is_tracing - 1); + __pyx_r = __pyx_t_16; + __pyx_t_16 = 0; + goto __pyx_L0; + } + } + + /* "_pydevd_bundle/pydevd_cython.pyx":1706 + * # ENDIF + * + * def __call__(self, frame, event, arg): # <<<<<<<<<<<<<< + * ''' This is the callback used when we enter some context in the debugger. + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_frame_cache_key); + __Pyx_XDECREF(__pyx_v_cache_skips); + __Pyx_XDECREF(__pyx_v_abs_path_canonical_path_and_base); + __Pyx_XDECREF((PyObject *)__pyx_v_additional_info); + __Pyx_XDECREF(__pyx_v_py_db); + __Pyx_XDECREF(__pyx_v_t); + __Pyx_XDECREF(__pyx_v_frame_skips_cache); + __Pyx_XDECREF(__pyx_v_back_frame); + __Pyx_XDECREF(__pyx_v_back_frame_cache_key); + __Pyx_XDECREF(__pyx_v_file_type); + __Pyx_XDECREF(__pyx_v_ret); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1696 + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef class ThreadTracer: + * cdef public tuple _args; # <<<<<<<<<<<<<< + * def __init__(self, tuple args): + * self._args = args + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args___get__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args___get__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->_args); + __pyx_r = __pyx_v_self->_args; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_2__set__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_2__set__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyTuple_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 1696, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer._args.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_4__del__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_4__del__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_args); + __Pyx_DECREF(__pyx_v_self->_args); + __pyx_v_self->_args = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_4__reduce_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_4__reduce_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self._args,) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_self->_args); + __Pyx_GIVEREF(__pyx_v_self->_args); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->_args); + __pyx_v_state = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self._args,) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v__dict = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":7 + * state = (self._args,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_2 = (__pyx_v__dict != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict); + __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self._args is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self._args,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self._args is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, None), state + */ + /*else*/ { + __pyx_t_3 = (__pyx_v_self->_args != ((PyObject*)Py_None)); + __pyx_v_use_setstate = __pyx_t_3; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self._args is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, None), state + * else: + */ + __pyx_t_3 = (__pyx_v_use_setstate != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":13 + * use_setstate = self._args is not None + * if use_setstate: + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_ThreadTracer); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_64458794); + __Pyx_GIVEREF(__pyx_int_64458794); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_64458794); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None); + __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state); + __pyx_t_4 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self._args is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, None), state + * else: + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_ThreadTracer__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle_ThreadTracer); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_64458794); + __Pyx_GIVEREF(__pyx_int_64458794); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_64458794); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1); + __pyx_t_5 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_ThreadTracer__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_6__setstate_cython__(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_6__setstate_cython__(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_ThreadTracer__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_ThreadTracer__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_ThreadTracer, (type(self), 0x3d7902a, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_ThreadTracer__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.ThreadTracer.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_bundle/pydevd_cython.pyx":1866 + * _original_call = ThreadTracer.__call__ + * + * def __call__(self, frame, event, arg): # <<<<<<<<<<<<<< + * constructed_tid_to_last_frame[self._args[1].ident] = frame + * return _original_call(self, frame, event, arg) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_11__call__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_11__call__ = {"__call__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_11__call__, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_11__call__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_event = 0; + PyObject *__pyx_v_arg = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__call__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_frame,&__pyx_n_s_event,&__pyx_n_s_arg,0}; + PyObject* values[4] = {0,0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + CYTHON_FALLTHROUGH; + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__call__", 1, 4, 4, 1); __PYX_ERR(0, 1866, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__call__", 1, 4, 4, 2); __PYX_ERR(0, 1866, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 3: + if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arg)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__call__", 1, 4, 4, 3); __PYX_ERR(0, 1866, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__call__") < 0)) __PYX_ERR(0, 1866, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 4) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + } + __pyx_v_self = values[0]; + __pyx_v_frame = values[1]; + __pyx_v_event = values[2]; + __pyx_v_arg = values[3]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__call__", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1866, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_10__call__(__pyx_self, __pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_10__call__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__call__", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":1867 + * + * def __call__(self, frame, event, arg): + * constructed_tid_to_last_frame[self._args[1].ident] = frame # <<<<<<<<<<<<<< + * return _original_call(self, frame, event, arg) + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_constructed_tid_to_last_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1867, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_args_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1867, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_2, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1867, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_ident); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1867, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(PyObject_SetItem(__pyx_t_1, __pyx_t_2, __pyx_v_frame) < 0)) __PYX_ERR(0, 1867, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1868 + * def __call__(self, frame, event, arg): + * constructed_tid_to_last_frame[self._args[1].ident] = frame + * return _original_call(self, frame, event, arg) # <<<<<<<<<<<<<< + * + * ThreadTracer.__call__ = __call__ + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_original_call); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1868, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = NULL; + __pyx_t_4 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + __pyx_t_4 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[5] = {__pyx_t_3, __pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_4, 4+__pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1868, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_2); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[5] = {__pyx_t_3, __pyx_v_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_4, 4+__pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1868, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_2); + } else + #endif + { + __pyx_t_5 = PyTuple_New(4+__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1868, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_self); + __Pyx_GIVEREF(__pyx_v_self); + PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_4, __pyx_v_self); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_4, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_5, 2+__pyx_t_4, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_5, 3+__pyx_t_4, __pyx_v_arg); + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1868, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1866 + * _original_call = ThreadTracer.__call__ + * + * def __call__(self, frame, event, arg): # <<<<<<<<<<<<<< + * constructed_tid_to_last_frame[self._args[1].ident] = frame + * return _original_call(self, frame, event, arg) + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle_PyDBAdditionalThreadInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_13__pyx_unpickle_PyDBAdditionalThreadInfo(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_13__pyx_unpickle_PyDBAdditionalThreadInfo = {"__pyx_unpickle_PyDBAdditionalThreadInfo", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_13__pyx_unpickle_PyDBAdditionalThreadInfo, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_13__pyx_unpickle_PyDBAdditionalThreadInfo(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_PyDBAdditionalThreadInfo (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_PyDBAdditionalThreadInfo", 1, 3, 3, 1); __PYX_ERR(2, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_PyDBAdditionalThreadInfo", 1, 3, 3, 2); __PYX_ERR(2, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_PyDBAdditionalThreadInfo") < 0)) __PYX_ERR(2, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_PyDBAdditionalThreadInfo", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_PyDBAdditionalThreadInfo", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_12__pyx_unpickle_PyDBAdditionalThreadInfo(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_12__pyx_unpickle_PyDBAdditionalThreadInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_PyDBAdditionalThreadInfo", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x75b3b02, 0x5f02be1, 0xa5a0d63): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x75b3b02, 0x5f02be1, 0xa5a0d63) = (conditional_breakpoint_exception, is_tracing, pydev_call_from_jinja2, pydev_call_inside_jinja2, pydev_django_resolve_frame, pydev_func_name, pydev_message, pydev_next_line, pydev_notify_kill, pydev_original_step_cmd, pydev_smart_child_offset, pydev_smart_parent_offset, pydev_smart_step_into_variants, pydev_smart_step_stop, pydev_state, pydev_step_cmd, pydev_step_stop, pydev_use_scoped_step_frame, step_in_initial_location, suspend_type, suspended_at_unhandled, target_id_to_smart_step_into_variant, thread_tracer, top_level_thread_tracer_no_back_frames, top_level_thread_tracer_unhandled, trace_suspend_type))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__9, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0x75b3b02, 0x5f02be1, 0xa5a0d63): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x75b3b02, 0x5f02be1, 0xa5a0d63) = (conditional_breakpoint_exception, is_tracing, pydev_call_from_jinja2, pydev_call_inside_jinja2, pydev_django_resolve_frame, pydev_func_name, pydev_message, pydev_next_line, pydev_notify_kill, pydev_original_step_cmd, pydev_smart_child_offset, pydev_smart_parent_offset, pydev_smart_step_into_variants, pydev_smart_step_stop, pydev_state, pydev_step_cmd, pydev_step_stop, pydev_use_scoped_step_frame, step_in_initial_location, suspend_type, suspended_at_unhandled, target_id_to_smart_step_into_variant, thread_tracer, top_level_thread_tracer_no_back_frames, top_level_thread_tracer_unhandled, trace_suspend_type))" % __pyx_checksum) + * __pyx_result = PyDBAdditionalThreadInfo.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0x75b3b02, 0x5f02be1, 0xa5a0d63): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x75b3b02, 0x5f02be1, 0xa5a0d63) = (conditional_breakpoint_exception, is_tracing, pydev_call_from_jinja2, pydev_call_inside_jinja2, pydev_django_resolve_frame, pydev_func_name, pydev_message, pydev_next_line, pydev_notify_kill, pydev_original_step_cmd, pydev_smart_child_offset, pydev_smart_parent_offset, pydev_smart_step_into_variants, pydev_smart_step_stop, pydev_state, pydev_step_cmd, pydev_step_stop, pydev_use_scoped_step_frame, step_in_initial_location, suspend_type, suspended_at_unhandled, target_id_to_smart_step_into_variant, thread_tracer, top_level_thread_tracer_no_back_frames, top_level_thread_tracer_unhandled, trace_suspend_type))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = PyDBAdditionalThreadInfo.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(2, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x75b3b02, 0x5f02be1, 0xa5a0d63): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x75b3b02, 0x5f02be1, 0xa5a0d63) = (conditional_breakpoint_exception, is_tracing, pydev_call_from_jinja2, pydev_call_inside_jinja2, pydev_django_resolve_frame, pydev_func_name, pydev_message, pydev_next_line, pydev_notify_kill, pydev_original_step_cmd, pydev_smart_child_offset, pydev_smart_parent_offset, pydev_smart_step_into_variants, pydev_smart_step_stop, pydev_state, pydev_step_cmd, pydev_step_stop, pydev_use_scoped_step_frame, step_in_initial_location, suspend_type, suspended_at_unhandled, target_id_to_smart_step_into_variant, thread_tracer, top_level_thread_tracer_no_back_frames, top_level_thread_tracer_unhandled, trace_suspend_type))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x75b3b02, 0x5f02be1, 0xa5a0d63) = (conditional_breakpoint_exception, is_tracing, pydev_call_from_jinja2, pydev_call_inside_jinja2, pydev_django_resolve_frame, pydev_func_name, pydev_message, pydev_next_line, pydev_notify_kill, pydev_original_step_cmd, pydev_smart_child_offset, pydev_smart_parent_offset, pydev_smart_step_into_variants, pydev_smart_step_stop, pydev_state, pydev_step_cmd, pydev_step_stop, pydev_use_scoped_step_frame, step_in_initial_location, suspend_type, suspended_at_unhandled, target_id_to_smart_step_into_variant, thread_tracer, top_level_thread_tracer_no_back_frames, top_level_thread_tracer_unhandled, trace_suspend_type))" % __pyx_checksum) + * __pyx_result = PyDBAdditionalThreadInfo.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state( __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x75b3b02, 0x5f02be1, 0xa5a0d63) = (conditional_breakpoint_exception, is_tracing, pydev_call_from_jinja2, pydev_call_inside_jinja2, pydev_django_resolve_frame, pydev_func_name, pydev_message, pydev_next_line, pydev_notify_kill, pydev_original_step_cmd, pydev_smart_child_offset, pydev_smart_parent_offset, pydev_smart_step_into_variants, pydev_smart_step_stop, pydev_state, pydev_step_cmd, pydev_step_stop, pydev_use_scoped_step_frame, step_in_initial_location, suspend_type, suspended_at_unhandled, target_id_to_smart_step_into_variant, thread_tracer, top_level_thread_tracer_no_back_frames, top_level_thread_tracer_unhandled, trace_suspend_type))" % __pyx_checksum) + * __pyx_result = PyDBAdditionalThreadInfo.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = PyDBAdditionalThreadInfo.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(PyDBAdditionalThreadInfo __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_PyDBAdditionalThreadInfo__set_state(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x75b3b02, 0x5f02be1, 0xa5a0d63) = (conditional_breakpoint_exception, is_tracing, pydev_call_from_jinja2, pydev_call_inside_jinja2, pydev_django_resolve_frame, pydev_func_name, pydev_message, pydev_next_line, pydev_notify_kill, pydev_original_step_cmd, pydev_smart_child_offset, pydev_smart_parent_offset, pydev_smart_step_into_variants, pydev_smart_step_stop, pydev_state, pydev_step_cmd, pydev_step_stop, pydev_use_scoped_step_frame, step_in_initial_location, suspend_type, suspended_at_unhandled, target_id_to_smart_step_into_variant, thread_tracer, top_level_thread_tracer_no_back_frames, top_level_thread_tracer_unhandled, trace_suspend_type))" % __pyx_checksum) + * __pyx_result = PyDBAdditionalThreadInfo.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(PyDBAdditionalThreadInfo __pyx_result, tuple __pyx_state): + * __pyx_result.conditional_breakpoint_exception = __pyx_state[0]; __pyx_result.is_tracing = __pyx_state[1]; __pyx_result.pydev_call_from_jinja2 = __pyx_state[2]; __pyx_result.pydev_call_inside_jinja2 = __pyx_state[3]; __pyx_result.pydev_django_resolve_frame = __pyx_state[4]; __pyx_result.pydev_func_name = __pyx_state[5]; __pyx_result.pydev_message = __pyx_state[6]; __pyx_result.pydev_next_line = __pyx_state[7]; __pyx_result.pydev_notify_kill = __pyx_state[8]; __pyx_result.pydev_original_step_cmd = __pyx_state[9]; __pyx_result.pydev_smart_child_offset = __pyx_state[10]; __pyx_result.pydev_smart_parent_offset = __pyx_state[11]; __pyx_result.pydev_smart_step_into_variants = __pyx_state[12]; __pyx_result.pydev_smart_step_stop = __pyx_state[13]; __pyx_result.pydev_state = __pyx_state[14]; __pyx_result.pydev_step_cmd = __pyx_state[15]; __pyx_result.pydev_step_stop = __pyx_state[16]; __pyx_result.pydev_use_scoped_step_frame = __pyx_state[17]; __pyx_result.step_in_initial_location = __pyx_state[18]; __pyx_result.suspend_type = __pyx_state[19]; __pyx_result.suspended_at_unhandled = __pyx_state[20]; __pyx_result.target_id_to_smart_step_into_variant = __pyx_state[21]; __pyx_result.thread_tracer = __pyx_state[22]; __pyx_result.top_level_thread_tracer_no_back_frames = __pyx_state[23]; __pyx_result.top_level_thread_tracer_unhandled = __pyx_state[24]; __pyx_result.trace_suspend_type = __pyx_state[25] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_PyDBAdditionalThreadInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_PyDBAdditionalThreadInfo", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(PyDBAdditionalThreadInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.conditional_breakpoint_exception = __pyx_state[0]; __pyx_result.is_tracing = __pyx_state[1]; __pyx_result.pydev_call_from_jinja2 = __pyx_state[2]; __pyx_result.pydev_call_inside_jinja2 = __pyx_state[3]; __pyx_result.pydev_django_resolve_frame = __pyx_state[4]; __pyx_result.pydev_func_name = __pyx_state[5]; __pyx_result.pydev_message = __pyx_state[6]; __pyx_result.pydev_next_line = __pyx_state[7]; __pyx_result.pydev_notify_kill = __pyx_state[8]; __pyx_result.pydev_original_step_cmd = __pyx_state[9]; __pyx_result.pydev_smart_child_offset = __pyx_state[10]; __pyx_result.pydev_smart_parent_offset = __pyx_state[11]; __pyx_result.pydev_smart_step_into_variants = __pyx_state[12]; __pyx_result.pydev_smart_step_stop = __pyx_state[13]; __pyx_result.pydev_state = __pyx_state[14]; __pyx_result.pydev_step_cmd = __pyx_state[15]; __pyx_result.pydev_step_stop = __pyx_state[16]; __pyx_result.pydev_use_scoped_step_frame = __pyx_state[17]; __pyx_result.step_in_initial_location = __pyx_state[18]; __pyx_result.suspend_type = __pyx_state[19]; __pyx_result.suspended_at_unhandled = __pyx_state[20]; __pyx_result.target_id_to_smart_step_into_variant = __pyx_state[21]; __pyx_result.thread_tracer = __pyx_state[22]; __pyx_result.top_level_thread_tracer_no_back_frames = __pyx_state[23]; __pyx_result.top_level_thread_tracer_unhandled = __pyx_state[24]; __pyx_result.trace_suspend_type = __pyx_state[25] + * if len(__pyx_state) > 26 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_PyDBAdditionalThreadInfo__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + Py_ssize_t __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_PyDBAdditionalThreadInfo__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(PyDBAdditionalThreadInfo __pyx_result, tuple __pyx_state): + * __pyx_result.conditional_breakpoint_exception = __pyx_state[0]; __pyx_result.is_tracing = __pyx_state[1]; __pyx_result.pydev_call_from_jinja2 = __pyx_state[2]; __pyx_result.pydev_call_inside_jinja2 = __pyx_state[3]; __pyx_result.pydev_django_resolve_frame = __pyx_state[4]; __pyx_result.pydev_func_name = __pyx_state[5]; __pyx_result.pydev_message = __pyx_state[6]; __pyx_result.pydev_next_line = __pyx_state[7]; __pyx_result.pydev_notify_kill = __pyx_state[8]; __pyx_result.pydev_original_step_cmd = __pyx_state[9]; __pyx_result.pydev_smart_child_offset = __pyx_state[10]; __pyx_result.pydev_smart_parent_offset = __pyx_state[11]; __pyx_result.pydev_smart_step_into_variants = __pyx_state[12]; __pyx_result.pydev_smart_step_stop = __pyx_state[13]; __pyx_result.pydev_state = __pyx_state[14]; __pyx_result.pydev_step_cmd = __pyx_state[15]; __pyx_result.pydev_step_stop = __pyx_state[16]; __pyx_result.pydev_use_scoped_step_frame = __pyx_state[17]; __pyx_result.step_in_initial_location = __pyx_state[18]; __pyx_result.suspend_type = __pyx_state[19]; __pyx_result.suspended_at_unhandled = __pyx_state[20]; __pyx_result.target_id_to_smart_step_into_variant = __pyx_state[21]; __pyx_result.thread_tracer = __pyx_state[22]; __pyx_result.top_level_thread_tracer_no_back_frames = __pyx_state[23]; __pyx_result.top_level_thread_tracer_unhandled = __pyx_state[24]; __pyx_result.trace_suspend_type = __pyx_state[25] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 26 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[26]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->conditional_breakpoint_exception); + __Pyx_DECREF(__pyx_v___pyx_result->conditional_breakpoint_exception); + __pyx_v___pyx_result->conditional_breakpoint_exception = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->is_tracing = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->pydev_call_from_jinja2); + __Pyx_DECREF(__pyx_v___pyx_result->pydev_call_from_jinja2); + __pyx_v___pyx_result->pydev_call_from_jinja2 = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->pydev_call_inside_jinja2); + __Pyx_DECREF(__pyx_v___pyx_result->pydev_call_inside_jinja2); + __pyx_v___pyx_result->pydev_call_inside_jinja2 = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 4, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_django_resolve_frame = __pyx_t_3; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 5, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->pydev_func_name); + __Pyx_DECREF(__pyx_v___pyx_result->pydev_func_name); + __pyx_v___pyx_result->pydev_func_name = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 6, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->pydev_message); + __Pyx_DECREF(__pyx_v___pyx_result->pydev_message); + __pyx_v___pyx_result->pydev_message = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 7, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_next_line = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 8, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_notify_kill = __pyx_t_3; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 9, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_original_step_cmd = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 10, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_smart_child_offset = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 11, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_smart_parent_offset = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 12, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->pydev_smart_step_into_variants); + __Pyx_DECREF(__pyx_v___pyx_result->pydev_smart_step_into_variants); + __pyx_v___pyx_result->pydev_smart_step_into_variants = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 13, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->pydev_smart_step_stop); + __Pyx_DECREF(__pyx_v___pyx_result->pydev_smart_step_stop); + __pyx_v___pyx_result->pydev_smart_step_stop = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 14, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_state = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 15, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_step_cmd = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 16, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->pydev_step_stop); + __Pyx_DECREF(__pyx_v___pyx_result->pydev_step_stop); + __pyx_v___pyx_result->pydev_step_stop = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 17, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->pydev_use_scoped_step_frame = __pyx_t_3; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 18, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->step_in_initial_location); + __Pyx_DECREF(__pyx_v___pyx_result->step_in_initial_location); + __pyx_v___pyx_result->step_in_initial_location = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 19, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->suspend_type = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 20, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->suspended_at_unhandled = __pyx_t_3; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 21, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyDict_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->target_id_to_smart_step_into_variant); + __Pyx_DECREF(__pyx_v___pyx_result->target_id_to_smart_step_into_variant); + __pyx_v___pyx_result->target_id_to_smart_step_into_variant = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 22, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->thread_tracer); + __Pyx_DECREF(__pyx_v___pyx_result->thread_tracer); + __pyx_v___pyx_result->thread_tracer = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 23, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->top_level_thread_tracer_no_back_frames); + __Pyx_DECREF(__pyx_v___pyx_result->top_level_thread_tracer_no_back_frames); + __pyx_v___pyx_result->top_level_thread_tracer_no_back_frames = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 24, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->top_level_thread_tracer_unhandled); + __Pyx_DECREF(__pyx_v___pyx_result->top_level_thread_tracer_unhandled); + __pyx_v___pyx_result->top_level_thread_tracer_unhandled = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 25, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->trace_suspend_type); + __Pyx_DECREF(__pyx_v___pyx_result->trace_suspend_type); + __pyx_v___pyx_result->trace_suspend_type = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(PyDBAdditionalThreadInfo __pyx_result, tuple __pyx_state): + * __pyx_result.conditional_breakpoint_exception = __pyx_state[0]; __pyx_result.is_tracing = __pyx_state[1]; __pyx_result.pydev_call_from_jinja2 = __pyx_state[2]; __pyx_result.pydev_call_inside_jinja2 = __pyx_state[3]; __pyx_result.pydev_django_resolve_frame = __pyx_state[4]; __pyx_result.pydev_func_name = __pyx_state[5]; __pyx_result.pydev_message = __pyx_state[6]; __pyx_result.pydev_next_line = __pyx_state[7]; __pyx_result.pydev_notify_kill = __pyx_state[8]; __pyx_result.pydev_original_step_cmd = __pyx_state[9]; __pyx_result.pydev_smart_child_offset = __pyx_state[10]; __pyx_result.pydev_smart_parent_offset = __pyx_state[11]; __pyx_result.pydev_smart_step_into_variants = __pyx_state[12]; __pyx_result.pydev_smart_step_stop = __pyx_state[13]; __pyx_result.pydev_state = __pyx_state[14]; __pyx_result.pydev_step_cmd = __pyx_state[15]; __pyx_result.pydev_step_stop = __pyx_state[16]; __pyx_result.pydev_use_scoped_step_frame = __pyx_state[17]; __pyx_result.step_in_initial_location = __pyx_state[18]; __pyx_result.suspend_type = __pyx_state[19]; __pyx_result.suspended_at_unhandled = __pyx_state[20]; __pyx_result.target_id_to_smart_step_into_variant = __pyx_state[21]; __pyx_result.thread_tracer = __pyx_state[22]; __pyx_result.top_level_thread_tracer_no_back_frames = __pyx_state[23]; __pyx_result.top_level_thread_tracer_unhandled = __pyx_state[24]; __pyx_result.trace_suspend_type = __pyx_state[25] + * if len(__pyx_state) > 26 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[26]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(2, 13, __pyx_L1_error) + } + __pyx_t_4 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_5 = ((__pyx_t_4 > 26) != 0); + if (__pyx_t_5) { + } else { + __pyx_t_3 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_6 = (__pyx_t_5 != 0); + __pyx_t_3 = __pyx_t_6; + __pyx_L4_bool_binop_done:; + if (__pyx_t_3) { + + /* "(tree fragment)":14 + * __pyx_result.conditional_breakpoint_exception = __pyx_state[0]; __pyx_result.is_tracing = __pyx_state[1]; __pyx_result.pydev_call_from_jinja2 = __pyx_state[2]; __pyx_result.pydev_call_inside_jinja2 = __pyx_state[3]; __pyx_result.pydev_django_resolve_frame = __pyx_state[4]; __pyx_result.pydev_func_name = __pyx_state[5]; __pyx_result.pydev_message = __pyx_state[6]; __pyx_result.pydev_next_line = __pyx_state[7]; __pyx_result.pydev_notify_kill = __pyx_state[8]; __pyx_result.pydev_original_step_cmd = __pyx_state[9]; __pyx_result.pydev_smart_child_offset = __pyx_state[10]; __pyx_result.pydev_smart_parent_offset = __pyx_state[11]; __pyx_result.pydev_smart_step_into_variants = __pyx_state[12]; __pyx_result.pydev_smart_step_stop = __pyx_state[13]; __pyx_result.pydev_state = __pyx_state[14]; __pyx_result.pydev_step_cmd = __pyx_state[15]; __pyx_result.pydev_step_stop = __pyx_state[16]; __pyx_result.pydev_use_scoped_step_frame = __pyx_state[17]; __pyx_result.step_in_initial_location = __pyx_state[18]; __pyx_result.suspend_type = __pyx_state[19]; __pyx_result.suspended_at_unhandled = __pyx_state[20]; __pyx_result.target_id_to_smart_step_into_variant = __pyx_state[21]; __pyx_result.thread_tracer = __pyx_state[22]; __pyx_result.top_level_thread_tracer_no_back_frames = __pyx_state[23]; __pyx_result.top_level_thread_tracer_unhandled = __pyx_state[24]; __pyx_result.trace_suspend_type = __pyx_state[25] + * if len(__pyx_state) > 26 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[26]) # <<<<<<<<<<<<<< + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_update); if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 14, __pyx_L1_error) + } + __pyx_t_7 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 26, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_9, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(PyDBAdditionalThreadInfo __pyx_result, tuple __pyx_state): + * __pyx_result.conditional_breakpoint_exception = __pyx_state[0]; __pyx_result.is_tracing = __pyx_state[1]; __pyx_result.pydev_call_from_jinja2 = __pyx_state[2]; __pyx_result.pydev_call_inside_jinja2 = __pyx_state[3]; __pyx_result.pydev_django_resolve_frame = __pyx_state[4]; __pyx_result.pydev_func_name = __pyx_state[5]; __pyx_result.pydev_message = __pyx_state[6]; __pyx_result.pydev_next_line = __pyx_state[7]; __pyx_result.pydev_notify_kill = __pyx_state[8]; __pyx_result.pydev_original_step_cmd = __pyx_state[9]; __pyx_result.pydev_smart_child_offset = __pyx_state[10]; __pyx_result.pydev_smart_parent_offset = __pyx_state[11]; __pyx_result.pydev_smart_step_into_variants = __pyx_state[12]; __pyx_result.pydev_smart_step_stop = __pyx_state[13]; __pyx_result.pydev_state = __pyx_state[14]; __pyx_result.pydev_step_cmd = __pyx_state[15]; __pyx_result.pydev_step_stop = __pyx_state[16]; __pyx_result.pydev_use_scoped_step_frame = __pyx_state[17]; __pyx_result.step_in_initial_location = __pyx_state[18]; __pyx_result.suspend_type = __pyx_state[19]; __pyx_result.suspended_at_unhandled = __pyx_state[20]; __pyx_result.target_id_to_smart_step_into_variant = __pyx_state[21]; __pyx_result.thread_tracer = __pyx_state[22]; __pyx_result.top_level_thread_tracer_no_back_frames = __pyx_state[23]; __pyx_result.top_level_thread_tracer_unhandled = __pyx_state[24]; __pyx_result.trace_suspend_type = __pyx_state[25] + * if len(__pyx_state) > 26 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[26]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(PyDBAdditionalThreadInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.conditional_breakpoint_exception = __pyx_state[0]; __pyx_result.is_tracing = __pyx_state[1]; __pyx_result.pydev_call_from_jinja2 = __pyx_state[2]; __pyx_result.pydev_call_inside_jinja2 = __pyx_state[3]; __pyx_result.pydev_django_resolve_frame = __pyx_state[4]; __pyx_result.pydev_func_name = __pyx_state[5]; __pyx_result.pydev_message = __pyx_state[6]; __pyx_result.pydev_next_line = __pyx_state[7]; __pyx_result.pydev_notify_kill = __pyx_state[8]; __pyx_result.pydev_original_step_cmd = __pyx_state[9]; __pyx_result.pydev_smart_child_offset = __pyx_state[10]; __pyx_result.pydev_smart_parent_offset = __pyx_state[11]; __pyx_result.pydev_smart_step_into_variants = __pyx_state[12]; __pyx_result.pydev_smart_step_stop = __pyx_state[13]; __pyx_result.pydev_state = __pyx_state[14]; __pyx_result.pydev_step_cmd = __pyx_state[15]; __pyx_result.pydev_step_stop = __pyx_state[16]; __pyx_result.pydev_use_scoped_step_frame = __pyx_state[17]; __pyx_result.step_in_initial_location = __pyx_state[18]; __pyx_result.suspend_type = __pyx_state[19]; __pyx_result.suspended_at_unhandled = __pyx_state[20]; __pyx_result.target_id_to_smart_step_into_variant = __pyx_state[21]; __pyx_result.thread_tracer = __pyx_state[22]; __pyx_result.top_level_thread_tracer_no_back_frames = __pyx_state[23]; __pyx_result.top_level_thread_tracer_unhandled = __pyx_state[24]; __pyx_result.trace_suspend_type = __pyx_state[25] + * if len(__pyx_state) > 26 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_PyDBAdditionalThreadInfo__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle__TryExceptContainerObj(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15__pyx_unpickle__TryExceptContainerObj(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_15__pyx_unpickle__TryExceptContainerObj = {"__pyx_unpickle__TryExceptContainerObj", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_15__pyx_unpickle__TryExceptContainerObj, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_15__pyx_unpickle__TryExceptContainerObj(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle__TryExceptContainerObj (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__TryExceptContainerObj", 1, 3, 3, 1); __PYX_ERR(2, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__TryExceptContainerObj", 1, 3, 3, 2); __PYX_ERR(2, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle__TryExceptContainerObj") < 0)) __PYX_ERR(2, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__TryExceptContainerObj", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle__TryExceptContainerObj", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_14__pyx_unpickle__TryExceptContainerObj(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_14__pyx_unpickle__TryExceptContainerObj(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle__TryExceptContainerObj", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0xc8b6eb1, 0xdbf5e44, 0xde17cd3): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc8b6eb1, 0xdbf5e44, 0xde17cd3) = (try_except_infos))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__10, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0xc8b6eb1, 0xdbf5e44, 0xde17cd3): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc8b6eb1, 0xdbf5e44, 0xde17cd3) = (try_except_infos))" % __pyx_checksum) + * __pyx_result = _TryExceptContainerObj.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0xc8b6eb1, 0xdbf5e44, 0xde17cd3): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc8b6eb1, 0xdbf5e44, 0xde17cd3) = (try_except_infos))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = _TryExceptContainerObj.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_2, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(2, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0xc8b6eb1, 0xdbf5e44, 0xde17cd3): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc8b6eb1, 0xdbf5e44, 0xde17cd3) = (try_except_infos))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc8b6eb1, 0xdbf5e44, 0xde17cd3) = (try_except_infos))" % __pyx_checksum) + * __pyx_result = _TryExceptContainerObj.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle__TryExceptContainerObj__set_state(<_TryExceptContainerObj> __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc8b6eb1, 0xdbf5e44, 0xde17cd3) = (try_except_infos))" % __pyx_checksum) + * __pyx_result = _TryExceptContainerObj.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle__TryExceptContainerObj__set_state(<_TryExceptContainerObj> __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = _TryExceptContainerObj.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle__TryExceptContainerObj__set_state(<_TryExceptContainerObj> __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle__TryExceptContainerObj__set_state(_TryExceptContainerObj __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle__TryExceptContainerObj__set_state(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc8b6eb1, 0xdbf5e44, 0xde17cd3) = (try_except_infos))" % __pyx_checksum) + * __pyx_result = _TryExceptContainerObj.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle__TryExceptContainerObj__set_state(<_TryExceptContainerObj> __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle__TryExceptContainerObj__set_state(<_TryExceptContainerObj> __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle__TryExceptContainerObj__set_state(_TryExceptContainerObj __pyx_result, tuple __pyx_state): + * __pyx_result.try_except_infos = __pyx_state[0] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle__TryExceptContainerObj(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle__TryExceptContainerObj", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle__TryExceptContainerObj__set_state(<_TryExceptContainerObj> __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle__TryExceptContainerObj__set_state(_TryExceptContainerObj __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.try_except_infos = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle__TryExceptContainerObj__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle__TryExceptContainerObj__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle__TryExceptContainerObj__set_state(_TryExceptContainerObj __pyx_result, tuple __pyx_state): + * __pyx_result.try_except_infos = __pyx_state[0] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyList_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->try_except_infos); + __Pyx_DECREF(__pyx_v___pyx_result->try_except_infos); + __pyx_v___pyx_result->try_except_infos = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle__TryExceptContainerObj__set_state(_TryExceptContainerObj __pyx_result, tuple __pyx_state): + * __pyx_result.try_except_infos = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(2, 13, __pyx_L1_error) + } + __pyx_t_3 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_4 = ((__pyx_t_3 > 1) != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_4 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_5 = (__pyx_t_4 != 0); + __pyx_t_2 = __pyx_t_5; + __pyx_L4_bool_binop_done:; + if (__pyx_t_2) { + + /* "(tree fragment)":14 + * __pyx_result.try_except_infos = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[1]) # <<<<<<<<<<<<<< + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_update); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 14, __pyx_L1_error) + } + __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle__TryExceptContainerObj__set_state(_TryExceptContainerObj __pyx_result, tuple __pyx_state): + * __pyx_result.try_except_infos = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle__TryExceptContainerObj__set_state(<_TryExceptContainerObj> __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle__TryExceptContainerObj__set_state(_TryExceptContainerObj __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.try_except_infos = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle__TryExceptContainerObj__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle_PyDBFrame(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_17__pyx_unpickle_PyDBFrame(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_17__pyx_unpickle_PyDBFrame = {"__pyx_unpickle_PyDBFrame", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_17__pyx_unpickle_PyDBFrame, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_17__pyx_unpickle_PyDBFrame(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_PyDBFrame (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_PyDBFrame", 1, 3, 3, 1); __PYX_ERR(2, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_PyDBFrame", 1, 3, 3, 2); __PYX_ERR(2, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_PyDBFrame") < 0)) __PYX_ERR(2, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_PyDBFrame", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_PyDBFrame", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_16__pyx_unpickle_PyDBFrame(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_16__pyx_unpickle_PyDBFrame(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_PyDBFrame", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x506e682, 0x3a8c26e, 0xb793695): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x506e682, 0x3a8c26e, 0xb793695) = (_args, exc_info, should_skip))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__11, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0x506e682, 0x3a8c26e, 0xb793695): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x506e682, 0x3a8c26e, 0xb793695) = (_args, exc_info, should_skip))" % __pyx_checksum) + * __pyx_result = PyDBFrame.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0x506e682, 0x3a8c26e, 0xb793695): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x506e682, 0x3a8c26e, 0xb793695) = (_args, exc_info, should_skip))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = PyDBFrame.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_3, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(2, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x506e682, 0x3a8c26e, 0xb793695): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x506e682, 0x3a8c26e, 0xb793695) = (_args, exc_info, should_skip))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x506e682, 0x3a8c26e, 0xb793695) = (_args, exc_info, should_skip))" % __pyx_checksum) + * __pyx_result = PyDBFrame.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_PyDBFrame__set_state( __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBFrame), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x506e682, 0x3a8c26e, 0xb793695) = (_args, exc_info, should_skip))" % __pyx_checksum) + * __pyx_result = PyDBFrame.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_PyDBFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = PyDBFrame.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_PyDBFrame__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_PyDBFrame__set_state(PyDBFrame __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_PyDBFrame__set_state(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x506e682, 0x3a8c26e, 0xb793695) = (_args, exc_info, should_skip))" % __pyx_checksum) + * __pyx_result = PyDBFrame.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_PyDBFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_PyDBFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_PyDBFrame__set_state(PyDBFrame __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0]; __pyx_result.exc_info = __pyx_state[1]; __pyx_result.should_skip = __pyx_state[2] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_PyDBFrame(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_PyDBFrame", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_PyDBFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_PyDBFrame__set_state(PyDBFrame __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0]; __pyx_result.exc_info = __pyx_state[1]; __pyx_result.should_skip = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_PyDBFrame__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + Py_ssize_t __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_PyDBFrame__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_PyDBFrame__set_state(PyDBFrame __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0]; __pyx_result.exc_info = __pyx_state[1]; __pyx_result.should_skip = __pyx_state[2] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[3]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->_args); + __Pyx_DECREF(__pyx_v___pyx_result->_args); + __pyx_v___pyx_result->_args = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->exc_info); + __Pyx_DECREF(__pyx_v___pyx_result->exc_info); + __pyx_v___pyx_result->exc_info = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->should_skip = __pyx_t_2; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_PyDBFrame__set_state(PyDBFrame __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0]; __pyx_result.exc_info = __pyx_state[1]; __pyx_result.should_skip = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[3]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(2, 13, __pyx_L1_error) + } + __pyx_t_4 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_5 = ((__pyx_t_4 > 3) != 0); + if (__pyx_t_5) { + } else { + __pyx_t_3 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_6 = (__pyx_t_5 != 0); + __pyx_t_3 = __pyx_t_6; + __pyx_L4_bool_binop_done:; + if (__pyx_t_3) { + + /* "(tree fragment)":14 + * __pyx_result._args = __pyx_state[0]; __pyx_result.exc_info = __pyx_state[1]; __pyx_result.should_skip = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[3]) # <<<<<<<<<<<<<< + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_update); if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 14, __pyx_L1_error) + } + __pyx_t_7 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_9, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_PyDBFrame__set_state(PyDBFrame __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0]; __pyx_result.exc_info = __pyx_state[1]; __pyx_result.should_skip = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[3]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle_PyDBFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_PyDBFrame__set_state(PyDBFrame __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0]; __pyx_result.exc_info = __pyx_state[1]; __pyx_result.should_skip = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_PyDBFrame__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle_SafeCallWrapper(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_19__pyx_unpickle_SafeCallWrapper(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_19__pyx_unpickle_SafeCallWrapper = {"__pyx_unpickle_SafeCallWrapper", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_19__pyx_unpickle_SafeCallWrapper, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_19__pyx_unpickle_SafeCallWrapper(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_SafeCallWrapper (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_SafeCallWrapper", 1, 3, 3, 1); __PYX_ERR(2, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_SafeCallWrapper", 1, 3, 3, 2); __PYX_ERR(2, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_SafeCallWrapper") < 0)) __PYX_ERR(2, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_SafeCallWrapper", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_SafeCallWrapper", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_18__pyx_unpickle_SafeCallWrapper(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_18__pyx_unpickle_SafeCallWrapper(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_SafeCallWrapper", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x77c077b, 0xa14289b, 0x3cc10aa): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x77c077b, 0xa14289b, 0x3cc10aa) = (method_object))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__12, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0x77c077b, 0xa14289b, 0x3cc10aa): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x77c077b, 0xa14289b, 0x3cc10aa) = (method_object))" % __pyx_checksum) + * __pyx_result = SafeCallWrapper.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0x77c077b, 0xa14289b, 0x3cc10aa): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x77c077b, 0xa14289b, 0x3cc10aa) = (method_object))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = SafeCallWrapper.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_4, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(2, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x77c077b, 0xa14289b, 0x3cc10aa): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x77c077b, 0xa14289b, 0x3cc10aa) = (method_object))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x77c077b, 0xa14289b, 0x3cc10aa) = (method_object))" % __pyx_checksum) + * __pyx_result = SafeCallWrapper.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_SafeCallWrapper__set_state( __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x77c077b, 0xa14289b, 0x3cc10aa) = (method_object))" % __pyx_checksum) + * __pyx_result = SafeCallWrapper.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_SafeCallWrapper__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = SafeCallWrapper.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_SafeCallWrapper__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_SafeCallWrapper__set_state(SafeCallWrapper __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_SafeCallWrapper__set_state(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x77c077b, 0xa14289b, 0x3cc10aa) = (method_object))" % __pyx_checksum) + * __pyx_result = SafeCallWrapper.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_SafeCallWrapper__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_SafeCallWrapper__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_SafeCallWrapper__set_state(SafeCallWrapper __pyx_result, tuple __pyx_state): + * __pyx_result.method_object = __pyx_state[0] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_SafeCallWrapper(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_SafeCallWrapper", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_SafeCallWrapper__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_SafeCallWrapper__set_state(SafeCallWrapper __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.method_object = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_SafeCallWrapper__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_SafeCallWrapper__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_SafeCallWrapper__set_state(SafeCallWrapper __pyx_result, tuple __pyx_state): + * __pyx_result.method_object = __pyx_state[0] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->method_object); + __Pyx_DECREF(__pyx_v___pyx_result->method_object); + __pyx_v___pyx_result->method_object = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_SafeCallWrapper__set_state(SafeCallWrapper __pyx_result, tuple __pyx_state): + * __pyx_result.method_object = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(2, 13, __pyx_L1_error) + } + __pyx_t_3 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_4 = ((__pyx_t_3 > 1) != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_4 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_5 = (__pyx_t_4 != 0); + __pyx_t_2 = __pyx_t_5; + __pyx_L4_bool_binop_done:; + if (__pyx_t_2) { + + /* "(tree fragment)":14 + * __pyx_result.method_object = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[1]) # <<<<<<<<<<<<<< + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_update); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 14, __pyx_L1_error) + } + __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_SafeCallWrapper__set_state(SafeCallWrapper __pyx_result, tuple __pyx_state): + * __pyx_result.method_object = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle_SafeCallWrapper__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_SafeCallWrapper__set_state(SafeCallWrapper __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.method_object = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_SafeCallWrapper__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_21__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_21__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions = {"__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_21__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_21__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions", 1, 3, 3, 1); __PYX_ERR(2, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions", 1, 3, 3, 2); __PYX_ERR(2, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions") < 0)) __PYX_ERR(2, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_20__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_20__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d7902a, 0x121e1fb, 0xf3a61b1): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__13, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d7902a, 0x121e1fb, 0xf3a61b1): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + * __pyx_result = TopLevelThreadTracerOnlyUnhandledExceptions.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0x3d7902a, 0x121e1fb, 0xf3a61b1): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = TopLevelThreadTracerOnlyUnhandledExceptions.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_5, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(2, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d7902a, 0x121e1fb, 0xf3a61b1): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + * __pyx_result = TopLevelThreadTracerOnlyUnhandledExceptions.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state( __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + * __pyx_result = TopLevelThreadTracerOnlyUnhandledExceptions.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = TopLevelThreadTracerOnlyUnhandledExceptions.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(TopLevelThreadTracerOnlyUnhandledExceptions __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + * __pyx_result = TopLevelThreadTracerOnlyUnhandledExceptions.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(TopLevelThreadTracerOnlyUnhandledExceptions __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(TopLevelThreadTracerOnlyUnhandledExceptions __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(TopLevelThreadTracerOnlyUnhandledExceptions __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->_args); + __Pyx_DECREF(__pyx_v___pyx_result->_args); + __pyx_v___pyx_result->_args = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(TopLevelThreadTracerOnlyUnhandledExceptions __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(2, 13, __pyx_L1_error) + } + __pyx_t_3 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_4 = ((__pyx_t_3 > 1) != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_4 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_5 = (__pyx_t_4 != 0); + __pyx_t_2 = __pyx_t_5; + __pyx_L4_bool_binop_done:; + if (__pyx_t_2) { + + /* "(tree fragment)":14 + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[1]) # <<<<<<<<<<<<<< + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_update); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 14, __pyx_L1_error) + } + __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(TopLevelThreadTracerOnlyUnhandledExceptions __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(TopLevelThreadTracerOnlyUnhandledExceptions __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle_TopLevelThreadTracerNoBackFrame(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_23__pyx_unpickle_TopLevelThreadTracerNoBackFrame(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_23__pyx_unpickle_TopLevelThreadTracerNoBackFrame = {"__pyx_unpickle_TopLevelThreadTracerNoBackFrame", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_23__pyx_unpickle_TopLevelThreadTracerNoBackFrame, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_23__pyx_unpickle_TopLevelThreadTracerNoBackFrame(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_TopLevelThreadTracerNoBackFrame (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_TopLevelThreadTracerNoBackFrame", 1, 3, 3, 1); __PYX_ERR(2, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_TopLevelThreadTracerNoBackFrame", 1, 3, 3, 2); __PYX_ERR(2, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_TopLevelThreadTracerNoBackFrame") < 0)) __PYX_ERR(2, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_TopLevelThreadTracerNoBackFrame", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_TopLevelThreadTracerNoBackFrame", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_22__pyx_unpickle_TopLevelThreadTracerNoBackFrame(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_22__pyx_unpickle_TopLevelThreadTracerNoBackFrame(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_TopLevelThreadTracerNoBackFrame", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96) = (_args, _frame_trace_dispatch, _last_exc_arg, _last_raise_line, _raise_lines, try_except_infos))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__14, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96) = (_args, _frame_trace_dispatch, _last_exc_arg, _last_raise_line, _raise_lines, try_except_infos))" % __pyx_checksum) + * __pyx_result = TopLevelThreadTracerNoBackFrame.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96) = (_args, _frame_trace_dispatch, _last_exc_arg, _last_raise_line, _raise_lines, try_except_infos))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = TopLevelThreadTracerNoBackFrame.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_6, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(2, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96) = (_args, _frame_trace_dispatch, _last_exc_arg, _last_raise_line, _raise_lines, try_except_infos))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96) = (_args, _frame_trace_dispatch, _last_exc_arg, _last_raise_line, _raise_lines, try_except_infos))" % __pyx_checksum) + * __pyx_result = TopLevelThreadTracerNoBackFrame.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state( __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96) = (_args, _frame_trace_dispatch, _last_exc_arg, _last_raise_line, _raise_lines, try_except_infos))" % __pyx_checksum) + * __pyx_result = TopLevelThreadTracerNoBackFrame.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = TopLevelThreadTracerNoBackFrame.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(TopLevelThreadTracerNoBackFrame __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xa3a9ec1, 0x3f5f7e9, 0x0ff9c96) = (_args, _frame_trace_dispatch, _last_exc_arg, _last_raise_line, _raise_lines, try_except_infos))" % __pyx_checksum) + * __pyx_result = TopLevelThreadTracerNoBackFrame.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(TopLevelThreadTracerNoBackFrame __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0]; __pyx_result._frame_trace_dispatch = __pyx_state[1]; __pyx_result._last_exc_arg = __pyx_state[2]; __pyx_result._last_raise_line = __pyx_state[3]; __pyx_result._raise_lines = __pyx_state[4]; __pyx_result.try_except_infos = __pyx_state[5] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_TopLevelThreadTracerNoBackFrame(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_TopLevelThreadTracerNoBackFrame", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(TopLevelThreadTracerNoBackFrame __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0]; __pyx_result._frame_trace_dispatch = __pyx_state[1]; __pyx_result._last_exc_arg = __pyx_state[2]; __pyx_result._last_raise_line = __pyx_state[3]; __pyx_result._raise_lines = __pyx_state[4]; __pyx_result.try_except_infos = __pyx_state[5] + * if len(__pyx_state) > 6 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + Py_ssize_t __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(TopLevelThreadTracerNoBackFrame __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0]; __pyx_result._frame_trace_dispatch = __pyx_state[1]; __pyx_result._last_exc_arg = __pyx_state[2]; __pyx_result._last_raise_line = __pyx_state[3]; __pyx_result._raise_lines = __pyx_state[4]; __pyx_result.try_except_infos = __pyx_state[5] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 6 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[6]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->_args); + __Pyx_DECREF(__pyx_v___pyx_result->_args); + __pyx_v___pyx_result->_args = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->_frame_trace_dispatch); + __Pyx_DECREF(__pyx_v___pyx_result->_frame_trace_dispatch); + __pyx_v___pyx_result->_frame_trace_dispatch = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->_last_exc_arg); + __Pyx_DECREF(__pyx_v___pyx_result->_last_exc_arg); + __pyx_v___pyx_result->_last_exc_arg = __pyx_t_1; + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->_last_raise_line = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 4, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PySet_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "set", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->_raise_lines); + __Pyx_DECREF(__pyx_v___pyx_result->_raise_lines); + __pyx_v___pyx_result->_raise_lines = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 5, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->try_except_infos); + __Pyx_DECREF(__pyx_v___pyx_result->try_except_infos); + __pyx_v___pyx_result->try_except_infos = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(TopLevelThreadTracerNoBackFrame __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0]; __pyx_result._frame_trace_dispatch = __pyx_state[1]; __pyx_result._last_exc_arg = __pyx_state[2]; __pyx_result._last_raise_line = __pyx_state[3]; __pyx_result._raise_lines = __pyx_state[4]; __pyx_result.try_except_infos = __pyx_state[5] + * if len(__pyx_state) > 6 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[6]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(2, 13, __pyx_L1_error) + } + __pyx_t_4 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_5 = ((__pyx_t_4 > 6) != 0); + if (__pyx_t_5) { + } else { + __pyx_t_3 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_6 = (__pyx_t_5 != 0); + __pyx_t_3 = __pyx_t_6; + __pyx_L4_bool_binop_done:; + if (__pyx_t_3) { + + /* "(tree fragment)":14 + * __pyx_result._args = __pyx_state[0]; __pyx_result._frame_trace_dispatch = __pyx_state[1]; __pyx_result._last_exc_arg = __pyx_state[2]; __pyx_result._last_raise_line = __pyx_state[3]; __pyx_result._raise_lines = __pyx_state[4]; __pyx_result.try_except_infos = __pyx_state[5] + * if len(__pyx_state) > 6 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[6]) # <<<<<<<<<<<<<< + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_update); if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 14, __pyx_L1_error) + } + __pyx_t_7 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 6, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_9, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(TopLevelThreadTracerNoBackFrame __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0]; __pyx_result._frame_trace_dispatch = __pyx_state[1]; __pyx_result._last_exc_arg = __pyx_state[2]; __pyx_result._last_raise_line = __pyx_state[3]; __pyx_result._raise_lines = __pyx_state[4]; __pyx_result.try_except_infos = __pyx_state[5] + * if len(__pyx_state) > 6 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[6]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state(TopLevelThreadTracerNoBackFrame __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0]; __pyx_result._frame_trace_dispatch = __pyx_state[1]; __pyx_result._last_exc_arg = __pyx_state[2]; __pyx_result._last_raise_line = __pyx_state[3]; __pyx_result._raise_lines = __pyx_state[4]; __pyx_result.try_except_infos = __pyx_state[5] + * if len(__pyx_state) > 6 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_TopLevelThreadTracerNoBackFrame__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle_ThreadTracer(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_25__pyx_unpickle_ThreadTracer(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_14_pydevd_bundle_13pydevd_cython_25__pyx_unpickle_ThreadTracer = {"__pyx_unpickle_ThreadTracer", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_25__pyx_unpickle_ThreadTracer, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_14_pydevd_bundle_13pydevd_cython_25__pyx_unpickle_ThreadTracer(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_ThreadTracer (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_ThreadTracer", 1, 3, 3, 1); __PYX_ERR(2, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_ThreadTracer", 1, 3, 3, 2); __PYX_ERR(2, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_ThreadTracer") < 0)) __PYX_ERR(2, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_ThreadTracer", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_ThreadTracer", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_14_pydevd_bundle_13pydevd_cython_24__pyx_unpickle_ThreadTracer(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_14_pydevd_bundle_13pydevd_cython_24__pyx_unpickle_ThreadTracer(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_ThreadTracer", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d7902a, 0x121e1fb, 0xf3a61b1): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__13, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d7902a, 0x121e1fb, 0xf3a61b1): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + * __pyx_result = ThreadTracer.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0x3d7902a, 0x121e1fb, 0xf3a61b1): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = ThreadTracer.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_5, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(2, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d7902a, 0x121e1fb, 0xf3a61b1): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + * __pyx_result = ThreadTracer.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_ThreadTracer__set_state( __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_ThreadTracer), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + * __pyx_result = ThreadTracer.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_ThreadTracer__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = ThreadTracer.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_ThreadTracer__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_ThreadTracer__set_state(ThreadTracer __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_ThreadTracer__set_state(((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d7902a, 0x121e1fb, 0xf3a61b1) = (_args))" % __pyx_checksum) + * __pyx_result = ThreadTracer.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_ThreadTracer__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_ThreadTracer__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_ThreadTracer__set_state(ThreadTracer __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_ThreadTracer(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_ThreadTracer", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_ThreadTracer__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_ThreadTracer__set_state(ThreadTracer __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_14_pydevd_bundle_13pydevd_cython___pyx_unpickle_ThreadTracer__set_state(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_ThreadTracer__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_ThreadTracer__set_state(ThreadTracer __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(2, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->_args); + __Pyx_DECREF(__pyx_v___pyx_result->_args); + __pyx_v___pyx_result->_args = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_ThreadTracer__set_state(ThreadTracer __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(2, 13, __pyx_L1_error) + } + __pyx_t_3 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_4 = ((__pyx_t_3 > 1) != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_4 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 13, __pyx_L1_error) + __pyx_t_5 = (__pyx_t_4 != 0); + __pyx_t_2 = __pyx_t_5; + __pyx_L4_bool_binop_done:; + if (__pyx_t_2) { + + /* "(tree fragment)":14 + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[1]) # <<<<<<<<<<<<<< + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_update); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(2, 14, __pyx_L1_error) + } + __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_ThreadTracer__set_state(ThreadTracer __pyx_result, tuple __pyx_state): + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[1]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle_ThreadTracer__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_ThreadTracer__set_state(ThreadTracer __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython.__pyx_unpickle_ThreadTracer__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_tp_new_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)o); + p->pydev_step_stop = Py_None; Py_INCREF(Py_None); + p->pydev_smart_step_stop = Py_None; Py_INCREF(Py_None); + p->pydev_call_from_jinja2 = Py_None; Py_INCREF(Py_None); + p->pydev_call_inside_jinja2 = Py_None; Py_INCREF(Py_None); + p->conditional_breakpoint_exception = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->pydev_message = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->pydev_func_name = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->trace_suspend_type = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->top_level_thread_tracer_no_back_frames = Py_None; Py_INCREF(Py_None); + p->top_level_thread_tracer_unhandled = Py_None; Py_INCREF(Py_None); + p->thread_tracer = Py_None; Py_INCREF(Py_None); + p->step_in_initial_location = Py_None; Py_INCREF(Py_None); + p->pydev_smart_step_into_variants = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->target_id_to_smart_step_into_variant = ((PyObject*)Py_None); Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo(PyObject *o) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->pydev_step_stop); + Py_CLEAR(p->pydev_smart_step_stop); + Py_CLEAR(p->pydev_call_from_jinja2); + Py_CLEAR(p->pydev_call_inside_jinja2); + Py_CLEAR(p->conditional_breakpoint_exception); + Py_CLEAR(p->pydev_message); + Py_CLEAR(p->pydev_func_name); + Py_CLEAR(p->trace_suspend_type); + Py_CLEAR(p->top_level_thread_tracer_no_back_frames); + Py_CLEAR(p->top_level_thread_tracer_unhandled); + Py_CLEAR(p->thread_tracer); + Py_CLEAR(p->step_in_initial_location); + Py_CLEAR(p->pydev_smart_step_into_variants); + Py_CLEAR(p->target_id_to_smart_step_into_variant); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)o; + if (p->pydev_step_stop) { + e = (*v)(p->pydev_step_stop, a); if (e) return e; + } + if (p->pydev_smart_step_stop) { + e = (*v)(p->pydev_smart_step_stop, a); if (e) return e; + } + if (p->pydev_call_from_jinja2) { + e = (*v)(p->pydev_call_from_jinja2, a); if (e) return e; + } + if (p->pydev_call_inside_jinja2) { + e = (*v)(p->pydev_call_inside_jinja2, a); if (e) return e; + } + if (p->conditional_breakpoint_exception) { + e = (*v)(p->conditional_breakpoint_exception, a); if (e) return e; + } + if (p->top_level_thread_tracer_no_back_frames) { + e = (*v)(p->top_level_thread_tracer_no_back_frames, a); if (e) return e; + } + if (p->top_level_thread_tracer_unhandled) { + e = (*v)(p->top_level_thread_tracer_unhandled, a); if (e) return e; + } + if (p->thread_tracer) { + e = (*v)(p->thread_tracer, a); if (e) return e; + } + if (p->step_in_initial_location) { + e = (*v)(p->step_in_initial_location, a); if (e) return e; + } + if (p->pydev_smart_step_into_variants) { + e = (*v)(p->pydev_smart_step_into_variants, a); if (e) return e; + } + if (p->target_id_to_smart_step_into_variant) { + e = (*v)(p->target_id_to_smart_step_into_variant, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)o; + tmp = ((PyObject*)p->pydev_step_stop); + p->pydev_step_stop = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->pydev_smart_step_stop); + p->pydev_smart_step_stop = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->pydev_call_from_jinja2); + p->pydev_call_from_jinja2 = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->pydev_call_inside_jinja2); + p->pydev_call_inside_jinja2 = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->conditional_breakpoint_exception); + p->conditional_breakpoint_exception = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->top_level_thread_tracer_no_back_frames); + p->top_level_thread_tracer_no_back_frames = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->top_level_thread_tracer_unhandled); + p->top_level_thread_tracer_unhandled = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->thread_tracer); + p->thread_tracer = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->step_in_initial_location); + p->step_in_initial_location = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->pydev_smart_step_into_variants); + p->pydev_smart_step_into_variants = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->target_id_to_smart_step_into_variant); + p->target_id_to_smart_step_into_variant = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_state(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_state(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_11pydev_state_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_step_stop(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_step_stop(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_step_stop_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_original_step_cmd(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_original_step_cmd(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_23pydev_original_step_cmd_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_step_cmd(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_step_cmd(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_14pydev_step_cmd_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_notify_kill(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_notify_kill(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_17pydev_notify_kill_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_step_stop(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_step_stop(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_21pydev_smart_step_stop_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_django_resolve_frame(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_django_resolve_frame(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_26pydev_django_resolve_frame_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_call_from_jinja2(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_call_from_jinja2(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22pydev_call_from_jinja2_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_call_inside_jinja2(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_call_inside_jinja2(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_call_inside_jinja2_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_is_tracing(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_is_tracing(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_10is_tracing_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_conditional_breakpoint_exception(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_conditional_breakpoint_exception(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_32conditional_breakpoint_exception_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_message(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_message(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13pydev_message_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_suspend_type(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_suspend_type(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_12suspend_type_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_next_line(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_next_line(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_next_line_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_func_name(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_func_name(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_15pydev_func_name_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_suspended_at_unhandled(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_suspended_at_unhandled(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_22suspended_at_unhandled_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_trace_suspend_type(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_trace_suspend_type(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_18trace_suspend_type_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_top_level_thread_tracer_no_back_frames(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_top_level_thread_tracer_no_back_frames(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_38top_level_thread_tracer_no_back_frames_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_top_level_thread_tracer_unhandled(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_top_level_thread_tracer_unhandled(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_33top_level_thread_tracer_unhandled_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_thread_tracer(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_thread_tracer(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_13thread_tracer_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_step_in_initial_location(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_step_in_initial_location(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24step_in_initial_location_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_parent_offset(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_parent_offset(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_25pydev_smart_parent_offset_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_child_offset(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_child_offset(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_24pydev_smart_child_offset_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_step_into_variants(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_step_into_variants(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_30pydev_smart_step_into_variants_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_target_id_to_smart_step_into_variant(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_target_id_to_smart_step_into_variant(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_36target_id_to_smart_step_into_variant_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_use_scoped_step_frame(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_use_scoped_step_frame(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_27pydev_use_scoped_step_frame_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyMethodDef __pyx_methods_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo[] = { + {"get_topmost_frame", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_3get_topmost_frame, METH_O, __pyx_doc_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_2get_topmost_frame}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_7__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_9__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo[] = { + {(char *)"pydev_state", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_state, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_state, (char *)0, 0}, + {(char *)"pydev_step_stop", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_step_stop, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_step_stop, (char *)0, 0}, + {(char *)"pydev_original_step_cmd", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_original_step_cmd, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_original_step_cmd, (char *)0, 0}, + {(char *)"pydev_step_cmd", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_step_cmd, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_step_cmd, (char *)0, 0}, + {(char *)"pydev_notify_kill", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_notify_kill, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_notify_kill, (char *)0, 0}, + {(char *)"pydev_smart_step_stop", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_step_stop, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_step_stop, (char *)0, 0}, + {(char *)"pydev_django_resolve_frame", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_django_resolve_frame, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_django_resolve_frame, (char *)0, 0}, + {(char *)"pydev_call_from_jinja2", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_call_from_jinja2, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_call_from_jinja2, (char *)0, 0}, + {(char *)"pydev_call_inside_jinja2", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_call_inside_jinja2, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_call_inside_jinja2, (char *)0, 0}, + {(char *)"is_tracing", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_is_tracing, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_is_tracing, (char *)0, 0}, + {(char *)"conditional_breakpoint_exception", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_conditional_breakpoint_exception, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_conditional_breakpoint_exception, (char *)0, 0}, + {(char *)"pydev_message", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_message, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_message, (char *)0, 0}, + {(char *)"suspend_type", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_suspend_type, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_suspend_type, (char *)0, 0}, + {(char *)"pydev_next_line", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_next_line, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_next_line, (char *)0, 0}, + {(char *)"pydev_func_name", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_func_name, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_func_name, (char *)0, 0}, + {(char *)"suspended_at_unhandled", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_suspended_at_unhandled, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_suspended_at_unhandled, (char *)0, 0}, + {(char *)"trace_suspend_type", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_trace_suspend_type, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_trace_suspend_type, (char *)0, 0}, + {(char *)"top_level_thread_tracer_no_back_frames", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_top_level_thread_tracer_no_back_frames, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_top_level_thread_tracer_no_back_frames, (char *)0, 0}, + {(char *)"top_level_thread_tracer_unhandled", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_top_level_thread_tracer_unhandled, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_top_level_thread_tracer_unhandled, (char *)0, 0}, + {(char *)"thread_tracer", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_thread_tracer, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_thread_tracer, (char *)0, 0}, + {(char *)"step_in_initial_location", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_step_in_initial_location, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_step_in_initial_location, (char *)0, 0}, + {(char *)"pydev_smart_parent_offset", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_parent_offset, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_parent_offset, (char *)0, 0}, + {(char *)"pydev_smart_child_offset", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_child_offset, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_child_offset, (char *)0, 0}, + {(char *)"pydev_smart_step_into_variants", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_step_into_variants, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_smart_step_into_variants, (char *)0, 0}, + {(char *)"target_id_to_smart_step_into_variant", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_target_id_to_smart_step_into_variant, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_target_id_to_smart_step_into_variant, (char *)0, 0}, + {(char *)"pydev_use_scoped_step_frame", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_use_scoped_step_frame, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_pydev_use_scoped_step_frame, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_bundle.pydevd_cython.PyDBAdditionalThreadInfo", /*tp_name*/ + sizeof(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_5__str__, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo, /*tp_traverse*/ + __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_24PyDBAdditionalThreadInfo_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyObject *__pyx_tp_new_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)o); + p->try_except_infos = ((PyObject*)Py_None); Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj(PyObject *o) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->try_except_infos); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)o; + if (p->try_except_infos) { + e = (*v)(p->try_except_infos, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj *)o; + tmp = ((PyObject*)p->try_except_infos); + p->try_except_infos = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_try_except_infos(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_try_except_infos(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_16try_except_infos_5__del__(o); + } +} + +static PyMethodDef __pyx_methods_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj[] = { + {"__reduce_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_3__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_5__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj[] = { + {(char *)"try_except_infos", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_try_except_infos, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_try_except_infos, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_bundle.pydevd_cython._TryExceptContainerObj", /*tp_name*/ + sizeof(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj, /*tp_traverse*/ + __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_22_TryExceptContainerObj_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; +static struct __pyx_vtabstruct_14_pydevd_bundle_13pydevd_cython_PyDBFrame __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame; + +static PyObject *__pyx_tp_new_14_pydevd_bundle_13pydevd_cython_PyDBFrame(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)o); + p->__pyx_vtab = __pyx_vtabptr_14_pydevd_bundle_13pydevd_cython_PyDBFrame; + p->_args = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->exc_info = Py_None; Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_PyDBFrame(PyObject *o) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->_args); + Py_CLEAR(p->exc_info); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_PyDBFrame(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)o; + if (p->_args) { + e = (*v)(p->_args, a); if (e) return e; + } + if (p->exc_info) { + e = (*v)(p->exc_info, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_PyDBFrame(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *)o; + tmp = ((PyObject*)p->_args); + p->_args = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->exc_info); + p->exc_info = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyMethodDef __pyx_methods_14_pydevd_bundle_13pydevd_cython_PyDBFrame[] = { + {"set_suspend", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_3set_suspend, METH_VARARGS|METH_KEYWORDS, 0}, + {"do_wait_suspend", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_5do_wait_suspend, METH_VARARGS|METH_KEYWORDS, 0}, + {"trace_exception", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_7trace_exception, METH_VARARGS|METH_KEYWORDS, 0}, + {"handle_user_exception", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_9handle_user_exception, METH_O, 0}, + {"trace_dispatch", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_11trace_dispatch, METH_VARARGS|METH_KEYWORDS, 0}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_13__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_15__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_bundle.pydevd_cython.PyDBFrame", /*tp_name*/ + sizeof(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_PyDBFrame, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_PyDBFrame, /*tp_traverse*/ + __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_PyDBFrame, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_14_pydevd_bundle_13pydevd_cython_PyDBFrame, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_14_pydevd_bundle_13pydevd_cython_PyDBFrame, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyObject *__pyx_tp_new_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)o); + p->method_object = Py_None; Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper(PyObject *o) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->method_object); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)o; + if (p->method_object) { + e = (*v)(p->method_object, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper *)o; + tmp = ((PyObject*)p->method_object); + p->method_object = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyMethodDef __pyx_methods_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper[] = { + {"get_method_object", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_5get_method_object, METH_NOARGS, 0}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_7__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_9__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_bundle.pydevd_cython.SafeCallWrapper", /*tp_name*/ + sizeof(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_3__call__, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper, /*tp_traverse*/ + __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_15SafeCallWrapper_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyObject *__pyx_tp_new_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)o); + p->_args = ((PyObject*)Py_None); Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions(PyObject *o) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->_args); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)o; + if (p->_args) { + e = (*v)(p->_args, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions *)o; + tmp = ((PyObject*)p->_args); + p->_args = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions__args(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions__args(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5_args_5__del__(o); + } +} + +static PyMethodDef __pyx_methods_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions[] = { + {"trace_unhandled_exceptions", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_3trace_unhandled_exceptions, METH_VARARGS|METH_KEYWORDS, 0}, + {"get_trace_dispatch_func", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_5get_trace_dispatch_func, METH_NOARGS, 0}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_7__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_9__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions[] = { + {(char *)"_args", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions__args, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions__args, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_bundle.pydevd_cython.TopLevelThreadTracerOnlyUnhandledExceptions", /*tp_name*/ + sizeof(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions, /*tp_traverse*/ + __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_43TopLevelThreadTracerOnlyUnhandledExceptions_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyObject *__pyx_tp_new_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)o); + p->_frame_trace_dispatch = Py_None; Py_INCREF(Py_None); + p->_args = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->try_except_infos = Py_None; Py_INCREF(Py_None); + p->_last_exc_arg = Py_None; Py_INCREF(Py_None); + p->_raise_lines = ((PyObject*)Py_None); Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame(PyObject *o) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->_frame_trace_dispatch); + Py_CLEAR(p->_args); + Py_CLEAR(p->try_except_infos); + Py_CLEAR(p->_last_exc_arg); + Py_CLEAR(p->_raise_lines); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)o; + if (p->_frame_trace_dispatch) { + e = (*v)(p->_frame_trace_dispatch, a); if (e) return e; + } + if (p->_args) { + e = (*v)(p->_args, a); if (e) return e; + } + if (p->try_except_infos) { + e = (*v)(p->try_except_infos, a); if (e) return e; + } + if (p->_last_exc_arg) { + e = (*v)(p->_last_exc_arg, a); if (e) return e; + } + if (p->_raise_lines) { + e = (*v)(p->_raise_lines, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame *)o; + tmp = ((PyObject*)p->_frame_trace_dispatch); + p->_frame_trace_dispatch = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_args); + p->_args = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->try_except_infos); + p->try_except_infos = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_last_exc_arg); + p->_last_exc_arg = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_raise_lines); + p->_raise_lines = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__frame_trace_dispatch(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__frame_trace_dispatch(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_21_frame_trace_dispatch_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__args(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__args(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5_args_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_try_except_infos(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_try_except_infos(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16try_except_infos_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__last_exc_arg(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__last_exc_arg(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_13_last_exc_arg_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__raise_lines(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__raise_lines(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_12_raise_lines_5__del__(o); + } +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__last_raise_line(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__last_raise_line(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_16_last_raise_line_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyMethodDef __pyx_methods_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame[] = { + {"trace_dispatch_and_unhandled_exceptions", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_3trace_dispatch_and_unhandled_exceptions, METH_VARARGS|METH_KEYWORDS, 0}, + {"get_trace_dispatch_func", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_5get_trace_dispatch_func, METH_NOARGS, 0}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_7__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_9__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame[] = { + {(char *)"_frame_trace_dispatch", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__frame_trace_dispatch, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__frame_trace_dispatch, (char *)0, 0}, + {(char *)"_args", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__args, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__args, (char *)0, 0}, + {(char *)"try_except_infos", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_try_except_infos, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_try_except_infos, (char *)0, 0}, + {(char *)"_last_exc_arg", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__last_exc_arg, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__last_exc_arg, (char *)0, 0}, + {(char *)"_raise_lines", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__raise_lines, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__raise_lines, (char *)0, 0}, + {(char *)"_last_raise_line", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__last_raise_line, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame__last_raise_line, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_bundle.pydevd_cython.TopLevelThreadTracerNoBackFrame", /*tp_name*/ + sizeof(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame, /*tp_traverse*/ + __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_31TopLevelThreadTracerNoBackFrame_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyObject *__pyx_tp_new_14_pydevd_bundle_13pydevd_cython_ThreadTracer(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)o); + p->_args = ((PyObject*)Py_None); Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_ThreadTracer(PyObject *o) { + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->_args); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_ThreadTracer(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)o; + if (p->_args) { + e = (*v)(p->_args, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_ThreadTracer(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *p = (struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer *)o; + tmp = ((PyObject*)p->_args); + p->_args = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_14_pydevd_bundle_13pydevd_cython_12ThreadTracer__args(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_1__get__(o); +} + +static int __pyx_setprop_14_pydevd_bundle_13pydevd_cython_12ThreadTracer__args(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_3__set__(o, v); + } + else { + return __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5_args_5__del__(o); + } +} + +static PyMethodDef __pyx_methods_14_pydevd_bundle_13pydevd_cython_ThreadTracer[] = { + {"__reduce_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_5__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_7__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_14_pydevd_bundle_13pydevd_cython_ThreadTracer[] = { + {(char *)"_args", __pyx_getprop_14_pydevd_bundle_13pydevd_cython_12ThreadTracer__args, __pyx_setprop_14_pydevd_bundle_13pydevd_cython_12ThreadTracer__args, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_bundle.pydevd_cython.ThreadTracer", /*tp_name*/ + sizeof(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_ThreadTracer), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_14_pydevd_bundle_13pydevd_cython_ThreadTracer, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_3__call__, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_14_pydevd_bundle_13pydevd_cython_ThreadTracer, /*tp_traverse*/ + __pyx_tp_clear_14_pydevd_bundle_13pydevd_cython_ThreadTracer, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_14_pydevd_bundle_13pydevd_cython_ThreadTracer, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_14_pydevd_bundle_13pydevd_cython_ThreadTracer, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_14_pydevd_bundle_13pydevd_cython_ThreadTracer, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_pydevd_cython(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_pydevd_cython}, + {0, NULL} +}; +#endif + +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + "pydevd_cython", + 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else + -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_s_, __pyx_k_, sizeof(__pyx_k_), 0, 0, 1, 0}, + {&__pyx_kp_s_1, __pyx_k_1, sizeof(__pyx_k_1), 0, 0, 1, 0}, + {&__pyx_n_s_ALL, __pyx_k_ALL, sizeof(__pyx_k_ALL), 0, 0, 1, 1}, + {&__pyx_n_s_AttributeError, __pyx_k_AttributeError, sizeof(__pyx_k_AttributeError), 0, 0, 1, 1}, + {&__pyx_n_s_CMD_SET_FUNCTION_BREAK, __pyx_k_CMD_SET_FUNCTION_BREAK, sizeof(__pyx_k_CMD_SET_FUNCTION_BREAK), 0, 0, 1, 1}, + {&__pyx_n_s_DEBUG_START, __pyx_k_DEBUG_START, sizeof(__pyx_k_DEBUG_START), 0, 0, 1, 1}, + {&__pyx_n_s_DEBUG_START_PY3K, __pyx_k_DEBUG_START_PY3K, sizeof(__pyx_k_DEBUG_START_PY3K), 0, 0, 1, 1}, + {&__pyx_n_s_EXCEPTION_TYPE_HANDLED, __pyx_k_EXCEPTION_TYPE_HANDLED, sizeof(__pyx_k_EXCEPTION_TYPE_HANDLED), 0, 0, 1, 1}, + {&__pyx_n_s_EXCEPTION_TYPE_USER_UNHANDLED, __pyx_k_EXCEPTION_TYPE_USER_UNHANDLED, sizeof(__pyx_k_EXCEPTION_TYPE_USER_UNHANDLED), 0, 0, 1, 1}, + {&__pyx_kp_s_Error_in_linecache_checkcache_r, __pyx_k_Error_in_linecache_checkcache_r, sizeof(__pyx_k_Error_in_linecache_checkcache_r), 0, 0, 1, 0}, + {&__pyx_kp_s_Error_in_linecache_getline_r_s_f, __pyx_k_Error_in_linecache_getline_r_s_f, sizeof(__pyx_k_Error_in_linecache_getline_r_s_f), 0, 0, 1, 0}, + {&__pyx_n_s_ForkSafeLock, __pyx_k_ForkSafeLock, sizeof(__pyx_k_ForkSafeLock), 0, 0, 1, 1}, + {&__pyx_n_s_GeneratorExit, __pyx_k_GeneratorExit, sizeof(__pyx_k_GeneratorExit), 0, 0, 1, 1}, + {&__pyx_n_s_IGNORE_EXCEPTION_TAG, __pyx_k_IGNORE_EXCEPTION_TAG, sizeof(__pyx_k_IGNORE_EXCEPTION_TAG), 0, 0, 1, 1}, + {&__pyx_kp_s_IgnoreException, __pyx_k_IgnoreException, sizeof(__pyx_k_IgnoreException), 0, 0, 1, 0}, + {&__pyx_kp_s_Ignore_exception_s_in_library_s, __pyx_k_Ignore_exception_s_in_library_s, sizeof(__pyx_k_Ignore_exception_s_in_library_s), 0, 0, 1, 0}, + {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_k_Incompatible_checksums_0x_x_vs_0, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_2, __pyx_k_Incompatible_checksums_0x_x_vs_0_2, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_2), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_3, __pyx_k_Incompatible_checksums_0x_x_vs_0_3, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_3), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_4, __pyx_k_Incompatible_checksums_0x_x_vs_0_4, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_4), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_5, __pyx_k_Incompatible_checksums_0x_x_vs_0_5, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_5), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_6, __pyx_k_Incompatible_checksums_0x_x_vs_0_6, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_6), 0, 0, 1, 0}, + {&__pyx_n_s_KeyboardInterrupt, __pyx_k_KeyboardInterrupt, sizeof(__pyx_k_KeyboardInterrupt), 0, 0, 1, 1}, + {&__pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER, __pyx_k_NORM_PATHS_AND_BASE_CONTAINER, sizeof(__pyx_k_NORM_PATHS_AND_BASE_CONTAINER), 0, 0, 1, 1}, + {&__pyx_n_s_NO_FTRACE, __pyx_k_NO_FTRACE, sizeof(__pyx_k_NO_FTRACE), 0, 0, 1, 1}, + {&__pyx_n_s_NameError, __pyx_k_NameError, sizeof(__pyx_k_NameError), 0, 0, 1, 1}, + {&__pyx_n_s_None, __pyx_k_None, sizeof(__pyx_k_None), 0, 0, 1, 1}, + {&__pyx_n_s_PYDEVD_IPYTHON_CONTEXT, __pyx_k_PYDEVD_IPYTHON_CONTEXT, sizeof(__pyx_k_PYDEVD_IPYTHON_CONTEXT), 0, 0, 1, 1}, + {&__pyx_n_s_PYDEV_FILE, __pyx_k_PYDEV_FILE, sizeof(__pyx_k_PYDEV_FILE), 0, 0, 1, 1}, + {&__pyx_n_s_PYTHON_SUSPEND, __pyx_k_PYTHON_SUSPEND, sizeof(__pyx_k_PYTHON_SUSPEND), 0, 0, 1, 1}, + {&__pyx_n_s_PickleError, __pyx_k_PickleError, sizeof(__pyx_k_PickleError), 0, 0, 1, 1}, + {&__pyx_n_s_PyDBAdditionalThreadInfo, __pyx_k_PyDBAdditionalThreadInfo, sizeof(__pyx_k_PyDBAdditionalThreadInfo), 0, 0, 1, 1}, + {&__pyx_n_s_PyDBFrame, __pyx_k_PyDBFrame, sizeof(__pyx_k_PyDBFrame), 0, 0, 1, 1}, + {&__pyx_n_s_RETURN_VALUES_DICT, __pyx_k_RETURN_VALUES_DICT, sizeof(__pyx_k_RETURN_VALUES_DICT), 0, 0, 1, 1}, + {&__pyx_n_s_STATE_RUN, __pyx_k_STATE_RUN, sizeof(__pyx_k_STATE_RUN), 0, 0, 1, 1}, + {&__pyx_n_s_SUPPORT_GEVENT, __pyx_k_SUPPORT_GEVENT, sizeof(__pyx_k_SUPPORT_GEVENT), 0, 0, 1, 1}, + {&__pyx_n_s_SafeCallWrapper, __pyx_k_SafeCallWrapper, sizeof(__pyx_k_SafeCallWrapper), 0, 0, 1, 1}, + {&__pyx_kp_s_State_s_Stop_s_Cmd_s_Kill_s, __pyx_k_State_s_Stop_s_Cmd_s_Kill_s, sizeof(__pyx_k_State_s_Stop_s_Cmd_s_Kill_s), 0, 0, 1, 0}, + {&__pyx_n_s_StopAsyncIteration, __pyx_k_StopAsyncIteration, sizeof(__pyx_k_StopAsyncIteration), 0, 0, 1, 1}, + {&__pyx_n_s_StopIteration, __pyx_k_StopIteration, sizeof(__pyx_k_StopIteration), 0, 0, 1, 1}, + {&__pyx_kp_s_Stop_inside_ipython_call, __pyx_k_Stop_inside_ipython_call, sizeof(__pyx_k_Stop_inside_ipython_call), 0, 0, 1, 0}, + {&__pyx_n_s_SystemExit, __pyx_k_SystemExit, sizeof(__pyx_k_SystemExit), 0, 0, 1, 1}, + {&__pyx_n_s_TRACE_PROPERTY, __pyx_k_TRACE_PROPERTY, sizeof(__pyx_k_TRACE_PROPERTY), 0, 0, 1, 1}, + {&__pyx_n_s_Thread, __pyx_k_Thread, sizeof(__pyx_k_Thread), 0, 0, 1, 1}, + {&__pyx_n_s_ThreadTracer, __pyx_k_ThreadTracer, sizeof(__pyx_k_ThreadTracer), 0, 0, 1, 1}, + {&__pyx_n_s_TopLevelThreadTracerNoBackFrame, __pyx_k_TopLevelThreadTracerNoBackFrame, sizeof(__pyx_k_TopLevelThreadTracerNoBackFrame), 0, 0, 1, 1}, + {&__pyx_n_s_TopLevelThreadTracerOnlyUnhandle, __pyx_k_TopLevelThreadTracerOnlyUnhandle, sizeof(__pyx_k_TopLevelThreadTracerOnlyUnhandle), 0, 0, 1, 1}, + {&__pyx_n_s_TryExceptContainerObj, __pyx_k_TryExceptContainerObj, sizeof(__pyx_k_TryExceptContainerObj), 0, 0, 1, 1}, + {&__pyx_n_s_USE_CUSTOM_SYS_CURRENT_FRAMES_MA, __pyx_k_USE_CUSTOM_SYS_CURRENT_FRAMES_MA, sizeof(__pyx_k_USE_CUSTOM_SYS_CURRENT_FRAMES_MA), 0, 0, 1, 1}, + {&__pyx_kp_s_Unable_to_get_topmost_frame_for, __pyx_k_Unable_to_get_topmost_frame_for, sizeof(__pyx_k_Unable_to_get_topmost_frame_for), 0, 0, 1, 0}, + {&__pyx_kp_s_Using_Cython_speedups, __pyx_k_Using_Cython_speedups, sizeof(__pyx_k_Using_Cython_speedups), 0, 0, 1, 0}, + {&__pyx_kp_s__3, __pyx_k__3, sizeof(__pyx_k__3), 0, 0, 1, 0}, + {&__pyx_kp_s__5, __pyx_k__5, sizeof(__pyx_k__5), 0, 0, 1, 0}, + {&__pyx_kp_s__6, __pyx_k__6, sizeof(__pyx_k__6), 0, 0, 1, 0}, + {&__pyx_kp_s__7, __pyx_k__7, sizeof(__pyx_k__7), 0, 0, 1, 0}, + {&__pyx_n_s_add, __pyx_k_add, sizeof(__pyx_k_add), 0, 0, 1, 1}, + {&__pyx_n_s_add_command, __pyx_k_add_command, sizeof(__pyx_k_add_command), 0, 0, 1, 1}, + {&__pyx_n_s_add_exception_to_frame, __pyx_k_add_exception_to_frame, sizeof(__pyx_k_add_exception_to_frame), 0, 0, 1, 1}, + {&__pyx_n_s_additional_info, __pyx_k_additional_info, sizeof(__pyx_k_additional_info), 0, 0, 1, 1}, + {&__pyx_n_s_append, __pyx_k_append, sizeof(__pyx_k_append), 0, 0, 1, 1}, + {&__pyx_n_s_apply_files_filter, __pyx_k_apply_files_filter, sizeof(__pyx_k_apply_files_filter), 0, 0, 1, 1}, + {&__pyx_n_s_apply_to_settrace, __pyx_k_apply_to_settrace, sizeof(__pyx_k_apply_to_settrace), 0, 0, 1, 1}, + {&__pyx_n_s_arg, __pyx_k_arg, sizeof(__pyx_k_arg), 0, 0, 1, 1}, + {&__pyx_n_s_args, __pyx_k_args, sizeof(__pyx_k_args), 0, 0, 1, 1}, + {&__pyx_n_s_args_2, __pyx_k_args_2, sizeof(__pyx_k_args_2), 0, 0, 1, 1}, + {&__pyx_n_s_basename, __pyx_k_basename, sizeof(__pyx_k_basename), 0, 0, 1, 1}, + {&__pyx_n_s_bootstrap, __pyx_k_bootstrap, sizeof(__pyx_k_bootstrap), 0, 0, 1, 1}, + {&__pyx_n_s_bootstrap_2, __pyx_k_bootstrap_2, sizeof(__pyx_k_bootstrap_2), 0, 0, 1, 1}, + {&__pyx_n_s_bootstrap_inner, __pyx_k_bootstrap_inner, sizeof(__pyx_k_bootstrap_inner), 0, 0, 1, 1}, + {&__pyx_n_s_bootstrap_inner_2, __pyx_k_bootstrap_inner_2, sizeof(__pyx_k_bootstrap_inner_2), 0, 0, 1, 1}, + {&__pyx_n_s_break_on_caught_exceptions, __pyx_k_break_on_caught_exceptions, sizeof(__pyx_k_break_on_caught_exceptions), 0, 0, 1, 1}, + {&__pyx_n_s_break_on_user_uncaught_exception, __pyx_k_break_on_user_uncaught_exception, sizeof(__pyx_k_break_on_user_uncaught_exception), 0, 0, 1, 1}, + {&__pyx_n_s_breakpoints, __pyx_k_breakpoints, sizeof(__pyx_k_breakpoints), 0, 0, 1, 1}, + {&__pyx_n_s_call, __pyx_k_call, sizeof(__pyx_k_call), 0, 0, 1, 1}, + {&__pyx_n_s_call_2, __pyx_k_call_2, sizeof(__pyx_k_call_2), 0, 0, 1, 1}, + {&__pyx_n_s_can_skip, __pyx_k_can_skip, sizeof(__pyx_k_can_skip), 0, 0, 1, 1}, + {&__pyx_kp_s_cell, __pyx_k_cell, sizeof(__pyx_k_cell), 0, 0, 1, 0}, + {&__pyx_n_s_checkcache, __pyx_k_checkcache, sizeof(__pyx_k_checkcache), 0, 0, 1, 1}, + {&__pyx_n_s_children_variants, __pyx_k_children_variants, sizeof(__pyx_k_children_variants), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_cmd_factory, __pyx_k_cmd_factory, sizeof(__pyx_k_cmd_factory), 0, 0, 1, 1}, + {&__pyx_n_s_cmd_step_into, __pyx_k_cmd_step_into, sizeof(__pyx_k_cmd_step_into), 0, 0, 1, 1}, + {&__pyx_n_s_cmd_step_over, __pyx_k_cmd_step_over, sizeof(__pyx_k_cmd_step_over), 0, 0, 1, 1}, + {&__pyx_n_s_co_filename, __pyx_k_co_filename, sizeof(__pyx_k_co_filename), 0, 0, 1, 1}, + {&__pyx_n_s_co_firstlineno, __pyx_k_co_firstlineno, sizeof(__pyx_k_co_firstlineno), 0, 0, 1, 1}, + {&__pyx_n_s_co_flags, __pyx_k_co_flags, sizeof(__pyx_k_co_flags), 0, 0, 1, 1}, + {&__pyx_n_s_co_name, __pyx_k_co_name, sizeof(__pyx_k_co_name), 0, 0, 1, 1}, + {&__pyx_n_s_collect_return_info, __pyx_k_collect_return_info, sizeof(__pyx_k_collect_return_info), 0, 0, 1, 1}, + {&__pyx_n_s_collect_try_except_info, __pyx_k_collect_try_except_info, sizeof(__pyx_k_collect_try_except_info), 0, 0, 1, 1}, + {&__pyx_n_s_compile, __pyx_k_compile, sizeof(__pyx_k_compile), 0, 0, 1, 1}, + {&__pyx_n_s_condition, __pyx_k_condition, sizeof(__pyx_k_condition), 0, 0, 1, 1}, + {&__pyx_n_s_constant_to_str, __pyx_k_constant_to_str, sizeof(__pyx_k_constant_to_str), 0, 0, 1, 1}, + {&__pyx_n_s_constructed_tid_to_last_frame, __pyx_k_constructed_tid_to_last_frame, sizeof(__pyx_k_constructed_tid_to_last_frame), 0, 0, 1, 1}, + {&__pyx_n_s_current_frames, __pyx_k_current_frames, sizeof(__pyx_k_current_frames), 0, 0, 1, 1}, + {&__pyx_n_s_debug, __pyx_k_debug, sizeof(__pyx_k_debug), 0, 0, 1, 1}, + {&__pyx_n_s_dict, __pyx_k_dict, sizeof(__pyx_k_dict), 0, 0, 1, 1}, + {&__pyx_n_s_dis, __pyx_k_dis, sizeof(__pyx_k_dis), 0, 0, 1, 1}, + {&__pyx_n_s_disable_tracing, __pyx_k_disable_tracing, sizeof(__pyx_k_disable_tracing), 0, 0, 1, 1}, + {&__pyx_n_s_do_wait_suspend, __pyx_k_do_wait_suspend, sizeof(__pyx_k_do_wait_suspend), 0, 0, 1, 1}, + {&__pyx_n_s_enable_tracing, __pyx_k_enable_tracing, sizeof(__pyx_k_enable_tracing), 0, 0, 1, 1}, + {&__pyx_n_s_encode, __pyx_k_encode, sizeof(__pyx_k_encode), 0, 0, 1, 1}, + {&__pyx_n_s_endswith, __pyx_k_endswith, sizeof(__pyx_k_endswith), 0, 0, 1, 1}, + {&__pyx_n_s_enter, __pyx_k_enter, sizeof(__pyx_k_enter), 0, 0, 1, 1}, + {&__pyx_n_s_event, __pyx_k_event, sizeof(__pyx_k_event), 0, 0, 1, 1}, + {&__pyx_n_s_except_line, __pyx_k_except_line, sizeof(__pyx_k_except_line), 0, 0, 1, 1}, + {&__pyx_n_s_exception, __pyx_k_exception, sizeof(__pyx_k_exception), 0, 0, 1, 1}, + {&__pyx_n_s_exception_break, __pyx_k_exception_break, sizeof(__pyx_k_exception_break), 0, 0, 1, 1}, + {&__pyx_n_s_exception_type, __pyx_k_exception_type, sizeof(__pyx_k_exception_type), 0, 0, 1, 1}, + {&__pyx_n_s_exclude_exception_by_filter, __pyx_k_exclude_exception_by_filter, sizeof(__pyx_k_exclude_exception_by_filter), 0, 0, 1, 1}, + {&__pyx_n_s_exec, __pyx_k_exec, sizeof(__pyx_k_exec), 0, 0, 1, 1}, + {&__pyx_n_s_execfile, __pyx_k_execfile, sizeof(__pyx_k_execfile), 0, 0, 1, 1}, + {&__pyx_n_s_exit, __pyx_k_exit, sizeof(__pyx_k_exit), 0, 0, 1, 1}, + {&__pyx_n_s_expression, __pyx_k_expression, sizeof(__pyx_k_expression), 0, 0, 1, 1}, + {&__pyx_n_s_f_back, __pyx_k_f_back, sizeof(__pyx_k_f_back), 0, 0, 1, 1}, + {&__pyx_n_s_f_code, __pyx_k_f_code, sizeof(__pyx_k_f_code), 0, 0, 1, 1}, + {&__pyx_n_s_f_globals, __pyx_k_f_globals, sizeof(__pyx_k_f_globals), 0, 0, 1, 1}, + {&__pyx_n_s_f_lasti, __pyx_k_f_lasti, sizeof(__pyx_k_f_lasti), 0, 0, 1, 1}, + {&__pyx_n_s_f_lineno, __pyx_k_f_lineno, sizeof(__pyx_k_f_lineno), 0, 0, 1, 1}, + {&__pyx_n_s_f_locals, __pyx_k_f_locals, sizeof(__pyx_k_f_locals), 0, 0, 1, 1}, + {&__pyx_n_s_f_trace, __pyx_k_f_trace, sizeof(__pyx_k_f_trace), 0, 0, 1, 1}, + {&__pyx_n_s_f_unhandled, __pyx_k_f_unhandled, sizeof(__pyx_k_f_unhandled), 0, 0, 1, 1}, + {&__pyx_n_s_filename, __pyx_k_filename, sizeof(__pyx_k_filename), 0, 0, 1, 1}, + {&__pyx_n_s_filename_to_lines_where_exceptio, __pyx_k_filename_to_lines_where_exceptio, sizeof(__pyx_k_filename_to_lines_where_exceptio), 0, 0, 1, 1}, + {&__pyx_n_s_filename_to_stat_info, __pyx_k_filename_to_stat_info, sizeof(__pyx_k_filename_to_stat_info), 0, 0, 1, 1}, + {&__pyx_n_s_findlinestarts, __pyx_k_findlinestarts, sizeof(__pyx_k_findlinestarts), 0, 0, 1, 1}, + {&__pyx_n_s_fix_top_level_trace_and_get_trac, __pyx_k_fix_top_level_trace_and_get_trac, sizeof(__pyx_k_fix_top_level_trace_and_get_trac), 0, 0, 1, 1}, + {&__pyx_n_s_force_only_unhandled_tracer, __pyx_k_force_only_unhandled_tracer, sizeof(__pyx_k_force_only_unhandled_tracer), 0, 0, 1, 1}, + {&__pyx_n_s_frame, __pyx_k_frame, sizeof(__pyx_k_frame), 0, 0, 1, 1}, + {&__pyx_n_s_frame_trace_dispatch, __pyx_k_frame_trace_dispatch, sizeof(__pyx_k_frame_trace_dispatch), 0, 0, 1, 1}, + {&__pyx_n_s_func_name, __pyx_k_func_name, sizeof(__pyx_k_func_name), 0, 0, 1, 1}, + {&__pyx_n_s_function_breakpoint_name_to_brea, __pyx_k_function_breakpoint_name_to_brea, sizeof(__pyx_k_function_breakpoint_name_to_brea), 0, 0, 1, 1}, + {&__pyx_n_s_get, __pyx_k_get, sizeof(__pyx_k_get), 0, 0, 1, 1}, + {&__pyx_n_s_get_abs_path_real_path_and_base, __pyx_k_get_abs_path_real_path_and_base, sizeof(__pyx_k_get_abs_path_real_path_and_base), 0, 0, 1, 1}, + {&__pyx_n_s_get_breakpoint, __pyx_k_get_breakpoint, sizeof(__pyx_k_get_breakpoint), 0, 0, 1, 1}, + {&__pyx_n_s_get_clsname_for_code, __pyx_k_get_clsname_for_code, sizeof(__pyx_k_get_clsname_for_code), 0, 0, 1, 1}, + {&__pyx_n_s_get_current_thread_id, __pyx_k_get_current_thread_id, sizeof(__pyx_k_get_current_thread_id), 0, 0, 1, 1}, + {&__pyx_n_s_get_exception_breakpoint, __pyx_k_get_exception_breakpoint, sizeof(__pyx_k_get_exception_breakpoint), 0, 0, 1, 1}, + {&__pyx_n_s_get_file_type, __pyx_k_get_file_type, sizeof(__pyx_k_get_file_type), 0, 0, 1, 1}, + {&__pyx_n_s_get_smart_step_into_variant_from, __pyx_k_get_smart_step_into_variant_from, sizeof(__pyx_k_get_smart_step_into_variant_from), 0, 0, 1, 1}, + {&__pyx_n_s_get_trace_dispatch_func, __pyx_k_get_trace_dispatch_func, sizeof(__pyx_k_get_trace_dispatch_func), 0, 0, 1, 1}, + {&__pyx_n_s_getline, __pyx_k_getline, sizeof(__pyx_k_getline), 0, 0, 1, 1}, + {&__pyx_n_s_getstate, __pyx_k_getstate, sizeof(__pyx_k_getstate), 0, 0, 1, 1}, + {&__pyx_n_s_global_cache_frame_skips, __pyx_k_global_cache_frame_skips, sizeof(__pyx_k_global_cache_frame_skips), 0, 0, 1, 1}, + {&__pyx_n_s_global_cache_skips, __pyx_k_global_cache_skips, sizeof(__pyx_k_global_cache_skips), 0, 0, 1, 1}, + {&__pyx_n_s_global_notify_skipped_step_in_l, __pyx_k_global_notify_skipped_step_in_l, sizeof(__pyx_k_global_notify_skipped_step_in_l), 0, 0, 1, 1}, + {&__pyx_n_s_handle_breakpoint_condition, __pyx_k_handle_breakpoint_condition, sizeof(__pyx_k_handle_breakpoint_condition), 0, 0, 1, 1}, + {&__pyx_n_s_handle_breakpoint_expression, __pyx_k_handle_breakpoint_expression, sizeof(__pyx_k_handle_breakpoint_expression), 0, 0, 1, 1}, + {&__pyx_n_s_handle_user_exception, __pyx_k_handle_user_exception, sizeof(__pyx_k_handle_user_exception), 0, 0, 1, 1}, + {&__pyx_n_s_has_condition, __pyx_k_has_condition, sizeof(__pyx_k_has_condition), 0, 0, 1, 1}, + {&__pyx_n_s_has_plugin_exception_breaks, __pyx_k_has_plugin_exception_breaks, sizeof(__pyx_k_has_plugin_exception_breaks), 0, 0, 1, 1}, + {&__pyx_n_s_has_plugin_line_breaks, __pyx_k_has_plugin_line_breaks, sizeof(__pyx_k_has_plugin_line_breaks), 0, 0, 1, 1}, + {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, + {&__pyx_n_s_id, __pyx_k_id, sizeof(__pyx_k_id), 0, 0, 1, 1}, + {&__pyx_n_s_ident, __pyx_k_ident, sizeof(__pyx_k_ident), 0, 0, 1, 1}, + {&__pyx_n_s_ignore_exception_trace, __pyx_k_ignore_exception_trace, sizeof(__pyx_k_ignore_exception_trace), 0, 0, 1, 1}, + {&__pyx_n_s_ignore_exceptions_thrown_in_line, __pyx_k_ignore_exceptions_thrown_in_line, sizeof(__pyx_k_ignore_exceptions_thrown_in_line), 0, 0, 1, 1}, + {&__pyx_n_s_ignore_system_exit_code, __pyx_k_ignore_system_exit_code, sizeof(__pyx_k_ignore_system_exit_code), 0, 0, 1, 1}, + {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, + {&__pyx_n_s_in_project_scope, __pyx_k_in_project_scope, sizeof(__pyx_k_in_project_scope), 0, 0, 1, 1}, + {&__pyx_n_s_info, __pyx_k_info, sizeof(__pyx_k_info), 0, 0, 1, 1}, + {&__pyx_kp_s_invalid, __pyx_k_invalid, sizeof(__pyx_k_invalid), 0, 0, 1, 0}, + {&__pyx_n_s_is_files_filter_enabled, __pyx_k_is_files_filter_enabled, sizeof(__pyx_k_is_files_filter_enabled), 0, 0, 1, 1}, + {&__pyx_n_s_is_line_in_except_block, __pyx_k_is_line_in_except_block, sizeof(__pyx_k_is_line_in_except_block), 0, 0, 1, 1}, + {&__pyx_n_s_is_line_in_try_block, __pyx_k_is_line_in_try_block, sizeof(__pyx_k_is_line_in_try_block), 0, 0, 1, 1}, + {&__pyx_n_s_is_logpoint, __pyx_k_is_logpoint, sizeof(__pyx_k_is_logpoint), 0, 0, 1, 1}, + {&__pyx_n_s_is_thread_alive, __pyx_k_is_thread_alive, sizeof(__pyx_k_is_thread_alive), 0, 0, 1, 1}, + {&__pyx_n_s_j, __pyx_k_j, sizeof(__pyx_k_j), 0, 0, 1, 1}, + {&__pyx_n_s_just_raised, __pyx_k_just_raised, sizeof(__pyx_k_just_raised), 0, 0, 1, 1}, + {&__pyx_n_s_kwargs, __pyx_k_kwargs, sizeof(__pyx_k_kwargs), 0, 0, 1, 1}, + {&__pyx_kp_s_lambda, __pyx_k_lambda, sizeof(__pyx_k_lambda), 0, 0, 1, 0}, + {&__pyx_n_s_line, __pyx_k_line, sizeof(__pyx_k_line), 0, 0, 1, 1}, + {&__pyx_n_s_linecache, __pyx_k_linecache, sizeof(__pyx_k_linecache), 0, 0, 1, 1}, + {&__pyx_n_s_linesep, __pyx_k_linesep, sizeof(__pyx_k_linesep), 0, 0, 1, 1}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_main_2, __pyx_k_main_2, sizeof(__pyx_k_main_2), 0, 0, 1, 1}, + {&__pyx_n_s_make_io_message, __pyx_k_make_io_message, sizeof(__pyx_k_make_io_message), 0, 0, 1, 1}, + {&__pyx_n_s_match, __pyx_k_match, sizeof(__pyx_k_match), 0, 0, 1, 1}, + {&__pyx_n_s_method_object, __pyx_k_method_object, sizeof(__pyx_k_method_object), 0, 0, 1, 1}, + {&__pyx_kp_s_module, __pyx_k_module, sizeof(__pyx_k_module), 0, 0, 1, 0}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_name_2, __pyx_k_name_2, sizeof(__pyx_k_name_2), 0, 0, 1, 1}, + {&__pyx_n_s_new, __pyx_k_new, sizeof(__pyx_k_new), 0, 0, 1, 1}, + {&__pyx_n_s_notify_on_first_raise_only, __pyx_k_notify_on_first_raise_only, sizeof(__pyx_k_notify_on_first_raise_only), 0, 0, 1, 1}, + {&__pyx_n_s_notify_skipped_step_in_because_o, __pyx_k_notify_skipped_step_in_because_o, sizeof(__pyx_k_notify_skipped_step_in_because_o), 0, 0, 1, 1}, + {&__pyx_n_s_notify_thread_not_alive, __pyx_k_notify_thread_not_alive, sizeof(__pyx_k_notify_thread_not_alive), 0, 0, 1, 1}, + {&__pyx_n_s_original_call, __pyx_k_original_call, sizeof(__pyx_k_original_call), 0, 0, 1, 1}, + {&__pyx_n_s_original_step_cmd, __pyx_k_original_step_cmd, sizeof(__pyx_k_original_step_cmd), 0, 0, 1, 1}, + {&__pyx_n_s_os, __pyx_k_os, sizeof(__pyx_k_os), 0, 0, 1, 1}, + {&__pyx_n_s_os_path, __pyx_k_os_path, sizeof(__pyx_k_os_path), 0, 0, 1, 1}, + {&__pyx_n_s_path, __pyx_k_path, sizeof(__pyx_k_path), 0, 0, 1, 1}, + {&__pyx_n_s_pickle, __pyx_k_pickle, sizeof(__pyx_k_pickle), 0, 0, 1, 1}, + {&__pyx_n_s_plugin, __pyx_k_plugin, sizeof(__pyx_k_plugin), 0, 0, 1, 1}, + {&__pyx_n_s_pop, __pyx_k_pop, sizeof(__pyx_k_pop), 0, 0, 1, 1}, + {&__pyx_n_s_py_db, __pyx_k_py_db, sizeof(__pyx_k_py_db), 0, 0, 1, 1}, + {&__pyx_kp_s_pyc, __pyx_k_pyc, sizeof(__pyx_k_pyc), 0, 0, 1, 0}, + {&__pyx_n_s_pydb_disposed, __pyx_k_pydb_disposed, sizeof(__pyx_k_pydb_disposed), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_bundle, __pyx_k_pydev_bundle, sizeof(__pyx_k_pydev_bundle), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_bundle__pydev_saved_modul, __pyx_k_pydev_bundle__pydev_saved_modul, sizeof(__pyx_k_pydev_bundle__pydev_saved_modul), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_bundle_pydev_is_thread_al, __pyx_k_pydev_bundle_pydev_is_thread_al, sizeof(__pyx_k_pydev_bundle_pydev_is_thread_al), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_bundle_pydev_log, __pyx_k_pydev_bundle_pydev_log, sizeof(__pyx_k_pydev_bundle_pydev_log), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_do_not_trace, __pyx_k_pydev_do_not_trace, sizeof(__pyx_k_pydev_do_not_trace), 0, 0, 1, 1}, + {&__pyx_kp_s_pydev_execfile_py, __pyx_k_pydev_execfile_py, sizeof(__pyx_k_pydev_execfile_py), 0, 0, 1, 0}, + {&__pyx_n_s_pydev_log, __pyx_k_pydev_log, sizeof(__pyx_k_pydev_log), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_log_exception, __pyx_k_pydev_log_exception, sizeof(__pyx_k_pydev_log_exception), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_monkey, __pyx_k_pydev_monkey, sizeof(__pyx_k_pydev_monkey), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd, __pyx_k_pydevd, sizeof(__pyx_k_pydevd), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle, __pyx_k_pydevd_bundle, sizeof(__pyx_k_pydevd_bundle), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle_pydevd_bytecode_u, __pyx_k_pydevd_bundle_pydevd_bytecode_u, sizeof(__pyx_k_pydevd_bundle_pydevd_bytecode_u), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle_pydevd_comm_const, __pyx_k_pydevd_bundle_pydevd_comm_const, sizeof(__pyx_k_pydevd_bundle_pydevd_comm_const), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle_pydevd_constants, __pyx_k_pydevd_bundle_pydevd_constants, sizeof(__pyx_k_pydevd_bundle_pydevd_constants), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle_pydevd_cython, __pyx_k_pydevd_bundle_pydevd_cython, sizeof(__pyx_k_pydevd_bundle_pydevd_cython), 0, 0, 1, 1}, + {&__pyx_kp_s_pydevd_bundle_pydevd_cython_pyx, __pyx_k_pydevd_bundle_pydevd_cython_pyx, sizeof(__pyx_k_pydevd_bundle_pydevd_cython_pyx), 0, 0, 1, 0}, + {&__pyx_n_s_pydevd_bundle_pydevd_frame_util, __pyx_k_pydevd_bundle_pydevd_frame_util, sizeof(__pyx_k_pydevd_bundle_pydevd_frame_util), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle_pydevd_utils, __pyx_k_pydevd_bundle_pydevd_utils, sizeof(__pyx_k_pydevd_bundle_pydevd_utils), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_dont_trace, __pyx_k_pydevd_dont_trace, sizeof(__pyx_k_pydevd_dont_trace), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_file_utils, __pyx_k_pydevd_file_utils, sizeof(__pyx_k_pydevd_file_utils), 0, 0, 1, 1}, + {&__pyx_kp_s_pydevd_py, __pyx_k_pydevd_py, sizeof(__pyx_k_pydevd_py), 0, 0, 1, 0}, + {&__pyx_kp_s_pydevd_traceproperty_py, __pyx_k_pydevd_traceproperty_py, sizeof(__pyx_k_pydevd_traceproperty_py), 0, 0, 1, 0}, + {&__pyx_n_s_pydevd_tracing, __pyx_k_pydevd_tracing, sizeof(__pyx_k_pydevd_tracing), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_PickleError, __pyx_k_pyx_PickleError, sizeof(__pyx_k_pyx_PickleError), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_checksum, __pyx_k_pyx_checksum, sizeof(__pyx_k_pyx_checksum), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_result, __pyx_k_pyx_result, sizeof(__pyx_k_pyx_result), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_state, __pyx_k_pyx_state, sizeof(__pyx_k_pyx_state), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_type, __pyx_k_pyx_type, sizeof(__pyx_k_pyx_type), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle_PyDBAdditionalThr, __pyx_k_pyx_unpickle_PyDBAdditionalThr, sizeof(__pyx_k_pyx_unpickle_PyDBAdditionalThr), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle_PyDBFrame, __pyx_k_pyx_unpickle_PyDBFrame, sizeof(__pyx_k_pyx_unpickle_PyDBFrame), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle_SafeCallWrapper, __pyx_k_pyx_unpickle_SafeCallWrapper, sizeof(__pyx_k_pyx_unpickle_SafeCallWrapper), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle_ThreadTracer, __pyx_k_pyx_unpickle_ThreadTracer, sizeof(__pyx_k_pyx_unpickle_ThreadTracer), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle_TopLevelThreadTra, __pyx_k_pyx_unpickle_TopLevelThreadTra, sizeof(__pyx_k_pyx_unpickle_TopLevelThreadTra), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle_TopLevelThreadTra_2, __pyx_k_pyx_unpickle_TopLevelThreadTra_2, sizeof(__pyx_k_pyx_unpickle_TopLevelThreadTra_2), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle__TryExceptContain, __pyx_k_pyx_unpickle__TryExceptContain, sizeof(__pyx_k_pyx_unpickle__TryExceptContain), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_vtable, __pyx_k_pyx_vtable, sizeof(__pyx_k_pyx_vtable), 0, 0, 1, 1}, + {&__pyx_n_s_qname, __pyx_k_qname, sizeof(__pyx_k_qname), 0, 0, 1, 1}, + {&__pyx_n_s_quitting, __pyx_k_quitting, sizeof(__pyx_k_quitting), 0, 0, 1, 1}, + {&__pyx_n_s_raise_lines_in_except, __pyx_k_raise_lines_in_except, sizeof(__pyx_k_raise_lines_in_except), 0, 0, 1, 1}, + {&__pyx_n_s_re, __pyx_k_re, sizeof(__pyx_k_re), 0, 0, 1, 1}, + {&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1}, + {&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1}, + {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1}, + {&__pyx_n_s_remove_exception_from_frame, __pyx_k_remove_exception_from_frame, sizeof(__pyx_k_remove_exception_from_frame), 0, 0, 1, 1}, + {&__pyx_n_s_remove_return_values_flag, __pyx_k_remove_return_values_flag, sizeof(__pyx_k_remove_return_values_flag), 0, 0, 1, 1}, + {&__pyx_n_s_return, __pyx_k_return, sizeof(__pyx_k_return), 0, 0, 1, 1}, + {&__pyx_n_s_return_line, __pyx_k_return_line, sizeof(__pyx_k_return_line), 0, 0, 1, 1}, + {&__pyx_n_s_returns, __pyx_k_returns, sizeof(__pyx_k_returns), 0, 0, 1, 1}, + {&__pyx_n_s_rfind, __pyx_k_rfind, sizeof(__pyx_k_rfind), 0, 0, 1, 1}, + {&__pyx_n_s_run, __pyx_k_run, sizeof(__pyx_k_run), 0, 0, 1, 1}, + {&__pyx_kp_s_s_s, __pyx_k_s_s, sizeof(__pyx_k_s_s), 0, 0, 1, 0}, + {&__pyx_n_s_self, __pyx_k_self, sizeof(__pyx_k_self), 0, 0, 1, 1}, + {&__pyx_n_s_send_caught_exception_stack, __pyx_k_send_caught_exception_stack, sizeof(__pyx_k_send_caught_exception_stack), 0, 0, 1, 1}, + {&__pyx_n_s_send_caught_exception_stack_proc, __pyx_k_send_caught_exception_stack_proc, sizeof(__pyx_k_send_caught_exception_stack_proc), 0, 0, 1, 1}, + {&__pyx_n_s_set_additional_thread_info, __pyx_k_set_additional_thread_info, sizeof(__pyx_k_set_additional_thread_info), 0, 0, 1, 1}, + {&__pyx_n_s_set_additional_thread_info_lock, __pyx_k_set_additional_thread_info_lock, sizeof(__pyx_k_set_additional_thread_info_lock), 0, 0, 1, 1}, + {&__pyx_n_s_set_suspend, __pyx_k_set_suspend, sizeof(__pyx_k_set_suspend), 0, 0, 1, 1}, + {&__pyx_n_s_set_trace_for_frame_and_parents, __pyx_k_set_trace_for_frame_and_parents, sizeof(__pyx_k_set_trace_for_frame_and_parents), 0, 0, 1, 1}, + {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1}, + {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1}, + {&__pyx_n_s_should_trace_hook, __pyx_k_should_trace_hook, sizeof(__pyx_k_should_trace_hook), 0, 0, 1, 1}, + {&__pyx_n_s_show_return_values, __pyx_k_show_return_values, sizeof(__pyx_k_show_return_values), 0, 0, 1, 1}, + {&__pyx_n_s_skip_on_exceptions_thrown_in_sam, __pyx_k_skip_on_exceptions_thrown_in_sam, sizeof(__pyx_k_skip_on_exceptions_thrown_in_sam), 0, 0, 1, 1}, + {&__pyx_n_s_st_mtime, __pyx_k_st_mtime, sizeof(__pyx_k_st_mtime), 0, 0, 1, 1}, + {&__pyx_n_s_st_size, __pyx_k_st_size, sizeof(__pyx_k_st_size), 0, 0, 1, 1}, + {&__pyx_n_s_startswith, __pyx_k_startswith, sizeof(__pyx_k_startswith), 0, 0, 1, 1}, + {&__pyx_n_s_stat, __pyx_k_stat, sizeof(__pyx_k_stat), 0, 0, 1, 1}, + {&__pyx_n_s_stop, __pyx_k_stop, sizeof(__pyx_k_stop), 0, 0, 1, 1}, + {&__pyx_n_s_stop_on_unhandled_exception, __pyx_k_stop_on_unhandled_exception, sizeof(__pyx_k_stop_on_unhandled_exception), 0, 0, 1, 1}, + {&__pyx_kp_s_stringsource, __pyx_k_stringsource, sizeof(__pyx_k_stringsource), 0, 0, 1, 0}, + {&__pyx_n_s_suspend, __pyx_k_suspend, sizeof(__pyx_k_suspend), 0, 0, 1, 1}, + {&__pyx_n_s_suspend_other_threads, __pyx_k_suspend_other_threads, sizeof(__pyx_k_suspend_other_threads), 0, 0, 1, 1}, + {&__pyx_n_s_suspend_policy, __pyx_k_suspend_policy, sizeof(__pyx_k_suspend_policy), 0, 0, 1, 1}, + {&__pyx_n_s_suspended_at_unhandled, __pyx_k_suspended_at_unhandled, sizeof(__pyx_k_suspended_at_unhandled), 0, 0, 1, 1}, + {&__pyx_n_s_t, __pyx_k_t, sizeof(__pyx_k_t), 0, 0, 1, 1}, + {&__pyx_n_s_tb_frame, __pyx_k_tb_frame, sizeof(__pyx_k_tb_frame), 0, 0, 1, 1}, + {&__pyx_n_s_tb_lineno, __pyx_k_tb_lineno, sizeof(__pyx_k_tb_lineno), 0, 0, 1, 1}, + {&__pyx_n_s_tb_next, __pyx_k_tb_next, sizeof(__pyx_k_tb_next), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {&__pyx_n_s_thread, __pyx_k_thread, sizeof(__pyx_k_thread), 0, 0, 1, 1}, + {&__pyx_n_s_thread_trace_func, __pyx_k_thread_trace_func, sizeof(__pyx_k_thread_trace_func), 0, 0, 1, 1}, + {&__pyx_n_s_thread_tracer, __pyx_k_thread_tracer, sizeof(__pyx_k_thread_tracer), 0, 0, 1, 1}, + {&__pyx_n_s_threading, __pyx_k_threading, sizeof(__pyx_k_threading), 0, 0, 1, 1}, + {&__pyx_n_s_threading_active, __pyx_k_threading_active, sizeof(__pyx_k_threading_active), 0, 0, 1, 1}, + {&__pyx_n_s_threading_current_thread, __pyx_k_threading_current_thread, sizeof(__pyx_k_threading_current_thread), 0, 0, 1, 1}, + {&__pyx_n_s_threading_get_ident, __pyx_k_threading_get_ident, sizeof(__pyx_k_threading_get_ident), 0, 0, 1, 1}, + {&__pyx_n_s_top_level_thread_tracer, __pyx_k_top_level_thread_tracer, sizeof(__pyx_k_top_level_thread_tracer), 0, 0, 1, 1}, + {&__pyx_n_s_top_level_thread_tracer_no_back, __pyx_k_top_level_thread_tracer_no_back, sizeof(__pyx_k_top_level_thread_tracer_no_back), 0, 0, 1, 1}, + {&__pyx_n_s_top_level_thread_tracer_unhandle, __pyx_k_top_level_thread_tracer_unhandle, sizeof(__pyx_k_top_level_thread_tracer_unhandle), 0, 0, 1, 1}, + {&__pyx_n_s_trace, __pyx_k_trace, sizeof(__pyx_k_trace), 0, 0, 1, 1}, + {&__pyx_n_s_trace_dispatch, __pyx_k_trace_dispatch, sizeof(__pyx_k_trace_dispatch), 0, 0, 1, 1}, + {&__pyx_n_s_trace_dispatch_and_unhandled_exc, __pyx_k_trace_dispatch_and_unhandled_exc, sizeof(__pyx_k_trace_dispatch_and_unhandled_exc), 0, 0, 1, 1}, + {&__pyx_n_s_trace_exception, __pyx_k_trace_exception, sizeof(__pyx_k_trace_exception), 0, 0, 1, 1}, + {&__pyx_n_s_trace_unhandled_exceptions, __pyx_k_trace_unhandled_exceptions, sizeof(__pyx_k_trace_unhandled_exceptions), 0, 0, 1, 1}, + {&__pyx_n_s_try_exc_info, __pyx_k_try_exc_info, sizeof(__pyx_k_try_exc_info), 0, 0, 1, 1}, + {&__pyx_n_s_try_except_infos, __pyx_k_try_except_infos, sizeof(__pyx_k_try_except_infos), 0, 0, 1, 1}, + {&__pyx_n_s_update, __pyx_k_update, sizeof(__pyx_k_update), 0, 0, 1, 1}, + {&__pyx_kp_s_utf_8, __pyx_k_utf_8, sizeof(__pyx_k_utf_8), 0, 0, 1, 0}, + {&__pyx_n_s_values, __pyx_k_values, sizeof(__pyx_k_values), 0, 0, 1, 1}, + {&__pyx_n_s_version, __pyx_k_version, sizeof(__pyx_k_version), 0, 0, 1, 1}, + {&__pyx_n_s_writer, __pyx_k_writer, sizeof(__pyx_k_writer), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_ImportError = __Pyx_GetBuiltinName(__pyx_n_s_ImportError); if (!__pyx_builtin_ImportError) __PYX_ERR(0, 174, __pyx_L1_error) + __pyx_builtin_NameError = __Pyx_GetBuiltinName(__pyx_n_s_NameError); if (!__pyx_builtin_NameError) __PYX_ERR(0, 207, __pyx_L1_error) + __pyx_builtin_StopIteration = __Pyx_GetBuiltinName(__pyx_n_s_StopIteration); if (!__pyx_builtin_StopIteration) __PYX_ERR(0, 208, __pyx_L1_error) + __pyx_builtin_id = __Pyx_GetBuiltinName(__pyx_n_s_id); if (!__pyx_builtin_id) __PYX_ERR(0, 130, __pyx_L1_error) + __pyx_builtin_AttributeError = __Pyx_GetBuiltinName(__pyx_n_s_AttributeError); if (!__pyx_builtin_AttributeError) __PYX_ERR(0, 149, __pyx_L1_error) + __pyx_builtin_SystemExit = __Pyx_GetBuiltinName(__pyx_n_s_SystemExit); if (!__pyx_builtin_SystemExit) __PYX_ERR(0, 375, __pyx_L1_error) + __pyx_builtin_GeneratorExit = __Pyx_GetBuiltinName(__pyx_n_s_GeneratorExit); if (!__pyx_builtin_GeneratorExit) __PYX_ERR(0, 378, __pyx_L1_error) + __pyx_builtin_KeyboardInterrupt = __Pyx_GetBuiltinName(__pyx_n_s_KeyboardInterrupt); if (!__pyx_builtin_KeyboardInterrupt) __PYX_ERR(0, 1367, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "_pydevd_bundle/pydevd_cython.pyx":151 + * raise AttributeError() + * except: + * with _set_additional_thread_info_lock: # <<<<<<<<<<<<<< + * # If it's not there, set it within a lock to avoid any racing + * # conditions. + */ + __pyx_tuple__2 = PyTuple_Pack(3, Py_None, Py_None, Py_None); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(0, 151, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__2); + __Pyx_GIVEREF(__pyx_tuple__2); + + /* "_pydevd_bundle/pydevd_cython.pyx":1177 + * filename = frame.f_code.co_filename + * if filename.endswith('.pyc'): + * filename = filename[:-1] # <<<<<<<<<<<<<< + * + * if not filename.endswith(PYDEVD_IPYTHON_CONTEXT[0]): + */ + __pyx_slice__4 = PySlice_New(Py_None, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__4)) __PYX_ERR(0, 1177, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice__4); + __Pyx_GIVEREF(__pyx_slice__4); + + /* "_pydevd_bundle/pydevd_cython.pyx":1489 + * if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'): + * # We need __bootstrap_inner, not __bootstrap. + * return None, False # <<<<<<<<<<<<<< + * + * elif f_unhandled.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'): + */ + __pyx_tuple__8 = PyTuple_Pack(2, Py_None, Py_False); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 1489, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__8); + __Pyx_GIVEREF(__pyx_tuple__8); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x75b3b02, 0x5f02be1, 0xa5a0d63): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x75b3b02, 0x5f02be1, 0xa5a0d63) = (conditional_breakpoint_exception, is_tracing, pydev_call_from_jinja2, pydev_call_inside_jinja2, pydev_django_resolve_frame, pydev_func_name, pydev_message, pydev_next_line, pydev_notify_kill, pydev_original_step_cmd, pydev_smart_child_offset, pydev_smart_parent_offset, pydev_smart_step_into_variants, pydev_smart_step_stop, pydev_state, pydev_step_cmd, pydev_step_stop, pydev_use_scoped_step_frame, step_in_initial_location, suspend_type, suspended_at_unhandled, target_id_to_smart_step_into_variant, thread_tracer, top_level_thread_tracer_no_back_frames, top_level_thread_tracer_unhandled, trace_suspend_type))" % __pyx_checksum) + */ + __pyx_tuple__9 = PyTuple_Pack(3, __pyx_int_123419394, __pyx_int_99625953, __pyx_int_173673827); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__9); + __Pyx_GIVEREF(__pyx_tuple__9); + __pyx_tuple__10 = PyTuple_Pack(3, __pyx_int_210464433, __pyx_int_230645316, __pyx_int_232881363); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__10); + __Pyx_GIVEREF(__pyx_tuple__10); + __pyx_tuple__11 = PyTuple_Pack(3, __pyx_int_84338306, __pyx_int_61391470, __pyx_int_192493205); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__11); + __Pyx_GIVEREF(__pyx_tuple__11); + __pyx_tuple__12 = PyTuple_Pack(3, __pyx_int_125568891, __pyx_int_169093275, __pyx_int_63705258); if (unlikely(!__pyx_tuple__12)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__12); + __Pyx_GIVEREF(__pyx_tuple__12); + __pyx_tuple__13 = PyTuple_Pack(3, __pyx_int_64458794, __pyx_int_18997755, __pyx_int_255484337); if (unlikely(!__pyx_tuple__13)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__13); + __Pyx_GIVEREF(__pyx_tuple__13); + __pyx_tuple__14 = PyTuple_Pack(3, __pyx_int_171613889, __pyx_int_66451433, __pyx_int_16751766); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(2, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__14); + __Pyx_GIVEREF(__pyx_tuple__14); + + /* "_pydevd_bundle/pydevd_cython.pyx":11 + * from _pydev_bundle import pydev_log + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * pydev_log.debug("Using Cython speedups") # <<<<<<<<<<<<<< + * # ELSE + * # from _pydevd_bundle.pydevd_frame import PyDBFrame + */ + __pyx_tuple__15 = PyTuple_Pack(1, __pyx_kp_s_Using_Cython_speedups); if (unlikely(!__pyx_tuple__15)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__15); + __Pyx_GIVEREF(__pyx_tuple__15); + + /* "_pydevd_bundle/pydevd_cython.pyx":145 + * + * + * def set_additional_thread_info(thread): # <<<<<<<<<<<<<< + * try: + * additional_info = thread.additional_info + */ + __pyx_tuple__16 = PyTuple_Pack(2, __pyx_n_s_thread, __pyx_n_s_additional_info); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(0, 145, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__16); + __Pyx_GIVEREF(__pyx_tuple__16); + __pyx_codeobj__17 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__16, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_bundle_pydevd_cython_pyx, __pyx_n_s_set_additional_thread_info, 145, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__17)) __PYX_ERR(0, 145, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":176 + * except ImportError: + * + * def get_smart_step_into_variant_from_frame_offset(*args, **kwargs): # <<<<<<<<<<<<<< + * return None + * + */ + __pyx_tuple__18 = PyTuple_Pack(2, __pyx_n_s_args, __pyx_n_s_kwargs); if (unlikely(!__pyx_tuple__18)) __PYX_ERR(0, 176, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__18); + __Pyx_GIVEREF(__pyx_tuple__18); + __pyx_codeobj__19 = (PyObject*)__Pyx_PyCode_New(0, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS|CO_VARARGS|CO_VARKEYWORDS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__18, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_bundle_pydevd_cython_pyx, __pyx_n_s_get_smart_step_into_variant_from, 176, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__19)) __PYX_ERR(0, 176, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":198 + * basename = os.path.basename + * + * IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') # <<<<<<<<<<<<<< + * DEBUG_START = ('pydevd.py', 'run') + * DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') + */ + __pyx_tuple__20 = PyTuple_Pack(1, __pyx_kp_s_IgnoreException); if (unlikely(!__pyx_tuple__20)) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__20); + __Pyx_GIVEREF(__pyx_tuple__20); + + /* "_pydevd_bundle/pydevd_cython.pyx":199 + * + * IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') + * DEBUG_START = ('pydevd.py', 'run') # <<<<<<<<<<<<<< + * DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') + * TRACE_PROPERTY = 'pydevd_traceproperty.py' + */ + __pyx_tuple__21 = PyTuple_Pack(2, __pyx_kp_s_pydevd_py, __pyx_n_s_run); if (unlikely(!__pyx_tuple__21)) __PYX_ERR(0, 199, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__21); + __Pyx_GIVEREF(__pyx_tuple__21); + + /* "_pydevd_bundle/pydevd_cython.pyx":200 + * IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') + * DEBUG_START = ('pydevd.py', 'run') + * DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') # <<<<<<<<<<<<<< + * TRACE_PROPERTY = 'pydevd_traceproperty.py' + * + */ + __pyx_tuple__22 = PyTuple_Pack(2, __pyx_kp_s_pydev_execfile_py, __pyx_n_s_execfile); if (unlikely(!__pyx_tuple__22)) __PYX_ERR(0, 200, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__22); + __Pyx_GIVEREF(__pyx_tuple__22); + + /* "_pydevd_bundle/pydevd_cython.pyx":1422 + * + * + * def notify_skipped_step_in_because_of_filters(py_db, frame): # <<<<<<<<<<<<<< + * global _global_notify_skipped_step_in + * + */ + __pyx_tuple__23 = PyTuple_Pack(2, __pyx_n_s_py_db, __pyx_n_s_frame); if (unlikely(!__pyx_tuple__23)) __PYX_ERR(0, 1422, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__23); + __Pyx_GIVEREF(__pyx_tuple__23); + __pyx_codeobj__24 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__23, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_bundle_pydevd_cython_pyx, __pyx_n_s_notify_skipped_step_in_because_o, 1422, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__24)) __PYX_ERR(0, 1422, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1452 + * + * + * def fix_top_level_trace_and_get_trace_func(py_db, frame): # <<<<<<<<<<<<<< + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef str filename; + */ + __pyx_tuple__25 = PyTuple_Pack(15, __pyx_n_s_py_db, __pyx_n_s_frame, __pyx_n_s_filename, __pyx_n_s_name_2, __pyx_n_s_args, __pyx_n_s_thread, __pyx_n_s_f_unhandled, __pyx_n_s_force_only_unhandled_tracer, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_t, __pyx_n_s_additional_info, __pyx_n_s_top_level_thread_tracer, __pyx_n_s_f_trace, __pyx_n_s_thread_tracer); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(0, 1452, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__25); + __Pyx_GIVEREF(__pyx_tuple__25); + __pyx_codeobj__26 = (PyObject*)__Pyx_PyCode_New(2, 0, 15, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__25, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_bundle_pydevd_cython_pyx, __pyx_n_s_fix_top_level_trace_and_get_trac, 1452, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__26)) __PYX_ERR(0, 1452, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1580 + * + * + * def trace_dispatch(py_db, frame, event, arg): # <<<<<<<<<<<<<< + * thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + * if thread_trace_func is None: + */ + __pyx_tuple__27 = PyTuple_Pack(6, __pyx_n_s_py_db, __pyx_n_s_frame, __pyx_n_s_event, __pyx_n_s_arg, __pyx_n_s_thread_trace_func, __pyx_n_s_apply_to_settrace); if (unlikely(!__pyx_tuple__27)) __PYX_ERR(0, 1580, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__27); + __Pyx_GIVEREF(__pyx_tuple__27); + __pyx_codeobj__28 = (PyObject*)__Pyx_PyCode_New(4, 0, 6, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__27, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_bundle_pydevd_cython_pyx, __pyx_n_s_trace_dispatch, 1580, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__28)) __PYX_ERR(0, 1580, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":1866 + * _original_call = ThreadTracer.__call__ + * + * def __call__(self, frame, event, arg): # <<<<<<<<<<<<<< + * constructed_tid_to_last_frame[self._args[1].ident] = frame + * return _original_call(self, frame, event, arg) + */ + __pyx_tuple__29 = PyTuple_Pack(4, __pyx_n_s_self, __pyx_n_s_frame, __pyx_n_s_event, __pyx_n_s_arg); if (unlikely(!__pyx_tuple__29)) __PYX_ERR(0, 1866, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__29); + __Pyx_GIVEREF(__pyx_tuple__29); + __pyx_codeobj__30 = (PyObject*)__Pyx_PyCode_New(4, 0, 4, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__29, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_bundle_pydevd_cython_pyx, __pyx_n_s_call_2, 1866, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__30)) __PYX_ERR(0, 1866, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __pyx_unpickle_PyDBAdditionalThreadInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_tuple__31 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__31)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__31); + __Pyx_GIVEREF(__pyx_tuple__31); + __pyx_codeobj__32 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__31, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_PyDBAdditionalThr, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__32)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_tuple__33 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__33)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__33); + __Pyx_GIVEREF(__pyx_tuple__33); + __pyx_codeobj__34 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__33, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle__TryExceptContain, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__34)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_tuple__35 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__35)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__35); + __Pyx_GIVEREF(__pyx_tuple__35); + __pyx_codeobj__36 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__35, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_PyDBFrame, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__36)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_tuple__37 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__37)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__37); + __Pyx_GIVEREF(__pyx_tuple__37); + __pyx_codeobj__38 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__37, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_SafeCallWrapper, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__38)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_tuple__39 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__39)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__39); + __Pyx_GIVEREF(__pyx_tuple__39); + __pyx_codeobj__40 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__39, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_TopLevelThreadTra, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__40)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_tuple__41 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__41)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__41); + __Pyx_GIVEREF(__pyx_tuple__41); + __pyx_codeobj__42 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__41, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_TopLevelThreadTra_2, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__42)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_tuple__43 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__43)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__43); + __Pyx_GIVEREF(__pyx_tuple__43); + __pyx_codeobj__44 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__43, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_ThreadTracer, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__44)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + __pyx_umethod_PyDict_Type_get.type = (PyObject*)&PyDict_Type; + __pyx_umethod_PyDict_Type_update.type = (PyObject*)&PyDict_Type; + __pyx_umethod_PyDict_Type_values.type = (PyObject*)&PyDict_Type; + __pyx_umethod_PyString_Type_rfind.type = (PyObject*)&PyString_Type; + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_11 = PyInt_FromLong(11); if (unlikely(!__pyx_int_11)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_111 = PyInt_FromLong(111); if (unlikely(!__pyx_int_111)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_137 = PyInt_FromLong(137); if (unlikely(!__pyx_int_137)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_160 = PyInt_FromLong(160); if (unlikely(!__pyx_int_160)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_16751766 = PyInt_FromLong(16751766L); if (unlikely(!__pyx_int_16751766)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_18997755 = PyInt_FromLong(18997755L); if (unlikely(!__pyx_int_18997755)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_61391470 = PyInt_FromLong(61391470L); if (unlikely(!__pyx_int_61391470)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_63705258 = PyInt_FromLong(63705258L); if (unlikely(!__pyx_int_63705258)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_64458794 = PyInt_FromLong(64458794L); if (unlikely(!__pyx_int_64458794)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_66451433 = PyInt_FromLong(66451433L); if (unlikely(!__pyx_int_66451433)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_84338306 = PyInt_FromLong(84338306L); if (unlikely(!__pyx_int_84338306)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_99625953 = PyInt_FromLong(99625953L); if (unlikely(!__pyx_int_99625953)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_123419394 = PyInt_FromLong(123419394L); if (unlikely(!__pyx_int_123419394)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_125568891 = PyInt_FromLong(125568891L); if (unlikely(!__pyx_int_125568891)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_169093275 = PyInt_FromLong(169093275L); if (unlikely(!__pyx_int_169093275)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_171613889 = PyInt_FromLong(171613889L); if (unlikely(!__pyx_int_171613889)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_173673827 = PyInt_FromLong(173673827L); if (unlikely(!__pyx_int_173673827)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_192493205 = PyInt_FromLong(192493205L); if (unlikely(!__pyx_int_192493205)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_210464433 = PyInt_FromLong(210464433L); if (unlikely(!__pyx_int_210464433)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_230645316 = PyInt_FromLong(230645316L); if (unlikely(!__pyx_int_230645316)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_232881363 = PyInt_FromLong(232881363L); if (unlikely(!__pyx_int_232881363)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_255484337 = PyInt_FromLong(255484337L); if (unlikely(!__pyx_int_255484337)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in = ((PyObject*)Py_None); Py_INCREF(Py_None); + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + if (PyType_Ready(&__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo) < 0) __PYX_ERR(0, 23, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo.tp_dictoffset && __pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_PyDBAdditionalThreadInfo, (PyObject *)&__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo) < 0) __PYX_ERR(0, 23, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo) < 0) __PYX_ERR(0, 23, __pyx_L1_error) + __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo = &__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo; + if (PyType_Ready(&__pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj) < 0) __PYX_ERR(0, 255, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj.tp_dictoffset && __pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_TryExceptContainerObj, (PyObject *)&__pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj) < 0) __PYX_ERR(0, 255, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj) < 0) __PYX_ERR(0, 255, __pyx_L1_error) + __pyx_ptype_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj = &__pyx_type_14_pydevd_bundle_13pydevd_cython__TryExceptContainerObj; + __pyx_vtabptr_14_pydevd_bundle_13pydevd_cython_PyDBFrame = &__pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame; + __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame._should_stop_on_exception = (PyObject *(*)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *, PyObject *))__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__should_stop_on_exception; + __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame._handle_exception = (PyObject *(*)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *, PyObject *, PyObject *))__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__handle_exception; + __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame.get_func_name = (PyObject *(*)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *))__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_get_func_name; + __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame._show_return_values = (PyObject *(*)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *))__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__show_return_values; + __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame._remove_return_values = (PyObject *(*)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *))__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__remove_return_values; + __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame._get_unfiltered_back_frame = (PyObject *(*)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *))__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__get_unfiltered_back_frame; + __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame._is_same_frame = (PyObject *(*)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *))__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame__is_same_frame; + __pyx_vtable_14_pydevd_bundle_13pydevd_cython_PyDBFrame.trace_dispatch = (PyObject *(*)(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBFrame *, PyObject *, PyObject *, PyObject *, int __pyx_skip_dispatch))__pyx_f_14_pydevd_bundle_13pydevd_cython_9PyDBFrame_trace_dispatch; + if (PyType_Ready(&__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame) < 0) __PYX_ERR(0, 273, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame.tp_dictoffset && __pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (__Pyx_SetVtable(__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame.tp_dict, __pyx_vtabptr_14_pydevd_bundle_13pydevd_cython_PyDBFrame) < 0) __PYX_ERR(0, 273, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_PyDBFrame, (PyObject *)&__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame) < 0) __PYX_ERR(0, 273, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame) < 0) __PYX_ERR(0, 273, __pyx_L1_error) + __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBFrame = &__pyx_type_14_pydevd_bundle_13pydevd_cython_PyDBFrame; + if (PyType_Ready(&__pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper) < 0) __PYX_ERR(0, 1434, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper.tp_dictoffset && __pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_SafeCallWrapper, (PyObject *)&__pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper) < 0) __PYX_ERR(0, 1434, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper) < 0) __PYX_ERR(0, 1434, __pyx_L1_error) + __pyx_ptype_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper = &__pyx_type_14_pydevd_bundle_13pydevd_cython_SafeCallWrapper; + if (PyType_Ready(&__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions) < 0) __PYX_ERR(0, 1590, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions.tp_dictoffset && __pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_TopLevelThreadTracerOnlyUnhandle, (PyObject *)&__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions) < 0) __PYX_ERR(0, 1590, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions) < 0) __PYX_ERR(0, 1590, __pyx_L1_error) + __pyx_ptype_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions = &__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerOnlyUnhandledExceptions; + if (PyType_Ready(&__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame) < 0) __PYX_ERR(0, 1620, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame.tp_dictoffset && __pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_TopLevelThreadTracerNoBackFrame, (PyObject *)&__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame) < 0) __PYX_ERR(0, 1620, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame) < 0) __PYX_ERR(0, 1620, __pyx_L1_error) + __pyx_ptype_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame = &__pyx_type_14_pydevd_bundle_13pydevd_cython_TopLevelThreadTracerNoBackFrame; + if (PyType_Ready(&__pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer) < 0) __PYX_ERR(0, 1695, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer.tp_dictoffset && __pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + #if CYTHON_UPDATE_DESCRIPTOR_DOC + { + PyObject *wrapper = PyObject_GetAttrString((PyObject *)&__pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer, "__call__"); if (unlikely(!wrapper)) __PYX_ERR(0, 1695, __pyx_L1_error) + if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) { + __pyx_wrapperbase_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_2__call__ = *((PyWrapperDescrObject *)wrapper)->d_base; + __pyx_wrapperbase_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_2__call__.doc = __pyx_doc_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_2__call__; + ((PyWrapperDescrObject *)wrapper)->d_base = &__pyx_wrapperbase_14_pydevd_bundle_13pydevd_cython_12ThreadTracer_2__call__; + } + } + #endif + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_ThreadTracer, (PyObject *)&__pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer) < 0) __PYX_ERR(0, 1695, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer) < 0) __PYX_ERR(0, 1695, __pyx_L1_error) + __pyx_ptype_14_pydevd_bundle_13pydevd_cython_ThreadTracer = &__pyx_type_14_pydevd_bundle_13pydevd_cython_ThreadTracer; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyTypeObject), + #else + sizeof(PyHeapTypeObject), + #endif + __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(3, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + +#ifndef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#elif PY_MAJOR_VERSION < 3 +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" void +#else +#define __Pyx_PyMODINIT_FUNC void +#endif +#else +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyObject * +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initpydevd_cython(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initpydevd_cython(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_pydevd_cython(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_pydevd_cython(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_pydevd_cython(PyObject *__pyx_pyinit_module) +#endif +#endif +{ + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_t_9; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'pydevd_cython' has already been imported. Re-initialisation is not supported."); + return -1; + } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_pydevd_cython(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + PyEval_InitThreads(); + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("pydevd_cython", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_b); + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_cython_runtime); + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main__pydevd_bundle__pydevd_cython) { + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "_pydevd_bundle.pydevd_cython")) { + if (unlikely(PyDict_SetItemString(modules, "_pydevd_bundle.pydevd_cython", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + if (unlikely(__Pyx_modinit_type_init_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + if (unlikely(__Pyx_modinit_type_import_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + + /* "_pydevd_bundle/pydevd_cython.pyx":7 + * # DO NOT edit manually! + * # DO NOT edit manually! + * from _pydevd_bundle.pydevd_constants import (STATE_RUN, PYTHON_SUSPEND, SUPPORT_GEVENT, ForkSafeLock, # <<<<<<<<<<<<<< + * _current_frames) + * from _pydev_bundle import pydev_log + */ + __pyx_t_1 = PyList_New(5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_STATE_RUN); + __Pyx_GIVEREF(__pyx_n_s_STATE_RUN); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_STATE_RUN); + __Pyx_INCREF(__pyx_n_s_PYTHON_SUSPEND); + __Pyx_GIVEREF(__pyx_n_s_PYTHON_SUSPEND); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_PYTHON_SUSPEND); + __Pyx_INCREF(__pyx_n_s_SUPPORT_GEVENT); + __Pyx_GIVEREF(__pyx_n_s_SUPPORT_GEVENT); + PyList_SET_ITEM(__pyx_t_1, 2, __pyx_n_s_SUPPORT_GEVENT); + __Pyx_INCREF(__pyx_n_s_ForkSafeLock); + __Pyx_GIVEREF(__pyx_n_s_ForkSafeLock); + PyList_SET_ITEM(__pyx_t_1, 3, __pyx_n_s_ForkSafeLock); + __Pyx_INCREF(__pyx_n_s_current_frames); + __Pyx_GIVEREF(__pyx_n_s_current_frames); + PyList_SET_ITEM(__pyx_t_1, 4, __pyx_n_s_current_frames); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_constants, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_STATE_RUN); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_STATE_RUN, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_PYTHON_SUSPEND); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_PYTHON_SUSPEND, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_SUPPORT_GEVENT); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_SUPPORT_GEVENT, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_ForkSafeLock); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_ForkSafeLock, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_current_frames); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_current_frames, __pyx_t_1) < 0) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":9 + * from _pydevd_bundle.pydevd_constants import (STATE_RUN, PYTHON_SUSPEND, SUPPORT_GEVENT, ForkSafeLock, + * _current_frames) + * from _pydev_bundle import pydev_log # <<<<<<<<<<<<<< + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * pydev_log.debug("Using Cython speedups") + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_pydev_log); + __Pyx_GIVEREF(__pyx_n_s_pydev_log); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_pydev_log); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydev_bundle, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pydev_log, __pyx_t_2) < 0) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":11 + * from _pydev_bundle import pydev_log + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * pydev_log.debug("Using Cython speedups") # <<<<<<<<<<<<<< + * # ELSE + * # from _pydevd_bundle.pydevd_frame import PyDBFrame + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_debug); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__15, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":16 + * # ENDIF + * + * version = 11 # <<<<<<<<<<<<<< + * + * + */ + if (PyDict_SetItem(__pyx_d, __pyx_n_s_version, __pyx_int_11) < 0) __PYX_ERR(0, 16, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":142 + * + * + * _set_additional_thread_info_lock = ForkSafeLock() # <<<<<<<<<<<<<< + * + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_ForkSafeLock); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 142, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 142, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_d, __pyx_n_s_set_additional_thread_info_lock, __pyx_t_2) < 0) __PYX_ERR(0, 142, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":145 + * + * + * def set_additional_thread_info(thread): # <<<<<<<<<<<<<< + * try: + * additional_info = thread.additional_info + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_1set_additional_thread_info, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 145, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_set_additional_thread_info, __pyx_t_2) < 0) __PYX_ERR(0, 145, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":160 + * + * return additional_info + * import linecache # <<<<<<<<<<<<<< + * import os.path + * import re + */ + __pyx_t_2 = __Pyx_Import(__pyx_n_s_linecache, 0, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 160, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_linecache, __pyx_t_2) < 0) __PYX_ERR(0, 160, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":161 + * return additional_info + * import linecache + * import os.path # <<<<<<<<<<<<<< + * import re + * + */ + __pyx_t_2 = __Pyx_Import(__pyx_n_s_os_path, 0, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 161, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_os, __pyx_t_2) < 0) __PYX_ERR(0, 161, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":162 + * import linecache + * import os.path + * import re # <<<<<<<<<<<<<< + * + * from _pydev_bundle import pydev_log + */ + __pyx_t_2 = __Pyx_Import(__pyx_n_s_re, 0, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_re, __pyx_t_2) < 0) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":164 + * import re + * + * from _pydev_bundle import pydev_log # <<<<<<<<<<<<<< + * from _pydevd_bundle import pydevd_dont_trace + * from _pydevd_bundle.pydevd_constants import (RETURN_VALUES_DICT, NO_FTRACE, + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_pydev_log); + __Pyx_GIVEREF(__pyx_n_s_pydev_log); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_pydev_log); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydev_bundle, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_pydev_log); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pydev_log, __pyx_t_2) < 0) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":165 + * + * from _pydev_bundle import pydev_log + * from _pydevd_bundle import pydevd_dont_trace # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_constants import (RETURN_VALUES_DICT, NO_FTRACE, + * EXCEPTION_TYPE_HANDLED, EXCEPTION_TYPE_USER_UNHANDLED, PYDEVD_IPYTHON_CONTEXT) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 165, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_pydevd_dont_trace); + __Pyx_GIVEREF(__pyx_n_s_pydevd_dont_trace); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_pydevd_dont_trace); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_bundle, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 165, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_pydevd_dont_trace); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 165, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pydevd_dont_trace, __pyx_t_1) < 0) __PYX_ERR(0, 165, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":166 + * from _pydev_bundle import pydev_log + * from _pydevd_bundle import pydevd_dont_trace + * from _pydevd_bundle.pydevd_constants import (RETURN_VALUES_DICT, NO_FTRACE, # <<<<<<<<<<<<<< + * EXCEPTION_TYPE_HANDLED, EXCEPTION_TYPE_USER_UNHANDLED, PYDEVD_IPYTHON_CONTEXT) + * from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace + */ + __pyx_t_2 = PyList_New(5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_RETURN_VALUES_DICT); + __Pyx_GIVEREF(__pyx_n_s_RETURN_VALUES_DICT); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_RETURN_VALUES_DICT); + __Pyx_INCREF(__pyx_n_s_NO_FTRACE); + __Pyx_GIVEREF(__pyx_n_s_NO_FTRACE); + PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_NO_FTRACE); + __Pyx_INCREF(__pyx_n_s_EXCEPTION_TYPE_HANDLED); + __Pyx_GIVEREF(__pyx_n_s_EXCEPTION_TYPE_HANDLED); + PyList_SET_ITEM(__pyx_t_2, 2, __pyx_n_s_EXCEPTION_TYPE_HANDLED); + __Pyx_INCREF(__pyx_n_s_EXCEPTION_TYPE_USER_UNHANDLED); + __Pyx_GIVEREF(__pyx_n_s_EXCEPTION_TYPE_USER_UNHANDLED); + PyList_SET_ITEM(__pyx_t_2, 3, __pyx_n_s_EXCEPTION_TYPE_USER_UNHANDLED); + __Pyx_INCREF(__pyx_n_s_PYDEVD_IPYTHON_CONTEXT); + __Pyx_GIVEREF(__pyx_n_s_PYDEVD_IPYTHON_CONTEXT); + PyList_SET_ITEM(__pyx_t_2, 4, __pyx_n_s_PYDEVD_IPYTHON_CONTEXT); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_constants, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_RETURN_VALUES_DICT); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_RETURN_VALUES_DICT, __pyx_t_2) < 0) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_FTRACE, __pyx_t_2) < 0) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_EXCEPTION_TYPE_HANDLED); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_EXCEPTION_TYPE_HANDLED, __pyx_t_2) < 0) __PYX_ERR(0, 167, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_EXCEPTION_TYPE_USER_UNHANDLED); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_EXCEPTION_TYPE_USER_UNHANDLED, __pyx_t_2) < 0) __PYX_ERR(0, 167, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_PYDEVD_IPYTHON_CONTEXT); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_PYDEVD_IPYTHON_CONTEXT, __pyx_t_2) < 0) __PYX_ERR(0, 167, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":168 + * from _pydevd_bundle.pydevd_constants import (RETURN_VALUES_DICT, NO_FTRACE, + * EXCEPTION_TYPE_HANDLED, EXCEPTION_TYPE_USER_UNHANDLED, PYDEVD_IPYTHON_CONTEXT) + * from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_utils import get_clsname_for_code + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame + */ + __pyx_t_1 = PyList_New(4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_add_exception_to_frame); + __Pyx_GIVEREF(__pyx_n_s_add_exception_to_frame); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_add_exception_to_frame); + __Pyx_INCREF(__pyx_n_s_just_raised); + __Pyx_GIVEREF(__pyx_n_s_just_raised); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_just_raised); + __Pyx_INCREF(__pyx_n_s_remove_exception_from_frame); + __Pyx_GIVEREF(__pyx_n_s_remove_exception_from_frame); + PyList_SET_ITEM(__pyx_t_1, 2, __pyx_n_s_remove_exception_from_frame); + __Pyx_INCREF(__pyx_n_s_ignore_exception_trace); + __Pyx_GIVEREF(__pyx_n_s_ignore_exception_trace); + PyList_SET_ITEM(__pyx_t_1, 3, __pyx_n_s_ignore_exception_trace); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_frame_util, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_add_exception_to_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_add_exception_to_frame, __pyx_t_1) < 0) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_just_raised); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_just_raised, __pyx_t_1) < 0) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_remove_exception_from_frame); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_remove_exception_from_frame, __pyx_t_1) < 0) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_ignore_exception_trace); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_ignore_exception_trace, __pyx_t_1) < 0) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":169 + * EXCEPTION_TYPE_HANDLED, EXCEPTION_TYPE_USER_UNHANDLED, PYDEVD_IPYTHON_CONTEXT) + * from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace + * from _pydevd_bundle.pydevd_utils import get_clsname_for_code # <<<<<<<<<<<<<< + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame + * from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 169, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_get_clsname_for_code); + __Pyx_GIVEREF(__pyx_n_s_get_clsname_for_code); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_get_clsname_for_code); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_utils, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 169, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_get_clsname_for_code); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 169, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_clsname_for_code, __pyx_t_2) < 0) __PYX_ERR(0, 169, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":170 + * from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace + * from _pydevd_bundle.pydevd_utils import get_clsname_for_code + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK + * try: + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 170, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_get_abs_path_real_path_and_base); + __Pyx_GIVEREF(__pyx_n_s_get_abs_path_real_path_and_base); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_get_abs_path_real_path_and_base); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_file_utils, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 170, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_get_abs_path_real_path_and_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 170, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_abs_path_real_path_and_base, __pyx_t_1) < 0) __PYX_ERR(0, 170, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":171 + * from _pydevd_bundle.pydevd_utils import get_clsname_for_code + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame + * from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK # <<<<<<<<<<<<<< + * try: + * from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset + */ + __pyx_t_2 = PyList_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_constant_to_str); + __Pyx_GIVEREF(__pyx_n_s_constant_to_str); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_constant_to_str); + __Pyx_INCREF(__pyx_n_s_CMD_SET_FUNCTION_BREAK); + __Pyx_GIVEREF(__pyx_n_s_CMD_SET_FUNCTION_BREAK); + PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_CMD_SET_FUNCTION_BREAK); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_comm_const, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_constant_to_str); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_constant_to_str, __pyx_t_2) < 0) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_CMD_SET_FUNCTION_BREAK); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_CMD_SET_FUNCTION_BREAK, __pyx_t_2) < 0) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":172 + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame + * from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK + * try: # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset + * except ImportError: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_3, &__pyx_t_4, &__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_5); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":173 + * from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK + * try: + * from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset # <<<<<<<<<<<<<< + * except ImportError: + * + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 173, __pyx_L2_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_get_smart_step_into_variant_from); + __Pyx_GIVEREF(__pyx_n_s_get_smart_step_into_variant_from); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_get_smart_step_into_variant_from); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_bytecode_u, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L2_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_get_smart_step_into_variant_from); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 173, __pyx_L2_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_smart_step_into_variant_from, __pyx_t_1) < 0) __PYX_ERR(0, 173, __pyx_L2_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":172 + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame + * from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK + * try: # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset + * except ImportError: + */ + } + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L7_try_end; + __pyx_L2_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":174 + * try: + * from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset + * except ImportError: # <<<<<<<<<<<<<< + * + * def get_smart_step_into_variant_from_frame_offset(*args, **kwargs): + */ + __pyx_t_6 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_ImportError); + if (__pyx_t_6) { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_1, &__pyx_t_7) < 0) __PYX_ERR(0, 174, __pyx_L4_except_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_7); + + /* "_pydevd_bundle/pydevd_cython.pyx":176 + * except ImportError: + * + * def get_smart_step_into_variant_from_frame_offset(*args, **kwargs): # <<<<<<<<<<<<<< + * return None + * + */ + __pyx_t_8 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_3get_smart_step_into_variant_from_frame_offset, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 176, __pyx_L4_except_error) + __Pyx_GOTREF(__pyx_t_8); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_smart_step_into_variant_from, __pyx_t_8) < 0) __PYX_ERR(0, 176, __pyx_L4_except_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L3_exception_handled; + } + goto __pyx_L4_except_error; + __pyx_L4_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":172 + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame + * from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK + * try: # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset + * except ImportError: + */ + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_ExceptionReset(__pyx_t_3, __pyx_t_4, __pyx_t_5); + goto __pyx_L1_error; + __pyx_L3_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_ExceptionReset(__pyx_t_3, __pyx_t_4, __pyx_t_5); + __pyx_L7_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":196 + * # ENDIF + * + * basename = os.path.basename # <<<<<<<<<<<<<< + * + * IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_os); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_path); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_basename); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_d, __pyx_n_s_basename, __pyx_t_7) < 0) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":198 + * basename = os.path.basename + * + * IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') # <<<<<<<<<<<<<< + * DEBUG_START = ('pydevd.py', 'run') + * DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_re); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_compile); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__20, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_d, __pyx_n_s_IGNORE_EXCEPTION_TAG, __pyx_t_7) < 0) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":199 + * + * IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') + * DEBUG_START = ('pydevd.py', 'run') # <<<<<<<<<<<<<< + * DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') + * TRACE_PROPERTY = 'pydevd_traceproperty.py' + */ + if (PyDict_SetItem(__pyx_d, __pyx_n_s_DEBUG_START, __pyx_tuple__21) < 0) __PYX_ERR(0, 199, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":200 + * IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') + * DEBUG_START = ('pydevd.py', 'run') + * DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') # <<<<<<<<<<<<<< + * TRACE_PROPERTY = 'pydevd_traceproperty.py' + * + */ + if (PyDict_SetItem(__pyx_d, __pyx_n_s_DEBUG_START_PY3K, __pyx_tuple__22) < 0) __PYX_ERR(0, 200, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":201 + * DEBUG_START = ('pydevd.py', 'run') + * DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') + * TRACE_PROPERTY = 'pydevd_traceproperty.py' # <<<<<<<<<<<<<< + * + * import dis + */ + if (PyDict_SetItem(__pyx_d, __pyx_n_s_TRACE_PROPERTY, __pyx_kp_s_pydevd_traceproperty_py) < 0) __PYX_ERR(0, 201, __pyx_L1_error) + + /* "_pydevd_bundle/pydevd_cython.pyx":203 + * TRACE_PROPERTY = 'pydevd_traceproperty.py' + * + * import dis # <<<<<<<<<<<<<< + * + * try: + */ + __pyx_t_7 = __Pyx_Import(__pyx_n_s_dis, 0, -1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 203, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_dis, __pyx_t_7) < 0) __PYX_ERR(0, 203, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":205 + * import dis + * + * try: # <<<<<<<<<<<<<< + * StopAsyncIteration + * except NameError: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_4, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "_pydevd_bundle/pydevd_cython.pyx":206 + * + * try: + * StopAsyncIteration # <<<<<<<<<<<<<< + * except NameError: + * StopAsyncIteration = StopIteration + */ + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_StopAsyncIteration); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 206, __pyx_L10_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":205 + * import dis + * + * try: # <<<<<<<<<<<<<< + * StopAsyncIteration + * except NameError: + */ + } + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L15_try_end; + __pyx_L10_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":207 + * try: + * StopAsyncIteration + * except NameError: # <<<<<<<<<<<<<< + * StopAsyncIteration = StopIteration + * + */ + __pyx_t_6 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_NameError); + if (__pyx_t_6) { + __Pyx_AddTraceback("_pydevd_bundle.pydevd_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_1, &__pyx_t_2) < 0) __PYX_ERR(0, 207, __pyx_L12_except_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_2); + + /* "_pydevd_bundle/pydevd_cython.pyx":208 + * StopAsyncIteration + * except NameError: + * StopAsyncIteration = StopIteration # <<<<<<<<<<<<<< + * + * + */ + if (PyDict_SetItem(__pyx_d, __pyx_n_s_StopAsyncIteration, __pyx_builtin_StopIteration) < 0) __PYX_ERR(0, 208, __pyx_L12_except_error) + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + goto __pyx_L11_exception_handled; + } + goto __pyx_L12_except_error; + __pyx_L12_except_error:; + + /* "_pydevd_bundle/pydevd_cython.pyx":205 + * import dis + * + * try: # <<<<<<<<<<<<<< + * StopAsyncIteration + * except NameError: + */ + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_4, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L11_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_4, __pyx_t_3); + __pyx_L15_try_end:; + } + + /* "_pydevd_bundle/pydevd_cython.pyx":286 + * # Same thing in the main debugger but only considering the file contents, while the one in the main debugger + * # considers the user input (so, the actual result must be a join of both). + * filename_to_lines_where_exceptions_are_ignored = {} # <<<<<<<<<<<<<< + * filename_to_stat_info = {} + * + */ + __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 286, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBFrame->tp_dict, __pyx_n_s_filename_to_lines_where_exceptio, __pyx_t_2) < 0) __PYX_ERR(0, 286, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + PyType_Modified(__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBFrame); + + /* "_pydevd_bundle/pydevd_cython.pyx":287 + * # considers the user input (so, the actual result must be a join of both). + * filename_to_lines_where_exceptions_are_ignored = {} + * filename_to_stat_info = {} # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 287, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBFrame->tp_dict, __pyx_n_s_filename_to_stat_info, __pyx_t_2) < 0) __PYX_ERR(0, 287, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + PyType_Modified(__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBFrame); + + /* "_pydevd_bundle/pydevd_cython.pyx":1387 + * + * # end trace_dispatch + * from _pydev_bundle.pydev_is_thread_alive import is_thread_alive # <<<<<<<<<<<<<< + * from _pydev_bundle.pydev_log import exception as pydev_log_exception + * from _pydev_bundle._pydev_saved_modules import threading + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1387, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_is_thread_alive); + __Pyx_GIVEREF(__pyx_n_s_is_thread_alive); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_is_thread_alive); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydev_bundle_pydev_is_thread_al, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1387, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_is_thread_alive); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1387, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_is_thread_alive, __pyx_t_2) < 0) __PYX_ERR(0, 1387, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1388 + * # end trace_dispatch + * from _pydev_bundle.pydev_is_thread_alive import is_thread_alive + * from _pydev_bundle.pydev_log import exception as pydev_log_exception # <<<<<<<<<<<<<< + * from _pydev_bundle._pydev_saved_modules import threading + * from _pydevd_bundle.pydevd_constants import (get_current_thread_id, NO_FTRACE, + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1388, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_exception); + __Pyx_GIVEREF(__pyx_n_s_exception); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_exception); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydev_bundle_pydev_log, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1388, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_exception); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1388, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pydev_log_exception, __pyx_t_1) < 0) __PYX_ERR(0, 1388, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1389 + * from _pydev_bundle.pydev_is_thread_alive import is_thread_alive + * from _pydev_bundle.pydev_log import exception as pydev_log_exception + * from _pydev_bundle._pydev_saved_modules import threading # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_constants import (get_current_thread_id, NO_FTRACE, + * USE_CUSTOM_SYS_CURRENT_FRAMES_MAP, ForkSafeLock) + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1389, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_threading); + __Pyx_GIVEREF(__pyx_n_s_threading); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_threading); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydev_bundle__pydev_saved_modul, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1389, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_threading); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1389, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_threading, __pyx_t_2) < 0) __PYX_ERR(0, 1389, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1390 + * from _pydev_bundle.pydev_log import exception as pydev_log_exception + * from _pydev_bundle._pydev_saved_modules import threading + * from _pydevd_bundle.pydevd_constants import (get_current_thread_id, NO_FTRACE, # <<<<<<<<<<<<<< + * USE_CUSTOM_SYS_CURRENT_FRAMES_MAP, ForkSafeLock) + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER + */ + __pyx_t_1 = PyList_New(4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1390, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_get_current_thread_id); + __Pyx_GIVEREF(__pyx_n_s_get_current_thread_id); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_get_current_thread_id); + __Pyx_INCREF(__pyx_n_s_NO_FTRACE); + __Pyx_GIVEREF(__pyx_n_s_NO_FTRACE); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_NO_FTRACE); + __Pyx_INCREF(__pyx_n_s_USE_CUSTOM_SYS_CURRENT_FRAMES_MA); + __Pyx_GIVEREF(__pyx_n_s_USE_CUSTOM_SYS_CURRENT_FRAMES_MA); + PyList_SET_ITEM(__pyx_t_1, 2, __pyx_n_s_USE_CUSTOM_SYS_CURRENT_FRAMES_MA); + __Pyx_INCREF(__pyx_n_s_ForkSafeLock); + __Pyx_GIVEREF(__pyx_n_s_ForkSafeLock); + PyList_SET_ITEM(__pyx_t_1, 3, __pyx_n_s_ForkSafeLock); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_constants, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1390, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_get_current_thread_id); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1390, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_current_thread_id, __pyx_t_1) < 0) __PYX_ERR(0, 1390, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_NO_FTRACE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1390, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_FTRACE, __pyx_t_1) < 0) __PYX_ERR(0, 1390, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_USE_CUSTOM_SYS_CURRENT_FRAMES_MA); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1390, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_USE_CUSTOM_SYS_CURRENT_FRAMES_MA, __pyx_t_1) < 0) __PYX_ERR(0, 1391, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_ForkSafeLock); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1390, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_ForkSafeLock, __pyx_t_1) < 0) __PYX_ERR(0, 1391, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1392 + * from _pydevd_bundle.pydevd_constants import (get_current_thread_id, NO_FTRACE, + * USE_CUSTOM_SYS_CURRENT_FRAMES_MAP, ForkSafeLock) + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER # <<<<<<<<<<<<<< + * + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + */ + __pyx_t_2 = PyList_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1392, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_get_abs_path_real_path_and_base); + __Pyx_GIVEREF(__pyx_n_s_get_abs_path_real_path_and_base); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_get_abs_path_real_path_and_base); + __Pyx_INCREF(__pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); + __Pyx_GIVEREF(__pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); + PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_file_utils, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1392, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_get_abs_path_real_path_and_base); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1392, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_abs_path_real_path_and_base, __pyx_t_2) < 0) __PYX_ERR(0, 1392, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1392, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER, __pyx_t_2) < 0) __PYX_ERR(0, 1392, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1415 + * # - Breakpoints are changed + * # It can be used when running regularly (without step over/step in/step return) + * global_cache_skips = {} # <<<<<<<<<<<<<< + * global_cache_frame_skips = {} + * + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1415, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_global_cache_skips, __pyx_t_1) < 0) __PYX_ERR(0, 1415, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1416 + * # It can be used when running regularly (without step over/step in/step return) + * global_cache_skips = {} + * global_cache_frame_skips = {} # <<<<<<<<<<<<<< + * + * _global_notify_skipped_step_in = False + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1416, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_global_cache_frame_skips, __pyx_t_1) < 0) __PYX_ERR(0, 1416, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1418 + * global_cache_frame_skips = {} + * + * _global_notify_skipped_step_in = False # <<<<<<<<<<<<<< + * _global_notify_skipped_step_in_lock = ForkSafeLock() + * + */ + __Pyx_INCREF(Py_False); + __Pyx_XGOTREF(__pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in); + __Pyx_DECREF_SET(__pyx_v_14_pydevd_bundle_13pydevd_cython__global_notify_skipped_step_in, ((PyObject*)Py_False)); + __Pyx_GIVEREF(Py_False); + + /* "_pydevd_bundle/pydevd_cython.pyx":1419 + * + * _global_notify_skipped_step_in = False + * _global_notify_skipped_step_in_lock = ForkSafeLock() # <<<<<<<<<<<<<< + * + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_ForkSafeLock); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1419, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_d, __pyx_n_s_global_notify_skipped_step_in_l, __pyx_t_2) < 0) __PYX_ERR(0, 1419, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1422 + * + * + * def notify_skipped_step_in_because_of_filters(py_db, frame): # <<<<<<<<<<<<<< + * global _global_notify_skipped_step_in + * + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_5notify_skipped_step_in_because_of_filters, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1422, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_notify_skipped_step_in_because_o, __pyx_t_2) < 0) __PYX_ERR(0, 1422, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1452 + * + * + * def fix_top_level_trace_and_get_trace_func(py_db, frame): # <<<<<<<<<<<<<< + * # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + * cdef str filename; + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_7fix_top_level_trace_and_get_trace_func, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1452, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_fix_top_level_trace_and_get_trac, __pyx_t_2) < 0) __PYX_ERR(0, 1452, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1580 + * + * + * def trace_dispatch(py_db, frame, event, arg): # <<<<<<<<<<<<<< + * thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + * if thread_trace_func is None: + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_9trace_dispatch, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1580, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_trace_dispatch, __pyx_t_2) < 0) __PYX_ERR(0, 1580, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1854 + * + * + * if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP: # <<<<<<<<<<<<<< + * # This is far from ideal, as we'll leak frames (we'll always have the last created frame, not really + * # the last topmost frame saved -- this should be Ok for our usage, but it may leak frames and things + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_USE_CUSTOM_SYS_CURRENT_FRAMES_MA); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1854, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 1854, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__pyx_t_9) { + + /* "_pydevd_bundle/pydevd_cython.pyx":1862 + * # + * # See: https://github.com/IronLanguages/main/issues/1630 + * from _pydevd_bundle.pydevd_constants import constructed_tid_to_last_frame # <<<<<<<<<<<<<< + * + * _original_call = ThreadTracer.__call__ + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1862, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_constructed_tid_to_last_frame); + __Pyx_GIVEREF(__pyx_n_s_constructed_tid_to_last_frame); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_constructed_tid_to_last_frame); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_constants, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1862, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_constructed_tid_to_last_frame); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1862, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_constructed_tid_to_last_frame, __pyx_t_2) < 0) __PYX_ERR(0, 1862, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1864 + * from _pydevd_bundle.pydevd_constants import constructed_tid_to_last_frame + * + * _original_call = ThreadTracer.__call__ # <<<<<<<<<<<<<< + * + * def __call__(self, frame, event, arg): + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_ThreadTracer), __pyx_n_s_call_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1864, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_original_call, __pyx_t_1) < 0) __PYX_ERR(0, 1864, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1866 + * _original_call = ThreadTracer.__call__ + * + * def __call__(self, frame, event, arg): # <<<<<<<<<<<<<< + * constructed_tid_to_last_frame[self._args[1].ident] = frame + * return _original_call(self, frame, event, arg) + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_11__call__, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1866, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_call_2, __pyx_t_1) < 0) __PYX_ERR(0, 1866, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1870 + * return _original_call(self, frame, event, arg) + * + * ThreadTracer.__call__ = __call__ # <<<<<<<<<<<<<< + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_call_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1870, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (__Pyx_PyObject_SetAttrStr(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_ThreadTracer), __pyx_n_s_call_2, __pyx_t_1) < 0) __PYX_ERR(0, 1870, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1854 + * + * + * if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP: # <<<<<<<<<<<<<< + * # This is far from ideal, as we'll leak frames (we'll always have the last created frame, not really + * # the last topmost frame saved -- this should be Ok for our usage, but it may leak frames and things + */ + } + + /* "(tree fragment)":1 + * def __pyx_unpickle_PyDBAdditionalThreadInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_13__pyx_unpickle_PyDBAdditionalThreadInfo, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_PyDBAdditionalThr, __pyx_t_1) < 0) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":11 + * __pyx_unpickle_PyDBAdditionalThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_PyDBAdditionalThreadInfo__set_state(PyDBAdditionalThreadInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.conditional_breakpoint_exception = __pyx_state[0]; __pyx_result.is_tracing = __pyx_state[1]; __pyx_result.pydev_call_from_jinja2 = __pyx_state[2]; __pyx_result.pydev_call_inside_jinja2 = __pyx_state[3]; __pyx_result.pydev_django_resolve_frame = __pyx_state[4]; __pyx_result.pydev_func_name = __pyx_state[5]; __pyx_result.pydev_message = __pyx_state[6]; __pyx_result.pydev_next_line = __pyx_state[7]; __pyx_result.pydev_notify_kill = __pyx_state[8]; __pyx_result.pydev_original_step_cmd = __pyx_state[9]; __pyx_result.pydev_smart_child_offset = __pyx_state[10]; __pyx_result.pydev_smart_parent_offset = __pyx_state[11]; __pyx_result.pydev_smart_step_into_variants = __pyx_state[12]; __pyx_result.pydev_smart_step_stop = __pyx_state[13]; __pyx_result.pydev_state = __pyx_state[14]; __pyx_result.pydev_step_cmd = __pyx_state[15]; __pyx_result.pydev_step_stop = __pyx_state[16]; __pyx_result.pydev_use_scoped_step_frame = __pyx_state[17]; __pyx_result.step_in_initial_location = __pyx_state[18]; __pyx_result.suspend_type = __pyx_state[19]; __pyx_result.suspended_at_unhandled = __pyx_state[20]; __pyx_result.target_id_to_smart_step_into_variant = __pyx_state[21]; __pyx_result.thread_tracer = __pyx_state[22]; __pyx_result.top_level_thread_tracer_no_back_frames = __pyx_state[23]; __pyx_result.top_level_thread_tracer_unhandled = __pyx_state[24]; __pyx_result.trace_suspend_type = __pyx_state[25] + * if len(__pyx_state) > 26 and hasattr(__pyx_result, '__dict__'): + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_15__pyx_unpickle__TryExceptContainerObj, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle__TryExceptContain, __pyx_t_1) < 0) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_PyDBFrame(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_17__pyx_unpickle_PyDBFrame, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_PyDBFrame, __pyx_t_1) < 0) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":11 + * __pyx_unpickle_PyDBFrame__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_PyDBFrame__set_state(PyDBFrame __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0]; __pyx_result.exc_info = __pyx_state[1]; __pyx_result.should_skip = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_19__pyx_unpickle_SafeCallWrapper, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_SafeCallWrapper, __pyx_t_1) < 0) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_21__pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_TopLevelThreadTra, __pyx_t_1) < 0) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":11 + * __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_TopLevelThreadTracerOnlyUnhandledExceptions__set_state(TopLevelThreadTracerOnlyUnhandledExceptions __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._args = __pyx_state[0] + * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_23__pyx_unpickle_TopLevelThreadTracerNoBackFrame, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_TopLevelThreadTra_2, __pyx_t_1) < 0) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_ThreadTracer(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_14_pydevd_bundle_13pydevd_cython_25__pyx_unpickle_ThreadTracer, NULL, __pyx_n_s_pydevd_bundle_pydevd_cython); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_ThreadTracer, __pyx_t_1) < 0) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_bundle/pydevd_cython.pyx":1 + * from __future__ import print_function # <<<<<<<<<<<<<< + * + * # Important: Autogenerated file. + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init _pydevd_bundle.pydevd_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init _pydevd_bundle.pydevd_cython"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 + return __pyx_m; + #else + return; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* GetBuiltinName */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* KeywordStringCheck */ +static int __Pyx_CheckKeywordStrings( + PyObject *kwdict, + const char* function_name, + int kw_allowed) +{ + PyObject* key = 0; + Py_ssize_t pos = 0; +#if CYTHON_COMPILING_IN_PYPY + if (!kw_allowed && PyDict_Next(kwdict, &pos, &key, 0)) + goto invalid_keyword; + return 1; +#else + while (PyDict_Next(kwdict, &pos, &key, 0)) { + #if PY_MAJOR_VERSION < 3 + if (unlikely(!PyString_Check(key))) + #endif + if (unlikely(!PyUnicode_Check(key))) + goto invalid_keyword_type; + } + if ((!kw_allowed) && unlikely(key)) + goto invalid_keyword; + return 1; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + return 0; +#endif +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif + return 0; +} + +/* PyDictVersioning */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ +#if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if !CYTHON_AVOID_BORROWED_REFS +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 + result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } else if (unlikely(PyErr_Occurred())) { + return NULL; + } +#else + result = PyDict_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } +#endif +#else + result = PyObject_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); +} + +/* PyFunctionFastCall */ +#if CYTHON_FAST_PYCALL +static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { + PyFrameObject *f; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject **fastlocals; + Py_ssize_t i; + PyObject *result; + assert(globals != NULL); + /* XXX Perhaps we should create a specialized + PyFrame_New() that doesn't take locals, but does + take builtins without sanity checking them. + */ + assert(tstate != NULL); + f = PyFrame_New(tstate, co, globals, NULL); + if (f == NULL) { + return NULL; + } + fastlocals = __Pyx_PyFrame_GetLocalsplus(f); + for (i = 0; i < na; i++) { + Py_INCREF(*args); + fastlocals[i] = *args++; + } + result = PyEval_EvalFrameEx(f,0); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return result; +} +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure; +#if PY_MAJOR_VERSION >= 3 + PyObject *kwdefs; +#endif + PyObject *kwtuple, **k; + PyObject **d; + Py_ssize_t nd; + Py_ssize_t nk; + PyObject *result; + assert(kwargs == NULL || PyDict_Check(kwargs)); + nk = kwargs ? PyDict_Size(kwargs) : 0; + if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { + return NULL; + } + if ( +#if PY_MAJOR_VERSION >= 3 + co->co_kwonlyargcount == 0 && +#endif + likely(kwargs == NULL || nk == 0) && + co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { + if (argdefs == NULL && co->co_argcount == nargs) { + result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); + goto done; + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); + goto done; + } + } + if (kwargs != NULL) { + Py_ssize_t pos, i; + kwtuple = PyTuple_New(2 * nk); + if (kwtuple == NULL) { + result = NULL; + goto done; + } + k = &PyTuple_GET_ITEM(kwtuple, 0); + pos = i = 0; + while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); + i += 2; + } + nk = i / 2; + } + else { + kwtuple = NULL; + k = NULL; + } + closure = PyFunction_GET_CLOSURE(func); +#if PY_MAJOR_VERSION >= 3 + kwdefs = PyFunction_GET_KW_DEFAULTS(func); +#endif + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = Py_SIZE(argdefs); + } + else { + d = NULL; + nd = 0; + } +#if PY_MAJOR_VERSION >= 3 + result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, kwdefs, closure); +#else + result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, closure); +#endif + Py_XDECREF(kwtuple); +done: + Py_LeaveRecursiveCall(); + return result; +} +#endif +#endif + +/* PyObjectCall */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = Py_TYPE(func)->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallNoArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, NULL, 0); + } +#endif +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) +#else + if (likely(PyCFunction_Check(func))) +#endif + { + if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { + return __Pyx_PyObject_CallMethO(func, NULL); + } + } + return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); +} +#endif + +/* PyCFunctionFastCall */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { + PyCFunctionObject *func = (PyCFunctionObject*)func_obj; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + assert(PyCFunction_Check(func)); + assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + /* _PyCFunction_FastCallDict() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller loses its exception */ + assert(!PyErr_Occurred()); + if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { + return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); + } else { + return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); + } +} +#endif + +/* PyObjectCallOneArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (__Pyx_PyFastCFunction_Check(func)) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* PyObjectCall2Args */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { + PyObject *args, *result = NULL; + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyFunction_FastCall(function, args, 2); + } + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyCFunction_FastCall(function, args, 2); + } + #endif + args = PyTuple_New(2); + if (unlikely(!args)) goto done; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + Py_INCREF(function); + result = __Pyx_PyObject_Call(function, args, NULL); + Py_DECREF(args); + Py_DECREF(function); +done: + return result; +} + +/* PyErrExceptionMatches */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; icurexc_type; + if (exc_type == err) return 1; + if (unlikely(!exc_type)) return 0; + if (unlikely(PyTuple_Check(err))) + return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); + return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); +} +#endif + +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* GetAttr */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) { +#if CYTHON_USE_TYPE_SLOTS +#if PY_MAJOR_VERSION >= 3 + if (likely(PyUnicode_Check(n))) +#else + if (likely(PyString_Check(n))) +#endif + return __Pyx_PyObject_GetAttrStr(o, n); +#endif + return PyObject_GetAttr(o, n); +} + +/* GetAttr3 */ +static PyObject *__Pyx_GetAttr3Default(PyObject *d) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + return NULL; + __Pyx_PyErr_Clear(); + Py_INCREF(d); + return d; +} +static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { + PyObject *r = __Pyx_GetAttr(o, n); + return (likely(r)) ? r : __Pyx_GetAttr3Default(d); +} + +/* RaiseException */ +#if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, + CYTHON_UNUSED PyObject *cause) { + __Pyx_PyThreadState_declare + Py_XINCREF(type); + if (!value || value == Py_None) + value = NULL; + else + Py_INCREF(value); + if (!tb || tb == Py_None) + tb = NULL; + else { + Py_INCREF(tb); + if (!PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + } + if (PyType_Check(type)) { +#if CYTHON_COMPILING_IN_PYPY + if (!value) { + Py_INCREF(Py_None); + value = Py_None; + } +#endif + PyErr_NormalizeException(&type, &value, &tb); + } else { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + value = type; + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + } + __Pyx_PyThreadState_assign + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} +#else +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + if (cause) { + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if CYTHON_COMPILING_IN_PYPY + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#else + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} +#endif + +/* GetTopmostException */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * +__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) +{ + _PyErr_StackItem *exc_info = tstate->exc_info; + while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + exc_info->previous_item != NULL) + { + exc_info = exc_info->previous_item; + } + return exc_info; +} +#endif + +/* SaveResetException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + *type = exc_info->exc_type; + *value = exc_info->exc_value; + *tb = exc_info->exc_traceback; + #else + *type = tstate->exc_type; + *value = tstate->exc_value; + *tb = tstate->exc_traceback; + #endif + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); +} +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = type; + exc_info->exc_value = value; + exc_info->exc_traceback = tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = type; + tstate->exc_value = value; + tstate->exc_traceback = tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +#endif + +/* GetException */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) +#endif +{ + PyObject *local_type, *local_value, *local_tb; +#if CYTHON_FAST_THREAD_STATE + PyObject *tmp_type, *tmp_value, *tmp_tb; + local_type = tstate->curexc_type; + local_value = tstate->curexc_value; + local_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +#else + PyErr_Fetch(&local_type, &local_value, &local_tb); +#endif + PyErr_NormalizeException(&local_type, &local_value, &local_tb); +#if CYTHON_FAST_THREAD_STATE + if (unlikely(tstate->curexc_type)) +#else + if (unlikely(PyErr_Occurred())) +#endif + goto bad; + #if PY_MAJOR_VERSION >= 3 + if (local_tb) { + if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) + goto bad; + } + #endif + Py_XINCREF(local_tb); + Py_XINCREF(local_type); + Py_XINCREF(local_value); + *type = local_type; + *value = local_value; + *tb = local_tb; +#if CYTHON_FAST_THREAD_STATE + #if CYTHON_USE_EXC_INFO_STACK + { + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = local_type; + exc_info->exc_value = local_value; + exc_info->exc_traceback = local_tb; + } + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = local_type; + tstate->exc_value = local_value; + tstate->exc_traceback = local_tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#else + PyErr_SetExcInfo(local_type, local_value, local_tb); +#endif + return 0; +bad: + *type = 0; + *value = 0; + *tb = 0; + Py_XDECREF(local_type); + Py_XDECREF(local_value); + Py_XDECREF(local_tb); + return -1; +} + +/* PyObjectSetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_setattro)) + return tp->tp_setattro(obj, attr_name, value); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_setattr)) + return tp->tp_setattr(obj, PyString_AS_STRING(attr_name), value); +#endif + return PyObject_SetAttr(obj, attr_name, value); +} +#endif + +/* None */ +static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { + PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); +} + +/* pyfrozenset_new */ +static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it) { + if (it) { + PyObject* result; +#if CYTHON_COMPILING_IN_PYPY + PyObject* args; + args = PyTuple_Pack(1, it); + if (unlikely(!args)) + return NULL; + result = PyObject_Call((PyObject*)&PyFrozenSet_Type, args, NULL); + Py_DECREF(args); + return result; +#else + if (PyFrozenSet_CheckExact(it)) { + Py_INCREF(it); + return it; + } + result = PyFrozenSet_New(it); + if (unlikely(!result)) + return NULL; + if ((PY_VERSION_HEX >= 0x031000A1) || likely(PySet_GET_SIZE(result))) + return result; + Py_DECREF(result); +#endif + } +#if CYTHON_USE_TYPE_SLOTS + return PyFrozenSet_Type.tp_new(&PyFrozenSet_Type, __pyx_empty_tuple, NULL); +#else + return PyObject_Call((PyObject*)&PyFrozenSet_Type, __pyx_empty_tuple, NULL); +#endif +} + +/* PySetContains */ +static int __Pyx_PySet_ContainsUnhashable(PyObject *set, PyObject *key) { + int result = -1; + if (PySet_Check(key) && PyErr_ExceptionMatches(PyExc_TypeError)) { + PyObject *tmpkey; + PyErr_Clear(); + tmpkey = __Pyx_PyFrozenSet_New(key); + if (tmpkey != NULL) { + result = PySet_Contains(set, tmpkey); + Py_DECREF(tmpkey); + } + } + return result; +} +static CYTHON_INLINE int __Pyx_PySet_ContainsTF(PyObject* key, PyObject* set, int eq) { + int result = PySet_Contains(set, key); + if (unlikely(result < 0)) { + result = __Pyx_PySet_ContainsUnhashable(set, key); + } + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* ArgTypeTest */ +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) +{ + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + else if (exact) { + #if PY_MAJOR_VERSION == 2 + if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; + #endif + } + else { + if (likely(__Pyx_TypeCheck(obj, type))) return 1; + } + PyErr_Format(PyExc_TypeError, + "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); + return 0; +} + +/* GetItemInt */ +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (!j) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyList_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { + PyObject *r = PyList_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyTuple_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); + if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { + PyObject *r = PyList_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } + else if (PyTuple_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } else { + PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; + if (likely(m && m->sq_item)) { + if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { + Py_ssize_t l = m->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return NULL; + PyErr_Clear(); + } + } + return m->sq_item(o, i); + } + } +#else + if (is_list || PySequence_Check(o)) { + return PySequence_GetItem(o, i); + } +#endif + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +} + +/* BytesEquals */ +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) { +#if CYTHON_COMPILING_IN_PYPY + return PyObject_RichCompareBool(s1, s2, equals); +#else + if (s1 == s2) { + return (equals == Py_EQ); + } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) { + const char *ps1, *ps2; + Py_ssize_t length = PyBytes_GET_SIZE(s1); + if (length != PyBytes_GET_SIZE(s2)) + return (equals == Py_NE); + ps1 = PyBytes_AS_STRING(s1); + ps2 = PyBytes_AS_STRING(s2); + if (ps1[0] != ps2[0]) { + return (equals == Py_NE); + } else if (length == 1) { + return (equals == Py_EQ); + } else { + int result; +#if CYTHON_USE_UNICODE_INTERNALS && (PY_VERSION_HEX < 0x030B0000) + Py_hash_t hash1, hash2; + hash1 = ((PyBytesObject*)s1)->ob_shash; + hash2 = ((PyBytesObject*)s2)->ob_shash; + if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { + return (equals == Py_NE); + } +#endif + result = memcmp(ps1, ps2, (size_t)length); + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) { + return (equals == Py_NE); + } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) { + return (equals == Py_NE); + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +#endif +} + +/* UnicodeEquals */ +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) { +#if CYTHON_COMPILING_IN_PYPY + return PyObject_RichCompareBool(s1, s2, equals); +#else +#if PY_MAJOR_VERSION < 3 + PyObject* owned_ref = NULL; +#endif + int s1_is_unicode, s2_is_unicode; + if (s1 == s2) { + goto return_eq; + } + s1_is_unicode = PyUnicode_CheckExact(s1); + s2_is_unicode = PyUnicode_CheckExact(s2); +#if PY_MAJOR_VERSION < 3 + if ((s1_is_unicode & (!s2_is_unicode)) && PyString_CheckExact(s2)) { + owned_ref = PyUnicode_FromObject(s2); + if (unlikely(!owned_ref)) + return -1; + s2 = owned_ref; + s2_is_unicode = 1; + } else if ((s2_is_unicode & (!s1_is_unicode)) && PyString_CheckExact(s1)) { + owned_ref = PyUnicode_FromObject(s1); + if (unlikely(!owned_ref)) + return -1; + s1 = owned_ref; + s1_is_unicode = 1; + } else if (((!s2_is_unicode) & (!s1_is_unicode))) { + return __Pyx_PyBytes_Equals(s1, s2, equals); + } +#endif + if (s1_is_unicode & s2_is_unicode) { + Py_ssize_t length; + int kind; + void *data1, *data2; + if (unlikely(__Pyx_PyUnicode_READY(s1) < 0) || unlikely(__Pyx_PyUnicode_READY(s2) < 0)) + return -1; + length = __Pyx_PyUnicode_GET_LENGTH(s1); + if (length != __Pyx_PyUnicode_GET_LENGTH(s2)) { + goto return_ne; + } +#if CYTHON_USE_UNICODE_INTERNALS + { + Py_hash_t hash1, hash2; + #if CYTHON_PEP393_ENABLED + hash1 = ((PyASCIIObject*)s1)->hash; + hash2 = ((PyASCIIObject*)s2)->hash; + #else + hash1 = ((PyUnicodeObject*)s1)->hash; + hash2 = ((PyUnicodeObject*)s2)->hash; + #endif + if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { + goto return_ne; + } + } +#endif + kind = __Pyx_PyUnicode_KIND(s1); + if (kind != __Pyx_PyUnicode_KIND(s2)) { + goto return_ne; + } + data1 = __Pyx_PyUnicode_DATA(s1); + data2 = __Pyx_PyUnicode_DATA(s2); + if (__Pyx_PyUnicode_READ(kind, data1, 0) != __Pyx_PyUnicode_READ(kind, data2, 0)) { + goto return_ne; + } else if (length == 1) { + goto return_eq; + } else { + int result = memcmp(data1, data2, (size_t)(length * kind)); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(owned_ref); + #endif + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & s2_is_unicode) { + goto return_ne; + } else if ((s2 == Py_None) & s1_is_unicode) { + goto return_ne; + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(owned_ref); + #endif + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +return_eq: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(owned_ref); + #endif + return (equals == Py_EQ); +return_ne: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(owned_ref); + #endif + return (equals == Py_NE); +#endif +} + +/* RaiseTooManyValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { + PyErr_Format(PyExc_ValueError, + "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); +} + +/* RaiseNeedMoreValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", + index, (index == 1) ? "" : "s"); +} + +/* IterFinish */ +static CYTHON_INLINE int __Pyx_IterFinish(void) { +#if CYTHON_FAST_THREAD_STATE + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* exc_type = tstate->curexc_type; + if (unlikely(exc_type)) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) { + PyObject *exc_value, *exc_tb; + exc_value = tstate->curexc_value; + exc_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; + Py_DECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); + return 0; + } else { + return -1; + } + } + return 0; +#else + if (unlikely(PyErr_Occurred())) { + if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) { + PyErr_Clear(); + return 0; + } else { + return -1; + } + } + return 0; +#endif +} + +/* UnpackItemEndCheck */ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { + if (unlikely(retval)) { + Py_DECREF(retval); + __Pyx_RaiseTooManyValuesError(expected); + return -1; + } else { + return __Pyx_IterFinish(); + } + return 0; +} + +/* ExtTypeTest */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + if (likely(__Pyx_TypeCheck(obj, type))) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", + Py_TYPE(obj)->tp_name, type->tp_name); + return 0; +} + +/* HasAttr */ +static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) { + PyObject *r; + if (unlikely(!__Pyx_PyBaseString_Check(n))) { + PyErr_SetString(PyExc_TypeError, + "hasattr(): attribute name must be string"); + return -1; + } + r = __Pyx_GetAttr(o, n); + if (unlikely(!r)) { + PyErr_Clear(); + return 0; + } else { + Py_DECREF(r); + return 1; + } +} + +/* UnpackUnboundCMethod */ +static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) { + PyObject *method; + method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name); + if (unlikely(!method)) + return -1; + target->method = method; +#if CYTHON_COMPILING_IN_CPYTHON + #if PY_MAJOR_VERSION >= 3 + if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type))) + #endif + { + PyMethodDescrObject *descr = (PyMethodDescrObject*) method; + target->func = descr->d_method->ml_meth; + target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS); + } +#endif + return 0; +} + +/* CallUnboundCMethod1 */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg) { + if (likely(cfunc->func)) { + int flag = cfunc->flag; + if (flag == METH_O) { + return (*(cfunc->func))(self, arg); + } else if (PY_VERSION_HEX >= 0x030600B1 && flag == METH_FASTCALL) { + if (PY_VERSION_HEX >= 0x030700A0) { + return (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)cfunc->func)(self, &arg, 1); + } else { + return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL); + } + } else if (PY_VERSION_HEX >= 0x030700A0 && flag == (METH_FASTCALL | METH_KEYWORDS)) { + return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL); + } + } + return __Pyx__CallUnboundCMethod1(cfunc, self, arg); +} +#endif +static PyObject* __Pyx__CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg){ + PyObject *args, *result = NULL; + if (unlikely(!cfunc->func && !cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; +#if CYTHON_COMPILING_IN_CPYTHON + if (cfunc->func && (cfunc->flag & METH_VARARGS)) { + args = PyTuple_New(1); + if (unlikely(!args)) goto bad; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + if (cfunc->flag & METH_KEYWORDS) + result = (*(PyCFunctionWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, NULL); + else + result = (*cfunc->func)(self, args); + } else { + args = PyTuple_New(2); + if (unlikely(!args)) goto bad; + Py_INCREF(self); + PyTuple_SET_ITEM(args, 0, self); + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 1, arg); + result = __Pyx_PyObject_Call(cfunc->method, args, NULL); + } +#else + args = PyTuple_Pack(2, self, arg); + if (unlikely(!args)) goto bad; + result = __Pyx_PyObject_Call(cfunc->method, args, NULL); +#endif +bad: + Py_XDECREF(args); + return result; +} + +/* CallUnboundCMethod2 */ +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030600B1 +static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2) { + if (likely(cfunc->func)) { + PyObject *args[2] = {arg1, arg2}; + if (cfunc->flag == METH_FASTCALL) { + #if PY_VERSION_HEX >= 0x030700A0 + return (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)cfunc->func)(self, args, 2); + #else + return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, 2, NULL); + #endif + } + #if PY_VERSION_HEX >= 0x030700A0 + if (cfunc->flag == (METH_FASTCALL | METH_KEYWORDS)) + return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, 2, NULL); + #endif + } + return __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2); +} +#endif +static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2){ + PyObject *args, *result = NULL; + if (unlikely(!cfunc->func && !cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; +#if CYTHON_COMPILING_IN_CPYTHON + if (cfunc->func && (cfunc->flag & METH_VARARGS)) { + args = PyTuple_New(2); + if (unlikely(!args)) goto bad; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + if (cfunc->flag & METH_KEYWORDS) + result = (*(PyCFunctionWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, NULL); + else + result = (*cfunc->func)(self, args); + } else { + args = PyTuple_New(3); + if (unlikely(!args)) goto bad; + Py_INCREF(self); + PyTuple_SET_ITEM(args, 0, self); + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 1, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 2, arg2); + result = __Pyx_PyObject_Call(cfunc->method, args, NULL); + } +#else + args = PyTuple_Pack(3, self, arg1, arg2); + if (unlikely(!args)) goto bad; + result = __Pyx_PyObject_Call(cfunc->method, args, NULL); +#endif +bad: + Py_XDECREF(args); + return result; +} + +/* dict_getitem_default */ +static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value) { + PyObject* value; +#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY + value = PyDict_GetItemWithError(d, key); + if (unlikely(!value)) { + if (unlikely(PyErr_Occurred())) + return NULL; + value = default_value; + } + Py_INCREF(value); + if ((1)); +#else + if (PyString_CheckExact(key) || PyUnicode_CheckExact(key) || PyInt_CheckExact(key)) { + value = PyDict_GetItem(d, key); + if (unlikely(!value)) { + value = default_value; + } + Py_INCREF(value); + } +#endif + else { + if (default_value == Py_None) + value = __Pyx_CallUnboundCMethod1(&__pyx_umethod_PyDict_Type_get, d, key); + else + value = __Pyx_CallUnboundCMethod2(&__pyx_umethod_PyDict_Type_get, d, key, default_value); + } + return value; +} + +/* SwapException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = *type; + exc_info->exc_value = *value; + exc_info->exc_traceback = *tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = *type; + tstate->exc_value = *value; + tstate->exc_traceback = *tb; + #endif + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb); + PyErr_SetExcInfo(*type, *value, *tb); + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#endif + +/* RaiseNoneIterError */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); +} + +/* PyIntBinop */ +#if !CYTHON_COMPILING_IN_PYPY +static PyObject* __Pyx_PyInt_AndObjC(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, int inplace, int zerodivision_check) { + (void)inplace; + (void)zerodivision_check; + #if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(op1))) { + const long b = intval; + long a = PyInt_AS_LONG(op1); + return PyInt_FromLong(a & b); + } + #endif + #if CYTHON_USE_PYLONG_INTERNALS + if (likely(PyLong_CheckExact(op1))) { + const long b = intval; + long a, x; +#ifdef HAVE_LONG_LONG + const PY_LONG_LONG llb = intval; + PY_LONG_LONG lla, llx; +#endif + const digit* digits = ((PyLongObject*)op1)->ob_digit; + const Py_ssize_t size = Py_SIZE(op1); + if (likely(__Pyx_sst_abs(size) <= 1)) { + a = likely(size) ? digits[0] : 0; + if (size == -1) a = -a; + } else { + switch (size) { + case -2: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + a = -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 2: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case -3: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + a = -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 3: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case -4: + if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + a = -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 4: + if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + default: return PyLong_Type.tp_as_number->nb_and(op1, op2); + } + } + x = a & b; + return PyLong_FromLong(x); +#ifdef HAVE_LONG_LONG + long_long: + llx = lla & llb; + return PyLong_FromLongLong(llx); +#endif + + + } + #endif + return (inplace ? PyNumber_InPlaceAnd : PyNumber_And)(op1, op2); +} +#endif + +/* PyObjectGetMethod */ +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { + PyObject *attr; +#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP + PyTypeObject *tp = Py_TYPE(obj); + PyObject *descr; + descrgetfunc f = NULL; + PyObject **dictptr, *dict; + int meth_found = 0; + assert (*method == NULL); + if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; + } + if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { + return 0; + } + descr = _PyType_Lookup(tp, name); + if (likely(descr != NULL)) { + Py_INCREF(descr); +#if PY_MAJOR_VERSION >= 3 + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type))) + #endif +#else + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr))) + #endif +#endif + { + meth_found = 1; + } else { + f = Py_TYPE(descr)->tp_descr_get; + if (f != NULL && PyDescr_IsData(descr)) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + } + } + dictptr = _PyObject_GetDictPtr(obj); + if (dictptr != NULL && (dict = *dictptr) != NULL) { + Py_INCREF(dict); + attr = __Pyx_PyDict_GetItemStr(dict, name); + if (attr != NULL) { + Py_INCREF(attr); + Py_DECREF(dict); + Py_XDECREF(descr); + goto try_unpack; + } + Py_DECREF(dict); + } + if (meth_found) { + *method = descr; + return 1; + } + if (f != NULL) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + if (descr != NULL) { + *method = descr; + return 0; + } + PyErr_Format(PyExc_AttributeError, +#if PY_MAJOR_VERSION >= 3 + "'%.50s' object has no attribute '%U'", + tp->tp_name, name); +#else + "'%.50s' object has no attribute '%.400s'", + tp->tp_name, PyString_AS_STRING(name)); +#endif + return 0; +#else + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; +#endif +try_unpack: +#if CYTHON_UNPACK_METHODS + if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { + PyObject *function = PyMethod_GET_FUNCTION(attr); + Py_INCREF(function); + Py_DECREF(attr); + *method = function; + return 1; + } +#endif + *method = attr; + return 0; +} + +/* PyObjectCallMethod0 */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) { + PyObject *method = NULL, *result = NULL; + int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); + if (likely(is_method)) { + result = __Pyx_PyObject_CallOneArg(method, obj); + Py_DECREF(method); + return result; + } + if (unlikely(!method)) goto bad; + result = __Pyx_PyObject_CallNoArg(method); + Py_DECREF(method); +bad: + return result; +} + +/* UnpackTupleError */ +static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) { + if (t == Py_None) { + __Pyx_RaiseNoneNotIterableError(); + } else if (PyTuple_GET_SIZE(t) < index) { + __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t)); + } else { + __Pyx_RaiseTooManyValuesError(index); + } +} + +/* UnpackTuple2 */ +static CYTHON_INLINE int __Pyx_unpack_tuple2_exact( + PyObject* tuple, PyObject** pvalue1, PyObject** pvalue2, int decref_tuple) { + PyObject *value1 = NULL, *value2 = NULL; +#if CYTHON_COMPILING_IN_PYPY + value1 = PySequence_ITEM(tuple, 0); if (unlikely(!value1)) goto bad; + value2 = PySequence_ITEM(tuple, 1); if (unlikely(!value2)) goto bad; +#else + value1 = PyTuple_GET_ITEM(tuple, 0); Py_INCREF(value1); + value2 = PyTuple_GET_ITEM(tuple, 1); Py_INCREF(value2); +#endif + if (decref_tuple) { + Py_DECREF(tuple); + } + *pvalue1 = value1; + *pvalue2 = value2; + return 0; +#if CYTHON_COMPILING_IN_PYPY +bad: + Py_XDECREF(value1); + Py_XDECREF(value2); + if (decref_tuple) { Py_XDECREF(tuple); } + return -1; +#endif +} +static int __Pyx_unpack_tuple2_generic(PyObject* tuple, PyObject** pvalue1, PyObject** pvalue2, + int has_known_size, int decref_tuple) { + Py_ssize_t index; + PyObject *value1 = NULL, *value2 = NULL, *iter = NULL; + iternextfunc iternext; + iter = PyObject_GetIter(tuple); + if (unlikely(!iter)) goto bad; + if (decref_tuple) { Py_DECREF(tuple); tuple = NULL; } + iternext = Py_TYPE(iter)->tp_iternext; + value1 = iternext(iter); if (unlikely(!value1)) { index = 0; goto unpacking_failed; } + value2 = iternext(iter); if (unlikely(!value2)) { index = 1; goto unpacking_failed; } + if (!has_known_size && unlikely(__Pyx_IternextUnpackEndCheck(iternext(iter), 2))) goto bad; + Py_DECREF(iter); + *pvalue1 = value1; + *pvalue2 = value2; + return 0; +unpacking_failed: + if (!has_known_size && __Pyx_IterFinish() == 0) + __Pyx_RaiseNeedMoreValuesError(index); +bad: + Py_XDECREF(iter); + Py_XDECREF(value1); + Py_XDECREF(value2); + if (decref_tuple) { Py_XDECREF(tuple); } + return -1; +} + +/* dict_iter */ +static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* iterable, int is_dict, PyObject* method_name, + Py_ssize_t* p_orig_length, int* p_source_is_dict) { + is_dict = is_dict || likely(PyDict_CheckExact(iterable)); + *p_source_is_dict = is_dict; + if (is_dict) { +#if !CYTHON_COMPILING_IN_PYPY + *p_orig_length = PyDict_Size(iterable); + Py_INCREF(iterable); + return iterable; +#elif PY_MAJOR_VERSION >= 3 + static PyObject *py_items = NULL, *py_keys = NULL, *py_values = NULL; + PyObject **pp = NULL; + if (method_name) { + const char *name = PyUnicode_AsUTF8(method_name); + if (strcmp(name, "iteritems") == 0) pp = &py_items; + else if (strcmp(name, "iterkeys") == 0) pp = &py_keys; + else if (strcmp(name, "itervalues") == 0) pp = &py_values; + if (pp) { + if (!*pp) { + *pp = PyUnicode_FromString(name + 4); + if (!*pp) + return NULL; + } + method_name = *pp; + } + } +#endif + } + *p_orig_length = 0; + if (method_name) { + PyObject* iter; + iterable = __Pyx_PyObject_CallMethod0(iterable, method_name); + if (!iterable) + return NULL; +#if !CYTHON_COMPILING_IN_PYPY + if (PyTuple_CheckExact(iterable) || PyList_CheckExact(iterable)) + return iterable; +#endif + iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + return iter; + } + return PyObject_GetIter(iterable); +} +static CYTHON_INLINE int __Pyx_dict_iter_next( + PyObject* iter_obj, CYTHON_NCP_UNUSED Py_ssize_t orig_length, CYTHON_NCP_UNUSED Py_ssize_t* ppos, + PyObject** pkey, PyObject** pvalue, PyObject** pitem, int source_is_dict) { + PyObject* next_item; +#if !CYTHON_COMPILING_IN_PYPY + if (source_is_dict) { + PyObject *key, *value; + if (unlikely(orig_length != PyDict_Size(iter_obj))) { + PyErr_SetString(PyExc_RuntimeError, "dictionary changed size during iteration"); + return -1; + } + if (unlikely(!PyDict_Next(iter_obj, ppos, &key, &value))) { + return 0; + } + if (pitem) { + PyObject* tuple = PyTuple_New(2); + if (unlikely(!tuple)) { + return -1; + } + Py_INCREF(key); + Py_INCREF(value); + PyTuple_SET_ITEM(tuple, 0, key); + PyTuple_SET_ITEM(tuple, 1, value); + *pitem = tuple; + } else { + if (pkey) { + Py_INCREF(key); + *pkey = key; + } + if (pvalue) { + Py_INCREF(value); + *pvalue = value; + } + } + return 1; + } else if (PyTuple_CheckExact(iter_obj)) { + Py_ssize_t pos = *ppos; + if (unlikely(pos >= PyTuple_GET_SIZE(iter_obj))) return 0; + *ppos = pos + 1; + next_item = PyTuple_GET_ITEM(iter_obj, pos); + Py_INCREF(next_item); + } else if (PyList_CheckExact(iter_obj)) { + Py_ssize_t pos = *ppos; + if (unlikely(pos >= PyList_GET_SIZE(iter_obj))) return 0; + *ppos = pos + 1; + next_item = PyList_GET_ITEM(iter_obj, pos); + Py_INCREF(next_item); + } else +#endif + { + next_item = PyIter_Next(iter_obj); + if (unlikely(!next_item)) { + return __Pyx_IterFinish(); + } + } + if (pitem) { + *pitem = next_item; + } else if (pkey && pvalue) { + if (__Pyx_unpack_tuple2(next_item, pkey, pvalue, source_is_dict, source_is_dict, 1)) + return -1; + } else if (pkey) { + *pkey = next_item; + } else { + *pvalue = next_item; + } + return 1; +} + +/* CallUnboundCMethod0 */ +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { + PyObject *args, *result = NULL; + if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; +#if CYTHON_ASSUME_SAFE_MACROS + args = PyTuple_New(1); + if (unlikely(!args)) goto bad; + Py_INCREF(self); + PyTuple_SET_ITEM(args, 0, self); +#else + args = PyTuple_Pack(1, self); + if (unlikely(!args)) goto bad; +#endif + result = __Pyx_PyObject_Call(cfunc->method, args, NULL); + Py_DECREF(args); +bad: + return result; +} + +/* py_dict_values */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d) { + if (PY_MAJOR_VERSION >= 3) + return __Pyx_CallUnboundCMethod0(&__pyx_umethod_PyDict_Type_values, d); + else + return PyDict_Values(d); +} + +/* DictGetItem */ +#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY +static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { + PyObject *value; + value = PyDict_GetItemWithError(d, key); + if (unlikely(!value)) { + if (!PyErr_Occurred()) { + if (unlikely(PyTuple_Check(key))) { + PyObject* args = PyTuple_Pack(1, key); + if (likely(args)) { + PyErr_SetObject(PyExc_KeyError, args); + Py_DECREF(args); + } + } else { + PyErr_SetObject(PyExc_KeyError, key); + } + } + return NULL; + } + Py_INCREF(value); + return value; +} +#endif + +/* SliceObject */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj, + Py_ssize_t cstart, Py_ssize_t cstop, + PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice, + int has_cstart, int has_cstop, CYTHON_UNUSED int wraparound) { +#if CYTHON_USE_TYPE_SLOTS + PyMappingMethods* mp; +#if PY_MAJOR_VERSION < 3 + PySequenceMethods* ms = Py_TYPE(obj)->tp_as_sequence; + if (likely(ms && ms->sq_slice)) { + if (!has_cstart) { + if (_py_start && (*_py_start != Py_None)) { + cstart = __Pyx_PyIndex_AsSsize_t(*_py_start); + if ((cstart == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; + } else + cstart = 0; + } + if (!has_cstop) { + if (_py_stop && (*_py_stop != Py_None)) { + cstop = __Pyx_PyIndex_AsSsize_t(*_py_stop); + if ((cstop == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; + } else + cstop = PY_SSIZE_T_MAX; + } + if (wraparound && unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) { + Py_ssize_t l = ms->sq_length(obj); + if (likely(l >= 0)) { + if (cstop < 0) { + cstop += l; + if (cstop < 0) cstop = 0; + } + if (cstart < 0) { + cstart += l; + if (cstart < 0) cstart = 0; + } + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + goto bad; + PyErr_Clear(); + } + } + return ms->sq_slice(obj, cstart, cstop); + } +#endif + mp = Py_TYPE(obj)->tp_as_mapping; + if (likely(mp && mp->mp_subscript)) +#endif + { + PyObject* result; + PyObject *py_slice, *py_start, *py_stop; + if (_py_slice) { + py_slice = *_py_slice; + } else { + PyObject* owned_start = NULL; + PyObject* owned_stop = NULL; + if (_py_start) { + py_start = *_py_start; + } else { + if (has_cstart) { + owned_start = py_start = PyInt_FromSsize_t(cstart); + if (unlikely(!py_start)) goto bad; + } else + py_start = Py_None; + } + if (_py_stop) { + py_stop = *_py_stop; + } else { + if (has_cstop) { + owned_stop = py_stop = PyInt_FromSsize_t(cstop); + if (unlikely(!py_stop)) { + Py_XDECREF(owned_start); + goto bad; + } + } else + py_stop = Py_None; + } + py_slice = PySlice_New(py_start, py_stop, Py_None); + Py_XDECREF(owned_start); + Py_XDECREF(owned_stop); + if (unlikely(!py_slice)) goto bad; + } +#if CYTHON_USE_TYPE_SLOTS + result = mp->mp_subscript(obj, py_slice); +#else + result = PyObject_GetItem(obj, py_slice); +#endif + if (!_py_slice) { + Py_DECREF(py_slice); + } + return result; + } + PyErr_Format(PyExc_TypeError, + "'%.200s' object is unsliceable", Py_TYPE(obj)->tp_name); +bad: + return NULL; +} + +/* PyIntBinop */ +#if !CYTHON_COMPILING_IN_PYPY +static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, int inplace, int zerodivision_check) { + (void)inplace; + (void)zerodivision_check; + #if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(op1))) { + const long b = intval; + long x; + long a = PyInt_AS_LONG(op1); + x = (long)((unsigned long)a + b); + if (likely((x^a) >= 0 || (x^b) >= 0)) + return PyInt_FromLong(x); + return PyLong_Type.tp_as_number->nb_add(op1, op2); + } + #endif + #if CYTHON_USE_PYLONG_INTERNALS + if (likely(PyLong_CheckExact(op1))) { + const long b = intval; + long a, x; +#ifdef HAVE_LONG_LONG + const PY_LONG_LONG llb = intval; + PY_LONG_LONG lla, llx; +#endif + const digit* digits = ((PyLongObject*)op1)->ob_digit; + const Py_ssize_t size = Py_SIZE(op1); + if (likely(__Pyx_sst_abs(size) <= 1)) { + a = likely(size) ? digits[0] : 0; + if (size == -1) a = -a; + } else { + switch (size) { + case -2: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + a = -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 2: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case -3: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + a = -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 3: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case -4: + if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + a = -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 4: + if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + default: return PyLong_Type.tp_as_number->nb_add(op1, op2); + } + } + x = a + b; + return PyLong_FromLong(x); +#ifdef HAVE_LONG_LONG + long_long: + llx = lla + llb; + return PyLong_FromLongLong(llx); +#endif + + + } + #endif + if (PyFloat_CheckExact(op1)) { + const long b = intval; + double a = PyFloat_AS_DOUBLE(op1); + double result; + PyFPE_START_PROTECT("add", return NULL) + result = ((double)a) + (double)b; + PyFPE_END_PROTECT(result) + return PyFloat_FromDouble(result); + } + return (inplace ? PyNumber_InPlaceAdd : PyNumber_Add)(op1, op2); +} +#endif + +/* PyObjectCallMethod1 */ +static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) { + PyObject *result = __Pyx_PyObject_CallOneArg(method, arg); + Py_DECREF(method); + return result; +} +static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) { + PyObject *method = NULL, *result; + int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); + if (likely(is_method)) { + result = __Pyx_PyObject_Call2Args(method, obj, arg); + Py_DECREF(method); + return result; + } + if (unlikely(!method)) return NULL; + return __Pyx__PyObject_CallMethod1(method, arg); +} + +/* append */ +static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x) { + if (likely(PyList_CheckExact(L))) { + if (unlikely(__Pyx_PyList_Append(L, x) < 0)) return -1; + } else { + PyObject* retval = __Pyx_PyObject_CallMethod1(L, __pyx_n_s_append, x); + if (unlikely(!retval)) + return -1; + Py_DECREF(retval); + } + return 0; +} + +/* SliceTupleAndList */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE void __Pyx_crop_slice(Py_ssize_t* _start, Py_ssize_t* _stop, Py_ssize_t* _length) { + Py_ssize_t start = *_start, stop = *_stop, length = *_length; + if (start < 0) { + start += length; + if (start < 0) + start = 0; + } + if (stop < 0) + stop += length; + else if (stop > length) + stop = length; + *_length = stop - start; + *_start = start; + *_stop = stop; +} +static CYTHON_INLINE void __Pyx_copy_object_array(PyObject** CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) { + PyObject *v; + Py_ssize_t i; + for (i = 0; i < length; i++) { + v = dest[i] = src[i]; + Py_INCREF(v); + } +} +static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice( + PyObject* src, Py_ssize_t start, Py_ssize_t stop) { + PyObject* dest; + Py_ssize_t length = PyList_GET_SIZE(src); + __Pyx_crop_slice(&start, &stop, &length); + if (unlikely(length <= 0)) + return PyList_New(0); + dest = PyList_New(length); + if (unlikely(!dest)) + return NULL; + __Pyx_copy_object_array( + ((PyListObject*)src)->ob_item + start, + ((PyListObject*)dest)->ob_item, + length); + return dest; +} +static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice( + PyObject* src, Py_ssize_t start, Py_ssize_t stop) { + PyObject* dest; + Py_ssize_t length = PyTuple_GET_SIZE(src); + __Pyx_crop_slice(&start, &stop, &length); + if (unlikely(length <= 0)) + return PyTuple_New(0); + dest = PyTuple_New(length); + if (unlikely(!dest)) + return NULL; + __Pyx_copy_object_array( + ((PyTupleObject*)src)->ob_item + start, + ((PyTupleObject*)dest)->ob_item, + length); + return dest; +} +#endif + +/* PyIntCompare */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_EqObjC(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, CYTHON_UNUSED long inplace) { + if (op1 == op2) { + Py_RETURN_TRUE; + } + #if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(op1))) { + const long b = intval; + long a = PyInt_AS_LONG(op1); + if (a == b) Py_RETURN_TRUE; else Py_RETURN_FALSE; + } + #endif + #if CYTHON_USE_PYLONG_INTERNALS + if (likely(PyLong_CheckExact(op1))) { + int unequal; + unsigned long uintval; + Py_ssize_t size = Py_SIZE(op1); + const digit* digits = ((PyLongObject*)op1)->ob_digit; + if (intval == 0) { + if (size == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; + } else if (intval < 0) { + if (size >= 0) + Py_RETURN_FALSE; + intval = -intval; + size = -size; + } else { + if (size <= 0) + Py_RETURN_FALSE; + } + uintval = (unsigned long) intval; +#if PyLong_SHIFT * 4 < SIZEOF_LONG*8 + if (uintval >> (PyLong_SHIFT * 4)) { + unequal = (size != 5) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) + | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[4] != ((uintval >> (4 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); + } else +#endif +#if PyLong_SHIFT * 3 < SIZEOF_LONG*8 + if (uintval >> (PyLong_SHIFT * 3)) { + unequal = (size != 4) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) + | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); + } else +#endif +#if PyLong_SHIFT * 2 < SIZEOF_LONG*8 + if (uintval >> (PyLong_SHIFT * 2)) { + unequal = (size != 3) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) + | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); + } else +#endif +#if PyLong_SHIFT * 1 < SIZEOF_LONG*8 + if (uintval >> (PyLong_SHIFT * 1)) { + unequal = (size != 2) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) + | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); + } else +#endif + unequal = (size != 1) || (((unsigned long) digits[0]) != (uintval & (unsigned long) PyLong_MASK)); + if (unequal == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; + } + #endif + if (PyFloat_CheckExact(op1)) { + const long b = intval; + double a = PyFloat_AS_DOUBLE(op1); + if ((double)a == (double)b) Py_RETURN_TRUE; else Py_RETURN_FALSE; + } + return ( + PyObject_RichCompare(op1, op2, Py_EQ)); +} + +/* ObjectGetItem */ +#if CYTHON_USE_TYPE_SLOTS +static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { + PyObject *runerr; + Py_ssize_t key_value; + PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; + if (unlikely(!(m && m->sq_item))) { + PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); + return NULL; + } + key_value = __Pyx_PyIndex_AsSsize_t(index); + if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { + return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); + } + if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { + PyErr_Clear(); + PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); + } + return NULL; +} +static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { + PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; + if (likely(m && m->mp_subscript)) { + return m->mp_subscript(obj, key); + } + return __Pyx_PyObject_GetIndex(obj, key); +} +#endif + +/* Import */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + #if PY_MAJOR_VERSION < 3 + PyObject *py_import; + py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); + if (!py_import) + goto bad; + #endif + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + { + #if PY_MAJOR_VERSION >= 3 + if (level == -1) { + if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) { + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, 1); + if (!module) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + goto bad; + PyErr_Clear(); + } + } + level = 0; + } + #endif + if (!module) { + #if PY_MAJOR_VERSION < 3 + PyObject *py_level = PyInt_FromLong(level); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); + Py_DECREF(py_level); + #else + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, level); + #endif + } + } +bad: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_import); + #endif + Py_XDECREF(empty_list); + Py_XDECREF(empty_dict); + return module; +} + +/* ImportFrom */ +static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { + PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); + if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_ImportError, + #if PY_MAJOR_VERSION < 3 + "cannot import name %.230s", PyString_AS_STRING(name)); + #else + "cannot import name %S", name); + #endif + } + return value; +} + +/* PyObject_GenericGetAttrNoDict */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) { + PyErr_Format(PyExc_AttributeError, +#if PY_MAJOR_VERSION >= 3 + "'%.50s' object has no attribute '%U'", + tp->tp_name, attr_name); +#else + "'%.50s' object has no attribute '%.400s'", + tp->tp_name, PyString_AS_STRING(attr_name)); +#endif + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { + PyObject *descr; + PyTypeObject *tp = Py_TYPE(obj); + if (unlikely(!PyString_Check(attr_name))) { + return PyObject_GenericGetAttr(obj, attr_name); + } + assert(!tp->tp_dictoffset); + descr = _PyType_Lookup(tp, attr_name); + if (unlikely(!descr)) { + return __Pyx_RaiseGenericGetAttributeError(tp, attr_name); + } + Py_INCREF(descr); + #if PY_MAJOR_VERSION < 3 + if (likely(PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))) + #endif + { + descrgetfunc f = Py_TYPE(descr)->tp_descr_get; + if (unlikely(f)) { + PyObject *res = f(descr, obj, (PyObject *)tp); + Py_DECREF(descr); + return res; + } + } + return descr; +} +#endif + +/* PyObject_GenericGetAttr */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) { + if (unlikely(Py_TYPE(obj)->tp_dictoffset)) { + return PyObject_GenericGetAttr(obj, attr_name); + } + return __Pyx_PyObject_GenericGetAttrNoDict(obj, attr_name); +} +#endif + +/* PyObjectGetAttrStrNoError */ +static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + __Pyx_PyErr_Clear(); +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { + PyObject *result; +#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1 + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { + return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); + } +#endif + result = __Pyx_PyObject_GetAttrStr(obj, attr_name); + if (unlikely(!result)) { + __Pyx_PyObject_GetAttrStr_ClearAttributeError(); + } + return result; +} + +/* SetupReduce */ +static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { + int ret; + PyObject *name_attr; + name_attr = __Pyx_PyObject_GetAttrStr(meth, __pyx_n_s_name); + if (likely(name_attr)) { + ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); + } else { + ret = -1; + } + if (unlikely(ret < 0)) { + PyErr_Clear(); + ret = 0; + } + Py_XDECREF(name_attr); + return ret; +} +static int __Pyx_setup_reduce(PyObject* type_obj) { + int ret = 0; + PyObject *object_reduce = NULL; + PyObject *object_getstate = NULL; + PyObject *object_reduce_ex = NULL; + PyObject *reduce = NULL; + PyObject *reduce_ex = NULL; + PyObject *reduce_cython = NULL; + PyObject *setstate = NULL; + PyObject *setstate_cython = NULL; + PyObject *getstate = NULL; +#if CYTHON_USE_PYTYPE_LOOKUP + getstate = _PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate); +#else + getstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_getstate); + if (!getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } +#endif + if (getstate) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_getstate = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_getstate); +#else + object_getstate = __Pyx_PyObject_GetAttrStrNoError((PyObject*)&PyBaseObject_Type, __pyx_n_s_getstate); + if (!object_getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } +#endif + if (object_getstate != getstate) { + goto __PYX_GOOD; + } + } +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#else + object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#endif + reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_ex); if (unlikely(!reduce_ex)) goto __PYX_BAD; + if (reduce_ex == object_reduce_ex) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; +#else + object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; +#endif + reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce); if (unlikely(!reduce)) goto __PYX_BAD; + if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_n_s_reduce_cython)) { + reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_reduce_cython); + if (likely(reduce_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (reduce == object_reduce || PyErr_Occurred()) { + goto __PYX_BAD; + } + setstate = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate); + if (!setstate) PyErr_Clear(); + if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_n_s_setstate_cython)) { + setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_setstate_cython); + if (likely(setstate_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (!setstate || PyErr_Occurred()) { + goto __PYX_BAD; + } + } + PyType_Modified((PyTypeObject*)type_obj); + } + } + goto __PYX_GOOD; +__PYX_BAD: + if (!PyErr_Occurred()) + PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for %s", ((PyTypeObject*)type_obj)->tp_name); + ret = -1; +__PYX_GOOD: +#if !CYTHON_USE_PYTYPE_LOOKUP + Py_XDECREF(object_reduce); + Py_XDECREF(object_reduce_ex); + Py_XDECREF(object_getstate); + Py_XDECREF(getstate); +#endif + Py_XDECREF(reduce); + Py_XDECREF(reduce_ex); + Py_XDECREF(reduce_cython); + Py_XDECREF(setstate); + Py_XDECREF(setstate_cython); + return ret; +} + +/* SetVTable */ +static int __Pyx_SetVtable(PyObject *dict, void *vtable) { +#if PY_VERSION_HEX >= 0x02070000 + PyObject *ob = PyCapsule_New(vtable, 0, 0); +#else + PyObject *ob = PyCObject_FromVoidPtr(vtable, 0); +#endif + if (!ob) + goto bad; + if (PyDict_SetItem(dict, __pyx_n_s_pyx_vtable, ob) < 0) + goto bad; + Py_DECREF(ob); + return 0; +bad: + Py_XDECREF(ob); + return -1; +} + +/* TypeImport */ +#ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, + size_t size, enum __Pyx_ImportType_CheckSize check_size) +{ + PyObject *result = 0; + char warning[200]; + Py_ssize_t basicsize; +#ifdef Py_LIMITED_API + PyObject *py_basicsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if ((size_t)basicsize < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* CLineInTraceback */ +#ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; + #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; + py_srcfile = PyString_FromString(filename); + if (!py_srcfile) goto bad; + #endif + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + if (!py_funcname) goto bad; + #endif + } + #if PY_MAJOR_VERSION < 3 + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline + return py_code; +bad: + Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(int) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(int) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(int) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(int), + little, !is_unsigned); + } +} + +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} +#endif +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; i '9'); + break; + } + if (rt_from_call[i] != ctversion[i]) { + same = 0; + break; + } + } + if (!same) { + char rtversion[5] = {'\0'}; + char message[200]; + for (i=0; i<4; ++i) { + if (rt_from_call[i] == '.') { + if (found_dot) break; + found_dot = 1; + } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { + break; + } + rtversion[i] = rt_from_call[i]; + } + PyOS_snprintf(message, sizeof(message), + "compiletime version %s of module '%.100s' " + "does not match runtime version %s", + ctversion, __Pyx_MODULE_NAME, rtversion); + return PyErr_WarnEx(NULL, message, 1); + } + return 0; +} + +/* InitStrings */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { + while (t->p) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) +#else + if (likely(PyLong_Check(x))) +#endif + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + #if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = m->nb_int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = m->nb_long(x); + } + #else + if (likely(m && m->nb_int)) { + name = "int"; + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); + } +#endif + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { +#else + if (unlikely(!PyLong_CheckExact(res))) { +#endif + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ diff --git a/_pydevd_bundle/pydevd_cython.pxd b/_pydevd_bundle/pydevd_cython.pxd new file mode 100644 index 0000000..51bb495 --- /dev/null +++ b/_pydevd_bundle/pydevd_cython.pxd @@ -0,0 +1,27 @@ +cdef class PyDBAdditionalThreadInfo: + cdef public int pydev_state + cdef public object pydev_step_stop # Actually, it's a frame or None + cdef public int pydev_original_step_cmd + cdef public int pydev_step_cmd + cdef public bint pydev_notify_kill + cdef public object pydev_smart_step_stop # Actually, it's a frame or None + cdef public bint pydev_django_resolve_frame + cdef public object pydev_call_from_jinja2 + cdef public object pydev_call_inside_jinja2 + cdef public int is_tracing + cdef public tuple conditional_breakpoint_exception + cdef public str pydev_message + cdef public int suspend_type + cdef public int pydev_next_line + cdef public str pydev_func_name + cdef public bint suspended_at_unhandled + cdef public str trace_suspend_type + cdef public object top_level_thread_tracer_no_back_frames + cdef public object top_level_thread_tracer_unhandled + cdef public object thread_tracer + cdef public object step_in_initial_location + cdef public int pydev_smart_parent_offset + cdef public int pydev_smart_child_offset + cdef public tuple pydev_smart_step_into_variants + cdef public dict target_id_to_smart_step_into_variant + cdef public bint pydev_use_scoped_step_frame diff --git a/_pydevd_bundle/pydevd_cython.pyx b/_pydevd_bundle/pydevd_cython.pyx new file mode 100644 index 0000000..da21f49 --- /dev/null +++ b/_pydevd_bundle/pydevd_cython.pyx @@ -0,0 +1,1870 @@ +from __future__ import print_function + +# Important: Autogenerated file. + +# DO NOT edit manually! +# DO NOT edit manually! +from _pydevd_bundle.pydevd_constants import (STATE_RUN, PYTHON_SUSPEND, SUPPORT_GEVENT, ForkSafeLock, + _current_frames) +from _pydev_bundle import pydev_log +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +pydev_log.debug("Using Cython speedups") +# ELSE +# from _pydevd_bundle.pydevd_frame import PyDBFrame +# ENDIF + +version = 11 + + +#======================================================================================================================= +# PyDBAdditionalThreadInfo +#======================================================================================================================= +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef class PyDBAdditionalThreadInfo: +# ELSE +# class PyDBAdditionalThreadInfo(object): +# ENDIF + + # Note: the params in cython are declared in pydevd_cython.pxd. + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + # ELSE +# __slots__ = [ +# 'pydev_state', +# 'pydev_step_stop', +# 'pydev_original_step_cmd', +# 'pydev_step_cmd', +# 'pydev_notify_kill', +# 'pydev_django_resolve_frame', +# 'pydev_call_from_jinja2', +# 'pydev_call_inside_jinja2', +# 'is_tracing', +# 'conditional_breakpoint_exception', +# 'pydev_message', +# 'suspend_type', +# 'pydev_next_line', +# 'pydev_func_name', +# 'suspended_at_unhandled', +# 'trace_suspend_type', +# 'top_level_thread_tracer_no_back_frames', +# 'top_level_thread_tracer_unhandled', +# 'thread_tracer', +# 'step_in_initial_location', +# +# # Used for CMD_SMART_STEP_INTO (to know which smart step into variant to use) +# 'pydev_smart_parent_offset', +# 'pydev_smart_child_offset', +# +# # Used for CMD_SMART_STEP_INTO (list[_pydevd_bundle.pydevd_bytecode_utils.Variant]) +# # Filled when the cmd_get_smart_step_into_variants is requested (so, this is a copy +# # of the last request for a given thread and pydev_smart_parent_offset/pydev_smart_child_offset relies on it). +# 'pydev_smart_step_into_variants', +# 'target_id_to_smart_step_into_variant', +# +# 'pydev_use_scoped_step_frame', +# ] + # ENDIF + + def __init__(self): + self.pydev_state = STATE_RUN # STATE_RUN or STATE_SUSPEND + self.pydev_step_stop = None + + # Note: we have `pydev_original_step_cmd` and `pydev_step_cmd` because the original is to + # say the action that started it and the other is to say what's the current tracing behavior + # (because it's possible that we start with a step over but may have to switch to a + # different step strategy -- for instance, if a step over is done and we return the current + # method the strategy is changed to a step in). + + self.pydev_original_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. + self.pydev_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc. + + self.pydev_notify_kill = False + self.pydev_django_resolve_frame = False + self.pydev_call_from_jinja2 = None + self.pydev_call_inside_jinja2 = None + self.is_tracing = 0 + self.conditional_breakpoint_exception = None + self.pydev_message = '' + self.suspend_type = PYTHON_SUSPEND + self.pydev_next_line = -1 + self.pydev_func_name = '.invalid.' # Must match the type in cython + self.suspended_at_unhandled = False + self.trace_suspend_type = 'trace' # 'trace' or 'frame_eval' + self.top_level_thread_tracer_no_back_frames = [] + self.top_level_thread_tracer_unhandled = None + self.thread_tracer = None + self.step_in_initial_location = None + self.pydev_smart_parent_offset = -1 + self.pydev_smart_child_offset = -1 + self.pydev_smart_step_into_variants = () + self.target_id_to_smart_step_into_variant = {} + + # Flag to indicate ipython use-case where each line will be executed as a call/line/return + # in a new new frame but in practice we want to consider each new frame as if it was all + # part of the same frame. + # + # In practice this means that a step over shouldn't revert to a step in and we need some + # special logic to know when we should stop in a step over as we need to consider 2 + # different frames as being equal if they're logically the continuation of a frame + # being executed by ipython line by line. + # + # See: https://github.com/microsoft/debugpy/issues/869#issuecomment-1132141003 + self.pydev_use_scoped_step_frame = False + + def get_topmost_frame(self, thread): + ''' + Gets the topmost frame for the given thread. Note that it may be None + and callers should remove the reference to the frame as soon as possible + to avoid disturbing user code. + ''' + # sys._current_frames(): dictionary with thread id -> topmost frame + current_frames = _current_frames() + topmost_frame = current_frames.get(thread.ident) + if topmost_frame is None: + # Note: this is expected for dummy threads (so, getting the topmost frame should be + # treated as optional). + pydev_log.info( + 'Unable to get topmost frame for thread: %s, thread.ident: %s, id(thread): %s\nCurrent frames: %s.\n' + 'GEVENT_SUPPORT: %s', + thread, + thread.ident, + id(thread), + current_frames, + SUPPORT_GEVENT, + ) + + return topmost_frame + + def __str__(self): + return 'State:%s Stop:%s Cmd: %s Kill:%s' % ( + self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill) + + +_set_additional_thread_info_lock = ForkSafeLock() + + +def set_additional_thread_info(thread): + try: + additional_info = thread.additional_info + if additional_info is None: + raise AttributeError() + except: + with _set_additional_thread_info_lock: + # If it's not there, set it within a lock to avoid any racing + # conditions. + additional_info = getattr(thread, 'additional_info', None) + if additional_info is None: + additional_info = PyDBAdditionalThreadInfo() + thread.additional_info = additional_info + + return additional_info +import linecache +import os.path +import re + +from _pydev_bundle import pydev_log +from _pydevd_bundle import pydevd_dont_trace +from _pydevd_bundle.pydevd_constants import (RETURN_VALUES_DICT, NO_FTRACE, + EXCEPTION_TYPE_HANDLED, EXCEPTION_TYPE_USER_UNHANDLED, PYDEVD_IPYTHON_CONTEXT) +from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace +from _pydevd_bundle.pydevd_utils import get_clsname_for_code +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame +from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK +try: + from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset +except ImportError: + + def get_smart_step_into_variant_from_frame_offset(*args, **kwargs): + return None + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +# ELSE +# # Note: those are now inlined on cython. +# 107 = 107 +# 144 = 144 +# 109 = 109 +# 160 = 160 +# 108 = 108 +# 159 = 159 +# 137 = 137 +# 111 = 111 +# 128 = 128 +# 206 = 206 +# 1 = 1 +# 2 = 2 +# ENDIF + +basename = os.path.basename + +IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') +DEBUG_START = ('pydevd.py', 'run') +DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') +TRACE_PROPERTY = 'pydevd_traceproperty.py' + +import dis + +try: + StopAsyncIteration +except NameError: + StopAsyncIteration = StopIteration + + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef is_unhandled_exception(container_obj, py_db, frame, int last_raise_line, set raise_lines): +# ELSE +# def is_unhandled_exception(container_obj, py_db, frame, last_raise_line, raise_lines): +# ENDIF + if frame.f_lineno in raise_lines: + return True + + else: + try_except_infos = container_obj.try_except_infos + if try_except_infos is None: + container_obj.try_except_infos = try_except_infos = py_db.collect_try_except_info(frame.f_code) + + if not try_except_infos: + # Consider the last exception as unhandled because there's no try..except in it. + return True + else: + # Now, consider only the try..except for the raise + valid_try_except_infos = [] + for try_except_info in try_except_infos: + if try_except_info.is_line_in_try_block(last_raise_line): + valid_try_except_infos.append(try_except_info) + + if not valid_try_except_infos: + return True + + else: + # Note: check all, not only the "valid" ones to cover the case + # in "tests_python.test_tracing_on_top_level.raise_unhandled10" + # where one try..except is inside the other with only a raise + # and it's gotten in the except line. + for try_except_info in try_except_infos: + if try_except_info.is_line_in_except_block(frame.f_lineno): + if ( + frame.f_lineno == try_except_info.except_line or + frame.f_lineno in try_except_info.raise_lines_in_except + ): + # In a raise inside a try..except block or some except which doesn't + # match the raised exception. + return True + return False + + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef class _TryExceptContainerObj: + cdef public list try_except_infos; + def __init__(self): + self.try_except_infos = None +# ELSE +# class _TryExceptContainerObj(object): +# ''' +# A dumb container object just to containe the try..except info when needed. Meant to be +# persisent among multiple PyDBFrames to the same code object. +# ''' +# try_except_infos = None +# ENDIF + + +#======================================================================================================================= +# PyDBFrame +#======================================================================================================================= +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef class PyDBFrame: +# ELSE +# class PyDBFrame: +# '''This makes the tracing for a given frame, so, the trace_dispatch +# is used initially when we enter into a new context ('call') and then +# is reused for the entire context. +# ''' +# ENDIF + + # Note: class (and not instance) attributes. + + # Same thing in the main debugger but only considering the file contents, while the one in the main debugger + # considers the user input (so, the actual result must be a join of both). + filename_to_lines_where_exceptions_are_ignored = {} + filename_to_stat_info = {} + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef tuple _args + cdef int should_skip + cdef object exc_info + def __init__(self, tuple args): + self._args = args # In the cython version we don't need to pass the frame + self.should_skip = -1 # On cythonized version, put in instance. + self.exc_info = () + # ELSE +# should_skip = -1 # Default value in class (put in instance on set). +# exc_info = () # Default value in class (put in instance on set). +# +# def __init__(self, args): +# # args = main_debugger, abs_path_canonical_path_and_base, base, info, t, frame +# # yeap, much faster than putting in self and then getting it from self later on +# self._args = args + # ENDIF + + def set_suspend(self, *args, **kwargs): + self._args[0].set_suspend(*args, **kwargs) + + def do_wait_suspend(self, *args, **kwargs): + self._args[0].do_wait_suspend(*args, **kwargs) + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + def trace_exception(self, frame, str event, arg): + cdef bint should_stop; + cdef tuple exc_info; + # ELSE +# def trace_exception(self, frame, event, arg): + # ENDIF + if event == 'exception': + should_stop, frame = self._should_stop_on_exception(frame, event, arg) + + if should_stop: + if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + return self.trace_dispatch + + elif event == 'return': + exc_info = self.exc_info + if exc_info and arg is None: + frame_skips_cache, frame_cache_key = self._args[4], self._args[5] + custom_key = (frame_cache_key, 'try_exc_info') + container_obj = frame_skips_cache.get(custom_key) + if container_obj is None: + container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ + self.handle_user_exception(frame): + return self.trace_dispatch + + return self.trace_exception + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef _should_stop_on_exception(self, frame, str event, arg): + cdef PyDBAdditionalThreadInfo info; + cdef bint should_stop; + cdef bint was_just_raised; + cdef list check_excs; + # ELSE +# def _should_stop_on_exception(self, frame, event, arg): + # ENDIF + + # main_debugger, _filename, info, _thread = self._args + main_debugger = self._args[0] + info = self._args[2] + should_stop = False + + # 2 = 2 + if info.pydev_state != 2: # and breakpoint is not None: + exception, value, trace = arg + + if trace is not None and hasattr(trace, 'tb_next'): + # on jython trace is None on the first event and it may not have a tb_next. + + should_stop = False + exception_breakpoint = None + try: + if main_debugger.plugin is not None: + result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + if result: + should_stop, frame = result + except: + pydev_log.exception() + + if not should_stop: + # Apply checks that don't need the exception breakpoint (where we shouldn't ever stop). + if exception == SystemExit and main_debugger.ignore_system_exit_code(value): + pass + + elif exception in (GeneratorExit, StopIteration, StopAsyncIteration): + # These exceptions are control-flow related (they work as a generator + # pause), so, we shouldn't stop on them. + pass + + elif ignore_exception_trace(trace): + pass + + else: + was_just_raised = trace.tb_next is None + + # It was not handled by any plugin, lets check exception breakpoints. + check_excs = [] + + # Note: check user unhandled before regular exceptions. + exc_break_user = main_debugger.get_exception_breakpoint( + exception, main_debugger.break_on_user_uncaught_exceptions) + if exc_break_user is not None: + check_excs.append((exc_break_user, True)) + + exc_break_caught = main_debugger.get_exception_breakpoint( + exception, main_debugger.break_on_caught_exceptions) + if exc_break_caught is not None: + check_excs.append((exc_break_caught, False)) + + for exc_break, is_user_uncaught in check_excs: + # Initially mark that it should stop and then go into exclusions. + should_stop = True + + if main_debugger.exclude_exception_by_filter(exc_break, trace): + pydev_log.debug("Ignore exception %s in library %s -- (%s)" % (exception, frame.f_code.co_filename, frame.f_code.co_name)) + should_stop = False + + elif exc_break.condition is not None and \ + not main_debugger.handle_breakpoint_condition(info, exc_break, frame): + should_stop = False + + elif is_user_uncaught: + # Note: we don't stop here, we just collect the exc_info to use later on... + should_stop = False + if not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) \ + and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)): + # User uncaught means that we're currently in user code but the code + # up the stack is library code. + exc_info = self.exc_info + if not exc_info: + exc_info = (arg, frame.f_lineno, set([frame.f_lineno])) + else: + lines = exc_info[2] + lines.add(frame.f_lineno) + exc_info = (arg, frame.f_lineno, lines) + self.exc_info = exc_info + else: + # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + if exc_break.notify_on_first_raise_only and main_debugger.skip_on_exceptions_thrown_in_same_context \ + and not was_just_raised and not just_raised(trace.tb_next): + # In this case we never stop if it was just raised, so, to know if it was the first we + # need to check if we're in the 2nd method. + should_stop = False # I.e.: we stop only when we're at the caller of a method that throws an exception + + elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ + and not was_just_raised: + should_stop = False # I.e.: we stop only when it was just raised + + elif was_just_raised and main_debugger.skip_on_exceptions_thrown_in_same_context: + # Option: Don't break if an exception is caught in the same function from which it is thrown + should_stop = False + + if should_stop: + exception_breakpoint = exc_break + try: + info.pydev_message = exc_break.qname + except: + info.pydev_message = exc_break.qname.encode('utf-8') + break + + if should_stop: + # Always add exception to frame (must remove later after we proceed). + add_exception_to_frame(frame, (exception, value, trace)) + + if exception_breakpoint is not None and exception_breakpoint.expression is not None: + main_debugger.handle_breakpoint_expression(exception_breakpoint, info, frame) + + return should_stop, frame + + def handle_user_exception(self, frame): + exc_info = self.exc_info + if exc_info: + return self._handle_exception(frame, 'exception', exc_info[0], EXCEPTION_TYPE_USER_UNHANDLED) + return False + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef _handle_exception(self, frame, str event, arg, str exception_type): + cdef bint stopped; + cdef tuple abs_real_path_and_base; + cdef str absolute_filename; + cdef str canonical_normalized_filename; + cdef dict filename_to_lines_where_exceptions_are_ignored; + cdef dict lines_ignored; + cdef dict frame_id_to_frame; + cdef dict merged; + cdef object trace_obj; + cdef object main_debugger; + # ELSE +# def _handle_exception(self, frame, event, arg, exception_type): + # ENDIF + stopped = False + try: + # print('_handle_exception', frame.f_lineno, frame.f_code.co_name) + + # We have 3 things in arg: exception type, description, traceback object + trace_obj = arg[2] + main_debugger = self._args[0] + + initial_trace_obj = trace_obj + if trace_obj.tb_next is None and trace_obj.tb_frame is frame: + # I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check). + pass + else: + # Get the trace_obj from where the exception was raised... + while trace_obj.tb_next is not None: + trace_obj = trace_obj.tb_next + + if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: + for check_trace_obj in (initial_trace_obj, trace_obj): + abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) + absolute_filename = abs_real_path_and_base[0] + canonical_normalized_filename = abs_real_path_and_base[1] + + filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored + + lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + if lines_ignored is None: + lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + + try: + curr_stat = os.stat(absolute_filename) + curr_stat = (curr_stat.st_size, curr_stat.st_mtime) + except: + curr_stat = None + + last_stat = self.filename_to_stat_info.get(absolute_filename) + if last_stat != curr_stat: + self.filename_to_stat_info[absolute_filename] = curr_stat + lines_ignored.clear() + try: + linecache.checkcache(absolute_filename) + except: + pydev_log.exception('Error in linecache.checkcache(%r)', absolute_filename) + + from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + if from_user_input: + merged = {} + merged.update(lines_ignored) + # Override what we have with the related entries that the user entered + merged.update(from_user_input) + else: + merged = lines_ignored + + exc_lineno = check_trace_obj.tb_lineno + + # print ('lines ignored', lines_ignored) + # print ('user input', from_user_input) + # print ('merged', merged, 'curr', exc_lineno) + + if exc_lineno not in merged: # Note: check on merged but update lines_ignored. + try: + line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + except: + pydev_log.exception('Error in linecache.getline(%r, %s, f_globals)', absolute_filename, exc_lineno) + line = '' + + if IGNORE_EXCEPTION_TAG.match(line) is not None: + lines_ignored[exc_lineno] = 1 + return False + else: + # Put in the cache saying not to ignore + lines_ignored[exc_lineno] = 0 + else: + # Ok, dict has it already cached, so, let's check it... + if merged.get(exc_lineno, 0): + return False + + thread = self._args[3] + + try: + frame_id_to_frame = {} + frame_id_to_frame[id(frame)] = frame + f = trace_obj.tb_frame + while f is not None: + frame_id_to_frame[id(f)] = f + f = f.f_back + f = None + + stopped = True + main_debugger.send_caught_exception_stack(thread, arg, id(frame)) + try: + self.set_suspend(thread, 137) + self.do_wait_suspend(thread, frame, event, arg, exception_type=exception_type) + finally: + main_debugger.send_caught_exception_stack_proceeded(thread) + except: + pydev_log.exception() + + main_debugger.set_trace_for_frame_and_parents(frame) + finally: + # Make sure the user cannot see the '__exception__' we added after we leave the suspend state. + remove_exception_from_frame(frame) + # Clear some local variables... + frame = None + trace_obj = None + initial_trace_obj = None + check_trace_obj = None + f = None + frame_id_to_frame = None + main_debugger = None + thread = None + + return stopped + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef get_func_name(self, frame): + cdef str func_name + # ELSE +# def get_func_name(self, frame): + # ENDIF + code_obj = frame.f_code + func_name = code_obj.co_name + try: + cls_name = get_clsname_for_code(code_obj, frame) + if cls_name is not None: + return "%s.%s" % (cls_name, func_name) + else: + return func_name + except: + pydev_log.exception() + return func_name + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef _show_return_values(self, frame, arg): + # ELSE +# def _show_return_values(self, frame, arg): + # ENDIF + try: + try: + f_locals_back = getattr(frame.f_back, "f_locals", None) + if f_locals_back is not None: + return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) + if return_values_dict is None: + return_values_dict = {} + f_locals_back[RETURN_VALUES_DICT] = return_values_dict + name = self.get_func_name(frame) + return_values_dict[name] = arg + except: + pydev_log.exception() + finally: + f_locals_back = None + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef _remove_return_values(self, main_debugger, frame): + # ELSE +# def _remove_return_values(self, main_debugger, frame): + # ENDIF + try: + try: + # Showing return values was turned off, we should remove them from locals dict. + # The values can be in the current frame or in the back one + frame.f_locals.pop(RETURN_VALUES_DICT, None) + + f_locals_back = getattr(frame.f_back, "f_locals", None) + if f_locals_back is not None: + f_locals_back.pop(RETURN_VALUES_DICT, None) + except: + pydev_log.exception() + finally: + f_locals_back = None + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef _get_unfiltered_back_frame(self, main_debugger, frame): + # ELSE +# def _get_unfiltered_back_frame(self, main_debugger, frame): + # ENDIF + f = frame.f_back + while f is not None: + if not main_debugger.is_files_filter_enabled: + return f + + else: + if main_debugger.apply_files_filter(f, f.f_code.co_filename, False): + f = f.f_back + + else: + return f + + return f + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef _is_same_frame(self, target_frame, current_frame): + cdef PyDBAdditionalThreadInfo info; + # ELSE +# def _is_same_frame(self, target_frame, current_frame): + # ENDIF + if target_frame is current_frame: + return True + + info = self._args[2] + if info.pydev_use_scoped_step_frame: + # If using scoped step we don't check the target, we just need to check + # if the current matches the same heuristic where the target was defined. + if target_frame is not None and current_frame is not None: + if target_frame.f_code.co_filename == current_frame.f_code.co_filename: + # The co_name may be different (it may include the line number), but + # the filename must still be the same. + f = current_frame.f_back + if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + f = f.f_back + if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + return True + + return False + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cpdef trace_dispatch(self, frame, str event, arg): + cdef tuple abs_path_canonical_path_and_base; + cdef bint is_exception_event; + cdef bint has_exception_breakpoints; + cdef bint can_skip; + cdef bint stop; + cdef PyDBAdditionalThreadInfo info; + cdef int step_cmd; + cdef int line; + cdef bint is_line; + cdef bint is_call; + cdef bint is_return; + cdef bint should_stop; + cdef dict breakpoints_for_file; + cdef dict stop_info; + cdef str curr_func_name; + cdef bint exist_result; + cdef dict frame_skips_cache; + cdef object frame_cache_key; + cdef tuple line_cache_key; + cdef int breakpoints_in_line_cache; + cdef int breakpoints_in_frame_cache; + cdef bint has_breakpoint_in_frame; + cdef bint is_coroutine_or_generator; + cdef int bp_line; + cdef object bp; + cdef int pydev_smart_parent_offset + cdef int pydev_smart_child_offset + cdef tuple pydev_smart_step_into_variants + # ELSE +# def trace_dispatch(self, frame, event, arg): + # ENDIF + # Note: this is a big function because most of the logic related to hitting a breakpoint and + # stepping is contained in it. Ideally this could be split among multiple functions, but the + # problem in this case is that in pure-python function calls are expensive and even more so + # when tracing is on (because each function call will get an additional tracing call). We + # try to address this by using the info.is_tracing for the fastest possible return, but the + # cost is still high (maybe we could use code-generation in the future and make the code + # generation be better split among what each part does). + + # DEBUG = '_debugger_case_generator.py' in frame.f_code.co_filename + main_debugger, abs_path_canonical_path_and_base, info, thread, frame_skips_cache, frame_cache_key = self._args + # if DEBUG: print('frame trace_dispatch %s %s %s %s %s %s, stop: %s' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event, constant_to_str(info.pydev_step_cmd), arg, info.pydev_step_stop)) + try: + info.is_tracing += 1 + + # TODO: This shouldn't be needed. The fact that frame.f_lineno + # is None seems like a bug in Python 3.11. + # Reported in: https://github.com/python/cpython/issues/94485 + line = frame.f_lineno or 0 # Workaround or case where frame.f_lineno is None + line_cache_key = (frame_cache_key, line) + + if main_debugger.pydb_disposed: + return None if event == 'call' else NO_FTRACE + + plugin_manager = main_debugger.plugin + has_exception_breakpoints = ( + main_debugger.break_on_caught_exceptions + or main_debugger.break_on_user_uncaught_exceptions + or main_debugger.has_plugin_exception_breaks) + + stop_frame = info.pydev_step_stop + step_cmd = info.pydev_step_cmd + function_breakpoint_on_call_event = None + + if frame.f_code.co_flags & 0xa0: # 0xa0 == CO_GENERATOR = 0x20 | CO_COROUTINE = 0x80 + # Dealing with coroutines and generators: + # When in a coroutine we change the perceived event to the debugger because + # a call, StopIteration exception and return are usually just pausing/unpausing it. + if event == 'line': + is_line = True + is_call = False + is_return = False + is_exception_event = False + + elif event == 'return': + is_line = False + is_call = False + is_return = True + is_exception_event = False + + returns_cache_key = (frame_cache_key, 'returns') + return_lines = frame_skips_cache.get(returns_cache_key) + if return_lines is None: + # Note: we're collecting the return lines by inspecting the bytecode as + # there are multiple returns and multiple stop iterations when awaiting and + # it doesn't give any clear indication when a coroutine or generator is + # finishing or just pausing. + return_lines = set() + for x in main_debugger.collect_return_info(frame.f_code): + # Note: cython does not support closures in cpdefs (so we can't use + # a list comprehension). + return_lines.add(x.return_line) + + frame_skips_cache[returns_cache_key] = return_lines + + if line not in return_lines: + # Not really a return (coroutine/generator paused). + return self.trace_dispatch + else: + if self.exc_info: + self.handle_user_exception(frame) + return self.trace_dispatch + + # Tricky handling: usually when we're on a frame which is about to exit + # we set the step mode to step into, but in this case we'd end up in the + # asyncio internal machinery, which is not what we want, so, we just + # ask the stop frame to be a level up. + # + # Note that there's an issue here which we may want to fix in the future: if + # the back frame is a frame which is filtered, we won't stop properly. + # Solving this may not be trivial as we'd need to put a scope in the step + # in, but we may have to do it anyways to have a step in which doesn't end + # up in asyncio). + # + # Note2: we don't revert to a step in if we're doing scoped stepping + # (because on scoped stepping we're always receiving a call/line/return + # event for each line in ipython, so, we can't revert to step in on return + # as the return shouldn't mean that we've actually completed executing a + # frame in this case). + if stop_frame is frame and not info.pydev_use_scoped_step_frame: + if step_cmd in (108, 159, 107, 144): + f = self._get_unfiltered_back_frame(main_debugger, frame) + if f is not None: + info.pydev_step_cmd = 206 + info.pydev_step_stop = f + else: + if step_cmd == 108: + info.pydev_step_cmd = 107 + info.pydev_step_stop = None + + elif step_cmd == 159: + info.pydev_step_cmd = 144 + info.pydev_step_stop = None + + elif step_cmd == 206: + # We're exiting this one, so, mark the new coroutine context. + f = self._get_unfiltered_back_frame(main_debugger, frame) + if f is not None: + info.pydev_step_stop = f + else: + info.pydev_step_cmd = 107 + info.pydev_step_stop = None + + elif event == 'exception': + breakpoints_for_file = None + if has_exception_breakpoints: + should_stop, frame = self._should_stop_on_exception(frame, event, arg) + if should_stop: + if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + return self.trace_dispatch + + return self.trace_dispatch + else: + # event == 'call' or event == 'c_XXX' + return self.trace_dispatch + + else: # Not coroutine nor generator + if event == 'line': + is_line = True + is_call = False + is_return = False + is_exception_event = False + + elif event == 'return': + is_line = False + is_return = True + is_call = False + is_exception_event = False + + # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break + # eventually. Force the step mode to step into and the step stop frame to None. + # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user + # to make a step in or step over at that location). + # Note: this is especially troublesome when we're skipping code with the + # @DontTrace comment. + if ( + stop_frame is frame and + not info.pydev_use_scoped_step_frame and is_return and + step_cmd in (108, 109, 159, 160, 128) + ): + + if step_cmd in (108, 109, 128): + info.pydev_step_cmd = 107 + else: + info.pydev_step_cmd = 144 + info.pydev_step_stop = None + + if self.exc_info: + if self.handle_user_exception(frame): + return self.trace_dispatch + + elif event == 'call': + is_line = False + is_call = True + is_return = False + is_exception_event = False + if frame.f_code.co_firstlineno == frame.f_lineno: # Check line to deal with async/await. + function_breakpoint_on_call_event = main_debugger.function_breakpoint_name_to_breakpoint.get(frame.f_code.co_name) + + elif event == 'exception': + is_exception_event = True + breakpoints_for_file = None + if has_exception_breakpoints: + should_stop, frame = self._should_stop_on_exception(frame, event, arg) + if should_stop: + if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + return self.trace_dispatch + is_line = False + is_return = False + is_call = False + + else: + # Unexpected: just keep the same trace func (i.e.: event == 'c_XXX'). + return self.trace_dispatch + + if not is_exception_event: + breakpoints_for_file = main_debugger.breakpoints.get(abs_path_canonical_path_and_base[1]) + + can_skip = False + + if info.pydev_state == 1: # 1 = 1 + # we can skip if: + # - we have no stop marked + # - we should make a step return/step over and we're not in the current frame + # - we're stepping into a coroutine context and we're not in that context + if step_cmd == -1: + can_skip = True + + elif step_cmd in (108, 109, 159, 160) and not self._is_same_frame(stop_frame, frame): + can_skip = True + + elif step_cmd == 128 and ( + stop_frame is not None and + stop_frame is not frame and + stop_frame is not frame.f_back and + (frame.f_back is None or stop_frame is not frame.f_back.f_back)): + can_skip = True + + elif step_cmd == 144: + if ( + main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) + and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)) + ): + can_skip = True + + elif step_cmd == 206: + f = frame + while f is not None: + if self._is_same_frame(stop_frame, f): + break + f = f.f_back + else: + can_skip = True + + if can_skip: + if plugin_manager is not None and ( + main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): + can_skip = plugin_manager.can_skip(main_debugger, frame) + + if can_skip and main_debugger.show_return_values and info.pydev_step_cmd in (108, 159) and self._is_same_frame(stop_frame, frame.f_back): + # trace function for showing return values after step over + can_skip = False + + # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint, + # we will return nothing for the next trace + # also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway, + # so, that's why the additional checks are there. + + if function_breakpoint_on_call_event: + pass # Do nothing here (just keep on going as we can't skip it). + + elif not breakpoints_for_file: + if can_skip: + if has_exception_breakpoints: + return self.trace_exception + else: + return None if is_call else NO_FTRACE + + else: + # When cached, 0 means we don't have a breakpoint and 1 means we have. + if can_skip: + breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1) + if breakpoints_in_line_cache == 0: + return self.trace_dispatch + + breakpoints_in_frame_cache = frame_skips_cache.get(frame_cache_key, -1) + if breakpoints_in_frame_cache != -1: + # Gotten from cache. + has_breakpoint_in_frame = breakpoints_in_frame_cache == 1 + + else: + has_breakpoint_in_frame = False + + try: + func_lines = set() + for offset_and_lineno in dis.findlinestarts(frame.f_code): + func_lines.add(offset_and_lineno[1]) + except: + # This is a fallback for implementations where we can't get the function + # lines -- i.e.: jython (in this case clients need to provide the function + # name to decide on the skip or we won't be able to skip the function + # completely). + + # Checks the breakpoint to see if there is a context match in some function. + curr_func_name = frame.f_code.co_name + + # global context is set with an empty name + if curr_func_name in ('?', '', ''): + curr_func_name = '' + + for bp in breakpoints_for_file.values(): + # will match either global or some function + if bp.func_name in ('None', curr_func_name): + has_breakpoint_in_frame = True + break + else: + for bp_line in breakpoints_for_file: # iterate on keys + if bp_line in func_lines: + has_breakpoint_in_frame = True + break + + # Cache the value (1 or 0 or -1 for default because of cython). + if has_breakpoint_in_frame: + frame_skips_cache[frame_cache_key] = 1 + else: + frame_skips_cache[frame_cache_key] = 0 + + if can_skip and not has_breakpoint_in_frame: + if has_exception_breakpoints: + return self.trace_exception + else: + return None if is_call else NO_FTRACE + + # We may have hit a breakpoint or we are already in step mode. Either way, let's check what we should do in this frame + # if DEBUG: print('NOT skipped: %s %s %s %s' % (frame.f_lineno, frame.f_code.co_name, event, frame.__class__.__name__)) + + try: + flag = False + # return is not taken into account for breakpoint hit because we'd have a double-hit in this case + # (one for the line and the other for the return). + + stop_info = {} + breakpoint = None + exist_result = False + stop = False + stop_reason = 111 + bp_type = None + + if function_breakpoint_on_call_event: + breakpoint = function_breakpoint_on_call_event + stop = True + new_frame = frame + stop_reason = CMD_SET_FUNCTION_BREAK + + elif is_line and info.pydev_state != 2 and breakpoints_for_file is not None and line in breakpoints_for_file: + breakpoint = breakpoints_for_file[line] + new_frame = frame + stop = True + if step_cmd in (108, 159) and (self._is_same_frame(stop_frame, frame) and is_line): + stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) + elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: + result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) + if result: + exist_result = True + flag, breakpoint, new_frame, bp_type = result + + if breakpoint: + # ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint + # lets do the conditional stuff here + if breakpoint.expression is not None: + main_debugger.handle_breakpoint_expression(breakpoint, info, new_frame) + if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: + cmd = main_debugger.cmd_factory.make_io_message(info.pydev_message + os.linesep, '1') + main_debugger.writer.add_command(cmd) + + if stop or exist_result: + eval_result = False + if breakpoint.has_condition: + eval_result = main_debugger.handle_breakpoint_condition(info, breakpoint, new_frame) + + if breakpoint.has_condition: + if not eval_result: + stop = False + elif breakpoint.is_logpoint: + stop = False + + if is_call and (frame.f_code.co_name in ('', '') or (line == 1 and frame.f_code.co_name.startswith(' may be executed having each line compiled as a new + # module, so it's the same case as . + + return self.trace_dispatch + + if main_debugger.show_return_values: + if is_return and ( + (info.pydev_step_cmd in (108, 159, 128) and (self._is_same_frame(stop_frame, frame.f_back))) or + (info.pydev_step_cmd in (109, 160) and (self._is_same_frame(stop_frame, frame))) or + (info.pydev_step_cmd in (107, 206)) or + ( + info.pydev_step_cmd == 144 + and frame.f_back is not None + and not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True) + ) + ): + self._show_return_values(frame, arg) + + elif main_debugger.remove_return_values_flag: + try: + self._remove_return_values(main_debugger, frame) + finally: + main_debugger.remove_return_values_flag = False + + if stop: + self.set_suspend( + thread, + stop_reason, + suspend_other_threads=breakpoint and breakpoint.suspend_policy == "ALL", + ) + + elif flag and plugin_manager is not None: + result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) + if result: + frame = result + + # if thread has a suspend flag, we suspend with a busy wait + if info.pydev_state == 2: + self.do_wait_suspend(thread, frame, event, arg) + return self.trace_dispatch + else: + if not breakpoint and is_line: + # No stop from anyone and no breakpoint found in line (cache that). + frame_skips_cache[line_cache_key] = 0 + + except: + pydev_log.exception() + raise + + # step handling. We stop when we hit the right frame + try: + should_skip = 0 + if pydevd_dont_trace.should_trace_hook is not None: + if self.should_skip == -1: + # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). + # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code + # Which will be handled by this frame is read-only, so, we can cache it safely. + if not pydevd_dont_trace.should_trace_hook(frame, abs_path_canonical_path_and_base[0]): + # -1, 0, 1 to be Cython-friendly + should_skip = self.should_skip = 1 + else: + should_skip = self.should_skip = 0 + else: + should_skip = self.should_skip + + plugin_stop = False + if should_skip: + stop = False + + elif step_cmd in (107, 144, 206): + force_check_project_scope = step_cmd == 144 + if is_line: + if not info.pydev_use_scoped_step_frame: + if force_check_project_scope or main_debugger.is_files_filter_enabled: + stop = not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, force_check_project_scope) + else: + stop = True + else: + # We can only stop inside the ipython call. + filename = frame.f_code.co_filename + if filename.endswith('.pyc'): + filename = filename[:-1] + + if not filename.endswith(PYDEVD_IPYTHON_CONTEXT[0]): + f = frame.f_back + while f is not None: + if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + f2 = f.f_back + if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + pydev_log.debug('Stop inside ipython call') + stop = True + break + f = f.f_back + + del f + + if not stop: + # In scoped mode if step in didn't work in this context it won't work + # afterwards anyways. + return None if is_call else NO_FTRACE + + elif is_return and frame.f_back is not None and not info.pydev_use_scoped_step_frame: + if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + stop = False + else: + if force_check_project_scope or main_debugger.is_files_filter_enabled: + stop = not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, force_check_project_scope) + if stop: + # Prevent stopping in a return to the same location we were initially + # (i.e.: double-stop at the same place due to some filtering). + if info.step_in_initial_location == (frame.f_back, frame.f_back.f_lineno): + stop = False + else: + stop = True + else: + stop = False + + if stop: + if step_cmd == 206: + # i.e.: Check if we're stepping into the proper context. + f = frame + while f is not None: + if self._is_same_frame(stop_frame, f): + break + f = f.f_back + else: + stop = False + + if plugin_manager is not None: + result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) + if result: + stop, plugin_stop = result + + elif step_cmd in (108, 159): + # Note: when dealing with a step over my code it's the same as a step over (the + # difference is that when we return from a frame in one we go to regular step + # into and in the other we go to a step into my code). + stop = self._is_same_frame(stop_frame, frame) and is_line + # Note: don't stop on a return for step over, only for line events + # i.e.: don't stop in: (stop_frame is frame.f_back and is_return) as we'd stop twice in that line. + + if plugin_manager is not None: + result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) + if result: + stop, plugin_stop = result + + elif step_cmd == 128: + stop = False + back = frame.f_back + if self._is_same_frame(stop_frame, frame) and is_return: + # We're exiting the smart step into initial frame (so, we probably didn't find our target). + stop = True + + elif self._is_same_frame(stop_frame, back) and is_line: + if info.pydev_smart_child_offset != -1: + # i.e.: in this case, we're not interested in the pause in the parent, rather + # we're interested in the pause in the child (when the parent is at the proper place). + stop = False + + else: + pydev_smart_parent_offset = info.pydev_smart_parent_offset + + pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: + # Preferred mode (when the smart step into variants are available + # and the offset is set). + stop = get_smart_step_into_variant_from_frame_offset(back.f_lasti, pydev_smart_step_into_variants) is \ + get_smart_step_into_variant_from_frame_offset(pydev_smart_parent_offset, pydev_smart_step_into_variants) + + else: + # Only the name/line is available, so, check that. + curr_func_name = frame.f_code.co_name + + # global context is set with an empty name + if curr_func_name in ('?', '') or curr_func_name is None: + curr_func_name = '' + if curr_func_name == info.pydev_func_name and stop_frame.f_lineno == info.pydev_next_line: + stop = True + + if not stop: + # In smart step into, if we didn't hit it in this frame once, that'll + # not be the case next time either, so, disable tracing for this frame. + return None if is_call else NO_FTRACE + + elif back is not None and self._is_same_frame(stop_frame, back.f_back) and is_line: + # Ok, we have to track 2 stops at this point, the parent and the child offset. + # This happens when handling a step into which targets a function inside a list comprehension + # or generator (in which case an intermediary frame is created due to an internal function call). + pydev_smart_parent_offset = info.pydev_smart_parent_offset + pydev_smart_child_offset = info.pydev_smart_child_offset + # print('matched back frame', pydev_smart_parent_offset, pydev_smart_child_offset) + # print('parent f_lasti', back.f_back.f_lasti) + # print('child f_lasti', back.f_lasti) + stop = False + if pydev_smart_child_offset >= 0 and pydev_smart_child_offset >= 0: + pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + + if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: + # Note that we don't really check the parent offset, only the offset of + # the child (because this is a generator, the parent may have moved forward + # already -- and that's ok, so, we just check that the parent frame + # matches in this case). + smart_step_into_variant = get_smart_step_into_variant_from_frame_offset(pydev_smart_parent_offset, pydev_smart_step_into_variants) + # print('matched parent offset', pydev_smart_parent_offset) + # Ok, now, check the child variant + children_variants = smart_step_into_variant.children_variants + stop = children_variants and ( + get_smart_step_into_variant_from_frame_offset(back.f_lasti, children_variants) is \ + get_smart_step_into_variant_from_frame_offset(pydev_smart_child_offset, children_variants) + ) + # print('stop at child', stop) + + if not stop: + # In smart step into, if we didn't hit it in this frame once, that'll + # not be the case next time either, so, disable tracing for this frame. + return None if is_call else NO_FTRACE + + elif step_cmd in (109, 160): + stop = is_return and self._is_same_frame(stop_frame, frame) + + else: + stop = False + + if stop and step_cmd != -1 and is_return and hasattr(frame, "f_back"): + f_code = getattr(frame.f_back, 'f_code', None) + if f_code is not None: + if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + stop = False + + if plugin_stop: + stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) + elif stop: + if is_line: + self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + self.do_wait_suspend(thread, frame, event, arg) + elif is_return: # return event + back = frame.f_back + if back is not None: + # When we get to the pydevd run function, the debugging has actually finished for the main thread + # (note that it can still go on for other threads, but for this one, we just make it finish) + # So, just setting it to None should be OK + back_absolute_filename, _, base = get_abs_path_real_path_and_base_from_frame(back) + if (base, back.f_code.co_name) in (DEBUG_START, DEBUG_START_PY3K): + back = None + + elif base == TRACE_PROPERTY: + # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging) + # if we're in a return, we want it to appear to the user in the previous frame! + return None if is_call else NO_FTRACE + + elif pydevd_dont_trace.should_trace_hook is not None: + if not pydevd_dont_trace.should_trace_hook(back, back_absolute_filename): + # In this case, we'll have to skip the previous one because it shouldn't be traced. + # Also, we have to reset the tracing, because if the parent's parent (or some + # other parent) has to be traced and it's not currently, we wouldn't stop where + # we should anymore (so, a step in/over/return may not stop anywhere if no parent is traced). + # Related test: _debugger_case17a.py + main_debugger.set_trace_for_frame_and_parents(back) + return None if is_call else NO_FTRACE + + if back is not None: + # if we're in a return, we want it to appear to the user in the previous frame! + self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + self.do_wait_suspend(thread, back, event, arg) + else: + # in jython we may not have a back frame + info.pydev_step_stop = None + info.pydev_original_step_cmd = -1 + info.pydev_step_cmd = -1 + info.pydev_state = 1 + + except KeyboardInterrupt: + raise + except: + try: + pydev_log.exception() + info.pydev_original_step_cmd = -1 + info.pydev_step_cmd = -1 + info.pydev_step_stop = None + except: + return None if is_call else NO_FTRACE + + # if we are quitting, let's stop the tracing + if main_debugger.quitting: + return None if is_call else NO_FTRACE + + return self.trace_dispatch + finally: + info.is_tracing -= 1 + + # end trace_dispatch +from _pydev_bundle.pydev_is_thread_alive import is_thread_alive +from _pydev_bundle.pydev_log import exception as pydev_log_exception +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle.pydevd_constants import (get_current_thread_id, NO_FTRACE, + USE_CUSTOM_SYS_CURRENT_FRAMES_MAP, ForkSafeLock) +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +from cpython.object cimport PyObject +from cpython.ref cimport Py_INCREF, Py_XDECREF +# ELSE +# from _pydevd_bundle.pydevd_frame import PyDBFrame, is_unhandled_exception +# ENDIF + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef dict _global_notify_skipped_step_in +# ELSE +# # Note: those are now inlined on cython. +# 107 = 107 +# 144 = 144 +# 109 = 109 +# 160 = 160 +# ENDIF + +# Cache where we should keep that we completely skipped entering some context. +# It needs to be invalidated when: +# - Breakpoints are changed +# It can be used when running regularly (without step over/step in/step return) +global_cache_skips = {} +global_cache_frame_skips = {} + +_global_notify_skipped_step_in = False +_global_notify_skipped_step_in_lock = ForkSafeLock() + + +def notify_skipped_step_in_because_of_filters(py_db, frame): + global _global_notify_skipped_step_in + + with _global_notify_skipped_step_in_lock: + if _global_notify_skipped_step_in: + # Check with lock in place (callers should actually have checked + # before without the lock in place due to performance). + return + _global_notify_skipped_step_in = True + py_db.notify_skipped_step_in_because_of_filters(frame) + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef class SafeCallWrapper: + cdef method_object + def __init__(self, method_object): + self.method_object = method_object + def __call__(self, *args): + #Cannot use 'self' once inside the delegate call since we are borrowing the self reference f_trace field + #in the frame, and that reference might get destroyed by set trace on frame and parents + cdef PyObject* method_obj = self.method_object + Py_INCREF(method_obj) + ret = (method_obj)(*args) + Py_XDECREF (method_obj) + return SafeCallWrapper(ret) if ret is not None else None + def get_method_object(self): + return self.method_object +# ELSE +# ENDIF + + +def fix_top_level_trace_and_get_trace_func(py_db, frame): + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef str filename; + cdef str name; + cdef tuple args; + # ENDIF + + # Note: this is always the first entry-point in the tracing for any thread. + # After entering here we'll set a new tracing function for this thread + # where more information is cached (and will also setup the tracing for + # frames where we should deal with unhandled exceptions). + thread = None + # Cache the frame which should be traced to deal with unhandled exceptions. + # (i.e.: thread entry-points). + + f_unhandled = frame + # print('called at', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + force_only_unhandled_tracer = False + while f_unhandled is not None: + # name = splitext(basename(f_unhandled.f_code.co_filename))[0] + + name = f_unhandled.f_code.co_filename + # basename + i = name.rfind('/') + j = name.rfind('\\') + if j > i: + i = j + if i >= 0: + name = name[i + 1:] + # remove ext + i = name.rfind('.') + if i >= 0: + name = name[:i] + + if name == 'threading': + if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'): + # We need __bootstrap_inner, not __bootstrap. + return None, False + + elif f_unhandled.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'): + # Note: be careful not to use threading.currentThread to avoid creating a dummy thread. + t = f_unhandled.f_locals.get('self') + force_only_unhandled_tracer = True + if t is not None and isinstance(t, threading.Thread): + thread = t + break + + elif name == 'pydev_monkey': + if f_unhandled.f_code.co_name == '__call__': + force_only_unhandled_tracer = True + break + + elif name == 'pydevd': + if f_unhandled.f_code.co_name in ('run', 'main'): + # We need to get to _exec + return None, False + + if f_unhandled.f_code.co_name == '_exec': + force_only_unhandled_tracer = True + break + + elif name == 'pydevd_tracing': + return None, False + + elif f_unhandled.f_back is None: + break + + f_unhandled = f_unhandled.f_back + + if thread is None: + # Important: don't call threadingCurrentThread if we're in the threading module + # to avoid creating dummy threads. + if py_db.threading_get_ident is not None: + thread = py_db.threading_active.get(py_db.threading_get_ident()) + if thread is None: + return None, False + else: + # Jython does not have threading.get_ident(). + thread = py_db.threading_current_thread() + + if getattr(thread, 'pydev_do_not_trace', None): + py_db.disable_tracing() + return None, False + + try: + additional_info = thread.additional_info + if additional_info is None: + raise AttributeError() + except: + additional_info = py_db.set_additional_thread_info(thread) + + # print('enter thread tracer', thread, get_current_thread_id(thread)) + args = (py_db, thread, additional_info, global_cache_skips, global_cache_frame_skips) + + if f_unhandled is not None: + if f_unhandled.f_back is None and not force_only_unhandled_tracer: + # Happens when we attach to a running program (cannot reuse instance because it's mutable). + top_level_thread_tracer = TopLevelThreadTracerNoBackFrame(ThreadTracer(args), args) + additional_info.top_level_thread_tracer_no_back_frames.append(top_level_thread_tracer) # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). + else: + top_level_thread_tracer = additional_info.top_level_thread_tracer_unhandled + if top_level_thread_tracer is None: + # Stop in some internal place to report about unhandled exceptions + top_level_thread_tracer = TopLevelThreadTracerOnlyUnhandledExceptions(args) + additional_info.top_level_thread_tracer_unhandled = top_level_thread_tracer # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). + + # print(' --> found to trace unhandled', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + f_trace = top_level_thread_tracer.get_trace_dispatch_func() + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + f_trace = SafeCallWrapper(f_trace) + # ENDIF + f_unhandled.f_trace = f_trace + + if frame is f_unhandled: + return f_trace, False + + thread_tracer = additional_info.thread_tracer + if thread_tracer is None or thread_tracer._args[0] is not py_db: + thread_tracer = ThreadTracer(args) + additional_info.thread_tracer = thread_tracer + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + return SafeCallWrapper(thread_tracer), True +# ELSE +# return thread_tracer, True +# ENDIF + + +def trace_dispatch(py_db, frame, event, arg): + thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + if thread_trace_func is None: + return None if event == 'call' else NO_FTRACE + if apply_to_settrace: + py_db.enable_tracing(thread_trace_func) + return thread_trace_func(frame, event, arg) + + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef class TopLevelThreadTracerOnlyUnhandledExceptions: + cdef public tuple _args; + def __init__(self, tuple args): + self._args = args +# ELSE +# class TopLevelThreadTracerOnlyUnhandledExceptions(object): +# +# def __init__(self, args): +# self._args = args +# ENDIF + + def trace_unhandled_exceptions(self, frame, event, arg): + # Note that we ignore the frame as this tracing method should only be put in topmost frames already. + # print('trace_unhandled_exceptions', event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno) + if event == 'exception' and arg is not None: + py_db, t, additional_info = self._args[0:3] + if arg is not None: + if not additional_info.suspended_at_unhandled: + additional_info.suspended_at_unhandled = True + + py_db.stop_on_unhandled_exception(py_db, t, additional_info, arg) + + # No need to reset frame.f_trace to keep the same trace function. + return self.trace_unhandled_exceptions + + def get_trace_dispatch_func(self): + return self.trace_unhandled_exceptions + + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef class TopLevelThreadTracerNoBackFrame: + cdef public object _frame_trace_dispatch; + cdef public tuple _args; + cdef public object try_except_infos; + cdef public object _last_exc_arg; + cdef public set _raise_lines; + cdef public int _last_raise_line; + def __init__(self, frame_trace_dispatch, tuple args): + self._frame_trace_dispatch = frame_trace_dispatch + self._args = args + self.try_except_infos = None + self._last_exc_arg = None + self._raise_lines = set() + self._last_raise_line = -1 +# ELSE +# class TopLevelThreadTracerNoBackFrame(object): +# ''' +# This tracer is pretty special in that it's dealing with a frame without f_back (i.e.: top frame +# on remote attach or QThread). +# +# This means that we have to carefully inspect exceptions to discover whether the exception will +# be unhandled or not (if we're dealing with an unhandled exception we need to stop as unhandled, +# otherwise we need to use the regular tracer -- unfortunately the debugger has little info to +# work with in the tracing -- see: https://bugs.python.org/issue34099, so, we inspect bytecode to +# determine if some exception will be traced or not... note that if this is not available -- such +# as on Jython -- we consider any top-level exception to be unnhandled). +# ''' +# +# def __init__(self, frame_trace_dispatch, args): +# self._frame_trace_dispatch = frame_trace_dispatch +# self._args = args +# self.try_except_infos = None +# self._last_exc_arg = None +# self._raise_lines = set() +# self._last_raise_line = -1 +# ENDIF + + def trace_dispatch_and_unhandled_exceptions(self, frame, event, arg): + # DEBUG = 'code_to_debug' in frame.f_code.co_filename + # if DEBUG: print('trace_dispatch_and_unhandled_exceptions: %s %s %s %s %s %s' % (event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno, self._frame_trace_dispatch, frame.f_lineno)) + frame_trace_dispatch = self._frame_trace_dispatch + if frame_trace_dispatch is not None: + self._frame_trace_dispatch = frame_trace_dispatch(frame, event, arg) + + if event == 'exception': + self._last_exc_arg = arg + self._raise_lines.add(frame.f_lineno) + self._last_raise_line = frame.f_lineno + + elif event == 'return' and self._last_exc_arg is not None: + # For unhandled exceptions we actually track the return when at the topmost level. + try: + py_db, t, additional_info = self._args[0:3] + if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. + if is_unhandled_exception(self, py_db, frame, self._last_raise_line, self._raise_lines): + py_db.stop_on_unhandled_exception(py_db, t, additional_info, self._last_exc_arg) + finally: + # Remove reference to exception after handling it. + self._last_exc_arg = None + + ret = self.trace_dispatch_and_unhandled_exceptions + + # Need to reset (the call to _frame_trace_dispatch may have changed it). + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + frame.f_trace = SafeCallWrapper(ret) + # ELSE +# frame.f_trace = ret + # ENDIF + return ret + + def get_trace_dispatch_func(self): + return self.trace_dispatch_and_unhandled_exceptions + + +# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) +cdef class ThreadTracer: + cdef public tuple _args; + def __init__(self, tuple args): + self._args = args +# ELSE +# class ThreadTracer(object): +# +# def __init__(self, args): +# self._args = args +# ENDIF + + def __call__(self, frame, event, arg): + ''' This is the callback used when we enter some context in the debugger. + + We also decorate the thread we are in with info about the debugging. + The attributes added are: + pydev_state + pydev_step_stop + pydev_step_cmd + pydev_notify_kill + + :param PyDB py_db: + This is the global debugger (this method should actually be added as a method to it). + ''' + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + cdef str filename; + cdef str base; + cdef int pydev_step_cmd; + cdef object frame_cache_key; + cdef dict cache_skips; + cdef bint is_stepping; + cdef tuple abs_path_canonical_path_and_base; + cdef PyDBAdditionalThreadInfo additional_info; + # ENDIF + + # DEBUG = 'code_to_debug' in frame.f_code.co_filename + # if DEBUG: print('ENTER: trace_dispatch: %s %s %s %s' % (frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)) + py_db, t, additional_info, cache_skips, frame_skips_cache = self._args + if additional_info.is_tracing: + return None if event == 'call' else NO_FTRACE # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch + + additional_info.is_tracing += 1 + try: + pydev_step_cmd = additional_info.pydev_step_cmd + is_stepping = pydev_step_cmd != -1 + if py_db.pydb_disposed: + return None if event == 'call' else NO_FTRACE + + # if thread is not alive, cancel trace_dispatch processing + if not is_thread_alive(t): + py_db.notify_thread_not_alive(get_current_thread_id(t)) + return None if event == 'call' else NO_FTRACE + + # Note: it's important that the context name is also given because we may hit something once + # in the global context and another in the local context. + frame_cache_key = frame.f_code + if frame_cache_key in cache_skips: + if not is_stepping: + # if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + else: + # When stepping we can't take into account caching based on the breakpoints (only global filtering). + if cache_skips.get(frame_cache_key) == 1: + + if additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: + notify_skipped_step_in_because_of_filters(py_db, frame) + + back_frame = frame.f_back + if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + back_frame_cache_key = back_frame.f_code + if cache_skips.get(back_frame_cache_key) == 1: + # if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + else: + # if DEBUG: print('skipped: trace_dispatch (cache hit: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + + try: + # Make fast path faster! + abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + except: + abs_path_canonical_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) + + file_type = py_db.get_file_type(frame, abs_path_canonical_path_and_base) # we don't want to debug threading or anything related to pydevd + + if file_type is not None: + if file_type == 1: # inlining LIB_FILE = 1 + if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): + # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + cache_skips[frame_cache_key] = 1 + return None if event == 'call' else NO_FTRACE + else: + # if DEBUG: print('skipped: trace_dispatch', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + cache_skips[frame_cache_key] = 1 + return None if event == 'call' else NO_FTRACE + + if py_db.is_files_filter_enabled: + if py_db.apply_files_filter(frame, abs_path_canonical_path_and_base[0], False): + cache_skips[frame_cache_key] = 1 + + if is_stepping and additional_info.pydev_original_step_cmd in (107, 144) and not _global_notify_skipped_step_in: + notify_skipped_step_in_because_of_filters(py_db, frame) + + # A little gotcha, sometimes when we're stepping in we have to stop in a + # return event showing the back frame as the current frame, so, we need + # to check not only the current frame but the back frame too. + back_frame = frame.f_back + if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160): + if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): + back_frame_cache_key = back_frame.f_code + cache_skips[back_frame_cache_key] = 1 + # if DEBUG: print('skipped: trace_dispatch (filtered out: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + else: + # if DEBUG: print('skipped: trace_dispatch (filtered out: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + + # if DEBUG: print('trace_dispatch', filename, frame.f_lineno, event, frame.f_code.co_name, file_type) + + # Just create PyDBFrame directly (removed support for Python versions < 2.5, which required keeping a weak + # reference to the frame). + ret = PyDBFrame( + ( + py_db, abs_path_canonical_path_and_base, additional_info, t, frame_skips_cache, frame_cache_key, + ) + ).trace_dispatch(frame, event, arg) + if ret is None: + # 1 means skipped because of filters. + # 2 means skipped because no breakpoints were hit. + cache_skips[frame_cache_key] = 2 + return None if event == 'call' else NO_FTRACE + + # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated) + frame.f_trace = SafeCallWrapper(ret) # Make sure we keep the returned tracer. + # ELSE +# frame.f_trace = ret # Make sure we keep the returned tracer. + # ENDIF + return ret + + except SystemExit: + return None if event == 'call' else NO_FTRACE + + except Exception: + if py_db.pydb_disposed: + return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. + # Log it + try: + if pydev_log_exception is not None: + # This can actually happen during the interpreter shutdown in Python 2.7 + pydev_log_exception() + except: + # Error logging? We're really in the interpreter shutdown... + # (https://github.com/fabioz/PyDev.Debugger/issues/8) + pass + return None if event == 'call' else NO_FTRACE + finally: + additional_info.is_tracing -= 1 + + +if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP: + # This is far from ideal, as we'll leak frames (we'll always have the last created frame, not really + # the last topmost frame saved -- this should be Ok for our usage, but it may leak frames and things + # may live longer... as IronPython is garbage-collected, things should live longer anyways, so, it + # shouldn't be an issue as big as it's in CPython -- it may still be annoying, but this should + # be a reasonable workaround until IronPython itself is able to provide that functionality). + # + # See: https://github.com/IronLanguages/main/issues/1630 + from _pydevd_bundle.pydevd_constants import constructed_tid_to_last_frame + + _original_call = ThreadTracer.__call__ + + def __call__(self, frame, event, arg): + constructed_tid_to_last_frame[self._args[1].ident] = frame + return _original_call(self, frame, event, arg) + + ThreadTracer.__call__ = __call__ diff --git a/_pydevd_bundle/pydevd_cython_wrapper.py b/_pydevd_bundle/pydevd_cython_wrapper.py new file mode 100644 index 0000000..1058519 --- /dev/null +++ b/_pydevd_bundle/pydevd_cython_wrapper.py @@ -0,0 +1,52 @@ +import sys +try: + try: + from _pydevd_bundle_ext import pydevd_cython as mod + + except ImportError: + from _pydevd_bundle import pydevd_cython as mod + +except ImportError: + import struct + + try: + is_python_64bit = (struct.calcsize('P') == 8) + except: + # In Jython this call fails, but this is Ok, we don't support Jython for speedups anyways. + raise ImportError + plat = '32' + if is_python_64bit: + plat = '64' + + # We also accept things as: + # + # _pydevd_bundle.pydevd_cython_win32_27_32 + # _pydevd_bundle.pydevd_cython_win32_34_64 + # + # to have multiple pre-compiled pyds distributed along the IDE + # (generated by build_tools/build_binaries_windows.py). + + mod_name = 'pydevd_cython_%s_%s%s_%s' % (sys.platform, sys.version_info[0], sys.version_info[1], plat) + check_name = '_pydevd_bundle.%s' % (mod_name,) + mod = getattr(__import__(check_name), mod_name) + +# Regardless of how it was found, make sure it's later available as the +# initial name so that the expected types from cython in frame eval +# are valid. +sys.modules['_pydevd_bundle.pydevd_cython'] = mod + +trace_dispatch = mod.trace_dispatch + +PyDBAdditionalThreadInfo = mod.PyDBAdditionalThreadInfo + +set_additional_thread_info = mod.set_additional_thread_info + +global_cache_skips = mod.global_cache_skips + +global_cache_frame_skips = mod.global_cache_frame_skips + +_set_additional_thread_info_lock = mod._set_additional_thread_info_lock + +fix_top_level_trace_and_get_trace_func = mod.fix_top_level_trace_and_get_trace_func + +version = getattr(mod, 'version', 0) diff --git a/_pydevd_bundle/pydevd_daemon_thread.py b/_pydevd_bundle/pydevd_daemon_thread.py new file mode 100644 index 0000000..8729597 --- /dev/null +++ b/_pydevd_bundle/pydevd_daemon_thread.py @@ -0,0 +1,193 @@ +from _pydev_bundle._pydev_saved_modules import threading +from _pydev_bundle import _pydev_saved_modules +from _pydevd_bundle.pydevd_utils import notify_about_gevent_if_needed +import weakref +from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_IRONPYTHON, \ + PYDEVD_APPLY_PATCHING_TO_HIDE_PYDEVD_THREADS +from _pydev_bundle.pydev_log import exception as pydev_log_exception +import sys +from _pydev_bundle import pydev_log +import pydevd_tracing +from _pydevd_bundle.pydevd_collect_bytecode_info import iter_instructions + +if IS_JYTHON: + import org.python.core as JyCore # @UnresolvedImport + + +class PyDBDaemonThread(threading.Thread): + + def __init__(self, py_db, target_and_args=None): + ''' + :param target_and_args: + tuple(func, args, kwargs) if this should be a function and args to run. + -- Note: use through run_as_pydevd_daemon_thread(). + ''' + threading.Thread.__init__(self) + notify_about_gevent_if_needed() + self._py_db = weakref.ref(py_db) + self._kill_received = False + mark_as_pydevd_daemon_thread(self) + self._target_and_args = target_and_args + + @property + def py_db(self): + return self._py_db() + + def run(self): + created_pydb_daemon = self.py_db.created_pydb_daemon_threads + created_pydb_daemon[self] = 1 + try: + try: + if IS_JYTHON and not isinstance(threading.current_thread(), threading._MainThread): + # we shouldn't update sys.modules for the main thread, cause it leads to the second importing 'threading' + # module, and the new instance of main thread is created + ss = JyCore.PySystemState() + # Note: Py.setSystemState() affects only the current thread. + JyCore.Py.setSystemState(ss) + + self._stop_trace() + self._on_run() + except: + if sys is not None and pydev_log_exception is not None: + pydev_log_exception() + finally: + del created_pydb_daemon[self] + + def _on_run(self): + if self._target_and_args is not None: + target, args, kwargs = self._target_and_args + target(*args, **kwargs) + else: + raise NotImplementedError('Should be reimplemented by: %s' % self.__class__) + + def do_kill_pydev_thread(self): + if not self._kill_received: + pydev_log.debug('%s received kill signal', self.name) + self._kill_received = True + + def _stop_trace(self): + if self.pydev_do_not_trace: + pydevd_tracing.SetTrace(None) # no debugging on this thread + + +def _collect_load_names(func): + found_load_names = set() + for instruction in iter_instructions(func.__code__): + if instruction.opname in ('LOAD_GLOBAL', 'LOAD_ATTR', 'LOAD_METHOD'): + found_load_names.add(instruction.argrepr) + return found_load_names + + +def _patch_threading_to_hide_pydevd_threads(): + ''' + Patches the needed functions on the `threading` module so that the pydevd threads are hidden. + + Note that we patch the functions __code__ to avoid issues if some code had already imported those + variables prior to the patching. + ''' + found_load_names = _collect_load_names(threading.enumerate) + # i.e.: we'll only apply the patching if the function seems to be what we expect. + + new_threading_enumerate = None + + if found_load_names in ( + {'_active_limbo_lock', '_limbo', '_active', 'values', 'list'}, + {'_active_limbo_lock', '_limbo', '_active', 'values', 'NULL + list'} + ): + pydev_log.debug('Applying patching to hide pydevd threads (Py3 version).') + + def new_threading_enumerate(): + with _active_limbo_lock: + ret = list(_active.values()) + list(_limbo.values()) + + return [t for t in ret if not getattr(t, 'is_pydev_daemon_thread', False)] + + elif found_load_names == set(('_active_limbo_lock', '_limbo', '_active', 'values')): + pydev_log.debug('Applying patching to hide pydevd threads (Py2 version).') + + def new_threading_enumerate(): + with _active_limbo_lock: + ret = _active.values() + _limbo.values() + + return [t for t in ret if not getattr(t, 'is_pydev_daemon_thread', False)] + + else: + pydev_log.info('Unable to hide pydevd threads. Found names in threading.enumerate: %s', found_load_names) + + if new_threading_enumerate is not None: + + def pydevd_saved_threading_enumerate(): + with threading._active_limbo_lock: + return list(threading._active.values()) + list(threading._limbo.values()) + + _pydev_saved_modules.pydevd_saved_threading_enumerate = pydevd_saved_threading_enumerate + + threading.enumerate.__code__ = new_threading_enumerate.__code__ + + # We also need to patch the active count (to match what we have in the enumerate). + def new_active_count(): + # Note: as this will be executed in the `threading` module, `enumerate` will + # actually be threading.enumerate. + return len(enumerate()) + + threading.active_count.__code__ = new_active_count.__code__ + + # When shutting down, Python (on some versions) may do something as: + # + # def _pickSomeNonDaemonThread(): + # for t in enumerate(): + # if not t.daemon and t.is_alive(): + # return t + # return None + # + # But in this particular case, we do want threads with `is_pydev_daemon_thread` to appear + # explicitly due to the pydevd `CheckAliveThread` (because we want the shutdown to wait on it). + # So, it can't rely on the `enumerate` for that anymore as it's patched to not return pydevd threads. + if hasattr(threading, '_pickSomeNonDaemonThread'): + + def new_pick_some_non_daemon_thread(): + with _active_limbo_lock: + # Ok for py2 and py3. + threads = list(_active.values()) + list(_limbo.values()) + + for t in threads: + if not t.daemon and t.is_alive(): + return t + return None + + threading._pickSomeNonDaemonThread.__code__ = new_pick_some_non_daemon_thread.__code__ + + +_patched_threading_to_hide_pydevd_threads = False + + +def mark_as_pydevd_daemon_thread(thread): + if not IS_JYTHON and not IS_IRONPYTHON and PYDEVD_APPLY_PATCHING_TO_HIDE_PYDEVD_THREADS: + global _patched_threading_to_hide_pydevd_threads + if not _patched_threading_to_hide_pydevd_threads: + # When we mark the first thread as a pydevd daemon thread, we also change the threading + # functions to hide pydevd threads. + # Note: we don't just "hide" the pydevd threads from the threading module by not using it + # (i.e.: just using the `thread.start_new_thread` instead of `threading.Thread`) + # because there's 1 thread (the `CheckAliveThread`) which is a pydevd thread but + # isn't really a daemon thread (so, we need CPython to wait on it for shutdown, + # in which case it needs to be in `threading` and the patching would be needed anyways). + _patched_threading_to_hide_pydevd_threads = True + try: + _patch_threading_to_hide_pydevd_threads() + except: + pydev_log.exception('Error applying patching to hide pydevd threads.') + + thread.pydev_do_not_trace = True + thread.is_pydev_daemon_thread = True + thread.daemon = True + + +def run_as_pydevd_daemon_thread(py_db, func, *args, **kwargs): + ''' + Runs a function as a pydevd daemon thread (without any tracing in place). + ''' + t = PyDBDaemonThread(py_db, target_and_args=(func, args, kwargs)) + t.name = '%s (pydevd daemon thread)' % (func.__name__,) + t.start() + return t diff --git a/_pydevd_bundle/pydevd_defaults.py b/_pydevd_bundle/pydevd_defaults.py new file mode 100644 index 0000000..ec2393b --- /dev/null +++ b/_pydevd_bundle/pydevd_defaults.py @@ -0,0 +1,8 @@ +''' +This module holds the customization settings for the debugger. +''' +from _pydevd_bundle.pydevd_constants import QUOTED_LINE_PROTOCOL + + +class PydevdCustomization(object): + DEFAULT_PROTOCOL = QUOTED_LINE_PROTOCOL diff --git a/_pydevd_bundle/pydevd_dont_trace.py b/_pydevd_bundle/pydevd_dont_trace.py new file mode 100644 index 0000000..684af67 --- /dev/null +++ b/_pydevd_bundle/pydevd_dont_trace.py @@ -0,0 +1,123 @@ +''' +Support for a tag that allows skipping over functions while debugging. +''' +import linecache +import re + +# To suppress tracing a method, add the tag @DontTrace +# to a comment either preceding or on the same line as +# the method definition +# +# E.g.: +# #@DontTrace +# def test1(): +# pass +# +# ... or ... +# +# def test2(): #@DontTrace +# pass +DONT_TRACE_TAG = '@DontTrace' + +# Regular expression to match a decorator (at the beginning +# of a line). +RE_DECORATOR = re.compile(r'^\s*@') + +# Mapping from code object to bool. +# If the key exists, the value is the cached result of should_trace_hook +_filename_to_ignored_lines = {} + + +def default_should_trace_hook(frame, absolute_filename): + ''' + Return True if this frame should be traced, False if tracing should be blocked. + ''' + # First, check whether this code object has a cached value + ignored_lines = _filename_to_ignored_lines.get(absolute_filename) + if ignored_lines is None: + # Now, look up that line of code and check for a @DontTrace + # preceding or on the same line as the method. + # E.g.: + # #@DontTrace + # def test(): + # pass + # ... or ... + # def test(): #@DontTrace + # pass + ignored_lines = {} + lines = linecache.getlines(absolute_filename) + for i_line, line in enumerate(lines): + j = line.find('#') + if j >= 0: + comment = line[j:] + if DONT_TRACE_TAG in comment: + ignored_lines[i_line] = 1 + + # Note: when it's found in the comment, mark it up and down for the decorator lines found. + k = i_line - 1 + while k >= 0: + if RE_DECORATOR.match(lines[k]): + ignored_lines[k] = 1 + k -= 1 + else: + break + + k = i_line + 1 + while k <= len(lines): + if RE_DECORATOR.match(lines[k]): + ignored_lines[k] = 1 + k += 1 + else: + break + + _filename_to_ignored_lines[absolute_filename] = ignored_lines + + func_line = frame.f_code.co_firstlineno - 1 # co_firstlineno is 1-based, so -1 is needed + return not ( + func_line - 1 in ignored_lines or # -1 to get line before method + func_line in ignored_lines) # method line + + +should_trace_hook = None + + +def clear_trace_filter_cache(): + ''' + Clear the trace filter cache. + Call this after reloading. + ''' + global should_trace_hook + try: + # Need to temporarily disable a hook because otherwise + # _filename_to_ignored_lines.clear() will never complete. + old_hook = should_trace_hook + should_trace_hook = None + + # Clear the linecache + linecache.clearcache() + _filename_to_ignored_lines.clear() + + finally: + should_trace_hook = old_hook + + +def trace_filter(mode): + ''' + Set the trace filter mode. + + mode: Whether to enable the trace hook. + True: Trace filtering on (skipping methods tagged @DontTrace) + False: Trace filtering off (trace methods tagged @DontTrace) + None/default: Toggle trace filtering. + ''' + global should_trace_hook + if mode is None: + mode = should_trace_hook is None + + if mode: + should_trace_hook = default_should_trace_hook + else: + should_trace_hook = None + + return mode + diff --git a/_pydevd_bundle/pydevd_dont_trace_files.py b/_pydevd_bundle/pydevd_dont_trace_files.py new file mode 100644 index 0000000..d37b1fc --- /dev/null +++ b/_pydevd_bundle/pydevd_dont_trace_files.py @@ -0,0 +1,153 @@ +# Important: Autogenerated file. + +# DO NOT edit manually! +# DO NOT edit manually! + +LIB_FILE = 1 +PYDEV_FILE = 2 + +DONT_TRACE_DIRS = { + '_pydev_bundle': PYDEV_FILE, + '_pydev_runfiles': PYDEV_FILE, + '_pydevd_bundle': PYDEV_FILE, + '_pydevd_frame_eval': PYDEV_FILE, + 'pydev_ipython': PYDEV_FILE, + 'pydev_sitecustomize': PYDEV_FILE, + 'pydevd_attach_to_process': PYDEV_FILE, + 'pydevd_concurrency_analyser': PYDEV_FILE, + 'pydevd_plugins': PYDEV_FILE, + 'test_pydevd_reload': PYDEV_FILE, +} + +DONT_TRACE = { + # commonly used things from the stdlib that we don't want to trace + 'Queue.py':LIB_FILE, + 'queue.py':LIB_FILE, + 'socket.py':LIB_FILE, + 'weakref.py':LIB_FILE, + '_weakrefset.py':LIB_FILE, + 'linecache.py':LIB_FILE, + 'threading.py':LIB_FILE, + 'dis.py':LIB_FILE, + + # things from pydev that we don't want to trace + '__main__pydevd_gen_debug_adapter_protocol.py': PYDEV_FILE, + '_pydev_calltip_util.py': PYDEV_FILE, + '_pydev_completer.py': PYDEV_FILE, + '_pydev_execfile.py': PYDEV_FILE, + '_pydev_filesystem_encoding.py': PYDEV_FILE, + '_pydev_getopt.py': PYDEV_FILE, + '_pydev_imports_tipper.py': PYDEV_FILE, + '_pydev_jy_imports_tipper.py': PYDEV_FILE, + '_pydev_log.py': PYDEV_FILE, + '_pydev_saved_modules.py': PYDEV_FILE, + '_pydev_sys_patch.py': PYDEV_FILE, + '_pydev_tipper_common.py': PYDEV_FILE, + 'django_debug.py': PYDEV_FILE, + 'jinja2_debug.py': PYDEV_FILE, + 'pycompletionserver.py': PYDEV_FILE, + 'pydev_app_engine_debug_startup.py': PYDEV_FILE, + 'pydev_console_utils.py': PYDEV_FILE, + 'pydev_import_hook.py': PYDEV_FILE, + 'pydev_imports.py': PYDEV_FILE, + 'pydev_ipython_console.py': PYDEV_FILE, + 'pydev_ipython_console_011.py': PYDEV_FILE, + 'pydev_is_thread_alive.py': PYDEV_FILE, + 'pydev_localhost.py': PYDEV_FILE, + 'pydev_log.py': PYDEV_FILE, + 'pydev_monkey.py': PYDEV_FILE, + 'pydev_monkey_qt.py': PYDEV_FILE, + 'pydev_override.py': PYDEV_FILE, + 'pydev_run_in_console.py': PYDEV_FILE, + 'pydev_runfiles.py': PYDEV_FILE, + 'pydev_runfiles_coverage.py': PYDEV_FILE, + 'pydev_runfiles_nose.py': PYDEV_FILE, + 'pydev_runfiles_parallel.py': PYDEV_FILE, + 'pydev_runfiles_parallel_client.py': PYDEV_FILE, + 'pydev_runfiles_pytest2.py': PYDEV_FILE, + 'pydev_runfiles_unittest.py': PYDEV_FILE, + 'pydev_runfiles_xml_rpc.py': PYDEV_FILE, + 'pydev_umd.py': PYDEV_FILE, + 'pydev_versioncheck.py': PYDEV_FILE, + 'pydevconsole.py': PYDEV_FILE, + 'pydevconsole_code.py': PYDEV_FILE, + 'pydevd.py': PYDEV_FILE, + 'pydevd_additional_thread_info.py': PYDEV_FILE, + 'pydevd_additional_thread_info_regular.py': PYDEV_FILE, + 'pydevd_api.py': PYDEV_FILE, + 'pydevd_base_schema.py': PYDEV_FILE, + 'pydevd_breakpoints.py': PYDEV_FILE, + 'pydevd_bytecode_utils.py': PYDEV_FILE, + 'pydevd_code_to_source.py': PYDEV_FILE, + 'pydevd_collect_bytecode_info.py': PYDEV_FILE, + 'pydevd_comm.py': PYDEV_FILE, + 'pydevd_comm_constants.py': PYDEV_FILE, + 'pydevd_command_line_handling.py': PYDEV_FILE, + 'pydevd_concurrency_logger.py': PYDEV_FILE, + 'pydevd_console.py': PYDEV_FILE, + 'pydevd_constants.py': PYDEV_FILE, + 'pydevd_custom_frames.py': PYDEV_FILE, + 'pydevd_cython_wrapper.py': PYDEV_FILE, + 'pydevd_daemon_thread.py': PYDEV_FILE, + 'pydevd_defaults.py': PYDEV_FILE, + 'pydevd_dont_trace.py': PYDEV_FILE, + 'pydevd_dont_trace_files.py': PYDEV_FILE, + 'pydevd_exec2.py': PYDEV_FILE, + 'pydevd_extension_api.py': PYDEV_FILE, + 'pydevd_extension_utils.py': PYDEV_FILE, + 'pydevd_file_utils.py': PYDEV_FILE, + 'pydevd_filtering.py': PYDEV_FILE, + 'pydevd_frame.py': PYDEV_FILE, + 'pydevd_frame_eval_cython_wrapper.py': PYDEV_FILE, + 'pydevd_frame_eval_main.py': PYDEV_FILE, + 'pydevd_frame_tracing.py': PYDEV_FILE, + 'pydevd_frame_utils.py': PYDEV_FILE, + 'pydevd_gevent_integration.py': PYDEV_FILE, + 'pydevd_helpers.py': PYDEV_FILE, + 'pydevd_import_class.py': PYDEV_FILE, + 'pydevd_io.py': PYDEV_FILE, + 'pydevd_json_debug_options.py': PYDEV_FILE, + 'pydevd_line_validation.py': PYDEV_FILE, + 'pydevd_modify_bytecode.py': PYDEV_FILE, + 'pydevd_net_command.py': PYDEV_FILE, + 'pydevd_net_command_factory_json.py': PYDEV_FILE, + 'pydevd_net_command_factory_xml.py': PYDEV_FILE, + 'pydevd_plugin_numpy_types.py': PYDEV_FILE, + 'pydevd_plugin_pandas_types.py': PYDEV_FILE, + 'pydevd_plugin_utils.py': PYDEV_FILE, + 'pydevd_plugins_django_form_str.py': PYDEV_FILE, + 'pydevd_process_net_command.py': PYDEV_FILE, + 'pydevd_process_net_command_json.py': PYDEV_FILE, + 'pydevd_referrers.py': PYDEV_FILE, + 'pydevd_reload.py': PYDEV_FILE, + 'pydevd_resolver.py': PYDEV_FILE, + 'pydevd_runpy.py': PYDEV_FILE, + 'pydevd_safe_repr.py': PYDEV_FILE, + 'pydevd_save_locals.py': PYDEV_FILE, + 'pydevd_schema.py': PYDEV_FILE, + 'pydevd_schema_log.py': PYDEV_FILE, + 'pydevd_signature.py': PYDEV_FILE, + 'pydevd_source_mapping.py': PYDEV_FILE, + 'pydevd_stackless.py': PYDEV_FILE, + 'pydevd_suspended_frames.py': PYDEV_FILE, + 'pydevd_thread_lifecycle.py': PYDEV_FILE, + 'pydevd_thread_wrappers.py': PYDEV_FILE, + 'pydevd_timeout.py': PYDEV_FILE, + 'pydevd_trace_api.py': PYDEV_FILE, + 'pydevd_trace_dispatch.py': PYDEV_FILE, + 'pydevd_trace_dispatch_regular.py': PYDEV_FILE, + 'pydevd_traceproperty.py': PYDEV_FILE, + 'pydevd_tracing.py': PYDEV_FILE, + 'pydevd_utils.py': PYDEV_FILE, + 'pydevd_vars.py': PYDEV_FILE, + 'pydevd_vm_type.py': PYDEV_FILE, + 'pydevd_xml.py': PYDEV_FILE, +} + +# if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716) +DONT_TRACE['io.py'] = LIB_FILE + +# Don't trace common encodings too +DONT_TRACE['cp1252.py'] = LIB_FILE +DONT_TRACE['utf_8.py'] = LIB_FILE +DONT_TRACE['codecs.py'] = LIB_FILE diff --git a/_pydevd_bundle/pydevd_exec2.py b/_pydevd_bundle/pydevd_exec2.py new file mode 100644 index 0000000..ee4f37a --- /dev/null +++ b/_pydevd_bundle/pydevd_exec2.py @@ -0,0 +1,5 @@ +def Exec(exp, global_vars, local_vars=None): + if local_vars is not None: + exec(exp, global_vars, local_vars) + else: + exec(exp, global_vars) \ No newline at end of file diff --git a/_pydevd_bundle/pydevd_extension_api.py b/_pydevd_bundle/pydevd_extension_api.py new file mode 100644 index 0000000..aac7c79 --- /dev/null +++ b/_pydevd_bundle/pydevd_extension_api.py @@ -0,0 +1,87 @@ +import abc + + +# borrowed from from six +def _with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + return type.__new__(metaclass, 'temporary_class', (), {}) + + +# ======================================================================================================================= +# AbstractResolver +# ======================================================================================================================= +class _AbstractResolver(_with_metaclass(abc.ABCMeta)): + """ + This class exists only for documentation purposes to explain how to create a resolver. + + Some examples on how to resolve things: + - list: get_dictionary could return a dict with index->item and use the index to resolve it later + - set: get_dictionary could return a dict with id(object)->object and reiterate in that array to resolve it later + - arbitrary instance: get_dictionary could return dict with attr_name->attr and use getattr to resolve it later + """ + + @abc.abstractmethod + def resolve(self, var, attribute): + """ + In this method, we'll resolve some child item given the string representation of the item in the key + representing the previously asked dictionary. + + @param var: this is the actual variable to be resolved. + @param attribute: this is the string representation of a key previously returned in get_dictionary. + """ + raise NotImplementedError + + @abc.abstractmethod + def get_dictionary(self, var): + """ + @param var: this is the variable that should have its children gotten. + + @return: a dictionary where each pair key, value should be shown to the user as children items + in the variables view for the given var. + """ + raise NotImplementedError + + +class _AbstractProvider(_with_metaclass(abc.ABCMeta)): + @abc.abstractmethod + def can_provide(self, type_object, type_name): + raise NotImplementedError + + +# ======================================================================================================================= +# API CLASSES: +# ======================================================================================================================= + +class TypeResolveProvider(_AbstractResolver, _AbstractProvider): + """ + Implement this in an extension to provide a custom resolver, see _AbstractResolver + """ + + +class StrPresentationProvider(_AbstractProvider): + """ + Implement this in an extension to provide a str presentation for a type + """ + + @abc.abstractmethod + def get_str(self, val): + raise NotImplementedError + + +class DebuggerEventHandler(_with_metaclass(abc.ABCMeta)): + """ + Implement this to receive lifecycle events from the debugger + """ + + def on_debugger_modules_loaded(self, **kwargs): + """ + This method invoked after all debugger modules are loaded. Useful for importing and/or patching debugger + modules at a safe time + :param kwargs: This is intended to be flexible dict passed from the debugger. + Currently passes the debugger version + """ diff --git a/_pydevd_bundle/pydevd_extension_utils.py b/_pydevd_bundle/pydevd_extension_utils.py new file mode 100644 index 0000000..1386cc7 --- /dev/null +++ b/_pydevd_bundle/pydevd_extension_utils.py @@ -0,0 +1,67 @@ +import pkgutil +import sys +from _pydev_bundle import pydev_log +try: + import pydevd_plugins.extensions as extensions +except: + pydev_log.exception() + extensions = None + + +class ExtensionManager(object): + + def __init__(self): + self.loaded_extensions = None + self.type_to_instance = {} + + def _load_modules(self): + self.loaded_extensions = [] + if extensions: + for module_loader, name, ispkg in pkgutil.walk_packages(extensions.__path__, + extensions.__name__ + '.'): + mod_name = name.split('.')[-1] + if not ispkg and mod_name.startswith('pydevd_plugin'): + try: + __import__(name) + module = sys.modules[name] + self.loaded_extensions.append(module) + except ImportError: + pydev_log.critical('Unable to load extension: %s', name) + + def _ensure_loaded(self): + if self.loaded_extensions is None: + self._load_modules() + + def _iter_attr(self): + for extension in self.loaded_extensions: + dunder_all = getattr(extension, '__all__', None) + for attr_name in dir(extension): + if not attr_name.startswith('_'): + if dunder_all is None or attr_name in dunder_all: + yield attr_name, getattr(extension, attr_name) + + def get_extension_classes(self, extension_type): + self._ensure_loaded() + if extension_type in self.type_to_instance: + return self.type_to_instance[extension_type] + handlers = self.type_to_instance.setdefault(extension_type, []) + for attr_name, attr in self._iter_attr(): + if isinstance(attr, type) and issubclass(attr, extension_type) and attr is not extension_type: + try: + handlers.append(attr()) + except: + pydev_log.exception('Unable to load extension class: %s', attr_name) + return handlers + + +EXTENSION_MANAGER_INSTANCE = ExtensionManager() + + +def extensions_of_type(extension_type): + """ + + :param T extension_type: The type of the extension hook + :rtype: list[T] + """ + return EXTENSION_MANAGER_INSTANCE.get_extension_classes(extension_type) + diff --git a/_pydevd_bundle/pydevd_filtering.py b/_pydevd_bundle/pydevd_filtering.py new file mode 100644 index 0000000..67fd6cf --- /dev/null +++ b/_pydevd_bundle/pydevd_filtering.py @@ -0,0 +1,331 @@ +import fnmatch +import glob +import os.path +import sys + +from _pydev_bundle import pydev_log +import pydevd_file_utils +import json +from collections import namedtuple +from _pydev_bundle._pydev_saved_modules import threading +from pydevd_file_utils import normcase +from _pydevd_bundle.pydevd_constants import USER_CODE_BASENAMES_STARTING_WITH, \ + LIBRARY_CODE_BASENAMES_STARTING_WITH, IS_PYPY, IS_WINDOWS +from _pydevd_bundle import pydevd_constants + +ExcludeFilter = namedtuple('ExcludeFilter', 'name, exclude, is_path') + + +def _convert_to_str_and_clear_empty(roots): + new_roots = [] + for root in roots: + assert isinstance(root, str), '%s not str (found: %s)' % (root, type(root)) + if root: + new_roots.append(root) + return new_roots + + +def _check_matches(patterns, paths): + if not patterns and not paths: + # Matched to the end. + return True + + if (not patterns and paths) or (patterns and not paths): + return False + + pattern = normcase(patterns[0]) + path = normcase(paths[0]) + + if not glob.has_magic(pattern): + + if pattern != path: + return False + + elif pattern == '**': + if len(patterns) == 1: + return True # if ** is the last one it matches anything to the right. + + for i in range(len(paths)): + # Recursively check the remaining patterns as the + # current pattern could match any number of paths. + if _check_matches(patterns[1:], paths[i:]): + return True + + elif not fnmatch.fnmatch(path, pattern): + # Current part doesn't match. + return False + + return _check_matches(patterns[1:], paths[1:]) + + +def glob_matches_path(path, pattern, sep=os.sep, altsep=os.altsep): + if altsep: + pattern = pattern.replace(altsep, sep) + path = path.replace(altsep, sep) + + drive = '' + if len(path) > 1 and path[1] == ':': + drive, path = path[0], path[2:] + + if drive and len(pattern) > 1: + if pattern[1] == ':': + if drive.lower() != pattern[0].lower(): + return False + pattern = pattern[2:] + + patterns = pattern.split(sep) + paths = path.split(sep) + if paths: + if paths[0] == '': + paths = paths[1:] + if patterns: + if patterns[0] == '': + patterns = patterns[1:] + + return _check_matches(patterns, paths) + + +class FilesFiltering(object): + ''' + Note: calls at FilesFiltering are uncached. + + The actual API used should be through PyDB. + ''' + + def __init__(self): + self._exclude_filters = [] + self._project_roots = [] + self._library_roots = [] + + # Filter out libraries? + self._use_libraries_filter = False + self.require_module = False # True if some exclude filter filters by the module. + + self.set_use_libraries_filter(os.getenv('PYDEVD_FILTER_LIBRARIES') is not None) + + project_roots = os.getenv('IDE_PROJECT_ROOTS', None) + if project_roots is not None: + project_roots = project_roots.split(os.pathsep) + else: + project_roots = [] + self.set_project_roots(project_roots) + + library_roots = os.getenv('LIBRARY_ROOTS', None) + if library_roots is not None: + library_roots = library_roots.split(os.pathsep) + else: + library_roots = self._get_default_library_roots() + self.set_library_roots(library_roots) + + # Stepping filters. + pydevd_filters = os.getenv('PYDEVD_FILTERS', '') + # To filter out it's something as: {'**/not_my_code/**': True} + if pydevd_filters: + pydev_log.debug("PYDEVD_FILTERS %s", (pydevd_filters,)) + if pydevd_filters.startswith('{'): + # dict(glob_pattern (str) -> exclude(True or False)) + exclude_filters = [] + for key, val in json.loads(pydevd_filters).items(): + exclude_filters.append(ExcludeFilter(key, val, True)) + self._exclude_filters = exclude_filters + else: + # A ';' separated list of strings with globs for the + # list of excludes. + filters = pydevd_filters.split(';') + new_filters = [] + for new_filter in filters: + if new_filter.strip(): + new_filters.append(ExcludeFilter(new_filter.strip(), True, True)) + self._exclude_filters = new_filters + + @classmethod + def _get_default_library_roots(cls): + pydev_log.debug("Collecting default library roots.") + # Provide sensible defaults if not in env vars. + import site + + roots = [] + + try: + import sysconfig # Python 2.7 onwards only. + except ImportError: + pass + else: + for path_name in set(('stdlib', 'platstdlib', 'purelib', 'platlib')) & set(sysconfig.get_path_names()): + roots.append(sysconfig.get_path(path_name)) + + # Make sure we always get at least the standard library location (based on the `os` and + # `threading` modules -- it's a bit weird that it may be different on the ci, but it happens). + roots.append(os.path.dirname(os.__file__)) + roots.append(os.path.dirname(threading.__file__)) + if IS_PYPY: + # On PyPy 3.6 (7.3.1) it wrongly says that sysconfig.get_path('stdlib') is + # /lib-pypy when the installed version is /lib_pypy. + try: + import _pypy_wait + except ImportError: + pydev_log.debug("Unable to import _pypy_wait on PyPy when collecting default library roots.") + else: + pypy_lib_dir = os.path.dirname(_pypy_wait.__file__) + pydev_log.debug("Adding %s to default library roots.", pypy_lib_dir) + roots.append(pypy_lib_dir) + + if hasattr(site, 'getusersitepackages'): + site_paths = site.getusersitepackages() + if isinstance(site_paths, (list, tuple)): + for site_path in site_paths: + roots.append(site_path) + else: + roots.append(site_paths) + + if hasattr(site, 'getsitepackages'): + site_paths = site.getsitepackages() + if isinstance(site_paths, (list, tuple)): + for site_path in site_paths: + roots.append(site_path) + else: + roots.append(site_paths) + + for path in sys.path: + if os.path.exists(path) and os.path.basename(path) in ('site-packages', 'pip-global'): + roots.append(path) + + roots.extend([os.path.realpath(path) for path in roots]) + + return sorted(set(roots)) + + def _fix_roots(self, roots): + roots = _convert_to_str_and_clear_empty(roots) + new_roots = [] + for root in roots: + path = self._absolute_normalized_path(root) + if pydevd_constants.IS_WINDOWS: + new_roots.append(path + '\\') + else: + new_roots.append(path + '/') + return new_roots + + def _absolute_normalized_path(self, filename): + ''' + Provides a version of the filename that's absolute and normalized. + ''' + return normcase(pydevd_file_utils.absolute_path(filename)) + + def set_project_roots(self, project_roots): + self._project_roots = self._fix_roots(project_roots) + pydev_log.debug("IDE_PROJECT_ROOTS %s\n" % project_roots) + + def _get_project_roots(self): + return self._project_roots + + def set_library_roots(self, roots): + self._library_roots = self._fix_roots(roots) + pydev_log.debug("LIBRARY_ROOTS %s\n" % roots) + + def _get_library_roots(self): + return self._library_roots + + def in_project_roots(self, received_filename): + ''' + Note: don't call directly. Use PyDb.in_project_scope (there's no caching here and it doesn't + handle all possibilities for knowing whether a project is actually in the scope, it + just handles the heuristics based on the absolute_normalized_filename without the actual frame). + ''' + DEBUG = False + + if received_filename.startswith(USER_CODE_BASENAMES_STARTING_WITH): + if DEBUG: + pydev_log.debug('In in_project_roots - user basenames - starts with %s (%s)', received_filename, USER_CODE_BASENAMES_STARTING_WITH) + return True + + if received_filename.startswith(LIBRARY_CODE_BASENAMES_STARTING_WITH): + if DEBUG: + pydev_log.debug('Not in in_project_roots - library basenames - starts with %s (%s)', received_filename, LIBRARY_CODE_BASENAMES_STARTING_WITH) + return False + + project_roots = self._get_project_roots() # roots are absolute/normalized. + + absolute_normalized_filename = self._absolute_normalized_path(received_filename) + absolute_normalized_filename_as_dir = absolute_normalized_filename + ('\\' if IS_WINDOWS else '/') + + found_in_project = [] + for root in project_roots: + if root and (absolute_normalized_filename.startswith(root) or root == absolute_normalized_filename_as_dir): + if DEBUG: + pydev_log.debug('In project: %s (%s)', absolute_normalized_filename, root) + found_in_project.append(root) + + found_in_library = [] + library_roots = self._get_library_roots() + for root in library_roots: + if root and (absolute_normalized_filename.startswith(root) or root == absolute_normalized_filename_as_dir): + found_in_library.append(root) + if DEBUG: + pydev_log.debug('In library: %s (%s)', absolute_normalized_filename, root) + else: + if DEBUG: + pydev_log.debug('Not in library: %s (%s)', absolute_normalized_filename, root) + + if not project_roots: + # If we have no project roots configured, consider it being in the project + # roots if it's not found in site-packages (because we have defaults for those + # and not the other way around). + in_project = not found_in_library + if DEBUG: + pydev_log.debug('Final in project (no project roots): %s (%s)', absolute_normalized_filename, in_project) + + else: + in_project = False + if found_in_project: + if not found_in_library: + if DEBUG: + pydev_log.debug('Final in project (in_project and not found_in_library): %s (True)', absolute_normalized_filename) + in_project = True + else: + # Found in both, let's see which one has the bigger path matched. + if max(len(x) for x in found_in_project) > max(len(x) for x in found_in_library): + in_project = True + if DEBUG: + pydev_log.debug('Final in project (found in both): %s (%s)', absolute_normalized_filename, in_project) + + return in_project + + def use_libraries_filter(self): + ''' + Should we debug only what's inside project folders? + ''' + return self._use_libraries_filter + + def set_use_libraries_filter(self, use): + pydev_log.debug("pydevd: Use libraries filter: %s\n" % use) + self._use_libraries_filter = use + + def use_exclude_filters(self): + # Enabled if we have any filters registered. + return len(self._exclude_filters) > 0 + + def exclude_by_filter(self, absolute_filename, module_name): + ''' + :return: True if it should be excluded, False if it should be included and None + if no rule matched the given file. + ''' + for exclude_filter in self._exclude_filters: # : :type exclude_filter: ExcludeFilter + if exclude_filter.is_path: + if glob_matches_path(absolute_filename, exclude_filter.name): + return exclude_filter.exclude + else: + # Module filter. + if exclude_filter.name == module_name or module_name.startswith(exclude_filter.name + '.'): + return exclude_filter.exclude + return None + + def set_exclude_filters(self, exclude_filters): + ''' + :param list(ExcludeFilter) exclude_filters: + ''' + self._exclude_filters = exclude_filters + self.require_module = False + for exclude_filter in exclude_filters: + if not exclude_filter.is_path: + self.require_module = True + break diff --git a/_pydevd_bundle/pydevd_frame.py b/_pydevd_bundle/pydevd_frame.py new file mode 100644 index 0000000..81a3f6f --- /dev/null +++ b/_pydevd_bundle/pydevd_frame.py @@ -0,0 +1,1239 @@ +import linecache +import os.path +import re + +from _pydev_bundle import pydev_log +from _pydevd_bundle import pydevd_dont_trace +from _pydevd_bundle.pydevd_constants import (RETURN_VALUES_DICT, NO_FTRACE, + EXCEPTION_TYPE_HANDLED, EXCEPTION_TYPE_USER_UNHANDLED, PYDEVD_IPYTHON_CONTEXT) +from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace +from _pydevd_bundle.pydevd_utils import get_clsname_for_code +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame +from _pydevd_bundle.pydevd_comm_constants import constant_to_str, CMD_SET_FUNCTION_BREAK +try: + from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset +except ImportError: + + def get_smart_step_into_variant_from_frame_offset(*args, **kwargs): + return None + +# IFDEF CYTHON +# cython_inline_constant: CMD_STEP_INTO = 107 +# cython_inline_constant: CMD_STEP_INTO_MY_CODE = 144 +# cython_inline_constant: CMD_STEP_RETURN = 109 +# cython_inline_constant: CMD_STEP_RETURN_MY_CODE = 160 +# cython_inline_constant: CMD_STEP_OVER = 108 +# cython_inline_constant: CMD_STEP_OVER_MY_CODE = 159 +# cython_inline_constant: CMD_STEP_CAUGHT_EXCEPTION = 137 +# cython_inline_constant: CMD_SET_BREAK = 111 +# cython_inline_constant: CMD_SMART_STEP_INTO = 128 +# cython_inline_constant: CMD_STEP_INTO_COROUTINE = 206 +# cython_inline_constant: STATE_RUN = 1 +# cython_inline_constant: STATE_SUSPEND = 2 +# ELSE +# Note: those are now inlined on cython. +CMD_STEP_INTO = 107 +CMD_STEP_INTO_MY_CODE = 144 +CMD_STEP_RETURN = 109 +CMD_STEP_RETURN_MY_CODE = 160 +CMD_STEP_OVER = 108 +CMD_STEP_OVER_MY_CODE = 159 +CMD_STEP_CAUGHT_EXCEPTION = 137 +CMD_SET_BREAK = 111 +CMD_SMART_STEP_INTO = 128 +CMD_STEP_INTO_COROUTINE = 206 +STATE_RUN = 1 +STATE_SUSPEND = 2 +# ENDIF + +basename = os.path.basename + +IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') +DEBUG_START = ('pydevd.py', 'run') +DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile') +TRACE_PROPERTY = 'pydevd_traceproperty.py' + +import dis + +try: + StopAsyncIteration +except NameError: + StopAsyncIteration = StopIteration + + +# IFDEF CYTHON +# cdef is_unhandled_exception(container_obj, py_db, frame, int last_raise_line, set raise_lines): +# ELSE +def is_unhandled_exception(container_obj, py_db, frame, last_raise_line, raise_lines): +# ENDIF + if frame.f_lineno in raise_lines: + return True + + else: + try_except_infos = container_obj.try_except_infos + if try_except_infos is None: + container_obj.try_except_infos = try_except_infos = py_db.collect_try_except_info(frame.f_code) + + if not try_except_infos: + # Consider the last exception as unhandled because there's no try..except in it. + return True + else: + # Now, consider only the try..except for the raise + valid_try_except_infos = [] + for try_except_info in try_except_infos: + if try_except_info.is_line_in_try_block(last_raise_line): + valid_try_except_infos.append(try_except_info) + + if not valid_try_except_infos: + return True + + else: + # Note: check all, not only the "valid" ones to cover the case + # in "tests_python.test_tracing_on_top_level.raise_unhandled10" + # where one try..except is inside the other with only a raise + # and it's gotten in the except line. + for try_except_info in try_except_infos: + if try_except_info.is_line_in_except_block(frame.f_lineno): + if ( + frame.f_lineno == try_except_info.except_line or + frame.f_lineno in try_except_info.raise_lines_in_except + ): + # In a raise inside a try..except block or some except which doesn't + # match the raised exception. + return True + return False + + +# IFDEF CYTHON +# cdef class _TryExceptContainerObj: +# cdef public list try_except_infos; +# def __init__(self): +# self.try_except_infos = None +# ELSE +class _TryExceptContainerObj(object): + ''' + A dumb container object just to containe the try..except info when needed. Meant to be + persisent among multiple PyDBFrames to the same code object. + ''' + try_except_infos = None +# ENDIF + + +#======================================================================================================================= +# PyDBFrame +#======================================================================================================================= +# IFDEF CYTHON +# cdef class PyDBFrame: +# ELSE +class PyDBFrame: + '''This makes the tracing for a given frame, so, the trace_dispatch + is used initially when we enter into a new context ('call') and then + is reused for the entire context. + ''' +# ENDIF + + # Note: class (and not instance) attributes. + + # Same thing in the main debugger but only considering the file contents, while the one in the main debugger + # considers the user input (so, the actual result must be a join of both). + filename_to_lines_where_exceptions_are_ignored = {} + filename_to_stat_info = {} + + # IFDEF CYTHON + # cdef tuple _args + # cdef int should_skip + # cdef object exc_info + # def __init__(self, tuple args): + # self._args = args # In the cython version we don't need to pass the frame + # self.should_skip = -1 # On cythonized version, put in instance. + # self.exc_info = () + # ELSE + should_skip = -1 # Default value in class (put in instance on set). + exc_info = () # Default value in class (put in instance on set). + + def __init__(self, args): + # args = main_debugger, abs_path_canonical_path_and_base, base, info, t, frame + # yeap, much faster than putting in self and then getting it from self later on + self._args = args + # ENDIF + + def set_suspend(self, *args, **kwargs): + self._args[0].set_suspend(*args, **kwargs) + + def do_wait_suspend(self, *args, **kwargs): + self._args[0].do_wait_suspend(*args, **kwargs) + + # IFDEF CYTHON + # def trace_exception(self, frame, str event, arg): + # cdef bint should_stop; + # cdef tuple exc_info; + # ELSE + def trace_exception(self, frame, event, arg): + # ENDIF + if event == 'exception': + should_stop, frame = self._should_stop_on_exception(frame, event, arg) + + if should_stop: + if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + return self.trace_dispatch + + elif event == 'return': + exc_info = self.exc_info + if exc_info and arg is None: + frame_skips_cache, frame_cache_key = self._args[4], self._args[5] + custom_key = (frame_cache_key, 'try_exc_info') + container_obj = frame_skips_cache.get(custom_key) + if container_obj is None: + container_obj = frame_skips_cache[custom_key] = _TryExceptContainerObj() + if is_unhandled_exception(container_obj, self._args[0], frame, exc_info[1], exc_info[2]) and \ + self.handle_user_exception(frame): + return self.trace_dispatch + + return self.trace_exception + + # IFDEF CYTHON + # cdef _should_stop_on_exception(self, frame, str event, arg): + # cdef PyDBAdditionalThreadInfo info; + # cdef bint should_stop; + # cdef bint was_just_raised; + # cdef list check_excs; + # ELSE + def _should_stop_on_exception(self, frame, event, arg): + # ENDIF + + # main_debugger, _filename, info, _thread = self._args + main_debugger = self._args[0] + info = self._args[2] + should_stop = False + + # STATE_SUSPEND = 2 + if info.pydev_state != 2: # and breakpoint is not None: + exception, value, trace = arg + + if trace is not None and hasattr(trace, 'tb_next'): + # on jython trace is None on the first event and it may not have a tb_next. + + should_stop = False + exception_breakpoint = None + try: + if main_debugger.plugin is not None: + result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg) + if result: + should_stop, frame = result + except: + pydev_log.exception() + + if not should_stop: + # Apply checks that don't need the exception breakpoint (where we shouldn't ever stop). + if exception == SystemExit and main_debugger.ignore_system_exit_code(value): + pass + + elif exception in (GeneratorExit, StopIteration, StopAsyncIteration): + # These exceptions are control-flow related (they work as a generator + # pause), so, we shouldn't stop on them. + pass + + elif ignore_exception_trace(trace): + pass + + else: + was_just_raised = trace.tb_next is None + + # It was not handled by any plugin, lets check exception breakpoints. + check_excs = [] + + # Note: check user unhandled before regular exceptions. + exc_break_user = main_debugger.get_exception_breakpoint( + exception, main_debugger.break_on_user_uncaught_exceptions) + if exc_break_user is not None: + check_excs.append((exc_break_user, True)) + + exc_break_caught = main_debugger.get_exception_breakpoint( + exception, main_debugger.break_on_caught_exceptions) + if exc_break_caught is not None: + check_excs.append((exc_break_caught, False)) + + for exc_break, is_user_uncaught in check_excs: + # Initially mark that it should stop and then go into exclusions. + should_stop = True + + if main_debugger.exclude_exception_by_filter(exc_break, trace): + pydev_log.debug("Ignore exception %s in library %s -- (%s)" % (exception, frame.f_code.co_filename, frame.f_code.co_name)) + should_stop = False + + elif exc_break.condition is not None and \ + not main_debugger.handle_breakpoint_condition(info, exc_break, frame): + should_stop = False + + elif is_user_uncaught: + # Note: we don't stop here, we just collect the exc_info to use later on... + should_stop = False + if not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) \ + and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)): + # User uncaught means that we're currently in user code but the code + # up the stack is library code. + exc_info = self.exc_info + if not exc_info: + exc_info = (arg, frame.f_lineno, set([frame.f_lineno])) + else: + lines = exc_info[2] + lines.add(frame.f_lineno) + exc_info = (arg, frame.f_lineno, lines) + self.exc_info = exc_info + else: + # I.e.: these are only checked if we're not dealing with user uncaught exceptions. + if exc_break.notify_on_first_raise_only and main_debugger.skip_on_exceptions_thrown_in_same_context \ + and not was_just_raised and not just_raised(trace.tb_next): + # In this case we never stop if it was just raised, so, to know if it was the first we + # need to check if we're in the 2nd method. + should_stop = False # I.e.: we stop only when we're at the caller of a method that throws an exception + + elif exc_break.notify_on_first_raise_only and not main_debugger.skip_on_exceptions_thrown_in_same_context \ + and not was_just_raised: + should_stop = False # I.e.: we stop only when it was just raised + + elif was_just_raised and main_debugger.skip_on_exceptions_thrown_in_same_context: + # Option: Don't break if an exception is caught in the same function from which it is thrown + should_stop = False + + if should_stop: + exception_breakpoint = exc_break + try: + info.pydev_message = exc_break.qname + except: + info.pydev_message = exc_break.qname.encode('utf-8') + break + + if should_stop: + # Always add exception to frame (must remove later after we proceed). + add_exception_to_frame(frame, (exception, value, trace)) + + if exception_breakpoint is not None and exception_breakpoint.expression is not None: + main_debugger.handle_breakpoint_expression(exception_breakpoint, info, frame) + + return should_stop, frame + + def handle_user_exception(self, frame): + exc_info = self.exc_info + if exc_info: + return self._handle_exception(frame, 'exception', exc_info[0], EXCEPTION_TYPE_USER_UNHANDLED) + return False + + # IFDEF CYTHON + # cdef _handle_exception(self, frame, str event, arg, str exception_type): + # cdef bint stopped; + # cdef tuple abs_real_path_and_base; + # cdef str absolute_filename; + # cdef str canonical_normalized_filename; + # cdef dict filename_to_lines_where_exceptions_are_ignored; + # cdef dict lines_ignored; + # cdef dict frame_id_to_frame; + # cdef dict merged; + # cdef object trace_obj; + # cdef object main_debugger; + # ELSE + def _handle_exception(self, frame, event, arg, exception_type): + # ENDIF + stopped = False + try: + # print('_handle_exception', frame.f_lineno, frame.f_code.co_name) + + # We have 3 things in arg: exception type, description, traceback object + trace_obj = arg[2] + main_debugger = self._args[0] + + initial_trace_obj = trace_obj + if trace_obj.tb_next is None and trace_obj.tb_frame is frame: + # I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check). + pass + else: + # Get the trace_obj from where the exception was raised... + while trace_obj.tb_next is not None: + trace_obj = trace_obj.tb_next + + if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: + for check_trace_obj in (initial_trace_obj, trace_obj): + abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame) + absolute_filename = abs_real_path_and_base[0] + canonical_normalized_filename = abs_real_path_and_base[1] + + filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored + + lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + if lines_ignored is None: + lines_ignored = filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + + try: + curr_stat = os.stat(absolute_filename) + curr_stat = (curr_stat.st_size, curr_stat.st_mtime) + except: + curr_stat = None + + last_stat = self.filename_to_stat_info.get(absolute_filename) + if last_stat != curr_stat: + self.filename_to_stat_info[absolute_filename] = curr_stat + lines_ignored.clear() + try: + linecache.checkcache(absolute_filename) + except: + pydev_log.exception('Error in linecache.checkcache(%r)', absolute_filename) + + from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + if from_user_input: + merged = {} + merged.update(lines_ignored) + # Override what we have with the related entries that the user entered + merged.update(from_user_input) + else: + merged = lines_ignored + + exc_lineno = check_trace_obj.tb_lineno + + # print ('lines ignored', lines_ignored) + # print ('user input', from_user_input) + # print ('merged', merged, 'curr', exc_lineno) + + if exc_lineno not in merged: # Note: check on merged but update lines_ignored. + try: + line = linecache.getline(absolute_filename, exc_lineno, check_trace_obj.tb_frame.f_globals) + except: + pydev_log.exception('Error in linecache.getline(%r, %s, f_globals)', absolute_filename, exc_lineno) + line = '' + + if IGNORE_EXCEPTION_TAG.match(line) is not None: + lines_ignored[exc_lineno] = 1 + return False + else: + # Put in the cache saying not to ignore + lines_ignored[exc_lineno] = 0 + else: + # Ok, dict has it already cached, so, let's check it... + if merged.get(exc_lineno, 0): + return False + + thread = self._args[3] + + try: + frame_id_to_frame = {} + frame_id_to_frame[id(frame)] = frame + f = trace_obj.tb_frame + while f is not None: + frame_id_to_frame[id(f)] = f + f = f.f_back + f = None + + stopped = True + main_debugger.send_caught_exception_stack(thread, arg, id(frame)) + try: + self.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION) + self.do_wait_suspend(thread, frame, event, arg, exception_type=exception_type) + finally: + main_debugger.send_caught_exception_stack_proceeded(thread) + except: + pydev_log.exception() + + main_debugger.set_trace_for_frame_and_parents(frame) + finally: + # Make sure the user cannot see the '__exception__' we added after we leave the suspend state. + remove_exception_from_frame(frame) + # Clear some local variables... + frame = None + trace_obj = None + initial_trace_obj = None + check_trace_obj = None + f = None + frame_id_to_frame = None + main_debugger = None + thread = None + + return stopped + + # IFDEF CYTHON + # cdef get_func_name(self, frame): + # cdef str func_name + # ELSE + def get_func_name(self, frame): + # ENDIF + code_obj = frame.f_code + func_name = code_obj.co_name + try: + cls_name = get_clsname_for_code(code_obj, frame) + if cls_name is not None: + return "%s.%s" % (cls_name, func_name) + else: + return func_name + except: + pydev_log.exception() + return func_name + + # IFDEF CYTHON + # cdef _show_return_values(self, frame, arg): + # ELSE + def _show_return_values(self, frame, arg): + # ENDIF + try: + try: + f_locals_back = getattr(frame.f_back, "f_locals", None) + if f_locals_back is not None: + return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None) + if return_values_dict is None: + return_values_dict = {} + f_locals_back[RETURN_VALUES_DICT] = return_values_dict + name = self.get_func_name(frame) + return_values_dict[name] = arg + except: + pydev_log.exception() + finally: + f_locals_back = None + + # IFDEF CYTHON + # cdef _remove_return_values(self, main_debugger, frame): + # ELSE + def _remove_return_values(self, main_debugger, frame): + # ENDIF + try: + try: + # Showing return values was turned off, we should remove them from locals dict. + # The values can be in the current frame or in the back one + frame.f_locals.pop(RETURN_VALUES_DICT, None) + + f_locals_back = getattr(frame.f_back, "f_locals", None) + if f_locals_back is not None: + f_locals_back.pop(RETURN_VALUES_DICT, None) + except: + pydev_log.exception() + finally: + f_locals_back = None + + # IFDEF CYTHON + # cdef _get_unfiltered_back_frame(self, main_debugger, frame): + # ELSE + def _get_unfiltered_back_frame(self, main_debugger, frame): + # ENDIF + f = frame.f_back + while f is not None: + if not main_debugger.is_files_filter_enabled: + return f + + else: + if main_debugger.apply_files_filter(f, f.f_code.co_filename, False): + f = f.f_back + + else: + return f + + return f + + # IFDEF CYTHON + # cdef _is_same_frame(self, target_frame, current_frame): + # cdef PyDBAdditionalThreadInfo info; + # ELSE + def _is_same_frame(self, target_frame, current_frame): + # ENDIF + if target_frame is current_frame: + return True + + info = self._args[2] + if info.pydev_use_scoped_step_frame: + # If using scoped step we don't check the target, we just need to check + # if the current matches the same heuristic where the target was defined. + if target_frame is not None and current_frame is not None: + if target_frame.f_code.co_filename == current_frame.f_code.co_filename: + # The co_name may be different (it may include the line number), but + # the filename must still be the same. + f = current_frame.f_back + if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + f = f.f_back + if f is not None and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + return True + + return False + + # IFDEF CYTHON + # cpdef trace_dispatch(self, frame, str event, arg): + # cdef tuple abs_path_canonical_path_and_base; + # cdef bint is_exception_event; + # cdef bint has_exception_breakpoints; + # cdef bint can_skip; + # cdef bint stop; + # cdef PyDBAdditionalThreadInfo info; + # cdef int step_cmd; + # cdef int line; + # cdef bint is_line; + # cdef bint is_call; + # cdef bint is_return; + # cdef bint should_stop; + # cdef dict breakpoints_for_file; + # cdef dict stop_info; + # cdef str curr_func_name; + # cdef bint exist_result; + # cdef dict frame_skips_cache; + # cdef object frame_cache_key; + # cdef tuple line_cache_key; + # cdef int breakpoints_in_line_cache; + # cdef int breakpoints_in_frame_cache; + # cdef bint has_breakpoint_in_frame; + # cdef bint is_coroutine_or_generator; + # cdef int bp_line; + # cdef object bp; + # cdef int pydev_smart_parent_offset + # cdef int pydev_smart_child_offset + # cdef tuple pydev_smart_step_into_variants + # ELSE + def trace_dispatch(self, frame, event, arg): + # ENDIF + # Note: this is a big function because most of the logic related to hitting a breakpoint and + # stepping is contained in it. Ideally this could be split among multiple functions, but the + # problem in this case is that in pure-python function calls are expensive and even more so + # when tracing is on (because each function call will get an additional tracing call). We + # try to address this by using the info.is_tracing for the fastest possible return, but the + # cost is still high (maybe we could use code-generation in the future and make the code + # generation be better split among what each part does). + + # DEBUG = '_debugger_case_generator.py' in frame.f_code.co_filename + main_debugger, abs_path_canonical_path_and_base, info, thread, frame_skips_cache, frame_cache_key = self._args + # if DEBUG: print('frame trace_dispatch %s %s %s %s %s %s, stop: %s' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event, constant_to_str(info.pydev_step_cmd), arg, info.pydev_step_stop)) + try: + info.is_tracing += 1 + + # TODO: This shouldn't be needed. The fact that frame.f_lineno + # is None seems like a bug in Python 3.11. + # Reported in: https://github.com/python/cpython/issues/94485 + line = frame.f_lineno or 0 # Workaround or case where frame.f_lineno is None + line_cache_key = (frame_cache_key, line) + + if main_debugger.pydb_disposed: + return None if event == 'call' else NO_FTRACE + + plugin_manager = main_debugger.plugin + has_exception_breakpoints = ( + main_debugger.break_on_caught_exceptions + or main_debugger.break_on_user_uncaught_exceptions + or main_debugger.has_plugin_exception_breaks) + + stop_frame = info.pydev_step_stop + step_cmd = info.pydev_step_cmd + function_breakpoint_on_call_event = None + + if frame.f_code.co_flags & 0xa0: # 0xa0 == CO_GENERATOR = 0x20 | CO_COROUTINE = 0x80 + # Dealing with coroutines and generators: + # When in a coroutine we change the perceived event to the debugger because + # a call, StopIteration exception and return are usually just pausing/unpausing it. + if event == 'line': + is_line = True + is_call = False + is_return = False + is_exception_event = False + + elif event == 'return': + is_line = False + is_call = False + is_return = True + is_exception_event = False + + returns_cache_key = (frame_cache_key, 'returns') + return_lines = frame_skips_cache.get(returns_cache_key) + if return_lines is None: + # Note: we're collecting the return lines by inspecting the bytecode as + # there are multiple returns and multiple stop iterations when awaiting and + # it doesn't give any clear indication when a coroutine or generator is + # finishing or just pausing. + return_lines = set() + for x in main_debugger.collect_return_info(frame.f_code): + # Note: cython does not support closures in cpdefs (so we can't use + # a list comprehension). + return_lines.add(x.return_line) + + frame_skips_cache[returns_cache_key] = return_lines + + if line not in return_lines: + # Not really a return (coroutine/generator paused). + return self.trace_dispatch + else: + if self.exc_info: + self.handle_user_exception(frame) + return self.trace_dispatch + + # Tricky handling: usually when we're on a frame which is about to exit + # we set the step mode to step into, but in this case we'd end up in the + # asyncio internal machinery, which is not what we want, so, we just + # ask the stop frame to be a level up. + # + # Note that there's an issue here which we may want to fix in the future: if + # the back frame is a frame which is filtered, we won't stop properly. + # Solving this may not be trivial as we'd need to put a scope in the step + # in, but we may have to do it anyways to have a step in which doesn't end + # up in asyncio). + # + # Note2: we don't revert to a step in if we're doing scoped stepping + # (because on scoped stepping we're always receiving a call/line/return + # event for each line in ipython, so, we can't revert to step in on return + # as the return shouldn't mean that we've actually completed executing a + # frame in this case). + if stop_frame is frame and not info.pydev_use_scoped_step_frame: + if step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE, CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE): + f = self._get_unfiltered_back_frame(main_debugger, frame) + if f is not None: + info.pydev_step_cmd = CMD_STEP_INTO_COROUTINE + info.pydev_step_stop = f + else: + if step_cmd == CMD_STEP_OVER: + info.pydev_step_cmd = CMD_STEP_INTO + info.pydev_step_stop = None + + elif step_cmd == CMD_STEP_OVER_MY_CODE: + info.pydev_step_cmd = CMD_STEP_INTO_MY_CODE + info.pydev_step_stop = None + + elif step_cmd == CMD_STEP_INTO_COROUTINE: + # We're exiting this one, so, mark the new coroutine context. + f = self._get_unfiltered_back_frame(main_debugger, frame) + if f is not None: + info.pydev_step_stop = f + else: + info.pydev_step_cmd = CMD_STEP_INTO + info.pydev_step_stop = None + + elif event == 'exception': + breakpoints_for_file = None + if has_exception_breakpoints: + should_stop, frame = self._should_stop_on_exception(frame, event, arg) + if should_stop: + if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + return self.trace_dispatch + + return self.trace_dispatch + else: + # event == 'call' or event == 'c_XXX' + return self.trace_dispatch + + else: # Not coroutine nor generator + if event == 'line': + is_line = True + is_call = False + is_return = False + is_exception_event = False + + elif event == 'return': + is_line = False + is_return = True + is_call = False + is_exception_event = False + + # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break + # eventually. Force the step mode to step into and the step stop frame to None. + # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user + # to make a step in or step over at that location). + # Note: this is especially troublesome when we're skipping code with the + # @DontTrace comment. + if ( + stop_frame is frame and + not info.pydev_use_scoped_step_frame and is_return and + step_cmd in (CMD_STEP_OVER, CMD_STEP_RETURN, CMD_STEP_OVER_MY_CODE, CMD_STEP_RETURN_MY_CODE, CMD_SMART_STEP_INTO) + ): + + if step_cmd in (CMD_STEP_OVER, CMD_STEP_RETURN, CMD_SMART_STEP_INTO): + info.pydev_step_cmd = CMD_STEP_INTO + else: + info.pydev_step_cmd = CMD_STEP_INTO_MY_CODE + info.pydev_step_stop = None + + if self.exc_info: + if self.handle_user_exception(frame): + return self.trace_dispatch + + elif event == 'call': + is_line = False + is_call = True + is_return = False + is_exception_event = False + if frame.f_code.co_firstlineno == frame.f_lineno: # Check line to deal with async/await. + function_breakpoint_on_call_event = main_debugger.function_breakpoint_name_to_breakpoint.get(frame.f_code.co_name) + + elif event == 'exception': + is_exception_event = True + breakpoints_for_file = None + if has_exception_breakpoints: + should_stop, frame = self._should_stop_on_exception(frame, event, arg) + if should_stop: + if self._handle_exception(frame, event, arg, EXCEPTION_TYPE_HANDLED): + return self.trace_dispatch + is_line = False + is_return = False + is_call = False + + else: + # Unexpected: just keep the same trace func (i.e.: event == 'c_XXX'). + return self.trace_dispatch + + if not is_exception_event: + breakpoints_for_file = main_debugger.breakpoints.get(abs_path_canonical_path_and_base[1]) + + can_skip = False + + if info.pydev_state == 1: # STATE_RUN = 1 + # we can skip if: + # - we have no stop marked + # - we should make a step return/step over and we're not in the current frame + # - we're stepping into a coroutine context and we're not in that context + if step_cmd == -1: + can_skip = True + + elif step_cmd in (CMD_STEP_OVER, CMD_STEP_RETURN, CMD_STEP_OVER_MY_CODE, CMD_STEP_RETURN_MY_CODE) and not self._is_same_frame(stop_frame, frame): + can_skip = True + + elif step_cmd == CMD_SMART_STEP_INTO and ( + stop_frame is not None and + stop_frame is not frame and + stop_frame is not frame.f_back and + (frame.f_back is None or stop_frame is not frame.f_back.f_back)): + can_skip = True + + elif step_cmd == CMD_STEP_INTO_MY_CODE: + if ( + main_debugger.apply_files_filter(frame, frame.f_code.co_filename, True) + and (frame.f_back is None or main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True)) + ): + can_skip = True + + elif step_cmd == CMD_STEP_INTO_COROUTINE: + f = frame + while f is not None: + if self._is_same_frame(stop_frame, f): + break + f = f.f_back + else: + can_skip = True + + if can_skip: + if plugin_manager is not None and ( + main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks): + can_skip = plugin_manager.can_skip(main_debugger, frame) + + if can_skip and main_debugger.show_return_values and info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and self._is_same_frame(stop_frame, frame.f_back): + # trace function for showing return values after step over + can_skip = False + + # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint, + # we will return nothing for the next trace + # also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway, + # so, that's why the additional checks are there. + + if function_breakpoint_on_call_event: + pass # Do nothing here (just keep on going as we can't skip it). + + elif not breakpoints_for_file: + if can_skip: + if has_exception_breakpoints: + return self.trace_exception + else: + return None if is_call else NO_FTRACE + + else: + # When cached, 0 means we don't have a breakpoint and 1 means we have. + if can_skip: + breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1) + if breakpoints_in_line_cache == 0: + return self.trace_dispatch + + breakpoints_in_frame_cache = frame_skips_cache.get(frame_cache_key, -1) + if breakpoints_in_frame_cache != -1: + # Gotten from cache. + has_breakpoint_in_frame = breakpoints_in_frame_cache == 1 + + else: + has_breakpoint_in_frame = False + + try: + func_lines = set() + for offset_and_lineno in dis.findlinestarts(frame.f_code): + func_lines.add(offset_and_lineno[1]) + except: + # This is a fallback for implementations where we can't get the function + # lines -- i.e.: jython (in this case clients need to provide the function + # name to decide on the skip or we won't be able to skip the function + # completely). + + # Checks the breakpoint to see if there is a context match in some function. + curr_func_name = frame.f_code.co_name + + # global context is set with an empty name + if curr_func_name in ('?', '', ''): + curr_func_name = '' + + for bp in breakpoints_for_file.values(): + # will match either global or some function + if bp.func_name in ('None', curr_func_name): + has_breakpoint_in_frame = True + break + else: + for bp_line in breakpoints_for_file: # iterate on keys + if bp_line in func_lines: + has_breakpoint_in_frame = True + break + + # Cache the value (1 or 0 or -1 for default because of cython). + if has_breakpoint_in_frame: + frame_skips_cache[frame_cache_key] = 1 + else: + frame_skips_cache[frame_cache_key] = 0 + + if can_skip and not has_breakpoint_in_frame: + if has_exception_breakpoints: + return self.trace_exception + else: + return None if is_call else NO_FTRACE + + # We may have hit a breakpoint or we are already in step mode. Either way, let's check what we should do in this frame + # if DEBUG: print('NOT skipped: %s %s %s %s' % (frame.f_lineno, frame.f_code.co_name, event, frame.__class__.__name__)) + + try: + flag = False + # return is not taken into account for breakpoint hit because we'd have a double-hit in this case + # (one for the line and the other for the return). + + stop_info = {} + breakpoint = None + exist_result = False + stop = False + stop_reason = CMD_SET_BREAK + bp_type = None + + if function_breakpoint_on_call_event: + breakpoint = function_breakpoint_on_call_event + stop = True + new_frame = frame + stop_reason = CMD_SET_FUNCTION_BREAK + + elif is_line and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None and line in breakpoints_for_file: + breakpoint = breakpoints_for_file[line] + new_frame = frame + stop = True + if step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and (self._is_same_frame(stop_frame, frame) and is_line): + stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) + elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: + result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) + if result: + exist_result = True + flag, breakpoint, new_frame, bp_type = result + + if breakpoint: + # ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint + # lets do the conditional stuff here + if breakpoint.expression is not None: + main_debugger.handle_breakpoint_expression(breakpoint, info, new_frame) + if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0: + cmd = main_debugger.cmd_factory.make_io_message(info.pydev_message + os.linesep, '1') + main_debugger.writer.add_command(cmd) + + if stop or exist_result: + eval_result = False + if breakpoint.has_condition: + eval_result = main_debugger.handle_breakpoint_condition(info, breakpoint, new_frame) + + if breakpoint.has_condition: + if not eval_result: + stop = False + elif breakpoint.is_logpoint: + stop = False + + if is_call and (frame.f_code.co_name in ('', '') or (line == 1 and frame.f_code.co_name.startswith(' may be executed having each line compiled as a new + # module, so it's the same case as . + + return self.trace_dispatch + + if main_debugger.show_return_values: + if is_return and ( + (info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE, CMD_SMART_STEP_INTO) and (self._is_same_frame(stop_frame, frame.f_back))) or + (info.pydev_step_cmd in (CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE) and (self._is_same_frame(stop_frame, frame))) or + (info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_COROUTINE)) or + ( + info.pydev_step_cmd == CMD_STEP_INTO_MY_CODE + and frame.f_back is not None + and not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, True) + ) + ): + self._show_return_values(frame, arg) + + elif main_debugger.remove_return_values_flag: + try: + self._remove_return_values(main_debugger, frame) + finally: + main_debugger.remove_return_values_flag = False + + if stop: + self.set_suspend( + thread, + stop_reason, + suspend_other_threads=breakpoint and breakpoint.suspend_policy == "ALL", + ) + + elif flag and plugin_manager is not None: + result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) + if result: + frame = result + + # if thread has a suspend flag, we suspend with a busy wait + if info.pydev_state == STATE_SUSPEND: + self.do_wait_suspend(thread, frame, event, arg) + return self.trace_dispatch + else: + if not breakpoint and is_line: + # No stop from anyone and no breakpoint found in line (cache that). + frame_skips_cache[line_cache_key] = 0 + + except: + pydev_log.exception() + raise + + # step handling. We stop when we hit the right frame + try: + should_skip = 0 + if pydevd_dont_trace.should_trace_hook is not None: + if self.should_skip == -1: + # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). + # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code + # Which will be handled by this frame is read-only, so, we can cache it safely. + if not pydevd_dont_trace.should_trace_hook(frame, abs_path_canonical_path_and_base[0]): + # -1, 0, 1 to be Cython-friendly + should_skip = self.should_skip = 1 + else: + should_skip = self.should_skip = 0 + else: + should_skip = self.should_skip + + plugin_stop = False + if should_skip: + stop = False + + elif step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE): + force_check_project_scope = step_cmd == CMD_STEP_INTO_MY_CODE + if is_line: + if not info.pydev_use_scoped_step_frame: + if force_check_project_scope or main_debugger.is_files_filter_enabled: + stop = not main_debugger.apply_files_filter(frame, frame.f_code.co_filename, force_check_project_scope) + else: + stop = True + else: + # We can only stop inside the ipython call. + filename = frame.f_code.co_filename + if filename.endswith('.pyc'): + filename = filename[:-1] + + if not filename.endswith(PYDEVD_IPYTHON_CONTEXT[0]): + f = frame.f_back + while f is not None: + if f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + f2 = f.f_back + if f2 is not None and f2.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + pydev_log.debug('Stop inside ipython call') + stop = True + break + f = f.f_back + + del f + + if not stop: + # In scoped mode if step in didn't work in this context it won't work + # afterwards anyways. + return None if is_call else NO_FTRACE + + elif is_return and frame.f_back is not None and not info.pydev_use_scoped_step_frame: + if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + stop = False + else: + if force_check_project_scope or main_debugger.is_files_filter_enabled: + stop = not main_debugger.apply_files_filter(frame.f_back, frame.f_back.f_code.co_filename, force_check_project_scope) + if stop: + # Prevent stopping in a return to the same location we were initially + # (i.e.: double-stop at the same place due to some filtering). + if info.step_in_initial_location == (frame.f_back, frame.f_back.f_lineno): + stop = False + else: + stop = True + else: + stop = False + + if stop: + if step_cmd == CMD_STEP_INTO_COROUTINE: + # i.e.: Check if we're stepping into the proper context. + f = frame + while f is not None: + if self._is_same_frame(stop_frame, f): + break + f = f.f_back + else: + stop = False + + if plugin_manager is not None: + result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) + if result: + stop, plugin_stop = result + + elif step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE): + # Note: when dealing with a step over my code it's the same as a step over (the + # difference is that when we return from a frame in one we go to regular step + # into and in the other we go to a step into my code). + stop = self._is_same_frame(stop_frame, frame) and is_line + # Note: don't stop on a return for step over, only for line events + # i.e.: don't stop in: (stop_frame is frame.f_back and is_return) as we'd stop twice in that line. + + if plugin_manager is not None: + result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) + if result: + stop, plugin_stop = result + + elif step_cmd == CMD_SMART_STEP_INTO: + stop = False + back = frame.f_back + if self._is_same_frame(stop_frame, frame) and is_return: + # We're exiting the smart step into initial frame (so, we probably didn't find our target). + stop = True + + elif self._is_same_frame(stop_frame, back) and is_line: + if info.pydev_smart_child_offset != -1: + # i.e.: in this case, we're not interested in the pause in the parent, rather + # we're interested in the pause in the child (when the parent is at the proper place). + stop = False + + else: + pydev_smart_parent_offset = info.pydev_smart_parent_offset + + pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: + # Preferred mode (when the smart step into variants are available + # and the offset is set). + stop = get_smart_step_into_variant_from_frame_offset(back.f_lasti, pydev_smart_step_into_variants) is \ + get_smart_step_into_variant_from_frame_offset(pydev_smart_parent_offset, pydev_smart_step_into_variants) + + else: + # Only the name/line is available, so, check that. + curr_func_name = frame.f_code.co_name + + # global context is set with an empty name + if curr_func_name in ('?', '') or curr_func_name is None: + curr_func_name = '' + if curr_func_name == info.pydev_func_name and stop_frame.f_lineno == info.pydev_next_line: + stop = True + + if not stop: + # In smart step into, if we didn't hit it in this frame once, that'll + # not be the case next time either, so, disable tracing for this frame. + return None if is_call else NO_FTRACE + + elif back is not None and self._is_same_frame(stop_frame, back.f_back) and is_line: + # Ok, we have to track 2 stops at this point, the parent and the child offset. + # This happens when handling a step into which targets a function inside a list comprehension + # or generator (in which case an intermediary frame is created due to an internal function call). + pydev_smart_parent_offset = info.pydev_smart_parent_offset + pydev_smart_child_offset = info.pydev_smart_child_offset + # print('matched back frame', pydev_smart_parent_offset, pydev_smart_child_offset) + # print('parent f_lasti', back.f_back.f_lasti) + # print('child f_lasti', back.f_lasti) + stop = False + if pydev_smart_child_offset >= 0 and pydev_smart_child_offset >= 0: + pydev_smart_step_into_variants = info.pydev_smart_step_into_variants + + if pydev_smart_parent_offset >= 0 and pydev_smart_step_into_variants: + # Note that we don't really check the parent offset, only the offset of + # the child (because this is a generator, the parent may have moved forward + # already -- and that's ok, so, we just check that the parent frame + # matches in this case). + smart_step_into_variant = get_smart_step_into_variant_from_frame_offset(pydev_smart_parent_offset, pydev_smart_step_into_variants) + # print('matched parent offset', pydev_smart_parent_offset) + # Ok, now, check the child variant + children_variants = smart_step_into_variant.children_variants + stop = children_variants and ( + get_smart_step_into_variant_from_frame_offset(back.f_lasti, children_variants) is \ + get_smart_step_into_variant_from_frame_offset(pydev_smart_child_offset, children_variants) + ) + # print('stop at child', stop) + + if not stop: + # In smart step into, if we didn't hit it in this frame once, that'll + # not be the case next time either, so, disable tracing for this frame. + return None if is_call else NO_FTRACE + + elif step_cmd in (CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE): + stop = is_return and self._is_same_frame(stop_frame, frame) + + else: + stop = False + + if stop and step_cmd != -1 and is_return and hasattr(frame, "f_back"): + f_code = getattr(frame.f_back, 'f_code', None) + if f_code is not None: + if main_debugger.get_file_type(frame.f_back) == main_debugger.PYDEV_FILE: + stop = False + + if plugin_stop: + stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) + elif stop: + if is_line: + self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + self.do_wait_suspend(thread, frame, event, arg) + elif is_return: # return event + back = frame.f_back + if back is not None: + # When we get to the pydevd run function, the debugging has actually finished for the main thread + # (note that it can still go on for other threads, but for this one, we just make it finish) + # So, just setting it to None should be OK + back_absolute_filename, _, base = get_abs_path_real_path_and_base_from_frame(back) + if (base, back.f_code.co_name) in (DEBUG_START, DEBUG_START_PY3K): + back = None + + elif base == TRACE_PROPERTY: + # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging) + # if we're in a return, we want it to appear to the user in the previous frame! + return None if is_call else NO_FTRACE + + elif pydevd_dont_trace.should_trace_hook is not None: + if not pydevd_dont_trace.should_trace_hook(back, back_absolute_filename): + # In this case, we'll have to skip the previous one because it shouldn't be traced. + # Also, we have to reset the tracing, because if the parent's parent (or some + # other parent) has to be traced and it's not currently, we wouldn't stop where + # we should anymore (so, a step in/over/return may not stop anywhere if no parent is traced). + # Related test: _debugger_case17a.py + main_debugger.set_trace_for_frame_and_parents(back) + return None if is_call else NO_FTRACE + + if back is not None: + # if we're in a return, we want it to appear to the user in the previous frame! + self.set_suspend(thread, step_cmd, original_step_cmd=info.pydev_original_step_cmd) + self.do_wait_suspend(thread, back, event, arg) + else: + # in jython we may not have a back frame + info.pydev_step_stop = None + info.pydev_original_step_cmd = -1 + info.pydev_step_cmd = -1 + info.pydev_state = STATE_RUN + + except KeyboardInterrupt: + raise + except: + try: + pydev_log.exception() + info.pydev_original_step_cmd = -1 + info.pydev_step_cmd = -1 + info.pydev_step_stop = None + except: + return None if is_call else NO_FTRACE + + # if we are quitting, let's stop the tracing + if main_debugger.quitting: + return None if is_call else NO_FTRACE + + return self.trace_dispatch + finally: + info.is_tracing -= 1 + + # end trace_dispatch diff --git a/_pydevd_bundle/pydevd_frame_utils.py b/_pydevd_bundle/pydevd_frame_utils.py new file mode 100644 index 0000000..c34ed30 --- /dev/null +++ b/_pydevd_bundle/pydevd_frame_utils.py @@ -0,0 +1,302 @@ +from _pydevd_bundle.pydevd_constants import EXCEPTION_TYPE_USER_UNHANDLED, EXCEPTION_TYPE_UNHANDLED +from _pydev_bundle import pydev_log + + +class Frame(object): + + def __init__( + self, + f_back, + f_fileno, + f_code, + f_locals, + f_globals=None, + f_trace=None): + self.f_back = f_back + self.f_lineno = f_fileno + self.f_code = f_code + self.f_locals = f_locals + self.f_globals = f_globals + self.f_trace = f_trace + + if self.f_globals is None: + self.f_globals = {} + + +class FCode(object): + + def __init__(self, name, filename): + self.co_name = name + self.co_filename = filename + self.co_firstlineno = 1 + self.co_flags = 0 + + +def add_exception_to_frame(frame, exception_info): + frame.f_locals['__exception__'] = exception_info + + +def remove_exception_from_frame(frame): + frame.f_locals.pop('__exception__', None) + + +FILES_WITH_IMPORT_HOOKS = ['pydev_monkey_qt.py', 'pydev_import_hook.py'] + + +def just_raised(trace): + if trace is None: + return False + return trace.tb_next is None + + +def ignore_exception_trace(trace): + while trace is not None: + filename = trace.tb_frame.f_code.co_filename + if filename in ( + '', ''): + # Do not stop on inner exceptions in py3 while importing + return True + + # ImportError should appear in a user's code, not inside debugger + for file in FILES_WITH_IMPORT_HOOKS: + if filename.endswith(file): + return True + + trace = trace.tb_next + + return False + + +def cached_call(obj, func, *args): + cached_name = '_cached_' + func.__name__ + if not hasattr(obj, cached_name): + setattr(obj, cached_name, func(*args)) + + return getattr(obj, cached_name) + + +class FramesList(object): + + def __init__(self): + self._frames = [] + + # If available, the line number for the frame will be gotten from this dict, + # otherwise frame.f_lineno will be used (needed for unhandled exceptions as + # the place where we report may be different from the place where it's raised). + self.frame_id_to_lineno = {} + + self.exc_type = None + self.exc_desc = None + self.trace_obj = None + + # This may be set to set the current frame (for the case where we have + # an unhandled exception where we want to show the root bu we have a different + # executing frame). + self.current_frame = None + + # This is to know whether an exception was extracted from a __cause__ or __context__. + self.exc_context_msg = '' + + def append(self, frame): + self._frames.append(frame) + + def last_frame(self): + return self._frames[-1] + + def __len__(self): + return len(self._frames) + + def __iter__(self): + return iter(self._frames) + + def __repr__(self): + lst = ['FramesList('] + + lst.append('\n exc_type: ') + lst.append(str(self.exc_type)) + + lst.append('\n exc_desc: ') + lst.append(str(self.exc_desc)) + + lst.append('\n trace_obj: ') + lst.append(str(self.trace_obj)) + + lst.append('\n current_frame: ') + lst.append(str(self.current_frame)) + + for frame in self._frames: + lst.append('\n ') + lst.append(repr(frame)) + lst.append(',') + lst.append('\n)') + return ''.join(lst) + + __str__ = __repr__ + + +class _DummyFrameWrapper(object): + + def __init__(self, frame, f_lineno, f_back): + self._base_frame = frame + self.f_lineno = f_lineno + self.f_back = f_back + self.f_trace = None + original_code = frame.f_code + self.f_code = FCode(original_code.co_name , original_code.co_filename) + + @property + def f_locals(self): + return self._base_frame.f_locals + + @property + def f_globals(self): + return self._base_frame.f_globals + + +_cause_message = ( + "\nThe above exception was the direct cause " + "of the following exception:\n\n") + +_context_message = ( + "\nDuring handling of the above exception, " + "another exception occurred:\n\n") + + +def create_frames_list_from_exception_cause(trace_obj, frame, exc_type, exc_desc, memo): + lst = [] + msg = '' + try: + exc_cause = getattr(exc_desc, '__cause__', None) + msg = _cause_message + except Exception: + exc_cause = None + + if exc_cause is None: + try: + exc_cause = getattr(exc_desc, '__context__', None) + msg = _context_message + except Exception: + exc_cause = None + + if exc_cause is None or id(exc_cause) in memo: + return None + + # The traceback module does this, so, let's play safe here too... + memo.add(id(exc_cause)) + + tb = exc_cause.__traceback__ + frames_list = FramesList() + frames_list.exc_type = type(exc_cause) + frames_list.exc_desc = exc_cause + frames_list.trace_obj = tb + frames_list.exc_context_msg = msg + + while tb is not None: + # Note: we don't use the actual tb.tb_frame because if the cause of the exception + # uses the same frame object, the id(frame) would be the same and the frame_id_to_lineno + # would be wrong as the same frame needs to appear with 2 different lines. + lst.append((_DummyFrameWrapper(tb.tb_frame, tb.tb_lineno, None), tb.tb_lineno)) + tb = tb.tb_next + + for tb_frame, tb_lineno in lst: + frames_list.append(tb_frame) + frames_list.frame_id_to_lineno[id(tb_frame)] = tb_lineno + + return frames_list + + +def create_frames_list_from_traceback(trace_obj, frame, exc_type, exc_desc, exception_type=None): + ''' + :param trace_obj: + This is the traceback from which the list should be created. + + :param frame: + This is the first frame to be considered (i.e.: topmost frame). If None is passed, all + the frames from the traceback are shown (so, None should be passed for unhandled exceptions). + + :param exception_type: + If this is an unhandled exception or user unhandled exception, we'll not trim the stack to create from the passed + frame, rather, we'll just mark the frame in the frames list. + ''' + lst = [] + + tb = trace_obj + if tb is not None and tb.tb_frame is not None: + f = tb.tb_frame.f_back + while f is not None: + lst.insert(0, (f, f.f_lineno)) + f = f.f_back + + while tb is not None: + lst.append((tb.tb_frame, tb.tb_lineno)) + tb = tb.tb_next + + curr = exc_desc + memo = set() + while True: + initial = curr + try: + curr = getattr(initial, '__cause__', None) + except Exception: + curr = None + + if curr is None: + try: + curr = getattr(initial, '__context__', None) + except Exception: + curr = None + + if curr is None or id(curr) in memo: + break + + # The traceback module does this, so, let's play safe here too... + memo.add(id(curr)) + + tb = getattr(curr, '__traceback__', None) + + while tb is not None: + # Note: we don't use the actual tb.tb_frame because if the cause of the exception + # uses the same frame object, the id(frame) would be the same and the frame_id_to_lineno + # would be wrong as the same frame needs to appear with 2 different lines. + lst.append((_DummyFrameWrapper(tb.tb_frame, tb.tb_lineno, None), tb.tb_lineno)) + tb = tb.tb_next + + frames_list = None + + for tb_frame, tb_lineno in reversed(lst): + if frames_list is None and ( + (frame is tb_frame) or + (frame is None) or + (exception_type == EXCEPTION_TYPE_USER_UNHANDLED) + ): + frames_list = FramesList() + + if frames_list is not None: + frames_list.append(tb_frame) + frames_list.frame_id_to_lineno[id(tb_frame)] = tb_lineno + + if frames_list is None and frame is not None: + # Fallback (shouldn't happen in practice). + pydev_log.info('create_frames_list_from_traceback did not find topmost frame in list.') + frames_list = create_frames_list_from_frame(frame) + + frames_list.exc_type = exc_type + frames_list.exc_desc = exc_desc + frames_list.trace_obj = trace_obj + + if exception_type == EXCEPTION_TYPE_USER_UNHANDLED: + frames_list.current_frame = frame + elif exception_type == EXCEPTION_TYPE_UNHANDLED: + if len(frames_list) > 0: + frames_list.current_frame = frames_list.last_frame() + + return frames_list + + +def create_frames_list_from_frame(frame): + lst = FramesList() + while frame is not None: + lst.append(frame) + frame = frame.f_back + + return lst diff --git a/_pydevd_bundle/pydevd_gevent_integration.py b/_pydevd_bundle/pydevd_gevent_integration.py new file mode 100644 index 0000000..ca404ba --- /dev/null +++ b/_pydevd_bundle/pydevd_gevent_integration.py @@ -0,0 +1,93 @@ +import pydevd_tracing +import greenlet +import gevent +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle.pydevd_custom_frames import add_custom_frame, update_custom_frame, remove_custom_frame +from _pydevd_bundle.pydevd_constants import GEVENT_SHOW_PAUSED_GREENLETS, get_global_debugger, \ + thread_get_ident +from _pydev_bundle import pydev_log +from pydevd_file_utils import basename + +_saved_greenlets_to_custom_frame_thread_id = {} + +if GEVENT_SHOW_PAUSED_GREENLETS: + + def _get_paused_name(py_db, g): + frame = g.gr_frame + use_frame = frame + + # i.e.: Show in the description of the greenlet the last user-code found. + while use_frame is not None: + if py_db.apply_files_filter(use_frame, use_frame.f_code.co_filename, True): + frame = use_frame + use_frame = use_frame.f_back + else: + break + + if use_frame is None: + use_frame = frame + + return '%s: %s - %s' % (type(g).__name__, use_frame.f_code.co_name, basename(use_frame.f_code.co_filename)) + + def greenlet_events(event, args): + if event in ('switch', 'throw'): + py_db = get_global_debugger() + origin, target = args + + if not origin.dead and origin.gr_frame is not None: + frame_custom_thread_id = _saved_greenlets_to_custom_frame_thread_id.get(origin) + if frame_custom_thread_id is None: + _saved_greenlets_to_custom_frame_thread_id[origin] = add_custom_frame( + origin.gr_frame, _get_paused_name(py_db, origin), thread_get_ident()) + else: + update_custom_frame( + frame_custom_thread_id, origin.gr_frame, _get_paused_name(py_db, origin), thread_get_ident()) + else: + frame_custom_thread_id = _saved_greenlets_to_custom_frame_thread_id.pop(origin, None) + if frame_custom_thread_id is not None: + remove_custom_frame(frame_custom_thread_id) + + # This one will be resumed, so, remove custom frame from it. + frame_custom_thread_id = _saved_greenlets_to_custom_frame_thread_id.pop(target, None) + if frame_custom_thread_id is not None: + remove_custom_frame(frame_custom_thread_id) + + # The tracing needs to be reapplied for each greenlet as gevent + # clears the tracing set through sys.settrace for each greenlet. + pydevd_tracing.reapply_settrace() + +else: + + # i.e.: no logic related to showing paused greenlets is needed. + def greenlet_events(event, args): + pydevd_tracing.reapply_settrace() + + +def enable_gevent_integration(): + # References: + # https://greenlet.readthedocs.io/en/latest/api.html#greenlet.settrace + # https://greenlet.readthedocs.io/en/latest/tracing.html + + # Note: gevent.version_info is WRONG (gevent.__version__ must be used). + try: + if tuple(int(x) for x in gevent.__version__.split('.')[:2]) <= (20, 0): + if not GEVENT_SHOW_PAUSED_GREENLETS: + return + + if not hasattr(greenlet, 'settrace'): + # In older versions it was optional. + # We still try to use if available though (because without it + pydev_log.debug('greenlet.settrace not available. GEVENT_SHOW_PAUSED_GREENLETS will have no effect.') + return + try: + greenlet.settrace(greenlet_events) + except: + pydev_log.exception('Error with greenlet.settrace.') + except: + pydev_log.exception('Error setting up gevent %s.', gevent.__version__) + + +def log_gevent_debug_info(): + pydev_log.debug('Greenlet version: %s', greenlet.__version__) + pydev_log.debug('Gevent version: %s', gevent.__version__) + pydev_log.debug('Gevent install location: %s', gevent.__file__) diff --git a/_pydevd_bundle/pydevd_import_class.py b/_pydevd_bundle/pydevd_import_class.py new file mode 100644 index 0000000..ee3527c --- /dev/null +++ b/_pydevd_bundle/pydevd_import_class.py @@ -0,0 +1,68 @@ +#Note: code gotten from _pydev_imports_tipper. + +import sys + +def _imp(name, log=None): + try: + return __import__(name) + except: + if '.' in name: + sub = name[0:name.rfind('.')] + + if log is not None: + log.add_content('Unable to import', name, 'trying with', sub) + log.add_exception() + + return _imp(sub, log) + else: + s = 'Unable to import module: %s - sys.path: %s' % (str(name), sys.path) + if log is not None: + log.add_content(s) + log.add_exception() + + raise ImportError(s) + + +IS_IPY = False +if sys.platform == 'cli': + IS_IPY = True + _old_imp = _imp + def _imp(name, log=None): + #We must add a reference in clr for .Net + import clr #@UnresolvedImport + initial_name = name + while '.' in name: + try: + clr.AddReference(name) + break #If it worked, that's OK. + except: + name = name[0:name.rfind('.')] + else: + try: + clr.AddReference(name) + except: + pass #That's OK (not dot net module). + + return _old_imp(initial_name, log) + + +def import_name(name, log=None): + mod = _imp(name, log) + + components = name.split('.') + + old_comp = None + for comp in components[1:]: + try: + #this happens in the following case: + #we have mx.DateTime.mxDateTime.mxDateTime.pyd + #but after importing it, mx.DateTime.mxDateTime shadows access to mxDateTime.pyd + mod = getattr(mod, comp) + except AttributeError: + if old_comp != comp: + raise + + old_comp = comp + + return mod + diff --git a/_pydevd_bundle/pydevd_io.py b/_pydevd_bundle/pydevd_io.py new file mode 100644 index 0000000..3682c4d --- /dev/null +++ b/_pydevd_bundle/pydevd_io.py @@ -0,0 +1,258 @@ +from _pydevd_bundle.pydevd_constants import ForkSafeLock, get_global_debugger +import os +import sys +from contextlib import contextmanager + + +class IORedirector: + ''' + This class works to wrap a stream (stdout/stderr) with an additional redirect. + ''' + + def __init__(self, original, new_redirect, wrap_buffer=False): + ''' + :param stream original: + The stream to be wrapped (usually stdout/stderr, but could be None). + + :param stream new_redirect: + Usually IOBuf (below). + + :param bool wrap_buffer: + Whether to create a buffer attribute (needed to mimick python 3 s + tdout/stderr which has a buffer to write binary data). + ''' + self._lock = ForkSafeLock(rlock=True) + self._writing = False + self._redirect_to = (original, new_redirect) + if wrap_buffer and hasattr(original, 'buffer'): + self.buffer = IORedirector(original.buffer, new_redirect.buffer, False) + + def write(self, s): + # Note that writing to the original stream may fail for some reasons + # (such as trying to write something that's not a string or having it closed). + with self._lock: + if self._writing: + return + self._writing = True + try: + for r in self._redirect_to: + if hasattr(r, 'write'): + r.write(s) + finally: + self._writing = False + + def isatty(self): + for r in self._redirect_to: + if hasattr(r, 'isatty'): + return r.isatty() + return False + + def flush(self): + for r in self._redirect_to: + if hasattr(r, 'flush'): + r.flush() + + def __getattr__(self, name): + for r in self._redirect_to: + if hasattr(r, name): + return getattr(r, name) + raise AttributeError(name) + + +class RedirectToPyDBIoMessages(object): + + def __init__(self, out_ctx, wrap_stream, wrap_buffer, on_write=None): + ''' + :param out_ctx: + 1=stdout and 2=stderr + + :param wrap_stream: + Either sys.stdout or sys.stderr. + + :param bool wrap_buffer: + If True the buffer attribute (which wraps writing bytes) should be + wrapped. + + :param callable(str) on_write: + May be a custom callable to be called when to write something. + If not passed the default implementation will create an io message + and send it through the debugger. + ''' + encoding = getattr(wrap_stream, 'encoding', None) + if not encoding: + encoding = os.environ.get('PYTHONIOENCODING', 'utf-8') + self.encoding = encoding + self._out_ctx = out_ctx + if wrap_buffer: + self.buffer = RedirectToPyDBIoMessages(out_ctx, wrap_stream, wrap_buffer=False, on_write=on_write) + self._on_write = on_write + + def get_pydb(self): + # Note: separate method for mocking on tests. + return get_global_debugger() + + def flush(self): + pass # no-op here + + def write(self, s): + if self._on_write is not None: + self._on_write(s) + return + + if s: + # Need s in str + if isinstance(s, bytes): + s = s.decode(self.encoding, errors='replace') + + py_db = self.get_pydb() + if py_db is not None: + # Note that the actual message contents will be a xml with utf-8, although + # the entry is str on py3 and bytes on py2. + cmd = py_db.cmd_factory.make_io_message(s, self._out_ctx) + if py_db.writer is not None: + py_db.writer.add_command(cmd) + + +class IOBuf: + '''This class works as a replacement for stdio and stderr. + It is a buffer and when its contents are requested, it will erase what + it has so far so that the next return will not return the same contents again. + ''' + + def __init__(self): + self.buflist = [] + import os + self.encoding = os.environ.get('PYTHONIOENCODING', 'utf-8') + + def getvalue(self): + b = self.buflist + self.buflist = [] # clear it + return ''.join(b) # bytes on py2, str on py3. + + def write(self, s): + if isinstance(s, bytes): + s = s.decode(self.encoding, errors='replace') + self.buflist.append(s) + + def isatty(self): + return False + + def flush(self): + pass + + def empty(self): + return len(self.buflist) == 0 + + +class _RedirectInfo(object): + + def __init__(self, original, redirect_to): + self.original = original + self.redirect_to = redirect_to + + +class _RedirectionsHolder: + _lock = ForkSafeLock(rlock=True) + _stack_stdout = [] + _stack_stderr = [] + + _pydevd_stdout_redirect_ = None + _pydevd_stderr_redirect_ = None + + +def start_redirect(keep_original_redirection=False, std='stdout', redirect_to=None): + ''' + @param std: 'stdout', 'stderr', or 'both' + ''' + with _RedirectionsHolder._lock: + if redirect_to is None: + redirect_to = IOBuf() + + if std == 'both': + config_stds = ['stdout', 'stderr'] + else: + config_stds = [std] + + for std in config_stds: + original = getattr(sys, std) + stack = getattr(_RedirectionsHolder, '_stack_%s' % std) + + if keep_original_redirection: + wrap_buffer = True if hasattr(redirect_to, 'buffer') else False + new_std_instance = IORedirector(getattr(sys, std), redirect_to, wrap_buffer=wrap_buffer) + setattr(sys, std, new_std_instance) + else: + new_std_instance = redirect_to + setattr(sys, std, redirect_to) + + stack.append(_RedirectInfo(original, new_std_instance)) + + return redirect_to + + +def end_redirect(std='stdout'): + with _RedirectionsHolder._lock: + if std == 'both': + config_stds = ['stdout', 'stderr'] + else: + config_stds = [std] + for std in config_stds: + stack = getattr(_RedirectionsHolder, '_stack_%s' % std) + redirect_info = stack.pop() + setattr(sys, std, redirect_info.original) + + +def redirect_stream_to_pydb_io_messages(std): + ''' + :param std: + 'stdout' or 'stderr' + ''' + with _RedirectionsHolder._lock: + redirect_to_name = '_pydevd_%s_redirect_' % (std,) + if getattr(_RedirectionsHolder, redirect_to_name) is None: + wrap_buffer = True + original = getattr(sys, std) + + redirect_to = RedirectToPyDBIoMessages(1 if std == 'stdout' else 2, original, wrap_buffer) + start_redirect(keep_original_redirection=True, std=std, redirect_to=redirect_to) + + stack = getattr(_RedirectionsHolder, '_stack_%s' % std) + setattr(_RedirectionsHolder, redirect_to_name, stack[-1]) + return True + + return False + + +def stop_redirect_stream_to_pydb_io_messages(std): + ''' + :param std: + 'stdout' or 'stderr' + ''' + with _RedirectionsHolder._lock: + redirect_to_name = '_pydevd_%s_redirect_' % (std,) + redirect_info = getattr(_RedirectionsHolder, redirect_to_name) + if redirect_info is not None: # :type redirect_info: _RedirectInfo + setattr(_RedirectionsHolder, redirect_to_name, None) + + stack = getattr(_RedirectionsHolder, '_stack_%s' % std) + prev_info = stack.pop() + + curr = getattr(sys, std) + if curr is redirect_info.redirect_to: + setattr(sys, std, redirect_info.original) + + +@contextmanager +def redirect_stream_to_pydb_io_messages_context(): + with _RedirectionsHolder._lock: + redirecting = [] + for std in ('stdout', 'stderr'): + if redirect_stream_to_pydb_io_messages(std): + redirecting.append(std) + + try: + yield + finally: + for std in redirecting: + stop_redirect_stream_to_pydb_io_messages(std) + diff --git a/_pydevd_bundle/pydevd_json_debug_options.py b/_pydevd_bundle/pydevd_json_debug_options.py new file mode 100644 index 0000000..4923268 --- /dev/null +++ b/_pydevd_bundle/pydevd_json_debug_options.py @@ -0,0 +1,196 @@ +import json +import urllib.parse as urllib_parse + + +class DebugOptions(object): + + __slots__ = [ + 'just_my_code', + 'redirect_output', + 'show_return_value', + 'break_system_exit_zero', + 'django_debug', + 'flask_debug', + 'stop_on_entry', + 'max_exception_stack_frames', + 'gui_event_loop', + ] + + def __init__(self): + self.just_my_code = True + self.redirect_output = False + self.show_return_value = False + self.break_system_exit_zero = False + self.django_debug = False + self.flask_debug = False + self.stop_on_entry = False + self.max_exception_stack_frames = 0 + self.gui_event_loop = 'matplotlib' + + def to_json(self): + dct = {} + for s in self.__slots__: + dct[s] = getattr(self, s) + return json.dumps(dct) + + def update_fom_debug_options(self, debug_options): + if 'DEBUG_STDLIB' in debug_options: + self.just_my_code = not debug_options.get('DEBUG_STDLIB') + + if 'REDIRECT_OUTPUT' in debug_options: + self.redirect_output = debug_options.get('REDIRECT_OUTPUT') + + if 'SHOW_RETURN_VALUE' in debug_options: + self.show_return_value = debug_options.get('SHOW_RETURN_VALUE') + + if 'BREAK_SYSTEMEXIT_ZERO' in debug_options: + self.break_system_exit_zero = debug_options.get('BREAK_SYSTEMEXIT_ZERO') + + if 'DJANGO_DEBUG' in debug_options: + self.django_debug = debug_options.get('DJANGO_DEBUG') + + if 'FLASK_DEBUG' in debug_options: + self.flask_debug = debug_options.get('FLASK_DEBUG') + + if 'STOP_ON_ENTRY' in debug_options: + self.stop_on_entry = debug_options.get('STOP_ON_ENTRY') + + # Note: _max_exception_stack_frames cannot be set by debug options. + + def update_from_args(self, args): + if 'justMyCode' in args: + self.just_my_code = bool_parser(args['justMyCode']) + else: + # i.e.: if justMyCode is provided, don't check the deprecated value + if 'debugStdLib' in args: + self.just_my_code = not bool_parser(args['debugStdLib']) + + if 'redirectOutput' in args: + self.redirect_output = bool_parser(args['redirectOutput']) + + if 'showReturnValue' in args: + self.show_return_value = bool_parser(args['showReturnValue']) + + if 'breakOnSystemExitZero' in args: + self.break_system_exit_zero = bool_parser(args['breakOnSystemExitZero']) + + if 'django' in args: + self.django_debug = bool_parser(args['django']) + + if 'flask' in args: + self.flask_debug = bool_parser(args['flask']) + + if 'jinja' in args: + self.flask_debug = bool_parser(args['jinja']) + + if 'stopOnEntry' in args: + self.stop_on_entry = bool_parser(args['stopOnEntry']) + + self.max_exception_stack_frames = int_parser(args.get('maxExceptionStackFrames', 0)) + + if 'guiEventLoop' in args: + self.gui_event_loop = str(args['guiEventLoop']) + + +def int_parser(s, default_value=0): + try: + return int(s) + except Exception: + return default_value + + +def bool_parser(s): + return s in ("True", "true", "1", True, 1) + + +def unquote(s): + return None if s is None else urllib_parse.unquote(s) + + +DEBUG_OPTIONS_PARSER = { + 'WAIT_ON_ABNORMAL_EXIT': bool_parser, + 'WAIT_ON_NORMAL_EXIT': bool_parser, + 'BREAK_SYSTEMEXIT_ZERO': bool_parser, + 'REDIRECT_OUTPUT': bool_parser, + 'DJANGO_DEBUG': bool_parser, + 'FLASK_DEBUG': bool_parser, + 'FIX_FILE_PATH_CASE': bool_parser, + 'CLIENT_OS_TYPE': unquote, + 'DEBUG_STDLIB': bool_parser, + 'STOP_ON_ENTRY': bool_parser, + 'SHOW_RETURN_VALUE': bool_parser, + 'MULTIPROCESS': bool_parser, +} + +DEBUG_OPTIONS_BY_FLAG = { + 'RedirectOutput': 'REDIRECT_OUTPUT=True', + 'WaitOnNormalExit': 'WAIT_ON_NORMAL_EXIT=True', + 'WaitOnAbnormalExit': 'WAIT_ON_ABNORMAL_EXIT=True', + 'BreakOnSystemExitZero': 'BREAK_SYSTEMEXIT_ZERO=True', + 'Django': 'DJANGO_DEBUG=True', + 'Flask': 'FLASK_DEBUG=True', + 'Jinja': 'FLASK_DEBUG=True', + 'FixFilePathCase': 'FIX_FILE_PATH_CASE=True', + 'DebugStdLib': 'DEBUG_STDLIB=True', + 'WindowsClient': 'CLIENT_OS_TYPE=WINDOWS', + 'UnixClient': 'CLIENT_OS_TYPE=UNIX', + 'StopOnEntry': 'STOP_ON_ENTRY=True', + 'ShowReturnValue': 'SHOW_RETURN_VALUE=True', + 'Multiprocess': 'MULTIPROCESS=True', +} + + +def _build_debug_options(flags): + """Build string representation of debug options from the launch config.""" + return ';'.join(DEBUG_OPTIONS_BY_FLAG[flag] + for flag in flags or [] + if flag in DEBUG_OPTIONS_BY_FLAG) + + +def _parse_debug_options(opts): + """Debug options are semicolon separated key=value pairs + """ + options = {} + if not opts: + return options + + for opt in opts.split(';'): + try: + key, value = opt.split('=') + except ValueError: + continue + try: + options[key] = DEBUG_OPTIONS_PARSER[key](value) + except KeyError: + continue + + return options + + +def _extract_debug_options(opts, flags=None): + """Return the debug options encoded in the given value. + + "opts" is a semicolon-separated string of "key=value" pairs. + "flags" is a list of strings. + + If flags is provided then it is used as a fallback. + + The values come from the launch config: + + { + type:'python', + request:'launch'|'attach', + name:'friendly name for debug config', + debugOptions:[ + 'RedirectOutput', 'Django' + ], + options:'REDIRECT_OUTPUT=True;DJANGO_DEBUG=True' + } + + Further information can be found here: + + https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes + """ + if not opts: + opts = _build_debug_options(flags) + return _parse_debug_options(opts) diff --git a/_pydevd_bundle/pydevd_net_command.py b/_pydevd_bundle/pydevd_net_command.py new file mode 100644 index 0000000..506f5fd --- /dev/null +++ b/_pydevd_bundle/pydevd_net_command.py @@ -0,0 +1,146 @@ +from _pydevd_bundle.pydevd_constants import DebugInfoHolder, \ + get_global_debugger, GetGlobalDebugger, set_global_debugger # Keep for backward compatibility @UnusedImport +from _pydevd_bundle.pydevd_utils import quote_smart as quote, to_string +from _pydevd_bundle.pydevd_comm_constants import ID_TO_MEANING, CMD_EXIT +from _pydevd_bundle.pydevd_constants import HTTP_PROTOCOL, HTTP_JSON_PROTOCOL, \ + get_protocol, IS_JYTHON, ForkSafeLock +import json +from _pydev_bundle import pydev_log + + +class _BaseNetCommand(object): + + # Command id. Should be set in instance. + id = -1 + + # Dict representation of the command to be set in instance. Only set for json commands. + as_dict = None + + def send(self, *args, **kwargs): + pass + + def call_after_send(self, callback): + pass + + +class _NullNetCommand(_BaseNetCommand): + pass + + +class _NullExitCommand(_NullNetCommand): + + id = CMD_EXIT + + +# Constant meant to be passed to the writer when the command is meant to be ignored. +NULL_NET_COMMAND = _NullNetCommand() + +# Exit command -- only internal (we don't want/need to send this to the IDE). +NULL_EXIT_COMMAND = _NullExitCommand() + + +class NetCommand(_BaseNetCommand): + """ + Commands received/sent over the network. + + Command can represent command received from the debugger, + or one to be sent by daemon. + """ + next_seq = 0 # sequence numbers + + _showing_debug_info = 0 + _show_debug_info_lock = ForkSafeLock(rlock=True) + + _after_send = None + + def __init__(self, cmd_id, seq, text, is_json=False): + """ + If sequence is 0, new sequence will be generated (otherwise, this was the response + to a command from the client). + """ + protocol = get_protocol() + self.id = cmd_id + if seq == 0: + NetCommand.next_seq += 2 + seq = NetCommand.next_seq + + self.seq = seq + + if is_json: + if hasattr(text, 'to_dict'): + as_dict = text.to_dict(update_ids_to_dap=True) + else: + assert isinstance(text, dict) + as_dict = text + as_dict['pydevd_cmd_id'] = cmd_id + as_dict['seq'] = seq + self.as_dict = as_dict + text = json.dumps(as_dict) + + assert isinstance(text, str) + + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + self._show_debug_info(cmd_id, seq, text) + + if is_json: + msg = text + else: + if protocol not in (HTTP_PROTOCOL, HTTP_JSON_PROTOCOL): + encoded = quote(to_string(text), '/<>_=" \t') + msg = '%s\t%s\t%s\n' % (cmd_id, seq, encoded) + + else: + msg = '%s\t%s\t%s' % (cmd_id, seq, text) + + if isinstance(msg, str): + msg = msg.encode('utf-8') + + assert isinstance(msg, bytes) + as_bytes = msg + self._as_bytes = as_bytes + + def send(self, sock): + as_bytes = self._as_bytes + try: + if get_protocol() in (HTTP_PROTOCOL, HTTP_JSON_PROTOCOL): + sock.sendall(('Content-Length: %s\r\n\r\n' % len(as_bytes)).encode('ascii')) + sock.sendall(as_bytes) + if self._after_send: + for method in self._after_send: + method(sock) + except: + if IS_JYTHON: + # Ignore errors in sock.sendall in Jython (seems to be common for Jython to + # give spurious exceptions at interpreter shutdown here). + pass + else: + raise + + def call_after_send(self, callback): + if not self._after_send: + self._after_send = [callback] + else: + self._after_send.append(callback) + + @classmethod + def _show_debug_info(cls, cmd_id, seq, text): + with cls._show_debug_info_lock: + # Only one thread each time (rlock). + if cls._showing_debug_info: + # avoid recursing in the same thread (just printing could create + # a new command when redirecting output). + return + + cls._showing_debug_info += 1 + try: + out_message = 'sending cmd (%s) --> ' % (get_protocol(),) + out_message += "%20s" % ID_TO_MEANING.get(str(cmd_id), 'UNKNOWN') + out_message += ' ' + out_message += text.replace('\n', ' ') + try: + pydev_log.critical('%s\n', out_message) + except: + pass + finally: + cls._showing_debug_info -= 1 + diff --git a/_pydevd_bundle/pydevd_net_command_factory_json.py b/_pydevd_bundle/pydevd_net_command_factory_json.py new file mode 100644 index 0000000..a73b189 --- /dev/null +++ b/_pydevd_bundle/pydevd_net_command_factory_json.py @@ -0,0 +1,474 @@ +from functools import partial +import itertools +import os +import sys +import socket as socket_module + +from _pydev_bundle._pydev_imports_tipper import TYPE_IMPORT, TYPE_CLASS, TYPE_FUNCTION, TYPE_ATTR, \ + TYPE_BUILTIN, TYPE_PARAM +from _pydev_bundle.pydev_is_thread_alive import is_thread_alive +from _pydev_bundle.pydev_override import overrides +from _pydevd_bundle._debug_adapter import pydevd_schema +from _pydevd_bundle._debug_adapter.pydevd_schema import ModuleEvent, ModuleEventBody, Module, \ + OutputEventBody, OutputEvent, ContinuedEventBody, ExitedEventBody, \ + ExitedEvent +from _pydevd_bundle.pydevd_comm_constants import CMD_THREAD_CREATE, CMD_RETURN, CMD_MODULE_EVENT, \ + CMD_WRITE_TO_CONSOLE, CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE, \ + CMD_STEP_RETURN, CMD_STEP_CAUGHT_EXCEPTION, CMD_ADD_EXCEPTION_BREAK, CMD_SET_BREAK, \ + CMD_SET_NEXT_STATEMENT, CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, \ + CMD_THREAD_RESUME_SINGLE_NOTIFICATION, CMD_THREAD_KILL, CMD_STOP_ON_START, CMD_INPUT_REQUESTED, \ + CMD_EXIT, CMD_STEP_INTO_COROUTINE, CMD_STEP_RETURN_MY_CODE, CMD_SMART_STEP_INTO, \ + CMD_SET_FUNCTION_BREAK +from _pydevd_bundle.pydevd_constants import get_thread_id, ForkSafeLock +from _pydevd_bundle.pydevd_net_command import NetCommand, NULL_NET_COMMAND +from _pydevd_bundle.pydevd_net_command_factory_xml import NetCommandFactory +from _pydevd_bundle.pydevd_utils import get_non_pydevd_threads +import pydevd_file_utils +from _pydevd_bundle.pydevd_comm import build_exception_info_response +from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info +from _pydevd_bundle import pydevd_frame_utils, pydevd_constants, pydevd_utils +import linecache +from _pydevd_bundle.pydevd_thread_lifecycle import pydevd_find_thread_by_id +from io import StringIO + + +class ModulesManager(object): + + def __init__(self): + self._lock = ForkSafeLock() + self._modules = {} + self._next_id = partial(next, itertools.count(0)) + + def track_module(self, filename_in_utf8, module_name, frame): + ''' + :return list(NetCommand): + Returns a list with the module events to be sent. + ''' + if filename_in_utf8 in self._modules: + return [] + + module_events = [] + with self._lock: + # Must check again after getting the lock. + if filename_in_utf8 in self._modules: + return + + try: + version = str(frame.f_globals.get('__version__', '')) + except: + version = '' + + try: + package_name = str(frame.f_globals.get('__package__', '')) + except: + package_name = '' + + module_id = self._next_id() + + module = Module(module_id, module_name, filename_in_utf8) + if version: + module.version = version + + if package_name: + # Note: package doesn't appear in the docs but seems to be expected? + module.kwargs['package'] = package_name + + module_event = ModuleEvent(ModuleEventBody('new', module)) + + module_events.append(NetCommand(CMD_MODULE_EVENT, 0, module_event, is_json=True)) + + self._modules[filename_in_utf8] = module.to_dict() + return module_events + + def get_modules_info(self): + ''' + :return list(Module) + ''' + with self._lock: + return list(self._modules.values()) + + +class NetCommandFactoryJson(NetCommandFactory): + ''' + Factory for commands which will provide messages as json (they should be + similar to the debug adapter where possible, although some differences + are currently Ok). + + Note that it currently overrides the xml version so that messages + can be done one at a time (any message not overridden will currently + use the xml version) -- after having all messages handled, it should + no longer use NetCommandFactory as the base class. + ''' + + def __init__(self): + NetCommandFactory.__init__(self) + self.modules_manager = ModulesManager() + + @overrides(NetCommandFactory.make_version_message) + def make_version_message(self, seq): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_protocol_set_message) + def make_protocol_set_message(self, seq): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_thread_created_message) + def make_thread_created_message(self, thread): + + # Note: the thread id for the debug adapter must be an int + # (make the actual id from get_thread_id respect that later on). + msg = pydevd_schema.ThreadEvent( + pydevd_schema.ThreadEventBody('started', get_thread_id(thread)), + ) + + return NetCommand(CMD_THREAD_CREATE, 0, msg, is_json=True) + + @overrides(NetCommandFactory.make_custom_frame_created_message) + def make_custom_frame_created_message(self, frame_id, frame_description): + self._additional_thread_id_to_thread_name[frame_id] = frame_description + msg = pydevd_schema.ThreadEvent( + pydevd_schema.ThreadEventBody('started', frame_id), + ) + + return NetCommand(CMD_THREAD_CREATE, 0, msg, is_json=True) + + @overrides(NetCommandFactory.make_thread_killed_message) + def make_thread_killed_message(self, tid): + self._additional_thread_id_to_thread_name.pop(tid, None) + msg = pydevd_schema.ThreadEvent( + pydevd_schema.ThreadEventBody('exited', tid), + ) + + return NetCommand(CMD_THREAD_KILL, 0, msg, is_json=True) + + @overrides(NetCommandFactory.make_list_threads_message) + def make_list_threads_message(self, py_db, seq): + threads = [] + for thread in get_non_pydevd_threads(): + if is_thread_alive(thread): + thread_id = get_thread_id(thread) + + # Notify that it's created (no-op if we already notified before). + py_db.notify_thread_created(thread_id, thread) + + thread_schema = pydevd_schema.Thread(id=thread_id, name=thread.name) + threads.append(thread_schema.to_dict()) + + for thread_id, thread_name in list(self._additional_thread_id_to_thread_name.items()): + thread_schema = pydevd_schema.Thread(id=thread_id, name=thread_name) + threads.append(thread_schema.to_dict()) + + body = pydevd_schema.ThreadsResponseBody(threads) + response = pydevd_schema.ThreadsResponse( + request_seq=seq, success=True, command='threads', body=body) + + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + @overrides(NetCommandFactory.make_get_completions_message) + def make_get_completions_message(self, seq, completions, qualifier, start): + COMPLETION_TYPE_LOOK_UP = { + TYPE_IMPORT: pydevd_schema.CompletionItemType.MODULE, + TYPE_CLASS: pydevd_schema.CompletionItemType.CLASS, + TYPE_FUNCTION: pydevd_schema.CompletionItemType.FUNCTION, + TYPE_ATTR: pydevd_schema.CompletionItemType.FIELD, + TYPE_BUILTIN: pydevd_schema.CompletionItemType.KEYWORD, + TYPE_PARAM: pydevd_schema.CompletionItemType.VARIABLE, + } + + qualifier = qualifier.lower() + qualifier_len = len(qualifier) + targets = [] + for completion in completions: + label = completion[0] + if label.lower().startswith(qualifier): + completion = pydevd_schema.CompletionItem( + label=label, type=COMPLETION_TYPE_LOOK_UP[completion[3]], start=start, length=qualifier_len) + targets.append(completion.to_dict()) + + body = pydevd_schema.CompletionsResponseBody(targets) + response = pydevd_schema.CompletionsResponse( + request_seq=seq, success=True, command='completions', body=body) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def _format_frame_name(self, fmt, initial_name, module_name, line, path): + if fmt is None: + return initial_name + frame_name = initial_name + if fmt.get('module', False): + if module_name: + if initial_name == '': + frame_name = module_name + else: + frame_name = '%s.%s' % (module_name, initial_name) + else: + basename = os.path.basename(path) + basename = basename[0:-3] if basename.lower().endswith('.py') else basename + if initial_name == '': + frame_name = '%s in %s' % (initial_name, basename) + else: + frame_name = '%s.%s' % (basename, initial_name) + + if fmt.get('line', False): + frame_name = '%s : %d' % (frame_name, line) + + return frame_name + + @overrides(NetCommandFactory.make_get_thread_stack_message) + def make_get_thread_stack_message(self, py_db, seq, thread_id, topmost_frame, fmt, must_be_suspended=False, start_frame=0, levels=0): + frames = [] + module_events = [] + + try: + # : :type suspended_frames_manager: SuspendedFramesManager + suspended_frames_manager = py_db.suspended_frames_manager + frames_list = suspended_frames_manager.get_frames_list(thread_id) + if frames_list is None: + # Could not find stack of suspended frame... + if must_be_suspended: + return None + else: + frames_list = pydevd_frame_utils.create_frames_list_from_frame(topmost_frame) + + for frame_id, frame, method_name, original_filename, filename_in_utf8, lineno, applied_mapping, show_as_current_frame in self._iter_visible_frames_info( + py_db, frames_list + ): + + try: + module_name = str(frame.f_globals.get('__name__', '')) + except: + module_name = '' + + module_events.extend(self.modules_manager.track_module(filename_in_utf8, module_name, frame)) + + presentation_hint = None + if not getattr(frame, 'IS_PLUGIN_FRAME', False): # Never filter out plugin frames! + if py_db.is_files_filter_enabled and py_db.apply_files_filter(frame, original_filename, False): + continue + + if not py_db.in_project_scope(frame): + presentation_hint = 'subtle' + + formatted_name = self._format_frame_name(fmt, method_name, module_name, lineno, filename_in_utf8) + if show_as_current_frame: + formatted_name += ' (Current frame)' + source_reference = pydevd_file_utils.get_client_filename_source_reference(filename_in_utf8) + + if not source_reference and not applied_mapping and not os.path.exists(original_filename): + if getattr(frame.f_code, 'co_lnotab', None): + # Create a source-reference to be used where we provide the source by decompiling the code. + # Note: When the time comes to retrieve the source reference in this case, we'll + # check the linecache first (see: get_decompiled_source_from_frame_id). + source_reference = pydevd_file_utils.create_source_reference_for_frame_id(frame_id, original_filename) + else: + # Check if someone added a source reference to the linecache (Python attrs does this). + if linecache.getline(original_filename, 1): + source_reference = pydevd_file_utils.create_source_reference_for_linecache( + original_filename) + + frames.append(pydevd_schema.StackFrame( + frame_id, formatted_name, lineno, column=1, source={ + 'path': filename_in_utf8, + 'sourceReference': source_reference, + }, + presentationHint=presentation_hint).to_dict()) + finally: + topmost_frame = None + + for module_event in module_events: + py_db.writer.add_command(module_event) + + total_frames = len(frames) + stack_frames = frames + if bool(levels): + start = start_frame + end = min(start + levels, total_frames) + stack_frames = frames[start:end] + + response = pydevd_schema.StackTraceResponse( + request_seq=seq, + success=True, + command='stackTrace', + body=pydevd_schema.StackTraceResponseBody(stackFrames=stack_frames, totalFrames=total_frames)) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + @overrides(NetCommandFactory.make_warning_message) + def make_warning_message(self, msg): + category = 'important' + body = OutputEventBody(msg, category) + event = OutputEvent(body) + return NetCommand(CMD_WRITE_TO_CONSOLE, 0, event, is_json=True) + + @overrides(NetCommandFactory.make_io_message) + def make_io_message(self, msg, ctx): + category = 'stdout' if int(ctx) == 1 else 'stderr' + body = OutputEventBody(msg, category) + event = OutputEvent(body) + return NetCommand(CMD_WRITE_TO_CONSOLE, 0, event, is_json=True) + + _STEP_REASONS = set([ + CMD_STEP_INTO, + CMD_STEP_INTO_MY_CODE, + CMD_STEP_OVER, + CMD_STEP_OVER_MY_CODE, + CMD_STEP_RETURN, + CMD_STEP_RETURN_MY_CODE, + CMD_STEP_INTO_MY_CODE, + CMD_STOP_ON_START, + CMD_STEP_INTO_COROUTINE, + CMD_SMART_STEP_INTO, + ]) + _EXCEPTION_REASONS = set([ + CMD_STEP_CAUGHT_EXCEPTION, + CMD_ADD_EXCEPTION_BREAK, + ]) + + @overrides(NetCommandFactory.make_thread_suspend_single_notification) + def make_thread_suspend_single_notification(self, py_db, thread_id, stop_reason): + exc_desc = None + exc_name = None + thread = pydevd_find_thread_by_id(thread_id) + info = set_additional_thread_info(thread) + + preserve_focus_hint = False + if stop_reason in self._STEP_REASONS: + if info.pydev_original_step_cmd == CMD_STOP_ON_START: + + # Just to make sure that's not set as the original reason anymore. + info.pydev_original_step_cmd = -1 + stop_reason = 'entry' + else: + stop_reason = 'step' + elif stop_reason in self._EXCEPTION_REASONS: + stop_reason = 'exception' + elif stop_reason == CMD_SET_BREAK: + stop_reason = 'breakpoint' + elif stop_reason == CMD_SET_FUNCTION_BREAK: + stop_reason = 'function breakpoint' + elif stop_reason == CMD_SET_NEXT_STATEMENT: + stop_reason = 'goto' + else: + stop_reason = 'pause' + preserve_focus_hint = True + + if stop_reason == 'exception': + exception_info_response = build_exception_info_response( + py_db, thread_id, -1, set_additional_thread_info, self._iter_visible_frames_info, max_frames=-1) + exception_info_response + + exc_name = exception_info_response.body.exceptionId + exc_desc = exception_info_response.body.description + + body = pydevd_schema.StoppedEventBody( + reason=stop_reason, + description=exc_desc, + threadId=thread_id, + text=exc_name, + allThreadsStopped=True, + preserveFocusHint=preserve_focus_hint, + ) + event = pydevd_schema.StoppedEvent(body) + return NetCommand(CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, 0, event, is_json=True) + + @overrides(NetCommandFactory.make_thread_resume_single_notification) + def make_thread_resume_single_notification(self, thread_id): + body = ContinuedEventBody(threadId=thread_id, allThreadsContinued=True) + event = pydevd_schema.ContinuedEvent(body) + return NetCommand(CMD_THREAD_RESUME_SINGLE_NOTIFICATION, 0, event, is_json=True) + + @overrides(NetCommandFactory.make_set_next_stmnt_status_message) + def make_set_next_stmnt_status_message(self, seq, is_success, exception_msg): + response = pydevd_schema.GotoResponse( + request_seq=int(seq), + success=is_success, + command='goto', + body={}, + message=(None if is_success else exception_msg)) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + @overrides(NetCommandFactory.make_send_curr_exception_trace_message) + def make_send_curr_exception_trace_message(self, *args, **kwargs): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_send_curr_exception_trace_proceeded_message) + def make_send_curr_exception_trace_proceeded_message(self, *args, **kwargs): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_send_breakpoint_exception_message) + def make_send_breakpoint_exception_message(self, *args, **kwargs): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_process_created_message) + def make_process_created_message(self, *args, **kwargs): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_process_about_to_be_replaced_message) + def make_process_about_to_be_replaced_message(self): + event = ExitedEvent(ExitedEventBody(-1, pydevdReason="processReplaced")) + + cmd = NetCommand(CMD_RETURN, 0, event, is_json=True) + + def after_send(socket): + socket.setsockopt(socket_module.IPPROTO_TCP, socket_module.TCP_NODELAY, 1) + + cmd.call_after_send(after_send) + return cmd + + @overrides(NetCommandFactory.make_thread_suspend_message) + def make_thread_suspend_message(self, *args, **kwargs): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_thread_run_message) + def make_thread_run_message(self, *args, **kwargs): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_reloaded_code_message) + def make_reloaded_code_message(self, *args, **kwargs): + return NULL_NET_COMMAND # Not a part of the debug adapter protocol + + @overrides(NetCommandFactory.make_input_requested_message) + def make_input_requested_message(self, started): + event = pydevd_schema.PydevdInputRequestedEvent(body={}) + return NetCommand(CMD_INPUT_REQUESTED, 0, event, is_json=True) + + @overrides(NetCommandFactory.make_skipped_step_in_because_of_filters) + def make_skipped_step_in_because_of_filters(self, py_db, frame): + msg = 'Frame skipped from debugging during step-in.' + if py_db.get_use_libraries_filter(): + msg += ('\nNote: may have been skipped because of "justMyCode" option (default == true). ' + 'Try setting \"justMyCode\": false in the debug configuration (e.g., launch.json).\n') + return self.make_warning_message(msg) + + @overrides(NetCommandFactory.make_evaluation_timeout_msg) + def make_evaluation_timeout_msg(self, py_db, expression, curr_thread): + msg = '''Evaluating: %s did not finish after %.2f seconds. +This may mean a number of things: +- This evaluation is really slow and this is expected. + In this case it's possible to silence this error by raising the timeout, setting the + PYDEVD_WARN_EVALUATION_TIMEOUT environment variable to a bigger value. + +- The evaluation may need other threads running while it's running: + In this case, it's possible to set the PYDEVD_UNBLOCK_THREADS_TIMEOUT + environment variable so that if after a given timeout an evaluation doesn't finish, + other threads are unblocked or you can manually resume all threads. + + Alternatively, it's also possible to skip breaking on a particular thread by setting a + `pydev_do_not_trace = True` attribute in the related threading.Thread instance + (if some thread should always be running and no breakpoints are expected to be hit in it). + +- The evaluation is deadlocked: + In this case you may set the PYDEVD_THREAD_DUMP_ON_WARN_EVALUATION_TIMEOUT + environment variable to true so that a thread dump is shown along with this message and + optionally, set the PYDEVD_INTERRUPT_THREAD_TIMEOUT to some value so that the debugger + tries to interrupt the evaluation (if possible) when this happens. +''' % (expression, pydevd_constants.PYDEVD_WARN_EVALUATION_TIMEOUT) + + if pydevd_constants.PYDEVD_THREAD_DUMP_ON_WARN_EVALUATION_TIMEOUT: + stream = StringIO() + pydevd_utils.dump_threads(stream, show_pydevd_threads=False) + msg += '\n\n%s\n' % stream.getvalue() + return self.make_warning_message(msg) + + @overrides(NetCommandFactory.make_exit_command) + def make_exit_command(self, py_db): + event = pydevd_schema.TerminatedEvent(pydevd_schema.TerminatedEventBody()) + return NetCommand(CMD_EXIT, 0, event, is_json=True) diff --git a/_pydevd_bundle/pydevd_net_command_factory_xml.py b/_pydevd_bundle/pydevd_net_command_factory_xml.py new file mode 100644 index 0000000..072ba98 --- /dev/null +++ b/_pydevd_bundle/pydevd_net_command_factory_xml.py @@ -0,0 +1,493 @@ +import json + +from _pydev_bundle.pydev_is_thread_alive import is_thread_alive +from _pydev_bundle._pydev_saved_modules import thread +from _pydevd_bundle import pydevd_xml, pydevd_frame_utils, pydevd_constants, pydevd_utils +from _pydevd_bundle.pydevd_comm_constants import ( + CMD_THREAD_CREATE, CMD_THREAD_KILL, CMD_THREAD_SUSPEND, CMD_THREAD_RUN, CMD_GET_VARIABLE, + CMD_EVALUATE_EXPRESSION, CMD_GET_FRAME, CMD_WRITE_TO_CONSOLE, CMD_GET_COMPLETIONS, + CMD_LOAD_SOURCE, CMD_SET_NEXT_STATEMENT, CMD_EXIT, CMD_GET_FILE_CONTENTS, + CMD_EVALUATE_CONSOLE_EXPRESSION, CMD_RUN_CUSTOM_OPERATION, + CMD_GET_BREAKPOINT_EXCEPTION, CMD_SEND_CURR_EXCEPTION_TRACE, + CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED, CMD_SHOW_CONSOLE, CMD_GET_ARRAY, + CMD_INPUT_REQUESTED, CMD_GET_DESCRIPTION, CMD_PROCESS_CREATED, + CMD_SHOW_CYTHON_WARNING, CMD_LOAD_FULL_VALUE, CMD_GET_THREAD_STACK, + CMD_GET_EXCEPTION_DETAILS, CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, + CMD_THREAD_RESUME_SINGLE_NOTIFICATION, + CMD_GET_NEXT_STATEMENT_TARGETS, CMD_VERSION, + CMD_RETURN, CMD_SET_PROTOCOL, CMD_ERROR, MAX_IO_MSG_SIZE, VERSION_STRING, + CMD_RELOAD_CODE, CMD_LOAD_SOURCE_FROM_FRAME_ID) +from _pydevd_bundle.pydevd_constants import (DebugInfoHolder, get_thread_id, + get_global_debugger, GetGlobalDebugger, set_global_debugger) # Keep for backward compatibility @UnusedImport +from _pydevd_bundle.pydevd_net_command import NetCommand, NULL_NET_COMMAND, NULL_EXIT_COMMAND +from _pydevd_bundle.pydevd_utils import quote_smart as quote, get_non_pydevd_threads +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame +import pydevd_file_utils +from pydevd_tracing import get_exception_traceback_str +from _pydev_bundle._pydev_completer import completions_to_xml +from _pydev_bundle import pydev_log +from _pydevd_bundle.pydevd_frame_utils import FramesList +from io import StringIO + + +#======================================================================================================================= +# NetCommandFactory +#======================================================================================================================= +class NetCommandFactory(object): + + def __init__(self): + self._additional_thread_id_to_thread_name = {} + + def _thread_to_xml(self, thread): + """ thread information as XML """ + name = pydevd_xml.make_valid_xml_value(thread.name) + cmd_text = '' % (quote(name), get_thread_id(thread)) + return cmd_text + + def make_error_message(self, seq, text): + cmd = NetCommand(CMD_ERROR, seq, text) + if DebugInfoHolder.DEBUG_TRACE_LEVEL > 2: + pydev_log.error("Error: %s" % (text,)) + return cmd + + def make_protocol_set_message(self, seq): + return NetCommand(CMD_SET_PROTOCOL, seq, '') + + def make_thread_created_message(self, thread): + cmdText = "" + self._thread_to_xml(thread) + "" + return NetCommand(CMD_THREAD_CREATE, 0, cmdText) + + def make_process_created_message(self): + cmdText = '' + return NetCommand(CMD_PROCESS_CREATED, 0, cmdText) + + def make_process_about_to_be_replaced_message(self): + return NULL_NET_COMMAND + + def make_show_cython_warning_message(self): + try: + return NetCommand(CMD_SHOW_CYTHON_WARNING, 0, '') + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_custom_frame_created_message(self, frame_id, frame_description): + self._additional_thread_id_to_thread_name[frame_id] = frame_description + frame_description = pydevd_xml.make_valid_xml_value(frame_description) + return NetCommand(CMD_THREAD_CREATE, 0, '' % (frame_description, frame_id)) + + def make_list_threads_message(self, py_db, seq): + """ returns thread listing as XML """ + try: + threads = get_non_pydevd_threads() + cmd_text = [""] + append = cmd_text.append + for thread in threads: + if is_thread_alive(thread): + append(self._thread_to_xml(thread)) + + for thread_id, thread_name in list(self._additional_thread_id_to_thread_name.items()): + name = pydevd_xml.make_valid_xml_value(thread_name) + append('' % (quote(name), thread_id)) + + append("") + return NetCommand(CMD_RETURN, seq, ''.join(cmd_text)) + except: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_get_thread_stack_message(self, py_db, seq, thread_id, topmost_frame, fmt, must_be_suspended=False, start_frame=0, levels=0): + """ + Returns thread stack as XML. + + :param must_be_suspended: If True and the thread is not suspended, returns None. + """ + try: + # If frame is None, the return is an empty frame list. + cmd_text = ['' % (thread_id,)] + + if topmost_frame is not None: + try: + # : :type suspended_frames_manager: SuspendedFramesManager + suspended_frames_manager = py_db.suspended_frames_manager + frames_list = suspended_frames_manager.get_frames_list(thread_id) + if frames_list is None: + # Could not find stack of suspended frame... + if must_be_suspended: + return None + else: + frames_list = pydevd_frame_utils.create_frames_list_from_frame(topmost_frame) + + cmd_text.append(self.make_thread_stack_str(py_db, frames_list)) + finally: + topmost_frame = None + cmd_text.append('') + return NetCommand(CMD_GET_THREAD_STACK, seq, ''.join(cmd_text)) + except: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_variable_changed_message(self, seq, payload): + # notify debugger that value was changed successfully + return NetCommand(CMD_RETURN, seq, payload) + + def make_warning_message(self, msg): + return self.make_io_message(msg, 2) + + def make_io_message(self, msg, ctx): + ''' + @param msg: the message to pass to the debug server + @param ctx: 1 for stdio 2 for stderr + ''' + try: + msg = pydevd_constants.as_str(msg) + + if len(msg) > MAX_IO_MSG_SIZE: + msg = msg[0:MAX_IO_MSG_SIZE] + msg += '...' + + msg = pydevd_xml.make_valid_xml_value(quote(msg, '/>_= ')) + return NetCommand(str(CMD_WRITE_TO_CONSOLE), 0, '' % (msg, ctx)) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_version_message(self, seq): + try: + return NetCommand(CMD_VERSION, seq, VERSION_STRING) + except: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_thread_killed_message(self, tid): + self._additional_thread_id_to_thread_name.pop(tid, None) + try: + return NetCommand(CMD_THREAD_KILL, 0, str(tid)) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def _iter_visible_frames_info(self, py_db, frames_list): + assert frames_list.__class__ == FramesList + for frame in frames_list: + show_as_current_frame = frame is frames_list.current_frame + if frame.f_code is None: + pydev_log.info('Frame without f_code: %s', frame) + continue # IronPython sometimes does not have it! + + method_name = frame.f_code.co_name # method name (if in method) or ? if global + if method_name is None: + pydev_log.info('Frame without co_name: %s', frame) + continue # IronPython sometimes does not have it! + + abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) + if py_db.get_file_type(frame, abs_path_real_path_and_base) == py_db.PYDEV_FILE: + # Skip pydevd files. + frame = frame.f_back + continue + + frame_id = id(frame) + lineno = frames_list.frame_id_to_lineno.get(frame_id, frame.f_lineno) + + filename_in_utf8, lineno, changed = py_db.source_mapping.map_to_client(abs_path_real_path_and_base[0], lineno) + new_filename_in_utf8, applied_mapping = pydevd_file_utils.map_file_to_client(filename_in_utf8) + applied_mapping = applied_mapping or changed + + yield frame_id, frame, method_name, abs_path_real_path_and_base[0], new_filename_in_utf8, lineno, applied_mapping, show_as_current_frame + + def make_thread_stack_str(self, py_db, frames_list): + assert frames_list.__class__ == FramesList + make_valid_xml_value = pydevd_xml.make_valid_xml_value + cmd_text_list = [] + append = cmd_text_list.append + + try: + for frame_id, frame, method_name, _original_filename, filename_in_utf8, lineno, _applied_mapping, _show_as_current_frame in self._iter_visible_frames_info( + py_db, frames_list + ): + + # print("file is ", filename_in_utf8) + # print("line is ", lineno) + + # Note: variables are all gotten 'on-demand'. + append('' % (quote(make_valid_xml_value(filename_in_utf8), '/>_= \t'), lineno)) + append("") + except: + pydev_log.exception() + + return ''.join(cmd_text_list) + + def make_thread_suspend_str( + self, + py_db, + thread_id, + frames_list, + stop_reason=None, + message=None, + suspend_type="trace", + ): + """ + :return tuple(str,str): + Returns tuple(thread_suspended_str, thread_stack_str). + + i.e.: + ( + ''' + + + + + + + ''' + , + ''' + + + ''' + ) + """ + assert frames_list.__class__ == FramesList + make_valid_xml_value = pydevd_xml.make_valid_xml_value + cmd_text_list = [] + append = cmd_text_list.append + + cmd_text_list.append('') + if message: + message = make_valid_xml_value(message) + + append('') + thread_stack_str = self.make_thread_stack_str(py_db, frames_list) + append(thread_stack_str) + append("") + + return ''.join(cmd_text_list), thread_stack_str + + def make_thread_suspend_message(self, py_db, thread_id, frames_list, stop_reason, message, suspend_type): + try: + thread_suspend_str, thread_stack_str = self.make_thread_suspend_str( + py_db, thread_id, frames_list, stop_reason, message, suspend_type) + cmd = NetCommand(CMD_THREAD_SUSPEND, 0, thread_suspend_str) + cmd.thread_stack_str = thread_stack_str + cmd.thread_suspend_str = thread_suspend_str + return cmd + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_thread_suspend_single_notification(self, py_db, thread_id, stop_reason): + try: + return NetCommand(CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, 0, json.dumps( + {'thread_id': thread_id, 'stop_reason':stop_reason})) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_thread_resume_single_notification(self, thread_id): + try: + return NetCommand(CMD_THREAD_RESUME_SINGLE_NOTIFICATION, 0, json.dumps( + {'thread_id': thread_id})) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_thread_run_message(self, thread_id, reason): + try: + return NetCommand(CMD_THREAD_RUN, 0, "%s\t%s" % (thread_id, reason)) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_get_variable_message(self, seq, payload): + try: + return NetCommand(CMD_GET_VARIABLE, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_get_array_message(self, seq, payload): + try: + return NetCommand(CMD_GET_ARRAY, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_get_description_message(self, seq, payload): + try: + return NetCommand(CMD_GET_DESCRIPTION, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_get_frame_message(self, seq, payload): + try: + return NetCommand(CMD_GET_FRAME, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_evaluate_expression_message(self, seq, payload): + try: + return NetCommand(CMD_EVALUATE_EXPRESSION, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_get_completions_message(self, seq, completions, qualifier, start): + try: + payload = completions_to_xml(completions) + return NetCommand(CMD_GET_COMPLETIONS, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_get_file_contents(self, seq, payload): + try: + return NetCommand(CMD_GET_FILE_CONTENTS, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_reloaded_code_message(self, seq, reloaded_ok): + try: + return NetCommand(CMD_RELOAD_CODE, seq, '' % reloaded_ok) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_send_breakpoint_exception_message(self, seq, payload): + try: + return NetCommand(CMD_GET_BREAKPOINT_EXCEPTION, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def _make_send_curr_exception_trace_str(self, py_db, thread_id, exc_type, exc_desc, trace_obj): + frames_list = pydevd_frame_utils.create_frames_list_from_traceback(trace_obj, None, exc_type, exc_desc) + + exc_type = pydevd_xml.make_valid_xml_value(str(exc_type)).replace('\t', ' ') or 'exception: type unknown' + exc_desc = pydevd_xml.make_valid_xml_value(str(exc_desc)).replace('\t', ' ') or 'exception: no description' + + thread_suspend_str, thread_stack_str = self.make_thread_suspend_str( + py_db, thread_id, frames_list, CMD_SEND_CURR_EXCEPTION_TRACE, '') + return exc_type, exc_desc, thread_suspend_str, thread_stack_str + + def make_send_curr_exception_trace_message(self, py_db, seq, thread_id, curr_frame_id, exc_type, exc_desc, trace_obj): + try: + exc_type, exc_desc, thread_suspend_str, _thread_stack_str = self._make_send_curr_exception_trace_str( + py_db, thread_id, exc_type, exc_desc, trace_obj) + payload = str(curr_frame_id) + '\t' + exc_type + "\t" + exc_desc + "\t" + thread_suspend_str + return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_get_exception_details_message(self, py_db, seq, thread_id, topmost_frame): + """Returns exception details as XML """ + try: + # If the debugger is not suspended, just return the thread and its id. + cmd_text = ['') + cmd_text.append(thread_stack_str) + break + frame = frame.f_back + else: + cmd_text.append('>') + finally: + frame = None + cmd_text.append('') + return NetCommand(CMD_GET_EXCEPTION_DETAILS, seq, ''.join(cmd_text)) + except: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_send_curr_exception_trace_proceeded_message(self, seq, thread_id): + try: + return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED, 0, str(thread_id)) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_send_console_message(self, seq, payload): + try: + return NetCommand(CMD_EVALUATE_CONSOLE_EXPRESSION, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_custom_operation_message(self, seq, payload): + try: + return NetCommand(CMD_RUN_CUSTOM_OPERATION, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_load_source_message(self, seq, source): + return NetCommand(CMD_LOAD_SOURCE, seq, source) + + def make_load_source_from_frame_id_message(self, seq, source): + return NetCommand(CMD_LOAD_SOURCE_FROM_FRAME_ID, seq, source) + + def make_show_console_message(self, py_db, thread_id, frame): + try: + frames_list = pydevd_frame_utils.create_frames_list_from_frame(frame) + thread_suspended_str, _thread_stack_str = self.make_thread_suspend_str( + py_db, thread_id, frames_list, CMD_SHOW_CONSOLE, '') + return NetCommand(CMD_SHOW_CONSOLE, 0, thread_suspended_str) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_input_requested_message(self, started): + try: + return NetCommand(CMD_INPUT_REQUESTED, 0, str(started)) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_set_next_stmnt_status_message(self, seq, is_success, exception_msg): + try: + message = str(is_success) + '\t' + exception_msg + return NetCommand(CMD_SET_NEXT_STATEMENT, int(seq), message) + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_load_full_value_message(self, seq, payload): + try: + return NetCommand(CMD_LOAD_FULL_VALUE, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_get_next_statement_targets_message(self, seq, payload): + try: + return NetCommand(CMD_GET_NEXT_STATEMENT_TARGETS, seq, payload) + except Exception: + return self.make_error_message(seq, get_exception_traceback_str()) + + def make_skipped_step_in_because_of_filters(self, py_db, frame): + return NULL_NET_COMMAND # Not a part of the xml protocol + + def make_evaluation_timeout_msg(self, py_db, expression, thread): + msg = '''pydevd: Evaluating: %s did not finish after %.2f seconds. +This may mean a number of things: +- This evaluation is really slow and this is expected. + In this case it's possible to silence this error by raising the timeout, setting the + PYDEVD_WARN_EVALUATION_TIMEOUT environment variable to a bigger value. + +- The evaluation may need other threads running while it's running: + In this case, you may need to manually let other paused threads continue. + + Alternatively, it's also possible to skip breaking on a particular thread by setting a + `pydev_do_not_trace = True` attribute in the related threading.Thread instance + (if some thread should always be running and no breakpoints are expected to be hit in it). + +- The evaluation is deadlocked: + In this case you may set the PYDEVD_THREAD_DUMP_ON_WARN_EVALUATION_TIMEOUT + environment variable to true so that a thread dump is shown along with this message and + optionally, set the PYDEVD_INTERRUPT_THREAD_TIMEOUT to some value so that the debugger + tries to interrupt the evaluation (if possible) when this happens. +''' % (expression, pydevd_constants.PYDEVD_WARN_EVALUATION_TIMEOUT) + + if pydevd_constants.PYDEVD_THREAD_DUMP_ON_WARN_EVALUATION_TIMEOUT: + stream = StringIO() + pydevd_utils.dump_threads(stream, show_pydevd_threads=False) + msg += '\n\n%s\n' % stream.getvalue() + return self.make_warning_message(msg) + + def make_exit_command(self, py_db): + return NULL_EXIT_COMMAND diff --git a/_pydevd_bundle/pydevd_plugin_utils.py b/_pydevd_bundle/pydevd_plugin_utils.py new file mode 100644 index 0000000..0cd0d76 --- /dev/null +++ b/_pydevd_bundle/pydevd_plugin_utils.py @@ -0,0 +1,91 @@ +import types + +from _pydev_bundle import pydev_log +from _pydevd_bundle import pydevd_trace_api + +try: + from pydevd_plugins import django_debug +except: + django_debug = None + pydev_log.debug('Unable to load django_debug plugin') + +try: + from pydevd_plugins import jinja2_debug +except: + jinja2_debug = None + pydev_log.debug('Unable to load jinja2_debug plugin') + +def load_plugins(): + plugins = [] + if django_debug is not None: + plugins.append(django_debug) + + if jinja2_debug is not None: + plugins.append(jinja2_debug) + return plugins + + +def bind_func_to_method(func, obj, method_name): + bound_method = types.MethodType(func, obj) + + setattr(obj, method_name, bound_method) + return bound_method + + +class PluginManager(object): + + def __init__(self, main_debugger): + self.plugins = load_plugins() + self.active_plugins = [] + self.main_debugger = main_debugger + self.rebind_methods() + + def add_breakpoint(self, func_name, *args, **kwargs): + # add breakpoint for plugin and remember which plugin to use in tracing + for plugin in self.plugins: + if hasattr(plugin, func_name): + func = getattr(plugin, func_name) + result = func(self, *args, **kwargs) + if result: + self.activate(plugin) + + return result + return None + + def activate(self, plugin): + if plugin not in self.active_plugins: + self.active_plugins.append(plugin) + self.rebind_methods() + + def rebind_methods(self): + if len(self.active_plugins) == 0: + self.bind_functions(pydevd_trace_api, getattr, pydevd_trace_api) + elif len(self.active_plugins) == 1: + self.bind_functions(pydevd_trace_api, getattr, self.active_plugins[0]) + else: + self.bind_functions(pydevd_trace_api, create_dispatch, self.active_plugins) + + def bind_functions(self, interface, function_factory, arg): + for name in dir(interface): + func = function_factory(arg, name) + if type(func) == types.FunctionType: + bind_func_to_method(func, self, name) + + +def create_dispatch(obj, name): + def dispatch(self, *args, **kwargs): + result = None + for p in self.active_plugins: + r = getattr(p, name)(self, *args, **kwargs) + if not result: + result = r + return result + return dispatch + + + + + + + + diff --git a/_pydevd_bundle/pydevd_process_net_command.py b/_pydevd_bundle/pydevd_process_net_command.py new file mode 100644 index 0000000..e3afdcd --- /dev/null +++ b/_pydevd_bundle/pydevd_process_net_command.py @@ -0,0 +1,757 @@ +import json +import os +import sys +import traceback + +from _pydev_bundle import pydev_log +from _pydev_bundle.pydev_log import exception as pydev_log_exception +from _pydevd_bundle import pydevd_traceproperty, pydevd_dont_trace, pydevd_utils +from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info +from _pydevd_bundle.pydevd_breakpoints import get_exception_class +from _pydevd_bundle.pydevd_comm import ( + InternalEvaluateConsoleExpression, InternalConsoleGetCompletions, InternalRunCustomOperation, + internal_get_next_statement_targets, internal_get_smart_step_into_variants) +from _pydevd_bundle.pydevd_constants import NEXT_VALUE_SEPARATOR, IS_WINDOWS, NULL +from _pydevd_bundle.pydevd_comm_constants import ID_TO_MEANING, CMD_EXEC_EXPRESSION, CMD_AUTHENTICATE +from _pydevd_bundle.pydevd_api import PyDevdAPI +from io import StringIO +from _pydevd_bundle.pydevd_net_command import NetCommand +from _pydevd_bundle.pydevd_thread_lifecycle import pydevd_find_thread_by_id +import pydevd_file_utils + + +class _PyDevCommandProcessor(object): + + def __init__(self): + self.api = PyDevdAPI() + + def process_net_command(self, py_db, cmd_id, seq, text): + '''Processes a command received from the Java side + + @param cmd_id: the id of the command + @param seq: the sequence of the command + @param text: the text received in the command + ''' + + # We can only proceed if the client is already authenticated or if it's the + # command to authenticate. + if cmd_id != CMD_AUTHENTICATE and not py_db.authentication.is_authenticated(): + cmd = py_db.cmd_factory.make_error_message(seq, 'Client not authenticated.') + py_db.writer.add_command(cmd) + return + + meaning = ID_TO_MEANING[str(cmd_id)] + + # print('Handling %s (%s)' % (meaning, text)) + + method_name = meaning.lower() + + on_command = getattr(self, method_name.lower(), None) + if on_command is None: + # I have no idea what this is all about + cmd = py_db.cmd_factory.make_error_message(seq, "unexpected command " + str(cmd_id)) + py_db.writer.add_command(cmd) + return + + lock = py_db._main_lock + if method_name == 'cmd_thread_dump_to_stderr': + # We can skip the main debugger locks for cases where we know it's not needed. + lock = NULL + + with lock: + try: + cmd = on_command(py_db, cmd_id, seq, text) + if cmd is not None: + py_db.writer.add_command(cmd) + except: + if traceback is not None and sys is not None and pydev_log_exception is not None: + pydev_log_exception() + + stream = StringIO() + traceback.print_exc(file=stream) + cmd = py_db.cmd_factory.make_error_message( + seq, + "Unexpected exception in process_net_command.\nInitial params: %s. Exception: %s" % ( + ((cmd_id, seq, text), stream.getvalue()) + ) + ) + if cmd is not None: + py_db.writer.add_command(cmd) + + def cmd_authenticate(self, py_db, cmd_id, seq, text): + access_token = text + py_db.authentication.login(access_token) + if py_db.authentication.is_authenticated(): + return NetCommand(cmd_id, seq, py_db.authentication.client_access_token) + + return py_db.cmd_factory.make_error_message(seq, 'Client not authenticated.') + + def cmd_run(self, py_db, cmd_id, seq, text): + return self.api.run(py_db) + + def cmd_list_threads(self, py_db, cmd_id, seq, text): + return self.api.list_threads(py_db, seq) + + def cmd_get_completions(self, py_db, cmd_id, seq, text): + # we received some command to get a variable + # the text is: thread_id\tframe_id\tactivation token + thread_id, frame_id, _scope, act_tok = text.split('\t', 3) + + return self.api.request_completions(py_db, seq, thread_id, frame_id, act_tok) + + def cmd_get_thread_stack(self, py_db, cmd_id, seq, text): + # Receives a thread_id and a given timeout, which is the time we should + # wait to the provide the stack if a given thread is still not suspended. + if '\t' in text: + thread_id, timeout = text.split('\t') + timeout = float(timeout) + else: + thread_id = text + timeout = .5 # Default timeout is .5 seconds + + return self.api.request_stack(py_db, seq, thread_id, fmt={}, timeout=timeout) + + def cmd_set_protocol(self, py_db, cmd_id, seq, text): + return self.api.set_protocol(py_db, seq, text.strip()) + + def cmd_thread_suspend(self, py_db, cmd_id, seq, text): + return self.api.request_suspend_thread(py_db, text.strip()) + + def cmd_version(self, py_db, cmd_id, seq, text): + # Default based on server process (although ideally the IDE should + # provide it). + if IS_WINDOWS: + ide_os = 'WINDOWS' + else: + ide_os = 'UNIX' + + # Breakpoints can be grouped by 'LINE' or by 'ID'. + breakpoints_by = 'LINE' + + splitted = text.split('\t') + if len(splitted) == 1: + _local_version = splitted + + elif len(splitted) == 2: + _local_version, ide_os = splitted + + elif len(splitted) == 3: + _local_version, ide_os, breakpoints_by = splitted + + version_msg = self.api.set_ide_os_and_breakpoints_by(py_db, seq, ide_os, breakpoints_by) + + # Enable thread notifications after the version command is completed. + self.api.set_enable_thread_notifications(py_db, True) + + return version_msg + + def cmd_thread_run(self, py_db, cmd_id, seq, text): + return self.api.request_resume_thread(text.strip()) + + def _cmd_step(self, py_db, cmd_id, seq, text): + return self.api.request_step(py_db, text.strip(), cmd_id) + + cmd_step_into = _cmd_step + cmd_step_into_my_code = _cmd_step + cmd_step_over = _cmd_step + cmd_step_over_my_code = _cmd_step + cmd_step_return = _cmd_step + cmd_step_return_my_code = _cmd_step + + def _cmd_set_next(self, py_db, cmd_id, seq, text): + thread_id, line, func_name = text.split('\t', 2) + return self.api.request_set_next(py_db, seq, thread_id, cmd_id, None, line, func_name) + + cmd_run_to_line = _cmd_set_next + cmd_set_next_statement = _cmd_set_next + + def cmd_smart_step_into(self, py_db, cmd_id, seq, text): + thread_id, line_or_bytecode_offset, func_name = text.split('\t', 2) + if line_or_bytecode_offset.startswith('offset='): + # In this case we request the smart step into to stop given the parent frame + # and the location of the parent frame bytecode offset and not just the func_name + # (this implies that `CMD_GET_SMART_STEP_INTO_VARIANTS` was previously used + # to know what are the valid stop points). + + temp = line_or_bytecode_offset[len('offset='):] + if ';' in temp: + offset, child_offset = temp.split(';') + offset = int(offset) + child_offset = int(child_offset) + else: + child_offset = -1 + offset = int(temp) + return self.api.request_smart_step_into(py_db, seq, thread_id, offset, child_offset) + else: + # If the offset wasn't passed, just use the line/func_name to do the stop. + return self.api.request_smart_step_into_by_func_name(py_db, seq, thread_id, line_or_bytecode_offset, func_name) + + def cmd_reload_code(self, py_db, cmd_id, seq, text): + text = text.strip() + if '\t' not in text: + module_name = text.strip() + filename = None + else: + module_name, filename = text.split('\t', 1) + self.api.request_reload_code(py_db, seq, module_name, filename) + + def cmd_change_variable(self, py_db, cmd_id, seq, text): + # the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change + thread_id, frame_id, scope, attr_and_value = text.split('\t', 3) + + tab_index = attr_and_value.rindex('\t') + attr = attr_and_value[0:tab_index].replace('\t', '.') + value = attr_and_value[tab_index + 1:] + self.api.request_change_variable(py_db, seq, thread_id, frame_id, scope, attr, value) + + def cmd_get_variable(self, py_db, cmd_id, seq, text): + # we received some command to get a variable + # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes* + thread_id, frame_id, scopeattrs = text.split('\t', 2) + + if scopeattrs.find('\t') != -1: # there are attributes beyond scope + scope, attrs = scopeattrs.split('\t', 1) + else: + scope, attrs = (scopeattrs, None) + + self.api.request_get_variable(py_db, seq, thread_id, frame_id, scope, attrs) + + def cmd_get_array(self, py_db, cmd_id, seq, text): + # Note: untested and unused in pydev + # we received some command to get an array variable + # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tname\ttemp\troffs\tcoffs\trows\tcols\tformat + roffset, coffset, rows, cols, format, thread_id, frame_id, scopeattrs = text.split('\t', 7) + + if scopeattrs.find('\t') != -1: # there are attributes beyond scope + scope, attrs = scopeattrs.split('\t', 1) + else: + scope, attrs = (scopeattrs, None) + + self.api.request_get_array(py_db, seq, roffset, coffset, rows, cols, format, thread_id, frame_id, scope, attrs) + + def cmd_show_return_values(self, py_db, cmd_id, seq, text): + show_return_values = text.split('\t')[1] + self.api.set_show_return_values(py_db, int(show_return_values) == 1) + + def cmd_load_full_value(self, py_db, cmd_id, seq, text): + # Note: untested and unused in pydev + thread_id, frame_id, scopeattrs = text.split('\t', 2) + vars = scopeattrs.split(NEXT_VALUE_SEPARATOR) + + self.api.request_load_full_value(py_db, seq, thread_id, frame_id, vars) + + def cmd_get_description(self, py_db, cmd_id, seq, text): + # Note: untested and unused in pydev + thread_id, frame_id, expression = text.split('\t', 2) + self.api.request_get_description(py_db, seq, thread_id, frame_id, expression) + + def cmd_get_frame(self, py_db, cmd_id, seq, text): + thread_id, frame_id, scope = text.split('\t', 2) + self.api.request_get_frame(py_db, seq, thread_id, frame_id) + + def cmd_set_break(self, py_db, cmd_id, seq, text): + # func name: 'None': match anything. Empty: match global, specified: only method context. + # command to add some breakpoint. + # text is filename\tline. Add to breakpoints dictionary + suspend_policy = u"NONE" # Can be 'NONE' or 'ALL' + is_logpoint = False + hit_condition = None + if py_db._set_breakpoints_with_id: + try: + try: + breakpoint_id, btype, filename, line, func_name, condition, expression, hit_condition, is_logpoint, suspend_policy = text.split(u'\t', 9) + except ValueError: # not enough values to unpack + # No suspend_policy passed (use default). + breakpoint_id, btype, filename, line, func_name, condition, expression, hit_condition, is_logpoint = text.split(u'\t', 8) + is_logpoint = is_logpoint == u'True' + except ValueError: # not enough values to unpack + breakpoint_id, btype, filename, line, func_name, condition, expression = text.split(u'\t', 6) + + breakpoint_id = int(breakpoint_id) + line = int(line) + + # We must restore new lines and tabs as done in + # AbstractDebugTarget.breakpointAdded + condition = condition.replace(u"@_@NEW_LINE_CHAR@_@", u'\n').\ + replace(u"@_@TAB_CHAR@_@", u'\t').strip() + + expression = expression.replace(u"@_@NEW_LINE_CHAR@_@", u'\n').\ + replace(u"@_@TAB_CHAR@_@", u'\t').strip() + else: + # Note: this else should be removed after PyCharm migrates to setting + # breakpoints by id (and ideally also provides func_name). + btype, filename, line, func_name, suspend_policy, condition, expression = text.split(u'\t', 6) + # If we don't have an id given for each breakpoint, consider + # the id to be the line. + breakpoint_id = line = int(line) + + condition = condition.replace(u"@_@NEW_LINE_CHAR@_@", u'\n'). \ + replace(u"@_@TAB_CHAR@_@", u'\t').strip() + + expression = expression.replace(u"@_@NEW_LINE_CHAR@_@", u'\n'). \ + replace(u"@_@TAB_CHAR@_@", u'\t').strip() + + if condition is not None and (len(condition) <= 0 or condition == u"None"): + condition = None + + if expression is not None and (len(expression) <= 0 or expression == u"None"): + expression = None + + if hit_condition is not None and (len(hit_condition) <= 0 or hit_condition == u"None"): + hit_condition = None + + def on_changed_breakpoint_state(breakpoint_id, add_breakpoint_result): + error_code = add_breakpoint_result.error_code + + translated_line = add_breakpoint_result.translated_line + translated_filename = add_breakpoint_result.translated_filename + msg = '' + if error_code: + + if error_code == self.api.ADD_BREAKPOINT_FILE_NOT_FOUND: + msg = 'pydev debugger: Trying to add breakpoint to file that does not exist: %s (will have no effect).\n' % (translated_filename,) + + elif error_code == self.api.ADD_BREAKPOINT_FILE_EXCLUDED_BY_FILTERS: + msg = 'pydev debugger: Trying to add breakpoint to file that is excluded by filters: %s (will have no effect).\n' % (translated_filename,) + + elif error_code == self.api.ADD_BREAKPOINT_LAZY_VALIDATION: + msg = '' # Ignore this here (if/when loaded, it'll call on_changed_breakpoint_state again accordingly). + + elif error_code == self.api.ADD_BREAKPOINT_INVALID_LINE: + msg = 'pydev debugger: Trying to add breakpoint to line (%s) that is not valid in: %s.\n' % (translated_line, translated_filename,) + + else: + # Shouldn't get here. + msg = 'pydev debugger: Breakpoint not validated (reason unknown -- please report as error): %s (%s).\n' % (translated_filename, translated_line) + + else: + if add_breakpoint_result.original_line != translated_line: + msg = 'pydev debugger (info): Breakpoint in line: %s moved to line: %s (in %s).\n' % (add_breakpoint_result.original_line, translated_line, translated_filename) + + if msg: + py_db.writer.add_command(py_db.cmd_factory.make_warning_message(msg)) + + result = self.api.add_breakpoint( + py_db, self.api.filename_to_str(filename), btype, breakpoint_id, line, condition, func_name, + expression, suspend_policy, hit_condition, is_logpoint, on_changed_breakpoint_state=on_changed_breakpoint_state) + + on_changed_breakpoint_state(breakpoint_id, result) + + def cmd_remove_break(self, py_db, cmd_id, seq, text): + # command to remove some breakpoint + # text is type\file\tid. Remove from breakpoints dictionary + breakpoint_type, filename, breakpoint_id = text.split('\t', 2) + + filename = self.api.filename_to_str(filename) + + try: + breakpoint_id = int(breakpoint_id) + except ValueError: + pydev_log.critical('Error removing breakpoint. Expected breakpoint_id to be an int. Found: %s', breakpoint_id) + + else: + self.api.remove_breakpoint(py_db, filename, breakpoint_type, breakpoint_id) + + def _cmd_exec_or_evaluate_expression(self, py_db, cmd_id, seq, text): + # command to evaluate the given expression + # text is: thread\tstackframe\tLOCAL\texpression + attr_to_set_result = "" + try: + thread_id, frame_id, scope, expression, trim, attr_to_set_result = text.split('\t', 5) + except ValueError: + thread_id, frame_id, scope, expression, trim = text.split('\t', 4) + is_exec = cmd_id == CMD_EXEC_EXPRESSION + trim_if_too_big = int(trim) == 1 + + self.api.request_exec_or_evaluate( + py_db, seq, thread_id, frame_id, expression, is_exec, trim_if_too_big, attr_to_set_result) + + cmd_evaluate_expression = _cmd_exec_or_evaluate_expression + cmd_exec_expression = _cmd_exec_or_evaluate_expression + + def cmd_console_exec(self, py_db, cmd_id, seq, text): + # command to exec expression in console, in case expression is only partially valid 'False' is returned + # text is: thread\tstackframe\tLOCAL\texpression + + thread_id, frame_id, scope, expression = text.split('\t', 3) + self.api.request_console_exec(py_db, seq, thread_id, frame_id, expression) + + def cmd_set_path_mapping_json(self, py_db, cmd_id, seq, text): + ''' + :param text: + Json text. Something as: + + { + "pathMappings": [ + { + "localRoot": "c:/temp", + "remoteRoot": "/usr/temp" + } + ], + "debug": true, + "force": false + } + ''' + as_json = json.loads(text) + force = as_json.get('force', False) + + path_mappings = [] + for pathMapping in as_json.get('pathMappings', []): + localRoot = pathMapping.get('localRoot', '') + remoteRoot = pathMapping.get('remoteRoot', '') + if (localRoot != '') and (remoteRoot != ''): + path_mappings.append((localRoot, remoteRoot)) + + if bool(path_mappings) or force: + pydevd_file_utils.setup_client_server_paths(path_mappings) + + debug = as_json.get('debug', False) + if debug or force: + pydevd_file_utils.DEBUG_CLIENT_SERVER_TRANSLATION = debug + + def cmd_set_py_exception_json(self, py_db, cmd_id, seq, text): + # This API is optional and works 'in bulk' -- it's possible + # to get finer-grained control with CMD_ADD_EXCEPTION_BREAK/CMD_REMOVE_EXCEPTION_BREAK + # which allows setting caught/uncaught per exception, although global settings such as: + # - skip_on_exceptions_thrown_in_same_context + # - ignore_exceptions_thrown_in_lines_with_ignore_exception + # must still be set through this API (before anything else as this clears all existing + # exception breakpoints). + try: + py_db.break_on_uncaught_exceptions = {} + py_db.break_on_caught_exceptions = {} + py_db.break_on_user_uncaught_exceptions = {} + + as_json = json.loads(text) + break_on_uncaught = as_json.get('break_on_uncaught', False) + break_on_caught = as_json.get('break_on_caught', False) + break_on_user_caught = as_json.get('break_on_user_caught', False) + py_db.skip_on_exceptions_thrown_in_same_context = as_json.get('skip_on_exceptions_thrown_in_same_context', False) + py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception = as_json.get('ignore_exceptions_thrown_in_lines_with_ignore_exception', False) + ignore_libraries = as_json.get('ignore_libraries', False) + exception_types = as_json.get('exception_types', []) + + for exception_type in exception_types: + if not exception_type: + continue + + py_db.add_break_on_exception( + exception_type, + condition=None, + expression=None, + notify_on_handled_exceptions=break_on_caught, + notify_on_unhandled_exceptions=break_on_uncaught, + notify_on_user_unhandled_exceptions=break_on_user_caught, + notify_on_first_raise_only=True, + ignore_libraries=ignore_libraries, + ) + + py_db.on_breakpoints_changed() + except: + pydev_log.exception("Error when setting exception list. Received: %s", text) + + def cmd_set_py_exception(self, py_db, cmd_id, seq, text): + # DEPRECATED. Use cmd_set_py_exception_json instead. + try: + splitted = text.split(';') + py_db.break_on_uncaught_exceptions = {} + py_db.break_on_caught_exceptions = {} + py_db.break_on_user_uncaught_exceptions = {} + if len(splitted) >= 5: + if splitted[0] == 'true': + break_on_uncaught = True + else: + break_on_uncaught = False + + if splitted[1] == 'true': + break_on_caught = True + else: + break_on_caught = False + + if splitted[2] == 'true': + py_db.skip_on_exceptions_thrown_in_same_context = True + else: + py_db.skip_on_exceptions_thrown_in_same_context = False + + if splitted[3] == 'true': + py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception = True + else: + py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception = False + + if splitted[4] == 'true': + ignore_libraries = True + else: + ignore_libraries = False + + for exception_type in splitted[5:]: + exception_type = exception_type.strip() + if not exception_type: + continue + + py_db.add_break_on_exception( + exception_type, + condition=None, + expression=None, + notify_on_handled_exceptions=break_on_caught, + notify_on_unhandled_exceptions=break_on_uncaught, + notify_on_user_unhandled_exceptions=False, # TODO (not currently supported in this API). + notify_on_first_raise_only=True, + ignore_libraries=ignore_libraries, + ) + else: + pydev_log.exception("Expected to have at least 5 ';' separated items. Received: %s", text) + + except: + pydev_log.exception("Error when setting exception list. Received: %s", text) + + def _load_source(self, py_db, cmd_id, seq, text): + filename = text + filename = self.api.filename_to_str(filename) + self.api.request_load_source(py_db, seq, filename) + + cmd_load_source = _load_source + cmd_get_file_contents = _load_source + + def cmd_load_source_from_frame_id(self, py_db, cmd_id, seq, text): + frame_id = text + self.api.request_load_source_from_frame_id(py_db, seq, frame_id) + + def cmd_set_property_trace(self, py_db, cmd_id, seq, text): + # Command which receives whether to trace property getter/setter/deleter + # text is feature_state(true/false);disable_getter/disable_setter/disable_deleter + if text: + splitted = text.split(';') + if len(splitted) >= 3: + if not py_db.disable_property_trace and splitted[0] == 'true': + # Replacing property by custom property only when the debugger starts + pydevd_traceproperty.replace_builtin_property() + py_db.disable_property_trace = True + # Enable/Disable tracing of the property getter + if splitted[1] == 'true': + py_db.disable_property_getter_trace = True + else: + py_db.disable_property_getter_trace = False + # Enable/Disable tracing of the property setter + if splitted[2] == 'true': + py_db.disable_property_setter_trace = True + else: + py_db.disable_property_setter_trace = False + # Enable/Disable tracing of the property deleter + if splitted[3] == 'true': + py_db.disable_property_deleter_trace = True + else: + py_db.disable_property_deleter_trace = False + + def cmd_add_exception_break(self, py_db, cmd_id, seq, text): + # Note that this message has some idiosyncrasies... + # + # notify_on_handled_exceptions can be 0, 1 or 2 + # 0 means we should not stop on handled exceptions. + # 1 means we should stop on handled exceptions showing it on all frames where the exception passes. + # 2 means we should stop on handled exceptions but we should only notify about it once. + # + # To ignore_libraries properly, besides setting ignore_libraries to 1, the IDE_PROJECT_ROOTS environment + # variable must be set (so, we'll ignore anything not below IDE_PROJECT_ROOTS) -- this is not ideal as + # the environment variable may not be properly set if it didn't start from the debugger (we should + # create a custom message for that). + # + # There are 2 global settings which can only be set in CMD_SET_PY_EXCEPTION. Namely: + # + # py_db.skip_on_exceptions_thrown_in_same_context + # - If True, we should only show the exception in a caller, not where it was first raised. + # + # py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception + # - If True exceptions thrown in lines with '@IgnoreException' will not be shown. + + condition = "" + expression = "" + if text.find('\t') != -1: + try: + exception, condition, expression, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text.split('\t', 5) + except: + exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text.split('\t', 3) + else: + exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text, 0, 0, 0 + + condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').replace("@_@TAB_CHAR@_@", '\t').strip() + + if condition is not None and (len(condition) == 0 or condition == "None"): + condition = None + + expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').replace("@_@TAB_CHAR@_@", '\t').strip() + + if expression is not None and (len(expression) == 0 or expression == "None"): + expression = None + + if exception.find('-') != -1: + breakpoint_type, exception = exception.split('-') + else: + breakpoint_type = 'python' + + if breakpoint_type == 'python': + self.api.add_python_exception_breakpoint( + py_db, exception, condition, expression, + notify_on_handled_exceptions=int(notify_on_handled_exceptions) > 0, + notify_on_unhandled_exceptions=int(notify_on_unhandled_exceptions) == 1, + notify_on_user_unhandled_exceptions=0, # TODO (not currently supported in this API). + notify_on_first_raise_only=int(notify_on_handled_exceptions) == 2, + ignore_libraries=int(ignore_libraries) > 0, + ) + else: + self.api.add_plugins_exception_breakpoint(py_db, breakpoint_type, exception) + + def cmd_remove_exception_break(self, py_db, cmd_id, seq, text): + exception = text + if exception.find('-') != -1: + exception_type, exception = exception.split('-') + else: + exception_type = 'python' + + if exception_type == 'python': + self.api.remove_python_exception_breakpoint(py_db, exception) + else: + self.api.remove_plugins_exception_breakpoint(py_db, exception_type, exception) + + def cmd_add_django_exception_break(self, py_db, cmd_id, seq, text): + self.api.add_plugins_exception_breakpoint(py_db, breakpoint_type='django', exception=text) + + def cmd_remove_django_exception_break(self, py_db, cmd_id, seq, text): + self.api.remove_plugins_exception_breakpoint(py_db, exception_type='django', exception=text) + + def cmd_evaluate_console_expression(self, py_db, cmd_id, seq, text): + # Command which takes care for the debug console communication + if text != "": + thread_id, frame_id, console_command = text.split('\t', 2) + console_command, line = console_command.split('\t') + + if console_command == 'EVALUATE': + int_cmd = InternalEvaluateConsoleExpression( + seq, thread_id, frame_id, line, buffer_output=True) + + elif console_command == 'EVALUATE_UNBUFFERED': + int_cmd = InternalEvaluateConsoleExpression( + seq, thread_id, frame_id, line, buffer_output=False) + + elif console_command == 'GET_COMPLETIONS': + int_cmd = InternalConsoleGetCompletions(seq, thread_id, frame_id, line) + + else: + raise ValueError('Unrecognized command: %s' % (console_command,)) + + py_db.post_internal_command(int_cmd, thread_id) + + def cmd_run_custom_operation(self, py_db, cmd_id, seq, text): + # Command which runs a custom operation + if text != "": + try: + location, custom = text.split('||', 1) + except: + sys.stderr.write('Custom operation now needs a || separator. Found: %s\n' % (text,)) + raise + + thread_id, frame_id, scopeattrs = location.split('\t', 2) + + if scopeattrs.find('\t') != -1: # there are attributes beyond scope + scope, attrs = scopeattrs.split('\t', 1) + else: + scope, attrs = (scopeattrs, None) + + # : style: EXECFILE or EXEC + # : encoded_code_or_file: file to execute or code + # : fname: name of function to be executed in the resulting namespace + style, encoded_code_or_file, fnname = custom.split('\t', 3) + int_cmd = InternalRunCustomOperation(seq, thread_id, frame_id, scope, attrs, + style, encoded_code_or_file, fnname) + py_db.post_internal_command(int_cmd, thread_id) + + def cmd_ignore_thrown_exception_at(self, py_db, cmd_id, seq, text): + if text: + replace = 'REPLACE:' # Not all 3.x versions support u'REPLACE:', so, doing workaround. + if text.startswith(replace): + text = text[8:] + py_db.filename_to_lines_where_exceptions_are_ignored.clear() + + if text: + for line in text.split('||'): # Can be bulk-created (one in each line) + original_filename, line_number = line.split('|') + original_filename = self.api.filename_to_server(original_filename) + + canonical_normalized_filename = pydevd_file_utils.canonical_normalized_path(original_filename) + absolute_filename = pydevd_file_utils.absolute_path(original_filename) + + if os.path.exists(absolute_filename): + lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored.get(canonical_normalized_filename) + if lines_ignored is None: + lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored[canonical_normalized_filename] = {} + lines_ignored[int(line_number)] = 1 + else: + sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\ + ' on file that does not exist: %s (will have no effect)\n' % (absolute_filename,)) + + def cmd_enable_dont_trace(self, py_db, cmd_id, seq, text): + if text: + true_str = 'true' # Not all 3.x versions support u'str', so, doing workaround. + mode = text.strip() == true_str + pydevd_dont_trace.trace_filter(mode) + + def cmd_redirect_output(self, py_db, cmd_id, seq, text): + if text: + py_db.enable_output_redirection('STDOUT' in text, 'STDERR' in text) + + def cmd_get_next_statement_targets(self, py_db, cmd_id, seq, text): + thread_id, frame_id = text.split('\t', 1) + + py_db.post_method_as_internal_command( + thread_id, internal_get_next_statement_targets, seq, thread_id, frame_id) + + def cmd_get_smart_step_into_variants(self, py_db, cmd_id, seq, text): + thread_id, frame_id, start_line, end_line = text.split('\t', 3) + + py_db.post_method_as_internal_command( + thread_id, internal_get_smart_step_into_variants, seq, thread_id, frame_id, start_line, end_line, set_additional_thread_info=set_additional_thread_info) + + def cmd_set_project_roots(self, py_db, cmd_id, seq, text): + self.api.set_project_roots(py_db, text.split(u'\t')) + + def cmd_thread_dump_to_stderr(self, py_db, cmd_id, seq, text): + pydevd_utils.dump_threads() + + def cmd_stop_on_start(self, py_db, cmd_id, seq, text): + if text.strip() in ('True', 'true', '1'): + self.api.stop_on_entry() + + def cmd_pydevd_json_config(self, py_db, cmd_id, seq, text): + # Expected to receive a json string as: + # { + # 'skip_suspend_on_breakpoint_exception': [], + # 'skip_print_breakpoint_exception': [], + # 'multi_threads_single_notification': bool, + # } + msg = json.loads(text.strip()) + if 'skip_suspend_on_breakpoint_exception' in msg: + py_db.skip_suspend_on_breakpoint_exception = tuple( + get_exception_class(x) for x in msg['skip_suspend_on_breakpoint_exception']) + + if 'skip_print_breakpoint_exception' in msg: + py_db.skip_print_breakpoint_exception = tuple( + get_exception_class(x) for x in msg['skip_print_breakpoint_exception']) + + if 'multi_threads_single_notification' in msg: + py_db.multi_threads_single_notification = msg['multi_threads_single_notification'] + + def cmd_get_exception_details(self, py_db, cmd_id, seq, text): + thread_id = text + t = pydevd_find_thread_by_id(thread_id) + frame = None + if t and not getattr(t, 'pydev_do_not_trace', None): + additional_info = set_additional_thread_info(t) + frame = additional_info.get_topmost_frame(t) + try: + return py_db.cmd_factory.make_get_exception_details_message(py_db, seq, thread_id, frame) + finally: + frame = None + t = None + + +process_net_command = _PyDevCommandProcessor().process_net_command + diff --git a/_pydevd_bundle/pydevd_process_net_command_json.py b/_pydevd_bundle/pydevd_process_net_command_json.py new file mode 100644 index 0000000..c305c6d --- /dev/null +++ b/_pydevd_bundle/pydevd_process_net_command_json.py @@ -0,0 +1,1311 @@ +import itertools +import json +import linecache +import os +import platform +import sys +from functools import partial + +import pydevd_file_utils +from _pydev_bundle import pydev_log +from _pydevd_bundle._debug_adapter import pydevd_base_schema, pydevd_schema +from _pydevd_bundle._debug_adapter.pydevd_schema import ( + CompletionsResponseBody, EvaluateResponseBody, ExceptionOptions, + GotoTargetsResponseBody, ModulesResponseBody, ProcessEventBody, + ProcessEvent, Scope, ScopesResponseBody, SetExpressionResponseBody, + SetVariableResponseBody, SourceBreakpoint, SourceResponseBody, + VariablesResponseBody, SetBreakpointsResponseBody, Response, + Capabilities, PydevdAuthorizeRequest, Request, + StepInTargetsResponseBody, SetFunctionBreakpointsResponseBody, BreakpointEvent, + BreakpointEventBody) +from _pydevd_bundle.pydevd_api import PyDevdAPI +from _pydevd_bundle.pydevd_breakpoints import get_exception_class, FunctionBreakpoint +from _pydevd_bundle.pydevd_comm_constants import ( + CMD_PROCESS_EVENT, CMD_RETURN, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO, + CMD_STEP_INTO_MY_CODE, CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE, file_system_encoding, + CMD_STEP_RETURN_MY_CODE, CMD_STEP_RETURN) +from _pydevd_bundle.pydevd_filtering import ExcludeFilter +from _pydevd_bundle.pydevd_json_debug_options import _extract_debug_options, DebugOptions +from _pydevd_bundle.pydevd_net_command import NetCommand +from _pydevd_bundle.pydevd_utils import convert_dap_log_message_to_expression, ScopeRequest +from _pydevd_bundle.pydevd_constants import (PY_IMPL_NAME, DebugInfoHolder, PY_VERSION_STR, + PY_IMPL_VERSION_STR, IS_64BIT_PROCESS) +from _pydevd_bundle.pydevd_trace_dispatch import USING_CYTHON +from _pydevd_frame_eval.pydevd_frame_eval_main import USING_FRAME_EVAL +from _pydevd_bundle.pydevd_comm import internal_get_step_in_targets_json +from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info +from _pydevd_bundle.pydevd_thread_lifecycle import pydevd_find_thread_by_id + + +def _convert_rules_to_exclude_filters(rules, on_error): + exclude_filters = [] + if not isinstance(rules, list): + on_error('Invalid "rules" (expected list of dicts). Found: %s' % (rules,)) + + else: + directory_exclude_filters = [] + module_exclude_filters = [] + glob_exclude_filters = [] + + for rule in rules: + if not isinstance(rule, dict): + on_error('Invalid "rules" (expected list of dicts). Found: %s' % (rules,)) + continue + + include = rule.get('include') + if include is None: + on_error('Invalid "rule" (expected dict with "include"). Found: %s' % (rule,)) + continue + + path = rule.get('path') + module = rule.get('module') + if path is None and module is None: + on_error('Invalid "rule" (expected dict with "path" or "module"). Found: %s' % (rule,)) + continue + + if path is not None: + glob_pattern = path + if '*' not in path and '?' not in path: + if os.path.isdir(glob_pattern): + # If a directory was specified, add a '/**' + # to be consistent with the glob pattern required + # by pydevd. + if not glob_pattern.endswith('/') and not glob_pattern.endswith('\\'): + glob_pattern += '/' + glob_pattern += '**' + directory_exclude_filters.append(ExcludeFilter(glob_pattern, not include, True)) + else: + glob_exclude_filters.append(ExcludeFilter(glob_pattern, not include, True)) + + elif module is not None: + module_exclude_filters.append(ExcludeFilter(module, not include, False)) + + else: + on_error('Internal error: expected path or module to be specified.') + + # Note that we have to sort the directory/module exclude filters so that the biggest + # paths match first. + # i.e.: if we have: + # /sub1/sub2/sub3 + # a rule with /sub1/sub2 would match before a rule only with /sub1. + directory_exclude_filters = sorted(directory_exclude_filters, key=lambda exclude_filter:-len(exclude_filter.name)) + module_exclude_filters = sorted(module_exclude_filters, key=lambda exclude_filter:-len(exclude_filter.name)) + exclude_filters = directory_exclude_filters + glob_exclude_filters + module_exclude_filters + + return exclude_filters + + +class IDMap(object): + + def __init__(self): + self._value_to_key = {} + self._key_to_value = {} + self._next_id = partial(next, itertools.count(0)) + + def obtain_value(self, key): + return self._key_to_value[key] + + def obtain_key(self, value): + try: + key = self._value_to_key[value] + except KeyError: + key = self._next_id() + self._key_to_value[key] = value + self._value_to_key[value] = key + return key + + +class PyDevJsonCommandProcessor(object): + + def __init__(self, from_json): + self.from_json = from_json + self.api = PyDevdAPI() + self._options = DebugOptions() + self._next_breakpoint_id = partial(next, itertools.count(0)) + self._goto_targets_map = IDMap() + self._launch_or_attach_request_done = False + + def process_net_command_json(self, py_db, json_contents, send_response=True): + ''' + Processes a debug adapter protocol json command. + ''' + + DEBUG = False + + try: + if isinstance(json_contents, bytes): + json_contents = json_contents.decode('utf-8') + + request = self.from_json(json_contents, update_ids_from_dap=True) + except Exception as e: + try: + loaded_json = json.loads(json_contents) + request = Request(loaded_json.get('command', ''), loaded_json['seq']) + except: + # There's not much we can do in this case... + pydev_log.exception('Error loading json: %s', json_contents) + return + + error_msg = str(e) + if error_msg.startswith("'") and error_msg.endswith("'"): + error_msg = error_msg[1:-1] + + # This means a failure processing the request (but we were able to load the seq, + # so, answer with a failure response). + def on_request(py_db, request): + error_response = { + 'type': 'response', + 'request_seq': request.seq, + 'success': False, + 'command': request.command, + 'message': error_msg, + } + return NetCommand(CMD_RETURN, 0, error_response, is_json=True) + + else: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + pydev_log.info('Process %s: %s\n' % ( + request.__class__.__name__, json.dumps(request.to_dict(update_ids_to_dap=True), indent=4, sort_keys=True),)) + + assert request.type == 'request' + method_name = 'on_%s_request' % (request.command.lower(),) + on_request = getattr(self, method_name, None) + if on_request is None: + print('Unhandled: %s not available in PyDevJsonCommandProcessor.\n' % (method_name,)) + return + + if DEBUG: + print('Handled in pydevd: %s (in PyDevJsonCommandProcessor).\n' % (method_name,)) + + with py_db._main_lock: + if request.__class__ == PydevdAuthorizeRequest: + authorize_request = request # : :type authorize_request: PydevdAuthorizeRequest + access_token = authorize_request.arguments.debugServerAccessToken + py_db.authentication.login(access_token) + + if not py_db.authentication.is_authenticated(): + response = Response( + request.seq, success=False, command=request.command, message='Client not authenticated.', body={}) + cmd = NetCommand(CMD_RETURN, 0, response, is_json=True) + py_db.writer.add_command(cmd) + return + + cmd = on_request(py_db, request) + if cmd is not None and send_response: + py_db.writer.add_command(cmd) + + def on_pydevdauthorize_request(self, py_db, request): + client_access_token = py_db.authentication.client_access_token + body = {'clientAccessToken': None} + if client_access_token: + body['clientAccessToken'] = client_access_token + + response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_initialize_request(self, py_db, request): + body = Capabilities( + # Supported. + supportsConfigurationDoneRequest=True, + supportsConditionalBreakpoints=True, + supportsHitConditionalBreakpoints=True, + supportsEvaluateForHovers=True, + supportsSetVariable=True, + supportsGotoTargetsRequest=True, + supportsCompletionsRequest=True, + supportsModulesRequest=True, + supportsExceptionOptions=True, + supportsValueFormattingOptions=True, + supportsExceptionInfoRequest=True, + supportTerminateDebuggee=True, + supportsDelayedStackTraceLoading=True, + supportsLogPoints=True, + supportsSetExpression=True, + supportsTerminateRequest=True, + supportsClipboardContext=True, + supportsFunctionBreakpoints=True, + + exceptionBreakpointFilters=[ + {'filter': 'raised', 'label': 'Raised Exceptions', 'default': False}, + {'filter': 'uncaught', 'label': 'Uncaught Exceptions', 'default': True}, + {"filter": "userUnhandled", "label": "User Uncaught Exceptions", "default": False}, + ], + + # Not supported. + supportsStepBack=False, + supportsRestartFrame=False, + supportsStepInTargetsRequest=True, + supportsRestartRequest=False, + supportsLoadedSourcesRequest=False, + supportsTerminateThreadsRequest=False, + supportsDataBreakpoints=False, + supportsReadMemoryRequest=False, + supportsDisassembleRequest=False, + additionalModuleColumns=[], + completionTriggerCharacters=[], + supportedChecksumAlgorithms=[], + ).to_dict() + + # Non-standard capabilities/info below. + body['supportsDebuggerProperties'] = True + + body['pydevd'] = pydevd_info = {} + pydevd_info['processId'] = os.getpid() + self.api.notify_initialize(py_db) + response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_configurationdone_request(self, py_db, request): + ''' + :param ConfigurationDoneRequest request: + ''' + if not self._launch_or_attach_request_done: + pydev_log.critical('Missing launch request or attach request before configuration done request.') + + self.api.run(py_db) + self.api.notify_configuration_done(py_db) + + configuration_done_response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, configuration_done_response, is_json=True) + + def on_threads_request(self, py_db, request): + ''' + :param ThreadsRequest request: + ''' + return self.api.list_threads(py_db, request.seq) + + def on_terminate_request(self, py_db, request): + ''' + :param TerminateRequest request: + ''' + self._request_terminate_process(py_db) + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def _request_terminate_process(self, py_db): + self.api.request_terminate_process(py_db) + + def on_completions_request(self, py_db, request): + ''' + :param CompletionsRequest request: + ''' + arguments = request.arguments # : :type arguments: CompletionsArguments + seq = request.seq + text = arguments.text + frame_id = arguments.frameId + thread_id = py_db.suspended_frames_manager.get_thread_id_for_variable_reference( + frame_id) + + if thread_id is None: + body = CompletionsResponseBody([]) + variables_response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': body, + 'success': False, + 'message': 'Thread to get completions seems to have resumed already.' + }) + return NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + + # Note: line and column are 1-based (convert to 0-based for pydevd). + column = arguments.column - 1 + + if arguments.line is None: + # line is optional + line = -1 + else: + line = arguments.line - 1 + + self.api.request_completions(py_db, seq, thread_id, frame_id, text, line=line, column=column) + + def _resolve_remote_root(self, local_root, remote_root): + if remote_root == '.': + cwd = os.getcwd() + append_pathsep = local_root.endswith('\\') or local_root.endswith('/') + return cwd + (os.path.sep if append_pathsep else '') + return remote_root + + def _set_debug_options(self, py_db, args, start_reason): + rules = args.get('rules') + stepping_resumes_all_threads = args.get('steppingResumesAllThreads', True) + self.api.set_stepping_resumes_all_threads(py_db, stepping_resumes_all_threads) + + terminate_child_processes = args.get('terminateChildProcesses', True) + self.api.set_terminate_child_processes(py_db, terminate_child_processes) + + variable_presentation = args.get('variablePresentation', None) + if isinstance(variable_presentation, dict): + + def get_variable_presentation(setting, default): + value = variable_presentation.get(setting, default) + if value not in ('group', 'inline', 'hide'): + pydev_log.info( + 'The value set for "%s" (%s) in the variablePresentation is not valid. Valid values are: "group", "inline", "hide"' % ( + setting, value,)) + value = default + + return value + + default = get_variable_presentation('all', 'group') + + special_presentation = get_variable_presentation('special', default) + function_presentation = get_variable_presentation('function', default) + class_presentation = get_variable_presentation('class', default) + protected_presentation = get_variable_presentation('protected', default) + + self.api.set_variable_presentation(py_db, self.api.VariablePresentation( + special_presentation, + function_presentation, + class_presentation, + protected_presentation + )) + + exclude_filters = [] + + if rules is not None: + exclude_filters = _convert_rules_to_exclude_filters( + rules, lambda msg: self.api.send_error_message(py_db, msg)) + + self.api.set_exclude_filters(py_db, exclude_filters) + + debug_options = _extract_debug_options( + args.get('options'), + args.get('debugOptions'), + ) + self._options.update_fom_debug_options(debug_options) + self._options.update_from_args(args) + + self.api.set_use_libraries_filter(py_db, self._options.just_my_code) + + path_mappings = [] + for pathMapping in args.get('pathMappings', []): + localRoot = pathMapping.get('localRoot', '') + remoteRoot = pathMapping.get('remoteRoot', '') + remoteRoot = self._resolve_remote_root(localRoot, remoteRoot) + if (localRoot != '') and (remoteRoot != ''): + path_mappings.append((localRoot, remoteRoot)) + + if bool(path_mappings): + pydevd_file_utils.setup_client_server_paths(path_mappings) + + resolve_symlinks = args.get('resolveSymlinks', None) + if resolve_symlinks is not None: + pydevd_file_utils.set_resolve_symlinks(resolve_symlinks) + + redirecting = args.get("isOutputRedirected") + if self._options.redirect_output: + py_db.enable_output_redirection(True, True) + redirecting = True + else: + py_db.enable_output_redirection(False, False) + + py_db.is_output_redirected = redirecting + + self.api.set_show_return_values(py_db, self._options.show_return_value) + + if not self._options.break_system_exit_zero: + ignore_system_exit_codes = [0, None] + if self._options.django_debug or self._options.flask_debug: + ignore_system_exit_codes += [3] + + self.api.set_ignore_system_exit_codes(py_db, ignore_system_exit_codes) + + auto_reload = args.get('autoReload', {}) + if not isinstance(auto_reload, dict): + pydev_log.info('Expected autoReload to be a dict. Received: %s' % (auto_reload,)) + auto_reload = {} + + enable_auto_reload = auto_reload.get('enable', False) + watch_dirs = auto_reload.get('watchDirectories') + if not watch_dirs: + watch_dirs = [] + # Note: by default this is no longer done because on some cases there are entries in the PYTHONPATH + # such as the home directory or /python/x64, where the site packages are in /python/x64/libs, so, + # we only watch the current working directory as well as executed script. + # check = getattr(sys, 'path', [])[:] + # # By default only watch directories that are in the project roots / + # # program dir (if available), sys.argv[0], as well as the current dir (we don't want to + # # listen to the whole site-packages by default as it can be huge). + # watch_dirs = [pydevd_file_utils.absolute_path(w) for w in check] + # watch_dirs = [w for w in watch_dirs if py_db.in_project_roots_filename_uncached(w) and os.path.isdir(w)] + + program = args.get('program') + if program: + if os.path.isdir(program): + watch_dirs.append(program) + else: + watch_dirs.append(os.path.dirname(program)) + watch_dirs.append(os.path.abspath('.')) + + argv = getattr(sys, 'argv', []) + if argv: + f = argv[0] + if f: # argv[0] could be None (https://github.com/microsoft/debugpy/issues/987) + if os.path.isdir(f): + watch_dirs.append(f) + else: + watch_dirs.append(os.path.dirname(f)) + + if not isinstance(watch_dirs, (list, set, tuple)): + watch_dirs = (watch_dirs,) + new_watch_dirs = set() + for w in watch_dirs: + try: + new_watch_dirs.add(pydevd_file_utils.get_path_with_real_case(pydevd_file_utils.absolute_path(w))) + except Exception: + pydev_log.exception('Error adding watch dir: %s', w) + watch_dirs = new_watch_dirs + + poll_target_time = auto_reload.get('pollingInterval', 1) + exclude_patterns = auto_reload.get('exclude', ('**/.git/**', '**/__pycache__/**', '**/node_modules/**', '**/.metadata/**', '**/site-packages/**')) + include_patterns = auto_reload.get('include', ('**/*.py', '**/*.pyw')) + self.api.setup_auto_reload_watcher( + py_db, enable_auto_reload, watch_dirs, poll_target_time, exclude_patterns, include_patterns) + + if self._options.stop_on_entry and start_reason == 'launch': + self.api.stop_on_entry() + + self.api.set_gui_event_loop(py_db, self._options.gui_event_loop) + + def _send_process_event(self, py_db, start_method): + argv = getattr(sys, 'argv', []) + if len(argv) > 0: + name = argv[0] + else: + name = '' + + if isinstance(name, bytes): + name = name.decode(file_system_encoding, 'replace') + name = name.encode('utf-8') + + body = ProcessEventBody( + name=name, + systemProcessId=os.getpid(), + isLocalProcess=True, + startMethod=start_method, + ) + event = ProcessEvent(body) + py_db.writer.add_command(NetCommand(CMD_PROCESS_EVENT, 0, event, is_json=True)) + + def _handle_launch_or_attach_request(self, py_db, request, start_reason): + self._send_process_event(py_db, start_reason) + self._launch_or_attach_request_done = True + self.api.set_enable_thread_notifications(py_db, True) + self._set_debug_options(py_db, request.arguments.kwargs, start_reason=start_reason) + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_launch_request(self, py_db, request): + ''' + :param LaunchRequest request: + ''' + return self._handle_launch_or_attach_request(py_db, request, start_reason='launch') + + def on_attach_request(self, py_db, request): + ''' + :param AttachRequest request: + ''' + return self._handle_launch_or_attach_request(py_db, request, start_reason='attach') + + def on_pause_request(self, py_db, request): + ''' + :param PauseRequest request: + ''' + arguments = request.arguments # : :type arguments: PauseArguments + thread_id = arguments.threadId + + self.api.request_suspend_thread(py_db, thread_id=thread_id) + + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_continue_request(self, py_db, request): + ''' + :param ContinueRequest request: + ''' + arguments = request.arguments # : :type arguments: ContinueArguments + thread_id = arguments.threadId + + def on_resumed(): + body = {'allThreadsContinued': thread_id == '*'} + response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + cmd = NetCommand(CMD_RETURN, 0, response, is_json=True) + py_db.writer.add_command(cmd) + + # Only send resumed notification when it has actually resumed! + # (otherwise the user could send a continue, receive the notification and then + # request a new pause which would be paused without sending any notification as + # it didn't really run in the first place). + py_db.threads_suspended_single_notification.add_on_resumed_callback(on_resumed) + self.api.request_resume_thread(thread_id) + + def on_next_request(self, py_db, request): + ''' + :param NextRequest request: + ''' + arguments = request.arguments # : :type arguments: NextArguments + thread_id = arguments.threadId + + if py_db.get_use_libraries_filter(): + step_cmd_id = CMD_STEP_OVER_MY_CODE + else: + step_cmd_id = CMD_STEP_OVER + + self.api.request_step(py_db, thread_id, step_cmd_id) + + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_stepin_request(self, py_db, request): + ''' + :param StepInRequest request: + ''' + arguments = request.arguments # : :type arguments: StepInArguments + thread_id = arguments.threadId + + target_id = arguments.targetId + if target_id is not None: + thread = pydevd_find_thread_by_id(thread_id) + info = set_additional_thread_info(thread) + target_id_to_smart_step_into_variant = info.target_id_to_smart_step_into_variant + if not target_id_to_smart_step_into_variant: + variables_response = pydevd_base_schema.build_response( + request, + kwargs={ + 'success': False, + 'message': 'Unable to step into target (no targets are saved in the thread info).' + }) + return NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + + variant = target_id_to_smart_step_into_variant.get(target_id) + if variant is not None: + parent = variant.parent + if parent is not None: + self.api.request_smart_step_into(py_db, request.seq, thread_id, parent.offset, variant.offset) + else: + self.api.request_smart_step_into(py_db, request.seq, thread_id, variant.offset, -1) + else: + variables_response = pydevd_base_schema.build_response( + request, + kwargs={ + 'success': False, + 'message': 'Unable to find step into target %s. Available targets: %s' % ( + target_id, target_id_to_smart_step_into_variant) + }) + return NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + + else: + if py_db.get_use_libraries_filter(): + step_cmd_id = CMD_STEP_INTO_MY_CODE + else: + step_cmd_id = CMD_STEP_INTO + + self.api.request_step(py_db, thread_id, step_cmd_id) + + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_stepintargets_request(self, py_db, request): + ''' + :param StepInTargetsRequest request: + ''' + frame_id = request.arguments.frameId + thread_id = py_db.suspended_frames_manager.get_thread_id_for_variable_reference( + frame_id) + + if thread_id is None: + body = StepInTargetsResponseBody([]) + variables_response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': body, + 'success': False, + 'message': 'Unable to get thread_id from frame_id (thread to get step in targets seems to have resumed already).' + }) + return NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + + py_db.post_method_as_internal_command( + thread_id, internal_get_step_in_targets_json, request.seq, thread_id, frame_id, request, set_additional_thread_info) + + def on_stepout_request(self, py_db, request): + ''' + :param StepOutRequest request: + ''' + arguments = request.arguments # : :type arguments: StepOutArguments + thread_id = arguments.threadId + + if py_db.get_use_libraries_filter(): + step_cmd_id = CMD_STEP_RETURN_MY_CODE + else: + step_cmd_id = CMD_STEP_RETURN + + self.api.request_step(py_db, thread_id, step_cmd_id) + + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def _get_hit_condition_expression(self, hit_condition): + '''Following hit condition values are supported + + * x or == x when breakpoint is hit x times + * >= x when breakpoint is hit more than or equal to x times + * % x when breakpoint is hit multiple of x times + + Returns '@HIT@ == x' where @HIT@ will be replaced by number of hits + ''' + if not hit_condition: + return None + + expr = hit_condition.strip() + try: + int(expr) + return '@HIT@ == {}'.format(expr) + except ValueError: + pass + + if expr.startswith('%'): + return '@HIT@ {} == 0'.format(expr) + + if expr.startswith('==') or \ + expr.startswith('>') or \ + expr.startswith('<'): + return '@HIT@ {}'.format(expr) + + return hit_condition + + def on_disconnect_request(self, py_db, request): + ''' + :param DisconnectRequest request: + ''' + if request.arguments.terminateDebuggee: + self._request_terminate_process(py_db) + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + self._launch_or_attach_request_done = False + py_db.enable_output_redirection(False, False) + self.api.request_disconnect(py_db, resume_threads=True) + + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def _verify_launch_or_attach_done(self, request): + if not self._launch_or_attach_request_done: + # Note that to validate the breakpoints we need the launch request to be done already + # (otherwise the filters wouldn't be set for the breakpoint validation). + if request.command == 'setFunctionBreakpoints': + body = SetFunctionBreakpointsResponseBody([]) + else: + body = SetBreakpointsResponseBody([]) + response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': body, + 'success': False, + 'message': 'Breakpoints may only be set after the launch request is received.' + }) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_setfunctionbreakpoints_request(self, py_db, request): + ''' + :param SetFunctionBreakpointsRequest request: + ''' + response = self._verify_launch_or_attach_done(request) + if response is not None: + return response + + arguments = request.arguments # : :type arguments: SetFunctionBreakpointsArguments + function_breakpoints = [] + suspend_policy = 'ALL' + + # Not currently covered by the DAP. + is_logpoint = False + expression = None + + breakpoints_set = [] + for bp in arguments.breakpoints: + hit_condition = self._get_hit_condition_expression(bp.get('hitCondition')) + condition = bp.get('condition') + + function_breakpoints.append( + FunctionBreakpoint(bp['name'], condition, expression, suspend_policy, hit_condition, is_logpoint)) + + # Note: always succeeds. + breakpoints_set.append(pydevd_schema.Breakpoint( + verified=True, id=self._next_breakpoint_id()).to_dict()) + + self.api.set_function_breakpoints(py_db, function_breakpoints) + + body = {'breakpoints': breakpoints_set} + set_breakpoints_response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + return NetCommand(CMD_RETURN, 0, set_breakpoints_response, is_json=True) + + def on_setbreakpoints_request(self, py_db, request): + ''' + :param SetBreakpointsRequest request: + ''' + response = self._verify_launch_or_attach_done(request) + if response is not None: + return response + + arguments = request.arguments # : :type arguments: SetBreakpointsArguments + # TODO: Path is optional here it could be source reference. + filename = self.api.filename_to_str(arguments.source.path) + func_name = 'None' + + self.api.remove_all_breakpoints(py_db, filename) + + btype = 'python-line' + suspend_policy = 'ALL' + + if not filename.lower().endswith('.py'): # Note: check based on original file, not mapping. + if self._options.django_debug: + btype = 'django-line' + elif self._options.flask_debug: + btype = 'jinja2-line' + + breakpoints_set = [] + + for source_breakpoint in arguments.breakpoints: + source_breakpoint = SourceBreakpoint(**source_breakpoint) + line = source_breakpoint.line + condition = source_breakpoint.condition + breakpoint_id = self._next_breakpoint_id() + + hit_condition = self._get_hit_condition_expression(source_breakpoint.hitCondition) + log_message = source_breakpoint.logMessage + if not log_message: + is_logpoint = None + expression = None + else: + is_logpoint = True + expression = convert_dap_log_message_to_expression(log_message) + + on_changed_breakpoint_state = partial(self._on_changed_breakpoint_state, py_db, arguments.source) + result = self.api.add_breakpoint( + py_db, filename, btype, breakpoint_id, line, condition, func_name, expression, + suspend_policy, hit_condition, is_logpoint, adjust_line=True, on_changed_breakpoint_state=on_changed_breakpoint_state) + + bp = self._create_breakpoint_from_add_breakpoint_result(py_db, arguments.source, breakpoint_id, result) + breakpoints_set.append(bp) + + body = {'breakpoints': breakpoints_set} + set_breakpoints_response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + return NetCommand(CMD_RETURN, 0, set_breakpoints_response, is_json=True) + + def _on_changed_breakpoint_state(self, py_db, source, breakpoint_id, result): + bp = self._create_breakpoint_from_add_breakpoint_result(py_db, source, breakpoint_id, result) + body = BreakpointEventBody( + reason='changed', + breakpoint=bp, + ) + event = BreakpointEvent(body) + event_id = 0 # Actually ignored in this case + py_db.writer.add_command(NetCommand(event_id, 0, event, is_json=True)) + + def _create_breakpoint_from_add_breakpoint_result(self, py_db, source, breakpoint_id, result): + error_code = result.error_code + + if error_code: + if error_code == self.api.ADD_BREAKPOINT_FILE_NOT_FOUND: + error_msg = 'Breakpoint in file that does not exist.' + + elif error_code == self.api.ADD_BREAKPOINT_FILE_EXCLUDED_BY_FILTERS: + error_msg = 'Breakpoint in file excluded by filters.' + if py_db.get_use_libraries_filter(): + error_msg += ('\nNote: may be excluded because of "justMyCode" option (default == true).' + 'Try setting \"justMyCode\": false in the debug configuration (e.g., launch.json).\n') + + elif error_code == self.api.ADD_BREAKPOINT_LAZY_VALIDATION: + error_msg = 'Waiting for code to be loaded to verify breakpoint.' + + elif error_code == self.api.ADD_BREAKPOINT_INVALID_LINE: + error_msg = 'Breakpoint added to invalid line.' + + else: + # Shouldn't get here. + error_msg = 'Breakpoint not validated (reason unknown -- please report as bug).' + + return pydevd_schema.Breakpoint( + verified=False, id=breakpoint_id, line=result.translated_line, message=error_msg, source=source).to_dict() + else: + return pydevd_schema.Breakpoint( + verified=True, id=breakpoint_id, line=result.translated_line, source=source).to_dict() + + def on_setexceptionbreakpoints_request(self, py_db, request): + ''' + :param SetExceptionBreakpointsRequest request: + ''' + # : :type arguments: SetExceptionBreakpointsArguments + arguments = request.arguments + filters = arguments.filters + exception_options = arguments.exceptionOptions + self.api.remove_all_exception_breakpoints(py_db) + + # Can't set these in the DAP. + condition = None + expression = None + notify_on_first_raise_only = False + + ignore_libraries = 1 if py_db.get_use_libraries_filter() else 0 + + if exception_options: + break_raised = False + break_uncaught = False + + for option in exception_options: + option = ExceptionOptions(**option) + if not option.path: + continue + + # never: never breaks + # + # always: always breaks + # + # unhandled: breaks when exception unhandled + # + # userUnhandled: breaks if the exception is not handled by user code + + notify_on_handled_exceptions = 1 if option.breakMode == 'always' else 0 + notify_on_unhandled_exceptions = 1 if option.breakMode == 'unhandled' else 0 + notify_on_user_unhandled_exceptions = 1 if option.breakMode == 'userUnhandled' else 0 + exception_paths = option.path + break_raised |= notify_on_handled_exceptions + break_uncaught |= notify_on_unhandled_exceptions + + exception_names = [] + if len(exception_paths) == 0: + continue + + elif len(exception_paths) == 1: + if 'Python Exceptions' in exception_paths[0]['names']: + exception_names = ['BaseException'] + + else: + path_iterator = iter(exception_paths) + if 'Python Exceptions' in next(path_iterator)['names']: + for path in path_iterator: + for ex_name in path['names']: + exception_names.append(ex_name) + + for exception_name in exception_names: + self.api.add_python_exception_breakpoint( + py_db, + exception_name, + condition, + expression, + notify_on_handled_exceptions, + notify_on_unhandled_exceptions, + notify_on_user_unhandled_exceptions, + notify_on_first_raise_only, + ignore_libraries + ) + + else: + break_raised = 'raised' in filters + break_uncaught = 'uncaught' in filters + break_user = 'userUnhandled' in filters + if break_raised or break_uncaught or break_user: + notify_on_handled_exceptions = 1 if break_raised else 0 + notify_on_unhandled_exceptions = 1 if break_uncaught else 0 + notify_on_user_unhandled_exceptions = 1 if break_user else 0 + exception = 'BaseException' + + self.api.add_python_exception_breakpoint( + py_db, + exception, + condition, + expression, + notify_on_handled_exceptions, + notify_on_unhandled_exceptions, + notify_on_user_unhandled_exceptions, + notify_on_first_raise_only, + ignore_libraries + ) + + if break_raised: + btype = None + if self._options.django_debug: + btype = 'django' + elif self._options.flask_debug: + btype = 'jinja2' + + if btype: + self.api.add_plugins_exception_breakpoint( + py_db, btype, 'BaseException') # Note: Exception name could be anything here. + + # Note: no body required on success. + set_breakpoints_response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, set_breakpoints_response, is_json=True) + + def on_stacktrace_request(self, py_db, request): + ''' + :param StackTraceRequest request: + ''' + # : :type stack_trace_arguments: StackTraceArguments + stack_trace_arguments = request.arguments + thread_id = stack_trace_arguments.threadId + + if stack_trace_arguments.startFrame: + start_frame = int(stack_trace_arguments.startFrame) + else: + start_frame = 0 + + if stack_trace_arguments.levels: + levels = int(stack_trace_arguments.levels) + else: + levels = 0 + + fmt = stack_trace_arguments.format + if hasattr(fmt, 'to_dict'): + fmt = fmt.to_dict() + self.api.request_stack(py_db, request.seq, thread_id, fmt=fmt, start_frame=start_frame, levels=levels) + + def on_exceptioninfo_request(self, py_db, request): + ''' + :param ExceptionInfoRequest request: + ''' + # : :type exception_into_arguments: ExceptionInfoArguments + exception_into_arguments = request.arguments + thread_id = exception_into_arguments.threadId + max_frames = self._options.max_exception_stack_frames + self.api.request_exception_info_json(py_db, request, thread_id, max_frames) + + def on_scopes_request(self, py_db, request): + ''' + Scopes are the top-level items which appear for a frame (so, we receive the frame id + and provide the scopes it has). + + :param ScopesRequest request: + ''' + frame_id = request.arguments.frameId + + variables_reference = frame_id + scopes = [ + Scope('Locals', ScopeRequest(int(variables_reference), 'locals'), False, presentationHint='locals'), + Scope('Globals', ScopeRequest(int(variables_reference), 'globals'), False), + ] + body = ScopesResponseBody(scopes) + scopes_response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + return NetCommand(CMD_RETURN, 0, scopes_response, is_json=True) + + def on_evaluate_request(self, py_db, request): + ''' + :param EvaluateRequest request: + ''' + # : :type arguments: EvaluateArguments + arguments = request.arguments + + if arguments.frameId is None: + self.api.request_exec_or_evaluate_json(py_db, request, thread_id='*') + else: + thread_id = py_db.suspended_frames_manager.get_thread_id_for_variable_reference( + arguments.frameId) + + if thread_id is not None: + self.api.request_exec_or_evaluate_json( + py_db, request, thread_id) + else: + body = EvaluateResponseBody('', 0) + response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': body, + 'success': False, + 'message': 'Unable to find thread for evaluation.' + }) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_setexpression_request(self, py_db, request): + # : :type arguments: SetExpressionArguments + arguments = request.arguments + + thread_id = py_db.suspended_frames_manager.get_thread_id_for_variable_reference( + arguments.frameId) + + if thread_id is not None: + self.api.request_set_expression_json(py_db, request, thread_id) + else: + body = SetExpressionResponseBody('') + response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': body, + 'success': False, + 'message': 'Unable to find thread to set expression.' + }) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_variables_request(self, py_db, request): + ''' + Variables can be asked whenever some place returned a variables reference (so, it + can be a scope gotten from on_scopes_request, the result of some evaluation, etc.). + + Note that in the DAP the variables reference requires a unique int... the way this works for + pydevd is that an instance is generated for that specific variable reference and we use its + id(instance) to identify it to make sure all items are unique (and the actual {id->instance} + is added to a dict which is only valid while the thread is suspended and later cleared when + the related thread resumes execution). + + see: SuspendedFramesManager + + :param VariablesRequest request: + ''' + arguments = request.arguments # : :type arguments: VariablesArguments + variables_reference = arguments.variablesReference + + if isinstance(variables_reference, ScopeRequest): + variables_reference = variables_reference.variable_reference + + thread_id = py_db.suspended_frames_manager.get_thread_id_for_variable_reference( + variables_reference) + if thread_id is not None: + self.api.request_get_variable_json(py_db, request, thread_id) + else: + variables = [] + body = VariablesResponseBody(variables) + variables_response = pydevd_base_schema.build_response(request, kwargs={ + 'body': body, + 'success': False, + 'message': 'Unable to find thread to evaluate variable reference.' + }) + return NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + + def on_setvariable_request(self, py_db, request): + arguments = request.arguments # : :type arguments: SetVariableArguments + variables_reference = arguments.variablesReference + + if isinstance(variables_reference, ScopeRequest): + variables_reference = variables_reference.variable_reference + + if arguments.name.startswith('(return) '): + response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': SetVariableResponseBody(''), + 'success': False, + 'message': 'Cannot change return value' + }) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + thread_id = py_db.suspended_frames_manager.get_thread_id_for_variable_reference( + variables_reference) + + if thread_id is not None: + self.api.request_change_variable_json(py_db, request, thread_id) + else: + response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': SetVariableResponseBody(''), + 'success': False, + 'message': 'Unable to find thread to evaluate variable reference.' + }) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_modules_request(self, py_db, request): + modules_manager = py_db.cmd_factory.modules_manager # : :type modules_manager: ModulesManager + modules_info = modules_manager.get_modules_info() + body = ModulesResponseBody(modules_info) + variables_response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + return NetCommand(CMD_RETURN, 0, variables_response, is_json=True) + + def on_source_request(self, py_db, request): + ''' + :param SourceRequest request: + ''' + source_reference = request.arguments.sourceReference + server_filename = None + content = None + + if source_reference != 0: + server_filename = pydevd_file_utils.get_server_filename_from_source_reference(source_reference) + if not server_filename: + server_filename = pydevd_file_utils.get_source_reference_filename_from_linecache(source_reference) + + if server_filename: + # Try direct file access first - it's much faster when available. + try: + with open(server_filename, 'r') as stream: + content = stream.read() + except: + pass + + if content is None: + # File might not exist at all, or we might not have a permission to read it, + # but it might also be inside a zipfile, or an IPython cell. In this case, + # linecache might still be able to retrieve the source. + lines = (linecache.getline(server_filename, i) for i in itertools.count(1)) + lines = itertools.takewhile(bool, lines) # empty lines are '\n', EOF is '' + + # If we didn't get at least one line back, reset it to None so that it's + # reported as error below, and not as an empty file. + content = ''.join(lines) or None + + if content is None: + frame_id = pydevd_file_utils.get_frame_id_from_source_reference(source_reference) + pydev_log.debug('Found frame id: %s for source reference: %s', frame_id, source_reference) + if frame_id is not None: + try: + content = self.api.get_decompiled_source_from_frame_id(py_db, frame_id) + except Exception: + pydev_log.exception('Error getting source for frame id: %s', frame_id) + content = None + + body = SourceResponseBody(content or '') + response_args = {'body': body} + + if content is None: + if source_reference == 0: + message = 'Source unavailable' + elif server_filename: + message = 'Unable to retrieve source for %s' % (server_filename,) + else: + message = 'Invalid sourceReference %d' % (source_reference,) + response_args.update({'success': False, 'message': message}) + + response = pydevd_base_schema.build_response(request, kwargs=response_args) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_gototargets_request(self, py_db, request): + path = request.arguments.source.path + line = request.arguments.line + target_id = self._goto_targets_map.obtain_key((path, line)) + target = { + 'id': target_id, + 'label': '%s:%s' % (path, line), + 'line': line + } + body = GotoTargetsResponseBody(targets=[target]) + response_args = {'body': body} + response = pydevd_base_schema.build_response(request, kwargs=response_args) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_goto_request(self, py_db, request): + target_id = int(request.arguments.targetId) + thread_id = request.arguments.threadId + try: + path, line = self._goto_targets_map.obtain_value(target_id) + except KeyError: + response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': {}, + 'success': False, + 'message': 'Unknown goto target id: %d' % (target_id,), + }) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + self.api.request_set_next(py_db, request.seq, thread_id, CMD_SET_NEXT_STATEMENT, path, line, '*') + # See 'NetCommandFactoryJson.make_set_next_stmnt_status_message' for response + return None + + def on_setdebuggerproperty_request(self, py_db, request): + args = request.arguments # : :type args: SetDebuggerPropertyArguments + if args.ideOS is not None: + self.api.set_ide_os(args.ideOS) + + if args.dontTraceStartPatterns is not None and args.dontTraceEndPatterns is not None: + start_patterns = tuple(args.dontTraceStartPatterns) + end_patterns = tuple(args.dontTraceEndPatterns) + self.api.set_dont_trace_start_end_patterns(py_db, start_patterns, end_patterns) + + if args.skipSuspendOnBreakpointException is not None: + py_db.skip_suspend_on_breakpoint_exception = tuple( + get_exception_class(x) for x in args.skipSuspendOnBreakpointException) + + if args.skipPrintBreakpointException is not None: + py_db.skip_print_breakpoint_exception = tuple( + get_exception_class(x) for x in args.skipPrintBreakpointException) + + if args.multiThreadsSingleNotification is not None: + py_db.multi_threads_single_notification = args.multiThreadsSingleNotification + + # TODO: Support other common settings. Note that not all of these might be relevant to python. + # JustMyCodeStepping: 0 or 1 + # AllowOutOfProcessSymbols: 0 or 1 + # DisableJITOptimization: 0 or 1 + # InterpreterOptions: 0 or 1 + # StopOnExceptionCrossingManagedBoundary: 0 or 1 + # WarnIfNoUserCodeOnLaunch: 0 or 1 + # EnableStepFiltering: true of false + + response = pydevd_base_schema.build_response(request, kwargs={'body': {}}) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_pydevdsysteminfo_request(self, py_db, request): + try: + pid = os.getpid() + except AttributeError: + pid = None + + # It's possible to have the ppid reported from args. In this case, use that instead of the + # real ppid (athough we're using `ppid`, what we want in meaning is the `launcher_pid` -- + # so, if a python process is launched from another python process, consider that process the + # parent and not any intermediary stubs). + + ppid = py_db.get_arg_ppid() or self.api.get_ppid() + + try: + impl_desc = platform.python_implementation() + except AttributeError: + impl_desc = PY_IMPL_NAME + + py_info = pydevd_schema.PydevdPythonInfo( + version=PY_VERSION_STR, + implementation=pydevd_schema.PydevdPythonImplementationInfo( + name=PY_IMPL_NAME, + version=PY_IMPL_VERSION_STR, + description=impl_desc, + ) + ) + platform_info = pydevd_schema.PydevdPlatformInfo(name=sys.platform) + process_info = pydevd_schema.PydevdProcessInfo( + pid=pid, + ppid=ppid, + executable=sys.executable, + bitness=64 if IS_64BIT_PROCESS else 32, + ) + pydevd_info = pydevd_schema.PydevdInfo( + usingCython=USING_CYTHON, + usingFrameEval=USING_FRAME_EVAL, + ) + body = { + 'python': py_info, + 'platform': platform_info, + 'process': process_info, + 'pydevd': pydevd_info, + } + response = pydevd_base_schema.build_response(request, kwargs={'body': body}) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + def on_setpydevdsourcemap_request(self, py_db, request): + args = request.arguments # : :type args: SetPydevdSourceMapArguments + SourceMappingEntry = self.api.SourceMappingEntry + + path = args.source.path + source_maps = args.pydevdSourceMaps + # : :type source_map: PydevdSourceMap + new_mappings = [ + SourceMappingEntry( + source_map['line'], + source_map['endLine'], + source_map['runtimeLine'], + self.api.filename_to_str(source_map['runtimeSource']['path']) + ) for source_map in source_maps + ] + + error_msg = self.api.set_source_mapping(py_db, path, new_mappings) + if error_msg: + response = pydevd_base_schema.build_response( + request, + kwargs={ + 'body': {}, + 'success': False, + 'message': error_msg, + }) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + + response = pydevd_base_schema.build_response(request) + return NetCommand(CMD_RETURN, 0, response, is_json=True) + diff --git a/_pydevd_bundle/pydevd_referrers.py b/_pydevd_bundle/pydevd_referrers.py new file mode 100644 index 0000000..c7e1bfa --- /dev/null +++ b/_pydevd_bundle/pydevd_referrers.py @@ -0,0 +1,257 @@ +import sys +from _pydevd_bundle import pydevd_xml +from os.path import basename +from _pydev_bundle import pydev_log +from urllib.parse import unquote_plus +from _pydevd_bundle.pydevd_constants import IS_PY311_OR_GREATER + + +#=================================================================================================== +# print_var_node +#=================================================================================================== +def print_var_node(xml_node, stream): + name = xml_node.getAttribute('name') + value = xml_node.getAttribute('value') + val_type = xml_node.getAttribute('type') + + found_as = xml_node.getAttribute('found_as') + stream.write('Name: ') + stream.write(unquote_plus(name)) + stream.write(', Value: ') + stream.write(unquote_plus(value)) + stream.write(', Type: ') + stream.write(unquote_plus(val_type)) + if found_as: + stream.write(', Found as: %s' % (unquote_plus(found_as),)) + stream.write('\n') + + +#=================================================================================================== +# print_referrers +#=================================================================================================== +def print_referrers(obj, stream=None): + if stream is None: + stream = sys.stdout + result = get_referrer_info(obj) + from xml.dom.minidom import parseString + dom = parseString(result) + + xml = dom.getElementsByTagName('xml')[0] + for node in xml.childNodes: + if node.nodeType == node.TEXT_NODE: + continue + + if node.localName == 'for': + stream.write('Searching references for: ') + for child in node.childNodes: + if child.nodeType == node.TEXT_NODE: + continue + print_var_node(child, stream) + + elif node.localName == 'var': + stream.write('Referrer found: ') + print_var_node(node, stream) + + else: + sys.stderr.write('Unhandled node: %s\n' % (node,)) + + return result + + +#=================================================================================================== +# get_referrer_info +#=================================================================================================== +def get_referrer_info(searched_obj): + DEBUG = 0 + if DEBUG: + sys.stderr.write('Getting referrers info.\n') + try: + try: + if searched_obj is None: + ret = ['\n'] + + ret.append('\n') + ret.append(pydevd_xml.var_to_xml( + searched_obj, + 'Skipping getting referrers for None', + additional_in_xml=' id="%s"' % (id(searched_obj),))) + ret.append('\n') + ret.append('') + ret = ''.join(ret) + return ret + + obj_id = id(searched_obj) + + try: + if DEBUG: + sys.stderr.write('Getting referrers...\n') + import gc + referrers = gc.get_referrers(searched_obj) + except: + pydev_log.exception() + ret = ['\n'] + + ret.append('\n') + ret.append(pydevd_xml.var_to_xml( + searched_obj, + 'Exception raised while trying to get_referrers.', + additional_in_xml=' id="%s"' % (id(searched_obj),))) + ret.append('\n') + ret.append('') + ret = ''.join(ret) + return ret + + if DEBUG: + sys.stderr.write('Found %s referrers.\n' % (len(referrers),)) + + curr_frame = sys._getframe() + frame_type = type(curr_frame) + + # Ignore this frame and any caller frame of this frame + + ignore_frames = {} # Should be a set, but it's not available on all python versions. + while curr_frame is not None: + if basename(curr_frame.f_code.co_filename).startswith('pydev'): + ignore_frames[curr_frame] = 1 + curr_frame = curr_frame.f_back + + ret = ['\n'] + + ret.append('\n') + if DEBUG: + sys.stderr.write('Searching Referrers of obj with id="%s"\n' % (obj_id,)) + + ret.append(pydevd_xml.var_to_xml( + searched_obj, + 'Referrers of obj with id="%s"' % (obj_id,))) + ret.append('\n') + + curr_frame = sys._getframe() + all_objects = None + + for r in referrers: + try: + if r in ignore_frames: + continue # Skip the references we may add ourselves + except: + pass # Ok: unhashable type checked... + + if r is referrers: + continue + + if r is curr_frame.f_locals: + continue + + r_type = type(r) + r_id = str(id(r)) + + representation = str(r_type) + + found_as = '' + if r_type == frame_type: + if DEBUG: + sys.stderr.write('Found frame referrer: %r\n' % (r,)) + for key, val in r.f_locals.items(): + if val is searched_obj: + found_as = key + break + + elif r_type == dict: + if DEBUG: + sys.stderr.write('Found dict referrer: %r\n' % (r,)) + + # Try to check if it's a value in the dict (and under which key it was found) + for key, val in r.items(): + if val is searched_obj: + found_as = key + if DEBUG: + sys.stderr.write(' Found as %r in dict\n' % (found_as,)) + break + + # Ok, there's one annoying thing: many times we find it in a dict from an instance, + # but with this we don't directly have the class, only the dict, so, to workaround that + # we iterate over all reachable objects ad check if one of those has the given dict. + if all_objects is None: + all_objects = gc.get_objects() + + for x in all_objects: + try: + if getattr(x, '__dict__', None) is r: + r = x + r_type = type(x) + r_id = str(id(r)) + representation = str(r_type) + break + except: + pass # Just ignore any error here (i.e.: ReferenceError, etc.) + + elif r_type in (tuple, list): + if DEBUG: + sys.stderr.write('Found tuple referrer: %r\n' % (r,)) + + for i, x in enumerate(r): + if x is searched_obj: + found_as = '%s[%s]' % (r_type.__name__, i) + if DEBUG: + sys.stderr.write(' Found as %s in tuple: \n' % (found_as,)) + break + + elif IS_PY311_OR_GREATER: + # Up to Python 3.10, gc.get_referrers for an instance actually returned the + # object.__dict__, but on Python 3.11 it returns the actual object, so, + # handling is a bit easier (we don't need the workaround from the dict + # case to find the actual instance, we just need to find the attribute name). + if DEBUG: + sys.stderr.write('Found dict referrer: %r\n' % (r,)) + + dct = getattr(r, '__dict__', None) + if dct: + # Try to check if it's a value in the dict (and under which key it was found) + for key, val in dct.items(): + if val is searched_obj: + found_as = key + if DEBUG: + sys.stderr.write(' Found as %r in object instance\n' % (found_as,)) + break + + if found_as: + if not isinstance(found_as, str): + found_as = str(found_as) + found_as = ' found_as="%s"' % (pydevd_xml.make_valid_xml_value(found_as),) + + ret.append(pydevd_xml.var_to_xml( + r, + representation, + additional_in_xml=' id="%s"%s' % (r_id, found_as))) + finally: + if DEBUG: + sys.stderr.write('Done searching for references.\n') + + # If we have any exceptions, don't keep dangling references from this frame to any of our objects. + all_objects = None + referrers = None + searched_obj = None + r = None + x = None + key = None + val = None + curr_frame = None + ignore_frames = None + except: + pydev_log.exception() + ret = ['\n'] + + ret.append('\n') + ret.append(pydevd_xml.var_to_xml( + searched_obj, + 'Error getting referrers for:', + additional_in_xml=' id="%s"' % (id(searched_obj),))) + ret.append('\n') + ret.append('') + ret = ''.join(ret) + return ret + + ret.append('') + ret = ''.join(ret) + return ret + diff --git a/_pydevd_bundle/pydevd_reload.py b/_pydevd_bundle/pydevd_reload.py new file mode 100644 index 0000000..507e73b --- /dev/null +++ b/_pydevd_bundle/pydevd_reload.py @@ -0,0 +1,433 @@ +""" +Based on the python xreload. + +Changes +====================== + +1. we don't recreate the old namespace from new classes. Rather, we keep the existing namespace, +load a new version of it and update only some of the things we can inplace. That way, we don't break +things such as singletons or end up with a second representation of the same class in memory. + +2. If we find it to be a __metaclass__, we try to update it as a regular class. + +3. We don't remove old attributes (and leave them lying around even if they're no longer used). + +4. Reload hooks were changed + +These changes make it more stable, especially in the common case (where in a debug session only the +contents of a function are changed), besides providing flexibility for users that want to extend +on it. + + + +Hooks +====================== + +Classes/modules can be specially crafted to work with the reload (so that it can, for instance, +update some constant which was changed). + +1. To participate in the change of some attribute: + + In a module: + + __xreload_old_new__(namespace, name, old, new) + + in a class: + + @classmethod + __xreload_old_new__(cls, name, old, new) + + A class or module may include a method called '__xreload_old_new__' which is called when we're + unable to reload a given attribute. + + + +2. To do something after the whole reload is finished: + + In a module: + + __xreload_after_reload_update__(namespace): + + In a class: + + @classmethod + __xreload_after_reload_update__(cls): + + + A class or module may include a method called '__xreload_after_reload_update__' which is called + after the reload finishes. + + +Important: when providing a hook, always use the namespace or cls provided and not anything in the global +namespace, as the global namespace are only temporarily created during the reload and may not reflect the +actual application state (while the cls and namespace passed are). + + +Current limitations +====================== + + +- Attributes/constants are added, but not changed (so singletons and the application state is not + broken -- use provided hooks to workaround it). + +- Code using metaclasses may not always work. + +- Functions and methods using decorators (other than classmethod and staticmethod) are not handled + correctly. + +- Renamings are not handled correctly. + +- Dependent modules are not reloaded. + +- New __slots__ can't be added to existing classes. + + +Info +====================== + +Original: http://svn.python.org/projects/sandbox/trunk/xreload/xreload.py +Note: it seems https://github.com/plone/plone.reload/blob/master/plone/reload/xreload.py enhances it (to check later) + +Interesting alternative: https://code.google.com/p/reimport/ + +Alternative to reload(). + +This works by executing the module in a scratch namespace, and then patching classes, methods and +functions in place. This avoids the need to patch instances. New objects are copied into the +target namespace. + +""" + +from _pydev_bundle.pydev_imports import execfile +from _pydevd_bundle import pydevd_dont_trace +import types +from _pydev_bundle import pydev_log +from _pydevd_bundle.pydevd_constants import get_global_debugger + +NO_DEBUG = 0 +LEVEL1 = 1 +LEVEL2 = 2 + +DEBUG = NO_DEBUG + + +def write_err(*args): + py_db = get_global_debugger() + if py_db is not None: + new_lst = [] + for a in args: + new_lst.append(str(a)) + + msg = ' '.join(new_lst) + s = 'code reload: %s\n' % (msg,) + cmd = py_db.cmd_factory.make_io_message(s, 2) + if py_db.writer is not None: + py_db.writer.add_command(cmd) + + +def notify_info0(*args): + write_err(*args) + + +def notify_info(*args): + if DEBUG >= LEVEL1: + write_err(*args) + + +def notify_info2(*args): + if DEBUG >= LEVEL2: + write_err(*args) + + +def notify_error(*args): + write_err(*args) + + +#======================================================================================================================= +# code_objects_equal +#======================================================================================================================= +def code_objects_equal(code0, code1): + for d in dir(code0): + if d.startswith('_') or 'line' in d or d in ('replace', 'co_positions', 'co_qualname'): + continue + if getattr(code0, d) != getattr(code1, d): + return False + return True + + +#======================================================================================================================= +# xreload +#======================================================================================================================= +def xreload(mod): + """Reload a module in place, updating classes, methods and functions. + + mod: a module object + + Returns a boolean indicating whether a change was done. + """ + r = Reload(mod) + r.apply() + found_change = r.found_change + r = None + pydevd_dont_trace.clear_trace_filter_cache() + return found_change + +# This isn't actually used... Initially I planned to reload variables which are immutable on the +# namespace, but this can destroy places where we're saving state, which may not be what we want, +# so, we're being conservative and giving the user hooks if he wants to do a reload. +# +# immutable_types = [int, str, float, tuple] #That should be common to all Python versions +# +# for name in 'long basestr unicode frozenset'.split(): +# try: +# immutable_types.append(__builtins__[name]) +# except: +# pass #Just ignore: not all python versions are created equal. +# immutable_types = tuple(immutable_types) + + +#======================================================================================================================= +# Reload +#======================================================================================================================= +class Reload: + + def __init__(self, mod, mod_name=None, mod_filename=None): + self.mod = mod + if mod_name: + self.mod_name = mod_name + else: + self.mod_name = mod.__name__ if mod is not None else None + + if mod_filename: + self.mod_filename = mod_filename + else: + self.mod_filename = mod.__file__ if mod is not None else None + + self.found_change = False + + def apply(self): + mod = self.mod + self._on_finish_callbacks = [] + try: + # Get the module namespace (dict) early; this is part of the type check + modns = mod.__dict__ + + # Execute the code. We copy the module dict to a temporary; then + # clear the module dict; then execute the new code in the module + # dict; then swap things back and around. This trick (due to + # Glyph Lefkowitz) ensures that the (readonly) __globals__ + # attribute of methods and functions is set to the correct dict + # object. + new_namespace = modns.copy() + new_namespace.clear() + if self.mod_filename: + new_namespace["__file__"] = self.mod_filename + try: + new_namespace["__builtins__"] = __builtins__ + except NameError: + raise # Ok if not there. + + if self.mod_name: + new_namespace["__name__"] = self.mod_name + if new_namespace["__name__"] == '__main__': + # We do this because usually the __main__ starts-up the program, guarded by + # the if __name__ == '__main__', but we don't want to start the program again + # on a reload. + new_namespace["__name__"] = '__main_reloaded__' + + execfile(self.mod_filename, new_namespace, new_namespace) + # Now we get to the hard part + oldnames = set(modns) + newnames = set(new_namespace) + + # Create new tokens (note: not deleting existing) + for name in newnames - oldnames: + notify_info0('Added:', name, 'to namespace') + self.found_change = True + modns[name] = new_namespace[name] + + # Update in-place what we can + for name in oldnames & newnames: + self._update(modns, name, modns[name], new_namespace[name]) + + self._handle_namespace(modns) + + for c in self._on_finish_callbacks: + c() + del self._on_finish_callbacks[:] + except: + pydev_log.exception() + + def _handle_namespace(self, namespace, is_class_namespace=False): + on_finish = None + if is_class_namespace: + xreload_after_update = getattr(namespace, '__xreload_after_reload_update__', None) + if xreload_after_update is not None: + self.found_change = True + on_finish = lambda: xreload_after_update() + + elif '__xreload_after_reload_update__' in namespace: + xreload_after_update = namespace['__xreload_after_reload_update__'] + self.found_change = True + on_finish = lambda: xreload_after_update(namespace) + + if on_finish is not None: + # If a client wants to know about it, give him a chance. + self._on_finish_callbacks.append(on_finish) + + def _update(self, namespace, name, oldobj, newobj, is_class_namespace=False): + """Update oldobj, if possible in place, with newobj. + + If oldobj is immutable, this simply returns newobj. + + Args: + oldobj: the object to be updated + newobj: the object used as the source for the update + """ + try: + notify_info2('Updating: ', oldobj) + if oldobj is newobj: + # Probably something imported + return + + if type(oldobj) is not type(newobj): + # Cop-out: if the type changed, give up + if name not in ('__builtins__',): + notify_error('Type of: %s (old: %s != new: %s) changed... Skipping.' % (name, type(oldobj), type(newobj))) + return + + if isinstance(newobj, types.FunctionType): + self._update_function(oldobj, newobj) + return + + if isinstance(newobj, types.MethodType): + self._update_method(oldobj, newobj) + return + + if isinstance(newobj, classmethod): + self._update_classmethod(oldobj, newobj) + return + + if isinstance(newobj, staticmethod): + self._update_staticmethod(oldobj, newobj) + return + + if hasattr(types, 'ClassType'): + classtype = (types.ClassType, type) # object is not instance of types.ClassType. + else: + classtype = type + + if isinstance(newobj, classtype): + self._update_class(oldobj, newobj) + return + + # New: dealing with metaclasses. + if hasattr(newobj, '__metaclass__') and hasattr(newobj, '__class__') and newobj.__metaclass__ == newobj.__class__: + self._update_class(oldobj, newobj) + return + + if namespace is not None: + # Check for the `__xreload_old_new__` protocol (don't even compare things + # as even doing a comparison may break things -- see: https://github.com/microsoft/debugpy/issues/615). + xreload_old_new = None + if is_class_namespace: + xreload_old_new = getattr(namespace, '__xreload_old_new__', None) + if xreload_old_new is not None: + self.found_change = True + xreload_old_new(name, oldobj, newobj) + + elif '__xreload_old_new__' in namespace: + xreload_old_new = namespace['__xreload_old_new__'] + xreload_old_new(namespace, name, oldobj, newobj) + self.found_change = True + + # Too much information to the user... + # else: + # notify_info0('%s NOT updated. Create __xreload_old_new__(name, old, new) for custom reload' % (name,)) + + except: + notify_error('Exception found when updating %s. Proceeding for other items.' % (name,)) + pydev_log.exception() + + # All of the following functions have the same signature as _update() + + def _update_function(self, oldfunc, newfunc): + """Update a function object.""" + oldfunc.__doc__ = newfunc.__doc__ + oldfunc.__dict__.update(newfunc.__dict__) + + try: + newfunc.__code__ + attr_name = '__code__' + except AttributeError: + newfunc.func_code + attr_name = 'func_code' + + old_code = getattr(oldfunc, attr_name) + new_code = getattr(newfunc, attr_name) + if not code_objects_equal(old_code, new_code): + notify_info0('Updated function code:', oldfunc) + setattr(oldfunc, attr_name, new_code) + self.found_change = True + + try: + oldfunc.__defaults__ = newfunc.__defaults__ + except AttributeError: + oldfunc.func_defaults = newfunc.func_defaults + + return oldfunc + + def _update_method(self, oldmeth, newmeth): + """Update a method object.""" + # XXX What if im_func is not a function? + if hasattr(oldmeth, 'im_func') and hasattr(newmeth, 'im_func'): + self._update(None, None, oldmeth.im_func, newmeth.im_func) + elif hasattr(oldmeth, '__func__') and hasattr(newmeth, '__func__'): + self._update(None, None, oldmeth.__func__, newmeth.__func__) + return oldmeth + + def _update_class(self, oldclass, newclass): + """Update a class object.""" + olddict = oldclass.__dict__ + newdict = newclass.__dict__ + + oldnames = set(olddict) + newnames = set(newdict) + + for name in newnames - oldnames: + setattr(oldclass, name, newdict[name]) + notify_info0('Added:', name, 'to', oldclass) + self.found_change = True + + # Note: not removing old things... + # for name in oldnames - newnames: + # notify_info('Removed:', name, 'from', oldclass) + # delattr(oldclass, name) + + for name in (oldnames & newnames) - set(['__dict__', '__doc__']): + self._update(oldclass, name, olddict[name], newdict[name], is_class_namespace=True) + + old_bases = getattr(oldclass, '__bases__', None) + new_bases = getattr(newclass, '__bases__', None) + if str(old_bases) != str(new_bases): + notify_error('Changing the hierarchy of a class is not supported. %s may be inconsistent.' % (oldclass,)) + + self._handle_namespace(oldclass, is_class_namespace=True) + + def _update_classmethod(self, oldcm, newcm): + """Update a classmethod update.""" + # While we can't modify the classmethod object itself (it has no + # mutable attributes), we *can* extract the underlying function + # (by calling __get__(), which returns a method object) and update + # it in-place. We don't have the class available to pass to + # __get__() but any object except None will do. + self._update(None, None, oldcm.__get__(0), newcm.__get__(0)) + + def _update_staticmethod(self, oldsm, newsm): + """Update a staticmethod update.""" + # While we can't modify the staticmethod object itself (it has no + # mutable attributes), we *can* extract the underlying function + # (by calling __get__(), which returns it) and update it in-place. + # We don't have the class available to pass to __get__() but any + # object except None will do. + self._update(None, None, oldsm.__get__(0), newsm.__get__(0)) diff --git a/_pydevd_bundle/pydevd_resolver.py b/_pydevd_bundle/pydevd_resolver.py new file mode 100644 index 0000000..ac7aa10 --- /dev/null +++ b/_pydevd_bundle/pydevd_resolver.py @@ -0,0 +1,723 @@ +from _pydev_bundle import pydev_log +from _pydevd_bundle.pydevd_utils import hasattr_checked, DAPGrouper, Timer +from io import StringIO +import traceback +from os.path import basename + +from functools import partial +from _pydevd_bundle.pydevd_constants import IS_PY36_OR_GREATER, \ + MethodWrapperType, RETURN_VALUES_DICT, DebugInfoHolder, IS_PYPY, GENERATED_LEN_ATTR_NAME +from _pydevd_bundle.pydevd_safe_repr import SafeRepr + +# Note: 300 is already a lot to see in the outline (after that the user should really use the shell to get things) +# and this also means we'll pass less information to the client side (which makes debugging faster). +MAX_ITEMS_TO_HANDLE = 300 + +TOO_LARGE_MSG = 'Too large to show contents. Max items to show: ' + str(MAX_ITEMS_TO_HANDLE) +TOO_LARGE_ATTR = 'Unable to handle:' + + +#======================================================================================================================= +# UnableToResolveVariableException +#======================================================================================================================= +class UnableToResolveVariableException(Exception): + pass + + +try: + from collections import OrderedDict +except: + OrderedDict = dict + +try: + import java.lang # @UnresolvedImport +except: + pass + +#======================================================================================================================= +# See: pydevd_extension_api module for resolver interface +#======================================================================================================================= + + +def sorted_attributes_key(attr_name): + if attr_name.startswith('__'): + if attr_name.endswith('__'): + # __ double under before and after __ + return (3, attr_name) + else: + # __ double under before + return (2, attr_name) + elif attr_name.startswith('_'): + # _ single under + return (1, attr_name) + else: + # Regular (Before anything) + return (0, attr_name) + + +#======================================================================================================================= +# DefaultResolver +#======================================================================================================================= +class DefaultResolver: + ''' + DefaultResolver is the class that'll actually resolve how to show some variable. + ''' + + def resolve(self, var, attribute): + return getattr(var, attribute) + + def get_contents_debug_adapter_protocol(self, obj, fmt=None): + if MethodWrapperType: + dct, used___dict__ = self._get_py_dictionary(obj) + else: + dct = self._get_jy_dictionary(obj)[0] + + lst = sorted(dct.items(), key=lambda tup: sorted_attributes_key(tup[0])) + if used___dict__: + eval_name = '.__dict__[%s]' + else: + eval_name = '.%s' + + ret = [] + for attr_name, attr_value in lst: + entry = (attr_name, attr_value, eval_name % attr_name) + ret.append(entry) + + return ret + + def get_dictionary(self, var, names=None, used___dict__=False): + if MethodWrapperType: + return self._get_py_dictionary(var, names, used___dict__=used___dict__)[0] + else: + return self._get_jy_dictionary(var)[0] + + def _get_jy_dictionary(self, obj): + ret = {} + found = java.util.HashMap() + + original = obj + if hasattr_checked(obj, '__class__') and obj.__class__ == java.lang.Class: + + # get info about superclasses + classes = [] + classes.append(obj) + c = obj.getSuperclass() + while c != None: + classes.append(c) + c = c.getSuperclass() + + # get info about interfaces + interfs = [] + for obj in classes: + interfs.extend(obj.getInterfaces()) + classes.extend(interfs) + + # now is the time when we actually get info on the declared methods and fields + for obj in classes: + + declaredMethods = obj.getDeclaredMethods() + declaredFields = obj.getDeclaredFields() + for i in range(len(declaredMethods)): + name = declaredMethods[i].getName() + ret[name] = declaredMethods[i].toString() + found.put(name, 1) + + for i in range(len(declaredFields)): + name = declaredFields[i].getName() + found.put(name, 1) + # if declaredFields[i].isAccessible(): + declaredFields[i].setAccessible(True) + # ret[name] = declaredFields[i].get( declaredFields[i] ) + try: + ret[name] = declaredFields[i].get(original) + except: + ret[name] = declaredFields[i].toString() + + # this simple dir does not always get all the info, that's why we have the part before + # (e.g.: if we do a dir on String, some methods that are from other interfaces such as + # charAt don't appear) + try: + d = dir(original) + for name in d: + if found.get(name) != 1: + ret[name] = getattr(original, name) + except: + # sometimes we're unable to do a dir + pass + + return ret + + def get_names(self, var): + used___dict__ = False + try: + names = dir(var) + except Exception: + names = [] + if not names: + if hasattr_checked(var, '__dict__'): + names = list(var.__dict__) + used___dict__ = True + return names, used___dict__ + + def _get_py_dictionary(self, var, names=None, used___dict__=False): + ''' + :return tuple(names, used___dict__), where used___dict__ means we have to access + using obj.__dict__[name] instead of getattr(obj, name) + ''' + + # On PyPy we never show functions. This is because of a corner case where PyPy becomes + # absurdly slow -- it takes almost half a second to introspect a single numpy function (so, + # the related test, "test_case_16_resolve_numpy_array", times out... this probably isn't + # specific to numpy, but to any library where the CPython bridge is used, but as we + # can't be sure in the debugger, we play it safe and don't show it at all). + filter_function = IS_PYPY + + if not names: + names, used___dict__ = self.get_names(var) + d = {} + + # Be aware that the order in which the filters are applied attempts to + # optimize the operation by removing as many items as possible in the + # first filters, leaving fewer items for later filters + + timer = Timer() + cls = type(var) + for name in names: + try: + name_as_str = name + if name_as_str.__class__ != str: + name_as_str = '%r' % (name_as_str,) + + if not used___dict__: + attr = getattr(var, name) + else: + attr = var.__dict__[name] + + # filter functions? + if filter_function: + if inspect.isroutine(attr) or isinstance(attr, MethodWrapperType): + continue + except: + # if some error occurs getting it, let's put it to the user. + strIO = StringIO() + traceback.print_exc(file=strIO) + attr = strIO.getvalue() + + finally: + timer.report_if_getting_attr_slow(cls, name_as_str) + + d[name_as_str] = attr + + return d, used___dict__ + + +class DAPGrouperResolver: + + def get_contents_debug_adapter_protocol(self, obj, fmt=None): + return obj.get_contents_debug_adapter_protocol() + + +_basic_immutable_types = (int, float, complex, str, bytes, type(None), bool, frozenset) + + +def _does_obj_repr_evaluate_to_obj(obj): + ''' + If obj is an object where evaluating its representation leads to + the same object, return True, otherwise, return False. + ''' + try: + if isinstance(obj, tuple): + for o in obj: + if not _does_obj_repr_evaluate_to_obj(o): + return False + return True + else: + return isinstance(obj, _basic_immutable_types) + except: + return False + + +#======================================================================================================================= +# DictResolver +#======================================================================================================================= +class DictResolver: + + sort_keys = not IS_PY36_OR_GREATER + + def resolve(self, dct, key): + if key in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR): + return None + + if '(' not in key: + # we have to treat that because the dict resolver is also used to directly resolve the global and local + # scopes (which already have the items directly) + try: + return dct[key] + except: + return getattr(dct, key) + + # ok, we have to iterate over the items to find the one that matches the id, because that's the only way + # to actually find the reference from the string we have before. + expected_id = int(key.split('(')[-1][:-1]) + for key, val in dct.items(): + if id(key) == expected_id: + return val + + raise UnableToResolveVariableException() + + def key_to_str(self, key, fmt=None): + if fmt is not None: + if fmt.get('hex', False): + safe_repr = SafeRepr() + safe_repr.convert_to_hex = True + return safe_repr(key) + return '%r' % (key,) + + def init_dict(self): + return {} + + def get_contents_debug_adapter_protocol(self, dct, fmt=None): + ''' + This method is to be used in the case where the variables are all saved by its id (and as + such don't need to have the `resolve` method called later on, so, keys don't need to + embed the reference in the key). + + Note that the return should be ordered. + + :return list(tuple(name:str, value:object, evaluateName:str)) + ''' + ret = [] + + i = 0 + + found_representations = set() + + for key, val in dct.items(): + i += 1 + key_as_str = self.key_to_str(key, fmt) + + if key_as_str not in found_representations: + found_representations.add(key_as_str) + else: + # If the key would be a duplicate, add the key id (otherwise + # VSCode won't show all keys correctly). + # See: https://github.com/microsoft/debugpy/issues/148 + key_as_str = '%s (id: %s)' % (key_as_str, id(key)) + found_representations.add(key_as_str) + + if _does_obj_repr_evaluate_to_obj(key): + s = self.key_to_str(key) # do not format the key + eval_key_str = '[%s]' % (s,) + else: + eval_key_str = None + ret.append((key_as_str, val, eval_key_str)) + if i > MAX_ITEMS_TO_HANDLE: + ret.append((TOO_LARGE_ATTR, TOO_LARGE_MSG, None)) + break + + # in case the class extends built-in type and has some additional fields + from_default_resolver = defaultResolver.get_contents_debug_adapter_protocol(dct, fmt) + + if from_default_resolver: + ret = from_default_resolver + ret + + if self.sort_keys: + ret = sorted(ret, key=lambda tup: sorted_attributes_key(tup[0])) + + ret.append((GENERATED_LEN_ATTR_NAME, len(dct), partial(_apply_evaluate_name, evaluate_name='len(%s)'))) + return ret + + def get_dictionary(self, dct): + ret = self.init_dict() + + i = 0 + for key, val in dct.items(): + i += 1 + # we need to add the id because otherwise we cannot find the real object to get its contents later on. + key = '%s (%s)' % (self.key_to_str(key), id(key)) + ret[key] = val + if i > MAX_ITEMS_TO_HANDLE: + ret[TOO_LARGE_ATTR] = TOO_LARGE_MSG + break + + # in case if the class extends built-in type and has some additional fields + additional_fields = defaultResolver.get_dictionary(dct) + ret.update(additional_fields) + ret[GENERATED_LEN_ATTR_NAME] = len(dct) + return ret + + +def _apply_evaluate_name(parent_name, evaluate_name): + return evaluate_name % (parent_name,) + + +#======================================================================================================================= +# TupleResolver +#======================================================================================================================= +class TupleResolver: # to enumerate tuples and lists + + def resolve(self, var, attribute): + ''' + @param var: that's the original attribute + @param attribute: that's the key passed in the dict (as a string) + ''' + if attribute in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR): + return None + try: + return var[int(attribute)] + except: + return getattr(var, attribute) + + def get_contents_debug_adapter_protocol(self, lst, fmt=None): + ''' + This method is to be used in the case where the variables are all saved by its id (and as + such don't need to have the `resolve` method called later on, so, keys don't need to + embed the reference in the key). + + Note that the return should be ordered. + + :return list(tuple(name:str, value:object, evaluateName:str)) + ''' + l = len(lst) + ret = [] + + format_str = '%0' + str(int(len(str(l - 1)))) + 'd' + if fmt is not None and fmt.get('hex', False): + format_str = '0x%0' + str(int(len(hex(l).lstrip('0x')))) + 'x' + + for i, item in enumerate(lst): + ret.append((format_str % i, item, '[%s]' % i)) + + if i > MAX_ITEMS_TO_HANDLE: + ret.append((TOO_LARGE_ATTR, TOO_LARGE_MSG, None)) + break + + # Needed in case the class extends the built-in type and has some additional fields. + from_default_resolver = defaultResolver.get_contents_debug_adapter_protocol(lst, fmt=fmt) + if from_default_resolver: + ret = from_default_resolver + ret + + ret.append((GENERATED_LEN_ATTR_NAME, len(lst), partial(_apply_evaluate_name, evaluate_name='len(%s)'))) + return ret + + def get_dictionary(self, var, fmt={}): + l = len(var) + d = {} + + format_str = '%0' + str(int(len(str(l - 1)))) + 'd' + if fmt is not None and fmt.get('hex', False): + format_str = '0x%0' + str(int(len(hex(l).lstrip('0x')))) + 'x' + + for i, item in enumerate(var): + d[format_str % i] = item + + if i > MAX_ITEMS_TO_HANDLE: + d[TOO_LARGE_ATTR] = TOO_LARGE_MSG + break + + # in case if the class extends built-in type and has some additional fields + additional_fields = defaultResolver.get_dictionary(var) + d.update(additional_fields) + d[GENERATED_LEN_ATTR_NAME] = len(var) + return d + + +#======================================================================================================================= +# SetResolver +#======================================================================================================================= +class SetResolver: + ''' + Resolves a set as dict id(object)->object + ''' + + def get_contents_debug_adapter_protocol(self, obj, fmt=None): + ret = [] + + for i, item in enumerate(obj): + ret.append((str(id(item)), item, None)) + + if i > MAX_ITEMS_TO_HANDLE: + ret.append((TOO_LARGE_ATTR, TOO_LARGE_MSG, None)) + break + + # Needed in case the class extends the built-in type and has some additional fields. + from_default_resolver = defaultResolver.get_contents_debug_adapter_protocol(obj, fmt=fmt) + if from_default_resolver: + ret = from_default_resolver + ret + ret.append((GENERATED_LEN_ATTR_NAME, len(obj), partial(_apply_evaluate_name, evaluate_name='len(%s)'))) + return ret + + def resolve(self, var, attribute): + if attribute in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR): + return None + + try: + attribute = int(attribute) + except: + return getattr(var, attribute) + + for v in var: + if id(v) == attribute: + return v + + raise UnableToResolveVariableException('Unable to resolve %s in %s' % (attribute, var)) + + def get_dictionary(self, var): + d = {} + for i, item in enumerate(var): + d[str(id(item))] = item + + if i > MAX_ITEMS_TO_HANDLE: + d[TOO_LARGE_ATTR] = TOO_LARGE_MSG + break + + # in case if the class extends built-in type and has some additional fields + additional_fields = defaultResolver.get_dictionary(var) + d.update(additional_fields) + d[GENERATED_LEN_ATTR_NAME] = len(var) + return d + + def change_var_from_name(self, container, name, new_value): + # The name given in this case must be the id(item), so, we can actually + # iterate in the set and see which item matches the given id. + + try: + # Check that the new value can actually be added to a set (i.e.: it's hashable/comparable). + set().add(new_value) + except: + return None + + for item in container: + if str(id(item)) == name: + container.remove(item) + container.add(new_value) + return str(id(new_value)) + + return None + + +#======================================================================================================================= +# InstanceResolver +#======================================================================================================================= +class InstanceResolver: + + def resolve(self, var, attribute): + field = var.__class__.getDeclaredField(attribute) + field.setAccessible(True) + return field.get(var) + + def get_dictionary(self, obj): + ret = {} + + declaredFields = obj.__class__.getDeclaredFields() + for i in range(len(declaredFields)): + name = declaredFields[i].getName() + try: + declaredFields[i].setAccessible(True) + ret[name] = declaredFields[i].get(obj) + except: + pydev_log.exception() + + return ret + + +#======================================================================================================================= +# JyArrayResolver +#======================================================================================================================= +class JyArrayResolver: + ''' + This resolves a regular Object[] array from java + ''' + + def resolve(self, var, attribute): + if attribute == GENERATED_LEN_ATTR_NAME: + return None + return var[int(attribute)] + + def get_dictionary(self, obj): + ret = {} + + for i in range(len(obj)): + ret[ i ] = obj[i] + + ret[GENERATED_LEN_ATTR_NAME] = len(obj) + return ret + + +#======================================================================================================================= +# MultiValueDictResolver +#======================================================================================================================= +class MultiValueDictResolver(DictResolver): + + def resolve(self, dct, key): + if key in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR): + return None + + # ok, we have to iterate over the items to find the one that matches the id, because that's the only way + # to actually find the reference from the string we have before. + expected_id = int(key.split('(')[-1][:-1]) + for key in list(dct.keys()): + val = dct.getlist(key) + if id(key) == expected_id: + return val + + raise UnableToResolveVariableException() + + +#======================================================================================================================= +# DjangoFormResolver +#======================================================================================================================= +class DjangoFormResolver(DefaultResolver): + + def get_dictionary(self, var, names=None): + # Do not call self.errors because it is a property and has side effects. + names, used___dict__ = self.get_names(var) + + has_errors_attr = False + if "errors" in names: + has_errors_attr = True + names.remove("errors") + + d = defaultResolver.get_dictionary(var, names=names, used___dict__=used___dict__) + if has_errors_attr: + try: + errors_attr = getattr(var, "_errors") + except: + errors_attr = None + d["errors"] = errors_attr + return d + + +#======================================================================================================================= +# DequeResolver +#======================================================================================================================= +class DequeResolver(TupleResolver): + + def get_dictionary(self, var): + d = TupleResolver.get_dictionary(self, var) + d['maxlen'] = getattr(var, 'maxlen', None) + return d + + +#======================================================================================================================= +# OrderedDictResolver +#======================================================================================================================= +class OrderedDictResolver(DictResolver): + + sort_keys = False + + def init_dict(self): + return OrderedDict() + + +#======================================================================================================================= +# FrameResolver +#======================================================================================================================= +class FrameResolver: + ''' + This resolves a frame. + ''' + + def resolve(self, obj, attribute): + if attribute == '__internals__': + return defaultResolver.get_dictionary(obj) + + if attribute == 'stack': + return self.get_frame_stack(obj) + + if attribute == 'f_locals': + return obj.f_locals + + return None + + def get_dictionary(self, obj): + ret = {} + ret['__internals__'] = defaultResolver.get_dictionary(obj) + ret['stack'] = self.get_frame_stack(obj) + ret['f_locals'] = obj.f_locals + return ret + + def get_frame_stack(self, frame): + ret = [] + if frame is not None: + ret.append(self.get_frame_name(frame)) + + while frame.f_back: + frame = frame.f_back + ret.append(self.get_frame_name(frame)) + + return ret + + def get_frame_name(self, frame): + if frame is None: + return 'None' + try: + name = basename(frame.f_code.co_filename) + return 'frame: %s [%s:%s] id:%s' % (frame.f_code.co_name, name, frame.f_lineno, id(frame)) + except: + return 'frame object' + + +defaultResolver = DefaultResolver() +dictResolver = DictResolver() +tupleResolver = TupleResolver() +instanceResolver = InstanceResolver() +jyArrayResolver = JyArrayResolver() +setResolver = SetResolver() +multiValueDictResolver = MultiValueDictResolver() +djangoFormResolver = DjangoFormResolver() +dequeResolver = DequeResolver() +orderedDictResolver = OrderedDictResolver() +frameResolver = FrameResolver() +dapGrouperResolver = DAPGrouperResolver() + + +class InspectStub: + + def isbuiltin(self, _args): + return False + + def isroutine(self, object): + return False + + +try: + import inspect +except: + inspect = InspectStub() + + +def get_var_scope(attr_name, attr_value, evaluate_name, handle_return_values): + if attr_name.startswith("'"): + if attr_name.endswith("'"): + attr_name = attr_name[1:-1] + else: + i = attr_name.find("__' (") + if i >= 0: + # Handle attr_name such as: >>'__name__' (1732494379184)<< + attr_name = attr_name[1: i + 2] + + if handle_return_values and attr_name == RETURN_VALUES_DICT: + return '' + + elif attr_name == GENERATED_LEN_ATTR_NAME: + return '' + + if attr_name.startswith('__') and attr_name.endswith('__'): + return DAPGrouper.SCOPE_SPECIAL_VARS + + if attr_name.startswith('_') or attr_name.endswith('__'): + return DAPGrouper.SCOPE_PROTECTED_VARS + + try: + if inspect.isroutine(attr_value) or isinstance(attr_value, MethodWrapperType): + return DAPGrouper.SCOPE_FUNCTION_VARS + + elif inspect.isclass(attr_value): + return DAPGrouper.SCOPE_CLASS_VARS + except: + # It's possible that isinstance throws an exception when dealing with user-code. + if DebugInfoHolder.DEBUG_TRACE_LEVEL > 0: + pydev_log.exception() + + return '' diff --git a/_pydevd_bundle/pydevd_safe_repr.py b/_pydevd_bundle/pydevd_safe_repr.py new file mode 100644 index 0000000..f1b64b7 --- /dev/null +++ b/_pydevd_bundle/pydevd_safe_repr.py @@ -0,0 +1,399 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See LICENSE in the project root +# for license information. + +# Gotten from ptvsd for supporting the format expected there. +import sys +from _pydevd_bundle.pydevd_constants import IS_PY36_OR_GREATER +import locale +from _pydev_bundle import pydev_log + + +class SafeRepr(object): + # Can be used to override the encoding from locale.getpreferredencoding() + locale_preferred_encoding = None + + # Can be used to override the encoding used for sys.stdout.encoding + sys_stdout_encoding = None + + # String types are truncated to maxstring_outer when at the outer- + # most level, and truncated to maxstring_inner characters inside + # collections. + maxstring_outer = 2 ** 16 + maxstring_inner = 30 + string_types = (str, bytes) + bytes = bytes + set_info = (set, '{', '}', False) + frozenset_info = (frozenset, 'frozenset({', '})', False) + int_types = (int,) + long_iter_types = (list, tuple, bytearray, range, + dict, set, frozenset) + + # Collection types are recursively iterated for each limit in + # maxcollection. + maxcollection = (15, 10) + + # Specifies type, prefix string, suffix string, and whether to include a + # comma if there is only one element. (Using a sequence rather than a + # mapping because we use isinstance() to determine the matching type.) + collection_types = [ + (tuple, '(', ')', True), + (list, '[', ']', False), + frozenset_info, + set_info, + ] + try: + from collections import deque + collection_types.append((deque, 'deque([', '])', False)) + except Exception: + pass + + # type, prefix string, suffix string, item prefix string, + # item key/value separator, item suffix string + dict_types = [(dict, '{', '}', '', ': ', '')] + try: + from collections import OrderedDict + dict_types.append((OrderedDict, 'OrderedDict([', '])', '(', ', ', ')')) + except Exception: + pass + + # All other types are treated identically to strings, but using + # different limits. + maxother_outer = 2 ** 16 + maxother_inner = 30 + + convert_to_hex = False + raw_value = False + + def __call__(self, obj): + ''' + :param object obj: + The object for which we want a representation. + + :return str: + Returns bytes encoded as utf-8 on py2 and str on py3. + ''' + try: + return ''.join(self._repr(obj, 0)) + except Exception: + try: + return 'An exception was raised: %r' % sys.exc_info()[1] + except Exception: + return 'An exception was raised' + + def _repr(self, obj, level): + '''Returns an iterable of the parts in the final repr string.''' + + try: + obj_repr = type(obj).__repr__ + except Exception: + obj_repr = None + + def has_obj_repr(t): + r = t.__repr__ + try: + return obj_repr == r + except Exception: + return obj_repr is r + + for t, prefix, suffix, comma in self.collection_types: + if isinstance(obj, t) and has_obj_repr(t): + return self._repr_iter(obj, level, prefix, suffix, comma) + + for t, prefix, suffix, item_prefix, item_sep, item_suffix in self.dict_types: # noqa + if isinstance(obj, t) and has_obj_repr(t): + return self._repr_dict(obj, level, prefix, suffix, + item_prefix, item_sep, item_suffix) + + for t in self.string_types: + if isinstance(obj, t) and has_obj_repr(t): + return self._repr_str(obj, level) + + if self._is_long_iter(obj): + return self._repr_long_iter(obj) + + return self._repr_other(obj, level) + + # Determines whether an iterable exceeds the limits set in + # maxlimits, and is therefore unsafe to repr(). + def _is_long_iter(self, obj, level=0): + try: + # Strings have their own limits (and do not nest). Because + # they don't have __iter__ in 2.x, this check goes before + # the next one. + if isinstance(obj, self.string_types): + return len(obj) > self.maxstring_inner + + # If it's not an iterable (and not a string), it's fine. + if not hasattr(obj, '__iter__'): + return False + + # If it's not an instance of these collection types then it + # is fine. Note: this is a fix for + # https://github.com/Microsoft/ptvsd/issues/406 + if not isinstance(obj, self.long_iter_types): + return False + + # Iterable is its own iterator - this is a one-off iterable + # like generator or enumerate(). We can't really count that, + # but repr() for these should not include any elements anyway, + # so we can treat it the same as non-iterables. + if obj is iter(obj): + return False + + # range reprs fine regardless of length. + if isinstance(obj, range): + return False + + # numpy and scipy collections (ndarray etc) have + # self-truncating repr, so they're always safe. + try: + module = type(obj).__module__.partition('.')[0] + if module in ('numpy', 'scipy'): + return False + except Exception: + pass + + # Iterables that nest too deep are considered long. + if level >= len(self.maxcollection): + return True + + # It is too long if the length exceeds the limit, or any + # of its elements are long iterables. + if hasattr(obj, '__len__'): + try: + size = len(obj) + except Exception: + size = None + if size is not None and size > self.maxcollection[level]: + return True + return any((self._is_long_iter(item, level + 1) for item in obj)) # noqa + return any(i > self.maxcollection[level] or self._is_long_iter(item, level + 1) for i, item in enumerate(obj)) # noqa + + except Exception: + # If anything breaks, assume the worst case. + return True + + def _repr_iter(self, obj, level, prefix, suffix, + comma_after_single_element=False): + yield prefix + + if level >= len(self.maxcollection): + yield '...' + else: + count = self.maxcollection[level] + yield_comma = False + for item in obj: + if yield_comma: + yield ', ' + yield_comma = True + + count -= 1 + if count <= 0: + yield '...' + break + + for p in self._repr(item, 100 if item is obj else level + 1): + yield p + else: + if comma_after_single_element: + if count == self.maxcollection[level] - 1: + yield ',' + yield suffix + + def _repr_long_iter(self, obj): + try: + length = hex(len(obj)) if self.convert_to_hex else len(obj) + obj_repr = '<%s, len() = %s>' % (type(obj).__name__, length) + except Exception: + try: + obj_repr = '<' + type(obj).__name__ + '>' + except Exception: + obj_repr = '' + yield obj_repr + + def _repr_dict(self, obj, level, prefix, suffix, + item_prefix, item_sep, item_suffix): + if not obj: + yield prefix + suffix + return + if level >= len(self.maxcollection): + yield prefix + '...' + suffix + return + + yield prefix + + count = self.maxcollection[level] + yield_comma = False + + if IS_PY36_OR_GREATER: + # On Python 3.6 (onwards) dictionaries now keep + # insertion order. + sorted_keys = list(obj) + else: + try: + sorted_keys = sorted(obj) + except Exception: + sorted_keys = list(obj) + + for key in sorted_keys: + if yield_comma: + yield ', ' + yield_comma = True + + count -= 1 + if count <= 0: + yield '...' + break + + yield item_prefix + for p in self._repr(key, level + 1): + yield p + + yield item_sep + + try: + item = obj[key] + except Exception: + yield '' + else: + for p in self._repr(item, 100 if item is obj else level + 1): + yield p + yield item_suffix + + yield suffix + + def _repr_str(self, obj, level): + try: + if self.raw_value: + # For raw value retrieval, ignore all limits. + if isinstance(obj, bytes): + yield obj.decode('latin-1') + else: + yield obj + return + + limit_inner = self.maxother_inner + limit_outer = self.maxother_outer + limit = limit_inner if level > 0 else limit_outer + if len(obj) <= limit: + # Note that we check the limit before doing the repr (so, the final string + # may actually be considerably bigger on some cases, as besides + # the additional u, b, ' chars, some chars may be escaped in repr, so + # even a single char such as \U0010ffff may end up adding more + # chars than expected). + yield self._convert_to_unicode_or_bytes_repr(repr(obj)) + return + + # Slightly imprecise calculations - we may end up with a string that is + # up to 6 characters longer than limit. If you need precise formatting, + # you are using the wrong class. + left_count, right_count = max(1, int(2 * limit / 3)), max(1, int(limit / 3)) # noqa + + # Important: only do repr after slicing to avoid duplicating a byte array that could be + # huge. + + # Note: we don't deal with high surrogates here because we're not dealing with the + # repr() of a random object. + # i.e.: A high surrogate unicode char may be splitted on Py2, but as we do a `repr` + # afterwards, that's ok. + + # Also, we just show the unicode/string/bytes repr() directly to make clear what the + # input type was (so, on py2 a unicode would start with u' and on py3 a bytes would + # start with b'). + + part1 = obj[:left_count] + part1 = repr(part1) + part1 = part1[:part1.rindex("'")] # Remove the last ' + + part2 = obj[-right_count:] + part2 = repr(part2) + part2 = part2[part2.index("'") + 1:] # Remove the first ' (and possibly u or b). + + yield part1 + yield '...' + yield part2 + except: + # This shouldn't really happen, but let's play it safe. + pydev_log.exception('Error getting string representation to show.') + for part in self._repr_obj(obj, level, + self.maxother_inner, self.maxother_outer): + yield part + + def _repr_other(self, obj, level): + return self._repr_obj(obj, level, + self.maxother_inner, self.maxother_outer) + + def _repr_obj(self, obj, level, limit_inner, limit_outer): + try: + if self.raw_value: + # For raw value retrieval, ignore all limits. + if isinstance(obj, bytes): + yield obj.decode('latin-1') + return + + try: + mv = memoryview(obj) + except Exception: + yield self._convert_to_unicode_or_bytes_repr(repr(obj)) + return + else: + # Map bytes to Unicode codepoints with same values. + yield mv.tobytes().decode('latin-1') + return + elif self.convert_to_hex and isinstance(obj, self.int_types): + obj_repr = hex(obj) + else: + obj_repr = repr(obj) + except Exception: + try: + obj_repr = object.__repr__(obj) + except Exception: + try: + obj_repr = '' # noqa + except Exception: + obj_repr = '' + + limit = limit_inner if level > 0 else limit_outer + + if limit >= len(obj_repr): + yield self._convert_to_unicode_or_bytes_repr(obj_repr) + return + + # Slightly imprecise calculations - we may end up with a string that is + # up to 3 characters longer than limit. If you need precise formatting, + # you are using the wrong class. + left_count, right_count = max(1, int(2 * limit / 3)), max(1, int(limit / 3)) # noqa + + yield obj_repr[:left_count] + yield '...' + yield obj_repr[-right_count:] + + def _convert_to_unicode_or_bytes_repr(self, obj_repr): + return obj_repr + + def _bytes_as_unicode_if_possible(self, obj_repr): + # We try to decode with 3 possible encoding (sys.stdout.encoding, + # locale.getpreferredencoding() and 'utf-8). If no encoding can decode + # the input, we return the original bytes. + try_encodings = [] + encoding = self.sys_stdout_encoding or getattr(sys.stdout, 'encoding', '') + if encoding: + try_encodings.append(encoding.lower()) + + preferred_encoding = self.locale_preferred_encoding or locale.getpreferredencoding() + if preferred_encoding: + preferred_encoding = preferred_encoding.lower() + if preferred_encoding not in try_encodings: + try_encodings.append(preferred_encoding) + + if 'utf-8' not in try_encodings: + try_encodings.append('utf-8') + + for encoding in try_encodings: + try: + return obj_repr.decode(encoding) + except UnicodeDecodeError: + pass + + return obj_repr # Return the original version (in bytes) diff --git a/_pydevd_bundle/pydevd_save_locals.py b/_pydevd_bundle/pydevd_save_locals.py new file mode 100644 index 0000000..fa1a125 --- /dev/null +++ b/_pydevd_bundle/pydevd_save_locals.py @@ -0,0 +1,96 @@ +""" +Utility for saving locals. +""" +import sys + +try: + import types + + frame_type = types.FrameType +except: + frame_type = type(sys._getframe()) + + +def is_save_locals_available(): + return save_locals_impl is not None + + +def save_locals(frame): + """ + Copy values from locals_dict into the fast stack slots in the given frame. + + Note: the 'save_locals' branch had a different approach wrapping the frame (much more code, but it gives ideas + on how to save things partially, not the 'whole' locals). + """ + if not isinstance(frame, frame_type): + # Fix exception when changing Django variable (receiving DjangoTemplateFrame) + return + + if save_locals_impl is not None: + try: + save_locals_impl(frame) + except: + pass + + +def make_save_locals_impl(): + """ + Factory for the 'save_locals_impl' method. This may seem like a complicated pattern but it is essential that the method is created at + module load time. Inner imports after module load time would cause an occasional debugger deadlock due to the importer lock and debugger + lock being taken in different order in different threads. + """ + try: + if '__pypy__' in sys.builtin_module_names: + import __pypy__ # @UnresolvedImport + save_locals = __pypy__.locals_to_fast + except: + pass + else: + if '__pypy__' in sys.builtin_module_names: + + def save_locals_pypy_impl(frame): + save_locals(frame) + + return save_locals_pypy_impl + + try: + import ctypes + locals_to_fast = ctypes.pythonapi.PyFrame_LocalsToFast + except: + pass + else: + + def save_locals_ctypes_impl(frame): + locals_to_fast(ctypes.py_object(frame), ctypes.c_int(0)) + + return save_locals_ctypes_impl + + return None + + +save_locals_impl = make_save_locals_impl() + + +def update_globals_and_locals(updated_globals, initial_globals, frame): + # We don't have the locals and passed all in globals, so, we have to + # manually choose how to update the variables. + # + # Note that the current implementation is a bit tricky: it does work in general + # but if we do something as 'some_var = 10' and 'some_var' is already defined to have + # the value '10' in the globals, we won't actually put that value in the locals + # (which means that the frame locals won't be updated). + # Still, the approach to have a single namespace was chosen because it was the only + # one that enabled creating and using variables during the same evaluation. + assert updated_globals is not None + f_locals = None + for key, val in updated_globals.items(): + if initial_globals.get(key) is not val: + if f_locals is None: + # Note: we call f_locals only once because each time + # we call it the values may be reset. + f_locals = frame.f_locals + + f_locals[key] = val + + if f_locals is not None: + save_locals(frame) diff --git a/_pydevd_bundle/pydevd_signature.py b/_pydevd_bundle/pydevd_signature.py new file mode 100644 index 0000000..3877e62 --- /dev/null +++ b/_pydevd_bundle/pydevd_signature.py @@ -0,0 +1,201 @@ +from _pydev_bundle import pydev_log + +try: + import trace +except ImportError: + pass +else: + trace._warn = lambda *args: None # workaround for http://bugs.python.org/issue17143 (PY-8706) + +import os +from _pydevd_bundle.pydevd_comm import CMD_SIGNATURE_CALL_TRACE, NetCommand +from _pydevd_bundle import pydevd_xml +from _pydevd_bundle.pydevd_utils import get_clsname_for_code + + +class Signature(object): + + def __init__(self, file, name): + self.file = file + self.name = name + self.args = [] + self.args_str = [] + self.return_type = None + + def add_arg(self, name, type): + self.args.append((name, type)) + self.args_str.append("%s:%s" % (name, type)) + + def set_args(self, frame, recursive=False): + self.args = [] + + code = frame.f_code + locals = frame.f_locals + + for i in range(0, code.co_argcount): + name = code.co_varnames[i] + class_name = get_type_of_value(locals[name], recursive=recursive) + + self.add_arg(name, class_name) + + def __str__(self): + return "%s %s(%s)" % (self.file, self.name, ", ".join(self.args_str)) + + +def get_type_of_value(value, ignore_module_name=('__main__', '__builtin__', 'builtins'), recursive=False): + tp = type(value) + class_name = tp.__name__ + if class_name == 'instance': # old-style classes + tp = value.__class__ + class_name = tp.__name__ + + if hasattr(tp, '__module__') and tp.__module__ and tp.__module__ not in ignore_module_name: + class_name = "%s.%s" % (tp.__module__, class_name) + + if class_name == 'list': + class_name = 'List' + if len(value) > 0 and recursive: + class_name += '[%s]' % get_type_of_value(value[0], recursive=recursive) + return class_name + + if class_name == 'dict': + class_name = 'Dict' + if len(value) > 0 and recursive: + for (k, v) in value.items(): + class_name += '[%s, %s]' % (get_type_of_value(k, recursive=recursive), + get_type_of_value(v, recursive=recursive)) + break + return class_name + + if class_name == 'tuple': + class_name = 'Tuple' + if len(value) > 0 and recursive: + class_name += '[' + class_name += ', '.join(get_type_of_value(v, recursive=recursive) for v in value) + class_name += ']' + + return class_name + + +def _modname(path): + """Return a plausible module name for the path""" + base = os.path.basename(path) + filename, ext = os.path.splitext(base) + return filename + + +class SignatureFactory(object): + + def __init__(self): + self._caller_cache = {} + self.cache = CallSignatureCache() + + def create_signature(self, frame, filename, with_args=True): + try: + _, modulename, funcname = self.file_module_function_of(frame) + signature = Signature(filename, funcname) + if with_args: + signature.set_args(frame, recursive=True) + return signature + except: + pydev_log.exception() + + def file_module_function_of(self, frame): # this code is take from trace module and fixed to work with new-style classes + code = frame.f_code + filename = code.co_filename + if filename: + modulename = _modname(filename) + else: + modulename = None + + funcname = code.co_name + clsname = None + if code in self._caller_cache: + if self._caller_cache[code] is not None: + clsname = self._caller_cache[code] + else: + self._caller_cache[code] = None + clsname = get_clsname_for_code(code, frame) + if clsname is not None: + # cache the result - assumption is that new.* is + # not called later to disturb this relationship + # _caller_cache could be flushed if functions in + # the new module get called. + self._caller_cache[code] = clsname + + if clsname is not None: + funcname = "%s.%s" % (clsname, funcname) + + return filename, modulename, funcname + + +def get_signature_info(signature): + return signature.file, signature.name, ' '.join([arg[1] for arg in signature.args]) + + +def get_frame_info(frame): + co = frame.f_code + return co.co_name, frame.f_lineno, co.co_filename + + +class CallSignatureCache(object): + + def __init__(self): + self.cache = {} + + def add(self, signature): + filename, name, args_type = get_signature_info(signature) + calls_from_file = self.cache.setdefault(filename, {}) + name_calls = calls_from_file.setdefault(name, {}) + name_calls[args_type] = None + + def is_in_cache(self, signature): + filename, name, args_type = get_signature_info(signature) + if args_type in self.cache.get(filename, {}).get(name, {}): + return True + return False + + +def create_signature_message(signature): + cmdTextList = [""] + + cmdTextList.append('' % (pydevd_xml.make_valid_xml_value(signature.file), pydevd_xml.make_valid_xml_value(signature.name))) + + for arg in signature.args: + cmdTextList.append('' % (pydevd_xml.make_valid_xml_value(arg[0]), pydevd_xml.make_valid_xml_value(arg[1]))) + + if signature.return_type is not None: + cmdTextList.append('' % (pydevd_xml.make_valid_xml_value(signature.return_type))) + + cmdTextList.append("") + cmdText = ''.join(cmdTextList) + return NetCommand(CMD_SIGNATURE_CALL_TRACE, 0, cmdText) + + +def send_signature_call_trace(dbg, frame, filename): + if dbg.signature_factory and dbg.in_project_scope(frame): + signature = dbg.signature_factory.create_signature(frame, filename) + if signature is not None: + if dbg.signature_factory.cache is not None: + if not dbg.signature_factory.cache.is_in_cache(signature): + dbg.signature_factory.cache.add(signature) + dbg.writer.add_command(create_signature_message(signature)) + return True + else: + # we don't send signature if it is cached + return False + else: + dbg.writer.add_command(create_signature_message(signature)) + return True + return False + + +def send_signature_return_trace(dbg, frame, filename, return_value): + if dbg.signature_factory and dbg.in_project_scope(frame): + signature = dbg.signature_factory.create_signature(frame, filename, with_args=False) + signature.return_type = get_type_of_value(return_value, recursive=True) + dbg.writer.add_command(create_signature_message(signature)) + return True + + return False + diff --git a/_pydevd_bundle/pydevd_source_mapping.py b/_pydevd_bundle/pydevd_source_mapping.py new file mode 100644 index 0000000..5455307 --- /dev/null +++ b/_pydevd_bundle/pydevd_source_mapping.py @@ -0,0 +1,153 @@ +import bisect +from _pydevd_bundle.pydevd_constants import NULL, KeyifyList +import pydevd_file_utils + + +class SourceMappingEntry(object): + + __slots__ = ['source_filename', 'line', 'end_line', 'runtime_line', 'runtime_source'] + + def __init__(self, line, end_line, runtime_line, runtime_source): + assert isinstance(runtime_source, str) + + self.line = int(line) + self.end_line = int(end_line) + self.runtime_line = int(runtime_line) + self.runtime_source = runtime_source # Something as + + # Should be set after translated to server (absolute_source_filename). + # This is what's sent to the client afterwards (so, its case should not be normalized). + self.source_filename = None + + def contains_line(self, i): + return self.line <= i <= self.end_line + + def contains_runtime_line(self, i): + line_count = self.end_line + self.line + runtime_end_line = self.runtime_line + line_count + return self.runtime_line <= i <= runtime_end_line + + def __str__(self): + return 'SourceMappingEntry(%s)' % ( + ', '.join('%s=%r' % (attr, getattr(self, attr)) for attr in self.__slots__)) + + __repr__ = __str__ + + +class SourceMapping(object): + + def __init__(self, on_source_mapping_changed=NULL): + self._mappings_to_server = {} # dict(normalized(file.py) to [SourceMappingEntry]) + self._mappings_to_client = {} # dict( to File.py) + self._cache = {} + self._on_source_mapping_changed = on_source_mapping_changed + + def set_source_mapping(self, absolute_filename, mapping): + ''' + :param str absolute_filename: + The filename for the source mapping (bytes on py2 and str on py3). + + :param list(SourceMappingEntry) mapping: + A list with the source mapping entries to be applied to the given filename. + + :return str: + An error message if it was not possible to set the mapping or an empty string if + everything is ok. + ''' + # Let's first validate if it's ok to apply that mapping. + # File mappings must be 1:N, not M:N (i.e.: if there's a mapping from file1.py to , + # there can be no other mapping from any other file to ). + # This is a limitation to make it easier to remove existing breakpoints when new breakpoints are + # set to a file (so, any file matching that breakpoint can be removed instead of needing to check + # which lines are corresponding to that file). + for map_entry in mapping: + existing_source_filename = self._mappings_to_client.get(map_entry.runtime_source) + if existing_source_filename and existing_source_filename != absolute_filename: + return 'Cannot apply mapping from %s to %s (it conflicts with mapping: %s to %s)' % ( + absolute_filename, map_entry.runtime_source, existing_source_filename, map_entry.runtime_source) + + try: + absolute_normalized_filename = pydevd_file_utils.normcase(absolute_filename) + current_mapping = self._mappings_to_server.get(absolute_normalized_filename, []) + for map_entry in current_mapping: + del self._mappings_to_client[map_entry.runtime_source] + + self._mappings_to_server[absolute_normalized_filename] = sorted(mapping, key=lambda entry:entry.line) + + for map_entry in mapping: + self._mappings_to_client[map_entry.runtime_source] = absolute_filename + finally: + self._cache.clear() + self._on_source_mapping_changed() + return '' + + def map_to_client(self, runtime_source_filename, lineno): + key = (lineno, 'client', runtime_source_filename) + try: + return self._cache[key] + except KeyError: + for _, mapping in list(self._mappings_to_server.items()): + for map_entry in mapping: + if map_entry.runtime_source == runtime_source_filename: # + if map_entry.contains_runtime_line(lineno): # matches line range + self._cache[key] = (map_entry.source_filename, map_entry.line + (lineno - map_entry.runtime_line), True) + return self._cache[key] + + self._cache[key] = (runtime_source_filename, lineno, False) # Mark that no translation happened in the cache. + return self._cache[key] + + def has_mapping_entry(self, runtime_source_filename): + ''' + :param runtime_source_filename: + Something as + ''' + # Note that we're not interested in the line here, just on knowing if a given filename + # (from the server) has a mapping for it. + key = ('has_entry', runtime_source_filename) + try: + return self._cache[key] + except KeyError: + for _absolute_normalized_filename, mapping in list(self._mappings_to_server.items()): + for map_entry in mapping: + if map_entry.runtime_source == runtime_source_filename: + self._cache[key] = True + return self._cache[key] + + self._cache[key] = False + return self._cache[key] + + def map_to_server(self, absolute_filename, lineno): + ''' + Convert something as 'file1.py' at line 10 to '' at line 2. + + Note that the name should be already normalized at this point. + ''' + absolute_normalized_filename = pydevd_file_utils.normcase(absolute_filename) + + changed = False + mappings = self._mappings_to_server.get(absolute_normalized_filename) + if mappings: + + i = bisect.bisect(KeyifyList(mappings, lambda entry:entry.line), lineno) + if i >= len(mappings): + i -= 1 + + if i == 0: + entry = mappings[i] + + else: + entry = mappings[i - 1] + + if not entry.contains_line(lineno): + entry = mappings[i] + if not entry.contains_line(lineno): + entry = None + + if entry is not None: + lineno = entry.runtime_line + (lineno - entry.line) + + absolute_filename = entry.runtime_source + changed = True + + return absolute_filename, lineno, changed + diff --git a/_pydevd_bundle/pydevd_stackless.py b/_pydevd_bundle/pydevd_stackless.py new file mode 100644 index 0000000..44bb768 --- /dev/null +++ b/_pydevd_bundle/pydevd_stackless.py @@ -0,0 +1,416 @@ +from __future__ import nested_scopes + +import weakref +import sys + +from _pydevd_bundle.pydevd_comm import get_global_debugger +from _pydevd_bundle.pydevd_constants import call_only_once +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle.pydevd_custom_frames import update_custom_frame, remove_custom_frame, add_custom_frame +import stackless # @UnresolvedImport +from _pydev_bundle import pydev_log + + +# Used so that we don't loose the id (because we'll remove when it's not alive and would generate a new id for the +# same tasklet). +class TaskletToLastId: + ''' + So, why not a WeakKeyDictionary? + The problem is that removals from the WeakKeyDictionary will create a new tasklet (as it adds a callback to + remove the key when it's garbage-collected), so, we can get into a recursion. + ''' + + def __init__(self): + self.tasklet_ref_to_last_id = {} + self._i = 0 + + def get(self, tasklet): + return self.tasklet_ref_to_last_id.get(weakref.ref(tasklet)) + + def __setitem__(self, tasklet, last_id): + self.tasklet_ref_to_last_id[weakref.ref(tasklet)] = last_id + self._i += 1 + if self._i % 100 == 0: # Collect at each 100 additions to the dict (no need to rush). + for tasklet_ref in list(self.tasklet_ref_to_last_id.keys()): + if tasklet_ref() is None: + del self.tasklet_ref_to_last_id[tasklet_ref] + + +_tasklet_to_last_id = TaskletToLastId() + + +#======================================================================================================================= +# _TaskletInfo +#======================================================================================================================= +class _TaskletInfo: + + _last_id = 0 + + def __init__(self, tasklet_weakref, tasklet): + self.frame_id = None + self.tasklet_weakref = tasklet_weakref + + last_id = _tasklet_to_last_id.get(tasklet) + if last_id is None: + _TaskletInfo._last_id += 1 + last_id = _TaskletInfo._last_id + _tasklet_to_last_id[tasklet] = last_id + + self._tasklet_id = last_id + + self.update_name() + + def update_name(self): + tasklet = self.tasklet_weakref() + if tasklet: + if tasklet.blocked: + state = 'blocked' + elif tasklet.paused: + state = 'paused' + elif tasklet.scheduled: + state = 'scheduled' + else: + state = '' + + try: + name = tasklet.name + except AttributeError: + if tasklet.is_main: + name = 'MainTasklet' + else: + name = 'Tasklet-%s' % (self._tasklet_id,) + + thread_id = tasklet.thread_id + if thread_id != -1: + for thread in threading.enumerate(): + if thread.ident == thread_id: + if thread.name: + thread_name = "of %s" % (thread.name,) + else: + thread_name = "of Thread-%s" % (thread.name or str(thread_id),) + break + else: + # should not happen. + thread_name = "of Thread-%s" % (str(thread_id),) + thread = None + else: + # tasklet is no longer bound to a thread, because its thread ended + thread_name = "without thread" + + tid = id(tasklet) + tasklet = None + else: + state = 'dead' + name = 'Tasklet-%s' % (self._tasklet_id,) + thread_name = "" + tid = '-' + self.tasklet_name = '%s %s %s (%s)' % (state, name, thread_name, tid) + + if not hasattr(stackless.tasklet, "trace_function"): + + # bug https://bitbucket.org/stackless-dev/stackless/issue/42 + # is not fixed. Stackless releases before 2014 + def update_name(self): + tasklet = self.tasklet_weakref() + if tasklet: + try: + name = tasklet.name + except AttributeError: + if tasklet.is_main: + name = 'MainTasklet' + else: + name = 'Tasklet-%s' % (self._tasklet_id,) + + thread_id = tasklet.thread_id + for thread in threading.enumerate(): + if thread.ident == thread_id: + if thread.name: + thread_name = "of %s" % (thread.name,) + else: + thread_name = "of Thread-%s" % (thread.name or str(thread_id),) + break + else: + # should not happen. + thread_name = "of Thread-%s" % (str(thread_id),) + thread = None + + tid = id(tasklet) + tasklet = None + else: + name = 'Tasklet-%s' % (self._tasklet_id,) + thread_name = "" + tid = '-' + self.tasklet_name = '%s %s (%s)' % (name, thread_name, tid) + + +_weak_tasklet_registered_to_info = {} + + +#======================================================================================================================= +# get_tasklet_info +#======================================================================================================================= +def get_tasklet_info(tasklet): + return register_tasklet_info(tasklet) + + +#======================================================================================================================= +# register_tasklet_info +#======================================================================================================================= +def register_tasklet_info(tasklet): + r = weakref.ref(tasklet) + info = _weak_tasklet_registered_to_info.get(r) + if info is None: + info = _weak_tasklet_registered_to_info[r] = _TaskletInfo(r, tasklet) + + return info + + +_application_set_schedule_callback = None + + +#======================================================================================================================= +# _schedule_callback +#======================================================================================================================= +def _schedule_callback(prev, next): + ''' + Called when a context is stopped or a new context is made runnable. + ''' + try: + if not prev and not next: + return + + current_frame = sys._getframe() + + if next: + register_tasklet_info(next) + + # Ok, making next runnable: set the tracing facility in it. + debugger = get_global_debugger() + if debugger is not None: + next.trace_function = debugger.get_thread_local_trace_func() + frame = next.frame + if frame is current_frame: + frame = frame.f_back + if hasattr(frame, 'f_trace'): # Note: can be None (but hasattr should cover for that too). + frame.f_trace = debugger.get_thread_local_trace_func() + + debugger = None + + if prev: + register_tasklet_info(prev) + + try: + for tasklet_ref, tasklet_info in list(_weak_tasklet_registered_to_info.items()): # Make sure it's a copy! + tasklet = tasklet_ref() + if tasklet is None or not tasklet.alive: + # Garbage-collected already! + try: + del _weak_tasklet_registered_to_info[tasklet_ref] + except KeyError: + pass + if tasklet_info.frame_id is not None: + remove_custom_frame(tasklet_info.frame_id) + else: + is_running = stackless.get_thread_info(tasklet.thread_id)[1] is tasklet + if tasklet is prev or (tasklet is not next and not is_running): + # the tasklet won't run after this scheduler action: + # - the tasklet is the previous tasklet + # - it is not the next tasklet and it is not an already running tasklet + frame = tasklet.frame + if frame is current_frame: + frame = frame.f_back + if frame is not None: + # print >>sys.stderr, "SchedCB: %r, %d, '%s', '%s'" % (tasklet, frame.f_lineno, _filename, base) + debugger = get_global_debugger() + if debugger is not None and debugger.get_file_type(frame) is None: + tasklet_info.update_name() + if tasklet_info.frame_id is None: + tasklet_info.frame_id = add_custom_frame(frame, tasklet_info.tasklet_name, tasklet.thread_id) + else: + update_custom_frame(tasklet_info.frame_id, frame, tasklet.thread_id, name=tasklet_info.tasklet_name) + debugger = None + + elif tasklet is next or is_running: + if tasklet_info.frame_id is not None: + # Remove info about stackless suspended when it starts to run. + remove_custom_frame(tasklet_info.frame_id) + tasklet_info.frame_id = None + + finally: + tasklet = None + tasklet_info = None + frame = None + + except: + pydev_log.exception() + + if _application_set_schedule_callback is not None: + return _application_set_schedule_callback(prev, next) + + +if not hasattr(stackless.tasklet, "trace_function"): + + # Older versions of Stackless, released before 2014 + # This code does not work reliable! It is affected by several + # stackless bugs: Stackless issues #44, #42, #40 + def _schedule_callback(prev, next): + ''' + Called when a context is stopped or a new context is made runnable. + ''' + try: + if not prev and not next: + return + + if next: + register_tasklet_info(next) + + # Ok, making next runnable: set the tracing facility in it. + debugger = get_global_debugger() + if debugger is not None and next.frame: + if hasattr(next.frame, 'f_trace'): + next.frame.f_trace = debugger.get_thread_local_trace_func() + debugger = None + + if prev: + register_tasklet_info(prev) + + try: + for tasklet_ref, tasklet_info in list(_weak_tasklet_registered_to_info.items()): # Make sure it's a copy! + tasklet = tasklet_ref() + if tasklet is None or not tasklet.alive: + # Garbage-collected already! + try: + del _weak_tasklet_registered_to_info[tasklet_ref] + except KeyError: + pass + if tasklet_info.frame_id is not None: + remove_custom_frame(tasklet_info.frame_id) + else: + if tasklet.paused or tasklet.blocked or tasklet.scheduled: + if tasklet.frame and tasklet.frame.f_back: + f_back = tasklet.frame.f_back + debugger = get_global_debugger() + if debugger is not None and debugger.get_file_type(f_back) is None: + if tasklet_info.frame_id is None: + tasklet_info.frame_id = add_custom_frame(f_back, tasklet_info.tasklet_name, tasklet.thread_id) + else: + update_custom_frame(tasklet_info.frame_id, f_back, tasklet.thread_id) + debugger = None + + elif tasklet.is_current: + if tasklet_info.frame_id is not None: + # Remove info about stackless suspended when it starts to run. + remove_custom_frame(tasklet_info.frame_id) + tasklet_info.frame_id = None + + finally: + tasklet = None + tasklet_info = None + f_back = None + + except: + pydev_log.exception() + + if _application_set_schedule_callback is not None: + return _application_set_schedule_callback(prev, next) + + _original_setup = stackless.tasklet.setup + + #======================================================================================================================= + # setup + #======================================================================================================================= + def setup(self, *args, **kwargs): + ''' + Called to run a new tasklet: rebind the creation so that we can trace it. + ''' + + f = self.tempval + + def new_f(old_f, args, kwargs): + + debugger = get_global_debugger() + if debugger is not None: + debugger.enable_tracing() + + debugger = None + + # Remove our own traces :) + self.tempval = old_f + register_tasklet_info(self) + + # Hover old_f to see the stackless being created and *args and **kwargs to see its parameters. + return old_f(*args, **kwargs) + + # This is the way to tell stackless that the function it should execute is our function, not the original one. Note: + # setting tempval is the same as calling bind(new_f), but it seems that there's no other way to get the currently + # bound function, so, keeping on using tempval instead of calling bind (which is actually the same thing in a better + # API). + + self.tempval = new_f + + return _original_setup(self, f, args, kwargs) + + #======================================================================================================================= + # __call__ + #======================================================================================================================= + def __call__(self, *args, **kwargs): + ''' + Called to run a new tasklet: rebind the creation so that we can trace it. + ''' + + return setup(self, *args, **kwargs) + + _original_run = stackless.run + + #======================================================================================================================= + # run + #======================================================================================================================= + def run(*args, **kwargs): + debugger = get_global_debugger() + if debugger is not None: + debugger.enable_tracing() + debugger = None + + return _original_run(*args, **kwargs) + + +#======================================================================================================================= +# patch_stackless +#======================================================================================================================= +def patch_stackless(): + ''' + This function should be called to patch the stackless module so that new tasklets are properly tracked in the + debugger. + ''' + global _application_set_schedule_callback + _application_set_schedule_callback = stackless.set_schedule_callback(_schedule_callback) + + def set_schedule_callback(callable): + global _application_set_schedule_callback + old = _application_set_schedule_callback + _application_set_schedule_callback = callable + return old + + def get_schedule_callback(): + global _application_set_schedule_callback + return _application_set_schedule_callback + + set_schedule_callback.__doc__ = stackless.set_schedule_callback.__doc__ + if hasattr(stackless, "get_schedule_callback"): + get_schedule_callback.__doc__ = stackless.get_schedule_callback.__doc__ + stackless.set_schedule_callback = set_schedule_callback + stackless.get_schedule_callback = get_schedule_callback + + if not hasattr(stackless.tasklet, "trace_function"): + # Older versions of Stackless, released before 2014 + __call__.__doc__ = stackless.tasklet.__call__.__doc__ + stackless.tasklet.__call__ = __call__ + + setup.__doc__ = stackless.tasklet.setup.__doc__ + stackless.tasklet.setup = setup + + run.__doc__ = stackless.run.__doc__ + stackless.run = run + + +patch_stackless = call_only_once(patch_stackless) diff --git a/_pydevd_bundle/pydevd_suspended_frames.py b/_pydevd_bundle/pydevd_suspended_frames.py new file mode 100644 index 0000000..955ba9a --- /dev/null +++ b/_pydevd_bundle/pydevd_suspended_frames.py @@ -0,0 +1,533 @@ +from contextlib import contextmanager +import sys + +from _pydevd_bundle.pydevd_constants import get_frame, RETURN_VALUES_DICT, \ + ForkSafeLock, GENERATED_LEN_ATTR_NAME, silence_warnings_decorator +from _pydevd_bundle.pydevd_xml import get_variable_details, get_type +from _pydev_bundle.pydev_override import overrides +from _pydevd_bundle.pydevd_resolver import sorted_attributes_key, TOO_LARGE_ATTR, get_var_scope +from _pydevd_bundle.pydevd_safe_repr import SafeRepr +from _pydev_bundle import pydev_log +from _pydevd_bundle import pydevd_vars +from _pydev_bundle.pydev_imports import Exec +from _pydevd_bundle.pydevd_frame_utils import FramesList +from _pydevd_bundle.pydevd_utils import ScopeRequest, DAPGrouper, Timer + + +class _AbstractVariable(object): + + # Default attributes in class, set in instance. + + name = None + value = None + evaluate_name = None + + def __init__(self, py_db): + assert py_db is not None + self.py_db = py_db + + def get_name(self): + return self.name + + def get_value(self): + return self.value + + def get_variable_reference(self): + return id(self.value) + + def get_var_data(self, fmt=None, **safe_repr_custom_attrs): + ''' + :param dict fmt: + Format expected by the DAP (keys: 'hex': bool, 'rawString': bool) + ''' + timer = Timer() + safe_repr = SafeRepr() + if fmt is not None: + safe_repr.convert_to_hex = fmt.get('hex', False) + safe_repr.raw_value = fmt.get('rawString', False) + for key, val in safe_repr_custom_attrs.items(): + setattr(safe_repr, key, val) + + type_name, _type_qualifier, _is_exception_on_eval, resolver, value = get_variable_details( + self.value, to_string=safe_repr) + + is_raw_string = type_name in ('str', 'bytes', 'bytearray') + + attributes = [] + + if is_raw_string: + attributes.append('rawString') + + name = self.name + + if self._is_return_value: + attributes.append('readOnly') + name = '(return) %s' % (name,) + + elif name in (TOO_LARGE_ATTR, GENERATED_LEN_ATTR_NAME): + attributes.append('readOnly') + + try: + if self.value.__class__ == DAPGrouper: + type_name = '' + except: + pass # Ignore errors accessing __class__. + + var_data = { + 'name': name, + 'value': value, + 'type': type_name, + } + + if self.evaluate_name is not None: + var_data['evaluateName'] = self.evaluate_name + + if resolver is not None: # I.e.: it's a container + var_data['variablesReference'] = self.get_variable_reference() + else: + var_data['variablesReference'] = 0 # It's mandatory (although if == 0 it doesn't have children). + + if len(attributes) > 0: + var_data['presentationHint'] = {'attributes': attributes} + + timer.report_if_compute_repr_attr_slow('', name, type_name) + return var_data + + def get_children_variables(self, fmt=None, scope=None): + raise NotImplementedError() + + def get_child_variable_named(self, name, fmt=None, scope=None): + for child_var in self.get_children_variables(fmt=fmt, scope=scope): + if child_var.get_name() == name: + return child_var + return None + + def _group_entries(self, lst, handle_return_values): + scope_to_grouper = {} + + group_entries = [] + if isinstance(self.value, DAPGrouper): + new_lst = lst + else: + new_lst = [] + get_presentation = self.py_db.variable_presentation.get_presentation + # Now that we have the contents, group items. + for attr_name, attr_value, evaluate_name in lst: + scope = get_var_scope(attr_name, attr_value, evaluate_name, handle_return_values) + + entry = (attr_name, attr_value, evaluate_name) + if scope: + presentation = get_presentation(scope) + if presentation == 'hide': + continue + + elif presentation == 'inline': + new_lst.append(entry) + + else: # group + if scope not in scope_to_grouper: + grouper = DAPGrouper(scope) + scope_to_grouper[scope] = grouper + else: + grouper = scope_to_grouper[scope] + + grouper.contents_debug_adapter_protocol.append(entry) + + else: + new_lst.append(entry) + + for scope in DAPGrouper.SCOPES_SORTED: + grouper = scope_to_grouper.get(scope) + if grouper is not None: + group_entries.append((scope, grouper, None)) + + return new_lst, group_entries + + +class _ObjectVariable(_AbstractVariable): + + def __init__(self, py_db, name, value, register_variable, is_return_value=False, evaluate_name=None, frame=None): + _AbstractVariable.__init__(self, py_db) + self.frame = frame + self.name = name + self.value = value + self._register_variable = register_variable + self._register_variable(self) + self._is_return_value = is_return_value + self.evaluate_name = evaluate_name + + @silence_warnings_decorator + @overrides(_AbstractVariable.get_children_variables) + def get_children_variables(self, fmt=None, scope=None): + _type, _type_name, resolver = get_type(self.value) + + children_variables = [] + if resolver is not None: # i.e.: it's a container. + if hasattr(resolver, 'get_contents_debug_adapter_protocol'): + # The get_contents_debug_adapter_protocol needs to return sorted. + lst = resolver.get_contents_debug_adapter_protocol(self.value, fmt=fmt) + else: + # If there's no special implementation, the default is sorting the keys. + dct = resolver.get_dictionary(self.value) + lst = sorted(dct.items(), key=lambda tup: sorted_attributes_key(tup[0])) + # No evaluate name in this case. + lst = [(key, value, None) for (key, value) in lst] + + lst, group_entries = self._group_entries(lst, handle_return_values=False) + if group_entries: + lst = group_entries + lst + parent_evaluate_name = self.evaluate_name + if parent_evaluate_name: + for key, val, evaluate_name in lst: + if evaluate_name is not None: + if callable(evaluate_name): + evaluate_name = evaluate_name(parent_evaluate_name) + else: + evaluate_name = parent_evaluate_name + evaluate_name + variable = _ObjectVariable( + self.py_db, key, val, self._register_variable, evaluate_name=evaluate_name, frame=self.frame) + children_variables.append(variable) + else: + for key, val, evaluate_name in lst: + # No evaluate name + variable = _ObjectVariable(self.py_db, key, val, self._register_variable, frame=self.frame) + children_variables.append(variable) + + return children_variables + + def change_variable(self, name, value, py_db, fmt=None): + + children_variable = self.get_child_variable_named(name) + if children_variable is None: + return None + + var_data = children_variable.get_var_data() + evaluate_name = var_data.get('evaluateName') + + if not evaluate_name: + # Note: right now we only pass control to the resolver in the cases where + # there's no evaluate name (the idea being that if we can evaluate it, + # we can use that evaluation to set the value too -- if in the future + # a case where this isn't true is found this logic may need to be changed). + _type, _type_name, container_resolver = get_type(self.value) + if hasattr(container_resolver, 'change_var_from_name'): + try: + new_value = eval(value) + except: + return None + new_key = container_resolver.change_var_from_name(self.value, name, new_value) + if new_key is not None: + return _ObjectVariable( + self.py_db, new_key, new_value, self._register_variable, evaluate_name=None, frame=self.frame) + + return None + else: + return None + + frame = self.frame + if frame is None: + return None + + try: + # This handles the simple cases (such as dict, list, object) + Exec('%s=%s' % (evaluate_name, value), frame.f_globals, frame.f_locals) + except: + return None + + return self.get_child_variable_named(name, fmt=fmt) + + +def sorted_variables_key(obj): + return sorted_attributes_key(obj.name) + + +class _FrameVariable(_AbstractVariable): + + def __init__(self, py_db, frame, register_variable): + _AbstractVariable.__init__(self, py_db) + self.frame = frame + + self.name = self.frame.f_code.co_name + self.value = frame + + self._register_variable = register_variable + self._register_variable(self) + + def change_variable(self, name, value, py_db, fmt=None): + frame = self.frame + + pydevd_vars.change_attr_expression(frame, name, value, py_db) + + return self.get_child_variable_named(name, fmt=fmt) + + @silence_warnings_decorator + @overrides(_AbstractVariable.get_children_variables) + def get_children_variables(self, fmt=None, scope=None): + children_variables = [] + if scope is not None: + assert isinstance(scope, ScopeRequest) + scope = scope.scope + + if scope in ('locals', None): + dct = self.frame.f_locals + elif scope == 'globals': + dct = self.frame.f_globals + else: + raise AssertionError('Unexpected scope: %s' % (scope,)) + + lst, group_entries = self._group_entries([(x[0], x[1], None) for x in list(dct.items()) if x[0] != '_pydev_stop_at_break'], handle_return_values=True) + group_variables = [] + + for key, val, _ in group_entries: + # Make sure that the contents in the group are also sorted. + val.contents_debug_adapter_protocol.sort(key=lambda v:sorted_attributes_key(v[0])) + variable = _ObjectVariable(self.py_db, key, val, self._register_variable, False, key, frame=self.frame) + group_variables.append(variable) + + for key, val, _ in lst: + is_return_value = key == RETURN_VALUES_DICT + if is_return_value: + for return_key, return_value in val.items(): + variable = _ObjectVariable( + self.py_db, return_key, return_value, self._register_variable, is_return_value, '%s[%r]' % (key, return_key), frame=self.frame) + children_variables.append(variable) + else: + variable = _ObjectVariable(self.py_db, key, val, self._register_variable, is_return_value, key, frame=self.frame) + children_variables.append(variable) + + # Frame variables always sorted. + children_variables.sort(key=sorted_variables_key) + if group_variables: + # Groups have priority over other variables. + children_variables = group_variables + children_variables + + return children_variables + + +class _FramesTracker(object): + ''' + This is a helper class to be used to track frames when a thread becomes suspended. + ''' + + def __init__(self, suspended_frames_manager, py_db): + self._suspended_frames_manager = suspended_frames_manager + self.py_db = py_db + self._frame_id_to_frame = {} + + # Note that a given frame may appear in multiple threads when we have custom + # frames added, but as those are coroutines, this map will point to the actual + # main thread (which is the one that needs to be suspended for us to get the + # variables). + self._frame_id_to_main_thread_id = {} + + # A map of the suspended thread id -> list(frames ids) -- note that + # frame ids are kept in order (the first one is the suspended frame). + self._thread_id_to_frame_ids = {} + + self._thread_id_to_frames_list = {} + + # The main suspended thread (if this is a coroutine this isn't the id of the + # coroutine thread, it's the id of the actual suspended thread). + self._main_thread_id = None + + # Helper to know if it was already untracked. + self._untracked = False + + # We need to be thread-safe! + self._lock = ForkSafeLock() + + self._variable_reference_to_variable = {} + + def _register_variable(self, variable): + variable_reference = variable.get_variable_reference() + self._variable_reference_to_variable[variable_reference] = variable + + def obtain_as_variable(self, name, value, evaluate_name=None, frame=None): + if evaluate_name is None: + evaluate_name = name + + variable_reference = id(value) + variable = self._variable_reference_to_variable.get(variable_reference) + if variable is not None: + return variable + + # Still not created, let's do it now. + return _ObjectVariable( + self.py_db, name, value, self._register_variable, is_return_value=False, evaluate_name=evaluate_name, frame=frame) + + def get_main_thread_id(self): + return self._main_thread_id + + def get_variable(self, variable_reference): + return self._variable_reference_to_variable[variable_reference] + + def track(self, thread_id, frames_list, frame_custom_thread_id=None): + ''' + :param thread_id: + The thread id to be used for this frame. + + :param FramesList frames_list: + A list of frames to be tracked (the first is the topmost frame which is suspended at the given thread). + + :param frame_custom_thread_id: + If None this this is the id of the thread id for the custom frame (i.e.: coroutine). + ''' + assert frames_list.__class__ == FramesList + with self._lock: + coroutine_or_main_thread_id = frame_custom_thread_id or thread_id + + if coroutine_or_main_thread_id in self._suspended_frames_manager._thread_id_to_tracker: + sys.stderr.write('pydevd: Something is wrong. Tracker being added twice to the same thread id.\n') + + self._suspended_frames_manager._thread_id_to_tracker[coroutine_or_main_thread_id] = self + self._main_thread_id = thread_id + + frame_ids_from_thread = self._thread_id_to_frame_ids.setdefault( + coroutine_or_main_thread_id, []) + + self._thread_id_to_frames_list[coroutine_or_main_thread_id] = frames_list + for frame in frames_list: + frame_id = id(frame) + self._frame_id_to_frame[frame_id] = frame + _FrameVariable(self.py_db, frame, self._register_variable) # Instancing is enough to register. + self._suspended_frames_manager._variable_reference_to_frames_tracker[frame_id] = self + frame_ids_from_thread.append(frame_id) + + self._frame_id_to_main_thread_id[frame_id] = thread_id + + frame = None + + def untrack_all(self): + with self._lock: + if self._untracked: + # Calling multiple times is expected for the set next statement. + return + self._untracked = True + for thread_id in self._thread_id_to_frame_ids: + self._suspended_frames_manager._thread_id_to_tracker.pop(thread_id, None) + + for frame_id in self._frame_id_to_frame: + del self._suspended_frames_manager._variable_reference_to_frames_tracker[frame_id] + + self._frame_id_to_frame.clear() + self._frame_id_to_main_thread_id.clear() + self._thread_id_to_frame_ids.clear() + self._thread_id_to_frames_list.clear() + self._main_thread_id = None + self._suspended_frames_manager = None + self._variable_reference_to_variable.clear() + + def get_frames_list(self, thread_id): + with self._lock: + return self._thread_id_to_frames_list.get(thread_id) + + def find_frame(self, thread_id, frame_id): + with self._lock: + return self._frame_id_to_frame.get(frame_id) + + def create_thread_suspend_command(self, thread_id, stop_reason, message, suspend_type): + with self._lock: + # First one is topmost frame suspended. + frames_list = self._thread_id_to_frames_list[thread_id] + + cmd = self.py_db.cmd_factory.make_thread_suspend_message( + self.py_db, thread_id, frames_list, stop_reason, message, suspend_type) + + frames_list = None + return cmd + + +class SuspendedFramesManager(object): + + def __init__(self): + self._thread_id_to_fake_frames = {} + self._thread_id_to_tracker = {} + + # Mappings + self._variable_reference_to_frames_tracker = {} + + def _get_tracker_for_variable_reference(self, variable_reference): + tracker = self._variable_reference_to_frames_tracker.get(variable_reference) + if tracker is not None: + return tracker + + for _thread_id, tracker in self._thread_id_to_tracker.items(): + try: + tracker.get_variable(variable_reference) + except KeyError: + pass + else: + return tracker + + return None + + def get_thread_id_for_variable_reference(self, variable_reference): + ''' + We can't evaluate variable references values on any thread, only in the suspended + thread (the main reason for this is that in UI frameworks inspecting a UI object + from a different thread can potentially crash the application). + + :param int variable_reference: + The variable reference (can be either a frame id or a reference to a previously + gotten variable). + + :return str: + The thread id for the thread to be used to inspect the given variable reference or + None if the thread was already resumed. + ''' + frames_tracker = self._get_tracker_for_variable_reference(variable_reference) + if frames_tracker is not None: + return frames_tracker.get_main_thread_id() + return None + + def get_frame_tracker(self, thread_id): + return self._thread_id_to_tracker.get(thread_id) + + def get_variable(self, variable_reference): + ''' + :raises KeyError + ''' + frames_tracker = self._get_tracker_for_variable_reference(variable_reference) + if frames_tracker is None: + raise KeyError() + return frames_tracker.get_variable(variable_reference) + + def get_frames_list(self, thread_id): + tracker = self._thread_id_to_tracker.get(thread_id) + if tracker is None: + return None + return tracker.get_frames_list(thread_id) + + @contextmanager + def track_frames(self, py_db): + tracker = _FramesTracker(self, py_db) + try: + yield tracker + finally: + tracker.untrack_all() + + def add_fake_frame(self, thread_id, frame_id, frame): + self._thread_id_to_fake_frames.setdefault(thread_id, {})[int(frame_id)] = frame + + def find_frame(self, thread_id, frame_id): + try: + if frame_id == "*": + return get_frame() # any frame is specified with "*" + frame_id = int(frame_id) + + fake_frames = self._thread_id_to_fake_frames.get(thread_id) + if fake_frames is not None: + frame = fake_frames.get(frame_id) + if frame is not None: + return frame + + frames_tracker = self._thread_id_to_tracker.get(thread_id) + if frames_tracker is not None: + frame = frames_tracker.find_frame(thread_id, frame_id) + if frame is not None: + return frame + + return None + except: + pydev_log.exception() + return None diff --git a/_pydevd_bundle/pydevd_thread_lifecycle.py b/_pydevd_bundle/pydevd_thread_lifecycle.py new file mode 100644 index 0000000..069b6b6 --- /dev/null +++ b/_pydevd_bundle/pydevd_thread_lifecycle.py @@ -0,0 +1,96 @@ +from _pydevd_bundle import pydevd_utils +from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info +from _pydevd_bundle.pydevd_comm_constants import CMD_STEP_INTO, CMD_THREAD_SUSPEND +from _pydevd_bundle.pydevd_constants import PYTHON_SUSPEND, STATE_SUSPEND, get_thread_id, STATE_RUN +from _pydev_bundle._pydev_saved_modules import threading +from _pydev_bundle import pydev_log + + +def pydevd_find_thread_by_id(thread_id): + try: + threads = threading.enumerate() + for i in threads: + tid = get_thread_id(i) + if thread_id == tid or thread_id.endswith('|' + tid): + return i + + # This can happen when a request comes for a thread which was previously removed. + pydev_log.info("Could not find thread %s.", thread_id) + pydev_log.info("Available: %s.", ([get_thread_id(t) for t in threads],)) + except: + pydev_log.exception() + + return None + + +def mark_thread_suspended(thread, stop_reason, original_step_cmd=-1): + info = set_additional_thread_info(thread) + info.suspend_type = PYTHON_SUSPEND + if original_step_cmd != -1: + stop_reason = original_step_cmd + thread.stop_reason = stop_reason + + # Note: don't set the 'pydev_original_step_cmd' here if unset. + + if info.pydev_step_cmd == -1: + # If the step command is not specified, set it to step into + # to make sure it'll break as soon as possible. + info.pydev_step_cmd = CMD_STEP_INTO + info.pydev_step_stop = None + + # Mark as suspended as the last thing. + info.pydev_state = STATE_SUSPEND + + return info + + +def internal_run_thread(thread, set_additional_thread_info): + info = set_additional_thread_info(thread) + info.pydev_original_step_cmd = -1 + info.pydev_step_cmd = -1 + info.pydev_step_stop = None + info.pydev_state = STATE_RUN + + +def resume_threads(thread_id, except_thread=None): + pydev_log.info('Resuming threads: %s (except thread: %s)', thread_id, except_thread) + threads = [] + if thread_id == '*': + threads = pydevd_utils.get_non_pydevd_threads() + + elif thread_id.startswith('__frame__:'): + pydev_log.critical("Can't make tasklet run: %s", thread_id) + + else: + threads = [pydevd_find_thread_by_id(thread_id)] + + for t in threads: + if t is None or t is except_thread: + pydev_log.info('Skipped resuming thread: %s', t) + continue + + internal_run_thread(t, set_additional_thread_info=set_additional_thread_info) + + +def suspend_all_threads(py_db, except_thread): + ''' + Suspend all except the one passed as a parameter. + :param except_thread: + ''' + pydev_log.info('Suspending all threads except: %s', except_thread) + all_threads = pydevd_utils.get_non_pydevd_threads() + for t in all_threads: + if getattr(t, 'pydev_do_not_trace', None): + pass # skip some other threads, i.e. ipython history saving thread from debug console + else: + if t is except_thread: + continue + info = mark_thread_suspended(t, CMD_THREAD_SUSPEND) + frame = info.get_topmost_frame(t) + + # Reset the tracing as in this case as it could've set scopes to be untraced. + if frame is not None: + try: + py_db.set_trace_for_frame_and_parents(frame) + finally: + frame = None diff --git a/_pydevd_bundle/pydevd_timeout.py b/_pydevd_bundle/pydevd_timeout.py new file mode 100644 index 0000000..4a18caf --- /dev/null +++ b/_pydevd_bundle/pydevd_timeout.py @@ -0,0 +1,239 @@ +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle.pydevd_daemon_thread import PyDBDaemonThread +from _pydevd_bundle.pydevd_constants import thread_get_ident, IS_CPYTHON, NULL +import ctypes +import time +from _pydev_bundle import pydev_log +import weakref +from _pydevd_bundle.pydevd_utils import is_current_thread_main_thread +from _pydevd_bundle import pydevd_utils + +_DEBUG = False # Default should be False as this can be very verbose. + + +class _TimeoutThread(PyDBDaemonThread): + ''' + The idea in this class is that it should be usually stopped waiting + for the next event to be called (paused in a threading.Event.wait). + + When a new handle is added it sets the event so that it processes the handles and + then keeps on waiting as needed again. + + This is done so that it's a bit more optimized than creating many Timer threads. + ''' + + def __init__(self, py_db): + PyDBDaemonThread.__init__(self, py_db) + self._event = threading.Event() + self._handles = [] + + # We could probably do things valid without this lock so that it's possible to add + # handles while processing, but the implementation would also be harder to follow, + # so, for now, we're either processing or adding handles, not both at the same time. + self._lock = threading.Lock() + + def _on_run(self): + wait_time = None + while not self._kill_received: + if _DEBUG: + if wait_time is None: + pydev_log.critical('pydevd_timeout: Wait until a new handle is added.') + else: + pydev_log.critical('pydevd_timeout: Next wait time: %s.', wait_time) + self._event.wait(wait_time) + + if self._kill_received: + self._handles = [] + return + + wait_time = self.process_handles() + + def process_handles(self): + ''' + :return int: + Returns the time we should be waiting for to process the next event properly. + ''' + with self._lock: + if _DEBUG: + pydev_log.critical('pydevd_timeout: Processing handles') + self._event.clear() + handles = self._handles + new_handles = self._handles = [] + + # Do all the processing based on this time (we want to consider snapshots + # of processing time -- anything not processed now may be processed at the + # next snapshot). + curtime = time.time() + + min_handle_timeout = None + + for handle in handles: + if curtime < handle.abs_timeout and not handle.disposed: + # It still didn't time out. + if _DEBUG: + pydev_log.critical('pydevd_timeout: Handle NOT processed: %s', handle) + new_handles.append(handle) + if min_handle_timeout is None: + min_handle_timeout = handle.abs_timeout + + elif handle.abs_timeout < min_handle_timeout: + min_handle_timeout = handle.abs_timeout + + else: + if _DEBUG: + pydev_log.critical('pydevd_timeout: Handle processed: %s', handle) + # Timed out (or disposed), so, let's execute it (should be no-op if disposed). + handle.exec_on_timeout() + + if min_handle_timeout is None: + return None + else: + timeout = min_handle_timeout - curtime + if timeout <= 0: + pydev_log.critical('pydevd_timeout: Expected timeout to be > 0. Found: %s', timeout) + + return timeout + + def do_kill_pydev_thread(self): + PyDBDaemonThread.do_kill_pydev_thread(self) + with self._lock: + self._event.set() + + def add_on_timeout_handle(self, handle): + with self._lock: + self._handles.append(handle) + self._event.set() + + +class _OnTimeoutHandle(object): + + def __init__(self, tracker, abs_timeout, on_timeout, kwargs): + self._str = '_OnTimeoutHandle(%s)' % (on_timeout,) + + self._tracker = weakref.ref(tracker) + self.abs_timeout = abs_timeout + self.on_timeout = on_timeout + if kwargs is None: + kwargs = {} + self.kwargs = kwargs + self.disposed = False + + def exec_on_timeout(self): + # Note: lock should already be obtained when executing this function. + kwargs = self.kwargs + on_timeout = self.on_timeout + + if not self.disposed: + self.disposed = True + self.kwargs = None + self.on_timeout = None + + try: + if _DEBUG: + pydev_log.critical('pydevd_timeout: Calling on timeout: %s with kwargs: %s', on_timeout, kwargs) + + on_timeout(**kwargs) + except Exception: + pydev_log.exception('pydevd_timeout: Exception on callback timeout.') + + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_val, exc_tb): + tracker = self._tracker() + + if tracker is None: + lock = NULL + else: + lock = tracker._lock + + with lock: + self.disposed = True + self.kwargs = None + self.on_timeout = None + + def __str__(self): + return self._str + + __repr__ = __str__ + + +class TimeoutTracker(object): + ''' + This is a helper class to track the timeout of something. + ''' + + def __init__(self, py_db): + self._thread = None + self._lock = threading.Lock() + self._py_db = weakref.ref(py_db) + + def call_on_timeout(self, timeout, on_timeout, kwargs=None): + ''' + This can be called regularly to always execute the given function after a given timeout: + + call_on_timeout(py_db, 10, on_timeout) + + + Or as a context manager to stop the method from being called if it finishes before the timeout + elapses: + + with call_on_timeout(py_db, 10, on_timeout): + ... + + Note: the callback will be called from a PyDBDaemonThread. + ''' + with self._lock: + if self._thread is None: + if _DEBUG: + pydev_log.critical('pydevd_timeout: Created _TimeoutThread.') + + self._thread = _TimeoutThread(self._py_db()) + self._thread.start() + + curtime = time.time() + handle = _OnTimeoutHandle(self, curtime + timeout, on_timeout, kwargs) + if _DEBUG: + pydev_log.critical('pydevd_timeout: Added handle: %s.', handle) + self._thread.add_on_timeout_handle(handle) + return handle + + +def create_interrupt_this_thread_callback(): + ''' + The idea here is returning a callback that when called will generate a KeyboardInterrupt + in the thread that called this function. + + If this is the main thread, this means that it'll emulate a Ctrl+C (which may stop I/O + and sleep operations). + + For other threads, this will call PyThreadState_SetAsyncExc to raise + a KeyboardInterrupt before the next instruction (so, it won't really interrupt I/O or + sleep operations). + + :return callable: + Returns a callback that will interrupt the current thread (this may be called + from an auxiliary thread). + ''' + tid = thread_get_ident() + + if is_current_thread_main_thread(): + main_thread = threading.current_thread() + + def raise_on_this_thread(): + pydev_log.debug('Callback to interrupt main thread.') + pydevd_utils.interrupt_main_thread(main_thread) + + else: + + # Note: this works in the sense that it can stop some cpu-intensive slow operation, + # but we can't really interrupt the thread out of some sleep or I/O operation + # (this will only be raised when Python is about to execute the next instruction). + def raise_on_this_thread(): + if IS_CPYTHON: + pydev_log.debug('Interrupt thread: %s', tid) + ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(KeyboardInterrupt)) + else: + pydev_log.debug('It is only possible to interrupt non-main threads in CPython.') + + return raise_on_this_thread diff --git a/_pydevd_bundle/pydevd_trace_api.py b/_pydevd_bundle/pydevd_trace_api.py new file mode 100644 index 0000000..77e8b3f --- /dev/null +++ b/_pydevd_bundle/pydevd_trace_api.py @@ -0,0 +1,62 @@ +def add_line_breakpoint(plugin, pydb, type, canonical_normalized_filename, breakpoint_id, line, condition, expression, func_name, hit_condition=None, is_logpoint=False, add_breakpoint_result=None, on_changed_breakpoint_state=None): + return None + + +def after_breakpoints_consolidated(py_db, canonical_normalized_filename, id_to_pybreakpoint, file_to_line_to_breakpoints): + return None + + +def add_exception_breakpoint(plugin, pydb, type, exception): + return False + + +def remove_exception_breakpoint(plugin, pydb, type, exception): + return False + + +def remove_all_exception_breakpoints(plugin, pydb): + return False + + +def get_breakpoints(plugin, pydb): + return None + + +def can_skip(plugin, pydb, frame): + return True + + +def has_exception_breaks(plugin): + return False + + +def has_line_breaks(plugin): + return False + + +def cmd_step_into(plugin, pydb, frame, event, args, stop_info, stop): + return False + + +def cmd_step_over(plugin, pydb, frame, event, args, stop_info, stop): + return False + + +def stop(plugin, pydb, frame, event, args, stop_info, arg, step_cmd): + return False + + +def get_breakpoint(plugin, pydb, pydb_frame, frame, event, args): + return None + + +def suspend(plugin, pydb, thread, frame): + return None + + +def exception_break(plugin, pydb, pydb_frame, frame, args, arg): + return None + + +def change_variable(plugin, frame, attr, expression): + return False diff --git a/_pydevd_bundle/pydevd_trace_dispatch.py b/_pydevd_bundle/pydevd_trace_dispatch.py new file mode 100644 index 0000000..40a6837 --- /dev/null +++ b/_pydevd_bundle/pydevd_trace_dispatch.py @@ -0,0 +1,62 @@ +# Defines which version of the trace_dispatch we'll use. +# Should give warning only here if cython is not available but supported. + +import os +from _pydevd_bundle.pydevd_constants import USE_CYTHON_FLAG, ENV_TRUE_LOWER_VALUES, \ + ENV_FALSE_LOWER_VALUES +from _pydev_bundle import pydev_log + +dirname = os.path.dirname(os.path.dirname(__file__)) +USING_CYTHON = False + + +def delete_old_compiled_extensions(): + import _pydevd_bundle + cython_extensions_dir = os.path.dirname(os.path.dirname(_pydevd_bundle.__file__)) + _pydevd_bundle_ext_dir = os.path.dirname(_pydevd_bundle.__file__) + _pydevd_frame_eval_ext_dir = os.path.join(cython_extensions_dir, '_pydevd_frame_eval_ext') + try: + import shutil + for file in os.listdir(_pydevd_bundle_ext_dir): + if file.startswith("pydevd") and file.endswith(".so"): + os.remove(os.path.join(_pydevd_bundle_ext_dir, file)) + for file in os.listdir(_pydevd_frame_eval_ext_dir): + if file.startswith("pydevd") and file.endswith(".so"): + os.remove(os.path.join(_pydevd_frame_eval_ext_dir, file)) + build_dir = os.path.join(cython_extensions_dir, "build") + if os.path.exists(build_dir): + shutil.rmtree(os.path.join(cython_extensions_dir, "build")) + except OSError: + pydev_log.error_once("warning: failed to delete old cython speedups. Please delete all *.so files from the directories " + "\"%s\" and \"%s\"" % (_pydevd_bundle_ext_dir, _pydevd_frame_eval_ext_dir)) + + +if USE_CYTHON_FLAG in ENV_TRUE_LOWER_VALUES: + # We must import the cython version if forcing cython + from _pydevd_bundle.pydevd_cython_wrapper import trace_dispatch, global_cache_skips, global_cache_frame_skips, fix_top_level_trace_and_get_trace_func + USING_CYTHON = True + +elif USE_CYTHON_FLAG in ENV_FALSE_LOWER_VALUES: + # Use the regular version if not forcing cython + from _pydevd_bundle.pydevd_trace_dispatch_regular import trace_dispatch, global_cache_skips, global_cache_frame_skips, fix_top_level_trace_and_get_trace_func # @UnusedImport + +else: + # Regular: use fallback if not found and give message to user + try: + from _pydevd_bundle.pydevd_cython_wrapper import trace_dispatch, global_cache_skips, global_cache_frame_skips, fix_top_level_trace_and_get_trace_func + + # This version number is always available + from _pydevd_bundle.pydevd_additional_thread_info_regular import version as regular_version + # This version number from the already compiled cython extension + from _pydevd_bundle.pydevd_cython_wrapper import version as cython_version + if cython_version != regular_version: + # delete_old_compiled_extensions() -- would be ok in dev mode but we don't want to erase + # files from other python versions on release, so, just raise import error here. + raise ImportError('Cython version of speedups does not match.') + else: + USING_CYTHON = True + + except ImportError: + from _pydevd_bundle.pydevd_trace_dispatch_regular import trace_dispatch, global_cache_skips, global_cache_frame_skips, fix_top_level_trace_and_get_trace_func # @UnusedImport + pydev_log.show_compile_cython_command_line() + diff --git a/_pydevd_bundle/pydevd_trace_dispatch_regular.py b/_pydevd_bundle/pydevd_trace_dispatch_regular.py new file mode 100644 index 0000000..88a3f08 --- /dev/null +++ b/_pydevd_bundle/pydevd_trace_dispatch_regular.py @@ -0,0 +1,490 @@ +from _pydev_bundle.pydev_is_thread_alive import is_thread_alive +from _pydev_bundle.pydev_log import exception as pydev_log_exception +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle.pydevd_constants import (get_current_thread_id, NO_FTRACE, + USE_CUSTOM_SYS_CURRENT_FRAMES_MAP, ForkSafeLock) +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER + +# IFDEF CYTHON +# from cpython.object cimport PyObject +# from cpython.ref cimport Py_INCREF, Py_XDECREF +# ELSE +from _pydevd_bundle.pydevd_frame import PyDBFrame, is_unhandled_exception +# ENDIF + +# IFDEF CYTHON +# cdef dict _global_notify_skipped_step_in +# cython_inline_constant: CMD_STEP_INTO = 107 +# cython_inline_constant: CMD_STEP_INTO_MY_CODE = 144 +# cython_inline_constant: CMD_STEP_RETURN = 109 +# cython_inline_constant: CMD_STEP_RETURN_MY_CODE = 160 +# ELSE +# Note: those are now inlined on cython. +CMD_STEP_INTO = 107 +CMD_STEP_INTO_MY_CODE = 144 +CMD_STEP_RETURN = 109 +CMD_STEP_RETURN_MY_CODE = 160 +# ENDIF + +# Cache where we should keep that we completely skipped entering some context. +# It needs to be invalidated when: +# - Breakpoints are changed +# It can be used when running regularly (without step over/step in/step return) +global_cache_skips = {} +global_cache_frame_skips = {} + +_global_notify_skipped_step_in = False +_global_notify_skipped_step_in_lock = ForkSafeLock() + + +def notify_skipped_step_in_because_of_filters(py_db, frame): + global _global_notify_skipped_step_in + + with _global_notify_skipped_step_in_lock: + if _global_notify_skipped_step_in: + # Check with lock in place (callers should actually have checked + # before without the lock in place due to performance). + return + _global_notify_skipped_step_in = True + py_db.notify_skipped_step_in_because_of_filters(frame) + +# IFDEF CYTHON +# cdef class SafeCallWrapper: +# cdef method_object +# def __init__(self, method_object): +# self.method_object = method_object +# def __call__(self, *args): +# #Cannot use 'self' once inside the delegate call since we are borrowing the self reference f_trace field +# #in the frame, and that reference might get destroyed by set trace on frame and parents +# cdef PyObject* method_obj = self.method_object +# Py_INCREF(method_obj) +# ret = (method_obj)(*args) +# Py_XDECREF (method_obj) +# return SafeCallWrapper(ret) if ret is not None else None +# def get_method_object(self): +# return self.method_object +# ELSE +# ENDIF + + +def fix_top_level_trace_and_get_trace_func(py_db, frame): + # IFDEF CYTHON + # cdef str filename; + # cdef str name; + # cdef tuple args; + # ENDIF + + # Note: this is always the first entry-point in the tracing for any thread. + # After entering here we'll set a new tracing function for this thread + # where more information is cached (and will also setup the tracing for + # frames where we should deal with unhandled exceptions). + thread = None + # Cache the frame which should be traced to deal with unhandled exceptions. + # (i.e.: thread entry-points). + + f_unhandled = frame + # print('called at', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + force_only_unhandled_tracer = False + while f_unhandled is not None: + # name = splitext(basename(f_unhandled.f_code.co_filename))[0] + + name = f_unhandled.f_code.co_filename + # basename + i = name.rfind('/') + j = name.rfind('\\') + if j > i: + i = j + if i >= 0: + name = name[i + 1:] + # remove ext + i = name.rfind('.') + if i >= 0: + name = name[:i] + + if name == 'threading': + if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'): + # We need __bootstrap_inner, not __bootstrap. + return None, False + + elif f_unhandled.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'): + # Note: be careful not to use threading.currentThread to avoid creating a dummy thread. + t = f_unhandled.f_locals.get('self') + force_only_unhandled_tracer = True + if t is not None and isinstance(t, threading.Thread): + thread = t + break + + elif name == 'pydev_monkey': + if f_unhandled.f_code.co_name == '__call__': + force_only_unhandled_tracer = True + break + + elif name == 'pydevd': + if f_unhandled.f_code.co_name in ('run', 'main'): + # We need to get to _exec + return None, False + + if f_unhandled.f_code.co_name == '_exec': + force_only_unhandled_tracer = True + break + + elif name == 'pydevd_tracing': + return None, False + + elif f_unhandled.f_back is None: + break + + f_unhandled = f_unhandled.f_back + + if thread is None: + # Important: don't call threadingCurrentThread if we're in the threading module + # to avoid creating dummy threads. + if py_db.threading_get_ident is not None: + thread = py_db.threading_active.get(py_db.threading_get_ident()) + if thread is None: + return None, False + else: + # Jython does not have threading.get_ident(). + thread = py_db.threading_current_thread() + + if getattr(thread, 'pydev_do_not_trace', None): + py_db.disable_tracing() + return None, False + + try: + additional_info = thread.additional_info + if additional_info is None: + raise AttributeError() + except: + additional_info = py_db.set_additional_thread_info(thread) + + # print('enter thread tracer', thread, get_current_thread_id(thread)) + args = (py_db, thread, additional_info, global_cache_skips, global_cache_frame_skips) + + if f_unhandled is not None: + if f_unhandled.f_back is None and not force_only_unhandled_tracer: + # Happens when we attach to a running program (cannot reuse instance because it's mutable). + top_level_thread_tracer = TopLevelThreadTracerNoBackFrame(ThreadTracer(args), args) + additional_info.top_level_thread_tracer_no_back_frames.append(top_level_thread_tracer) # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). + else: + top_level_thread_tracer = additional_info.top_level_thread_tracer_unhandled + if top_level_thread_tracer is None: + # Stop in some internal place to report about unhandled exceptions + top_level_thread_tracer = TopLevelThreadTracerOnlyUnhandledExceptions(args) + additional_info.top_level_thread_tracer_unhandled = top_level_thread_tracer # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough). + + # print(' --> found to trace unhandled', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno) + f_trace = top_level_thread_tracer.get_trace_dispatch_func() + # IFDEF CYTHON + # f_trace = SafeCallWrapper(f_trace) + # ENDIF + f_unhandled.f_trace = f_trace + + if frame is f_unhandled: + return f_trace, False + + thread_tracer = additional_info.thread_tracer + if thread_tracer is None or thread_tracer._args[0] is not py_db: + thread_tracer = ThreadTracer(args) + additional_info.thread_tracer = thread_tracer + +# IFDEF CYTHON +# return SafeCallWrapper(thread_tracer), True +# ELSE + return thread_tracer, True +# ENDIF + + +def trace_dispatch(py_db, frame, event, arg): + thread_trace_func, apply_to_settrace = py_db.fix_top_level_trace_and_get_trace_func(py_db, frame) + if thread_trace_func is None: + return None if event == 'call' else NO_FTRACE + if apply_to_settrace: + py_db.enable_tracing(thread_trace_func) + return thread_trace_func(frame, event, arg) + + +# IFDEF CYTHON +# cdef class TopLevelThreadTracerOnlyUnhandledExceptions: +# cdef public tuple _args; +# def __init__(self, tuple args): +# self._args = args +# ELSE +class TopLevelThreadTracerOnlyUnhandledExceptions(object): + + def __init__(self, args): + self._args = args +# ENDIF + + def trace_unhandled_exceptions(self, frame, event, arg): + # Note that we ignore the frame as this tracing method should only be put in topmost frames already. + # print('trace_unhandled_exceptions', event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno) + if event == 'exception' and arg is not None: + py_db, t, additional_info = self._args[0:3] + if arg is not None: + if not additional_info.suspended_at_unhandled: + additional_info.suspended_at_unhandled = True + + py_db.stop_on_unhandled_exception(py_db, t, additional_info, arg) + + # No need to reset frame.f_trace to keep the same trace function. + return self.trace_unhandled_exceptions + + def get_trace_dispatch_func(self): + return self.trace_unhandled_exceptions + + +# IFDEF CYTHON +# cdef class TopLevelThreadTracerNoBackFrame: +# +# cdef public object _frame_trace_dispatch; +# cdef public tuple _args; +# cdef public object try_except_infos; +# cdef public object _last_exc_arg; +# cdef public set _raise_lines; +# cdef public int _last_raise_line; +# +# def __init__(self, frame_trace_dispatch, tuple args): +# self._frame_trace_dispatch = frame_trace_dispatch +# self._args = args +# self.try_except_infos = None +# self._last_exc_arg = None +# self._raise_lines = set() +# self._last_raise_line = -1 +# ELSE +class TopLevelThreadTracerNoBackFrame(object): + ''' + This tracer is pretty special in that it's dealing with a frame without f_back (i.e.: top frame + on remote attach or QThread). + + This means that we have to carefully inspect exceptions to discover whether the exception will + be unhandled or not (if we're dealing with an unhandled exception we need to stop as unhandled, + otherwise we need to use the regular tracer -- unfortunately the debugger has little info to + work with in the tracing -- see: https://bugs.python.org/issue34099, so, we inspect bytecode to + determine if some exception will be traced or not... note that if this is not available -- such + as on Jython -- we consider any top-level exception to be unnhandled). + ''' + + def __init__(self, frame_trace_dispatch, args): + self._frame_trace_dispatch = frame_trace_dispatch + self._args = args + self.try_except_infos = None + self._last_exc_arg = None + self._raise_lines = set() + self._last_raise_line = -1 +# ENDIF + + def trace_dispatch_and_unhandled_exceptions(self, frame, event, arg): + # DEBUG = 'code_to_debug' in frame.f_code.co_filename + # if DEBUG: print('trace_dispatch_and_unhandled_exceptions: %s %s %s %s %s %s' % (event, frame.f_code.co_name, frame.f_code.co_filename, frame.f_code.co_firstlineno, self._frame_trace_dispatch, frame.f_lineno)) + frame_trace_dispatch = self._frame_trace_dispatch + if frame_trace_dispatch is not None: + self._frame_trace_dispatch = frame_trace_dispatch(frame, event, arg) + + if event == 'exception': + self._last_exc_arg = arg + self._raise_lines.add(frame.f_lineno) + self._last_raise_line = frame.f_lineno + + elif event == 'return' and self._last_exc_arg is not None: + # For unhandled exceptions we actually track the return when at the topmost level. + try: + py_db, t, additional_info = self._args[0:3] + if not additional_info.suspended_at_unhandled: # Note: only check it here, don't set. + if is_unhandled_exception(self, py_db, frame, self._last_raise_line, self._raise_lines): + py_db.stop_on_unhandled_exception(py_db, t, additional_info, self._last_exc_arg) + finally: + # Remove reference to exception after handling it. + self._last_exc_arg = None + + ret = self.trace_dispatch_and_unhandled_exceptions + + # Need to reset (the call to _frame_trace_dispatch may have changed it). + # IFDEF CYTHON + # frame.f_trace = SafeCallWrapper(ret) + # ELSE + frame.f_trace = ret + # ENDIF + return ret + + def get_trace_dispatch_func(self): + return self.trace_dispatch_and_unhandled_exceptions + + +# IFDEF CYTHON +# cdef class ThreadTracer: +# cdef public tuple _args; +# def __init__(self, tuple args): +# self._args = args +# ELSE +class ThreadTracer(object): + + def __init__(self, args): + self._args = args +# ENDIF + + def __call__(self, frame, event, arg): + ''' This is the callback used when we enter some context in the debugger. + + We also decorate the thread we are in with info about the debugging. + The attributes added are: + pydev_state + pydev_step_stop + pydev_step_cmd + pydev_notify_kill + + :param PyDB py_db: + This is the global debugger (this method should actually be added as a method to it). + ''' + # IFDEF CYTHON + # cdef str filename; + # cdef str base; + # cdef int pydev_step_cmd; + # cdef object frame_cache_key; + # cdef dict cache_skips; + # cdef bint is_stepping; + # cdef tuple abs_path_canonical_path_and_base; + # cdef PyDBAdditionalThreadInfo additional_info; + # ENDIF + + # DEBUG = 'code_to_debug' in frame.f_code.co_filename + # if DEBUG: print('ENTER: trace_dispatch: %s %s %s %s' % (frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)) + py_db, t, additional_info, cache_skips, frame_skips_cache = self._args + if additional_info.is_tracing: + return None if event == 'call' else NO_FTRACE # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch + + additional_info.is_tracing += 1 + try: + pydev_step_cmd = additional_info.pydev_step_cmd + is_stepping = pydev_step_cmd != -1 + if py_db.pydb_disposed: + return None if event == 'call' else NO_FTRACE + + # if thread is not alive, cancel trace_dispatch processing + if not is_thread_alive(t): + py_db.notify_thread_not_alive(get_current_thread_id(t)) + return None if event == 'call' else NO_FTRACE + + # Note: it's important that the context name is also given because we may hit something once + # in the global context and another in the local context. + frame_cache_key = frame.f_code + if frame_cache_key in cache_skips: + if not is_stepping: + # if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + else: + # When stepping we can't take into account caching based on the breakpoints (only global filtering). + if cache_skips.get(frame_cache_key) == 1: + + if additional_info.pydev_original_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE) and not _global_notify_skipped_step_in: + notify_skipped_step_in_because_of_filters(py_db, frame) + + back_frame = frame.f_back + if back_frame is not None and pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE): + back_frame_cache_key = back_frame.f_code + if cache_skips.get(back_frame_cache_key) == 1: + # if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + else: + # if DEBUG: print('skipped: trace_dispatch (cache hit: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + + try: + # Make fast path faster! + abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + except: + abs_path_canonical_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) + + file_type = py_db.get_file_type(frame, abs_path_canonical_path_and_base) # we don't want to debug threading or anything related to pydevd + + if file_type is not None: + if file_type == 1: # inlining LIB_FILE = 1 + if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): + # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + cache_skips[frame_cache_key] = 1 + return None if event == 'call' else NO_FTRACE + else: + # if DEBUG: print('skipped: trace_dispatch', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) + cache_skips[frame_cache_key] = 1 + return None if event == 'call' else NO_FTRACE + + if py_db.is_files_filter_enabled: + if py_db.apply_files_filter(frame, abs_path_canonical_path_and_base[0], False): + cache_skips[frame_cache_key] = 1 + + if is_stepping and additional_info.pydev_original_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE) and not _global_notify_skipped_step_in: + notify_skipped_step_in_because_of_filters(py_db, frame) + + # A little gotcha, sometimes when we're stepping in we have to stop in a + # return event showing the back frame as the current frame, so, we need + # to check not only the current frame but the back frame too. + back_frame = frame.f_back + if back_frame is not None and pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE): + if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): + back_frame_cache_key = back_frame.f_code + cache_skips[back_frame_cache_key] = 1 + # if DEBUG: print('skipped: trace_dispatch (filtered out: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + else: + # if DEBUG: print('skipped: trace_dispatch (filtered out: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) + return None if event == 'call' else NO_FTRACE + + # if DEBUG: print('trace_dispatch', filename, frame.f_lineno, event, frame.f_code.co_name, file_type) + + # Just create PyDBFrame directly (removed support for Python versions < 2.5, which required keeping a weak + # reference to the frame). + ret = PyDBFrame( + ( + py_db, abs_path_canonical_path_and_base, additional_info, t, frame_skips_cache, frame_cache_key, + ) + ).trace_dispatch(frame, event, arg) + if ret is None: + # 1 means skipped because of filters. + # 2 means skipped because no breakpoints were hit. + cache_skips[frame_cache_key] = 2 + return None if event == 'call' else NO_FTRACE + + # IFDEF CYTHON + # frame.f_trace = SafeCallWrapper(ret) # Make sure we keep the returned tracer. + # ELSE + frame.f_trace = ret # Make sure we keep the returned tracer. + # ENDIF + return ret + + except SystemExit: + return None if event == 'call' else NO_FTRACE + + except Exception: + if py_db.pydb_disposed: + return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. + # Log it + try: + if pydev_log_exception is not None: + # This can actually happen during the interpreter shutdown in Python 2.7 + pydev_log_exception() + except: + # Error logging? We're really in the interpreter shutdown... + # (https://github.com/fabioz/PyDev.Debugger/issues/8) + pass + return None if event == 'call' else NO_FTRACE + finally: + additional_info.is_tracing -= 1 + + +if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP: + # This is far from ideal, as we'll leak frames (we'll always have the last created frame, not really + # the last topmost frame saved -- this should be Ok for our usage, but it may leak frames and things + # may live longer... as IronPython is garbage-collected, things should live longer anyways, so, it + # shouldn't be an issue as big as it's in CPython -- it may still be annoying, but this should + # be a reasonable workaround until IronPython itself is able to provide that functionality). + # + # See: https://github.com/IronLanguages/main/issues/1630 + from _pydevd_bundle.pydevd_constants import constructed_tid_to_last_frame + + _original_call = ThreadTracer.__call__ + + def __call__(self, frame, event, arg): + constructed_tid_to_last_frame[self._args[1].ident] = frame + return _original_call(self, frame, event, arg) + + ThreadTracer.__call__ = __call__ diff --git a/_pydevd_bundle/pydevd_traceproperty.py b/_pydevd_bundle/pydevd_traceproperty.py new file mode 100644 index 0000000..2f38e4b --- /dev/null +++ b/_pydevd_bundle/pydevd_traceproperty.py @@ -0,0 +1,92 @@ +'''For debug purpose we are replacing actual builtin property by the debug property +''' +from _pydevd_bundle.pydevd_comm import get_global_debugger +from _pydev_bundle import pydev_log + + +#======================================================================================================================= +# replace_builtin_property +#======================================================================================================================= +def replace_builtin_property(new_property=None): + if new_property is None: + new_property = DebugProperty + original = property + try: + import builtins + builtins.__dict__['property'] = new_property + except: + pydev_log.exception() # @Reimport + return original + + +#======================================================================================================================= +# DebugProperty +#======================================================================================================================= +class DebugProperty(object): + """A custom property which allows python property to get + controlled by the debugger and selectively disable/re-enable + the tracing. + """ + + def __init__(self, fget=None, fset=None, fdel=None, doc=None): + self.fget = fget + self.fset = fset + self.fdel = fdel + self.__doc__ = doc + + def __get__(self, obj, objtype=None): + if obj is None: + return self + global_debugger = get_global_debugger() + try: + if global_debugger is not None and global_debugger.disable_property_getter_trace: + global_debugger.disable_tracing() + if self.fget is None: + raise AttributeError("unreadable attribute") + return self.fget(obj) + finally: + if global_debugger is not None: + global_debugger.enable_tracing() + + def __set__(self, obj, value): + global_debugger = get_global_debugger() + try: + if global_debugger is not None and global_debugger.disable_property_setter_trace: + global_debugger.disable_tracing() + if self.fset is None: + raise AttributeError("can't set attribute") + self.fset(obj, value) + finally: + if global_debugger is not None: + global_debugger.enable_tracing() + + def __delete__(self, obj): + global_debugger = get_global_debugger() + try: + if global_debugger is not None and global_debugger.disable_property_deleter_trace: + global_debugger.disable_tracing() + if self.fdel is None: + raise AttributeError("can't delete attribute") + self.fdel(obj) + finally: + if global_debugger is not None: + global_debugger.enable_tracing() + + def getter(self, fget): + """Overriding getter decorator for the property + """ + self.fget = fget + return self + + def setter(self, fset): + """Overriding setter decorator for the property + """ + self.fset = fset + return self + + def deleter(self, fdel): + """Overriding deleter decorator for the property + """ + self.fdel = fdel + return self + diff --git a/_pydevd_bundle/pydevd_utils.py b/_pydevd_bundle/pydevd_utils.py new file mode 100644 index 0000000..a45caa1 --- /dev/null +++ b/_pydevd_bundle/pydevd_utils.py @@ -0,0 +1,511 @@ +from __future__ import nested_scopes +import traceback +import warnings +from _pydev_bundle import pydev_log +from _pydev_bundle._pydev_saved_modules import thread, threading +from _pydev_bundle import _pydev_saved_modules +import signal +import os +import ctypes +from importlib import import_module +from urllib.parse import quote # @UnresolvedImport +import time +import inspect +import sys +from _pydevd_bundle.pydevd_constants import USE_CUSTOM_SYS_CURRENT_FRAMES, IS_PYPY, SUPPORT_GEVENT, \ + GEVENT_SUPPORT_NOT_SET_MSG, GENERATED_LEN_ATTR_NAME, PYDEVD_WARN_SLOW_RESOLVE_TIMEOUT, \ + get_global_debugger + + +def save_main_module(file, module_name): + # patch provided by: Scott Schlesier - when script is run, it does not + # use globals from pydevd: + # This will prevent the pydevd script from contaminating the namespace for the script to be debugged + # pretend pydevd is not the main module, and + # convince the file to be debugged that it was loaded as main + sys.modules[module_name] = sys.modules['__main__'] + sys.modules[module_name].__name__ = module_name + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=DeprecationWarning) + warnings.simplefilter("ignore", category=PendingDeprecationWarning) + from imp import new_module + + m = new_module('__main__') + sys.modules['__main__'] = m + if hasattr(sys.modules[module_name], '__loader__'): + m.__loader__ = getattr(sys.modules[module_name], '__loader__') + m.__file__ = file + + return m + + +def is_current_thread_main_thread(): + if hasattr(threading, 'main_thread'): + return threading.current_thread() is threading.main_thread() + else: + return isinstance(threading.current_thread(), threading._MainThread) + + +def get_main_thread(): + if hasattr(threading, 'main_thread'): + return threading.main_thread() + else: + for t in threading.enumerate(): + if isinstance(t, threading._MainThread): + return t + return None + + +def to_number(x): + if is_string(x): + try: + n = float(x) + return n + except ValueError: + pass + + l = x.find('(') + if l != -1: + y = x[0:l - 1] + # print y + try: + n = float(y) + return n + except ValueError: + pass + return None + + +def compare_object_attrs_key(x): + if GENERATED_LEN_ATTR_NAME == x: + as_number = to_number(x) + if as_number is None: + as_number = 99999999 + # len() should appear after other attributes in a list. + return (1, as_number) + else: + return (-1, to_string(x)) + + +def is_string(x): + return isinstance(x, str) + + +def to_string(x): + if isinstance(x, str): + return x + else: + return str(x) + + +def print_exc(): + if traceback: + traceback.print_exc() + + +def quote_smart(s, safe='/'): + return quote(s, safe) + + +def get_clsname_for_code(code, frame): + clsname = None + if len(code.co_varnames) > 0: + # We are checking the first argument of the function + # (`self` or `cls` for methods). + first_arg_name = code.co_varnames[0] + if first_arg_name in frame.f_locals: + first_arg_obj = frame.f_locals[first_arg_name] + if inspect.isclass(first_arg_obj): # class method + first_arg_class = first_arg_obj + else: # instance method + if hasattr(first_arg_obj, "__class__"): + first_arg_class = first_arg_obj.__class__ + else: # old style class, fall back on type + first_arg_class = type(first_arg_obj) + func_name = code.co_name + if hasattr(first_arg_class, func_name): + method = getattr(first_arg_class, func_name) + func_code = None + if hasattr(method, 'func_code'): # Python2 + func_code = method.func_code + elif hasattr(method, '__code__'): # Python3 + func_code = method.__code__ + if func_code and func_code == code: + clsname = first_arg_class.__name__ + + return clsname + + +def get_non_pydevd_threads(): + threads = threading.enumerate() + return [t for t in threads if t and not getattr(t, 'is_pydev_daemon_thread', False)] + + +if USE_CUSTOM_SYS_CURRENT_FRAMES and IS_PYPY: + # On PyPy we can use its fake_frames to get the traceback + # (instead of the actual real frames that need the tracing to be correct). + _tid_to_frame_for_dump_threads = sys._current_frames +else: + from _pydevd_bundle.pydevd_constants import _current_frames as _tid_to_frame_for_dump_threads + + +def dump_threads(stream=None, show_pydevd_threads=True): + ''' + Helper to dump thread info. + ''' + if stream is None: + stream = sys.stderr + thread_id_to_name_and_is_pydevd_thread = {} + try: + threading_enumerate = _pydev_saved_modules.pydevd_saved_threading_enumerate + if threading_enumerate is None: + threading_enumerate = threading.enumerate + + for t in threading_enumerate(): + is_pydevd_thread = getattr(t, 'is_pydev_daemon_thread', False) + thread_id_to_name_and_is_pydevd_thread[t.ident] = ( + '%s (daemon: %s, pydevd thread: %s)' % (t.name, t.daemon, is_pydevd_thread), + is_pydevd_thread + ) + except: + pass + + stream.write('===============================================================================\n') + stream.write('Threads running\n') + stream.write('================================= Thread Dump =================================\n') + stream.flush() + + for thread_id, frame in _tid_to_frame_for_dump_threads().items(): + name, is_pydevd_thread = thread_id_to_name_and_is_pydevd_thread.get(thread_id, (thread_id, False)) + if not show_pydevd_threads and is_pydevd_thread: + continue + + stream.write('\n-------------------------------------------------------------------------------\n') + stream.write(" Thread %s" % (name,)) + stream.write('\n\n') + + for i, (filename, lineno, name, line) in enumerate(traceback.extract_stack(frame)): + + stream.write(' File "%s", line %d, in %s\n' % (filename, lineno, name)) + if line: + stream.write(" %s\n" % (line.strip())) + + if i == 0 and 'self' in frame.f_locals: + stream.write(' self: ') + try: + stream.write(str(frame.f_locals['self'])) + except: + stream.write('Unable to get str of: %s' % (type(frame.f_locals['self']),)) + stream.write('\n') + stream.flush() + + stream.write('\n=============================== END Thread Dump ===============================') + stream.flush() + + +def _extract_variable_nested_braces(char_iter): + expression = [] + level = 0 + for c in char_iter: + if c == '{': + level += 1 + if c == '}': + level -= 1 + if level == -1: + return ''.join(expression).strip() + expression.append(c) + raise SyntaxError('Unbalanced braces in expression.') + + +def _extract_expression_list(log_message): + # Note: not using re because of nested braces. + expression = [] + expression_vars = [] + char_iter = iter(log_message) + for c in char_iter: + if c == '{': + expression_var = _extract_variable_nested_braces(char_iter) + if expression_var: + expression.append('%s') + expression_vars.append(expression_var) + else: + expression.append(c) + + expression = ''.join(expression) + return expression, expression_vars + + +def convert_dap_log_message_to_expression(log_message): + try: + expression, expression_vars = _extract_expression_list(log_message) + except SyntaxError: + return repr('Unbalanced braces in: %s' % (log_message)) + if not expression_vars: + return repr(expression) + # Note: use '%' to be compatible with Python 2.6. + return repr(expression) + ' % (' + ', '.join(str(x) for x in expression_vars) + ',)' + + +def notify_about_gevent_if_needed(stream=None): + ''' + When debugging with gevent check that the gevent flag is used if the user uses the gevent + monkey-patching. + + :return bool: + Returns True if a message had to be shown to the user and False otherwise. + ''' + stream = stream if stream is not None else sys.stderr + if not SUPPORT_GEVENT: + gevent_monkey = sys.modules.get('gevent.monkey') + if gevent_monkey is not None: + try: + saved = gevent_monkey.saved + except AttributeError: + pydev_log.exception_once('Error checking for gevent monkey-patching.') + return False + + if saved: + # Note: print to stderr as it may deadlock the debugger. + sys.stderr.write('%s\n' % (GEVENT_SUPPORT_NOT_SET_MSG,)) + return True + + return False + + +def hasattr_checked(obj, name): + try: + getattr(obj, name) + except: + # i.e.: Handle any exception, not only AttributeError. + return False + else: + return True + + +def getattr_checked(obj, name): + try: + return getattr(obj, name) + except: + # i.e.: Handle any exception, not only AttributeError. + return None + + +def dir_checked(obj): + try: + return dir(obj) + except: + return [] + + +def isinstance_checked(obj, cls): + try: + return isinstance(obj, cls) + except: + return False + + +class ScopeRequest(object): + + __slots__ = ['variable_reference', 'scope'] + + def __init__(self, variable_reference, scope): + assert scope in ('globals', 'locals') + self.variable_reference = variable_reference + self.scope = scope + + def __eq__(self, o): + if isinstance(o, ScopeRequest): + return self.variable_reference == o.variable_reference and self.scope == o.scope + + return False + + def __ne__(self, o): + return not self == o + + def __hash__(self): + return hash((self.variable_reference, self.scope)) + + +class DAPGrouper(object): + ''' + Note: this is a helper class to group variables on the debug adapter protocol (DAP). For + the xml protocol the type is just added to each variable and the UI can group/hide it as needed. + ''' + + SCOPE_SPECIAL_VARS = 'special variables' + SCOPE_PROTECTED_VARS = 'protected variables' + SCOPE_FUNCTION_VARS = 'function variables' + SCOPE_CLASS_VARS = 'class variables' + + SCOPES_SORTED = [ + SCOPE_SPECIAL_VARS, + SCOPE_PROTECTED_VARS, + SCOPE_FUNCTION_VARS, + SCOPE_CLASS_VARS, + ] + + __slots__ = ['variable_reference', 'scope', 'contents_debug_adapter_protocol'] + + def __init__(self, scope): + self.variable_reference = id(self) + self.scope = scope + self.contents_debug_adapter_protocol = [] + + def get_contents_debug_adapter_protocol(self): + return self.contents_debug_adapter_protocol[:] + + def __eq__(self, o): + if isinstance(o, ScopeRequest): + return self.variable_reference == o.variable_reference and self.scope == o.scope + + return False + + def __ne__(self, o): + return not self == o + + def __hash__(self): + return hash((self.variable_reference, self.scope)) + + def __repr__(self): + return '' + + def __str__(self): + return '' + + +def interrupt_main_thread(main_thread): + ''' + Generates a KeyboardInterrupt in the main thread by sending a Ctrl+C + or by calling thread.interrupt_main(). + + :param main_thread: + Needed because Jython needs main_thread._thread.interrupt() to be called. + + Note: if unable to send a Ctrl+C, the KeyboardInterrupt will only be raised + when the next Python instruction is about to be executed (so, it won't interrupt + a sleep(1000)). + ''' + pydev_log.debug('Interrupt main thread.') + called = False + try: + if os.name == 'posix': + # On Linux we can't interrupt 0 as in Windows because it's + # actually owned by a process -- on the good side, signals + # work much better on Linux! + os.kill(os.getpid(), signal.SIGINT) + called = True + + elif os.name == 'nt': + # This generates a Ctrl+C only for the current process and not + # to the process group! + # Note: there doesn't seem to be any public documentation for this + # function (although it seems to be present from Windows Server 2003 SP1 onwards + # according to: https://www.geoffchappell.com/studies/windows/win32/kernel32/api/index.htm) + ctypes.windll.kernel32.CtrlRoutine(0) + + # The code below is deprecated because it actually sends a Ctrl+C + # to the process group, so, if this was a process created without + # passing `CREATE_NEW_PROCESS_GROUP` the signal may be sent to the + # parent process and to sub-processes too (which is not ideal -- + # for instance, when using pytest-xdist, it'll actually stop the + # testing, even when called in the subprocess). + + # if hasattr_checked(signal, 'CTRL_C_EVENT'): + # os.kill(0, signal.CTRL_C_EVENT) + # else: + # # Python 2.6 + # ctypes.windll.kernel32.GenerateConsoleCtrlEvent(0, 0) + called = True + + except: + # If something went wrong, fallback to interrupting when the next + # Python instruction is being called. + pydev_log.exception('Error interrupting main thread (using fallback).') + + if not called: + try: + # In this case, we don't really interrupt a sleep() nor IO operations + # (this makes the KeyboardInterrupt be sent only when the next Python + # instruction is about to be executed). + if hasattr(thread, 'interrupt_main'): + thread.interrupt_main() + else: + main_thread._thread.interrupt() # Jython + except: + pydev_log.exception('Error on interrupt main thread fallback.') + + +class Timer(object): + + def __init__(self, min_diff=PYDEVD_WARN_SLOW_RESOLVE_TIMEOUT): + self.min_diff = min_diff + self._curr_time = time.time() + + def print_time(self, msg='Elapsed:'): + old = self._curr_time + new = self._curr_time = time.time() + diff = new - old + if diff >= self.min_diff: + print('%s: %.2fs' % (msg, diff)) + + def _report_slow(self, compute_msg, *args): + old = self._curr_time + new = self._curr_time = time.time() + diff = new - old + if diff >= self.min_diff: + py_db = get_global_debugger() + if py_db is not None: + msg = compute_msg(diff, *args) + py_db.writer.add_command(py_db.cmd_factory.make_warning_message(msg)) + + def report_if_compute_repr_attr_slow(self, attrs_tab_separated, attr_name, attr_type): + self._report_slow(self._compute_repr_slow, attrs_tab_separated, attr_name, attr_type) + + def _compute_repr_slow(self, diff, attrs_tab_separated, attr_name, attr_type): + try: + attr_type = attr_type.__name__ + except: + pass + if attrs_tab_separated: + return 'pydevd warning: Computing repr of %s.%s (%s) was slow (took %.2fs)\n' % ( + attrs_tab_separated.replace('\t', '.'), attr_name, attr_type, diff) + else: + return 'pydevd warning: Computing repr of %s (%s) was slow (took %.2fs)\n' % ( + attr_name, attr_type, diff) + + def report_if_getting_attr_slow(self, cls, attr_name): + self._report_slow(self._compute_get_attr_slow, cls, attr_name) + + def _compute_get_attr_slow(self, diff, cls, attr_name): + try: + cls = cls.__name__ + except: + pass + return 'pydevd warning: Getting attribute %s.%s was slow (took %.2fs)\n' % (cls, attr_name, diff) + + +def import_attr_from_module(import_with_attr_access): + if '.' not in import_with_attr_access: + # We need at least one '.' (we don't support just the module import, we need the attribute access too). + raise ImportError('Unable to import module with attr access: %s' % (import_with_attr_access,)) + + module_name, attr_name = import_with_attr_access.rsplit('.', 1) + + while True: + try: + mod = import_module(module_name) + except ImportError: + if '.' not in module_name: + raise ImportError('Unable to import module with attr access: %s' % (import_with_attr_access,)) + + module_name, new_attr_part = module_name.rsplit('.', 1) + attr_name = new_attr_part + '.' + attr_name + else: + # Ok, we got the base module, now, get the attribute we need. + try: + for attr in attr_name.split('.'): + mod = getattr(mod, attr) + return mod + except: + raise ImportError('Unable to import module with attr access: %s' % (import_with_attr_access,)) diff --git a/_pydevd_bundle/pydevd_vars.py b/_pydevd_bundle/pydevd_vars.py new file mode 100644 index 0000000..8010093 --- /dev/null +++ b/_pydevd_bundle/pydevd_vars.py @@ -0,0 +1,839 @@ +""" pydevd_vars deals with variables: + resolution/conversion to XML. +""" +import pickle +from _pydevd_bundle.pydevd_constants import get_frame, get_current_thread_id, \ + iter_chars, silence_warnings_decorator, get_global_debugger + +from _pydevd_bundle.pydevd_xml import ExceptionOnEvaluate, get_type, var_to_xml +from _pydev_bundle import pydev_log +import functools +from _pydevd_bundle.pydevd_thread_lifecycle import resume_threads, mark_thread_suspended, suspend_all_threads +from _pydevd_bundle.pydevd_comm_constants import CMD_SET_BREAK + +import sys # @Reimport + +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle import pydevd_save_locals, pydevd_timeout, pydevd_constants +from _pydev_bundle.pydev_imports import Exec, execfile +from _pydevd_bundle.pydevd_utils import to_string +import inspect +from _pydevd_bundle.pydevd_daemon_thread import PyDBDaemonThread +from _pydevd_bundle.pydevd_save_locals import update_globals_and_locals +from functools import lru_cache + +SENTINEL_VALUE = [] + + +class VariableError(RuntimeError): + pass + + +def iter_frames(frame): + while frame is not None: + yield frame + frame = frame.f_back + frame = None + + +def dump_frames(thread_id): + sys.stdout.write('dumping frames\n') + if thread_id != get_current_thread_id(threading.current_thread()): + raise VariableError("find_frame: must execute on same thread") + + frame = get_frame() + for frame in iter_frames(frame): + sys.stdout.write('%s\n' % pickle.dumps(frame)) + + +@silence_warnings_decorator +def getVariable(dbg, thread_id, frame_id, scope, attrs): + """ + returns the value of a variable + + :scope: can be BY_ID, EXPRESSION, GLOBAL, LOCAL, FRAME + + BY_ID means we'll traverse the list of all objects alive to get the object. + + :attrs: after reaching the proper scope, we have to get the attributes until we find + the proper location (i.e.: obj\tattr1\tattr2) + + :note: when BY_ID is used, the frame_id is considered the id of the object to find and + not the frame (as we don't care about the frame in this case). + """ + if scope == 'BY_ID': + if thread_id != get_current_thread_id(threading.current_thread()): + raise VariableError("getVariable: must execute on same thread") + + try: + import gc + objects = gc.get_objects() + except: + pass # Not all python variants have it. + else: + frame_id = int(frame_id) + for var in objects: + if id(var) == frame_id: + if attrs is not None: + attrList = attrs.split('\t') + for k in attrList: + _type, _type_name, resolver = get_type(var) + var = resolver.resolve(var, k) + + return var + + # If it didn't return previously, we coudn't find it by id (i.e.: alrceady garbage collected). + sys.stderr.write('Unable to find object with id: %s\n' % (frame_id,)) + return None + + frame = dbg.find_frame(thread_id, frame_id) + if frame is None: + return {} + + if attrs is not None: + attrList = attrs.split('\t') + else: + attrList = [] + + for attr in attrList: + attr.replace("@_@TAB_CHAR@_@", '\t') + + if scope == 'EXPRESSION': + for count in range(len(attrList)): + if count == 0: + # An Expression can be in any scope (globals/locals), therefore it needs to evaluated as an expression + var = evaluate_expression(dbg, frame, attrList[count], False) + else: + _type, _type_name, resolver = get_type(var) + var = resolver.resolve(var, attrList[count]) + else: + if scope == "GLOBAL": + var = frame.f_globals + del attrList[0] # globals are special, and they get a single dummy unused attribute + else: + # in a frame access both locals and globals as Python does + var = {} + var.update(frame.f_globals) + var.update(frame.f_locals) + + for k in attrList: + _type, _type_name, resolver = get_type(var) + var = resolver.resolve(var, k) + + return var + + +def resolve_compound_variable_fields(dbg, thread_id, frame_id, scope, attrs): + """ + Resolve compound variable in debugger scopes by its name and attributes + + :param thread_id: id of the variable's thread + :param frame_id: id of the variable's frame + :param scope: can be BY_ID, EXPRESSION, GLOBAL, LOCAL, FRAME + :param attrs: after reaching the proper scope, we have to get the attributes until we find + the proper location (i.e.: obj\tattr1\tattr2) + :return: a dictionary of variables's fields + """ + + var = getVariable(dbg, thread_id, frame_id, scope, attrs) + + try: + _type, type_name, resolver = get_type(var) + return type_name, resolver.get_dictionary(var) + except: + pydev_log.exception('Error evaluating: thread_id: %s\nframe_id: %s\nscope: %s\nattrs: %s.', + thread_id, frame_id, scope, attrs) + + +def resolve_var_object(var, attrs): + """ + Resolve variable's attribute + + :param var: an object of variable + :param attrs: a sequence of variable's attributes separated by \t (i.e.: obj\tattr1\tattr2) + :return: a value of resolved variable's attribute + """ + if attrs is not None: + attr_list = attrs.split('\t') + else: + attr_list = [] + for k in attr_list: + type, _type_name, resolver = get_type(var) + var = resolver.resolve(var, k) + return var + + +def resolve_compound_var_object_fields(var, attrs): + """ + Resolve compound variable by its object and attributes + + :param var: an object of variable + :param attrs: a sequence of variable's attributes separated by \t (i.e.: obj\tattr1\tattr2) + :return: a dictionary of variables's fields + """ + attr_list = attrs.split('\t') + + for k in attr_list: + type, _type_name, resolver = get_type(var) + var = resolver.resolve(var, k) + + try: + type, _type_name, resolver = get_type(var) + return resolver.get_dictionary(var) + except: + pydev_log.exception() + + +def custom_operation(dbg, thread_id, frame_id, scope, attrs, style, code_or_file, operation_fn_name): + """ + We'll execute the code_or_file and then search in the namespace the operation_fn_name to execute with the given var. + + code_or_file: either some code (i.e.: from pprint import pprint) or a file to be executed. + operation_fn_name: the name of the operation to execute after the exec (i.e.: pprint) + """ + expressionValue = getVariable(dbg, thread_id, frame_id, scope, attrs) + + try: + namespace = {'__name__': ''} + if style == "EXECFILE": + namespace['__file__'] = code_or_file + execfile(code_or_file, namespace, namespace) + else: # style == EXEC + namespace['__file__'] = '' + Exec(code_or_file, namespace, namespace) + + return str(namespace[operation_fn_name](expressionValue)) + except: + pydev_log.exception() + + +@lru_cache(3) +def _expression_to_evaluate(expression): + keepends = True + lines = expression.splitlines(keepends) + # find first non-empty line + chars_to_strip = 0 + for line in lines: + if line.strip(): # i.e.: check first non-empty line + for c in iter_chars(line): + if c.isspace(): + chars_to_strip += 1 + else: + break + break + + if chars_to_strip: + # I.e.: check that the chars we'll remove are really only whitespaces. + proceed = True + new_lines = [] + for line in lines: + if not proceed: + break + for c in iter_chars(line[:chars_to_strip]): + if not c.isspace(): + proceed = False + break + + new_lines.append(line[chars_to_strip:]) + + if proceed: + if isinstance(expression, bytes): + expression = b''.join(new_lines) + else: + expression = u''.join(new_lines) + + return expression + + +def eval_in_context(expression, global_vars, local_vars, py_db=None): + result = None + try: + compiled = compile_as_eval(expression) + is_async = inspect.CO_COROUTINE & compiled.co_flags == inspect.CO_COROUTINE + + if is_async: + if py_db is None: + py_db = get_global_debugger() + if py_db is None: + raise RuntimeError('Cannot evaluate async without py_db.') + t = _EvalAwaitInNewEventLoop(py_db, compiled, global_vars, local_vars) + t.start() + t.join() + + if t.exc: + raise t.exc[1].with_traceback(t.exc[2]) + else: + result = t.evaluated_value + else: + result = eval(compiled, global_vars, local_vars) + except (Exception, KeyboardInterrupt): + etype, result, tb = sys.exc_info() + result = ExceptionOnEvaluate(result, etype, tb) + + # Ok, we have the initial error message, but let's see if we're dealing with a name mangling error... + try: + if '.__' in expression: + # Try to handle '__' name mangling (for simple cases such as self.__variable.__another_var). + split = expression.split('.') + entry = split[0] + + if local_vars is None: + local_vars = global_vars + curr = local_vars[entry] # Note: we want the KeyError if it's not there. + for entry in split[1:]: + if entry.startswith('__') and not hasattr(curr, entry): + entry = '_%s%s' % (curr.__class__.__name__, entry) + curr = getattr(curr, entry) + + result = curr + except: + pass + return result + + +def _run_with_interrupt_thread(original_func, py_db, curr_thread, frame, expression, is_exec): + on_interrupt_threads = None + timeout_tracker = py_db.timeout_tracker # : :type timeout_tracker: TimeoutTracker + + interrupt_thread_timeout = pydevd_constants.PYDEVD_INTERRUPT_THREAD_TIMEOUT + + if interrupt_thread_timeout > 0: + on_interrupt_threads = pydevd_timeout.create_interrupt_this_thread_callback() + pydev_log.info('Doing evaluate with interrupt threads timeout: %s.', interrupt_thread_timeout) + + if on_interrupt_threads is None: + return original_func(py_db, frame, expression, is_exec) + else: + with timeout_tracker.call_on_timeout(interrupt_thread_timeout, on_interrupt_threads): + return original_func(py_db, frame, expression, is_exec) + + +def _run_with_unblock_threads(original_func, py_db, curr_thread, frame, expression, is_exec): + on_timeout_unblock_threads = None + timeout_tracker = py_db.timeout_tracker # : :type timeout_tracker: TimeoutTracker + + if py_db.multi_threads_single_notification: + unblock_threads_timeout = pydevd_constants.PYDEVD_UNBLOCK_THREADS_TIMEOUT + else: + unblock_threads_timeout = -1 # Don't use this if threads are managed individually. + + if unblock_threads_timeout >= 0: + pydev_log.info('Doing evaluate with unblock threads timeout: %s.', unblock_threads_timeout) + tid = get_current_thread_id(curr_thread) + + def on_timeout_unblock_threads(): + on_timeout_unblock_threads.called = True + pydev_log.info('Resuming threads after evaluate timeout.') + resume_threads('*', except_thread=curr_thread) + py_db.threads_suspended_single_notification.on_thread_resume(tid) + + on_timeout_unblock_threads.called = False + + try: + if on_timeout_unblock_threads is None: + return _run_with_interrupt_thread(original_func, py_db, curr_thread, frame, expression, is_exec) + else: + with timeout_tracker.call_on_timeout(unblock_threads_timeout, on_timeout_unblock_threads): + return _run_with_interrupt_thread(original_func, py_db, curr_thread, frame, expression, is_exec) + + finally: + if on_timeout_unblock_threads is not None and on_timeout_unblock_threads.called: + mark_thread_suspended(curr_thread, CMD_SET_BREAK) + py_db.threads_suspended_single_notification.increment_suspend_time() + suspend_all_threads(py_db, except_thread=curr_thread) + py_db.threads_suspended_single_notification.on_thread_suspend(tid, CMD_SET_BREAK) + + +def _evaluate_with_timeouts(original_func): + ''' + Provides a decorator that wraps the original evaluate to deal with slow evaluates. + + If some evaluation is too slow, we may show a message, resume threads or interrupt them + as needed (based on the related configurations). + ''' + + @functools.wraps(original_func) + def new_func(py_db, frame, expression, is_exec): + if py_db is None: + # Only for testing... + pydev_log.critical('_evaluate_with_timeouts called without py_db!') + return original_func(py_db, frame, expression, is_exec) + warn_evaluation_timeout = pydevd_constants.PYDEVD_WARN_EVALUATION_TIMEOUT + curr_thread = threading.current_thread() + + def on_warn_evaluation_timeout(): + py_db.writer.add_command(py_db.cmd_factory.make_evaluation_timeout_msg( + py_db, expression, curr_thread)) + + timeout_tracker = py_db.timeout_tracker # : :type timeout_tracker: TimeoutTracker + with timeout_tracker.call_on_timeout(warn_evaluation_timeout, on_warn_evaluation_timeout): + return _run_with_unblock_threads(original_func, py_db, curr_thread, frame, expression, is_exec) + + return new_func + + +_ASYNC_COMPILE_FLAGS = None +try: + from ast import PyCF_ALLOW_TOP_LEVEL_AWAIT + _ASYNC_COMPILE_FLAGS = PyCF_ALLOW_TOP_LEVEL_AWAIT +except: + pass + + +def compile_as_eval(expression): + ''' + + :param expression: + The expression to be _compiled. + + :return: code object + + :raises Exception if the expression cannot be evaluated. + ''' + expression_to_evaluate = _expression_to_evaluate(expression) + if _ASYNC_COMPILE_FLAGS is not None: + return compile(expression_to_evaluate, '', 'eval', _ASYNC_COMPILE_FLAGS) + else: + return compile(expression_to_evaluate, '', 'eval') + + +def _compile_as_exec(expression): + ''' + + :param expression: + The expression to be _compiled. + + :return: code object + + :raises Exception if the expression cannot be evaluated. + ''' + expression_to_evaluate = _expression_to_evaluate(expression) + if _ASYNC_COMPILE_FLAGS is not None: + return compile(expression_to_evaluate, '', 'exec', _ASYNC_COMPILE_FLAGS) + else: + return compile(expression_to_evaluate, '', 'exec') + + +class _EvalAwaitInNewEventLoop(PyDBDaemonThread): + + def __init__(self, py_db, compiled, updated_globals, updated_locals): + PyDBDaemonThread.__init__(self, py_db) + self._compiled = compiled + self._updated_globals = updated_globals + self._updated_locals = updated_locals + + # Output + self.evaluated_value = None + self.exc = None + + async def _async_func(self): + return await eval(self._compiled, self._updated_locals, self._updated_globals) + + def _on_run(self): + try: + import asyncio + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + self.evaluated_value = asyncio.run(self._async_func()) + except: + self.exc = sys.exc_info() + + +@_evaluate_with_timeouts +def evaluate_expression(py_db, frame, expression, is_exec): + ''' + :param str expression: + The expression to be evaluated. + + Note that if the expression is indented it's automatically dedented (based on the indentation + found on the first non-empty line). + + i.e.: something as: + + ` + def method(): + a = 1 + ` + + becomes: + + ` + def method(): + a = 1 + ` + + Also, it's possible to evaluate calls with a top-level await (currently this is done by + creating a new event loop in a new thread and making the evaluate at that thread -- note + that this is still done synchronously so the evaluation has to finish before this + function returns). + + :param is_exec: determines if we should do an exec or an eval. + There are some changes in this function depending on whether it's an exec or an eval. + + When it's an exec (i.e.: is_exec==True): + This function returns None. + Any exception that happens during the evaluation is reraised. + If the expression could actually be evaluated, the variable is printed to the console if not None. + + When it's an eval (i.e.: is_exec==False): + This function returns the result from the evaluation. + If some exception happens in this case, the exception is caught and a ExceptionOnEvaluate is returned. + Also, in this case we try to resolve name-mangling (i.e.: to be able to add a self.__my_var watch). + + :param py_db: + The debugger. Only needed if some top-level await is detected (for creating a + PyDBDaemonThread). + ''' + if frame is None: + return + + # This is very tricky. Some statements can change locals and use them in the same + # call (see https://github.com/microsoft/debugpy/issues/815), also, if locals and globals are + # passed separately, it's possible that one gets updated but apparently Python will still + # try to load from the other, so, what's done is that we merge all in a single dict and + # then go on and update the frame with the results afterwards. + + # -- see tests in test_evaluate_expression.py + + # This doesn't work because the variables aren't updated in the locals in case the + # evaluation tries to set a variable and use it in the same expression. + # updated_globals = frame.f_globals + # updated_locals = frame.f_locals + + # This doesn't work because the variables aren't updated in the locals in case the + # evaluation tries to set a variable and use it in the same expression. + # updated_globals = {} + # updated_globals.update(frame.f_globals) + # updated_globals.update(frame.f_locals) + # + # updated_locals = frame.f_locals + + # This doesn't work either in the case where the evaluation tries to set a variable and use + # it in the same expression (I really don't know why as it seems like this *should* work + # in theory but doesn't in practice). + # updated_globals = {} + # updated_globals.update(frame.f_globals) + # + # updated_locals = {} + # updated_globals.update(frame.f_locals) + + # This is the only case that worked consistently to run the tests in test_evaluate_expression.py + # It's a bit unfortunate because although the exec works in this case, we have to manually + # put the updates in the frame locals afterwards. + updated_globals = {} + updated_globals.update(frame.f_globals) + updated_globals.update(frame.f_locals) + + initial_globals = updated_globals.copy() + + updated_locals = None + + try: + expression = expression.replace('@LINE@', '\n') + + if is_exec: + try: + # Try to make it an eval (if it is an eval we can print it, otherwise we'll exec it and + # it will have whatever the user actually did) + compiled = compile_as_eval(expression) + except Exception: + compiled = None + + if compiled is None: + try: + compiled = _compile_as_exec(expression) + is_async = inspect.CO_COROUTINE & compiled.co_flags == inspect.CO_COROUTINE + if is_async: + t = _EvalAwaitInNewEventLoop(py_db, compiled, updated_globals, updated_locals) + t.start() + t.join() + + if t.exc: + raise t.exc[1].with_traceback(t.exc[2]) + else: + Exec(compiled, updated_globals, updated_locals) + finally: + # Update the globals even if it errored as it may have partially worked. + update_globals_and_locals(updated_globals, initial_globals, frame) + else: + is_async = inspect.CO_COROUTINE & compiled.co_flags == inspect.CO_COROUTINE + if is_async: + t = _EvalAwaitInNewEventLoop(py_db, compiled, updated_globals, updated_locals) + t.start() + t.join() + + if t.exc: + raise t.exc[1].with_traceback(t.exc[2]) + else: + result = t.evaluated_value + else: + result = eval(compiled, updated_globals, updated_locals) + if result is not None: # Only print if it's not None (as python does) + sys.stdout.write('%s\n' % (result,)) + return + + else: + ret = eval_in_context(expression, updated_globals, updated_locals, py_db) + try: + is_exception_returned = ret.__class__ == ExceptionOnEvaluate + except: + pass + else: + if not is_exception_returned: + # i.e.: by using a walrus assignment (:=), expressions can change the locals, + # so, make sure that we save the locals back to the frame. + update_globals_and_locals(updated_globals, initial_globals, frame) + return ret + finally: + # Should not be kept alive if an exception happens and this frame is kept in the stack. + del updated_globals + del updated_locals + del initial_globals + del frame + + +def change_attr_expression(frame, attr, expression, dbg, value=SENTINEL_VALUE): + '''Changes some attribute in a given frame. + ''' + if frame is None: + return + + try: + expression = expression.replace('@LINE@', '\n') + + if dbg.plugin and value is SENTINEL_VALUE: + result = dbg.plugin.change_variable(frame, attr, expression) + if result: + return result + + if attr[:7] == "Globals": + attr = attr[8:] + if attr in frame.f_globals: + if value is SENTINEL_VALUE: + value = eval(expression, frame.f_globals, frame.f_locals) + frame.f_globals[attr] = value + return frame.f_globals[attr] + else: + if '.' not in attr: # i.e.: if we have a '.', we're changing some attribute of a local var. + if pydevd_save_locals.is_save_locals_available(): + if value is SENTINEL_VALUE: + value = eval(expression, frame.f_globals, frame.f_locals) + frame.f_locals[attr] = value + pydevd_save_locals.save_locals(frame) + return frame.f_locals[attr] + + # i.e.: case with '.' or save locals not available (just exec the assignment in the frame). + if value is SENTINEL_VALUE: + value = eval(expression, frame.f_globals, frame.f_locals) + result = value + Exec('%s=%s' % (attr, expression), frame.f_globals, frame.f_locals) + return result + + except Exception: + pydev_log.exception() + + +MAXIMUM_ARRAY_SIZE = 100 +MAX_SLICE_SIZE = 1000 + + +def table_like_struct_to_xml(array, name, roffset, coffset, rows, cols, format): + _, type_name, _ = get_type(array) + if type_name == 'ndarray': + array, metaxml, r, c, f = array_to_meta_xml(array, name, format) + xml = metaxml + format = '%' + f + if rows == -1 and cols == -1: + rows = r + cols = c + xml += array_to_xml(array, roffset, coffset, rows, cols, format) + elif type_name == 'DataFrame': + xml = dataframe_to_xml(array, name, roffset, coffset, rows, cols, format) + else: + raise VariableError("Do not know how to convert type %s to table" % (type_name)) + + return "%s" % xml + + +def array_to_xml(array, roffset, coffset, rows, cols, format): + xml = "" + rows = min(rows, MAXIMUM_ARRAY_SIZE) + cols = min(cols, MAXIMUM_ARRAY_SIZE) + + # there is no obvious rule for slicing (at least 5 choices) + if len(array) == 1 and (rows > 1 or cols > 1): + array = array[0] + if array.size > len(array): + array = array[roffset:, coffset:] + rows = min(rows, len(array)) + cols = min(cols, len(array[0])) + if len(array) == 1: + array = array[0] + elif array.size == len(array): + if roffset == 0 and rows == 1: + array = array[coffset:] + cols = min(cols, len(array)) + elif coffset == 0 and cols == 1: + array = array[roffset:] + rows = min(rows, len(array)) + + xml += "" % (rows, cols) + for row in range(rows): + xml += "" % to_string(row) + for col in range(cols): + value = array + if rows == 1 or cols == 1: + if rows == 1 and cols == 1: + value = array[0] + else: + if rows == 1: + dim = col + else: + dim = row + value = array[dim] + if "ndarray" in str(type(value)): + value = value[0] + else: + value = array[row][col] + value = format % value + xml += var_to_xml(value, '') + return xml + + +def array_to_meta_xml(array, name, format): + type = array.dtype.kind + slice = name + l = len(array.shape) + + # initial load, compute slice + if format == '%': + if l > 2: + slice += '[0]' * (l - 2) + for r in range(l - 2): + array = array[0] + if type == 'f': + format = '.5f' + elif type == 'i' or type == 'u': + format = 'd' + else: + format = 's' + else: + format = format.replace('%', '') + + l = len(array.shape) + reslice = "" + if l > 2: + raise Exception("%s has more than 2 dimensions." % slice) + elif l == 1: + # special case with 1D arrays arr[i, :] - row, but arr[:, i] - column with equal shape and ndim + # http://stackoverflow.com/questions/16837946/numpy-a-2-rows-1-column-file-loadtxt-returns-1row-2-columns + # explanation: http://stackoverflow.com/questions/15165170/how-do-i-maintain-row-column-orientation-of-vectors-in-numpy?rq=1 + # we use kind of a hack - get information about memory from C_CONTIGUOUS + is_row = array.flags['C_CONTIGUOUS'] + + if is_row: + rows = 1 + cols = min(len(array), MAX_SLICE_SIZE) + if cols < len(array): + reslice = '[0:%s]' % (cols) + array = array[0:cols] + else: + cols = 1 + rows = min(len(array), MAX_SLICE_SIZE) + if rows < len(array): + reslice = '[0:%s]' % (rows) + array = array[0:rows] + elif l == 2: + rows = min(array.shape[-2], MAX_SLICE_SIZE) + cols = min(array.shape[-1], MAX_SLICE_SIZE) + if cols < array.shape[-1] or rows < array.shape[-2]: + reslice = '[0:%s, 0:%s]' % (rows, cols) + array = array[0:rows, 0:cols] + + # avoid slice duplication + if not slice.endswith(reslice): + slice += reslice + + bounds = (0, 0) + if type in "biufc": + bounds = (array.min(), array.max()) + xml = '' % \ + (slice, rows, cols, format, type, bounds[1], bounds[0]) + return array, xml, rows, cols, format + + +def dataframe_to_xml(df, name, roffset, coffset, rows, cols, format): + """ + :type df: pandas.core.frame.DataFrame + :type name: str + :type coffset: int + :type roffset: int + :type rows: int + :type cols: int + :type format: str + + + """ + num_rows = min(df.shape[0], MAX_SLICE_SIZE) + num_cols = min(df.shape[1], MAX_SLICE_SIZE) + if (num_rows, num_cols) != df.shape: + df = df.iloc[0:num_rows, 0: num_cols] + slice = '.iloc[0:%s, 0:%s]' % (num_rows, num_cols) + else: + slice = '' + slice = name + slice + xml = '\n' % \ + (slice, num_rows, num_cols) + + if (rows, cols) == (-1, -1): + rows, cols = num_rows, num_cols + + rows = min(rows, MAXIMUM_ARRAY_SIZE) + cols = min(min(cols, MAXIMUM_ARRAY_SIZE), num_cols) + # need to precompute column bounds here before slicing! + col_bounds = [None] * cols + for col in range(cols): + dtype = df.dtypes.iloc[coffset + col].kind + if dtype in "biufc": + cvalues = df.iloc[:, coffset + col] + bounds = (cvalues.min(), cvalues.max()) + else: + bounds = (0, 0) + col_bounds[col] = bounds + + df = df.iloc[roffset: roffset + rows, coffset: coffset + cols] + rows, cols = df.shape + + xml += "\n" % (rows, cols) + format = format.replace('%', '') + col_formats = [] + + get_label = lambda label: str(label) if not isinstance(label, tuple) else '/'.join(map(str, label)) + + for col in range(cols): + dtype = df.dtypes.iloc[col].kind + if dtype == 'f' and format: + fmt = format + elif dtype == 'f': + fmt = '.5f' + elif dtype == 'i' or dtype == 'u': + fmt = 'd' + else: + fmt = 's' + col_formats.append('%' + fmt) + bounds = col_bounds[col] + + xml += '\n' % \ + (str(col), get_label(df.axes[1].values[col]), dtype, fmt, bounds[1], bounds[0]) + for row, label in enumerate(iter(df.axes[0])): + xml += "\n" % \ + (str(row), get_label(label)) + xml += "\n" + xml += "\n" % (rows, cols) + for row in range(rows): + xml += "\n" % str(row) + for col in range(cols): + value = df.iat[row, col] + value = col_formats[col] % value + xml += var_to_xml(value, '') + return xml diff --git a/_pydevd_bundle/pydevd_vm_type.py b/_pydevd_bundle/pydevd_vm_type.py new file mode 100644 index 0000000..d2cf5b6 --- /dev/null +++ b/_pydevd_bundle/pydevd_vm_type.py @@ -0,0 +1,41 @@ +import sys + +#======================================================================================================================= +# PydevdVmType +#======================================================================================================================= +class PydevdVmType: + + PYTHON = 'python' + JYTHON = 'jython' + vm_type = None + + +#======================================================================================================================= +# set_vm_type +#======================================================================================================================= +def set_vm_type(vm_type): + PydevdVmType.vm_type = vm_type + + +#======================================================================================================================= +# get_vm_type +#======================================================================================================================= +def get_vm_type(): + if PydevdVmType.vm_type is None: + setup_type() + return PydevdVmType.vm_type + + +#======================================================================================================================= +# setup_type +#======================================================================================================================= +def setup_type(str=None): + if str is not None: + PydevdVmType.vm_type = str + return + + if sys.platform.startswith("java"): + PydevdVmType.vm_type = PydevdVmType.JYTHON + else: + PydevdVmType.vm_type = PydevdVmType.PYTHON + diff --git a/_pydevd_bundle/pydevd_xml.py b/_pydevd_bundle/pydevd_xml.py new file mode 100644 index 0000000..dcd1cdc --- /dev/null +++ b/_pydevd_bundle/pydevd_xml.py @@ -0,0 +1,399 @@ +from _pydev_bundle import pydev_log +from _pydevd_bundle import pydevd_extension_utils +from _pydevd_bundle import pydevd_resolver +import sys +from _pydevd_bundle.pydevd_constants import BUILTINS_MODULE_NAME, MAXIMUM_VARIABLE_REPRESENTATION_SIZE, \ + RETURN_VALUES_DICT, LOAD_VALUES_ASYNC, DEFAULT_VALUE +from _pydev_bundle.pydev_imports import quote +from _pydevd_bundle.pydevd_extension_api import TypeResolveProvider, StrPresentationProvider +from _pydevd_bundle.pydevd_utils import isinstance_checked, hasattr_checked, DAPGrouper +from _pydevd_bundle.pydevd_resolver import get_var_scope + +try: + import types + + frame_type = types.FrameType +except: + frame_type = None + + +def make_valid_xml_value(s): + # Same thing as xml.sax.saxutils.escape but also escaping double quotes. + return s.replace("&", "&").replace('<', '<').replace('>', '>').replace('"', '"') + + +class ExceptionOnEvaluate: + + def __init__(self, result, etype, tb): + self.result = result + self.etype = etype + self.tb = tb + + +_IS_JYTHON = sys.platform.startswith("java") + + +def _create_default_type_map(): + default_type_map = [ + # None means that it should not be treated as a compound variable + + # isintance does not accept a tuple on some versions of python, so, we must declare it expanded + (type(None), None,), + (int, None), + (float, None), + (complex, None), + (str, None), + (tuple, pydevd_resolver.tupleResolver), + (list, pydevd_resolver.tupleResolver), + (dict, pydevd_resolver.dictResolver), + ] + try: + from collections import OrderedDict + default_type_map.insert(0, (OrderedDict, pydevd_resolver.orderedDictResolver)) + # we should put it before dict + except: + pass + + try: + default_type_map.append((long, None)) # @UndefinedVariable + except: + pass # not available on all python versions + + default_type_map.append((DAPGrouper, pydevd_resolver.dapGrouperResolver)) + + try: + default_type_map.append((set, pydevd_resolver.setResolver)) + except: + pass # not available on all python versions + + try: + default_type_map.append((frozenset, pydevd_resolver.setResolver)) + except: + pass # not available on all python versions + + try: + from django.utils.datastructures import MultiValueDict + default_type_map.insert(0, (MultiValueDict, pydevd_resolver.multiValueDictResolver)) + # we should put it before dict + except: + pass # django may not be installed + + try: + from django.forms import BaseForm + default_type_map.insert(0, (BaseForm, pydevd_resolver.djangoFormResolver)) + # we should put it before instance resolver + except: + pass # django may not be installed + + try: + from collections import deque + default_type_map.append((deque, pydevd_resolver.dequeResolver)) + except: + pass + + if frame_type is not None: + default_type_map.append((frame_type, pydevd_resolver.frameResolver)) + + if _IS_JYTHON: + from org.python import core # @UnresolvedImport + default_type_map.append((core.PyNone, None)) + default_type_map.append((core.PyInteger, None)) + default_type_map.append((core.PyLong, None)) + default_type_map.append((core.PyFloat, None)) + default_type_map.append((core.PyComplex, None)) + default_type_map.append((core.PyString, None)) + default_type_map.append((core.PyTuple, pydevd_resolver.tupleResolver)) + default_type_map.append((core.PyList, pydevd_resolver.tupleResolver)) + default_type_map.append((core.PyDictionary, pydevd_resolver.dictResolver)) + default_type_map.append((core.PyStringMap, pydevd_resolver.dictResolver)) + + if hasattr(core, 'PyJavaInstance'): + # Jython 2.5b3 removed it. + default_type_map.append((core.PyJavaInstance, pydevd_resolver.instanceResolver)) + + return default_type_map + + +class TypeResolveHandler(object): + NO_PROVIDER = [] # Sentinel value (any mutable object to be used as a constant would be valid). + + def __init__(self): + # Note: don't initialize with the types we already know about so that the extensions can override + # the default resolvers that are already available if they want. + self._type_to_resolver_cache = {} + self._type_to_str_provider_cache = {} + self._initialized = False + + def _initialize(self): + self._default_type_map = _create_default_type_map() + self._resolve_providers = pydevd_extension_utils.extensions_of_type(TypeResolveProvider) + self._str_providers = pydevd_extension_utils.extensions_of_type(StrPresentationProvider) + self._initialized = True + + def get_type(self, o): + try: + try: + # Faster than type(o) as we don't need the function call. + type_object = o.__class__ # could fail here + type_name = type_object.__name__ + return self._get_type(o, type_object, type_name) # could fail here + except: + # Not all objects have __class__ (i.e.: there are bad bindings around). + type_object = type(o) + type_name = type_object.__name__ + + try: + return self._get_type(o, type_object, type_name) + except: + if isinstance(type_object, type): + # If it's still something manageable, use the default resolver, otherwise + # fallback to saying that it wasn't possible to get any info on it. + return type_object, str(type_name), pydevd_resolver.defaultResolver + + return 'Unable to get Type', 'Unable to get Type', None + except: + # This happens for org.python.core.InitModule + return 'Unable to get Type', 'Unable to get Type', None + + def _get_type(self, o, type_object, type_name): + # Note: we could have an exception here if the type_object is not hashable... + resolver = self._type_to_resolver_cache.get(type_object) + if resolver is not None: + return type_object, type_name, resolver + + if not self._initialized: + self._initialize() + + try: + for resolver in self._resolve_providers: + if resolver.can_provide(type_object, type_name): + # Cache it + self._type_to_resolver_cache[type_object] = resolver + return type_object, type_name, resolver + + for t in self._default_type_map: + if isinstance_checked(o, t[0]): + # Cache it + resolver = t[1] + self._type_to_resolver_cache[type_object] = resolver + return (type_object, type_name, resolver) + except: + pydev_log.exception() + + # No match return default (and cache it). + resolver = pydevd_resolver.defaultResolver + self._type_to_resolver_cache[type_object] = resolver + return type_object, type_name, resolver + + if _IS_JYTHON: + _base_get_type = _get_type + + def _get_type(self, o, type_object, type_name): + if type_name == 'org.python.core.PyJavaInstance': + return type_object, type_name, pydevd_resolver.instanceResolver + + if type_name == 'org.python.core.PyArray': + return type_object, type_name, pydevd_resolver.jyArrayResolver + + return self._base_get_type(o, type_object, type_name) + + def str_from_providers(self, o, type_object, type_name): + provider = self._type_to_str_provider_cache.get(type_object) + + if provider is self.NO_PROVIDER: + return None + + if provider is not None: + return provider.get_str(o) + + if not self._initialized: + self._initialize() + + for provider in self._str_providers: + if provider.can_provide(type_object, type_name): + self._type_to_str_provider_cache[type_object] = provider + try: + return provider.get_str(o) + except: + pydev_log.exception("Error when getting str with custom provider: %s." % (provider,)) + + self._type_to_str_provider_cache[type_object] = self.NO_PROVIDER + return None + + +_TYPE_RESOLVE_HANDLER = TypeResolveHandler() + +""" +def get_type(o): + Receives object and returns a triple (type_object, type_string, resolver). + + resolver != None means that variable is a container, and should be displayed as a hierarchy. + + Use the resolver to get its attributes. + + All container objects (i.e.: dict, list, tuple, object, etc) should have a resolver. +""" +get_type = _TYPE_RESOLVE_HANDLER.get_type + +_str_from_providers = _TYPE_RESOLVE_HANDLER.str_from_providers + + +def is_builtin(x): + return getattr(x, '__module__', None) == BUILTINS_MODULE_NAME + + +def should_evaluate_full_value(val): + return not LOAD_VALUES_ASYNC or (is_builtin(type(val)) and not isinstance_checked(val, (list, tuple, dict))) + + +def return_values_from_dict_to_xml(return_dict): + res = [] + for name, val in return_dict.items(): + res.append(var_to_xml(val, name, additional_in_xml=' isRetVal="True"')) + return ''.join(res) + + +def frame_vars_to_xml(frame_f_locals, hidden_ns=None): + """ dumps frame variables to XML + + """ + xml = [] + + keys = sorted(frame_f_locals) + + return_values_xml = [] + + for k in keys: + try: + v = frame_f_locals[k] + eval_full_val = should_evaluate_full_value(v) + + if k == '_pydev_stop_at_break': + continue + + if k == RETURN_VALUES_DICT: + for name, val in v.items(): + return_values_xml.append(var_to_xml(val, name, additional_in_xml=' isRetVal="True"')) + + else: + if hidden_ns is not None and k in hidden_ns: + xml.append(var_to_xml(v, str(k), additional_in_xml=' isIPythonHidden="True"', + evaluate_full_value=eval_full_val)) + else: + xml.append(var_to_xml(v, str(k), evaluate_full_value=eval_full_val)) + except Exception: + pydev_log.exception("Unexpected error, recovered safely.") + + # Show return values as the first entry. + return_values_xml.extend(xml) + return ''.join(return_values_xml) + + +def get_variable_details(val, evaluate_full_value=True, to_string=None): + try: + # This should be faster than isinstance (but we have to protect against not having a '__class__' attribute). + is_exception_on_eval = val.__class__ == ExceptionOnEvaluate + except: + is_exception_on_eval = False + + if is_exception_on_eval: + v = val.result + else: + v = val + + _type, type_name, resolver = get_type(v) + type_qualifier = getattr(_type, "__module__", "") + if not evaluate_full_value: + value = DEFAULT_VALUE + else: + try: + str_from_provider = _str_from_providers(v, _type, type_name) + if str_from_provider is not None: + value = str_from_provider + + elif to_string is not None: + value = to_string(v) + + elif hasattr_checked(v, '__class__'): + if v.__class__ == frame_type: + value = pydevd_resolver.frameResolver.get_frame_name(v) + + elif v.__class__ in (list, tuple): + if len(v) > 300: + value = '%s: %s' % (str(v.__class__), '' % (len(v),)) + else: + value = '%s: %s' % (str(v.__class__), v) + else: + try: + cName = str(v.__class__) + if cName.find('.') != -1: + cName = cName.split('.')[-1] + + elif cName.find("'") != -1: # does not have '.' (could be something like ) + cName = cName[cName.index("'") + 1:] + + if cName.endswith("'>"): + cName = cName[:-2] + except: + cName = str(v.__class__) + + value = '%s: %s' % (cName, v) + else: + value = str(v) + except: + try: + value = repr(v) + except: + value = 'Unable to get repr for %s' % v.__class__ + + # fix to work with unicode values + try: + if value.__class__ == bytes: + value = value.decode('utf-8', 'replace') + except TypeError: + pass + + return type_name, type_qualifier, is_exception_on_eval, resolver, value + + +def var_to_xml(val, name, trim_if_too_big=True, additional_in_xml='', evaluate_full_value=True): + """ single variable or dictionary to xml representation """ + + type_name, type_qualifier, is_exception_on_eval, resolver, value = get_variable_details( + val, evaluate_full_value) + + scope = get_var_scope(name, val, '', True) + try: + name = quote(name, '/>_= ') # TODO: Fix PY-5834 without using quote + except: + pass + + xml = ' MAXIMUM_VARIABLE_REPRESENTATION_SIZE and trim_if_too_big: + value = value[0:MAXIMUM_VARIABLE_REPRESENTATION_SIZE] + value += '...' + + xml_value = ' value="%s"' % (make_valid_xml_value(quote(value, '/>_= '))) + else: + xml_value = '' + + if is_exception_on_eval: + xml_container = ' isErrorOnEval="True"' + else: + if resolver is not None: + xml_container = ' isContainer="True"' + else: + xml_container = '' + + if scope: + return ''.join((xml, xml_qualifier, xml_value, xml_container, additional_in_xml, ' scope="', scope, '"', ' />\n')) + else: + return ''.join((xml, xml_qualifier, xml_value, xml_container, additional_in_xml, ' />\n')) diff --git a/_pydevd_frame_eval/.gitignore b/_pydevd_frame_eval/.gitignore new file mode 100644 index 0000000..b1a6718 --- /dev/null +++ b/_pydevd_frame_eval/.gitignore @@ -0,0 +1,3 @@ +/pydevd_frame_evaluator.*.so +/pydevd_frame_evaluator.*.pyd +/pydevd_frame_evaluator.pyx diff --git a/_pydevd_frame_eval/__init__.py b/_pydevd_frame_eval/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/_pydevd_frame_eval/pydevd_frame_eval_cython_wrapper.py b/_pydevd_frame_eval/pydevd_frame_eval_cython_wrapper.py new file mode 100644 index 0000000..0864a4e --- /dev/null +++ b/_pydevd_frame_eval/pydevd_frame_eval_cython_wrapper.py @@ -0,0 +1,43 @@ +try: + try: + from _pydevd_frame_eval_ext import pydevd_frame_evaluator as mod + except ImportError: + from _pydevd_frame_eval import pydevd_frame_evaluator as mod + +except ImportError: + try: + import sys + + try: + is_64bits = sys.maxsize > 2 ** 32 + except: + # In Jython this call fails, but this is Ok, we don't support Jython for speedups anyways. + raise ImportError + plat = '32' + if is_64bits: + plat = '64' + + # We also accept things as: + # + # _pydevd_frame_eval.pydevd_frame_evaluator_win32_27_32 + # _pydevd_frame_eval.pydevd_frame_evaluator_win32_34_64 + # + # to have multiple pre-compiled pyds distributed along the IDE + # (generated by build_tools/build_binaries_windows.py). + + mod_name = 'pydevd_frame_evaluator_%s_%s%s_%s' % (sys.platform, sys.version_info[0], sys.version_info[1], plat) + check_name = '_pydevd_frame_eval.%s' % (mod_name,) + mod = __import__(check_name) + mod = getattr(mod, mod_name) + except ImportError: + raise + +frame_eval_func = mod.frame_eval_func + +stop_frame_eval = mod.stop_frame_eval + +dummy_trace_dispatch = mod.dummy_trace_dispatch + +get_thread_info_py = mod.get_thread_info_py + +clear_thread_local_info = mod.clear_thread_local_info diff --git a/_pydevd_frame_eval/pydevd_frame_eval_main.py b/_pydevd_frame_eval/pydevd_frame_eval_main.py new file mode 100644 index 0000000..bfebea2 --- /dev/null +++ b/_pydevd_frame_eval/pydevd_frame_eval_main.py @@ -0,0 +1,48 @@ +import os + +from _pydev_bundle import pydev_log +from _pydevd_bundle.pydevd_trace_dispatch import USING_CYTHON +from _pydevd_bundle.pydevd_constants import USE_CYTHON_FLAG, ENV_FALSE_LOWER_VALUES, \ + ENV_TRUE_LOWER_VALUES, IS_PY36_OR_GREATER, IS_PY38_OR_GREATER, SUPPORT_GEVENT, IS_PYTHON_STACKLESS, \ + PYDEVD_USE_FRAME_EVAL, PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING + +frame_eval_func = None +stop_frame_eval = None +dummy_trace_dispatch = None +clear_thread_local_info = None + +# "NO" means we should not use frame evaluation, 'YES' we should use it (and fail if not there) and unspecified uses if possible. +if ( + PYDEVD_USE_FRAME_EVAL in ENV_FALSE_LOWER_VALUES or + USE_CYTHON_FLAG in ENV_FALSE_LOWER_VALUES or + not USING_CYTHON or + + # Frame eval mode does not work with ipython compatible debugging (this happens because the + # way that frame eval works is run untraced and set tracing only for the frames with + # breakpoints, but ipython compatible debugging creates separate frames for what's logically + # the same frame). + PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING + ): + USING_FRAME_EVAL = False + +elif SUPPORT_GEVENT or (IS_PYTHON_STACKLESS and not IS_PY38_OR_GREATER): + USING_FRAME_EVAL = False + # i.e gevent and frame eval mode don't get along very well. + # https://github.com/microsoft/debugpy/issues/189 + # Same problem with Stackless. + # https://github.com/stackless-dev/stackless/issues/240 + +elif PYDEVD_USE_FRAME_EVAL in ENV_TRUE_LOWER_VALUES: + # Fail if unable to use + from _pydevd_frame_eval.pydevd_frame_eval_cython_wrapper import frame_eval_func, stop_frame_eval, dummy_trace_dispatch, clear_thread_local_info + USING_FRAME_EVAL = True + +else: + USING_FRAME_EVAL = False + # Try to use if possible + if IS_PY36_OR_GREATER: + try: + from _pydevd_frame_eval.pydevd_frame_eval_cython_wrapper import frame_eval_func, stop_frame_eval, dummy_trace_dispatch, clear_thread_local_info + USING_FRAME_EVAL = True + except ImportError: + pydev_log.show_compile_cython_command_line() diff --git a/_pydevd_frame_eval/pydevd_frame_evaluator.c b/_pydevd_frame_eval/pydevd_frame_evaluator.c new file mode 100644 index 0000000..245e027 --- /dev/null +++ b/_pydevd_frame_eval/pydevd_frame_evaluator.c @@ -0,0 +1,20595 @@ +/* Generated by Cython 0.29.32 */ + +/* BEGIN: Cython Metadata +{ + "distutils": { + "depends": [ + "_pydevd_frame_eval/release_mem.h" + ], + "include_dirs": [ + "_pydevd_frame_eval" + ], + "name": "_pydevd_frame_eval.pydevd_frame_evaluator", + "sources": [ + "_pydevd_frame_eval/pydevd_frame_evaluator.pyx" + ] + }, + "module_name": "_pydevd_frame_eval.pydevd_frame_evaluator" +} +END: Cython Metadata */ + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ +#include "Python.h" +#if PY_VERSION_HEX >= 0x03090000 +#include "internal/pycore_gc.h" +#include "internal/pycore_interp.h" +#endif + +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. +#else +#define CYTHON_ABI "0_29_32" +#define CYTHON_HEX_VERSION 0x001D20F0 +#define CYTHON_FUTURE_DIVISION 0 +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_HEX >= 0x07030900) + #endif +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif +#elif defined(PY_NOGIL) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #ifndef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_NOGIL 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif + +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #elif defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif +#endif + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } +#else + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) + #endif +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact +#ifndef PyObject_Unicode + #define PyObject_Unicode PyObject_Str +#endif +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif +#else + #define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; +#endif + +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #if !defined(_USE_MATH_DEFINES) + #define _USE_MATH_DEFINES + #endif +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#define __PYX_MARK_ERR_POS(f_index, lineno) \ + { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE___pydevd_frame_eval__pydevd_frame_evaluator +#define __PYX_HAVE_API___pydevd_frame_eval__pydevd_frame_evaluator +/* Early includes */ +#include "frameobject.h" +#include "release_mem.h" +#include "code.h" +#include "pystate.h" +#if PY_VERSION_HEX >= 0x03080000 +#include "internal/pycore_pystate.h" +#endif + +#include "ceval.h" + +#if PY_VERSION_HEX >= 0x03090000 +PyObject * noop(PyFrameObject *frame, int exc) { + return NULL; +} +#define CALL_EvalFrameDefault_38(a, b) noop(a, b) +#define CALL_EvalFrameDefault_39(a, b, c) _PyEval_EvalFrameDefault(a, b, c) +#else +PyObject * noop(PyThreadState* tstate, PyFrameObject *frame, int exc) { + return NULL; +} +#define CALL_EvalFrameDefault_39(a, b, c) noop(a, b, c) +#define CALL_EvalFrameDefault_38(a, b) _PyEval_EvalFrameDefault(a, b) +#endif + +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); +#if CYTHON_ASSUME_SAFE_MACROS +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + + +static const char *__pyx_f[] = { + "_pydevd_frame_eval/pydevd_frame_evaluator.pyx", + "stringsource", + "_pydevd_bundle/pydevd_cython.pxd", +}; + +/*--- Type declarations ---*/ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo; +struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo; +struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo; +struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo; +struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue; + +/* "_pydevd_bundle/pydevd_cython.pxd":1 + * cdef class PyDBAdditionalThreadInfo: # <<<<<<<<<<<<<< + * cdef public int pydev_state + * cdef public object pydev_step_stop # Actually, it's a frame or None + */ +struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo { + PyObject_HEAD + int pydev_state; + PyObject *pydev_step_stop; + int pydev_original_step_cmd; + int pydev_step_cmd; + int pydev_notify_kill; + PyObject *pydev_smart_step_stop; + int pydev_django_resolve_frame; + PyObject *pydev_call_from_jinja2; + PyObject *pydev_call_inside_jinja2; + int is_tracing; + PyObject *conditional_breakpoint_exception; + PyObject *pydev_message; + int suspend_type; + int pydev_next_line; + PyObject *pydev_func_name; + int suspended_at_unhandled; + PyObject *trace_suspend_type; + PyObject *top_level_thread_tracer_no_back_frames; + PyObject *top_level_thread_tracer_unhandled; + PyObject *thread_tracer; + PyObject *step_in_initial_location; + int pydev_smart_parent_offset; + int pydev_smart_child_offset; + PyObject *pydev_smart_step_into_variants; + PyObject *target_id_to_smart_step_into_variant; + int pydev_use_scoped_step_frame; +}; + + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":24 + * + * + * cdef class ThreadInfo: # <<<<<<<<<<<<<< + * + * cdef public PyDBAdditionalThreadInfo additional_info + */ +struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo { + PyObject_HEAD + struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_vtab; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *additional_info; + int is_pydevd_thread; + int inside_frame_eval; + int fully_initialized; + PyObject *thread_trace_func; + int _can_create_dummy_thread; + int force_stay_in_untraced_mode; +}; + + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":125 + * + * + * cdef class FuncCodeInfo: # <<<<<<<<<<<<<< + * + * cdef public str co_filename + */ +struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo { + PyObject_HEAD + PyObject *co_filename; + PyObject *co_name; + PyObject *canonical_normalized_filename; + int always_skip_code; + int breakpoint_found; + PyObject *new_code; + int breakpoints_mtime; +}; + + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":316 + * + * + * cdef class _CodeLineInfo: # <<<<<<<<<<<<<< + * + * cdef public dict line_to_offset + */ +struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo { + PyObject_HEAD + PyObject *line_to_offset; + int first_line; + int last_line; +}; + + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":361 + * + * + * cdef class _CacheValue(object): # <<<<<<<<<<<<<< + * + * cdef public object code_obj_py + */ +struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue { + PyObject_HEAD + struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_vtab; + PyObject *code_obj_py; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *code_line_info; + PyObject *breakpoints_hit_at_lines; + PyObject *code_lines_as_set; +}; + + + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":24 + * + * + * cdef class ThreadInfo: # <<<<<<<<<<<<<< + * + * cdef public PyDBAdditionalThreadInfo additional_info + */ + +struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo { + PyObject *(*initialize)(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *, PyFrameObject *); + PyObject *(*initialize_if_possible)(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *); +}; +static struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_vtabptr_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo; + + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":361 + * + * + * cdef class _CacheValue(object): # <<<<<<<<<<<<<< + * + * cdef public object code_obj_py + */ + +struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue { + PyObject *(*compute_force_stay_in_untraced_mode)(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *, PyObject *, int __pyx_skip_dispatch); +}; +static struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_vtabptr_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue; + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* GetModuleGlobalName.proto */ +#if CYTHON_USE_DICT_VERSIONS +#define __Pyx_GetModuleGlobalName(var, name) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ + (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ + __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ + PY_UINT64_T __pyx_dict_version;\ + PyObject *__pyx_dict_cached_value;\ + (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); +#else +#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) +#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); +#endif + +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif +#if CYTHON_FAST_PYCALL + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL +#endif + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallNoArg.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); +#else +#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) +#endif + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyObjectCall2Args.proto */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); + +/* PyIntBinop.proto */ +#if !CYTHON_COMPILING_IN_PYPY +static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); +#else +#define __Pyx_PyInt_AddObjC(op1, op2, intval, inplace, zerodivision_check)\ + (inplace ? PyNumber_InPlaceAdd(op1, op2) : PyNumber_Add(op1, op2)) +#endif + +/* SliceObject.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice( + PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop, + PyObject** py_start, PyObject** py_stop, PyObject** py_slice, + int has_cstart, int has_cstop, int wraparound); + +/* IncludeStringH.proto */ +#include + +/* BytesEquals.proto */ +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); + +/* UnicodeEquals.proto */ +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); + +/* StrEquals.proto */ +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyString_Equals __Pyx_PyUnicode_Equals +#else +#define __Pyx_PyString_Equals __Pyx_PyBytes_Equals +#endif + +/* PyErrExceptionMatches.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) +static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); +#else +#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) +#endif + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* GetAttr.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *); + +/* GetAttr3.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); + +/* RaiseException.proto */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* GetTopmostException.proto */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); +#endif + +/* SaveResetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +#else +#define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) +#define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) +#endif + +/* GetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* PyObjectLookupSpecial.proto */ +#if CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name) { + PyObject *res; + PyTypeObject *tp = Py_TYPE(obj); +#if PY_MAJOR_VERSION < 3 + if (unlikely(PyInstance_Check(obj))) + return __Pyx_PyObject_GetAttrStr(obj, attr_name); +#endif + res = _PyType_Lookup(tp, attr_name); + if (likely(res)) { + descrgetfunc f = Py_TYPE(res)->tp_descr_get; + if (!f) { + Py_INCREF(res); + } else { + res = f(res, obj, (PyObject *)tp); + } + } else { + PyErr_SetObject(PyExc_AttributeError, attr_name); + } + return res; +} +#else +#define __Pyx_PyObject_LookupSpecial(o,n) __Pyx_PyObject_GetAttrStr(o,n) +#endif + +/* PyObjectSetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +#define __Pyx_PyObject_DelAttrStr(o,n) __Pyx_PyObject_SetAttrStr(o, n, NULL) +static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value); +#else +#define __Pyx_PyObject_DelAttrStr(o,n) PyObject_DelAttr(o,n) +#define __Pyx_PyObject_SetAttrStr(o,n,v) PyObject_SetAttr(o,n,v) +#endif + +/* None.proto */ +static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname); + +/* ExtTypeTest.proto */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); + +/* SwapException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSwap(type, value, tb) __Pyx__ExceptionSwap(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* KeywordStringCheck.proto */ +static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* ArgTypeTest.proto */ +#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\ + ((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 :\ + __Pyx__ArgTypeTest(obj, type, name, exact)) +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); + +/* DictGetItem.proto */ +#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY +static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key); +#define __Pyx_PyObject_Dict_GetItem(obj, name)\ + (likely(PyDict_CheckExact(obj)) ?\ + __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) +#else +#define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) +#define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) +#endif + +/* GetItemInt.proto */ +#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ + __Pyx_GetItemInt_Generic(o, to_py_func(i)))) +#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, + int is_list, int wraparound, int boundscheck); + +/* RaiseTooManyValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); + +/* RaiseNeedMoreValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +/* IterFinish.proto */ +static CYTHON_INLINE int __Pyx_IterFinish(void); + +/* UnpackItemEndCheck.proto */ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); + +/* PySequenceContains.proto */ +static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) { + int result = PySequence_Contains(seq, item); + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + +/* PyObjectGetMethod.proto */ +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); + +/* PyObjectCallMethod0.proto */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); + +/* RaiseNoneIterError.proto */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); + +/* UnpackTupleError.proto */ +static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); + +/* UnpackTuple2.proto */ +#define __Pyx_unpack_tuple2(tuple, value1, value2, is_tuple, has_known_size, decref_tuple)\ + (likely(is_tuple || PyTuple_Check(tuple)) ?\ + (likely(has_known_size || PyTuple_GET_SIZE(tuple) == 2) ?\ + __Pyx_unpack_tuple2_exact(tuple, value1, value2, decref_tuple) :\ + (__Pyx_UnpackTupleError(tuple, 2), -1)) :\ + __Pyx_unpack_tuple2_generic(tuple, value1, value2, has_known_size, decref_tuple)) +static CYTHON_INLINE int __Pyx_unpack_tuple2_exact( + PyObject* tuple, PyObject** value1, PyObject** value2, int decref_tuple); +static int __Pyx_unpack_tuple2_generic( + PyObject* tuple, PyObject** value1, PyObject** value2, int has_known_size, int decref_tuple); + +/* dict_iter.proto */ +static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* dict, int is_dict, PyObject* method_name, + Py_ssize_t* p_orig_length, int* p_is_dict); +static CYTHON_INLINE int __Pyx_dict_iter_next(PyObject* dict_or_iter, Py_ssize_t orig_length, Py_ssize_t* ppos, + PyObject** pkey, PyObject** pvalue, PyObject** pitem, int is_dict); + +/* PyDictContains.proto */ +static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict, int eq) { + int result = PyDict_Contains(dict, item); + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + +/* WriteUnraisableException.proto */ +static void __Pyx_WriteUnraisable(const char *name, int clineno, + int lineno, const char *filename, + int full_traceback, int nogil); + +/* Import.proto */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); + +/* ImportFrom.proto */ +static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); + +/* HasAttr.proto */ +static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); + +/* PyObject_GenericGetAttrNoDict.proto */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GenericGetAttrNoDict PyObject_GenericGetAttr +#endif + +/* PyObject_GenericGetAttr.proto */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GenericGetAttr PyObject_GenericGetAttr +#endif + +/* SetVTable.proto */ +static int __Pyx_SetVtable(PyObject *dict, void *vtable); + +/* PyObjectGetAttrStrNoError.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name); + +/* SetupReduce.proto */ +static int __Pyx_setup_reduce(PyObject* type_obj); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto +#define __PYX_HAVE_RT_ImportType_proto +enum __Pyx_ImportType_CheckSize { + __Pyx_ImportType_CheckSize_Error = 0, + __Pyx_ImportType_CheckSize_Warn = 1, + __Pyx_ImportType_CheckSize_Ignore = 2 +}; +static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); +#endif + +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_initialize(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyFrameObject *__pyx_v_frame_obj); /* proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_initialize_if_possible(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_compute_force_stay_in_untraced_mode(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_breakpoints, int __pyx_skip_dispatch); /* proto*/ + +/* Module declarations from 'cpython.mem' */ + +/* Module declarations from '_pydevd_bundle.pydevd_cython' */ +static PyTypeObject *__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo = 0; + +/* Module declarations from '_pydevd_frame_eval.pydevd_frame_evaluator' */ +static PyTypeObject *__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo = 0; +static PyTypeObject *__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo = 0; +static PyTypeObject *__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo = 0; +static PyTypeObject *__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue = 0; +static int __pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator__code_extra_index; +static int __pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator_IS_PY_39_OWNARDS; +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_thread_info(PyFrameObject *); /*proto*/ +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_func_code_info(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *, PyFrameObject *, PyCodeObject *); /*proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_generate_code_with_breakpoints(PyObject *, PyObject *); /*proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_bytecode_while_frame_eval_38(PyFrameObject *, int); /*proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_bytecode_while_frame_eval_39(PyThreadState *, PyFrameObject *, int); /*proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle_ThreadInfo__set_state(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *, PyObject *); /*proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle_FuncCodeInfo__set_state(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *, PyObject *); /*proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle__CodeLineInfo__set_state(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *, PyObject *); /*proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle__CacheValue__set_state(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *, PyObject *); /*proto*/ +#define __Pyx_MODULE_NAME "_pydevd_frame_eval.pydevd_frame_evaluator" +extern int __pyx_module_is_main__pydevd_frame_eval__pydevd_frame_evaluator; +int __pyx_module_is_main__pydevd_frame_eval__pydevd_frame_evaluator = 0; + +/* Implementation of '_pydevd_frame_eval.pydevd_frame_evaluator' */ +static PyObject *__pyx_builtin_AttributeError; +static PyObject *__pyx_builtin_min; +static PyObject *__pyx_builtin_max; +static const char __pyx_k_[] = "/"; +static const char __pyx_k__2[] = "\\"; +static const char __pyx_k__3[] = "."; +static const char __pyx_k__5[] = ""; +static const char __pyx_k_arg[] = "arg"; +static const char __pyx_k_dis[] = "dis"; +static const char __pyx_k_get[] = "get"; +static const char __pyx_k_max[] = "max"; +static const char __pyx_k_min[] = "min"; +static const char __pyx_k_new[] = "__new__"; +static const char __pyx_k_obj[] = "obj"; +static const char __pyx_k_run[] = "run"; +static const char __pyx_k_sys[] = "sys"; +static const char __pyx_k_call[] = "__call__"; +static const char __pyx_k_dict[] = "__dict__"; +static const char __pyx_k_exec[] = "_exec"; +static const char __pyx_k_exit[] = "__exit__"; +static const char __pyx_k_line[] = "line"; +static const char __pyx_k_main[] = "main"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_cache[] = "_cache"; +static const char __pyx_k_enter[] = "__enter__"; +static const char __pyx_k_event[] = "event"; +static const char __pyx_k_frame[] = "frame"; +static const char __pyx_k_local[] = "local"; +static const char __pyx_k_mtime[] = "mtime"; +static const char __pyx_k_rfind[] = "rfind"; +static const char __pyx_k_state[] = "state"; +static const char __pyx_k_active[] = "_active"; +static const char __pyx_k_call_2[] = "call"; +static const char __pyx_k_f_back[] = "f_back"; +static const char __pyx_k_import[] = "__import__"; +static const char __pyx_k_main_2[] = "__main__"; +static const char __pyx_k_offset[] = "offset"; +static const char __pyx_k_pickle[] = "pickle"; +static const char __pyx_k_plugin[] = "plugin"; +static const char __pyx_k_pydevd[] = "pydevd"; +static const char __pyx_k_reduce[] = "__reduce__"; +static const char __pyx_k_thread[] = "thread"; +static const char __pyx_k_update[] = "update"; +static const char __pyx_k_f_trace[] = "f_trace"; +static const char __pyx_k_SetTrace[] = "SetTrace"; +static const char __pyx_k_can_skip[] = "can_skip"; +static const char __pyx_k_code_obj[] = "code_obj"; +static const char __pyx_k_getstate[] = "__getstate__"; +static const char __pyx_k_pyx_type[] = "__pyx_type"; +static const char __pyx_k_setstate[] = "__setstate__"; +static const char __pyx_k_bootstrap[] = "__bootstrap"; +static const char __pyx_k_decref_py[] = "decref_py"; +static const char __pyx_k_get_ident[] = "_get_ident"; +static const char __pyx_k_last_line[] = "last_line"; +static const char __pyx_k_pyx_state[] = "__pyx_state"; +static const char __pyx_k_reduce_ex[] = "__reduce_ex__"; +static const char __pyx_k_threading[] = "threading"; +static const char __pyx_k_CacheValue[] = "_CacheValue"; +static const char __pyx_k_ThreadInfo[] = "ThreadInfo"; +static const char __pyx_k_first_line[] = "first_line"; +static const char __pyx_k_global_dbg[] = "global_dbg"; +static const char __pyx_k_issuperset[] = "issuperset"; +static const char __pyx_k_pyx_result[] = "__pyx_result"; +static const char __pyx_k_pyx_vtable[] = "__pyx_vtable__"; +static const char __pyx_k_DebugHelper[] = "DebugHelper"; +static const char __pyx_k_PickleError[] = "PickleError"; +static const char __pyx_k_bootstrap_2[] = "_bootstrap"; +static const char __pyx_k_breakpoints[] = "breakpoints"; +static const char __pyx_k_code_obj_py[] = "code_obj_py"; +static const char __pyx_k_get_ident_2[] = "get_ident"; +static const char __pyx_k_thread_info[] = "thread_info"; +static const char __pyx_k_CodeLineInfo[] = "_CodeLineInfo"; +static const char __pyx_k_FuncCodeInfo[] = "FuncCodeInfo"; +static const char __pyx_k_intersection[] = "intersection"; +static const char __pyx_k_pydev_monkey[] = "pydev_monkey"; +static const char __pyx_k_pyx_checksum[] = "__pyx_checksum"; +static const char __pyx_k_stringsource[] = "stringsource"; +static const char __pyx_k_version_info[] = "version_info"; +static const char __pyx_k_get_file_type[] = "get_file_type"; +static const char __pyx_k_reduce_cython[] = "__reduce_cython__"; +static const char __pyx_k_thread_active[] = "_thread_active"; +static const char __pyx_k_AttributeError[] = "AttributeError"; +static const char __pyx_k_code_line_info[] = "code_line_info"; +static const char __pyx_k_current_thread[] = "current_thread"; +static const char __pyx_k_findlinestarts[] = "findlinestarts"; +static const char __pyx_k_line_to_offset[] = "line_to_offset"; +static const char __pyx_k_pydevd_tracing[] = "pydevd_tracing"; +static const char __pyx_k_set_trace_func[] = "set_trace_func"; +static const char __pyx_k_trace_dispatch[] = "trace_dispatch"; +static const char __pyx_k_additional_info[] = "additional_info"; +static const char __pyx_k_bootstrap_inner[] = "__bootstrap_inner"; +static const char __pyx_k_frame_eval_func[] = "frame_eval_func"; +static const char __pyx_k_pyx_PickleError[] = "__pyx_PickleError"; +static const char __pyx_k_setstate_cython[] = "__setstate_cython__"; +static const char __pyx_k_stop_frame_eval[] = "stop_frame_eval"; +static const char __pyx_k_bootstrap_inner_2[] = "_bootstrap_inner"; +static const char __pyx_k_pydevd_file_utils[] = "pydevd_file_utils"; +static const char __pyx_k_signature_factory[] = "signature_factory"; +static const char __pyx_k_thread_local_info[] = "_thread_local_info"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_get_code_line_info[] = "_get_code_line_info"; +static const char __pyx_k_get_thread_info_py[] = "get_thread_info_py"; +static const char __pyx_k_show_return_values[] = "show_return_values"; +static const char __pyx_k_get_cache_file_type[] = "get_cache_file_type"; +static const char __pyx_k_update_globals_dict[] = "update_globals_dict"; +static const char __pyx_k_GlobalDebuggerHolder[] = "GlobalDebuggerHolder"; +static const char __pyx_k_dummy_trace_dispatch[] = "dummy_trace_dispatch"; +static const char __pyx_k_dummy_tracing_holder[] = "dummy_tracing_holder"; +static const char __pyx_k_insert_pydevd_breaks[] = "insert_pydevd_breaks"; +static const char __pyx_k_get_func_code_info_py[] = "get_func_code_info_py"; +static const char __pyx_k_has_plugin_line_breaks[] = "has_plugin_line_breaks"; +static const char __pyx_k_is_pydev_daemon_thread[] = "is_pydev_daemon_thread"; +static const char __pyx_k_clear_thread_local_info[] = "clear_thread_local_info"; +static const char __pyx_k_pyx_unpickle_ThreadInfo[] = "__pyx_unpickle_ThreadInfo"; +static const char __pyx_k_breakpoints_hit_at_lines[] = "breakpoints_hit_at_lines"; +static const char __pyx_k_pyx_unpickle__CacheValue[] = "__pyx_unpickle__CacheValue"; +static const char __pyx_k_pyx_unpickle_FuncCodeInfo[] = "__pyx_unpickle_FuncCodeInfo"; +static const char __pyx_k_break_on_caught_exceptions[] = "break_on_caught_exceptions"; +static const char __pyx_k_pyx_unpickle__CodeLineInfo[] = "__pyx_unpickle__CodeLineInfo"; +static const char __pyx_k_get_cached_code_obj_info_py[] = "get_cached_code_obj_info_py"; +static const char __pyx_k_has_plugin_exception_breaks[] = "has_plugin_exception_breaks"; +static const char __pyx_k_NORM_PATHS_AND_BASE_CONTAINER[] = "NORM_PATHS_AND_BASE_CONTAINER"; +static const char __pyx_k_pydevd_bundle_pydevd_constants[] = "_pydevd_bundle.pydevd_constants"; +static const char __pyx_k_pydevd_frame_eval_pydevd_frame[] = "_pydevd_frame_eval.pydevd_frame_tracing"; +static const char __pyx_k_If_a_code_object_is_cached_that[] = "If a code object is cached, that same code object must be reused."; +static const char __pyx_k_get_abs_path_real_path_and_base[] = "get_abs_path_real_path_and_base_from_frame"; +static const char __pyx_k_pydev_bundle__pydev_saved_modul[] = "_pydev_bundle._pydev_saved_modules"; +static const char __pyx_k_pydevd_bundle_pydevd_additional[] = "_pydevd_bundle.pydevd_additional_thread_info"; +static const char __pyx_k_pydevd_bundle_pydevd_trace_disp[] = "_pydevd_bundle.pydevd_trace_dispatch"; +static const char __pyx_k_pydevd_frame_eval_pydevd_modify[] = "_pydevd_frame_eval.pydevd_modify_bytecode"; +static const char __pyx_k_set_additional_thread_info_lock[] = "_set_additional_thread_info_lock"; +static const char __pyx_k_Incompatible_checksums_0x_x_vs_0[] = "Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))"; +static const char __pyx_k_break_on_user_uncaught_exception[] = "break_on_user_uncaught_exceptions"; +static const char __pyx_k_compute_force_stay_in_untraced_m[] = "compute_force_stay_in_untraced_mode"; +static const char __pyx_k_fix_top_level_trace_and_get_trac[] = "fix_top_level_trace_and_get_trace_func"; +static const char __pyx_k_function_breakpoint_name_to_brea[] = "function_breakpoint_name_to_breakpoint"; +static const char __pyx_k_generate_code_with_breakpoints_p[] = "generate_code_with_breakpoints_py"; +static const char __pyx_k_pydevd_frame_eval_pydevd_frame_2[] = "_pydevd_frame_eval/pydevd_frame_evaluator.pyx"; +static const char __pyx_k_pydevd_frame_eval_pydevd_frame_3[] = "_pydevd_frame_eval.pydevd_frame_evaluator"; +static const char __pyx_k_Incompatible_checksums_0x_x_vs_0_2[] = "Incompatible checksums (0x%x vs (0xb3ee05d, 0x450d2d6, 0x956dcaa) = (always_skip_code, breakpoint_found, breakpoints_mtime, canonical_normalized_filename, co_filename, co_name, new_code))"; +static const char __pyx_k_Incompatible_checksums_0x_x_vs_0_3[] = "Incompatible checksums (0x%x vs (0x3fbbd02, 0x5a9bcd5, 0x0267473) = (first_line, last_line, line_to_offset))"; +static const char __pyx_k_Incompatible_checksums_0x_x_vs_0_4[] = "Incompatible checksums (0x%x vs (0x3d481b9, 0xac42a46, 0xedff7c3) = (breakpoints_hit_at_lines, code_line_info, code_lines_as_set, code_obj_py))"; +static PyObject *__pyx_kp_s_; +static PyObject *__pyx_n_s_AttributeError; +static PyObject *__pyx_n_s_CacheValue; +static PyObject *__pyx_n_s_CodeLineInfo; +static PyObject *__pyx_n_s_DebugHelper; +static PyObject *__pyx_n_s_FuncCodeInfo; +static PyObject *__pyx_n_s_GlobalDebuggerHolder; +static PyObject *__pyx_kp_s_If_a_code_object_is_cached_that; +static PyObject *__pyx_kp_s_Incompatible_checksums_0x_x_vs_0; +static PyObject *__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_2; +static PyObject *__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_3; +static PyObject *__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_4; +static PyObject *__pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER; +static PyObject *__pyx_n_s_PickleError; +static PyObject *__pyx_n_s_SetTrace; +static PyObject *__pyx_n_s_ThreadInfo; +static PyObject *__pyx_kp_s__2; +static PyObject *__pyx_kp_s__3; +static PyObject *__pyx_kp_s__5; +static PyObject *__pyx_n_s_active; +static PyObject *__pyx_n_s_additional_info; +static PyObject *__pyx_n_s_arg; +static PyObject *__pyx_n_s_bootstrap; +static PyObject *__pyx_n_s_bootstrap_2; +static PyObject *__pyx_n_s_bootstrap_inner; +static PyObject *__pyx_n_s_bootstrap_inner_2; +static PyObject *__pyx_n_s_break_on_caught_exceptions; +static PyObject *__pyx_n_s_break_on_user_uncaught_exception; +static PyObject *__pyx_n_s_breakpoints; +static PyObject *__pyx_n_s_breakpoints_hit_at_lines; +static PyObject *__pyx_n_s_cache; +static PyObject *__pyx_n_s_call; +static PyObject *__pyx_n_s_call_2; +static PyObject *__pyx_n_s_can_skip; +static PyObject *__pyx_n_s_clear_thread_local_info; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_code_line_info; +static PyObject *__pyx_n_s_code_obj; +static PyObject *__pyx_n_s_code_obj_py; +static PyObject *__pyx_n_s_compute_force_stay_in_untraced_m; +static PyObject *__pyx_n_s_current_thread; +static PyObject *__pyx_n_s_decref_py; +static PyObject *__pyx_n_s_dict; +static PyObject *__pyx_n_s_dis; +static PyObject *__pyx_n_s_dummy_trace_dispatch; +static PyObject *__pyx_n_s_dummy_tracing_holder; +static PyObject *__pyx_n_s_enter; +static PyObject *__pyx_n_s_event; +static PyObject *__pyx_n_s_exec; +static PyObject *__pyx_n_s_exit; +static PyObject *__pyx_n_s_f_back; +static PyObject *__pyx_n_s_f_trace; +static PyObject *__pyx_n_s_findlinestarts; +static PyObject *__pyx_n_s_first_line; +static PyObject *__pyx_n_s_fix_top_level_trace_and_get_trac; +static PyObject *__pyx_n_s_frame; +static PyObject *__pyx_n_s_frame_eval_func; +static PyObject *__pyx_n_s_function_breakpoint_name_to_brea; +static PyObject *__pyx_n_s_generate_code_with_breakpoints_p; +static PyObject *__pyx_n_s_get; +static PyObject *__pyx_n_s_get_abs_path_real_path_and_base; +static PyObject *__pyx_n_s_get_cache_file_type; +static PyObject *__pyx_n_s_get_cached_code_obj_info_py; +static PyObject *__pyx_n_s_get_code_line_info; +static PyObject *__pyx_n_s_get_file_type; +static PyObject *__pyx_n_s_get_func_code_info_py; +static PyObject *__pyx_n_s_get_ident; +static PyObject *__pyx_n_s_get_ident_2; +static PyObject *__pyx_n_s_get_thread_info_py; +static PyObject *__pyx_n_s_getstate; +static PyObject *__pyx_n_s_global_dbg; +static PyObject *__pyx_n_s_has_plugin_exception_breaks; +static PyObject *__pyx_n_s_has_plugin_line_breaks; +static PyObject *__pyx_n_s_import; +static PyObject *__pyx_n_s_insert_pydevd_breaks; +static PyObject *__pyx_n_s_intersection; +static PyObject *__pyx_n_s_is_pydev_daemon_thread; +static PyObject *__pyx_n_s_issuperset; +static PyObject *__pyx_n_s_last_line; +static PyObject *__pyx_n_s_line; +static PyObject *__pyx_n_s_line_to_offset; +static PyObject *__pyx_n_s_local; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_main_2; +static PyObject *__pyx_n_s_max; +static PyObject *__pyx_n_s_min; +static PyObject *__pyx_n_s_mtime; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_n_s_new; +static PyObject *__pyx_n_s_obj; +static PyObject *__pyx_n_s_offset; +static PyObject *__pyx_n_s_pickle; +static PyObject *__pyx_n_s_plugin; +static PyObject *__pyx_n_s_pydev_bundle__pydev_saved_modul; +static PyObject *__pyx_n_s_pydev_monkey; +static PyObject *__pyx_n_s_pydevd; +static PyObject *__pyx_n_s_pydevd_bundle_pydevd_additional; +static PyObject *__pyx_n_s_pydevd_bundle_pydevd_constants; +static PyObject *__pyx_n_s_pydevd_bundle_pydevd_trace_disp; +static PyObject *__pyx_n_s_pydevd_file_utils; +static PyObject *__pyx_n_s_pydevd_frame_eval_pydevd_frame; +static PyObject *__pyx_kp_s_pydevd_frame_eval_pydevd_frame_2; +static PyObject *__pyx_n_s_pydevd_frame_eval_pydevd_frame_3; +static PyObject *__pyx_n_s_pydevd_frame_eval_pydevd_modify; +static PyObject *__pyx_n_s_pydevd_tracing; +static PyObject *__pyx_n_s_pyx_PickleError; +static PyObject *__pyx_n_s_pyx_checksum; +static PyObject *__pyx_n_s_pyx_result; +static PyObject *__pyx_n_s_pyx_state; +static PyObject *__pyx_n_s_pyx_type; +static PyObject *__pyx_n_s_pyx_unpickle_FuncCodeInfo; +static PyObject *__pyx_n_s_pyx_unpickle_ThreadInfo; +static PyObject *__pyx_n_s_pyx_unpickle__CacheValue; +static PyObject *__pyx_n_s_pyx_unpickle__CodeLineInfo; +static PyObject *__pyx_n_s_pyx_vtable; +static PyObject *__pyx_n_s_reduce; +static PyObject *__pyx_n_s_reduce_cython; +static PyObject *__pyx_n_s_reduce_ex; +static PyObject *__pyx_n_s_rfind; +static PyObject *__pyx_n_s_run; +static PyObject *__pyx_n_s_set_additional_thread_info_lock; +static PyObject *__pyx_n_s_set_trace_func; +static PyObject *__pyx_n_s_setstate; +static PyObject *__pyx_n_s_setstate_cython; +static PyObject *__pyx_n_s_show_return_values; +static PyObject *__pyx_n_s_signature_factory; +static PyObject *__pyx_n_s_state; +static PyObject *__pyx_n_s_stop_frame_eval; +static PyObject *__pyx_kp_s_stringsource; +static PyObject *__pyx_n_s_sys; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_n_s_thread; +static PyObject *__pyx_n_s_thread_active; +static PyObject *__pyx_n_s_thread_info; +static PyObject *__pyx_n_s_thread_local_info; +static PyObject *__pyx_n_s_threading; +static PyObject *__pyx_n_s_trace_dispatch; +static PyObject *__pyx_n_s_update; +static PyObject *__pyx_n_s_update_globals_dict; +static PyObject *__pyx_n_s_version_info; +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_clear_thread_local_info(CYTHON_UNUSED PyObject *__pyx_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo___reduce_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_2__setstate_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo___init__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_2__reduce_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_4__setstate_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_2dummy_trace_dispatch(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg); /* proto */ +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_4get_thread_info_py(CYTHON_UNUSED PyObject *__pyx_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_6decref_py(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_obj); /* proto */ +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_8get_func_code_info_py(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_thread_info, PyObject *__pyx_v_frame, PyObject *__pyx_v_code_obj); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo___init__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v_line_to_offset, int __pyx_v_first_line, int __pyx_v_last_line); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_2__reduce_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_4__setstate_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10_get_code_line_info(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_code_obj); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12get_cached_code_obj_info_py(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_code_obj_py); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_code_obj_py, struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_code_line_info, PyObject *__pyx_v_breakpoints_hit_at_lines); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_2compute_force_stay_in_untraced_mode(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_breakpoints); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_4__reduce_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_6__setstate_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_14generate_code_with_breakpoints_py(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_code_obj_py, PyObject *__pyx_v_breakpoints); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_16frame_eval_func(CYTHON_UNUSED PyObject *__pyx_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_18stop_frame_eval(CYTHON_UNUSED PyObject *__pyx_self); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_20__pyx_unpickle_ThreadInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_22__pyx_unpickle_FuncCodeInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_24__pyx_unpickle__CodeLineInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_26__pyx_unpickle__CacheValue(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_int_0; +static PyObject *__pyx_int_1; +static PyObject *__pyx_int_2; +static PyObject *__pyx_int_3; +static PyObject *__pyx_int_9; +static PyObject *__pyx_int_2520179; +static PyObject *__pyx_int_11485321; +static PyObject *__pyx_int_64258489; +static PyObject *__pyx_int_66829570; +static PyObject *__pyx_int_72405718; +static PyObject *__pyx_int_95010005; +static PyObject *__pyx_int_156687530; +static PyObject *__pyx_int_180628038; +static PyObject *__pyx_int_188670045; +static PyObject *__pyx_int_193022138; +static PyObject *__pyx_int_240343912; +static PyObject *__pyx_int_249558979; +static PyObject *__pyx_tuple__4; +static PyObject *__pyx_tuple__6; +static PyObject *__pyx_tuple__7; +static PyObject *__pyx_tuple__8; +static PyObject *__pyx_tuple__9; +static PyObject *__pyx_slice__24; +static PyObject *__pyx_tuple__11; +static PyObject *__pyx_tuple__14; +static PyObject *__pyx_tuple__16; +static PyObject *__pyx_tuple__18; +static PyObject *__pyx_tuple__20; +static PyObject *__pyx_tuple__22; +static PyObject *__pyx_tuple__25; +static PyObject *__pyx_tuple__26; +static PyObject *__pyx_tuple__28; +static PyObject *__pyx_tuple__30; +static PyObject *__pyx_tuple__32; +static PyObject *__pyx_tuple__34; +static PyObject *__pyx_tuple__36; +static PyObject *__pyx_codeobj__10; +static PyObject *__pyx_codeobj__12; +static PyObject *__pyx_codeobj__13; +static PyObject *__pyx_codeobj__15; +static PyObject *__pyx_codeobj__17; +static PyObject *__pyx_codeobj__19; +static PyObject *__pyx_codeobj__21; +static PyObject *__pyx_codeobj__23; +static PyObject *__pyx_codeobj__27; +static PyObject *__pyx_codeobj__29; +static PyObject *__pyx_codeobj__31; +static PyObject *__pyx_codeobj__33; +static PyObject *__pyx_codeobj__35; +static PyObject *__pyx_codeobj__37; +/* Late includes */ + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":19 + * _thread_active = threading._active + * + * def clear_thread_local_info(): # <<<<<<<<<<<<<< + * global _thread_local_info + * _thread_local_info = threading.local() + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_1clear_thread_local_info(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_1clear_thread_local_info = {"clear_thread_local_info", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_1clear_thread_local_info, METH_NOARGS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_1clear_thread_local_info(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("clear_thread_local_info (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_clear_thread_local_info(__pyx_self); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_clear_thread_local_info(CYTHON_UNUSED PyObject *__pyx_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("clear_thread_local_info", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":21 + * def clear_thread_local_info(): + * global _thread_local_info + * _thread_local_info = threading.local() # <<<<<<<<<<<<<< + * + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_threading); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 21, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_local); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 21, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (PyDict_SetItem(__pyx_d, __pyx_n_s_thread_local_info, __pyx_t_1) < 0) __PYX_ERR(0, 21, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":19 + * _thread_active = threading._active + * + * def clear_thread_local_info(): # <<<<<<<<<<<<<< + * global _thread_local_info + * _thread_local_info = threading.local() + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.clear_thread_local_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":39 + * cdef public bint force_stay_in_untraced_mode + * + * cdef initialize(self, PyFrameObject * frame_obj): # <<<<<<<<<<<<<< + * # Places that create a ThreadInfo should verify that + * # a current Python frame is being executed! + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_initialize(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyFrameObject *__pyx_v_frame_obj) { + PyObject *__pyx_v_basename = NULL; + PyObject *__pyx_v_i = NULL; + PyObject *__pyx_v_j = NULL; + PyObject *__pyx_v_co_name = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyFrameObject *__pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + int __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("initialize", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":42 + * # Places that create a ThreadInfo should verify that + * # a current Python frame is being executed! + * assert frame_obj != NULL # <<<<<<<<<<<<<< + * + * self.additional_info = None + */ + #ifndef CYTHON_WITHOUT_ASSERTIONS + if (unlikely(!Py_OptimizeFlag)) { + if (unlikely(!((__pyx_v_frame_obj != NULL) != 0))) { + PyErr_SetNone(PyExc_AssertionError); + __PYX_ERR(0, 42, __pyx_L1_error) + } + } + #endif + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":44 + * assert frame_obj != NULL + * + * self.additional_info = None # <<<<<<<<<<<<<< + * self.is_pydevd_thread = False + * self.inside_frame_eval = 0 + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->additional_info); + __Pyx_DECREF(((PyObject *)__pyx_v_self->additional_info)); + __pyx_v_self->additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)Py_None); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":45 + * + * self.additional_info = None + * self.is_pydevd_thread = False # <<<<<<<<<<<<<< + * self.inside_frame_eval = 0 + * self.fully_initialized = False + */ + __pyx_v_self->is_pydevd_thread = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":46 + * self.additional_info = None + * self.is_pydevd_thread = False + * self.inside_frame_eval = 0 # <<<<<<<<<<<<<< + * self.fully_initialized = False + * self.thread_trace_func = None + */ + __pyx_v_self->inside_frame_eval = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":47 + * self.is_pydevd_thread = False + * self.inside_frame_eval = 0 + * self.fully_initialized = False # <<<<<<<<<<<<<< + * self.thread_trace_func = None + * + */ + __pyx_v_self->fully_initialized = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":48 + * self.inside_frame_eval = 0 + * self.fully_initialized = False + * self.thread_trace_func = None # <<<<<<<<<<<<<< + * + * # Get the root (if it's not a Thread initialized from the threading + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->thread_trace_func); + __Pyx_DECREF(__pyx_v_self->thread_trace_func); + __pyx_v_self->thread_trace_func = Py_None; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":54 + * # otherwise, we have to wait for the threading module itself to + * # create the Thread entry). + * while frame_obj.f_back != NULL: # <<<<<<<<<<<<<< + * frame_obj = frame_obj.f_back + * + */ + while (1) { + __pyx_t_1 = ((__pyx_v_frame_obj->f_back != NULL) != 0); + if (!__pyx_t_1) break; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":55 + * # create the Thread entry). + * while frame_obj.f_back != NULL: + * frame_obj = frame_obj.f_back # <<<<<<<<<<<<<< + * + * basename = frame_obj.f_code.co_filename + */ + __pyx_t_2 = __pyx_v_frame_obj->f_back; + __pyx_v_frame_obj = __pyx_t_2; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":57 + * frame_obj = frame_obj.f_back + * + * basename = frame_obj.f_code.co_filename # <<<<<<<<<<<<<< + * i = basename.rfind('/') + * j = basename.rfind('\\') + */ + __pyx_t_3 = ((PyObject *)__pyx_v_frame_obj->f_code->co_filename); + __Pyx_INCREF(__pyx_t_3); + __pyx_v_basename = __pyx_t_3; + __pyx_t_3 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":58 + * + * basename = frame_obj.f_code.co_filename + * i = basename.rfind('/') # <<<<<<<<<<<<<< + * j = basename.rfind('\\') + * if j > i: + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_basename, __pyx_n_s_rfind); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 58, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_s_) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_s_); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 58, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_i = __pyx_t_3; + __pyx_t_3 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":59 + * basename = frame_obj.f_code.co_filename + * i = basename.rfind('/') + * j = basename.rfind('\\') # <<<<<<<<<<<<<< + * if j > i: + * i = j + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_basename, __pyx_n_s_rfind); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 59, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_s__2) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_s__2); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 59, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_j = __pyx_t_3; + __pyx_t_3 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":60 + * i = basename.rfind('/') + * j = basename.rfind('\\') + * if j > i: # <<<<<<<<<<<<<< + * i = j + * if i >= 0: + */ + __pyx_t_3 = PyObject_RichCompare(__pyx_v_j, __pyx_v_i, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 60, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 60, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":61 + * j = basename.rfind('\\') + * if j > i: + * i = j # <<<<<<<<<<<<<< + * if i >= 0: + * basename = basename[i + 1:] + */ + __Pyx_INCREF(__pyx_v_j); + __Pyx_DECREF_SET(__pyx_v_i, __pyx_v_j); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":60 + * i = basename.rfind('/') + * j = basename.rfind('\\') + * if j > i: # <<<<<<<<<<<<<< + * i = j + * if i >= 0: + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":62 + * if j > i: + * i = j + * if i >= 0: # <<<<<<<<<<<<<< + * basename = basename[i + 1:] + * # remove ext + */ + __pyx_t_3 = PyObject_RichCompare(__pyx_v_i, __pyx_int_0, Py_GE); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 62, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":63 + * i = j + * if i >= 0: + * basename = basename[i + 1:] # <<<<<<<<<<<<<< + * # remove ext + * i = basename.rfind('.') + */ + __pyx_t_3 = __Pyx_PyInt_AddObjC(__pyx_v_i, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 63, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyObject_GetSlice(__pyx_v_basename, 0, 0, &__pyx_t_3, NULL, NULL, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 63, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF_SET(__pyx_v_basename, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":62 + * if j > i: + * i = j + * if i >= 0: # <<<<<<<<<<<<<< + * basename = basename[i + 1:] + * # remove ext + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":65 + * basename = basename[i + 1:] + * # remove ext + * i = basename.rfind('.') # <<<<<<<<<<<<<< + * if i >= 0: + * basename = basename[:i] + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_basename, __pyx_n_s_rfind); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 65, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_kp_s__3) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_s__3); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 65, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF_SET(__pyx_v_i, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":66 + * # remove ext + * i = basename.rfind('.') + * if i >= 0: # <<<<<<<<<<<<<< + * basename = basename[:i] + * + */ + __pyx_t_4 = PyObject_RichCompare(__pyx_v_i, __pyx_int_0, Py_GE); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 66, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 66, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":67 + * i = basename.rfind('.') + * if i >= 0: + * basename = basename[:i] # <<<<<<<<<<<<<< + * + * co_name = frame_obj.f_code.co_name + */ + __pyx_t_4 = __Pyx_PyObject_GetSlice(__pyx_v_basename, 0, 0, NULL, &__pyx_v_i, NULL, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 67, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_basename, __pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":66 + * # remove ext + * i = basename.rfind('.') + * if i >= 0: # <<<<<<<<<<<<<< + * basename = basename[:i] + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":69 + * basename = basename[:i] + * + * co_name = frame_obj.f_code.co_name # <<<<<<<<<<<<<< + * + * # In these cases we cannot create a dummy thread (an actual + */ + __pyx_t_4 = ((PyObject *)__pyx_v_frame_obj->f_code->co_name); + __Pyx_INCREF(__pyx_t_4); + __pyx_v_co_name = __pyx_t_4; + __pyx_t_4 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":73 + * # In these cases we cannot create a dummy thread (an actual + * # thread will be created later or tracing will already be set). + * if basename == 'threading' and co_name in ('__bootstrap', '_bootstrap', '__bootstrap_inner', '_bootstrap_inner'): # <<<<<<<<<<<<<< + * self._can_create_dummy_thread = False + * elif basename == 'pydev_monkey' and co_name == '__call__': + */ + __pyx_t_6 = (__Pyx_PyString_Equals(__pyx_v_basename, __pyx_n_s_threading, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 73, __pyx_L1_error) + if (__pyx_t_6) { + } else { + __pyx_t_1 = __pyx_t_6; + goto __pyx_L9_bool_binop_done; + } + __Pyx_INCREF(__pyx_v_co_name); + __pyx_t_4 = __pyx_v_co_name; + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_bootstrap, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 73, __pyx_L1_error) + if (!__pyx_t_7) { + } else { + __pyx_t_6 = __pyx_t_7; + goto __pyx_L11_bool_binop_done; + } + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_bootstrap_2, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 73, __pyx_L1_error) + if (!__pyx_t_7) { + } else { + __pyx_t_6 = __pyx_t_7; + goto __pyx_L11_bool_binop_done; + } + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_bootstrap_inner, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 73, __pyx_L1_error) + if (!__pyx_t_7) { + } else { + __pyx_t_6 = __pyx_t_7; + goto __pyx_L11_bool_binop_done; + } + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_bootstrap_inner_2, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 73, __pyx_L1_error) + __pyx_t_6 = __pyx_t_7; + __pyx_L11_bool_binop_done:; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_7 = (__pyx_t_6 != 0); + __pyx_t_1 = __pyx_t_7; + __pyx_L9_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":74 + * # thread will be created later or tracing will already be set). + * if basename == 'threading' and co_name in ('__bootstrap', '_bootstrap', '__bootstrap_inner', '_bootstrap_inner'): + * self._can_create_dummy_thread = False # <<<<<<<<<<<<<< + * elif basename == 'pydev_monkey' and co_name == '__call__': + * self._can_create_dummy_thread = False + */ + __pyx_v_self->_can_create_dummy_thread = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":73 + * # In these cases we cannot create a dummy thread (an actual + * # thread will be created later or tracing will already be set). + * if basename == 'threading' and co_name in ('__bootstrap', '_bootstrap', '__bootstrap_inner', '_bootstrap_inner'): # <<<<<<<<<<<<<< + * self._can_create_dummy_thread = False + * elif basename == 'pydev_monkey' and co_name == '__call__': + */ + goto __pyx_L8; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":75 + * if basename == 'threading' and co_name in ('__bootstrap', '_bootstrap', '__bootstrap_inner', '_bootstrap_inner'): + * self._can_create_dummy_thread = False + * elif basename == 'pydev_monkey' and co_name == '__call__': # <<<<<<<<<<<<<< + * self._can_create_dummy_thread = False + * elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): + */ + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_basename, __pyx_n_s_pydev_monkey, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 75, __pyx_L1_error) + if (__pyx_t_7) { + } else { + __pyx_t_1 = __pyx_t_7; + goto __pyx_L15_bool_binop_done; + } + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_co_name, __pyx_n_s_call, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 75, __pyx_L1_error) + __pyx_t_1 = __pyx_t_7; + __pyx_L15_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":76 + * self._can_create_dummy_thread = False + * elif basename == 'pydev_monkey' and co_name == '__call__': + * self._can_create_dummy_thread = False # <<<<<<<<<<<<<< + * elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): + * self._can_create_dummy_thread = False + */ + __pyx_v_self->_can_create_dummy_thread = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":75 + * if basename == 'threading' and co_name in ('__bootstrap', '_bootstrap', '__bootstrap_inner', '_bootstrap_inner'): + * self._can_create_dummy_thread = False + * elif basename == 'pydev_monkey' and co_name == '__call__': # <<<<<<<<<<<<<< + * self._can_create_dummy_thread = False + * elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): + */ + goto __pyx_L8; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":77 + * elif basename == 'pydev_monkey' and co_name == '__call__': + * self._can_create_dummy_thread = False + * elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): # <<<<<<<<<<<<<< + * self._can_create_dummy_thread = False + * elif basename == 'pydevd_tracing': + */ + __pyx_t_7 = (__Pyx_PyString_Equals(__pyx_v_basename, __pyx_n_s_pydevd, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 77, __pyx_L1_error) + if (__pyx_t_7) { + } else { + __pyx_t_1 = __pyx_t_7; + goto __pyx_L17_bool_binop_done; + } + __Pyx_INCREF(__pyx_v_co_name); + __pyx_t_4 = __pyx_v_co_name; + __pyx_t_6 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_run, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 77, __pyx_L1_error) + if (!__pyx_t_6) { + } else { + __pyx_t_7 = __pyx_t_6; + goto __pyx_L19_bool_binop_done; + } + __pyx_t_6 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_main, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 77, __pyx_L1_error) + if (!__pyx_t_6) { + } else { + __pyx_t_7 = __pyx_t_6; + goto __pyx_L19_bool_binop_done; + } + __pyx_t_6 = (__Pyx_PyString_Equals(__pyx_t_4, __pyx_n_s_exec, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 77, __pyx_L1_error) + __pyx_t_7 = __pyx_t_6; + __pyx_L19_bool_binop_done:; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = (__pyx_t_7 != 0); + __pyx_t_1 = __pyx_t_6; + __pyx_L17_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":78 + * self._can_create_dummy_thread = False + * elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): + * self._can_create_dummy_thread = False # <<<<<<<<<<<<<< + * elif basename == 'pydevd_tracing': + * self._can_create_dummy_thread = False + */ + __pyx_v_self->_can_create_dummy_thread = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":77 + * elif basename == 'pydev_monkey' and co_name == '__call__': + * self._can_create_dummy_thread = False + * elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): # <<<<<<<<<<<<<< + * self._can_create_dummy_thread = False + * elif basename == 'pydevd_tracing': + */ + goto __pyx_L8; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":79 + * elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): + * self._can_create_dummy_thread = False + * elif basename == 'pydevd_tracing': # <<<<<<<<<<<<<< + * self._can_create_dummy_thread = False + * else: + */ + __pyx_t_1 = (__Pyx_PyString_Equals(__pyx_v_basename, __pyx_n_s_pydevd_tracing, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 79, __pyx_L1_error) + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":80 + * self._can_create_dummy_thread = False + * elif basename == 'pydevd_tracing': + * self._can_create_dummy_thread = False # <<<<<<<<<<<<<< + * else: + * self._can_create_dummy_thread = True + */ + __pyx_v_self->_can_create_dummy_thread = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":79 + * elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): + * self._can_create_dummy_thread = False + * elif basename == 'pydevd_tracing': # <<<<<<<<<<<<<< + * self._can_create_dummy_thread = False + * else: + */ + goto __pyx_L8; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":82 + * self._can_create_dummy_thread = False + * else: + * self._can_create_dummy_thread = True # <<<<<<<<<<<<<< + * + * # print('Can create dummy thread for thread started in: %s %s' % (basename, co_name)) + */ + /*else*/ { + __pyx_v_self->_can_create_dummy_thread = 1; + } + __pyx_L8:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":39 + * cdef public bint force_stay_in_untraced_mode + * + * cdef initialize(self, PyFrameObject * frame_obj): # <<<<<<<<<<<<<< + * # Places that create a ThreadInfo should verify that + * # a current Python frame is being executed! + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.initialize", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_basename); + __Pyx_XDECREF(__pyx_v_i); + __Pyx_XDECREF(__pyx_v_j); + __Pyx_XDECREF(__pyx_v_co_name); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":86 + * # print('Can create dummy thread for thread started in: %s %s' % (basename, co_name)) + * + * cdef initialize_if_possible(self): # <<<<<<<<<<<<<< + * # Don't call threading.currentThread because if we're too early in the process + * # we may create a dummy thread. + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_initialize_if_possible(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + PyObject *__pyx_v_thread_ident = NULL; + PyObject *__pyx_v_t = NULL; + PyObject *__pyx_v_additional_info = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + int __pyx_t_18; + int __pyx_t_19; + char const *__pyx_t_20; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("initialize_if_possible", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":89 + * # Don't call threading.currentThread because if we're too early in the process + * # we may create a dummy thread. + * self.inside_frame_eval += 1 # <<<<<<<<<<<<<< + * + * try: + */ + __pyx_v_self->inside_frame_eval = (__pyx_v_self->inside_frame_eval + 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":91 + * self.inside_frame_eval += 1 + * + * try: # <<<<<<<<<<<<<< + * thread_ident = _get_ident() + * t = _thread_active.get(thread_ident) + */ + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":92 + * + * try: + * thread_ident = _get_ident() # <<<<<<<<<<<<<< + * t = _thread_active.get(thread_ident) + * if t is None: + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_get_ident); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 92, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + } + } + __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 92, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_thread_ident = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":93 + * try: + * thread_ident = _get_ident() + * t = _thread_active.get(thread_ident) # <<<<<<<<<<<<<< + * if t is None: + * if self._can_create_dummy_thread: + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_thread_active); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 93, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_get); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 93, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_v_thread_ident) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_thread_ident); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 93, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_t = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":94 + * thread_ident = _get_ident() + * t = _thread_active.get(thread_ident) + * if t is None: # <<<<<<<<<<<<<< + * if self._can_create_dummy_thread: + * # Initialize the dummy thread and set the tracing (both are needed to + */ + __pyx_t_4 = (__pyx_v_t == Py_None); + __pyx_t_5 = (__pyx_t_4 != 0); + if (__pyx_t_5) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":95 + * t = _thread_active.get(thread_ident) + * if t is None: + * if self._can_create_dummy_thread: # <<<<<<<<<<<<<< + * # Initialize the dummy thread and set the tracing (both are needed to + * # actually stop on breakpoints). + */ + __pyx_t_5 = (__pyx_v_self->_can_create_dummy_thread != 0); + if (__pyx_t_5) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":98 + * # Initialize the dummy thread and set the tracing (both are needed to + * # actually stop on breakpoints). + * t = threading.current_thread() # <<<<<<<<<<<<<< + * SetTrace(dummy_trace_dispatch) + * else: + */ + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_threading); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 98, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_current_thread); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 98, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + } + } + __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 98, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF_SET(__pyx_v_t, __pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":99 + * # actually stop on breakpoints). + * t = threading.current_thread() + * SetTrace(dummy_trace_dispatch) # <<<<<<<<<<<<<< + * else: + * return # Cannot initialize until thread becomes active. + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_SetTrace); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 99, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_dummy_trace_dispatch); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 99, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + } + } + __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_6, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 99, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":95 + * t = _thread_active.get(thread_ident) + * if t is None: + * if self._can_create_dummy_thread: # <<<<<<<<<<<<<< + * # Initialize the dummy thread and set the tracing (both are needed to + * # actually stop on breakpoints). + */ + goto __pyx_L7; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":101 + * SetTrace(dummy_trace_dispatch) + * else: + * return # Cannot initialize until thread becomes active. # <<<<<<<<<<<<<< + * + * if getattr(t, 'is_pydev_daemon_thread', False): + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L3_return; + } + __pyx_L7:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":94 + * thread_ident = _get_ident() + * t = _thread_active.get(thread_ident) + * if t is None: # <<<<<<<<<<<<<< + * if self._can_create_dummy_thread: + * # Initialize the dummy thread and set the tracing (both are needed to + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":103 + * return # Cannot initialize until thread becomes active. + * + * if getattr(t, 'is_pydev_daemon_thread', False): # <<<<<<<<<<<<<< + * self.is_pydevd_thread = True + * self.fully_initialized = True + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_t, __pyx_n_s_is_pydev_daemon_thread, Py_False); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 103, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 103, __pyx_L4_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_5) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":104 + * + * if getattr(t, 'is_pydev_daemon_thread', False): + * self.is_pydevd_thread = True # <<<<<<<<<<<<<< + * self.fully_initialized = True + * else: + */ + __pyx_v_self->is_pydevd_thread = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":105 + * if getattr(t, 'is_pydev_daemon_thread', False): + * self.is_pydevd_thread = True + * self.fully_initialized = True # <<<<<<<<<<<<<< + * else: + * try: + */ + __pyx_v_self->fully_initialized = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":103 + * return # Cannot initialize until thread becomes active. + * + * if getattr(t, 'is_pydev_daemon_thread', False): # <<<<<<<<<<<<<< + * self.is_pydevd_thread = True + * self.fully_initialized = True + */ + goto __pyx_L8; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":107 + * self.fully_initialized = True + * else: + * try: # <<<<<<<<<<<<<< + * additional_info = t.additional_info + * if additional_info is None: + */ + /*else*/ { + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9); + __Pyx_XGOTREF(__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_9); + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":108 + * else: + * try: + * additional_info = t.additional_info # <<<<<<<<<<<<<< + * if additional_info is None: + * raise AttributeError() + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_t, __pyx_n_s_additional_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 108, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_additional_info = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":109 + * try: + * additional_info = t.additional_info + * if additional_info is None: # <<<<<<<<<<<<<< + * raise AttributeError() + * except: + */ + __pyx_t_5 = (__pyx_v_additional_info == Py_None); + __pyx_t_4 = (__pyx_t_5 != 0); + if (unlikely(__pyx_t_4)) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":110 + * additional_info = t.additional_info + * if additional_info is None: + * raise AttributeError() # <<<<<<<<<<<<<< + * except: + * with _set_additional_thread_info_lock: + */ + __pyx_t_1 = __Pyx_PyObject_CallNoArg(__pyx_builtin_AttributeError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 110, __pyx_L9_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(0, 110, __pyx_L9_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":109 + * try: + * additional_info = t.additional_info + * if additional_info is None: # <<<<<<<<<<<<<< + * raise AttributeError() + * except: + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":107 + * self.fully_initialized = True + * else: + * try: # <<<<<<<<<<<<<< + * additional_info = t.additional_info + * if additional_info is None: + */ + } + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L14_try_end; + __pyx_L9_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":111 + * if additional_info is None: + * raise AttributeError() + * except: # <<<<<<<<<<<<<< + * with _set_additional_thread_info_lock: + * # If it's not there, set it within a lock to avoid any racing + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.initialize_if_possible", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3) < 0) __PYX_ERR(0, 111, __pyx_L11_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GOTREF(__pyx_t_3); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":112 + * raise AttributeError() + * except: + * with _set_additional_thread_info_lock: # <<<<<<<<<<<<<< + * # If it's not there, set it within a lock to avoid any racing + * # conditions. + */ + /*with:*/ { + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_set_additional_thread_info_lock); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 112, __pyx_L11_except_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_10 = __Pyx_PyObject_LookupSpecial(__pyx_t_6, __pyx_n_s_exit); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 112, __pyx_L11_except_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_12 = __Pyx_PyObject_LookupSpecial(__pyx_t_6, __pyx_n_s_enter); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 112, __pyx_L18_error) + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_13 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_12))) { + __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_12); + if (likely(__pyx_t_13)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_12); + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_12, function); + } + } + __pyx_t_11 = (__pyx_t_13) ? __Pyx_PyObject_CallOneArg(__pyx_t_12, __pyx_t_13) : __Pyx_PyObject_CallNoArg(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 112, __pyx_L18_error) + __Pyx_GOTREF(__pyx_t_11); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + /*try:*/ { + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":115 + * # If it's not there, set it within a lock to avoid any racing + * # conditions. + * additional_info = getattr(thread, 'additional_info', None) # <<<<<<<<<<<<<< + * if additional_info is None: + * additional_info = PyDBAdditionalThreadInfo() + */ + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_thread); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 115, __pyx_L24_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_11 = __Pyx_GetAttr3(__pyx_t_6, __pyx_n_s_additional_info, Py_None); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 115, __pyx_L24_error) + __Pyx_GOTREF(__pyx_t_11); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF_SET(__pyx_v_additional_info, __pyx_t_11); + __pyx_t_11 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":116 + * # conditions. + * additional_info = getattr(thread, 'additional_info', None) + * if additional_info is None: # <<<<<<<<<<<<<< + * additional_info = PyDBAdditionalThreadInfo() + * t.additional_info = additional_info + */ + __pyx_t_4 = (__pyx_v_additional_info == Py_None); + __pyx_t_5 = (__pyx_t_4 != 0); + if (__pyx_t_5) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":117 + * additional_info = getattr(thread, 'additional_info', None) + * if additional_info is None: + * additional_info = PyDBAdditionalThreadInfo() # <<<<<<<<<<<<<< + * t.additional_info = additional_info + * self.additional_info = additional_info + */ + __pyx_t_11 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo)); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 117, __pyx_L24_error) + __Pyx_GOTREF(__pyx_t_11); + __Pyx_DECREF_SET(__pyx_v_additional_info, __pyx_t_11); + __pyx_t_11 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":116 + * # conditions. + * additional_info = getattr(thread, 'additional_info', None) + * if additional_info is None: # <<<<<<<<<<<<<< + * additional_info = PyDBAdditionalThreadInfo() + * t.additional_info = additional_info + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":118 + * if additional_info is None: + * additional_info = PyDBAdditionalThreadInfo() + * t.additional_info = additional_info # <<<<<<<<<<<<<< + * self.additional_info = additional_info + * self.fully_initialized = True + */ + if (__Pyx_PyObject_SetAttrStr(__pyx_v_t, __pyx_n_s_additional_info, __pyx_v_additional_info) < 0) __PYX_ERR(0, 118, __pyx_L24_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":112 + * raise AttributeError() + * except: + * with _set_additional_thread_info_lock: # <<<<<<<<<<<<<< + * # If it's not there, set it within a lock to avoid any racing + * # conditions. + */ + } + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; + goto __pyx_L31_try_end; + __pyx_L24_error:; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + /*except:*/ { + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.initialize_if_possible", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_11, &__pyx_t_6, &__pyx_t_12) < 0) __PYX_ERR(0, 112, __pyx_L26_except_error) + __Pyx_GOTREF(__pyx_t_11); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_13 = PyTuple_Pack(3, __pyx_t_11, __pyx_t_6, __pyx_t_12); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 112, __pyx_L26_except_error) + __Pyx_GOTREF(__pyx_t_13); + __pyx_t_17 = __Pyx_PyObject_Call(__pyx_t_10, __pyx_t_13, NULL); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 112, __pyx_L26_except_error) + __Pyx_GOTREF(__pyx_t_17); + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_17); + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + if (__pyx_t_5 < 0) __PYX_ERR(0, 112, __pyx_L26_except_error) + __pyx_t_4 = ((!(__pyx_t_5 != 0)) != 0); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_11); + __Pyx_GIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ErrRestoreWithState(__pyx_t_11, __pyx_t_6, __pyx_t_12); + __pyx_t_11 = 0; __pyx_t_6 = 0; __pyx_t_12 = 0; + __PYX_ERR(0, 112, __pyx_L26_except_error) + } + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + goto __pyx_L25_exception_handled; + } + __pyx_L26_except_error:; + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_14, __pyx_t_15, __pyx_t_16); + goto __pyx_L11_except_error; + __pyx_L25_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_14, __pyx_t_15, __pyx_t_16); + __pyx_L31_try_end:; + } + } + /*finally:*/ { + /*normal exit:*/{ + if (__pyx_t_10) { + __pyx_t_16 = __Pyx_PyObject_Call(__pyx_t_10, __pyx_tuple__4, NULL); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 112, __pyx_L11_except_error) + __Pyx_GOTREF(__pyx_t_16); + __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0; + } + goto __pyx_L23; + } + __pyx_L23:; + } + goto __pyx_L36; + __pyx_L18_error:; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + goto __pyx_L11_except_error; + __pyx_L36:; + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L10_exception_handled; + } + __pyx_L11_except_error:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":107 + * self.fully_initialized = True + * else: + * try: # <<<<<<<<<<<<<< + * additional_info = t.additional_info + * if additional_info is None: + */ + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9); + goto __pyx_L4_error; + __pyx_L10_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9); + __pyx_L14_try_end:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":119 + * additional_info = PyDBAdditionalThreadInfo() + * t.additional_info = additional_info + * self.additional_info = additional_info # <<<<<<<<<<<<<< + * self.fully_initialized = True + * finally: + */ + if (unlikely(!__pyx_v_additional_info)) { __Pyx_RaiseUnboundLocalError("additional_info"); __PYX_ERR(0, 119, __pyx_L4_error) } + if (!(likely(((__pyx_v_additional_info) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_additional_info, __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo))))) __PYX_ERR(0, 119, __pyx_L4_error) + __pyx_t_3 = __pyx_v_additional_info; + __Pyx_INCREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __Pyx_GOTREF(__pyx_v_self->additional_info); + __Pyx_DECREF(((PyObject *)__pyx_v_self->additional_info)); + __pyx_v_self->additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_3); + __pyx_t_3 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":120 + * t.additional_info = additional_info + * self.additional_info = additional_info + * self.fully_initialized = True # <<<<<<<<<<<<<< + * finally: + * self.inside_frame_eval -= 1 + */ + __pyx_v_self->fully_initialized = 1; + } + __pyx_L8:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":122 + * self.fully_initialized = True + * finally: + * self.inside_frame_eval -= 1 # <<<<<<<<<<<<<< + * + * + */ + /*finally:*/ { + /*normal exit:*/{ + __pyx_v_self->inside_frame_eval = (__pyx_v_self->inside_frame_eval - 1); + goto __pyx_L5; + } + __pyx_L4_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_9 = 0; __pyx_t_8 = 0; __pyx_t_7 = 0; __pyx_t_10 = 0; __pyx_t_16 = 0; __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_10, &__pyx_t_16, &__pyx_t_15); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_9, &__pyx_t_8, &__pyx_t_7) < 0)) __Pyx_ErrFetch(&__pyx_t_9, &__pyx_t_8, &__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_9); + __Pyx_XGOTREF(__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_15); + __pyx_t_18 = __pyx_lineno; __pyx_t_19 = __pyx_clineno; __pyx_t_20 = __pyx_filename; + { + __pyx_v_self->inside_frame_eval = (__pyx_v_self->inside_frame_eval - 1); + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_ExceptionReset(__pyx_t_10, __pyx_t_16, __pyx_t_15); + } + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_ErrRestore(__pyx_t_9, __pyx_t_8, __pyx_t_7); + __pyx_t_9 = 0; __pyx_t_8 = 0; __pyx_t_7 = 0; __pyx_t_10 = 0; __pyx_t_16 = 0; __pyx_t_15 = 0; + __pyx_lineno = __pyx_t_18; __pyx_clineno = __pyx_t_19; __pyx_filename = __pyx_t_20; + goto __pyx_L1_error; + } + __pyx_L3_return: { + __pyx_t_15 = __pyx_r; + __pyx_r = 0; + __pyx_v_self->inside_frame_eval = (__pyx_v_self->inside_frame_eval - 1); + __pyx_r = __pyx_t_15; + __pyx_t_15 = 0; + goto __pyx_L0; + } + __pyx_L5:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":86 + * # print('Can create dummy thread for thread started in: %s %s' % (basename, co_name)) + * + * cdef initialize_if_possible(self): # <<<<<<<<<<<<<< + * # Don't call threading.currentThread because if we're too early in the process + * # we may create a dummy thread. + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_11); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_13); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.initialize_if_possible", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_thread_ident); + __Pyx_XDECREF(__pyx_v_t); + __Pyx_XDECREF(__pyx_v_additional_info); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":26 + * cdef class ThreadInfo: + * + * cdef public PyDBAdditionalThreadInfo additional_info # <<<<<<<<<<<<<< + * cdef public bint is_pydevd_thread + * cdef public int inside_frame_eval + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_self->additional_info)); + __pyx_r = ((PyObject *)__pyx_v_self->additional_info); + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo))))) __PYX_ERR(0, 26, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->additional_info); + __Pyx_DECREF(((PyObject *)__pyx_v_self->additional_info)); + __pyx_v_self->additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.additional_info.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->additional_info); + __Pyx_DECREF(((PyObject *)__pyx_v_self->additional_info)); + __pyx_v_self->additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":27 + * + * cdef public PyDBAdditionalThreadInfo additional_info + * cdef public bint is_pydevd_thread # <<<<<<<<<<<<<< + * cdef public int inside_frame_eval + * cdef public bint fully_initialized + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->is_pydevd_thread); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.is_pydevd_thread.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 27, __pyx_L1_error) + __pyx_v_self->is_pydevd_thread = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.is_pydevd_thread.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":28 + * cdef public PyDBAdditionalThreadInfo additional_info + * cdef public bint is_pydevd_thread + * cdef public int inside_frame_eval # <<<<<<<<<<<<<< + * cdef public bint fully_initialized + * cdef public object thread_trace_func + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->inside_frame_eval); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.inside_frame_eval.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 28, __pyx_L1_error) + __pyx_v_self->inside_frame_eval = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.inside_frame_eval.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":29 + * cdef public bint is_pydevd_thread + * cdef public int inside_frame_eval + * cdef public bint fully_initialized # <<<<<<<<<<<<<< + * cdef public object thread_trace_func + * cdef bint _can_create_dummy_thread + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->fully_initialized); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.fully_initialized.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 29, __pyx_L1_error) + __pyx_v_self->fully_initialized = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.fully_initialized.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":30 + * cdef public int inside_frame_eval + * cdef public bint fully_initialized + * cdef public object thread_trace_func # <<<<<<<<<<<<<< + * cdef bint _can_create_dummy_thread + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->thread_trace_func); + __pyx_r = __pyx_v_self->thread_trace_func; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->thread_trace_func); + __Pyx_DECREF(__pyx_v_self->thread_trace_func); + __pyx_v_self->thread_trace_func = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->thread_trace_func); + __Pyx_DECREF(__pyx_v_self->thread_trace_func); + __pyx_v_self->thread_trace_func = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":37 + * # If True the debugger should not go into trace mode even if the new + * # code for a function is None and there are breakpoints. + * cdef public bint force_stay_in_untraced_mode # <<<<<<<<<<<<<< + * + * cdef initialize(self, PyFrameObject * frame_obj): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->force_stay_in_untraced_mode); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 37, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.force_stay_in_untraced_mode.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 37, __pyx_L1_error) + __pyx_v_self->force_stay_in_untraced_mode = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.force_stay_in_untraced_mode.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo___reduce_cython__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo___reduce_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + int __pyx_t_8; + int __pyx_t_9; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self._can_create_dummy_thread, self.additional_info, self.force_stay_in_untraced_mode, self.fully_initialized, self.inside_frame_eval, self.is_pydevd_thread, self.thread_trace_func) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->_can_create_dummy_thread); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_self->force_stay_in_untraced_mode); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_self->fully_initialized); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_self->inside_frame_eval); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyBool_FromLong(__pyx_v_self->is_pydevd_thread); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = PyTuple_New(7); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1); + __Pyx_INCREF(((PyObject *)__pyx_v_self->additional_info)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_self->additional_info)); + PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_self->additional_info)); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_6, 3, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_6, 4, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_6, 5, __pyx_t_5); + __Pyx_INCREF(__pyx_v_self->thread_trace_func); + __Pyx_GIVEREF(__pyx_v_self->thread_trace_func); + PyTuple_SET_ITEM(__pyx_t_6, 6, __pyx_v_self->thread_trace_func); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_t_3 = 0; + __pyx_t_4 = 0; + __pyx_t_5 = 0; + __pyx_v_state = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self._can_create_dummy_thread, self.additional_info, self.force_stay_in_untraced_mode, self.fully_initialized, self.inside_frame_eval, self.is_pydevd_thread, self.thread_trace_func) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_6 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v__dict = __pyx_t_6; + __pyx_t_6 = 0; + + /* "(tree fragment)":7 + * state = (self._can_create_dummy_thread, self.additional_info, self.force_stay_in_untraced_mode, self.fully_initialized, self.inside_frame_eval, self.is_pydevd_thread, self.thread_trace_func) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_7 = (__pyx_v__dict != Py_None); + __pyx_t_8 = (__pyx_t_7 != 0); + if (__pyx_t_8) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v__dict); + __pyx_t_5 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_5)); + __pyx_t_5 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self.additional_info is not None or self.thread_trace_func is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self._can_create_dummy_thread, self.additional_info, self.force_stay_in_untraced_mode, self.fully_initialized, self.inside_frame_eval, self.is_pydevd_thread, self.thread_trace_func) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self.additional_info is not None or self.thread_trace_func is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, None), state + */ + /*else*/ { + __pyx_t_7 = (((PyObject *)__pyx_v_self->additional_info) != Py_None); + __pyx_t_9 = (__pyx_t_7 != 0); + if (!__pyx_t_9) { + } else { + __pyx_t_8 = __pyx_t_9; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_9 = (__pyx_v_self->thread_trace_func != Py_None); + __pyx_t_7 = (__pyx_t_9 != 0); + __pyx_t_8 = __pyx_t_7; + __pyx_L4_bool_binop_done:; + __pyx_v_use_setstate = __pyx_t_8; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.additional_info is not None or self.thread_trace_func is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, None), state + * else: + */ + __pyx_t_8 = (__pyx_v_use_setstate != 0); + if (__pyx_t_8) { + + /* "(tree fragment)":13 + * use_setstate = self.additional_info is not None or self.thread_trace_func is not None + * if use_setstate: + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle_ThreadInfo); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_11485321); + __Pyx_GIVEREF(__pyx_int_11485321); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_int_11485321); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_6, 2, Py_None); + __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_6); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_state); + __pyx_t_5 = 0; + __pyx_t_6 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.additional_info is not None or self.thread_trace_func is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, None), state + * else: + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_ThreadInfo__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_ThreadInfo); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_11485321); + __Pyx_GIVEREF(__pyx_int_11485321); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_int_11485321); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_v_state); + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_6); + __pyx_t_4 = 0; + __pyx_t_6 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_ThreadInfo__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_2__setstate_cython__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_2__setstate_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_ThreadInfo__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle_ThreadInfo__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_ThreadInfo, (type(self), 0x0af4089, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_ThreadInfo__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":139 + * cdef public int breakpoints_mtime + * + * def __init__(self): # <<<<<<<<<<<<<< + * self.co_filename = '' + * self.canonical_normalized_filename = '' + */ + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;} + if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__init__", 0))) return -1; + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo___init__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo___init__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":140 + * + * def __init__(self): + * self.co_filename = '' # <<<<<<<<<<<<<< + * self.canonical_normalized_filename = '' + * self.always_skip_code = False + */ + __Pyx_INCREF(__pyx_kp_s__5); + __Pyx_GIVEREF(__pyx_kp_s__5); + __Pyx_GOTREF(__pyx_v_self->co_filename); + __Pyx_DECREF(__pyx_v_self->co_filename); + __pyx_v_self->co_filename = __pyx_kp_s__5; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":141 + * def __init__(self): + * self.co_filename = '' + * self.canonical_normalized_filename = '' # <<<<<<<<<<<<<< + * self.always_skip_code = False + * + */ + __Pyx_INCREF(__pyx_kp_s__5); + __Pyx_GIVEREF(__pyx_kp_s__5); + __Pyx_GOTREF(__pyx_v_self->canonical_normalized_filename); + __Pyx_DECREF(__pyx_v_self->canonical_normalized_filename); + __pyx_v_self->canonical_normalized_filename = __pyx_kp_s__5; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":142 + * self.co_filename = '' + * self.canonical_normalized_filename = '' + * self.always_skip_code = False # <<<<<<<<<<<<<< + * + * # If breakpoints are found but new_code is None, + */ + __pyx_v_self->always_skip_code = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":147 + * # this means we weren't able to actually add the code + * # where needed, so, fallback to tracing. + * self.breakpoint_found = False # <<<<<<<<<<<<<< + * self.new_code = None + * self.breakpoints_mtime = -1 + */ + __pyx_v_self->breakpoint_found = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":148 + * # where needed, so, fallback to tracing. + * self.breakpoint_found = False + * self.new_code = None # <<<<<<<<<<<<<< + * self.breakpoints_mtime = -1 + * + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->new_code); + __Pyx_DECREF(__pyx_v_self->new_code); + __pyx_v_self->new_code = Py_None; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":149 + * self.breakpoint_found = False + * self.new_code = None + * self.breakpoints_mtime = -1 # <<<<<<<<<<<<<< + * + * + */ + __pyx_v_self->breakpoints_mtime = -1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":139 + * cdef public int breakpoints_mtime + * + * def __init__(self): # <<<<<<<<<<<<<< + * self.co_filename = '' + * self.canonical_normalized_filename = '' + */ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":127 + * cdef class FuncCodeInfo: + * + * cdef public str co_filename # <<<<<<<<<<<<<< + * cdef public str co_name + * cdef public str canonical_normalized_filename + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->co_filename); + __pyx_r = __pyx_v_self->co_filename; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyString_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 127, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->co_filename); + __Pyx_DECREF(__pyx_v_self->co_filename); + __pyx_v_self->co_filename = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.co_filename.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->co_filename); + __Pyx_DECREF(__pyx_v_self->co_filename); + __pyx_v_self->co_filename = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":128 + * + * cdef public str co_filename + * cdef public str co_name # <<<<<<<<<<<<<< + * cdef public str canonical_normalized_filename + * cdef bint always_skip_code + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->co_name); + __pyx_r = __pyx_v_self->co_name; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyString_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 128, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->co_name); + __Pyx_DECREF(__pyx_v_self->co_name); + __pyx_v_self->co_name = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.co_name.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->co_name); + __Pyx_DECREF(__pyx_v_self->co_name); + __pyx_v_self->co_name = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":129 + * cdef public str co_filename + * cdef public str co_name + * cdef public str canonical_normalized_filename # <<<<<<<<<<<<<< + * cdef bint always_skip_code + * cdef public bint breakpoint_found + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->canonical_normalized_filename); + __pyx_r = __pyx_v_self->canonical_normalized_filename; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyString_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 129, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->canonical_normalized_filename); + __Pyx_DECREF(__pyx_v_self->canonical_normalized_filename); + __pyx_v_self->canonical_normalized_filename = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.canonical_normalized_filename.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->canonical_normalized_filename); + __Pyx_DECREF(__pyx_v_self->canonical_normalized_filename); + __pyx_v_self->canonical_normalized_filename = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":131 + * cdef public str canonical_normalized_filename + * cdef bint always_skip_code + * cdef public bint breakpoint_found # <<<<<<<<<<<<<< + * cdef public object new_code + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->breakpoint_found); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 131, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.breakpoint_found.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 131, __pyx_L1_error) + __pyx_v_self->breakpoint_found = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.breakpoint_found.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":132 + * cdef bint always_skip_code + * cdef public bint breakpoint_found + * cdef public object new_code # <<<<<<<<<<<<<< + * + * # When breakpoints_mtime != PyDb.mtime the validity of breakpoints have + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->new_code); + __pyx_r = __pyx_v_self->new_code; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->new_code); + __Pyx_DECREF(__pyx_v_self->new_code); + __pyx_v_self->new_code = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->new_code); + __Pyx_DECREF(__pyx_v_self->new_code); + __pyx_v_self->new_code = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":137 + * # to be re-evaluated (if invalid a new FuncCodeInfo must be created and + * # tracing can't be disabled for the related frames). + * cdef public int breakpoints_mtime # <<<<<<<<<<<<<< + * + * def __init__(self): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->breakpoints_mtime); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 137, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.breakpoints_mtime.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 137, __pyx_L1_error) + __pyx_v_self->breakpoints_mtime = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.breakpoints_mtime.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_2__reduce_cython__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_2__reduce_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + int __pyx_t_6; + int __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self.always_skip_code, self.breakpoint_found, self.breakpoints_mtime, self.canonical_normalized_filename, self.co_filename, self.co_name, self.new_code) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->always_skip_code); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_self->breakpoint_found); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_self->breakpoints_mtime); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(7); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3); + __Pyx_INCREF(__pyx_v_self->canonical_normalized_filename); + __Pyx_GIVEREF(__pyx_v_self->canonical_normalized_filename); + PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_v_self->canonical_normalized_filename); + __Pyx_INCREF(__pyx_v_self->co_filename); + __Pyx_GIVEREF(__pyx_v_self->co_filename); + PyTuple_SET_ITEM(__pyx_t_4, 4, __pyx_v_self->co_filename); + __Pyx_INCREF(__pyx_v_self->co_name); + __Pyx_GIVEREF(__pyx_v_self->co_name); + PyTuple_SET_ITEM(__pyx_t_4, 5, __pyx_v_self->co_name); + __Pyx_INCREF(__pyx_v_self->new_code); + __Pyx_GIVEREF(__pyx_v_self->new_code); + PyTuple_SET_ITEM(__pyx_t_4, 6, __pyx_v_self->new_code); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_t_3 = 0; + __pyx_v_state = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self.always_skip_code, self.breakpoint_found, self.breakpoints_mtime, self.canonical_normalized_filename, self.co_filename, self.co_name, self.new_code) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_4 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_v__dict = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":7 + * state = (self.always_skip_code, self.breakpoint_found, self.breakpoints_mtime, self.canonical_normalized_filename, self.co_filename, self.co_name, self.new_code) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_5 = (__pyx_v__dict != Py_None); + __pyx_t_6 = (__pyx_t_5 != 0); + if (__pyx_t_6) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v__dict); + __pyx_t_3 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_3)); + __pyx_t_3 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self.canonical_normalized_filename is not None or self.co_filename is not None or self.co_name is not None or self.new_code is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self.always_skip_code, self.breakpoint_found, self.breakpoints_mtime, self.canonical_normalized_filename, self.co_filename, self.co_name, self.new_code) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self.canonical_normalized_filename is not None or self.co_filename is not None or self.co_name is not None or self.new_code is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, None), state + */ + /*else*/ { + __pyx_t_5 = (__pyx_v_self->canonical_normalized_filename != ((PyObject*)Py_None)); + __pyx_t_7 = (__pyx_t_5 != 0); + if (!__pyx_t_7) { + } else { + __pyx_t_6 = __pyx_t_7; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_7 = (__pyx_v_self->co_filename != ((PyObject*)Py_None)); + __pyx_t_5 = (__pyx_t_7 != 0); + if (!__pyx_t_5) { + } else { + __pyx_t_6 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = (__pyx_v_self->co_name != ((PyObject*)Py_None)); + __pyx_t_7 = (__pyx_t_5 != 0); + if (!__pyx_t_7) { + } else { + __pyx_t_6 = __pyx_t_7; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_7 = (__pyx_v_self->new_code != Py_None); + __pyx_t_5 = (__pyx_t_7 != 0); + __pyx_t_6 = __pyx_t_5; + __pyx_L4_bool_binop_done:; + __pyx_v_use_setstate = __pyx_t_6; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.canonical_normalized_filename is not None or self.co_filename is not None or self.co_name is not None or self.new_code is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, None), state + * else: + */ + __pyx_t_6 = (__pyx_v_use_setstate != 0); + if (__pyx_t_6) { + + /* "(tree fragment)":13 + * use_setstate = self.canonical_normalized_filename is not None or self.co_filename is not None or self.co_name is not None or self.new_code is not None + * if use_setstate: + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_pyx_unpickle_FuncCodeInfo); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_188670045); + __Pyx_GIVEREF(__pyx_int_188670045); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_int_188670045); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_4, 2, Py_None); + __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_4); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_v_state); + __pyx_t_3 = 0; + __pyx_t_4 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.canonical_normalized_filename is not None or self.co_filename is not None or self.co_name is not None or self.new_code is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, None), state + * else: + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_FuncCodeInfo__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_pyx_unpickle_FuncCodeInfo); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_188670045); + __Pyx_GIVEREF(__pyx_int_188670045); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_int_188670045); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_state); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_4); + __pyx_t_2 = 0; + __pyx_t_4 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_FuncCodeInfo__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_4__setstate_cython__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_4__setstate_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_FuncCodeInfo__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle_FuncCodeInfo__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_FuncCodeInfo, (type(self), 0xb3ee05d, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_FuncCodeInfo__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":152 + * + * + * def dummy_trace_dispatch(frame, str event, arg): # <<<<<<<<<<<<<< + * if event == 'call': + * if frame.f_trace is not None: + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_3dummy_trace_dispatch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_3dummy_trace_dispatch = {"dummy_trace_dispatch", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_3dummy_trace_dispatch, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_3dummy_trace_dispatch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_event = 0; + PyObject *__pyx_v_arg = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("dummy_trace_dispatch (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_frame,&__pyx_n_s_event,&__pyx_n_s_arg,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("dummy_trace_dispatch", 1, 3, 3, 1); __PYX_ERR(0, 152, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arg)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("dummy_trace_dispatch", 1, 3, 3, 2); __PYX_ERR(0, 152, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "dummy_trace_dispatch") < 0)) __PYX_ERR(0, 152, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_frame = values[0]; + __pyx_v_event = ((PyObject*)values[1]); + __pyx_v_arg = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("dummy_trace_dispatch", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 152, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.dummy_trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_event), (&PyString_Type), 1, "event", 1))) __PYX_ERR(0, 152, __pyx_L1_error) + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_2dummy_trace_dispatch(__pyx_self, __pyx_v_frame, __pyx_v_event, __pyx_v_arg); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_2dummy_trace_dispatch(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_frame, PyObject *__pyx_v_event, PyObject *__pyx_v_arg) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("dummy_trace_dispatch", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":153 + * + * def dummy_trace_dispatch(frame, str event, arg): + * if event == 'call': # <<<<<<<<<<<<<< + * if frame.f_trace is not None: + * return frame.f_trace(frame, event, arg) + */ + __pyx_t_1 = (__Pyx_PyString_Equals(__pyx_v_event, __pyx_n_s_call_2, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 153, __pyx_L1_error) + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":154 + * def dummy_trace_dispatch(frame, str event, arg): + * if event == 'call': + * if frame.f_trace is not None: # <<<<<<<<<<<<<< + * return frame.f_trace(frame, event, arg) + * return None + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 154, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = (__pyx_t_3 != Py_None); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":155 + * if event == 'call': + * if frame.f_trace is not None: + * return frame.f_trace(frame, event, arg) # <<<<<<<<<<<<<< + * return None + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 155, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = NULL; + __pyx_t_6 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_6 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 3+__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 155, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_3); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_v_frame, __pyx_v_event, __pyx_v_arg}; + __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 3+__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 155, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_3); + } else + #endif + { + __pyx_t_7 = PyTuple_New(3+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 155, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_5) { + __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL; + } + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_v_frame); + __Pyx_INCREF(__pyx_v_event); + __Pyx_GIVEREF(__pyx_v_event); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_v_event); + __Pyx_INCREF(__pyx_v_arg); + __Pyx_GIVEREF(__pyx_v_arg); + PyTuple_SET_ITEM(__pyx_t_7, 2+__pyx_t_6, __pyx_v_arg); + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 155, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":154 + * def dummy_trace_dispatch(frame, str event, arg): + * if event == 'call': + * if frame.f_trace is not None: # <<<<<<<<<<<<<< + * return frame.f_trace(frame, event, arg) + * return None + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":153 + * + * def dummy_trace_dispatch(frame, str event, arg): + * if event == 'call': # <<<<<<<<<<<<<< + * if frame.f_trace is not None: + * return frame.f_trace(frame, event, arg) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":156 + * if frame.f_trace is not None: + * return frame.f_trace(frame, event, arg) + * return None # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":152 + * + * + * def dummy_trace_dispatch(frame, str event, arg): # <<<<<<<<<<<<<< + * if event == 'call': + * if frame.f_trace is not None: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.dummy_trace_dispatch", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":159 + * + * + * def get_thread_info_py() -> ThreadInfo: # <<<<<<<<<<<<<< + * return get_thread_info(PyEval_GetFrame()) + * + */ + +/* Python wrapper */ +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_5get_thread_info_py(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_5get_thread_info_py = {"get_thread_info_py", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_5get_thread_info_py, METH_NOARGS, 0}; +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_5get_thread_info_py(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_thread_info_py (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_4get_thread_info_py(__pyx_self); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_4get_thread_info_py(CYTHON_UNUSED PyObject *__pyx_self) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_thread_info_py", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":160 + * + * def get_thread_info_py() -> ThreadInfo: + * return get_thread_info(PyEval_GetFrame()) # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(((PyObject *)__pyx_r)); + __pyx_t_1 = ((PyObject *)__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_thread_info(PyEval_GetFrame())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 160, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_t_1); + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":159 + * + * + * def get_thread_info_py() -> ThreadInfo: # <<<<<<<<<<<<<< + * return get_thread_info(PyEval_GetFrame()) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_thread_info_py", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF((PyObject *)__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":163 + * + * + * cdef ThreadInfo get_thread_info(PyFrameObject * frame_obj): # <<<<<<<<<<<<<< + * ''' + * Provides thread-related info. + */ + +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_thread_info(PyFrameObject *__pyx_v_frame_obj) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_thread_info = 0; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + int __pyx_t_9; + int __pyx_t_10; + char const *__pyx_t_11; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_thread_info", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":170 + * ''' + * cdef ThreadInfo thread_info + * try: # <<<<<<<<<<<<<< + * # Note: changing to a `dict[thread.ident] = thread_info` had almost no + * # effect in the performance. + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":173 + * # Note: changing to a `dict[thread.ident] = thread_info` had almost no + * # effect in the performance. + * thread_info = _thread_local_info.thread_info # <<<<<<<<<<<<<< + * except: + * if frame_obj == NULL: + */ + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_thread_local_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 173, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_thread_info); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 173, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo))))) __PYX_ERR(0, 173, __pyx_L3_error) + __pyx_v_thread_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_t_5); + __pyx_t_5 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":170 + * ''' + * cdef ThreadInfo thread_info + * try: # <<<<<<<<<<<<<< + * # Note: changing to a `dict[thread.ident] = thread_info` had almost no + * # effect in the performance. + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":174 + * # effect in the performance. + * thread_info = _thread_local_info.thread_info + * except: # <<<<<<<<<<<<<< + * if frame_obj == NULL: + * return None + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_thread_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_4, &__pyx_t_6) < 0) __PYX_ERR(0, 174, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_6); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":175 + * thread_info = _thread_local_info.thread_info + * except: + * if frame_obj == NULL: # <<<<<<<<<<<<<< + * return None + * thread_info = ThreadInfo() + */ + __pyx_t_7 = ((__pyx_v_frame_obj == NULL) != 0); + if (__pyx_t_7) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":176 + * except: + * if frame_obj == NULL: + * return None # <<<<<<<<<<<<<< + * thread_info = ThreadInfo() + * thread_info.initialize(frame_obj) + */ + __Pyx_XDECREF(((PyObject *)__pyx_r)); + __pyx_r = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)Py_None); __Pyx_INCREF(Py_None); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L6_except_return; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":175 + * thread_info = _thread_local_info.thread_info + * except: + * if frame_obj == NULL: # <<<<<<<<<<<<<< + * return None + * thread_info = ThreadInfo() + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":177 + * if frame_obj == NULL: + * return None + * thread_info = ThreadInfo() # <<<<<<<<<<<<<< + * thread_info.initialize(frame_obj) + * thread_info.inside_frame_eval += 1 + */ + __pyx_t_8 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo)); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 177, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_XDECREF_SET(__pyx_v_thread_info, ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_t_8)); + __pyx_t_8 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":178 + * return None + * thread_info = ThreadInfo() + * thread_info.initialize(frame_obj) # <<<<<<<<<<<<<< + * thread_info.inside_frame_eval += 1 + * try: + */ + __pyx_t_8 = ((struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_thread_info->__pyx_vtab)->initialize(__pyx_v_thread_info, __pyx_v_frame_obj); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 178, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":179 + * thread_info = ThreadInfo() + * thread_info.initialize(frame_obj) + * thread_info.inside_frame_eval += 1 # <<<<<<<<<<<<<< + * try: + * _thread_local_info.thread_info = thread_info + */ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval + 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":180 + * thread_info.initialize(frame_obj) + * thread_info.inside_frame_eval += 1 + * try: # <<<<<<<<<<<<<< + * _thread_local_info.thread_info = thread_info + * + */ + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":181 + * thread_info.inside_frame_eval += 1 + * try: + * _thread_local_info.thread_info = thread_info # <<<<<<<<<<<<<< + * + * # Note: _code_extra_index is not actually thread-related, + */ + __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_thread_local_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 181, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_8); + if (__Pyx_PyObject_SetAttrStr(__pyx_t_8, __pyx_n_s_thread_info, ((PyObject *)__pyx_v_thread_info)) < 0) __PYX_ERR(0, 181, __pyx_L15_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":186 + * # but this is a good point to initialize it. + * global _code_extra_index + * if _code_extra_index == -1: # <<<<<<<<<<<<<< + * _code_extra_index = _PyEval_RequestCodeExtraIndex(release_co_extra) + * + */ + __pyx_t_7 = ((__pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator__code_extra_index == -1L) != 0); + if (__pyx_t_7) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":187 + * global _code_extra_index + * if _code_extra_index == -1: + * _code_extra_index = _PyEval_RequestCodeExtraIndex(release_co_extra) # <<<<<<<<<<<<<< + * + * thread_info.initialize_if_possible() + */ + __pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator__code_extra_index = ((int)_PyEval_RequestCodeExtraIndex(release_co_extra)); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":186 + * # but this is a good point to initialize it. + * global _code_extra_index + * if _code_extra_index == -1: # <<<<<<<<<<<<<< + * _code_extra_index = _PyEval_RequestCodeExtraIndex(release_co_extra) + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":189 + * _code_extra_index = _PyEval_RequestCodeExtraIndex(release_co_extra) + * + * thread_info.initialize_if_possible() # <<<<<<<<<<<<<< + * finally: + * thread_info.inside_frame_eval -= 1 + */ + __pyx_t_8 = ((struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_thread_info->__pyx_vtab)->initialize_if_possible(__pyx_v_thread_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 189, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":191 + * thread_info.initialize_if_possible() + * finally: + * thread_info.inside_frame_eval -= 1 # <<<<<<<<<<<<<< + * + * return thread_info + */ + /*finally:*/ { + /*normal exit:*/{ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval - 1); + goto __pyx_L16; + } + __pyx_L15_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14) < 0)) __Pyx_ErrFetch(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_13); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __pyx_t_9 = __pyx_lineno; __pyx_t_10 = __pyx_clineno; __pyx_t_11 = __pyx_filename; + { + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval - 1); + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_ExceptionReset(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_13); + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_ErrRestore(__pyx_t_12, __pyx_t_13, __pyx_t_14); + __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __pyx_lineno = __pyx_t_9; __pyx_clineno = __pyx_t_10; __pyx_filename = __pyx_t_11; + goto __pyx_L5_except_error; + } + __pyx_L16:; + } + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L4_exception_handled; + } + __pyx_L5_except_error:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":170 + * ''' + * cdef ThreadInfo thread_info + * try: # <<<<<<<<<<<<<< + * # Note: changing to a `dict[thread.ident] = thread_info` had almost no + * # effect in the performance. + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L0; + __pyx_L4_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + __pyx_L8_try_end:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":193 + * thread_info.inside_frame_eval -= 1 + * + * return thread_info # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(((PyObject *)__pyx_r)); + __Pyx_INCREF(((PyObject *)__pyx_v_thread_info)); + __pyx_r = __pyx_v_thread_info; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":163 + * + * + * cdef ThreadInfo get_thread_info(PyFrameObject * frame_obj): # <<<<<<<<<<<<<< + * ''' + * Provides thread-related info. + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_thread_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_thread_info); + __Pyx_XGIVEREF((PyObject *)__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":196 + * + * + * def decref_py(obj): # <<<<<<<<<<<<<< + * ''' + * Helper to be called from Python. + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_7decref_py(PyObject *__pyx_self, PyObject *__pyx_v_obj); /*proto*/ +static char __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_6decref_py[] = "\n Helper to be called from Python.\n "; +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_7decref_py = {"decref_py", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_7decref_py, METH_O, __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_6decref_py}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_7decref_py(PyObject *__pyx_self, PyObject *__pyx_v_obj) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("decref_py (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_6decref_py(__pyx_self, ((PyObject *)__pyx_v_obj)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_6decref_py(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_obj) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("decref_py", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":200 + * Helper to be called from Python. + * ''' + * Py_DECREF(obj) # <<<<<<<<<<<<<< + * + * + */ + Py_DECREF(__pyx_v_obj); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":196 + * + * + * def decref_py(obj): # <<<<<<<<<<<<<< + * ''' + * Helper to be called from Python. + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":203 + * + * + * def get_func_code_info_py(thread_info, frame, code_obj) -> FuncCodeInfo: # <<<<<<<<<<<<<< + * ''' + * Helper to be called from Python. + */ + +/* Python wrapper */ +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_9get_func_code_info_py(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_8get_func_code_info_py[] = "\n Helper to be called from Python.\n "; +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_9get_func_code_info_py = {"get_func_code_info_py", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_9get_func_code_info_py, METH_VARARGS|METH_KEYWORDS, __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_8get_func_code_info_py}; +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_9get_func_code_info_py(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_thread_info = 0; + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_code_obj = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_func_code_info_py (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_thread_info,&__pyx_n_s_frame,&__pyx_n_s_code_obj,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_thread_info)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_frame)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("get_func_code_info_py", 1, 3, 3, 1); __PYX_ERR(0, 203, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_code_obj)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("get_func_code_info_py", 1, 3, 3, 2); __PYX_ERR(0, 203, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "get_func_code_info_py") < 0)) __PYX_ERR(0, 203, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_thread_info = values[0]; + __pyx_v_frame = values[1]; + __pyx_v_code_obj = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("get_func_code_info_py", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 203, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_func_code_info_py", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_8get_func_code_info_py(__pyx_self, __pyx_v_thread_info, __pyx_v_frame, __pyx_v_code_obj); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_8get_func_code_info_py(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_thread_info, PyObject *__pyx_v_frame, PyObject *__pyx_v_code_obj) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_func_code_info_py", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":207 + * Helper to be called from Python. + * ''' + * return get_func_code_info( thread_info, frame, code_obj) # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(((PyObject *)__pyx_r)); + __pyx_t_1 = ((PyObject *)__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_func_code_info(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_thread_info), ((PyFrameObject *)__pyx_v_frame), ((PyCodeObject *)__pyx_v_code_obj))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 207, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_t_1); + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":203 + * + * + * def get_func_code_info_py(thread_info, frame, code_obj) -> FuncCodeInfo: # <<<<<<<<<<<<<< + * ''' + * Helper to be called from Python. + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_func_code_info_py", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF((PyObject *)__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":212 + * cdef int _code_extra_index = -1 + * + * cdef FuncCodeInfo get_func_code_info(ThreadInfo thread_info, PyFrameObject * frame_obj, PyCodeObject * code_obj): # <<<<<<<<<<<<<< + * ''' + * Provides code-object related info. + */ + +static struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_func_code_info(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_thread_info, PyFrameObject *__pyx_v_frame_obj, PyCodeObject *__pyx_v_code_obj) { + PyObject *__pyx_v_main_debugger = 0; + PyObject *__pyx_v_extra; + PyObject *__pyx_v_extra_obj; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_func_code_info_obj = NULL; + PyObject *__pyx_v_co_filename = 0; + PyObject *__pyx_v_co_name = 0; + PyObject *__pyx_v_cache_file_type = 0; + PyObject *__pyx_v_cache_file_type_key = 0; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_func_code_info = NULL; + PyObject *__pyx_v_abs_path_real_path_and_base = NULL; + PyObject *__pyx_v_file_type = NULL; + PyObject *__pyx_v_breakpoints = 0; + PyObject *__pyx_v_function_breakpoint = 0; + PyObject *__pyx_v_code_obj_py = 0; + PyObject *__pyx_v_cached_code_obj_info = 0; + PyObject *__pyx_v_breakpoint_found = NULL; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + int __pyx_t_13; + PyObject *(*__pyx_t_14)(PyObject *); + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_func_code_info", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":228 + * # print('get_func_code_info', f_code.co_name, f_code.co_filename) + * + * cdef object main_debugger = GlobalDebuggerHolder.global_dbg # <<<<<<<<<<<<<< + * thread_info.force_stay_in_untraced_mode = False # This is an output value of the function. + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_GlobalDebuggerHolder); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 228, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_global_dbg); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 228, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_main_debugger = __pyx_t_2; + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":229 + * + * cdef object main_debugger = GlobalDebuggerHolder.global_dbg + * thread_info.force_stay_in_untraced_mode = False # This is an output value of the function. # <<<<<<<<<<<<<< + * + * cdef PyObject * extra + */ + __pyx_v_thread_info->force_stay_in_untraced_mode = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":232 + * + * cdef PyObject * extra + * _PyCode_GetExtra( code_obj, _code_extra_index, & extra) # <<<<<<<<<<<<<< + * if extra is not NULL: + * extra_obj = extra + */ + (void)(_PyCode_GetExtra(((PyObject *)__pyx_v_code_obj), __pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator__code_extra_index, (&__pyx_v_extra))); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":233 + * cdef PyObject * extra + * _PyCode_GetExtra( code_obj, _code_extra_index, & extra) + * if extra is not NULL: # <<<<<<<<<<<<<< + * extra_obj = extra + * if extra_obj is not NULL: + */ + __pyx_t_3 = ((__pyx_v_extra != NULL) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":234 + * _PyCode_GetExtra( code_obj, _code_extra_index, & extra) + * if extra is not NULL: + * extra_obj = extra # <<<<<<<<<<<<<< + * if extra_obj is not NULL: + * func_code_info_obj = extra_obj + */ + __pyx_v_extra_obj = ((PyObject *)__pyx_v_extra); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":235 + * if extra is not NULL: + * extra_obj = extra + * if extra_obj is not NULL: # <<<<<<<<<<<<<< + * func_code_info_obj = extra_obj + * if func_code_info_obj.breakpoints_mtime == main_debugger.mtime: + */ + __pyx_t_3 = ((__pyx_v_extra_obj != NULL) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":236 + * extra_obj = extra + * if extra_obj is not NULL: + * func_code_info_obj = extra_obj # <<<<<<<<<<<<<< + * if func_code_info_obj.breakpoints_mtime == main_debugger.mtime: + * # if DEBUG: + */ + __pyx_t_2 = ((PyObject *)__pyx_v_extra_obj); + __Pyx_INCREF(__pyx_t_2); + __pyx_v_func_code_info_obj = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_t_2); + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":237 + * if extra_obj is not NULL: + * func_code_info_obj = extra_obj + * if func_code_info_obj.breakpoints_mtime == main_debugger.mtime: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_func_code_info: matched mtime', f_code.co_name, f_code.co_filename) + */ + __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_func_code_info_obj->breakpoints_mtime); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 237, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_mtime); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 237, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyObject_RichCompare(__pyx_t_2, __pyx_t_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 237, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 237, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":241 + * # print('get_func_code_info: matched mtime', f_code.co_name, f_code.co_filename) + * + * return func_code_info_obj # <<<<<<<<<<<<<< + * + * cdef str co_filename = code_obj.co_filename + */ + __Pyx_XDECREF(((PyObject *)__pyx_r)); + __Pyx_INCREF(((PyObject *)__pyx_v_func_code_info_obj)); + __pyx_r = __pyx_v_func_code_info_obj; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":237 + * if extra_obj is not NULL: + * func_code_info_obj = extra_obj + * if func_code_info_obj.breakpoints_mtime == main_debugger.mtime: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_func_code_info: matched mtime', f_code.co_name, f_code.co_filename) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":235 + * if extra is not NULL: + * extra_obj = extra + * if extra_obj is not NULL: # <<<<<<<<<<<<<< + * func_code_info_obj = extra_obj + * if func_code_info_obj.breakpoints_mtime == main_debugger.mtime: + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":233 + * cdef PyObject * extra + * _PyCode_GetExtra( code_obj, _code_extra_index, & extra) + * if extra is not NULL: # <<<<<<<<<<<<<< + * extra_obj = extra + * if extra_obj is not NULL: + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":243 + * return func_code_info_obj + * + * cdef str co_filename = code_obj.co_filename # <<<<<<<<<<<<<< + * cdef str co_name = code_obj.co_name + * cdef dict cache_file_type + */ + __pyx_t_4 = ((PyObject *)__pyx_v_code_obj->co_filename); + __Pyx_INCREF(__pyx_t_4); + __pyx_v_co_filename = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":244 + * + * cdef str co_filename = code_obj.co_filename + * cdef str co_name = code_obj.co_name # <<<<<<<<<<<<<< + * cdef dict cache_file_type + * cdef tuple cache_file_type_key + */ + __pyx_t_4 = ((PyObject *)__pyx_v_code_obj->co_name); + __Pyx_INCREF(__pyx_t_4); + __pyx_v_co_name = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":248 + * cdef tuple cache_file_type_key + * + * func_code_info = FuncCodeInfo() # <<<<<<<<<<<<<< + * func_code_info.breakpoints_mtime = main_debugger.mtime + * + */ + __pyx_t_4 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 248, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_func_code_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_t_4); + __pyx_t_4 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":249 + * + * func_code_info = FuncCodeInfo() + * func_code_info.breakpoints_mtime = main_debugger.mtime # <<<<<<<<<<<<<< + * + * func_code_info.co_filename = co_filename + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_mtime); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 249, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_4); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 249, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_func_code_info->breakpoints_mtime = __pyx_t_5; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":251 + * func_code_info.breakpoints_mtime = main_debugger.mtime + * + * func_code_info.co_filename = co_filename # <<<<<<<<<<<<<< + * func_code_info.co_name = co_name + * + */ + __Pyx_INCREF(__pyx_v_co_filename); + __Pyx_GIVEREF(__pyx_v_co_filename); + __Pyx_GOTREF(__pyx_v_func_code_info->co_filename); + __Pyx_DECREF(__pyx_v_func_code_info->co_filename); + __pyx_v_func_code_info->co_filename = __pyx_v_co_filename; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":252 + * + * func_code_info.co_filename = co_filename + * func_code_info.co_name = co_name # <<<<<<<<<<<<<< + * + * if not func_code_info.always_skip_code: + */ + __Pyx_INCREF(__pyx_v_co_name); + __Pyx_GIVEREF(__pyx_v_co_name); + __Pyx_GOTREF(__pyx_v_func_code_info->co_name); + __Pyx_DECREF(__pyx_v_func_code_info->co_name); + __pyx_v_func_code_info->co_name = __pyx_v_co_name; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":254 + * func_code_info.co_name = co_name + * + * if not func_code_info.always_skip_code: # <<<<<<<<<<<<<< + * try: + * abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] + */ + __pyx_t_3 = ((!(__pyx_v_func_code_info->always_skip_code != 0)) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":255 + * + * if not func_code_info.always_skip_code: + * try: # <<<<<<<<<<<<<< + * abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] + * except: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_6, &__pyx_t_7, &__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_8); + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":256 + * if not func_code_info.always_skip_code: + * try: + * abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] # <<<<<<<<<<<<<< + * except: + * abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame_obj) + */ + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 256, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_t_4, __pyx_v_co_filename); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 256, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_abs_path_real_path_and_base = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":255 + * + * if not func_code_info.always_skip_code: + * try: # <<<<<<<<<<<<<< + * abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] + * except: + */ + } + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L12_try_end; + __pyx_L7_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":257 + * try: + * abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] + * except: # <<<<<<<<<<<<<< + * abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame_obj) + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_func_code_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_4, &__pyx_t_2) < 0) __PYX_ERR(0, 257, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_2); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":258 + * abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] + * except: + * abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame_obj) # <<<<<<<<<<<<<< + * + * func_code_info.canonical_normalized_filename = abs_path_real_path_and_base[1] + */ + __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_n_s_get_abs_path_real_path_and_base); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 258, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_11 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_10))) { + __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_10); + if (likely(__pyx_t_11)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10); + __Pyx_INCREF(__pyx_t_11); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_10, function); + } + } + __pyx_t_9 = (__pyx_t_11) ? __Pyx_PyObject_Call2Args(__pyx_t_10, __pyx_t_11, ((PyObject *)__pyx_v_frame_obj)) : __Pyx_PyObject_CallOneArg(__pyx_t_10, ((PyObject *)__pyx_v_frame_obj)); + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 258, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF_SET(__pyx_v_abs_path_real_path_and_base, __pyx_t_9); + __pyx_t_9 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + goto __pyx_L8_exception_handled; + } + __pyx_L9_except_error:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":255 + * + * if not func_code_info.always_skip_code: + * try: # <<<<<<<<<<<<<< + * abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] + * except: + */ + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_ExceptionReset(__pyx_t_6, __pyx_t_7, __pyx_t_8); + goto __pyx_L1_error; + __pyx_L8_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_ExceptionReset(__pyx_t_6, __pyx_t_7, __pyx_t_8); + __pyx_L12_try_end:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":260 + * abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame_obj) + * + * func_code_info.canonical_normalized_filename = abs_path_real_path_and_base[1] # <<<<<<<<<<<<<< + * + * cache_file_type = main_debugger.get_cache_file_type() + */ + __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_abs_path_real_path_and_base, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 260, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (!(likely(PyString_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_2)->tp_name), 0))) __PYX_ERR(0, 260, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_2); + __Pyx_GOTREF(__pyx_v_func_code_info->canonical_normalized_filename); + __Pyx_DECREF(__pyx_v_func_code_info->canonical_normalized_filename); + __pyx_v_func_code_info->canonical_normalized_filename = ((PyObject*)__pyx_t_2); + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":262 + * func_code_info.canonical_normalized_filename = abs_path_real_path_and_base[1] + * + * cache_file_type = main_debugger.get_cache_file_type() # <<<<<<<<<<<<<< + * # Note: this cache key must be the same from PyDB.get_file_type() -- see it for comments + * # on the cache. + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_get_cache_file_type); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 262, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_1) : __Pyx_PyObject_CallNoArg(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 262, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (!(likely(PyDict_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_2)->tp_name), 0))) __PYX_ERR(0, 262, __pyx_L1_error) + __pyx_v_cache_file_type = ((PyObject*)__pyx_t_2); + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":265 + * # Note: this cache key must be the same from PyDB.get_file_type() -- see it for comments + * # on the cache. + * cache_file_type_key = (frame_obj.f_code.co_firstlineno, abs_path_real_path_and_base[0], frame_obj.f_code) # <<<<<<<<<<<<<< + * try: + * file_type = cache_file_type[cache_file_type_key] # Make it faster + */ + __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_frame_obj->f_code->co_firstlineno); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 265, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_abs_path_real_path_and_base, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 265, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 265, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_4); + __Pyx_INCREF(((PyObject *)__pyx_v_frame_obj->f_code)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_frame_obj->f_code)); + PyTuple_SET_ITEM(__pyx_t_1, 2, ((PyObject *)__pyx_v_frame_obj->f_code)); + __pyx_t_2 = 0; + __pyx_t_4 = 0; + __pyx_v_cache_file_type_key = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":266 + * # on the cache. + * cache_file_type_key = (frame_obj.f_code.co_firstlineno, abs_path_real_path_and_base[0], frame_obj.f_code) + * try: # <<<<<<<<<<<<<< + * file_type = cache_file_type[cache_file_type_key] # Make it faster + * except: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_8, &__pyx_t_7, &__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_6); + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":267 + * cache_file_type_key = (frame_obj.f_code.co_firstlineno, abs_path_real_path_and_base[0], frame_obj.f_code) + * try: + * file_type = cache_file_type[cache_file_type_key] # Make it faster # <<<<<<<<<<<<<< + * except: + * file_type = main_debugger.get_file_type(frame_obj, abs_path_real_path_and_base) # we don't want to debug anything related to pydevd + */ + if (unlikely(__pyx_v_cache_file_type == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 267, __pyx_L15_error) + } + __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_cache_file_type, __pyx_v_cache_file_type_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 267, __pyx_L15_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_file_type = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":266 + * # on the cache. + * cache_file_type_key = (frame_obj.f_code.co_firstlineno, abs_path_real_path_and_base[0], frame_obj.f_code) + * try: # <<<<<<<<<<<<<< + * file_type = cache_file_type[cache_file_type_key] # Make it faster + * except: + */ + } + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L20_try_end; + __pyx_L15_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":268 + * try: + * file_type = cache_file_type[cache_file_type_key] # Make it faster + * except: # <<<<<<<<<<<<<< + * file_type = main_debugger.get_file_type(frame_obj, abs_path_real_path_and_base) # we don't want to debug anything related to pydevd + * + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_func_code_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_4, &__pyx_t_2) < 0) __PYX_ERR(0, 268, __pyx_L17_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_t_2); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":269 + * file_type = cache_file_type[cache_file_type_key] # Make it faster + * except: + * file_type = main_debugger.get_file_type(frame_obj, abs_path_real_path_and_base) # we don't want to debug anything related to pydevd # <<<<<<<<<<<<<< + * + * if file_type is not None: + */ + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_get_file_type); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 269, __pyx_L17_except_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_11 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_10))) { + __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_10); + if (likely(__pyx_t_11)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10); + __Pyx_INCREF(__pyx_t_11); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_10, function); + __pyx_t_5 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_10)) { + PyObject *__pyx_temp[3] = {__pyx_t_11, ((PyObject *)__pyx_v_frame_obj), __pyx_v_abs_path_real_path_and_base}; + __pyx_t_9 = __Pyx_PyFunction_FastCall(__pyx_t_10, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 269, __pyx_L17_except_error) + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_GOTREF(__pyx_t_9); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_10)) { + PyObject *__pyx_temp[3] = {__pyx_t_11, ((PyObject *)__pyx_v_frame_obj), __pyx_v_abs_path_real_path_and_base}; + __pyx_t_9 = __Pyx_PyCFunction_FastCall(__pyx_t_10, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 269, __pyx_L17_except_error) + __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_GOTREF(__pyx_t_9); + } else + #endif + { + __pyx_t_12 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 269, __pyx_L17_except_error) + __Pyx_GOTREF(__pyx_t_12); + if (__pyx_t_11) { + __Pyx_GIVEREF(__pyx_t_11); PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_11); __pyx_t_11 = NULL; + } + __Pyx_INCREF(((PyObject *)__pyx_v_frame_obj)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_frame_obj)); + PyTuple_SET_ITEM(__pyx_t_12, 0+__pyx_t_5, ((PyObject *)__pyx_v_frame_obj)); + __Pyx_INCREF(__pyx_v_abs_path_real_path_and_base); + __Pyx_GIVEREF(__pyx_v_abs_path_real_path_and_base); + PyTuple_SET_ITEM(__pyx_t_12, 1+__pyx_t_5, __pyx_v_abs_path_real_path_and_base); + __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_10, __pyx_t_12, NULL); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 269, __pyx_L17_except_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + } + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF_SET(__pyx_v_file_type, __pyx_t_9); + __pyx_t_9 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + goto __pyx_L16_exception_handled; + } + __pyx_L17_except_error:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":266 + * # on the cache. + * cache_file_type_key = (frame_obj.f_code.co_firstlineno, abs_path_real_path_and_base[0], frame_obj.f_code) + * try: # <<<<<<<<<<<<<< + * file_type = cache_file_type[cache_file_type_key] # Make it faster + * except: + */ + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_ExceptionReset(__pyx_t_8, __pyx_t_7, __pyx_t_6); + goto __pyx_L1_error; + __pyx_L16_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_ExceptionReset(__pyx_t_8, __pyx_t_7, __pyx_t_6); + __pyx_L20_try_end:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":271 + * file_type = main_debugger.get_file_type(frame_obj, abs_path_real_path_and_base) # we don't want to debug anything related to pydevd + * + * if file_type is not None: # <<<<<<<<<<<<<< + * func_code_info.always_skip_code = True + * + */ + __pyx_t_3 = (__pyx_v_file_type != Py_None); + __pyx_t_13 = (__pyx_t_3 != 0); + if (__pyx_t_13) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":272 + * + * if file_type is not None: + * func_code_info.always_skip_code = True # <<<<<<<<<<<<<< + * + * if not func_code_info.always_skip_code: + */ + __pyx_v_func_code_info->always_skip_code = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":271 + * file_type = main_debugger.get_file_type(frame_obj, abs_path_real_path_and_base) # we don't want to debug anything related to pydevd + * + * if file_type is not None: # <<<<<<<<<<<<<< + * func_code_info.always_skip_code = True + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":254 + * func_code_info.co_name = co_name + * + * if not func_code_info.always_skip_code: # <<<<<<<<<<<<<< + * try: + * abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":274 + * func_code_info.always_skip_code = True + * + * if not func_code_info.always_skip_code: # <<<<<<<<<<<<<< + * if main_debugger is not None: + * + */ + __pyx_t_13 = ((!(__pyx_v_func_code_info->always_skip_code != 0)) != 0); + if (__pyx_t_13) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":275 + * + * if not func_code_info.always_skip_code: + * if main_debugger is not None: # <<<<<<<<<<<<<< + * + * breakpoints: dict = main_debugger.breakpoints.get(func_code_info.canonical_normalized_filename) + */ + __pyx_t_13 = (__pyx_v_main_debugger != Py_None); + __pyx_t_3 = (__pyx_t_13 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":277 + * if main_debugger is not None: + * + * breakpoints: dict = main_debugger.breakpoints.get(func_code_info.canonical_normalized_filename) # <<<<<<<<<<<<<< + * function_breakpoint: object = main_debugger.function_breakpoint_name_to_breakpoint.get(func_code_info.co_name) + * # print('\n---') + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_breakpoints); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 277, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_get); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 277, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_4, __pyx_v_func_code_info->canonical_normalized_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_func_code_info->canonical_normalized_filename); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 277, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(PyDict_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_2)->tp_name), 0))) __PYX_ERR(0, 277, __pyx_L1_error) + __pyx_v_breakpoints = ((PyObject*)__pyx_t_2); + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":278 + * + * breakpoints: dict = main_debugger.breakpoints.get(func_code_info.canonical_normalized_filename) + * function_breakpoint: object = main_debugger.function_breakpoint_name_to_breakpoint.get(func_code_info.co_name) # <<<<<<<<<<<<<< + * # print('\n---') + * # print(main_debugger.breakpoints) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_function_breakpoint_name_to_brea); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 278, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_get); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 278, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_1, __pyx_v_func_code_info->co_name) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_func_code_info->co_name); + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 278, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_function_breakpoint = __pyx_t_2; + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":283 + * # print(func_code_info.canonical_normalized_filename) + * # print(main_debugger.breakpoints.get(func_code_info.canonical_normalized_filename)) + * code_obj_py: object = code_obj # <<<<<<<<<<<<<< + * cached_code_obj_info: object = _cache.get(code_obj_py) + * if cached_code_obj_info: + */ + __pyx_t_2 = ((PyObject *)__pyx_v_code_obj); + __Pyx_INCREF(__pyx_t_2); + __pyx_v_code_obj_py = __pyx_t_2; + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":284 + * # print(main_debugger.breakpoints.get(func_code_info.canonical_normalized_filename)) + * code_obj_py: object = code_obj + * cached_code_obj_info: object = _cache.get(code_obj_py) # <<<<<<<<<<<<<< + * if cached_code_obj_info: + * # The cache is for new code objects, so, in this case it's already + */ + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_cache); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 284, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_get); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 284, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_4, __pyx_v_code_obj_py) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_code_obj_py); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 284, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_cached_code_obj_info = __pyx_t_2; + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":285 + * code_obj_py: object = code_obj + * cached_code_obj_info: object = _cache.get(code_obj_py) + * if cached_code_obj_info: # <<<<<<<<<<<<<< + * # The cache is for new code objects, so, in this case it's already + * # using the new code and we can't change it as this is a generator! + */ + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_cached_code_obj_info); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 285, __pyx_L1_error) + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":291 + * # we may not want to go into tracing mode (as would usually happen + * # when the new_code is None). + * func_code_info.new_code = None # <<<<<<<<<<<<<< + * breakpoint_found, thread_info.force_stay_in_untraced_mode = \ + * cached_code_obj_info.compute_force_stay_in_untraced_mode(breakpoints) + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_func_code_info->new_code); + __Pyx_DECREF(__pyx_v_func_code_info->new_code); + __pyx_v_func_code_info->new_code = Py_None; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":293 + * func_code_info.new_code = None + * breakpoint_found, thread_info.force_stay_in_untraced_mode = \ + * cached_code_obj_info.compute_force_stay_in_untraced_mode(breakpoints) # <<<<<<<<<<<<<< + * func_code_info.breakpoint_found = breakpoint_found + * + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_cached_code_obj_info, __pyx_n_s_compute_force_stay_in_untraced_m); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 293, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_4, __pyx_v_breakpoints) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_breakpoints); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 293, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) { + PyObject* sequence = __pyx_t_2; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 292, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_1 = PyList_GET_ITEM(sequence, 0); + __pyx_t_4 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); + #else + __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 292, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 292, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_9 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 292, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_14 = Py_TYPE(__pyx_t_9)->tp_iternext; + index = 0; __pyx_t_1 = __pyx_t_14(__pyx_t_9); if (unlikely(!__pyx_t_1)) goto __pyx_L27_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + index = 1; __pyx_t_4 = __pyx_t_14(__pyx_t_9); if (unlikely(!__pyx_t_4)) goto __pyx_L27_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_9), 2) < 0) __PYX_ERR(0, 292, __pyx_L1_error) + __pyx_t_14 = NULL; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L28_unpacking_done; + __pyx_L27_unpacking_failed:; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_14 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 292, __pyx_L1_error) + __pyx_L28_unpacking_done:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":292 + * # when the new_code is None). + * func_code_info.new_code = None + * breakpoint_found, thread_info.force_stay_in_untraced_mode = \ # <<<<<<<<<<<<<< + * cached_code_obj_info.compute_force_stay_in_untraced_mode(breakpoints) + * func_code_info.breakpoint_found = breakpoint_found + */ + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 292, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_breakpoint_found = __pyx_t_1; + __pyx_t_1 = 0; + __pyx_v_thread_info->force_stay_in_untraced_mode = __pyx_t_3; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":294 + * breakpoint_found, thread_info.force_stay_in_untraced_mode = \ + * cached_code_obj_info.compute_force_stay_in_untraced_mode(breakpoints) + * func_code_info.breakpoint_found = breakpoint_found # <<<<<<<<<<<<<< + * + * elif function_breakpoint: + */ + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_breakpoint_found); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 294, __pyx_L1_error) + __pyx_v_func_code_info->breakpoint_found = __pyx_t_3; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":285 + * code_obj_py: object = code_obj + * cached_code_obj_info: object = _cache.get(code_obj_py) + * if cached_code_obj_info: # <<<<<<<<<<<<<< + * # The cache is for new code objects, so, in this case it's already + * # using the new code and we can't change it as this is a generator! + */ + goto __pyx_L26; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":296 + * func_code_info.breakpoint_found = breakpoint_found + * + * elif function_breakpoint: # <<<<<<<<<<<<<< + * # Go directly into tracing mode + * func_code_info.breakpoint_found = True + */ + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_function_breakpoint); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 296, __pyx_L1_error) + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":298 + * elif function_breakpoint: + * # Go directly into tracing mode + * func_code_info.breakpoint_found = True # <<<<<<<<<<<<<< + * func_code_info.new_code = None + * + */ + __pyx_v_func_code_info->breakpoint_found = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":299 + * # Go directly into tracing mode + * func_code_info.breakpoint_found = True + * func_code_info.new_code = None # <<<<<<<<<<<<<< + * + * elif breakpoints: + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_func_code_info->new_code); + __Pyx_DECREF(__pyx_v_func_code_info->new_code); + __pyx_v_func_code_info->new_code = Py_None; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":296 + * func_code_info.breakpoint_found = breakpoint_found + * + * elif function_breakpoint: # <<<<<<<<<<<<<< + * # Go directly into tracing mode + * func_code_info.breakpoint_found = True + */ + goto __pyx_L26; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":301 + * func_code_info.new_code = None + * + * elif breakpoints: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('found breakpoints', code_obj_py.co_name, breakpoints) + */ + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_breakpoints); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 301, __pyx_L1_error) + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":307 + * # Note: new_code can be None if unable to generate. + * # It should automatically put the new code object in the cache. + * breakpoint_found, func_code_info.new_code = generate_code_with_breakpoints(code_obj_py, breakpoints) # <<<<<<<<<<<<<< + * func_code_info.breakpoint_found = breakpoint_found + * + */ + __pyx_t_2 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_generate_code_with_breakpoints(__pyx_v_code_obj_py, __pyx_v_breakpoints); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 307, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) { + PyObject* sequence = __pyx_t_2; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 307, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_4 = PyList_GET_ITEM(sequence, 0); + __pyx_t_1 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_1); + #else + __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 307, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 307, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_9 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 307, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_14 = Py_TYPE(__pyx_t_9)->tp_iternext; + index = 0; __pyx_t_4 = __pyx_t_14(__pyx_t_9); if (unlikely(!__pyx_t_4)) goto __pyx_L29_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + index = 1; __pyx_t_1 = __pyx_t_14(__pyx_t_9); if (unlikely(!__pyx_t_1)) goto __pyx_L29_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_9), 2) < 0) __PYX_ERR(0, 307, __pyx_L1_error) + __pyx_t_14 = NULL; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L30_unpacking_done; + __pyx_L29_unpacking_failed:; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_14 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 307, __pyx_L1_error) + __pyx_L30_unpacking_done:; + } + __pyx_v_breakpoint_found = __pyx_t_4; + __pyx_t_4 = 0; + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_func_code_info->new_code); + __Pyx_DECREF(__pyx_v_func_code_info->new_code); + __pyx_v_func_code_info->new_code = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":308 + * # It should automatically put the new code object in the cache. + * breakpoint_found, func_code_info.new_code = generate_code_with_breakpoints(code_obj_py, breakpoints) + * func_code_info.breakpoint_found = breakpoint_found # <<<<<<<<<<<<<< + * + * Py_INCREF(func_code_info) + */ + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_breakpoint_found); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 308, __pyx_L1_error) + __pyx_v_func_code_info->breakpoint_found = __pyx_t_3; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":301 + * func_code_info.new_code = None + * + * elif breakpoints: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('found breakpoints', code_obj_py.co_name, breakpoints) + */ + } + __pyx_L26:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":275 + * + * if not func_code_info.always_skip_code: + * if main_debugger is not None: # <<<<<<<<<<<<<< + * + * breakpoints: dict = main_debugger.breakpoints.get(func_code_info.canonical_normalized_filename) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":274 + * func_code_info.always_skip_code = True + * + * if not func_code_info.always_skip_code: # <<<<<<<<<<<<<< + * if main_debugger is not None: + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":310 + * func_code_info.breakpoint_found = breakpoint_found + * + * Py_INCREF(func_code_info) # <<<<<<<<<<<<<< + * _PyCode_SetExtra( code_obj, _code_extra_index, func_code_info) + * + */ + Py_INCREF(((PyObject *)__pyx_v_func_code_info)); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":311 + * + * Py_INCREF(func_code_info) + * _PyCode_SetExtra( code_obj, _code_extra_index, func_code_info) # <<<<<<<<<<<<<< + * + * return func_code_info + */ + (void)(_PyCode_SetExtra(((PyObject *)__pyx_v_code_obj), __pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator__code_extra_index, ((PyObject *)__pyx_v_func_code_info))); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":313 + * _PyCode_SetExtra( code_obj, _code_extra_index, func_code_info) + * + * return func_code_info # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(((PyObject *)__pyx_r)); + __Pyx_INCREF(((PyObject *)__pyx_v_func_code_info)); + __pyx_r = __pyx_v_func_code_info; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":212 + * cdef int _code_extra_index = -1 + * + * cdef FuncCodeInfo get_func_code_info(ThreadInfo thread_info, PyFrameObject * frame_obj, PyCodeObject * code_obj): # <<<<<<<<<<<<<< + * ''' + * Provides code-object related info. + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_XDECREF(__pyx_t_11); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_func_code_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_main_debugger); + __Pyx_XDECREF((PyObject *)__pyx_v_func_code_info_obj); + __Pyx_XDECREF(__pyx_v_co_filename); + __Pyx_XDECREF(__pyx_v_co_name); + __Pyx_XDECREF(__pyx_v_cache_file_type); + __Pyx_XDECREF(__pyx_v_cache_file_type_key); + __Pyx_XDECREF((PyObject *)__pyx_v_func_code_info); + __Pyx_XDECREF(__pyx_v_abs_path_real_path_and_base); + __Pyx_XDECREF(__pyx_v_file_type); + __Pyx_XDECREF(__pyx_v_breakpoints); + __Pyx_XDECREF(__pyx_v_function_breakpoint); + __Pyx_XDECREF(__pyx_v_code_obj_py); + __Pyx_XDECREF(__pyx_v_cached_code_obj_info); + __Pyx_XDECREF(__pyx_v_breakpoint_found); + __Pyx_XGIVEREF((PyObject *)__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":322 + * cdef public int last_line + * + * def __init__(self, dict line_to_offset, int first_line, int last_line): # <<<<<<<<<<<<<< + * self.line_to_offset = line_to_offset + * self.first_line = first_line + */ + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_line_to_offset = 0; + int __pyx_v_first_line; + int __pyx_v_last_line; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_line_to_offset,&__pyx_n_s_first_line,&__pyx_n_s_last_line,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_line_to_offset)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_first_line)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, 1); __PYX_ERR(0, 322, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_last_line)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, 2); __PYX_ERR(0, 322, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 322, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_line_to_offset = ((PyObject*)values[0]); + __pyx_v_first_line = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_first_line == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 322, __pyx_L3_error) + __pyx_v_last_line = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_last_line == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 322, __pyx_L3_error) + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 322, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_line_to_offset), (&PyDict_Type), 1, "line_to_offset", 1))) __PYX_ERR(0, 322, __pyx_L1_error) + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo___init__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self), __pyx_v_line_to_offset, __pyx_v_first_line, __pyx_v_last_line); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo___init__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v_line_to_offset, int __pyx_v_first_line, int __pyx_v_last_line) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":323 + * + * def __init__(self, dict line_to_offset, int first_line, int last_line): + * self.line_to_offset = line_to_offset # <<<<<<<<<<<<<< + * self.first_line = first_line + * self.last_line = last_line + */ + __Pyx_INCREF(__pyx_v_line_to_offset); + __Pyx_GIVEREF(__pyx_v_line_to_offset); + __Pyx_GOTREF(__pyx_v_self->line_to_offset); + __Pyx_DECREF(__pyx_v_self->line_to_offset); + __pyx_v_self->line_to_offset = __pyx_v_line_to_offset; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":324 + * def __init__(self, dict line_to_offset, int first_line, int last_line): + * self.line_to_offset = line_to_offset + * self.first_line = first_line # <<<<<<<<<<<<<< + * self.last_line = last_line + * + */ + __pyx_v_self->first_line = __pyx_v_first_line; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":325 + * self.line_to_offset = line_to_offset + * self.first_line = first_line + * self.last_line = last_line # <<<<<<<<<<<<<< + * + * + */ + __pyx_v_self->last_line = __pyx_v_last_line; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":322 + * cdef public int last_line + * + * def __init__(self, dict line_to_offset, int first_line, int last_line): # <<<<<<<<<<<<<< + * self.line_to_offset = line_to_offset + * self.first_line = first_line + */ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":318 + * cdef class _CodeLineInfo: + * + * cdef public dict line_to_offset # <<<<<<<<<<<<<< + * cdef public int first_line + * cdef public int last_line + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->line_to_offset); + __pyx_r = __pyx_v_self->line_to_offset; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PyDict_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 318, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->line_to_offset); + __Pyx_DECREF(__pyx_v_self->line_to_offset); + __pyx_v_self->line_to_offset = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo.line_to_offset.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->line_to_offset); + __Pyx_DECREF(__pyx_v_self->line_to_offset); + __pyx_v_self->line_to_offset = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":319 + * + * cdef public dict line_to_offset + * cdef public int first_line # <<<<<<<<<<<<<< + * cdef public int last_line + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->first_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 319, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo.first_line.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 319, __pyx_L1_error) + __pyx_v_self->first_line = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo.first_line.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":320 + * cdef public dict line_to_offset + * cdef public int first_line + * cdef public int last_line # <<<<<<<<<<<<<< + * + * def __init__(self, dict line_to_offset, int first_line, int last_line): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->last_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 320, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo.last_line.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 320, __pyx_L1_error) + __pyx_v_self->last_line = __pyx_t_1; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo.last_line.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_2__reduce_cython__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_2__reduce_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + int __pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self.first_line, self.last_line, self.line_to_offset) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->first_line); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_self->last_line); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2); + __Pyx_INCREF(__pyx_v_self->line_to_offset); + __Pyx_GIVEREF(__pyx_v_self->line_to_offset); + PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_self->line_to_offset); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_v_state = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self.first_line, self.last_line, self.line_to_offset) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_3 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_v__dict = __pyx_t_3; + __pyx_t_3 = 0; + + /* "(tree fragment)":7 + * state = (self.first_line, self.last_line, self.line_to_offset) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_4 = (__pyx_v__dict != Py_None); + __pyx_t_5 = (__pyx_t_4 != 0); + if (__pyx_t_5) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v__dict); + __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_2)); + __pyx_t_2 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self.line_to_offset is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self.first_line, self.last_line, self.line_to_offset) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self.line_to_offset is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, None), state + */ + /*else*/ { + __pyx_t_5 = (__pyx_v_self->line_to_offset != ((PyObject*)Py_None)); + __pyx_v_use_setstate = __pyx_t_5; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.line_to_offset is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, None), state + * else: + */ + __pyx_t_5 = (__pyx_v_use_setstate != 0); + if (__pyx_t_5) { + + /* "(tree fragment)":13 + * use_setstate = self.line_to_offset is not None + * if use_setstate: + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_pyx_unpickle__CodeLineInfo); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_66829570); + __Pyx_GIVEREF(__pyx_int_66829570); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_66829570); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_3, 2, Py_None); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state); + __pyx_t_2 = 0; + __pyx_t_3 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.line_to_offset is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, None), state + * else: + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle__CodeLineInfo__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pyx_unpickle__CodeLineInfo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_66829570); + __Pyx_GIVEREF(__pyx_int_66829570); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_66829570); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_state); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3); + __pyx_t_1 = 0; + __pyx_t_3 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle__CodeLineInfo__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_4__setstate_cython__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_4__setstate_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle__CodeLineInfo__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle__CodeLineInfo__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle__CodeLineInfo, (type(self), 0x3fbbd02, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle__CodeLineInfo__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":329 + * + * # Note: this method has a version in pure-python too. + * def _get_code_line_info(code_obj): # <<<<<<<<<<<<<< + * line_to_offset: dict = {} + * first_line: int = None + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_get_code_line_info(PyObject *__pyx_self, PyObject *__pyx_v_code_obj); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_get_code_line_info = {"_get_code_line_info", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_get_code_line_info, METH_O, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_get_code_line_info(PyObject *__pyx_self, PyObject *__pyx_v_code_obj) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("_get_code_line_info (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10_get_code_line_info(__pyx_self, ((PyObject *)__pyx_v_code_obj)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_10_get_code_line_info(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_code_obj) { + PyObject *__pyx_v_line_to_offset = 0; + PyObject *__pyx_v_first_line = 0; + PyObject *__pyx_v_last_line = 0; + int __pyx_v_offset; + int __pyx_v_line; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + Py_ssize_t __pyx_t_4; + PyObject *(*__pyx_t_5)(PyObject *); + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *(*__pyx_t_8)(PyObject *); + int __pyx_t_9; + int __pyx_t_10; + int __pyx_t_11; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_get_code_line_info", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":330 + * # Note: this method has a version in pure-python too. + * def _get_code_line_info(code_obj): + * line_to_offset: dict = {} # <<<<<<<<<<<<<< + * first_line: int = None + * last_line: int = None + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 330, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_line_to_offset = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":331 + * def _get_code_line_info(code_obj): + * line_to_offset: dict = {} + * first_line: int = None # <<<<<<<<<<<<<< + * last_line: int = None + * + */ + __Pyx_INCREF(Py_None); + __pyx_v_first_line = Py_None; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":332 + * line_to_offset: dict = {} + * first_line: int = None + * last_line: int = None # <<<<<<<<<<<<<< + * + * cdef int offset + */ + __Pyx_INCREF(Py_None); + __pyx_v_last_line = Py_None; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":337 + * cdef int line + * + * for offset, line in dis.findlinestarts(code_obj): # <<<<<<<<<<<<<< + * line_to_offset[line] = offset + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_dis); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_findlinestarts); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_v_code_obj) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_code_obj); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) { + __pyx_t_3 = __pyx_t_1; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0; + __pyx_t_5 = NULL; + } else { + __pyx_t_4 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 337, __pyx_L1_error) + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + for (;;) { + if (likely(!__pyx_t_5)) { + if (likely(PyList_CheckExact(__pyx_t_3))) { + if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_1 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_1); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 337, __pyx_L1_error) + #else + __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + } else { + if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_3)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_1); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 337, __pyx_L1_error) + #else + __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + } + } else { + __pyx_t_1 = __pyx_t_5(__pyx_t_3); + if (unlikely(!__pyx_t_1)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 337, __pyx_L1_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_1); + } + if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 337, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_2 = PyList_GET_ITEM(sequence, 0); + __pyx_t_6 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_6); + #else + __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_7 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_8 = Py_TYPE(__pyx_t_7)->tp_iternext; + index = 0; __pyx_t_2 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_2)) goto __pyx_L5_unpacking_failed; + __Pyx_GOTREF(__pyx_t_2); + index = 1; __pyx_t_6 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_6)) goto __pyx_L5_unpacking_failed; + __Pyx_GOTREF(__pyx_t_6); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_7), 2) < 0) __PYX_ERR(0, 337, __pyx_L1_error) + __pyx_t_8 = NULL; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L6_unpacking_done; + __pyx_L5_unpacking_failed:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_8 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 337, __pyx_L1_error) + __pyx_L6_unpacking_done:; + } + __pyx_t_9 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_9 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_10 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_10 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 337, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_v_offset = __pyx_t_9; + __pyx_v_line = __pyx_t_10; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":338 + * + * for offset, line in dis.findlinestarts(code_obj): + * line_to_offset[line] = offset # <<<<<<<<<<<<<< + * + * if line_to_offset: + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_offset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 338, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_6 = __Pyx_PyInt_From_int(__pyx_v_line); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 338, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + if (unlikely(PyDict_SetItem(__pyx_v_line_to_offset, __pyx_t_6, __pyx_t_1) < 0)) __PYX_ERR(0, 338, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":337 + * cdef int line + * + * for offset, line in dis.findlinestarts(code_obj): # <<<<<<<<<<<<<< + * line_to_offset[line] = offset + * + */ + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":340 + * line_to_offset[line] = offset + * + * if line_to_offset: # <<<<<<<<<<<<<< + * first_line = min(line_to_offset) + * last_line = max(line_to_offset) + */ + __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_v_line_to_offset); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 340, __pyx_L1_error) + if (__pyx_t_11) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":341 + * + * if line_to_offset: + * first_line = min(line_to_offset) # <<<<<<<<<<<<<< + * last_line = max(line_to_offset) + * return _CodeLineInfo(line_to_offset, first_line, last_line) + */ + __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_min, __pyx_v_line_to_offset); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 341, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF_SET(__pyx_v_first_line, __pyx_t_3); + __pyx_t_3 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":342 + * if line_to_offset: + * first_line = min(line_to_offset) + * last_line = max(line_to_offset) # <<<<<<<<<<<<<< + * return _CodeLineInfo(line_to_offset, first_line, last_line) + * + */ + __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_max, __pyx_v_line_to_offset); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 342, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF_SET(__pyx_v_last_line, __pyx_t_3); + __pyx_t_3 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":340 + * line_to_offset[line] = offset + * + * if line_to_offset: # <<<<<<<<<<<<<< + * first_line = min(line_to_offset) + * last_line = max(line_to_offset) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":343 + * first_line = min(line_to_offset) + * last_line = max(line_to_offset) + * return _CodeLineInfo(line_to_offset, first_line, last_line) # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 343, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_line_to_offset); + __Pyx_GIVEREF(__pyx_v_line_to_offset); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_line_to_offset); + __Pyx_INCREF(__pyx_v_first_line); + __Pyx_GIVEREF(__pyx_v_first_line); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_first_line); + __Pyx_INCREF(__pyx_v_last_line); + __Pyx_GIVEREF(__pyx_v_last_line); + PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_last_line); + __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo), __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 343, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":329 + * + * # Note: this method has a version in pure-python too. + * def _get_code_line_info(code_obj): # <<<<<<<<<<<<<< + * line_to_offset: dict = {} + * first_line: int = None + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._get_code_line_info", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_line_to_offset); + __Pyx_XDECREF(__pyx_v_first_line); + __Pyx_XDECREF(__pyx_v_last_line); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":353 + * _cache: dict = {} + * + * def get_cached_code_obj_info_py(code_obj_py): # <<<<<<<<<<<<<< + * ''' + * :return _CacheValue: + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13get_cached_code_obj_info_py(PyObject *__pyx_self, PyObject *__pyx_v_code_obj_py); /*proto*/ +static char __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_12get_cached_code_obj_info_py[] = "\n :return _CacheValue:\n :note: on cython use _cache.get(code_obj_py) directly.\n "; +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_13get_cached_code_obj_info_py = {"get_cached_code_obj_info_py", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13get_cached_code_obj_info_py, METH_O, __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_12get_cached_code_obj_info_py}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13get_cached_code_obj_info_py(PyObject *__pyx_self, PyObject *__pyx_v_code_obj_py) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_cached_code_obj_info_py (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12get_cached_code_obj_info_py(__pyx_self, ((PyObject *)__pyx_v_code_obj_py)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_12get_cached_code_obj_info_py(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_code_obj_py) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_cached_code_obj_info_py", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":358 + * :note: on cython use _cache.get(code_obj_py) directly. + * ''' + * return _cache.get(code_obj_py) # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_cache); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 358, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_get); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 358, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_v_code_obj_py) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_code_obj_py); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 358, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":353 + * _cache: dict = {} + * + * def get_cached_code_obj_info_py(code_obj_py): # <<<<<<<<<<<<<< + * ''' + * :return _CacheValue: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_cached_code_obj_info_py", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":368 + * cdef public set code_lines_as_set + * + * def __init__(self, object code_obj_py, _CodeLineInfo code_line_info, set breakpoints_hit_at_lines): # <<<<<<<<<<<<<< + * ''' + * :param code_obj_py: + */ + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__[] = "\n :param code_obj_py:\n :param _CodeLineInfo code_line_info:\n :param set[int] breakpoints_hit_at_lines:\n "; +#if CYTHON_UPDATE_DESCRIPTOR_DOC +struct wrapperbase __pyx_wrapperbase_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__; +#endif +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_code_obj_py = 0; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_code_line_info = 0; + PyObject *__pyx_v_breakpoints_hit_at_lines = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_code_obj_py,&__pyx_n_s_code_line_info,&__pyx_n_s_breakpoints_hit_at_lines,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_code_obj_py)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_code_line_info)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, 1); __PYX_ERR(0, 368, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_breakpoints_hit_at_lines)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, 2); __PYX_ERR(0, 368, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 368, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_code_obj_py = values[0]; + __pyx_v_code_line_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)values[1]); + __pyx_v_breakpoints_hit_at_lines = ((PyObject*)values[2]); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 368, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_code_line_info), __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo, 1, "code_line_info", 0))) __PYX_ERR(0, 368, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_breakpoints_hit_at_lines), (&PySet_Type), 1, "breakpoints_hit_at_lines", 1))) __PYX_ERR(0, 368, __pyx_L1_error) + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self), __pyx_v_code_obj_py, __pyx_v_code_line_info, __pyx_v_breakpoints_hit_at_lines); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_code_obj_py, struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v_code_line_info, PyObject *__pyx_v_breakpoints_hit_at_lines) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__init__", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":374 + * :param set[int] breakpoints_hit_at_lines: + * ''' + * self.code_obj_py = code_obj_py # <<<<<<<<<<<<<< + * self.code_line_info = code_line_info + * self.breakpoints_hit_at_lines = breakpoints_hit_at_lines + */ + __Pyx_INCREF(__pyx_v_code_obj_py); + __Pyx_GIVEREF(__pyx_v_code_obj_py); + __Pyx_GOTREF(__pyx_v_self->code_obj_py); + __Pyx_DECREF(__pyx_v_self->code_obj_py); + __pyx_v_self->code_obj_py = __pyx_v_code_obj_py; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":375 + * ''' + * self.code_obj_py = code_obj_py + * self.code_line_info = code_line_info # <<<<<<<<<<<<<< + * self.breakpoints_hit_at_lines = breakpoints_hit_at_lines + * self.code_lines_as_set = set(code_line_info.line_to_offset) + */ + __Pyx_INCREF(((PyObject *)__pyx_v_code_line_info)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_code_line_info)); + __Pyx_GOTREF(__pyx_v_self->code_line_info); + __Pyx_DECREF(((PyObject *)__pyx_v_self->code_line_info)); + __pyx_v_self->code_line_info = __pyx_v_code_line_info; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":376 + * self.code_obj_py = code_obj_py + * self.code_line_info = code_line_info + * self.breakpoints_hit_at_lines = breakpoints_hit_at_lines # <<<<<<<<<<<<<< + * self.code_lines_as_set = set(code_line_info.line_to_offset) + * + */ + __Pyx_INCREF(__pyx_v_breakpoints_hit_at_lines); + __Pyx_GIVEREF(__pyx_v_breakpoints_hit_at_lines); + __Pyx_GOTREF(__pyx_v_self->breakpoints_hit_at_lines); + __Pyx_DECREF(__pyx_v_self->breakpoints_hit_at_lines); + __pyx_v_self->breakpoints_hit_at_lines = __pyx_v_breakpoints_hit_at_lines; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":377 + * self.code_line_info = code_line_info + * self.breakpoints_hit_at_lines = breakpoints_hit_at_lines + * self.code_lines_as_set = set(code_line_info.line_to_offset) # <<<<<<<<<<<<<< + * + * cpdef compute_force_stay_in_untraced_mode(self, breakpoints): + */ + __pyx_t_1 = PySet_New(__pyx_v_code_line_info->line_to_offset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 377, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->code_lines_as_set); + __Pyx_DECREF(__pyx_v_self->code_lines_as_set); + __pyx_v_self->code_lines_as_set = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":368 + * cdef public set code_lines_as_set + * + * def __init__(self, object code_obj_py, _CodeLineInfo code_line_info, set breakpoints_hit_at_lines): # <<<<<<<<<<<<<< + * ''' + * :param code_obj_py: + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":379 + * self.code_lines_as_set = set(code_line_info.line_to_offset) + * + * cpdef compute_force_stay_in_untraced_mode(self, breakpoints): # <<<<<<<<<<<<<< + * ''' + * :param breakpoints: + */ + +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_3compute_force_stay_in_untraced_mode(PyObject *__pyx_v_self, PyObject *__pyx_v_breakpoints); /*proto*/ +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_compute_force_stay_in_untraced_mode(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_breakpoints, int __pyx_skip_dispatch) { + int __pyx_v_force_stay_in_untraced_mode; + int __pyx_v_breakpoint_found; + PyObject *__pyx_v_target_breakpoints = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("compute_force_stay_in_untraced_mode", 0); + /* Check if called by wrapper */ + if (unlikely(__pyx_skip_dispatch)) ; + /* Check if overridden in Python */ + else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) { + #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS + static PY_UINT64_T __pyx_tp_dict_version = __PYX_DICT_VERSION_INIT, __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT; + if (unlikely(!__Pyx_object_dict_version_matches(((PyObject *)__pyx_v_self), __pyx_tp_dict_version, __pyx_obj_dict_version))) { + PY_UINT64_T __pyx_type_dict_guard = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self)); + #endif + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_compute_force_stay_in_untraced_m); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 379, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_3compute_force_stay_in_untraced_mode)) { + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_t_1); + __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_breakpoints) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_breakpoints); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 379, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L0; + } + #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS + __pyx_tp_dict_version = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self)); + __pyx_obj_dict_version = __Pyx_get_object_dict_version(((PyObject *)__pyx_v_self)); + if (unlikely(__pyx_type_dict_guard != __pyx_tp_dict_version)) { + __pyx_tp_dict_version = __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT; + } + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS + } + #endif + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":389 + * cdef set target_breakpoints + * + * force_stay_in_untraced_mode = False # <<<<<<<<<<<<<< + * + * target_breakpoints = self.code_lines_as_set.intersection(breakpoints) + */ + __pyx_v_force_stay_in_untraced_mode = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":391 + * force_stay_in_untraced_mode = False + * + * target_breakpoints = self.code_lines_as_set.intersection(breakpoints) # <<<<<<<<<<<<<< + * breakpoint_found = bool(target_breakpoints) + * + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->code_lines_as_set, __pyx_n_s_intersection); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 391, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + } + } + __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_breakpoints) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_breakpoints); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 391, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!(likely(PySet_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "set", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 391, __pyx_L1_error) + __pyx_v_target_breakpoints = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":392 + * + * target_breakpoints = self.code_lines_as_set.intersection(breakpoints) + * breakpoint_found = bool(target_breakpoints) # <<<<<<<<<<<<<< + * + * if not breakpoint_found: + */ + __pyx_t_5 = (__pyx_v_target_breakpoints != Py_None)&&(PySet_GET_SIZE(__pyx_v_target_breakpoints) != 0); + __pyx_v_breakpoint_found = (!(!__pyx_t_5)); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":394 + * breakpoint_found = bool(target_breakpoints) + * + * if not breakpoint_found: # <<<<<<<<<<<<<< + * force_stay_in_untraced_mode = True + * else: + */ + __pyx_t_5 = ((!(__pyx_v_breakpoint_found != 0)) != 0); + if (__pyx_t_5) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":395 + * + * if not breakpoint_found: + * force_stay_in_untraced_mode = True # <<<<<<<<<<<<<< + * else: + * force_stay_in_untraced_mode = self.breakpoints_hit_at_lines.issuperset(set(breakpoints)) + */ + __pyx_v_force_stay_in_untraced_mode = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":394 + * breakpoint_found = bool(target_breakpoints) + * + * if not breakpoint_found: # <<<<<<<<<<<<<< + * force_stay_in_untraced_mode = True + * else: + */ + goto __pyx_L3; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":397 + * force_stay_in_untraced_mode = True + * else: + * force_stay_in_untraced_mode = self.breakpoints_hit_at_lines.issuperset(set(breakpoints)) # <<<<<<<<<<<<<< + * + * return breakpoint_found, force_stay_in_untraced_mode + */ + /*else*/ { + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->breakpoints_hit_at_lines, __pyx_n_s_issuperset); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 397, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PySet_New(__pyx_v_breakpoints); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 397, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + } + } + __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 397, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 397, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_force_stay_in_untraced_mode = __pyx_t_5; + } + __pyx_L3:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":399 + * force_stay_in_untraced_mode = self.breakpoints_hit_at_lines.issuperset(set(breakpoints)) + * + * return breakpoint_found, force_stay_in_untraced_mode # <<<<<<<<<<<<<< + * + * def generate_code_with_breakpoints_py(object code_obj_py, dict breakpoints): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_breakpoint_found); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 399, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_force_stay_in_untraced_mode); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 399, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 399, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":379 + * self.code_lines_as_set = set(code_line_info.line_to_offset) + * + * cpdef compute_force_stay_in_untraced_mode(self, breakpoints): # <<<<<<<<<<<<<< + * ''' + * :param breakpoints: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.compute_force_stay_in_untraced_mode", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_target_breakpoints); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_3compute_force_stay_in_untraced_mode(PyObject *__pyx_v_self, PyObject *__pyx_v_breakpoints); /*proto*/ +static char __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_2compute_force_stay_in_untraced_mode[] = "\n :param breakpoints:\n set(breakpoint_lines) or dict(breakpoint_line->breakpoint info)\n :return tuple(breakpoint_found, force_stay_in_untraced_mode)\n "; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_3compute_force_stay_in_untraced_mode(PyObject *__pyx_v_self, PyObject *__pyx_v_breakpoints) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("compute_force_stay_in_untraced_mode (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_2compute_force_stay_in_untraced_mode(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self), ((PyObject *)__pyx_v_breakpoints)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_2compute_force_stay_in_untraced_mode(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_breakpoints) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("compute_force_stay_in_untraced_mode", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_compute_force_stay_in_untraced_mode(__pyx_v_self, __pyx_v_breakpoints, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 379, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.compute_force_stay_in_untraced_mode", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":363 + * cdef class _CacheValue(object): + * + * cdef public object code_obj_py # <<<<<<<<<<<<<< + * cdef public _CodeLineInfo code_line_info + * cdef public set breakpoints_hit_at_lines + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->code_obj_py); + __pyx_r = __pyx_v_self->code_obj_py; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__", 0); + __Pyx_INCREF(__pyx_v_value); + __Pyx_GIVEREF(__pyx_v_value); + __Pyx_GOTREF(__pyx_v_self->code_obj_py); + __Pyx_DECREF(__pyx_v_self->code_obj_py); + __pyx_v_self->code_obj_py = __pyx_v_value; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->code_obj_py); + __Pyx_DECREF(__pyx_v_self->code_obj_py); + __pyx_v_self->code_obj_py = Py_None; + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":364 + * + * cdef public object code_obj_py + * cdef public _CodeLineInfo code_line_info # <<<<<<<<<<<<<< + * cdef public set breakpoints_hit_at_lines + * cdef public set code_lines_as_set + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_self->code_line_info)); + __pyx_r = ((PyObject *)__pyx_v_self->code_line_info); + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo))))) __PYX_ERR(0, 364, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->code_line_info); + __Pyx_DECREF(((PyObject *)__pyx_v_self->code_line_info)); + __pyx_v_self->code_line_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.code_line_info.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->code_line_info); + __Pyx_DECREF(((PyObject *)__pyx_v_self->code_line_info)); + __pyx_v_self->code_line_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":365 + * cdef public object code_obj_py + * cdef public _CodeLineInfo code_line_info + * cdef public set breakpoints_hit_at_lines # <<<<<<<<<<<<<< + * cdef public set code_lines_as_set + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->breakpoints_hit_at_lines); + __pyx_r = __pyx_v_self->breakpoints_hit_at_lines; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PySet_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "set", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 365, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->breakpoints_hit_at_lines); + __Pyx_DECREF(__pyx_v_self->breakpoints_hit_at_lines); + __pyx_v_self->breakpoints_hit_at_lines = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.breakpoints_hit_at_lines.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->breakpoints_hit_at_lines); + __Pyx_DECREF(__pyx_v_self->breakpoints_hit_at_lines); + __pyx_v_self->breakpoints_hit_at_lines = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":366 + * cdef public _CodeLineInfo code_line_info + * cdef public set breakpoints_hit_at_lines + * cdef public set code_lines_as_set # <<<<<<<<<<<<<< + * + * def __init__(self, object code_obj_py, _CodeLineInfo code_line_info, set breakpoints_hit_at_lines): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set___get__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set___get__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->code_lines_as_set); + __pyx_r = __pyx_v_self->code_lines_as_set; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__set__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_2__set__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_2__set__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__set__", 0); + if (!(likely(PySet_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "set", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 366, __pyx_L1_error) + __pyx_t_1 = __pyx_v_value; + __Pyx_INCREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->code_lines_as_set); + __Pyx_DECREF(__pyx_v_self->code_lines_as_set); + __pyx_v_self->code_lines_as_set = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.code_lines_as_set.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_5__del__(PyObject *__pyx_v_self); /*proto*/ +static int __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_5__del__(PyObject *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_4__del__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_4__del__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__del__", 0); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->code_lines_as_set); + __Pyx_DECREF(__pyx_v_self->code_lines_as_set); + __pyx_v_self->code_lines_as_set = ((PyObject*)Py_None); + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_4__reduce_cython__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_4__reduce_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self.breakpoints_hit_at_lines, self.code_line_info, self.code_lines_as_set, self.code_obj_py) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + */ + __pyx_t_1 = PyTuple_New(4); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_self->breakpoints_hit_at_lines); + __Pyx_GIVEREF(__pyx_v_self->breakpoints_hit_at_lines); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->breakpoints_hit_at_lines); + __Pyx_INCREF(((PyObject *)__pyx_v_self->code_line_info)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_self->code_line_info)); + PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_v_self->code_line_info)); + __Pyx_INCREF(__pyx_v_self->code_lines_as_set); + __Pyx_GIVEREF(__pyx_v_self->code_lines_as_set); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_self->code_lines_as_set); + __Pyx_INCREF(__pyx_v_self->code_obj_py); + __Pyx_GIVEREF(__pyx_v_self->code_obj_py); + PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_self->code_obj_py); + __pyx_v_state = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self.breakpoints_hit_at_lines, self.code_line_info, self.code_lines_as_set, self.code_obj_py) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None: + * state += (_dict,) + */ + __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v__dict = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":7 + * state = (self.breakpoints_hit_at_lines, self.code_line_info, self.code_lines_as_set, self.code_obj_py) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + __pyx_t_2 = (__pyx_v__dict != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: + */ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict); + __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "(tree fragment)":9 + * if _dict is not None: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self.breakpoints_hit_at_lines is not None or self.code_line_info is not None or self.code_lines_as_set is not None or self.code_obj_py is not None + */ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self.breakpoints_hit_at_lines, self.code_line_info, self.code_lines_as_set, self.code_obj_py) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True + */ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self.breakpoints_hit_at_lines is not None or self.code_line_info is not None or self.code_lines_as_set is not None or self.code_obj_py is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, None), state + */ + /*else*/ { + __pyx_t_2 = (__pyx_v_self->breakpoints_hit_at_lines != ((PyObject*)Py_None)); + __pyx_t_5 = (__pyx_t_2 != 0); + if (!__pyx_t_5) { + } else { + __pyx_t_3 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = (((PyObject *)__pyx_v_self->code_line_info) != Py_None); + __pyx_t_2 = (__pyx_t_5 != 0); + if (!__pyx_t_2) { + } else { + __pyx_t_3 = __pyx_t_2; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_2 = (__pyx_v_self->code_lines_as_set != ((PyObject*)Py_None)); + __pyx_t_5 = (__pyx_t_2 != 0); + if (!__pyx_t_5) { + } else { + __pyx_t_3 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = (__pyx_v_self->code_obj_py != Py_None); + __pyx_t_2 = (__pyx_t_5 != 0); + __pyx_t_3 = __pyx_t_2; + __pyx_L4_bool_binop_done:; + __pyx_v_use_setstate = __pyx_t_3; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.breakpoints_hit_at_lines is not None or self.code_line_info is not None or self.code_lines_as_set is not None or self.code_obj_py is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, None), state + * else: + */ + __pyx_t_3 = (__pyx_v_use_setstate != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":13 + * use_setstate = self.breakpoints_hit_at_lines is not None or self.code_line_info is not None or self.code_lines_as_set is not None or self.code_obj_py is not None + * if use_setstate: + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, state) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle__CacheValue); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_64258489); + __Pyx_GIVEREF(__pyx_int_64258489); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_64258489); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None); + __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_1); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_v_state); + __pyx_t_4 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.breakpoints_hit_at_lines is not None or self.code_line_info is not None or self.code_lines_as_set is not None or self.code_obj_py is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, None), state + * else: + */ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, None), state + * else: + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle__CacheValue__set_state(self, __pyx_state) + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pyx_unpickle__CacheValue); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_INCREF(__pyx_int_64258489); + __Pyx_GIVEREF(__pyx_int_64258489); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_64258489); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1); + __pyx_t_6 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle__CacheValue__set_state(self, __pyx_state) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_6__setstate_cython__(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_6__setstate_cython__(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle__CacheValue__set_state(self, __pyx_state) # <<<<<<<<<<<<<< + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error) + __pyx_t_1 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle__CacheValue__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle__CacheValue, (type(self), 0x3d481b9, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle__CacheValue__set_state(self, __pyx_state) + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":401 + * return breakpoint_found, force_stay_in_untraced_mode + * + * def generate_code_with_breakpoints_py(object code_obj_py, dict breakpoints): # <<<<<<<<<<<<<< + * return generate_code_with_breakpoints(code_obj_py, breakpoints) + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_15generate_code_with_breakpoints_py(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_15generate_code_with_breakpoints_py = {"generate_code_with_breakpoints_py", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_15generate_code_with_breakpoints_py, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_15generate_code_with_breakpoints_py(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_code_obj_py = 0; + PyObject *__pyx_v_breakpoints = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("generate_code_with_breakpoints_py (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_code_obj_py,&__pyx_n_s_breakpoints,0}; + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_code_obj_py)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_breakpoints)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("generate_code_with_breakpoints_py", 1, 2, 2, 1); __PYX_ERR(0, 401, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "generate_code_with_breakpoints_py") < 0)) __PYX_ERR(0, 401, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_code_obj_py = values[0]; + __pyx_v_breakpoints = ((PyObject*)values[1]); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("generate_code_with_breakpoints_py", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 401, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.generate_code_with_breakpoints_py", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_breakpoints), (&PyDict_Type), 1, "breakpoints", 1))) __PYX_ERR(0, 401, __pyx_L1_error) + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_14generate_code_with_breakpoints_py(__pyx_self, __pyx_v_code_obj_py, __pyx_v_breakpoints); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_14generate_code_with_breakpoints_py(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_code_obj_py, PyObject *__pyx_v_breakpoints) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("generate_code_with_breakpoints_py", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":402 + * + * def generate_code_with_breakpoints_py(object code_obj_py, dict breakpoints): + * return generate_code_with_breakpoints(code_obj_py, breakpoints) # <<<<<<<<<<<<<< + * + * # DEBUG = True + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_generate_code_with_breakpoints(__pyx_v_code_obj_py, __pyx_v_breakpoints); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 402, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":401 + * return breakpoint_found, force_stay_in_untraced_mode + * + * def generate_code_with_breakpoints_py(object code_obj_py, dict breakpoints): # <<<<<<<<<<<<<< + * return generate_code_with_breakpoints(code_obj_py, breakpoints) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.generate_code_with_breakpoints_py", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":407 + * # debug_helper = DebugHelper() + * + * cdef generate_code_with_breakpoints(object code_obj_py, dict breakpoints): # <<<<<<<<<<<<<< + * ''' + * :param breakpoints: + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_generate_code_with_breakpoints(PyObject *__pyx_v_code_obj_py, PyObject *__pyx_v_breakpoints) { + int __pyx_v_success; + int __pyx_v_breakpoint_line; + int __pyx_v_breakpoint_found; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v_cache_value = 0; + PyObject *__pyx_v_breakpoints_hit_at_lines = 0; + PyObject *__pyx_v_line_to_offset = 0; + PyObject *__pyx_v_code_line_info = NULL; + PyObject *__pyx_v_new_code = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + Py_ssize_t __pyx_t_5; + Py_ssize_t __pyx_t_6; + int __pyx_t_7; + int __pyx_t_8; + int __pyx_t_9; + int __pyx_t_10; + PyObject *__pyx_t_11 = NULL; + PyObject *(*__pyx_t_12)(PyObject *); + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("generate_code_with_breakpoints", 0); + __Pyx_INCREF(__pyx_v_code_obj_py); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":424 + * cdef dict line_to_offset + * + * assert code_obj_py not in _cache, 'If a code object is cached, that same code object must be reused.' # <<<<<<<<<<<<<< + * + * # if DEBUG: + */ + #ifndef CYTHON_WITHOUT_ASSERTIONS + if (unlikely(!Py_OptimizeFlag)) { + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_cache); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 424, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_v_code_obj_py, __pyx_t_1, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 424, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!(__pyx_t_2 != 0))) { + PyErr_SetObject(PyExc_AssertionError, __pyx_kp_s_If_a_code_object_is_cached_that); + __PYX_ERR(0, 424, __pyx_L1_error) + } + } + #endif + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":429 + * # initial_code_obj_py = code_obj_py + * + * code_line_info = _get_code_line_info(code_obj_py) # <<<<<<<<<<<<<< + * + * success = True + */ + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_get_code_line_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 429, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_code_obj_py) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_code_obj_py); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 429, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_code_line_info = __pyx_t_1; + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":431 + * code_line_info = _get_code_line_info(code_obj_py) + * + * success = True # <<<<<<<<<<<<<< + * + * breakpoints_hit_at_lines = set() + */ + __pyx_v_success = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":433 + * success = True + * + * breakpoints_hit_at_lines = set() # <<<<<<<<<<<<<< + * line_to_offset = code_line_info.line_to_offset + * + */ + __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 433, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_breakpoints_hit_at_lines = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":434 + * + * breakpoints_hit_at_lines = set() + * line_to_offset = code_line_info.line_to_offset # <<<<<<<<<<<<<< + * + * for breakpoint_line in breakpoints: + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_code_line_info, __pyx_n_s_line_to_offset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 434, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyDict_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 434, __pyx_L1_error) + __pyx_v_line_to_offset = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":436 + * line_to_offset = code_line_info.line_to_offset + * + * for breakpoint_line in breakpoints: # <<<<<<<<<<<<<< + * if breakpoint_line in line_to_offset: + * breakpoints_hit_at_lines.add(breakpoint_line) + */ + __pyx_t_5 = 0; + if (unlikely(__pyx_v_breakpoints == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 436, __pyx_L1_error) + } + __pyx_t_3 = __Pyx_dict_iterator(__pyx_v_breakpoints, 1, ((PyObject *)NULL), (&__pyx_t_6), (&__pyx_t_7)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 436, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_1); + __pyx_t_1 = __pyx_t_3; + __pyx_t_3 = 0; + while (1) { + __pyx_t_8 = __Pyx_dict_iter_next(__pyx_t_1, __pyx_t_6, &__pyx_t_5, &__pyx_t_3, NULL, NULL, __pyx_t_7); + if (unlikely(__pyx_t_8 == 0)) break; + if (unlikely(__pyx_t_8 == -1)) __PYX_ERR(0, 436, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 436, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_breakpoint_line = __pyx_t_8; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":437 + * + * for breakpoint_line in breakpoints: + * if breakpoint_line in line_to_offset: # <<<<<<<<<<<<<< + * breakpoints_hit_at_lines.add(breakpoint_line) + * + */ + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_breakpoint_line); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 437, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (unlikely(__pyx_v_line_to_offset == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 437, __pyx_L1_error) + } + __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_t_3, __pyx_v_line_to_offset, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 437, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_9 = (__pyx_t_2 != 0); + if (__pyx_t_9) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":438 + * for breakpoint_line in breakpoints: + * if breakpoint_line in line_to_offset: + * breakpoints_hit_at_lines.add(breakpoint_line) # <<<<<<<<<<<<<< + * + * if breakpoints_hit_at_lines: + */ + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_breakpoint_line); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 438, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_10 = PySet_Add(__pyx_v_breakpoints_hit_at_lines, __pyx_t_3); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 438, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":437 + * + * for breakpoint_line in breakpoints: + * if breakpoint_line in line_to_offset: # <<<<<<<<<<<<<< + * breakpoints_hit_at_lines.add(breakpoint_line) + * + */ + } + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":440 + * breakpoints_hit_at_lines.add(breakpoint_line) + * + * if breakpoints_hit_at_lines: # <<<<<<<<<<<<<< + * success, new_code = insert_pydevd_breaks( + * code_obj_py, + */ + __pyx_t_9 = (PySet_GET_SIZE(__pyx_v_breakpoints_hit_at_lines) != 0); + if (__pyx_t_9) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":441 + * + * if breakpoints_hit_at_lines: + * success, new_code = insert_pydevd_breaks( # <<<<<<<<<<<<<< + * code_obj_py, + * breakpoints_hit_at_lines, + */ + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_insert_pydevd_breaks); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":444 + * code_obj_py, + * breakpoints_hit_at_lines, + * code_line_info # <<<<<<<<<<<<<< + * ) + * + */ + __pyx_t_4 = NULL; + __pyx_t_7 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_7 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[4] = {__pyx_t_4, __pyx_v_code_obj_py, __pyx_v_breakpoints_hit_at_lines, __pyx_v_code_line_info}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[4] = {__pyx_t_4, __pyx_v_code_obj_py, __pyx_v_breakpoints_hit_at_lines, __pyx_v_code_line_info}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_11 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_11); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_4); __pyx_t_4 = NULL; + } + __Pyx_INCREF(__pyx_v_code_obj_py); + __Pyx_GIVEREF(__pyx_v_code_obj_py); + PyTuple_SET_ITEM(__pyx_t_11, 0+__pyx_t_7, __pyx_v_code_obj_py); + __Pyx_INCREF(__pyx_v_breakpoints_hit_at_lines); + __Pyx_GIVEREF(__pyx_v_breakpoints_hit_at_lines); + PyTuple_SET_ITEM(__pyx_t_11, 1+__pyx_t_7, __pyx_v_breakpoints_hit_at_lines); + __Pyx_INCREF(__pyx_v_code_line_info); + __Pyx_GIVEREF(__pyx_v_code_line_info); + PyTuple_SET_ITEM(__pyx_t_11, 2+__pyx_t_7, __pyx_v_code_line_info); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 441, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_11 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_11 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_11); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_11 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_11); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_12 = Py_TYPE(__pyx_t_4)->tp_iternext; + index = 0; __pyx_t_3 = __pyx_t_12(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L7_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 1; __pyx_t_11 = __pyx_t_12(__pyx_t_4); if (unlikely(!__pyx_t_11)) goto __pyx_L7_unpacking_failed; + __Pyx_GOTREF(__pyx_t_11); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_12(__pyx_t_4), 2) < 0) __PYX_ERR(0, 441, __pyx_L1_error) + __pyx_t_12 = NULL; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + goto __pyx_L8_unpacking_done; + __pyx_L7_unpacking_failed:; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_12 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 441, __pyx_L1_error) + __pyx_L8_unpacking_done:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":441 + * + * if breakpoints_hit_at_lines: + * success, new_code = insert_pydevd_breaks( # <<<<<<<<<<<<<< + * code_obj_py, + * breakpoints_hit_at_lines, + */ + __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely((__pyx_t_9 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 441, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_success = __pyx_t_9; + __pyx_v_new_code = __pyx_t_11; + __pyx_t_11 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":447 + * ) + * + * if not success: # <<<<<<<<<<<<<< + * code_obj_py = None + * else: + */ + __pyx_t_9 = ((!(__pyx_v_success != 0)) != 0); + if (__pyx_t_9) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":448 + * + * if not success: + * code_obj_py = None # <<<<<<<<<<<<<< + * else: + * code_obj_py = new_code + */ + __Pyx_INCREF(Py_None); + __Pyx_DECREF_SET(__pyx_v_code_obj_py, Py_None); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":447 + * ) + * + * if not success: # <<<<<<<<<<<<<< + * code_obj_py = None + * else: + */ + goto __pyx_L9; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":450 + * code_obj_py = None + * else: + * code_obj_py = new_code # <<<<<<<<<<<<<< + * + * breakpoint_found = bool(breakpoints_hit_at_lines) + */ + /*else*/ { + __Pyx_INCREF(__pyx_v_new_code); + __Pyx_DECREF_SET(__pyx_v_code_obj_py, __pyx_v_new_code); + } + __pyx_L9:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":440 + * breakpoints_hit_at_lines.add(breakpoint_line) + * + * if breakpoints_hit_at_lines: # <<<<<<<<<<<<<< + * success, new_code = insert_pydevd_breaks( + * code_obj_py, + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":452 + * code_obj_py = new_code + * + * breakpoint_found = bool(breakpoints_hit_at_lines) # <<<<<<<<<<<<<< + * if breakpoint_found and success: + * # if DEBUG: + */ + __pyx_t_9 = (PySet_GET_SIZE(__pyx_v_breakpoints_hit_at_lines) != 0); + __pyx_v_breakpoint_found = (!(!__pyx_t_9)); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":453 + * + * breakpoint_found = bool(breakpoints_hit_at_lines) + * if breakpoint_found and success: # <<<<<<<<<<<<<< + * # if DEBUG: + * # op_number = debug_helper.write_dis( + */ + __pyx_t_2 = (__pyx_v_breakpoint_found != 0); + if (__pyx_t_2) { + } else { + __pyx_t_9 = __pyx_t_2; + goto __pyx_L11_bool_binop_done; + } + __pyx_t_2 = (__pyx_v_success != 0); + __pyx_t_9 = __pyx_t_2; + __pyx_L11_bool_binop_done:; + if (__pyx_t_9) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":466 + * # ) + * + * cache_value = _CacheValue(code_obj_py, code_line_info, breakpoints_hit_at_lines) # <<<<<<<<<<<<<< + * _cache[code_obj_py] = cache_value + * + */ + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 466, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_code_obj_py); + __Pyx_GIVEREF(__pyx_v_code_obj_py); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_code_obj_py); + __Pyx_INCREF(__pyx_v_code_line_info); + __Pyx_GIVEREF(__pyx_v_code_line_info); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_code_line_info); + __Pyx_INCREF(__pyx_v_breakpoints_hit_at_lines); + __Pyx_GIVEREF(__pyx_v_breakpoints_hit_at_lines); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_breakpoints_hit_at_lines); + __pyx_t_11 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue), __pyx_t_1, NULL); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 466, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_11); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_cache_value = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_t_11); + __pyx_t_11 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":467 + * + * cache_value = _CacheValue(code_obj_py, code_line_info, breakpoints_hit_at_lines) + * _cache[code_obj_py] = cache_value # <<<<<<<<<<<<<< + * + * return breakpoint_found, code_obj_py + */ + __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_cache); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 467, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_11); + if (unlikely(PyObject_SetItem(__pyx_t_11, __pyx_v_code_obj_py, ((PyObject *)__pyx_v_cache_value)) < 0)) __PYX_ERR(0, 467, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":453 + * + * breakpoint_found = bool(breakpoints_hit_at_lines) + * if breakpoint_found and success: # <<<<<<<<<<<<<< + * # if DEBUG: + * # op_number = debug_helper.write_dis( + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":469 + * _cache[code_obj_py] = cache_value + * + * return breakpoint_found, code_obj_py # <<<<<<<<<<<<<< + * + * import sys + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_11 = __Pyx_PyBool_FromLong(__pyx_v_breakpoint_found); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 469, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_11); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 469, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_11); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_11); + __Pyx_INCREF(__pyx_v_code_obj_py); + __Pyx_GIVEREF(__pyx_v_code_obj_py); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_code_obj_py); + __pyx_t_11 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":407 + * # debug_helper = DebugHelper() + * + * cdef generate_code_with_breakpoints(object code_obj_py, dict breakpoints): # <<<<<<<<<<<<<< + * ''' + * :param breakpoints: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_11); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.generate_code_with_breakpoints", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_cache_value); + __Pyx_XDECREF(__pyx_v_breakpoints_hit_at_lines); + __Pyx_XDECREF(__pyx_v_line_to_offset); + __Pyx_XDECREF(__pyx_v_code_line_info); + __Pyx_XDECREF(__pyx_v_new_code); + __Pyx_XDECREF(__pyx_v_code_obj_py); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":475 + * cdef bint IS_PY_39_OWNARDS = sys.version_info[:2] >= (3, 9) + * + * def frame_eval_func(): # <<<<<<<<<<<<<< + * cdef PyThreadState *state = PyThreadState_Get() + * if IS_PY_39_OWNARDS: + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_17frame_eval_func(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_17frame_eval_func = {"frame_eval_func", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_17frame_eval_func, METH_NOARGS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_17frame_eval_func(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("frame_eval_func (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_16frame_eval_func(__pyx_self); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_16frame_eval_func(CYTHON_UNUSED PyObject *__pyx_self) { + PyThreadState *__pyx_v_state; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("frame_eval_func", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":476 + * + * def frame_eval_func(): + * cdef PyThreadState *state = PyThreadState_Get() # <<<<<<<<<<<<<< + * if IS_PY_39_OWNARDS: + * state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_39 + */ + __pyx_v_state = PyThreadState_Get(); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":477 + * def frame_eval_func(): + * cdef PyThreadState *state = PyThreadState_Get() + * if IS_PY_39_OWNARDS: # <<<<<<<<<<<<<< + * state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_39 + * else: + */ + __pyx_t_1 = (__pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator_IS_PY_39_OWNARDS != 0); + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":478 + * cdef PyThreadState *state = PyThreadState_Get() + * if IS_PY_39_OWNARDS: + * state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_39 # <<<<<<<<<<<<<< + * else: + * state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_38 + */ + __pyx_v_state->interp->eval_frame = ((_PyFrameEvalFunction *)__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_bytecode_while_frame_eval_39); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":477 + * def frame_eval_func(): + * cdef PyThreadState *state = PyThreadState_Get() + * if IS_PY_39_OWNARDS: # <<<<<<<<<<<<<< + * state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_39 + * else: + */ + goto __pyx_L3; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":480 + * state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_39 + * else: + * state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_38 # <<<<<<<<<<<<<< + * dummy_tracing_holder.set_trace_func(dummy_trace_dispatch) + * + */ + /*else*/ { + __pyx_v_state->interp->eval_frame = ((_PyFrameEvalFunction *)__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_bytecode_while_frame_eval_38); + } + __pyx_L3:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":481 + * else: + * state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_38 + * dummy_tracing_holder.set_trace_func(dummy_trace_dispatch) # <<<<<<<<<<<<<< + * + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_dummy_tracing_holder); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 481, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_set_trace_func); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 481, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_dummy_trace_dispatch); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 481, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 481, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":475 + * cdef bint IS_PY_39_OWNARDS = sys.version_info[:2] >= (3, 9) + * + * def frame_eval_func(): # <<<<<<<<<<<<<< + * cdef PyThreadState *state = PyThreadState_Get() + * if IS_PY_39_OWNARDS: + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.frame_eval_func", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":484 + * + * + * def stop_frame_eval(): # <<<<<<<<<<<<<< + * cdef PyThreadState *state = PyThreadState_Get() + * state.interp.eval_frame = _PyEval_EvalFrameDefault + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_19stop_frame_eval(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_19stop_frame_eval = {"stop_frame_eval", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_19stop_frame_eval, METH_NOARGS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_19stop_frame_eval(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("stop_frame_eval (wrapper)", 0); + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_18stop_frame_eval(__pyx_self); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_18stop_frame_eval(CYTHON_UNUSED PyObject *__pyx_self) { + PyThreadState *__pyx_v_state; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("stop_frame_eval", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":485 + * + * def stop_frame_eval(): + * cdef PyThreadState *state = PyThreadState_Get() # <<<<<<<<<<<<<< + * state.interp.eval_frame = _PyEval_EvalFrameDefault + * + */ + __pyx_v_state = PyThreadState_Get(); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":486 + * def stop_frame_eval(): + * cdef PyThreadState *state = PyThreadState_Get() + * state.interp.eval_frame = _PyEval_EvalFrameDefault # <<<<<<<<<<<<<< + * + * # During the build we'll generate 2 versions of the code below so that we're compatible with + */ + __pyx_v_state->interp->eval_frame = _PyEval_EvalFrameDefault; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":484 + * + * + * def stop_frame_eval(): # <<<<<<<<<<<<<< + * cdef PyThreadState *state = PyThreadState_Get() + * state.interp.eval_frame = _PyEval_EvalFrameDefault + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":494 + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * cdef PyObject * get_bytecode_while_frame_eval_38(PyFrameObject * frame_obj, int exc): # <<<<<<<<<<<<<< + * ''' + * This function makes the actual evaluation and changes the bytecode to a version + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_bytecode_while_frame_eval_38(PyFrameObject *__pyx_v_frame_obj, int __pyx_v_exc) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_thread_info = 0; + CYTHON_UNUSED int __pyx_v_STATE_SUSPEND; + int __pyx_v_CMD_STEP_INTO; + int __pyx_v_CMD_STEP_OVER; + int __pyx_v_CMD_STEP_OVER_MY_CODE; + int __pyx_v_CMD_STEP_INTO_MY_CODE; + int __pyx_v_CMD_STEP_INTO_COROUTINE; + int __pyx_v_CMD_SMART_STEP_INTO; + int __pyx_v_can_skip; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_additional_info = 0; + PyObject *__pyx_v_main_debugger = 0; + PyObject *__pyx_v_frame = NULL; + PyObject *__pyx_v_trace_func = NULL; + PyObject *__pyx_v_apply_to_global = NULL; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_func_code_info = 0; + PyObject *__pyx_v_old = NULL; + PyObject *__pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + int __pyx_t_11; + PyObject *(*__pyx_t_12)(PyObject *); + int __pyx_t_13; + char const *__pyx_t_14; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + PyObject *__pyx_t_18; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_bytecode_while_frame_eval_38", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":499 + * where programmatic breakpoints are added. + * ''' + * if GlobalDebuggerHolder is None or _thread_local_info is None or exc: # <<<<<<<<<<<<<< + * # Sometimes during process shutdown these global variables become None + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_GlobalDebuggerHolder); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 499, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = (__pyx_t_2 == Py_None); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_4 = (__pyx_t_3 != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_1 = __pyx_t_4; + goto __pyx_L4_bool_binop_done; + } + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_thread_local_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 499, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = (__pyx_t_2 == Py_None); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_3 = (__pyx_t_4 != 0); + if (!__pyx_t_3) { + } else { + __pyx_t_1 = __pyx_t_3; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_3 = (__pyx_v_exc != 0); + __pyx_t_1 = __pyx_t_3; + __pyx_L4_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":501 + * if GlobalDebuggerHolder is None or _thread_local_info is None or exc: + * # Sometimes during process shutdown these global variables become None + * return CALL_EvalFrameDefault_38(frame_obj, exc) # <<<<<<<<<<<<<< + * + * # co_filename: str = frame_obj.f_code.co_filename + */ + __pyx_r = CALL_EvalFrameDefault_38(__pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":499 + * where programmatic breakpoints are added. + * ''' + * if GlobalDebuggerHolder is None or _thread_local_info is None or exc: # <<<<<<<<<<<<<< + * # Sometimes during process shutdown these global variables become None + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":508 + * + * cdef ThreadInfo thread_info + * cdef int STATE_SUSPEND = 2 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_INTO = 107 + * cdef int CMD_STEP_OVER = 108 + */ + __pyx_v_STATE_SUSPEND = 2; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":509 + * cdef ThreadInfo thread_info + * cdef int STATE_SUSPEND = 2 + * cdef int CMD_STEP_INTO = 107 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_OVER = 108 + * cdef int CMD_STEP_OVER_MY_CODE = 159 + */ + __pyx_v_CMD_STEP_INTO = 0x6B; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":510 + * cdef int STATE_SUSPEND = 2 + * cdef int CMD_STEP_INTO = 107 + * cdef int CMD_STEP_OVER = 108 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_OVER_MY_CODE = 159 + * cdef int CMD_STEP_INTO_MY_CODE = 144 + */ + __pyx_v_CMD_STEP_OVER = 0x6C; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":511 + * cdef int CMD_STEP_INTO = 107 + * cdef int CMD_STEP_OVER = 108 + * cdef int CMD_STEP_OVER_MY_CODE = 159 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_INTO_MY_CODE = 144 + * cdef int CMD_STEP_INTO_COROUTINE = 206 + */ + __pyx_v_CMD_STEP_OVER_MY_CODE = 0x9F; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":512 + * cdef int CMD_STEP_OVER = 108 + * cdef int CMD_STEP_OVER_MY_CODE = 159 + * cdef int CMD_STEP_INTO_MY_CODE = 144 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_INTO_COROUTINE = 206 + * cdef int CMD_SMART_STEP_INTO = 128 + */ + __pyx_v_CMD_STEP_INTO_MY_CODE = 0x90; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":513 + * cdef int CMD_STEP_OVER_MY_CODE = 159 + * cdef int CMD_STEP_INTO_MY_CODE = 144 + * cdef int CMD_STEP_INTO_COROUTINE = 206 # <<<<<<<<<<<<<< + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True + */ + __pyx_v_CMD_STEP_INTO_COROUTINE = 0xCE; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":514 + * cdef int CMD_STEP_INTO_MY_CODE = 144 + * cdef int CMD_STEP_INTO_COROUTINE = 206 + * cdef int CMD_SMART_STEP_INTO = 128 # <<<<<<<<<<<<<< + * cdef bint can_skip = True + * try: + */ + __pyx_v_CMD_SMART_STEP_INTO = 0x80; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":515 + * cdef int CMD_STEP_INTO_COROUTINE = 206 + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True # <<<<<<<<<<<<<< + * try: + * thread_info = _thread_local_info.thread_info + */ + __pyx_v_can_skip = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":516 + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True + * try: # <<<<<<<<<<<<<< + * thread_info = _thread_local_info.thread_info + * except: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_7); + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":517 + * cdef bint can_skip = True + * try: + * thread_info = _thread_local_info.thread_info # <<<<<<<<<<<<<< + * except: + * thread_info = get_thread_info(frame_obj) + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_thread_local_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 517, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_thread_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 517, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!(likely(((__pyx_t_8) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_8, __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo))))) __PYX_ERR(0, 517, __pyx_L7_error) + __pyx_v_thread_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_t_8); + __pyx_t_8 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":516 + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True + * try: # <<<<<<<<<<<<<< + * thread_info = _thread_local_info.thread_info + * except: + */ + } + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L12_try_end; + __pyx_L7_error:; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":518 + * try: + * thread_info = _thread_local_info.thread_info + * except: # <<<<<<<<<<<<<< + * thread_info = get_thread_info(frame_obj) + * if thread_info is None: + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_bytecode_while_frame_eval_38", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_8, &__pyx_t_2, &__pyx_t_9) < 0) __PYX_ERR(0, 518, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GOTREF(__pyx_t_9); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":519 + * thread_info = _thread_local_info.thread_info + * except: + * thread_info = get_thread_info(frame_obj) # <<<<<<<<<<<<<< + * if thread_info is None: + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + __pyx_t_10 = ((PyObject *)__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_thread_info(__pyx_v_frame_obj)); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 519, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_XDECREF_SET(__pyx_v_thread_info, ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_t_10)); + __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":520 + * except: + * thread_info = get_thread_info(frame_obj) + * if thread_info is None: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + */ + __pyx_t_1 = (((PyObject *)__pyx_v_thread_info) == Py_None); + __pyx_t_3 = (__pyx_t_1 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":521 + * thread_info = get_thread_info(frame_obj) + * if thread_info is None: + * return CALL_EvalFrameDefault_38(frame_obj, exc) # <<<<<<<<<<<<<< + * + * if thread_info.inside_frame_eval: + */ + __pyx_r = CALL_EvalFrameDefault_38(__pyx_v_frame_obj, __pyx_v_exc); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L10_except_return; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":520 + * except: + * thread_info = get_thread_info(frame_obj) + * if thread_info is None: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + */ + } + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L8_exception_handled; + } + __pyx_L9_except_error:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":516 + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True + * try: # <<<<<<<<<<<<<< + * thread_info = _thread_local_info.thread_info + * except: + */ + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7); + goto __pyx_L1_error; + __pyx_L10_except_return:; + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7); + goto __pyx_L0; + __pyx_L8_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7); + __pyx_L12_try_end:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":523 + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + * if thread_info.inside_frame_eval: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + */ + __pyx_t_3 = (__pyx_v_thread_info->inside_frame_eval != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":524 + * + * if thread_info.inside_frame_eval: + * return CALL_EvalFrameDefault_38(frame_obj, exc) # <<<<<<<<<<<<<< + * + * if not thread_info.fully_initialized: + */ + __pyx_r = CALL_EvalFrameDefault_38(__pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":523 + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + * if thread_info.inside_frame_eval: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":526 + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + * if not thread_info.fully_initialized: # <<<<<<<<<<<<<< + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: + */ + __pyx_t_3 = ((!(__pyx_v_thread_info->fully_initialized != 0)) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":527 + * + * if not thread_info.fully_initialized: + * thread_info.initialize_if_possible() # <<<<<<<<<<<<<< + * if not thread_info.fully_initialized: + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + __pyx_t_9 = ((struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_thread_info->__pyx_vtab)->initialize_if_possible(__pyx_v_thread_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 527, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":528 + * if not thread_info.fully_initialized: + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + */ + __pyx_t_3 = ((!(__pyx_v_thread_info->fully_initialized != 0)) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":529 + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: + * return CALL_EvalFrameDefault_38(frame_obj, exc) # <<<<<<<<<<<<<< + * + * # Can only get additional_info when fully initialized. + */ + __pyx_r = CALL_EvalFrameDefault_38(__pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":528 + * if not thread_info.fully_initialized: + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":526 + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * + * if not thread_info.fully_initialized: # <<<<<<<<<<<<<< + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":532 + * + * # Can only get additional_info when fully initialized. + * cdef PyDBAdditionalThreadInfo additional_info = thread_info.additional_info # <<<<<<<<<<<<<< + * if thread_info.is_pydevd_thread or additional_info.is_tracing: + * # Make sure that we don't trace pydevd threads or inside our own calls. + */ + __pyx_t_9 = ((PyObject *)__pyx_v_thread_info->additional_info); + __Pyx_INCREF(__pyx_t_9); + __pyx_v_additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_9); + __pyx_t_9 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":533 + * # Can only get additional_info when fully initialized. + * cdef PyDBAdditionalThreadInfo additional_info = thread_info.additional_info + * if thread_info.is_pydevd_thread or additional_info.is_tracing: # <<<<<<<<<<<<<< + * # Make sure that we don't trace pydevd threads or inside our own calls. + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + __pyx_t_1 = (__pyx_v_thread_info->is_pydevd_thread != 0); + if (!__pyx_t_1) { + } else { + __pyx_t_3 = __pyx_t_1; + goto __pyx_L20_bool_binop_done; + } + __pyx_t_1 = (__pyx_v_additional_info->is_tracing != 0); + __pyx_t_3 = __pyx_t_1; + __pyx_L20_bool_binop_done:; + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":535 + * if thread_info.is_pydevd_thread or additional_info.is_tracing: + * # Make sure that we don't trace pydevd threads or inside our own calls. + * return CALL_EvalFrameDefault_38(frame_obj, exc) # <<<<<<<<<<<<<< + * + * # frame = frame_obj + */ + __pyx_r = CALL_EvalFrameDefault_38(__pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":533 + * # Can only get additional_info when fully initialized. + * cdef PyDBAdditionalThreadInfo additional_info = thread_info.additional_info + * if thread_info.is_pydevd_thread or additional_info.is_tracing: # <<<<<<<<<<<<<< + * # Make sure that we don't trace pydevd threads or inside our own calls. + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":542 + * # print('get_bytecode_while_frame_eval', frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename) + * + * thread_info.inside_frame_eval += 1 # <<<<<<<<<<<<<< + * additional_info.is_tracing = True + * try: + */ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval + 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":543 + * + * thread_info.inside_frame_eval += 1 + * additional_info.is_tracing = True # <<<<<<<<<<<<<< + * try: + * main_debugger: object = GlobalDebuggerHolder.global_dbg + */ + __pyx_v_additional_info->is_tracing = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":544 + * thread_info.inside_frame_eval += 1 + * additional_info.is_tracing = True + * try: # <<<<<<<<<<<<<< + * main_debugger: object = GlobalDebuggerHolder.global_dbg + * if main_debugger is None: + */ + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":545 + * additional_info.is_tracing = True + * try: + * main_debugger: object = GlobalDebuggerHolder.global_dbg # <<<<<<<<<<<<<< + * if main_debugger is None: + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_GlobalDebuggerHolder); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 545, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_global_dbg); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 545, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_v_main_debugger = __pyx_t_2; + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":546 + * try: + * main_debugger: object = GlobalDebuggerHolder.global_dbg + * if main_debugger is None: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * frame = frame_obj + */ + __pyx_t_3 = (__pyx_v_main_debugger == Py_None); + __pyx_t_1 = (__pyx_t_3 != 0); + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":547 + * main_debugger: object = GlobalDebuggerHolder.global_dbg + * if main_debugger is None: + * return CALL_EvalFrameDefault_38(frame_obj, exc) # <<<<<<<<<<<<<< + * frame = frame_obj + * + */ + __pyx_r = CALL_EvalFrameDefault_38(__pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L22_return; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":546 + * try: + * main_debugger: object = GlobalDebuggerHolder.global_dbg + * if main_debugger is None: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * frame = frame_obj + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":548 + * if main_debugger is None: + * return CALL_EvalFrameDefault_38(frame_obj, exc) + * frame = frame_obj # <<<<<<<<<<<<<< + * + * if thread_info.thread_trace_func is None: + */ + __pyx_t_2 = ((PyObject *)__pyx_v_frame_obj); + __Pyx_INCREF(__pyx_t_2); + __pyx_v_frame = __pyx_t_2; + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":550 + * frame = frame_obj + * + * if thread_info.thread_trace_func is None: # <<<<<<<<<<<<<< + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: + */ + __pyx_t_1 = (__pyx_v_thread_info->thread_trace_func == Py_None); + __pyx_t_3 = (__pyx_t_1 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":551 + * + * if thread_info.thread_trace_func is None: + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) # <<<<<<<<<<<<<< + * if apply_to_global: + * thread_info.thread_trace_func = trace_func + */ + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_fix_top_level_trace_and_get_trac); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 551, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_9)) { + PyObject *__pyx_temp[3] = {__pyx_t_8, __pyx_v_main_debugger, __pyx_v_frame}; + __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 551, __pyx_L23_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_2); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_9)) { + PyObject *__pyx_temp[3] = {__pyx_t_8, __pyx_v_main_debugger, __pyx_v_frame}; + __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 551, __pyx_L23_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_2); + } else + #endif + { + __pyx_t_10 = PyTuple_New(2+__pyx_t_11); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 551, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + if (__pyx_t_8) { + __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); __pyx_t_8 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_10, 0+__pyx_t_11, __pyx_v_main_debugger); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_10, 1+__pyx_t_11, __pyx_v_frame); + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_10, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 551, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) { + PyObject* sequence = __pyx_t_2; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 551, __pyx_L23_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_9 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_10 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_9 = PyList_GET_ITEM(sequence, 0); + __pyx_t_10 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(__pyx_t_10); + #else + __pyx_t_9 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 551, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 551, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + #endif + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_8 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 551, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_12 = Py_TYPE(__pyx_t_8)->tp_iternext; + index = 0; __pyx_t_9 = __pyx_t_12(__pyx_t_8); if (unlikely(!__pyx_t_9)) goto __pyx_L27_unpacking_failed; + __Pyx_GOTREF(__pyx_t_9); + index = 1; __pyx_t_10 = __pyx_t_12(__pyx_t_8); if (unlikely(!__pyx_t_10)) goto __pyx_L27_unpacking_failed; + __Pyx_GOTREF(__pyx_t_10); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_12(__pyx_t_8), 2) < 0) __PYX_ERR(0, 551, __pyx_L23_error) + __pyx_t_12 = NULL; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L28_unpacking_done; + __pyx_L27_unpacking_failed:; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_12 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 551, __pyx_L23_error) + __pyx_L28_unpacking_done:; + } + __pyx_v_trace_func = __pyx_t_9; + __pyx_t_9 = 0; + __pyx_v_apply_to_global = __pyx_t_10; + __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":552 + * if thread_info.thread_trace_func is None: + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: # <<<<<<<<<<<<<< + * thread_info.thread_trace_func = trace_func + * + */ + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_apply_to_global); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 552, __pyx_L23_error) + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":553 + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: + * thread_info.thread_trace_func = trace_func # <<<<<<<<<<<<<< + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ + */ + __Pyx_INCREF(__pyx_v_trace_func); + __Pyx_GIVEREF(__pyx_v_trace_func); + __Pyx_GOTREF(__pyx_v_thread_info->thread_trace_func); + __Pyx_DECREF(__pyx_v_thread_info->thread_trace_func); + __pyx_v_thread_info->thread_trace_func = __pyx_v_trace_func; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":552 + * if thread_info.thread_trace_func is None: + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: # <<<<<<<<<<<<<< + * thread_info.thread_trace_func = trace_func + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":550 + * frame = frame_obj + * + * if thread_info.thread_trace_func is None: # <<<<<<<<<<<<<< + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":555 + * thread_info.thread_trace_func = trace_func + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ # <<<<<<<<<<<<<< + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ + */ + __pyx_t_11 = __pyx_v_additional_info->pydev_step_cmd; + __pyx_t_4 = ((__pyx_t_11 == __pyx_v_CMD_STEP_INTO) != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_1 = __pyx_t_4; + goto __pyx_L33_bool_binop_done; + } + __pyx_t_4 = ((__pyx_t_11 == __pyx_v_CMD_STEP_INTO_MY_CODE) != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_1 = __pyx_t_4; + goto __pyx_L33_bool_binop_done; + } + __pyx_t_4 = ((__pyx_t_11 == __pyx_v_CMD_STEP_INTO_COROUTINE) != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_1 = __pyx_t_4; + goto __pyx_L33_bool_binop_done; + } + __pyx_t_4 = ((__pyx_t_11 == __pyx_v_CMD_SMART_STEP_INTO) != 0); + __pyx_t_1 = __pyx_t_4; + __pyx_L33_bool_binop_done:; + __pyx_t_4 = (__pyx_t_1 != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":556 + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ + * main_debugger.break_on_caught_exceptions or \ # <<<<<<<<<<<<<< + * main_debugger.break_on_user_uncaught_exceptions or \ + * main_debugger.has_plugin_exception_breaks or \ + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_break_on_caught_exceptions); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 556, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 556, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":557 + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ # <<<<<<<<<<<<<< + * main_debugger.has_plugin_exception_breaks or \ + * main_debugger.signature_factory or \ + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_break_on_user_uncaught_exception); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 557, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 557, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":558 + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ + * main_debugger.has_plugin_exception_breaks or \ # <<<<<<<<<<<<<< + * main_debugger.signature_factory or \ + * additional_info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop: + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_exception_breaks); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 558, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 558, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":559 + * main_debugger.break_on_user_uncaught_exceptions or \ + * main_debugger.has_plugin_exception_breaks or \ + * main_debugger.signature_factory or \ # <<<<<<<<<<<<<< + * additional_info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop: + * + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_signature_factory); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 559, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 559, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":560 + * main_debugger.has_plugin_exception_breaks or \ + * main_debugger.signature_factory or \ + * additional_info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop: # <<<<<<<<<<<<<< + * + * # if DEBUG: + */ + __pyx_t_11 = __pyx_v_additional_info->pydev_step_cmd; + __pyx_t_1 = ((__pyx_t_11 == __pyx_v_CMD_STEP_OVER) != 0); + if (!__pyx_t_1) { + } else { + __pyx_t_4 = __pyx_t_1; + goto __pyx_L42_bool_binop_done; + } + __pyx_t_1 = ((__pyx_t_11 == __pyx_v_CMD_STEP_OVER_MY_CODE) != 0); + __pyx_t_4 = __pyx_t_1; + __pyx_L42_bool_binop_done:; + __pyx_t_1 = (__pyx_t_4 != 0); + if (__pyx_t_1) { + } else { + __pyx_t_3 = __pyx_t_1; + goto __pyx_L31_bool_binop_done; + } + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_show_return_values); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 560, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 560, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__pyx_t_1) { + } else { + __pyx_t_3 = __pyx_t_1; + goto __pyx_L31_bool_binop_done; + } + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 560, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = (__pyx_t_2 == __pyx_v_additional_info->pydev_step_stop); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_4 = (__pyx_t_1 != 0); + __pyx_t_3 = __pyx_t_4; + __pyx_L31_bool_binop_done:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":555 + * thread_info.thread_trace_func = trace_func + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ # <<<<<<<<<<<<<< + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ + */ + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":564 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval enabled trace') + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + __pyx_t_3 = (__pyx_v_thread_info->thread_trace_func != Py_None); + __pyx_t_4 = (__pyx_t_3 != 0); + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":565 + * # print('get_bytecode_while_frame_eval enabled trace') + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func # <<<<<<<<<<<<<< + * else: + * frame.f_trace = main_debugger.trace_dispatch + */ + __pyx_t_2 = __pyx_v_thread_info->thread_trace_func; + __Pyx_INCREF(__pyx_t_2); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_2) < 0) __PYX_ERR(0, 565, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":564 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval enabled trace') + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + goto __pyx_L45; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":567 + * frame.f_trace = thread_info.thread_trace_func + * else: + * frame.f_trace = main_debugger.trace_dispatch # <<<<<<<<<<<<<< + * else: + * func_code_info: FuncCodeInfo = get_func_code_info(thread_info, frame_obj, frame_obj.f_code) + */ + /*else*/ { + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 567, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_10 = __pyx_t_2; + __Pyx_INCREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_10) < 0) __PYX_ERR(0, 567, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __pyx_L45:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":555 + * thread_info.thread_trace_func = trace_func + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ # <<<<<<<<<<<<<< + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ + */ + goto __pyx_L30; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":569 + * frame.f_trace = main_debugger.trace_dispatch + * else: + * func_code_info: FuncCodeInfo = get_func_code_info(thread_info, frame_obj, frame_obj.f_code) # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval always skip', func_code_info.always_skip_code) + */ + /*else*/ { + __pyx_t_10 = ((PyObject *)__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_func_code_info(__pyx_v_thread_info, __pyx_v_frame_obj, __pyx_v_frame_obj->f_code)); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 569, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_v_func_code_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_t_10); + __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":572 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval always skip', func_code_info.always_skip_code) + * if not func_code_info.always_skip_code: # <<<<<<<<<<<<<< + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: + */ + __pyx_t_4 = ((!(__pyx_v_func_code_info->always_skip_code != 0)) != 0); + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":574 + * if not func_code_info.always_skip_code: + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: # <<<<<<<<<<<<<< + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + * + */ + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_line_breaks); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 574, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 574, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (!__pyx_t_3) { + } else { + __pyx_t_4 = __pyx_t_3; + goto __pyx_L48_bool_binop_done; + } + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_exception_breaks); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 574, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 574, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_4 = __pyx_t_3; + __pyx_L48_bool_binop_done:; + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":575 + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) # <<<<<<<<<<<<<< + * + * if not can_skip: + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_plugin); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 575, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_can_skip); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 575, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_9)) { + PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_main_debugger, ((PyObject *)__pyx_v_frame_obj)}; + __pyx_t_10 = __Pyx_PyFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 575, __pyx_L23_error) + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_GOTREF(__pyx_t_10); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_9)) { + PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_main_debugger, ((PyObject *)__pyx_v_frame_obj)}; + __pyx_t_10 = __Pyx_PyCFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 575, __pyx_L23_error) + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_GOTREF(__pyx_t_10); + } else + #endif + { + __pyx_t_8 = PyTuple_New(2+__pyx_t_11); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 575, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_2) { + __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_2); __pyx_t_2 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_11, __pyx_v_main_debugger); + __Pyx_INCREF(((PyObject *)__pyx_v_frame_obj)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_frame_obj)); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_11, ((PyObject *)__pyx_v_frame_obj)); + __pyx_t_10 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_8, NULL); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 575, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 575, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_v_can_skip = __pyx_t_4; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":577 + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + * + * if not can_skip: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval not can_skip') + */ + __pyx_t_4 = ((!(__pyx_v_can_skip != 0)) != 0); + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":580 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval not can_skip') + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + __pyx_t_4 = (__pyx_v_thread_info->thread_trace_func != Py_None); + __pyx_t_3 = (__pyx_t_4 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":581 + * # print('get_bytecode_while_frame_eval not can_skip') + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func # <<<<<<<<<<<<<< + * else: + * frame.f_trace = main_debugger.trace_dispatch + */ + __pyx_t_10 = __pyx_v_thread_info->thread_trace_func; + __Pyx_INCREF(__pyx_t_10); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_10) < 0) __PYX_ERR(0, 581, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":580 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval not can_skip') + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + goto __pyx_L51; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":583 + * frame.f_trace = thread_info.thread_trace_func + * else: + * frame.f_trace = main_debugger.trace_dispatch # <<<<<<<<<<<<<< + * + * if can_skip and func_code_info.breakpoint_found: + */ + /*else*/ { + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 583, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_9 = __pyx_t_10; + __Pyx_INCREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_9) < 0) __PYX_ERR(0, 583, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } + __pyx_L51:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":577 + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + * + * if not can_skip: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval not can_skip') + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":574 + * if not func_code_info.always_skip_code: + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: # <<<<<<<<<<<<<< + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":585 + * frame.f_trace = main_debugger.trace_dispatch + * + * if can_skip and func_code_info.breakpoint_found: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + */ + __pyx_t_4 = (__pyx_v_can_skip != 0); + if (__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L53_bool_binop_done; + } + __pyx_t_4 = (__pyx_v_func_code_info->breakpoint_found != 0); + __pyx_t_3 = __pyx_t_4; + __pyx_L53_bool_binop_done:; + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":588 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + * if not thread_info.force_stay_in_untraced_mode: # <<<<<<<<<<<<<< + * # If breakpoints are found but new_code is None, + * # this means we weren't able to actually add the code + */ + __pyx_t_3 = ((!(__pyx_v_thread_info->force_stay_in_untraced_mode != 0)) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":592 + * # this means we weren't able to actually add the code + * # where needed, so, fallback to tracing. + * if func_code_info.new_code is None: # <<<<<<<<<<<<<< + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func + */ + __pyx_t_3 = (__pyx_v_func_code_info->new_code == Py_None); + __pyx_t_4 = (__pyx_t_3 != 0); + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":593 + * # where needed, so, fallback to tracing. + * if func_code_info.new_code is None: + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + __pyx_t_4 = (__pyx_v_thread_info->thread_trace_func != Py_None); + __pyx_t_3 = (__pyx_t_4 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":594 + * if func_code_info.new_code is None: + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func # <<<<<<<<<<<<<< + * else: + * frame.f_trace = main_debugger.trace_dispatch + */ + __pyx_t_9 = __pyx_v_thread_info->thread_trace_func; + __Pyx_INCREF(__pyx_t_9); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_9) < 0) __PYX_ERR(0, 594, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":593 + * # where needed, so, fallback to tracing. + * if func_code_info.new_code is None: + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + goto __pyx_L57; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":596 + * frame.f_trace = thread_info.thread_trace_func + * else: + * frame.f_trace = main_debugger.trace_dispatch # <<<<<<<<<<<<<< + * else: + * # print('Using frame eval break for', frame_obj.f_code.co_name) + */ + /*else*/ { + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 596, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = __pyx_t_9; + __Pyx_INCREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_10) < 0) __PYX_ERR(0, 596, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __pyx_L57:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":592 + * # this means we weren't able to actually add the code + * # where needed, so, fallback to tracing. + * if func_code_info.new_code is None: # <<<<<<<<<<<<<< + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func + */ + goto __pyx_L56; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":599 + * else: + * # print('Using frame eval break for', frame_obj.f_code.co_name) + * update_globals_dict( frame_obj.f_globals) # <<<<<<<<<<<<<< + * Py_INCREF(func_code_info.new_code) + * old = frame_obj.f_code + */ + /*else*/ { + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_update_globals_dict); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 599, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + } + } + __pyx_t_10 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_9, __pyx_t_8, ((PyObject *)__pyx_v_frame_obj->f_globals)) : __Pyx_PyObject_CallOneArg(__pyx_t_9, ((PyObject *)__pyx_v_frame_obj->f_globals)); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 599, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":600 + * # print('Using frame eval break for', frame_obj.f_code.co_name) + * update_globals_dict( frame_obj.f_globals) + * Py_INCREF(func_code_info.new_code) # <<<<<<<<<<<<<< + * old = frame_obj.f_code + * frame_obj.f_code = func_code_info.new_code + */ + __pyx_t_10 = __pyx_v_func_code_info->new_code; + __Pyx_INCREF(__pyx_t_10); + Py_INCREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":601 + * update_globals_dict( frame_obj.f_globals) + * Py_INCREF(func_code_info.new_code) + * old = frame_obj.f_code # <<<<<<<<<<<<<< + * frame_obj.f_code = func_code_info.new_code + * Py_DECREF(old) + */ + __pyx_t_10 = ((PyObject *)__pyx_v_frame_obj->f_code); + __Pyx_INCREF(__pyx_t_10); + __pyx_v_old = __pyx_t_10; + __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":602 + * Py_INCREF(func_code_info.new_code) + * old = frame_obj.f_code + * frame_obj.f_code = func_code_info.new_code # <<<<<<<<<<<<<< + * Py_DECREF(old) + * else: + */ + __pyx_v_frame_obj->f_code = ((PyCodeObject *)__pyx_v_func_code_info->new_code); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":603 + * old = frame_obj.f_code + * frame_obj.f_code = func_code_info.new_code + * Py_DECREF(old) # <<<<<<<<<<<<<< + * else: + * # When we're forcing to stay in traced mode we need to + */ + Py_DECREF(__pyx_v_old); + } + __pyx_L56:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":588 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + * if not thread_info.force_stay_in_untraced_mode: # <<<<<<<<<<<<<< + * # If breakpoints are found but new_code is None, + * # this means we weren't able to actually add the code + */ + goto __pyx_L55; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":608 + * # update the globals dict (because this means that we're reusing + * # a previous code which had breakpoints added in a new frame). + * update_globals_dict( frame_obj.f_globals) # <<<<<<<<<<<<<< + * + * finally: + */ + /*else*/ { + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_update_globals_dict); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 608, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + } + } + __pyx_t_10 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_9, __pyx_t_8, ((PyObject *)__pyx_v_frame_obj->f_globals)) : __Pyx_PyObject_CallOneArg(__pyx_t_9, ((PyObject *)__pyx_v_frame_obj->f_globals)); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 608, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __pyx_L55:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":585 + * frame.f_trace = main_debugger.trace_dispatch + * + * if can_skip and func_code_info.breakpoint_found: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":572 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval always skip', func_code_info.always_skip_code) + * if not func_code_info.always_skip_code: # <<<<<<<<<<<<<< + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: + */ + } + } + __pyx_L30:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":611 + * + * finally: + * thread_info.inside_frame_eval -= 1 # <<<<<<<<<<<<<< + * additional_info.is_tracing = False + * + */ + /*finally:*/ { + /*normal exit:*/{ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval - 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":612 + * finally: + * thread_info.inside_frame_eval -= 1 + * additional_info.is_tracing = False # <<<<<<<<<<<<<< + * + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + __pyx_v_additional_info->is_tracing = 0; + goto __pyx_L24; + } + __pyx_L23_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_7 = 0; __pyx_t_6 = 0; __pyx_t_5 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_7, &__pyx_t_6, &__pyx_t_5) < 0)) __Pyx_ErrFetch(&__pyx_t_7, &__pyx_t_6, &__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __pyx_t_11 = __pyx_lineno; __pyx_t_13 = __pyx_clineno; __pyx_t_14 = __pyx_filename; + { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":611 + * + * finally: + * thread_info.inside_frame_eval -= 1 # <<<<<<<<<<<<<< + * additional_info.is_tracing = False + * + */ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval - 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":612 + * finally: + * thread_info.inside_frame_eval -= 1 + * additional_info.is_tracing = False # <<<<<<<<<<<<<< + * + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + __pyx_v_additional_info->is_tracing = 0; + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_ExceptionReset(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_ErrRestore(__pyx_t_7, __pyx_t_6, __pyx_t_5); + __pyx_t_7 = 0; __pyx_t_6 = 0; __pyx_t_5 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __pyx_lineno = __pyx_t_11; __pyx_clineno = __pyx_t_13; __pyx_filename = __pyx_t_14; + goto __pyx_L1_error; + } + __pyx_L22_return: { + __pyx_t_18 = __pyx_r; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":611 + * + * finally: + * thread_info.inside_frame_eval -= 1 # <<<<<<<<<<<<<< + * additional_info.is_tracing = False + * + */ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval - 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":612 + * finally: + * thread_info.inside_frame_eval -= 1 + * additional_info.is_tracing = False # <<<<<<<<<<<<<< + * + * return CALL_EvalFrameDefault_38(frame_obj, exc) + */ + __pyx_v_additional_info->is_tracing = 0; + __pyx_r = __pyx_t_18; + goto __pyx_L0; + } + __pyx_L24:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":614 + * additional_info.is_tracing = False + * + * return CALL_EvalFrameDefault_38(frame_obj, exc) # <<<<<<<<<<<<<< + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * ### WARNING: GENERATED CODE, DO NOT EDIT! + */ + __pyx_r = CALL_EvalFrameDefault_38(__pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":494 + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * cdef PyObject * get_bytecode_while_frame_eval_38(PyFrameObject * frame_obj, int exc): # <<<<<<<<<<<<<< + * ''' + * This function makes the actual evaluation and changes the bytecode to a version + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_WriteUnraisable("_pydevd_frame_eval.pydevd_frame_evaluator.get_bytecode_while_frame_eval_38", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_thread_info); + __Pyx_XDECREF((PyObject *)__pyx_v_additional_info); + __Pyx_XDECREF(__pyx_v_main_debugger); + __Pyx_XDECREF(__pyx_v_frame); + __Pyx_XDECREF(__pyx_v_trace_func); + __Pyx_XDECREF(__pyx_v_apply_to_global); + __Pyx_XDECREF((PyObject *)__pyx_v_func_code_info); + __Pyx_XDECREF(__pyx_v_old); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":623 + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * cdef PyObject * get_bytecode_while_frame_eval_39(PyThreadState* tstate, PyFrameObject * frame_obj, int exc): # <<<<<<<<<<<<<< + * ''' + * This function makes the actual evaluation and changes the bytecode to a version + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_bytecode_while_frame_eval_39(PyThreadState *__pyx_v_tstate, PyFrameObject *__pyx_v_frame_obj, int __pyx_v_exc) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v_thread_info = 0; + CYTHON_UNUSED int __pyx_v_STATE_SUSPEND; + int __pyx_v_CMD_STEP_INTO; + int __pyx_v_CMD_STEP_OVER; + int __pyx_v_CMD_STEP_OVER_MY_CODE; + int __pyx_v_CMD_STEP_INTO_MY_CODE; + int __pyx_v_CMD_STEP_INTO_COROUTINE; + int __pyx_v_CMD_SMART_STEP_INTO; + int __pyx_v_can_skip; + struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *__pyx_v_additional_info = 0; + PyObject *__pyx_v_main_debugger = 0; + PyObject *__pyx_v_frame = NULL; + PyObject *__pyx_v_trace_func = NULL; + PyObject *__pyx_v_apply_to_global = NULL; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v_func_code_info = 0; + PyObject *__pyx_v_old = NULL; + PyObject *__pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + int __pyx_t_11; + PyObject *(*__pyx_t_12)(PyObject *); + int __pyx_t_13; + char const *__pyx_t_14; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + PyObject *__pyx_t_18; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_bytecode_while_frame_eval_39", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":628 + * where programmatic breakpoints are added. + * ''' + * if GlobalDebuggerHolder is None or _thread_local_info is None or exc: # <<<<<<<<<<<<<< + * # Sometimes during process shutdown these global variables become None + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_GlobalDebuggerHolder); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 628, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = (__pyx_t_2 == Py_None); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_4 = (__pyx_t_3 != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_1 = __pyx_t_4; + goto __pyx_L4_bool_binop_done; + } + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_thread_local_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 628, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = (__pyx_t_2 == Py_None); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_3 = (__pyx_t_4 != 0); + if (!__pyx_t_3) { + } else { + __pyx_t_1 = __pyx_t_3; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_3 = (__pyx_v_exc != 0); + __pyx_t_1 = __pyx_t_3; + __pyx_L4_bool_binop_done:; + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":630 + * if GlobalDebuggerHolder is None or _thread_local_info is None or exc: + * # Sometimes during process shutdown these global variables become None + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) # <<<<<<<<<<<<<< + * + * # co_filename: str = frame_obj.f_code.co_filename + */ + __pyx_r = CALL_EvalFrameDefault_39(__pyx_v_tstate, __pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":628 + * where programmatic breakpoints are added. + * ''' + * if GlobalDebuggerHolder is None or _thread_local_info is None or exc: # <<<<<<<<<<<<<< + * # Sometimes during process shutdown these global variables become None + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":637 + * + * cdef ThreadInfo thread_info + * cdef int STATE_SUSPEND = 2 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_INTO = 107 + * cdef int CMD_STEP_OVER = 108 + */ + __pyx_v_STATE_SUSPEND = 2; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":638 + * cdef ThreadInfo thread_info + * cdef int STATE_SUSPEND = 2 + * cdef int CMD_STEP_INTO = 107 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_OVER = 108 + * cdef int CMD_STEP_OVER_MY_CODE = 159 + */ + __pyx_v_CMD_STEP_INTO = 0x6B; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":639 + * cdef int STATE_SUSPEND = 2 + * cdef int CMD_STEP_INTO = 107 + * cdef int CMD_STEP_OVER = 108 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_OVER_MY_CODE = 159 + * cdef int CMD_STEP_INTO_MY_CODE = 144 + */ + __pyx_v_CMD_STEP_OVER = 0x6C; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":640 + * cdef int CMD_STEP_INTO = 107 + * cdef int CMD_STEP_OVER = 108 + * cdef int CMD_STEP_OVER_MY_CODE = 159 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_INTO_MY_CODE = 144 + * cdef int CMD_STEP_INTO_COROUTINE = 206 + */ + __pyx_v_CMD_STEP_OVER_MY_CODE = 0x9F; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":641 + * cdef int CMD_STEP_OVER = 108 + * cdef int CMD_STEP_OVER_MY_CODE = 159 + * cdef int CMD_STEP_INTO_MY_CODE = 144 # <<<<<<<<<<<<<< + * cdef int CMD_STEP_INTO_COROUTINE = 206 + * cdef int CMD_SMART_STEP_INTO = 128 + */ + __pyx_v_CMD_STEP_INTO_MY_CODE = 0x90; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":642 + * cdef int CMD_STEP_OVER_MY_CODE = 159 + * cdef int CMD_STEP_INTO_MY_CODE = 144 + * cdef int CMD_STEP_INTO_COROUTINE = 206 # <<<<<<<<<<<<<< + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True + */ + __pyx_v_CMD_STEP_INTO_COROUTINE = 0xCE; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":643 + * cdef int CMD_STEP_INTO_MY_CODE = 144 + * cdef int CMD_STEP_INTO_COROUTINE = 206 + * cdef int CMD_SMART_STEP_INTO = 128 # <<<<<<<<<<<<<< + * cdef bint can_skip = True + * try: + */ + __pyx_v_CMD_SMART_STEP_INTO = 0x80; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":644 + * cdef int CMD_STEP_INTO_COROUTINE = 206 + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True # <<<<<<<<<<<<<< + * try: + * thread_info = _thread_local_info.thread_info + */ + __pyx_v_can_skip = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":645 + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True + * try: # <<<<<<<<<<<<<< + * thread_info = _thread_local_info.thread_info + * except: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_7); + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":646 + * cdef bint can_skip = True + * try: + * thread_info = _thread_local_info.thread_info # <<<<<<<<<<<<<< + * except: + * thread_info = get_thread_info(frame_obj) + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_thread_local_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 646, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_thread_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 646, __pyx_L7_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!(likely(((__pyx_t_8) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_8, __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo))))) __PYX_ERR(0, 646, __pyx_L7_error) + __pyx_v_thread_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_t_8); + __pyx_t_8 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":645 + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True + * try: # <<<<<<<<<<<<<< + * thread_info = _thread_local_info.thread_info + * except: + */ + } + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L12_try_end; + __pyx_L7_error:; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":647 + * try: + * thread_info = _thread_local_info.thread_info + * except: # <<<<<<<<<<<<<< + * thread_info = get_thread_info(frame_obj) + * if thread_info is None: + */ + /*except:*/ { + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.get_bytecode_while_frame_eval_39", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_8, &__pyx_t_2, &__pyx_t_9) < 0) __PYX_ERR(0, 647, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GOTREF(__pyx_t_9); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":648 + * thread_info = _thread_local_info.thread_info + * except: + * thread_info = get_thread_info(frame_obj) # <<<<<<<<<<<<<< + * if thread_info is None: + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + __pyx_t_10 = ((PyObject *)__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_thread_info(__pyx_v_frame_obj)); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 648, __pyx_L9_except_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_XDECREF_SET(__pyx_v_thread_info, ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_t_10)); + __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":649 + * except: + * thread_info = get_thread_info(frame_obj) + * if thread_info is None: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + */ + __pyx_t_1 = (((PyObject *)__pyx_v_thread_info) == Py_None); + __pyx_t_3 = (__pyx_t_1 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":650 + * thread_info = get_thread_info(frame_obj) + * if thread_info is None: + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) # <<<<<<<<<<<<<< + * + * if thread_info.inside_frame_eval: + */ + __pyx_r = CALL_EvalFrameDefault_39(__pyx_v_tstate, __pyx_v_frame_obj, __pyx_v_exc); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L10_except_return; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":649 + * except: + * thread_info = get_thread_info(frame_obj) + * if thread_info is None: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + */ + } + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + goto __pyx_L8_exception_handled; + } + __pyx_L9_except_error:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":645 + * cdef int CMD_SMART_STEP_INTO = 128 + * cdef bint can_skip = True + * try: # <<<<<<<<<<<<<< + * thread_info = _thread_local_info.thread_info + * except: + */ + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7); + goto __pyx_L1_error; + __pyx_L10_except_return:; + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7); + goto __pyx_L0; + __pyx_L8_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7); + __pyx_L12_try_end:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":652 + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + * if thread_info.inside_frame_eval: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + */ + __pyx_t_3 = (__pyx_v_thread_info->inside_frame_eval != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":653 + * + * if thread_info.inside_frame_eval: + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) # <<<<<<<<<<<<<< + * + * if not thread_info.fully_initialized: + */ + __pyx_r = CALL_EvalFrameDefault_39(__pyx_v_tstate, __pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":652 + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + * if thread_info.inside_frame_eval: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":655 + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + * if not thread_info.fully_initialized: # <<<<<<<<<<<<<< + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: + */ + __pyx_t_3 = ((!(__pyx_v_thread_info->fully_initialized != 0)) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":656 + * + * if not thread_info.fully_initialized: + * thread_info.initialize_if_possible() # <<<<<<<<<<<<<< + * if not thread_info.fully_initialized: + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + __pyx_t_9 = ((struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v_thread_info->__pyx_vtab)->initialize_if_possible(__pyx_v_thread_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 656, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":657 + * if not thread_info.fully_initialized: + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + */ + __pyx_t_3 = ((!(__pyx_v_thread_info->fully_initialized != 0)) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":658 + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) # <<<<<<<<<<<<<< + * + * # Can only get additional_info when fully initialized. + */ + __pyx_r = CALL_EvalFrameDefault_39(__pyx_v_tstate, __pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":657 + * if not thread_info.fully_initialized: + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":655 + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * + * if not thread_info.fully_initialized: # <<<<<<<<<<<<<< + * thread_info.initialize_if_possible() + * if not thread_info.fully_initialized: + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":661 + * + * # Can only get additional_info when fully initialized. + * cdef PyDBAdditionalThreadInfo additional_info = thread_info.additional_info # <<<<<<<<<<<<<< + * if thread_info.is_pydevd_thread or additional_info.is_tracing: + * # Make sure that we don't trace pydevd threads or inside our own calls. + */ + __pyx_t_9 = ((PyObject *)__pyx_v_thread_info->additional_info); + __Pyx_INCREF(__pyx_t_9); + __pyx_v_additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_9); + __pyx_t_9 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":662 + * # Can only get additional_info when fully initialized. + * cdef PyDBAdditionalThreadInfo additional_info = thread_info.additional_info + * if thread_info.is_pydevd_thread or additional_info.is_tracing: # <<<<<<<<<<<<<< + * # Make sure that we don't trace pydevd threads or inside our own calls. + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + __pyx_t_1 = (__pyx_v_thread_info->is_pydevd_thread != 0); + if (!__pyx_t_1) { + } else { + __pyx_t_3 = __pyx_t_1; + goto __pyx_L20_bool_binop_done; + } + __pyx_t_1 = (__pyx_v_additional_info->is_tracing != 0); + __pyx_t_3 = __pyx_t_1; + __pyx_L20_bool_binop_done:; + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":664 + * if thread_info.is_pydevd_thread or additional_info.is_tracing: + * # Make sure that we don't trace pydevd threads or inside our own calls. + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) # <<<<<<<<<<<<<< + * + * # frame = frame_obj + */ + __pyx_r = CALL_EvalFrameDefault_39(__pyx_v_tstate, __pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":662 + * # Can only get additional_info when fully initialized. + * cdef PyDBAdditionalThreadInfo additional_info = thread_info.additional_info + * if thread_info.is_pydevd_thread or additional_info.is_tracing: # <<<<<<<<<<<<<< + * # Make sure that we don't trace pydevd threads or inside our own calls. + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":671 + * # print('get_bytecode_while_frame_eval', frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename) + * + * thread_info.inside_frame_eval += 1 # <<<<<<<<<<<<<< + * additional_info.is_tracing = True + * try: + */ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval + 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":672 + * + * thread_info.inside_frame_eval += 1 + * additional_info.is_tracing = True # <<<<<<<<<<<<<< + * try: + * main_debugger: object = GlobalDebuggerHolder.global_dbg + */ + __pyx_v_additional_info->is_tracing = 1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":673 + * thread_info.inside_frame_eval += 1 + * additional_info.is_tracing = True + * try: # <<<<<<<<<<<<<< + * main_debugger: object = GlobalDebuggerHolder.global_dbg + * if main_debugger is None: + */ + /*try:*/ { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":674 + * additional_info.is_tracing = True + * try: + * main_debugger: object = GlobalDebuggerHolder.global_dbg # <<<<<<<<<<<<<< + * if main_debugger is None: + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_GlobalDebuggerHolder); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 674, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_global_dbg); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 674, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_v_main_debugger = __pyx_t_2; + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":675 + * try: + * main_debugger: object = GlobalDebuggerHolder.global_dbg + * if main_debugger is None: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * frame = frame_obj + */ + __pyx_t_3 = (__pyx_v_main_debugger == Py_None); + __pyx_t_1 = (__pyx_t_3 != 0); + if (__pyx_t_1) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":676 + * main_debugger: object = GlobalDebuggerHolder.global_dbg + * if main_debugger is None: + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) # <<<<<<<<<<<<<< + * frame = frame_obj + * + */ + __pyx_r = CALL_EvalFrameDefault_39(__pyx_v_tstate, __pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L22_return; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":675 + * try: + * main_debugger: object = GlobalDebuggerHolder.global_dbg + * if main_debugger is None: # <<<<<<<<<<<<<< + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * frame = frame_obj + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":677 + * if main_debugger is None: + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + * frame = frame_obj # <<<<<<<<<<<<<< + * + * if thread_info.thread_trace_func is None: + */ + __pyx_t_2 = ((PyObject *)__pyx_v_frame_obj); + __Pyx_INCREF(__pyx_t_2); + __pyx_v_frame = __pyx_t_2; + __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":679 + * frame = frame_obj + * + * if thread_info.thread_trace_func is None: # <<<<<<<<<<<<<< + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: + */ + __pyx_t_1 = (__pyx_v_thread_info->thread_trace_func == Py_None); + __pyx_t_3 = (__pyx_t_1 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":680 + * + * if thread_info.thread_trace_func is None: + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) # <<<<<<<<<<<<<< + * if apply_to_global: + * thread_info.thread_trace_func = trace_func + */ + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_fix_top_level_trace_and_get_trac); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 680, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_9)) { + PyObject *__pyx_temp[3] = {__pyx_t_8, __pyx_v_main_debugger, __pyx_v_frame}; + __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 680, __pyx_L23_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_2); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_9)) { + PyObject *__pyx_temp[3] = {__pyx_t_8, __pyx_v_main_debugger, __pyx_v_frame}; + __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 680, __pyx_L23_error) + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_GOTREF(__pyx_t_2); + } else + #endif + { + __pyx_t_10 = PyTuple_New(2+__pyx_t_11); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 680, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + if (__pyx_t_8) { + __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); __pyx_t_8 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_10, 0+__pyx_t_11, __pyx_v_main_debugger); + __Pyx_INCREF(__pyx_v_frame); + __Pyx_GIVEREF(__pyx_v_frame); + PyTuple_SET_ITEM(__pyx_t_10, 1+__pyx_t_11, __pyx_v_frame); + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_10, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 680, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) { + PyObject* sequence = __pyx_t_2; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 680, __pyx_L23_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_9 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_10 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_9 = PyList_GET_ITEM(sequence, 0); + __pyx_t_10 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(__pyx_t_10); + #else + __pyx_t_9 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 680, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 680, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + #endif + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_8 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 680, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_12 = Py_TYPE(__pyx_t_8)->tp_iternext; + index = 0; __pyx_t_9 = __pyx_t_12(__pyx_t_8); if (unlikely(!__pyx_t_9)) goto __pyx_L27_unpacking_failed; + __Pyx_GOTREF(__pyx_t_9); + index = 1; __pyx_t_10 = __pyx_t_12(__pyx_t_8); if (unlikely(!__pyx_t_10)) goto __pyx_L27_unpacking_failed; + __Pyx_GOTREF(__pyx_t_10); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_12(__pyx_t_8), 2) < 0) __PYX_ERR(0, 680, __pyx_L23_error) + __pyx_t_12 = NULL; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L28_unpacking_done; + __pyx_L27_unpacking_failed:; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_12 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 680, __pyx_L23_error) + __pyx_L28_unpacking_done:; + } + __pyx_v_trace_func = __pyx_t_9; + __pyx_t_9 = 0; + __pyx_v_apply_to_global = __pyx_t_10; + __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":681 + * if thread_info.thread_trace_func is None: + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: # <<<<<<<<<<<<<< + * thread_info.thread_trace_func = trace_func + * + */ + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_apply_to_global); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 681, __pyx_L23_error) + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":682 + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: + * thread_info.thread_trace_func = trace_func # <<<<<<<<<<<<<< + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ + */ + __Pyx_INCREF(__pyx_v_trace_func); + __Pyx_GIVEREF(__pyx_v_trace_func); + __Pyx_GOTREF(__pyx_v_thread_info->thread_trace_func); + __Pyx_DECREF(__pyx_v_thread_info->thread_trace_func); + __pyx_v_thread_info->thread_trace_func = __pyx_v_trace_func; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":681 + * if thread_info.thread_trace_func is None: + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: # <<<<<<<<<<<<<< + * thread_info.thread_trace_func = trace_func + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":679 + * frame = frame_obj + * + * if thread_info.thread_trace_func is None: # <<<<<<<<<<<<<< + * trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + * if apply_to_global: + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":684 + * thread_info.thread_trace_func = trace_func + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ # <<<<<<<<<<<<<< + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ + */ + __pyx_t_11 = __pyx_v_additional_info->pydev_step_cmd; + __pyx_t_4 = ((__pyx_t_11 == __pyx_v_CMD_STEP_INTO) != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_1 = __pyx_t_4; + goto __pyx_L33_bool_binop_done; + } + __pyx_t_4 = ((__pyx_t_11 == __pyx_v_CMD_STEP_INTO_MY_CODE) != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_1 = __pyx_t_4; + goto __pyx_L33_bool_binop_done; + } + __pyx_t_4 = ((__pyx_t_11 == __pyx_v_CMD_STEP_INTO_COROUTINE) != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_1 = __pyx_t_4; + goto __pyx_L33_bool_binop_done; + } + __pyx_t_4 = ((__pyx_t_11 == __pyx_v_CMD_SMART_STEP_INTO) != 0); + __pyx_t_1 = __pyx_t_4; + __pyx_L33_bool_binop_done:; + __pyx_t_4 = (__pyx_t_1 != 0); + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":685 + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ + * main_debugger.break_on_caught_exceptions or \ # <<<<<<<<<<<<<< + * main_debugger.break_on_user_uncaught_exceptions or \ + * main_debugger.has_plugin_exception_breaks or \ + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_break_on_caught_exceptions); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 685, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 685, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":686 + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ # <<<<<<<<<<<<<< + * main_debugger.has_plugin_exception_breaks or \ + * main_debugger.signature_factory or \ + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_break_on_user_uncaught_exception); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 686, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 686, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":687 + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ + * main_debugger.has_plugin_exception_breaks or \ # <<<<<<<<<<<<<< + * main_debugger.signature_factory or \ + * additional_info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop: + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_exception_breaks); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 687, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 687, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":688 + * main_debugger.break_on_user_uncaught_exceptions or \ + * main_debugger.has_plugin_exception_breaks or \ + * main_debugger.signature_factory or \ # <<<<<<<<<<<<<< + * additional_info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop: + * + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_signature_factory); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 688, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 688, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (!__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L31_bool_binop_done; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":689 + * main_debugger.has_plugin_exception_breaks or \ + * main_debugger.signature_factory or \ + * additional_info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop: # <<<<<<<<<<<<<< + * + * # if DEBUG: + */ + __pyx_t_11 = __pyx_v_additional_info->pydev_step_cmd; + __pyx_t_1 = ((__pyx_t_11 == __pyx_v_CMD_STEP_OVER) != 0); + if (!__pyx_t_1) { + } else { + __pyx_t_4 = __pyx_t_1; + goto __pyx_L42_bool_binop_done; + } + __pyx_t_1 = ((__pyx_t_11 == __pyx_v_CMD_STEP_OVER_MY_CODE) != 0); + __pyx_t_4 = __pyx_t_1; + __pyx_L42_bool_binop_done:; + __pyx_t_1 = (__pyx_t_4 != 0); + if (__pyx_t_1) { + } else { + __pyx_t_3 = __pyx_t_1; + goto __pyx_L31_bool_binop_done; + } + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_show_return_values); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 689, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 689, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__pyx_t_1) { + } else { + __pyx_t_3 = __pyx_t_1; + goto __pyx_L31_bool_binop_done; + } + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_frame, __pyx_n_s_f_back); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 689, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = (__pyx_t_2 == __pyx_v_additional_info->pydev_step_stop); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_4 = (__pyx_t_1 != 0); + __pyx_t_3 = __pyx_t_4; + __pyx_L31_bool_binop_done:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":684 + * thread_info.thread_trace_func = trace_func + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ # <<<<<<<<<<<<<< + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ + */ + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":693 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval enabled trace') + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + __pyx_t_3 = (__pyx_v_thread_info->thread_trace_func != Py_None); + __pyx_t_4 = (__pyx_t_3 != 0); + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":694 + * # print('get_bytecode_while_frame_eval enabled trace') + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func # <<<<<<<<<<<<<< + * else: + * frame.f_trace = main_debugger.trace_dispatch + */ + __pyx_t_2 = __pyx_v_thread_info->thread_trace_func; + __Pyx_INCREF(__pyx_t_2); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_2) < 0) __PYX_ERR(0, 694, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":693 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval enabled trace') + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + goto __pyx_L45; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":696 + * frame.f_trace = thread_info.thread_trace_func + * else: + * frame.f_trace = main_debugger.trace_dispatch # <<<<<<<<<<<<<< + * else: + * func_code_info: FuncCodeInfo = get_func_code_info(thread_info, frame_obj, frame_obj.f_code) + */ + /*else*/ { + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 696, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_10 = __pyx_t_2; + __Pyx_INCREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_10) < 0) __PYX_ERR(0, 696, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __pyx_L45:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":684 + * thread_info.thread_trace_func = trace_func + * + * if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ # <<<<<<<<<<<<<< + * main_debugger.break_on_caught_exceptions or \ + * main_debugger.break_on_user_uncaught_exceptions or \ + */ + goto __pyx_L30; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":698 + * frame.f_trace = main_debugger.trace_dispatch + * else: + * func_code_info: FuncCodeInfo = get_func_code_info(thread_info, frame_obj, frame_obj.f_code) # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval always skip', func_code_info.always_skip_code) + */ + /*else*/ { + __pyx_t_10 = ((PyObject *)__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_get_func_code_info(__pyx_v_thread_info, __pyx_v_frame_obj, __pyx_v_frame_obj->f_code)); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 698, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_v_func_code_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_t_10); + __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":701 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval always skip', func_code_info.always_skip_code) + * if not func_code_info.always_skip_code: # <<<<<<<<<<<<<< + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: + */ + __pyx_t_4 = ((!(__pyx_v_func_code_info->always_skip_code != 0)) != 0); + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":703 + * if not func_code_info.always_skip_code: + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: # <<<<<<<<<<<<<< + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + * + */ + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_line_breaks); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 703, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 703, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (!__pyx_t_3) { + } else { + __pyx_t_4 = __pyx_t_3; + goto __pyx_L48_bool_binop_done; + } + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_has_plugin_exception_breaks); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 703, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 703, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_4 = __pyx_t_3; + __pyx_L48_bool_binop_done:; + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":704 + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) # <<<<<<<<<<<<<< + * + * if not can_skip: + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_plugin); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 704, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_can_skip); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 704, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = NULL; + __pyx_t_11 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + __pyx_t_11 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_9)) { + PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_main_debugger, ((PyObject *)__pyx_v_frame_obj)}; + __pyx_t_10 = __Pyx_PyFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 704, __pyx_L23_error) + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_GOTREF(__pyx_t_10); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_9)) { + PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_main_debugger, ((PyObject *)__pyx_v_frame_obj)}; + __pyx_t_10 = __Pyx_PyCFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_11, 2+__pyx_t_11); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 704, __pyx_L23_error) + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_GOTREF(__pyx_t_10); + } else + #endif + { + __pyx_t_8 = PyTuple_New(2+__pyx_t_11); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 704, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_2) { + __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_2); __pyx_t_2 = NULL; + } + __Pyx_INCREF(__pyx_v_main_debugger); + __Pyx_GIVEREF(__pyx_v_main_debugger); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_11, __pyx_v_main_debugger); + __Pyx_INCREF(((PyObject *)__pyx_v_frame_obj)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_frame_obj)); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_11, ((PyObject *)__pyx_v_frame_obj)); + __pyx_t_10 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_8, NULL); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 704, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 704, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_v_can_skip = __pyx_t_4; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":706 + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + * + * if not can_skip: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval not can_skip') + */ + __pyx_t_4 = ((!(__pyx_v_can_skip != 0)) != 0); + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":709 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval not can_skip') + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + __pyx_t_4 = (__pyx_v_thread_info->thread_trace_func != Py_None); + __pyx_t_3 = (__pyx_t_4 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":710 + * # print('get_bytecode_while_frame_eval not can_skip') + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func # <<<<<<<<<<<<<< + * else: + * frame.f_trace = main_debugger.trace_dispatch + */ + __pyx_t_10 = __pyx_v_thread_info->thread_trace_func; + __Pyx_INCREF(__pyx_t_10); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_10) < 0) __PYX_ERR(0, 710, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":709 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval not can_skip') + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + goto __pyx_L51; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":712 + * frame.f_trace = thread_info.thread_trace_func + * else: + * frame.f_trace = main_debugger.trace_dispatch # <<<<<<<<<<<<<< + * + * if can_skip and func_code_info.breakpoint_found: + */ + /*else*/ { + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 712, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_9 = __pyx_t_10; + __Pyx_INCREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_9) < 0) __PYX_ERR(0, 712, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } + __pyx_L51:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":706 + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + * + * if not can_skip: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval not can_skip') + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":703 + * if not func_code_info.always_skip_code: + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: # <<<<<<<<<<<<<< + * can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + * + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":714 + * frame.f_trace = main_debugger.trace_dispatch + * + * if can_skip and func_code_info.breakpoint_found: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + */ + __pyx_t_4 = (__pyx_v_can_skip != 0); + if (__pyx_t_4) { + } else { + __pyx_t_3 = __pyx_t_4; + goto __pyx_L53_bool_binop_done; + } + __pyx_t_4 = (__pyx_v_func_code_info->breakpoint_found != 0); + __pyx_t_3 = __pyx_t_4; + __pyx_L53_bool_binop_done:; + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":717 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + * if not thread_info.force_stay_in_untraced_mode: # <<<<<<<<<<<<<< + * # If breakpoints are found but new_code is None, + * # this means we weren't able to actually add the code + */ + __pyx_t_3 = ((!(__pyx_v_thread_info->force_stay_in_untraced_mode != 0)) != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":721 + * # this means we weren't able to actually add the code + * # where needed, so, fallback to tracing. + * if func_code_info.new_code is None: # <<<<<<<<<<<<<< + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func + */ + __pyx_t_3 = (__pyx_v_func_code_info->new_code == Py_None); + __pyx_t_4 = (__pyx_t_3 != 0); + if (__pyx_t_4) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":722 + * # where needed, so, fallback to tracing. + * if func_code_info.new_code is None: + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + __pyx_t_4 = (__pyx_v_thread_info->thread_trace_func != Py_None); + __pyx_t_3 = (__pyx_t_4 != 0); + if (__pyx_t_3) { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":723 + * if func_code_info.new_code is None: + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func # <<<<<<<<<<<<<< + * else: + * frame.f_trace = main_debugger.trace_dispatch + */ + __pyx_t_9 = __pyx_v_thread_info->thread_trace_func; + __Pyx_INCREF(__pyx_t_9); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_9) < 0) __PYX_ERR(0, 723, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":722 + * # where needed, so, fallback to tracing. + * if func_code_info.new_code is None: + * if thread_info.thread_trace_func is not None: # <<<<<<<<<<<<<< + * frame.f_trace = thread_info.thread_trace_func + * else: + */ + goto __pyx_L57; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":725 + * frame.f_trace = thread_info.thread_trace_func + * else: + * frame.f_trace = main_debugger.trace_dispatch # <<<<<<<<<<<<<< + * else: + * # print('Using frame eval break for', frame_obj.f_code.co_name) + */ + /*else*/ { + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_main_debugger, __pyx_n_s_trace_dispatch); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 725, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = __pyx_t_9; + __Pyx_INCREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + if (__Pyx_PyObject_SetAttrStr(__pyx_v_frame, __pyx_n_s_f_trace, __pyx_t_10) < 0) __PYX_ERR(0, 725, __pyx_L23_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __pyx_L57:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":721 + * # this means we weren't able to actually add the code + * # where needed, so, fallback to tracing. + * if func_code_info.new_code is None: # <<<<<<<<<<<<<< + * if thread_info.thread_trace_func is not None: + * frame.f_trace = thread_info.thread_trace_func + */ + goto __pyx_L56; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":728 + * else: + * # print('Using frame eval break for', frame_obj.f_code.co_name) + * update_globals_dict( frame_obj.f_globals) # <<<<<<<<<<<<<< + * Py_INCREF(func_code_info.new_code) + * old = frame_obj.f_code + */ + /*else*/ { + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_update_globals_dict); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 728, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + } + } + __pyx_t_10 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_9, __pyx_t_8, ((PyObject *)__pyx_v_frame_obj->f_globals)) : __Pyx_PyObject_CallOneArg(__pyx_t_9, ((PyObject *)__pyx_v_frame_obj->f_globals)); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 728, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":729 + * # print('Using frame eval break for', frame_obj.f_code.co_name) + * update_globals_dict( frame_obj.f_globals) + * Py_INCREF(func_code_info.new_code) # <<<<<<<<<<<<<< + * old = frame_obj.f_code + * frame_obj.f_code = func_code_info.new_code + */ + __pyx_t_10 = __pyx_v_func_code_info->new_code; + __Pyx_INCREF(__pyx_t_10); + Py_INCREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":730 + * update_globals_dict( frame_obj.f_globals) + * Py_INCREF(func_code_info.new_code) + * old = frame_obj.f_code # <<<<<<<<<<<<<< + * frame_obj.f_code = func_code_info.new_code + * Py_DECREF(old) + */ + __pyx_t_10 = ((PyObject *)__pyx_v_frame_obj->f_code); + __Pyx_INCREF(__pyx_t_10); + __pyx_v_old = __pyx_t_10; + __pyx_t_10 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":731 + * Py_INCREF(func_code_info.new_code) + * old = frame_obj.f_code + * frame_obj.f_code = func_code_info.new_code # <<<<<<<<<<<<<< + * Py_DECREF(old) + * else: + */ + __pyx_v_frame_obj->f_code = ((PyCodeObject *)__pyx_v_func_code_info->new_code); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":732 + * old = frame_obj.f_code + * frame_obj.f_code = func_code_info.new_code + * Py_DECREF(old) # <<<<<<<<<<<<<< + * else: + * # When we're forcing to stay in traced mode we need to + */ + Py_DECREF(__pyx_v_old); + } + __pyx_L56:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":717 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + * if not thread_info.force_stay_in_untraced_mode: # <<<<<<<<<<<<<< + * # If breakpoints are found but new_code is None, + * # this means we weren't able to actually add the code + */ + goto __pyx_L55; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":737 + * # update the globals dict (because this means that we're reusing + * # a previous code which had breakpoints added in a new frame). + * update_globals_dict( frame_obj.f_globals) # <<<<<<<<<<<<<< + * + * finally: + */ + /*else*/ { + __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_update_globals_dict); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 737, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_9); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_9, function); + } + } + __pyx_t_10 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_9, __pyx_t_8, ((PyObject *)__pyx_v_frame_obj->f_globals)) : __Pyx_PyObject_CallOneArg(__pyx_t_9, ((PyObject *)__pyx_v_frame_obj->f_globals)); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 737, __pyx_L23_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + } + __pyx_L55:; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":714 + * frame.f_trace = main_debugger.trace_dispatch + * + * if can_skip and func_code_info.breakpoint_found: # <<<<<<<<<<<<<< + * # if DEBUG: + * # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + */ + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":701 + * # if DEBUG: + * # print('get_bytecode_while_frame_eval always skip', func_code_info.always_skip_code) + * if not func_code_info.always_skip_code: # <<<<<<<<<<<<<< + * + * if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: + */ + } + } + __pyx_L30:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":740 + * + * finally: + * thread_info.inside_frame_eval -= 1 # <<<<<<<<<<<<<< + * additional_info.is_tracing = False + * + */ + /*finally:*/ { + /*normal exit:*/{ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval - 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":741 + * finally: + * thread_info.inside_frame_eval -= 1 + * additional_info.is_tracing = False # <<<<<<<<<<<<<< + * + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + __pyx_v_additional_info->is_tracing = 0; + goto __pyx_L24; + } + __pyx_L23_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_7 = 0; __pyx_t_6 = 0; __pyx_t_5 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_7, &__pyx_t_6, &__pyx_t_5) < 0)) __Pyx_ErrFetch(&__pyx_t_7, &__pyx_t_6, &__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __pyx_t_11 = __pyx_lineno; __pyx_t_13 = __pyx_clineno; __pyx_t_14 = __pyx_filename; + { + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":740 + * + * finally: + * thread_info.inside_frame_eval -= 1 # <<<<<<<<<<<<<< + * additional_info.is_tracing = False + * + */ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval - 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":741 + * finally: + * thread_info.inside_frame_eval -= 1 + * additional_info.is_tracing = False # <<<<<<<<<<<<<< + * + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + __pyx_v_additional_info->is_tracing = 0; + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_ExceptionReset(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_6); + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_ErrRestore(__pyx_t_7, __pyx_t_6, __pyx_t_5); + __pyx_t_7 = 0; __pyx_t_6 = 0; __pyx_t_5 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __pyx_lineno = __pyx_t_11; __pyx_clineno = __pyx_t_13; __pyx_filename = __pyx_t_14; + goto __pyx_L1_error; + } + __pyx_L22_return: { + __pyx_t_18 = __pyx_r; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":740 + * + * finally: + * thread_info.inside_frame_eval -= 1 # <<<<<<<<<<<<<< + * additional_info.is_tracing = False + * + */ + __pyx_v_thread_info->inside_frame_eval = (__pyx_v_thread_info->inside_frame_eval - 1); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":741 + * finally: + * thread_info.inside_frame_eval -= 1 + * additional_info.is_tracing = False # <<<<<<<<<<<<<< + * + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) + */ + __pyx_v_additional_info->is_tracing = 0; + __pyx_r = __pyx_t_18; + goto __pyx_L0; + } + __pyx_L24:; + } + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":743 + * additional_info.is_tracing = False + * + * return CALL_EvalFrameDefault_39(tstate, frame_obj, exc) # <<<<<<<<<<<<<< + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * ### WARNING: GENERATED CODE, DO NOT EDIT! + */ + __pyx_r = CALL_EvalFrameDefault_39(__pyx_v_tstate, __pyx_v_frame_obj, __pyx_v_exc); + goto __pyx_L0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":623 + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * ### WARNING: GENERATED CODE, DO NOT EDIT! + * cdef PyObject * get_bytecode_while_frame_eval_39(PyThreadState* tstate, PyFrameObject * frame_obj, int exc): # <<<<<<<<<<<<<< + * ''' + * This function makes the actual evaluation and changes the bytecode to a version + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_WriteUnraisable("_pydevd_frame_eval.pydevd_frame_evaluator.get_bytecode_while_frame_eval_39", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_thread_info); + __Pyx_XDECREF((PyObject *)__pyx_v_additional_info); + __Pyx_XDECREF(__pyx_v_main_debugger); + __Pyx_XDECREF(__pyx_v_frame); + __Pyx_XDECREF(__pyx_v_trace_func); + __Pyx_XDECREF(__pyx_v_apply_to_global); + __Pyx_XDECREF((PyObject *)__pyx_v_func_code_info); + __Pyx_XDECREF(__pyx_v_old); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle_ThreadInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_21__pyx_unpickle_ThreadInfo(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_21__pyx_unpickle_ThreadInfo = {"__pyx_unpickle_ThreadInfo", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_21__pyx_unpickle_ThreadInfo, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_21__pyx_unpickle_ThreadInfo(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_ThreadInfo (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_ThreadInfo", 1, 3, 3, 1); __PYX_ERR(1, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_ThreadInfo", 1, 3, 3, 2); __PYX_ERR(1, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_ThreadInfo") < 0)) __PYX_ERR(1, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(1, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_ThreadInfo", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(1, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle_ThreadInfo", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_20__pyx_unpickle_ThreadInfo(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_20__pyx_unpickle_ThreadInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_ThreadInfo", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x0af4089, 0xe535b68, 0xb8148ba): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__6, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0x0af4089, 0xe535b68, 0xb8148ba): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))" % __pyx_checksum) + * __pyx_result = ThreadInfo.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0x0af4089, 0xe535b68, 0xb8148ba): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = ThreadInfo.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(1, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x0af4089, 0xe535b68, 0xb8148ba): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))" % __pyx_checksum) + * __pyx_result = ThreadInfo.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_ThreadInfo__set_state( __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))" % __pyx_checksum) + * __pyx_result = ThreadInfo.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_ThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = ThreadInfo.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_ThreadInfo__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_ThreadInfo__set_state(ThreadInfo __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle_ThreadInfo__set_state(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))" % __pyx_checksum) + * __pyx_result = ThreadInfo.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_ThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_ThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_ThreadInfo__set_state(ThreadInfo __pyx_result, tuple __pyx_state): + * __pyx_result._can_create_dummy_thread = __pyx_state[0]; __pyx_result.additional_info = __pyx_state[1]; __pyx_result.force_stay_in_untraced_mode = __pyx_state[2]; __pyx_result.fully_initialized = __pyx_state[3]; __pyx_result.inside_frame_eval = __pyx_state[4]; __pyx_result.is_pydevd_thread = __pyx_state[5]; __pyx_result.thread_trace_func = __pyx_state[6] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_ThreadInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle_ThreadInfo", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_ThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_ThreadInfo__set_state(ThreadInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._can_create_dummy_thread = __pyx_state[0]; __pyx_result.additional_info = __pyx_state[1]; __pyx_result.force_stay_in_untraced_mode = __pyx_state[2]; __pyx_result.fully_initialized = __pyx_state[3]; __pyx_result.inside_frame_eval = __pyx_state[4]; __pyx_result.is_pydevd_thread = __pyx_state[5]; __pyx_result.thread_trace_func = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle_ThreadInfo__set_state(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + Py_ssize_t __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_ThreadInfo__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_ThreadInfo__set_state(ThreadInfo __pyx_result, tuple __pyx_state): + * __pyx_result._can_create_dummy_thread = __pyx_state[0]; __pyx_result.additional_info = __pyx_state[1]; __pyx_result.force_stay_in_untraced_mode = __pyx_state[2]; __pyx_result.fully_initialized = __pyx_state[3]; __pyx_result.inside_frame_eval = __pyx_state[4]; __pyx_result.is_pydevd_thread = __pyx_state[5]; __pyx_result.thread_trace_func = __pyx_state[6] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[7]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->_can_create_dummy_thread = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo))))) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->additional_info); + __Pyx_DECREF(((PyObject *)__pyx_v___pyx_result->additional_info)); + __pyx_v___pyx_result->additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->force_stay_in_untraced_mode = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->fully_initialized = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 4, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->inside_frame_eval = __pyx_t_3; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 5, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->is_pydevd_thread = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 6, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->thread_trace_func); + __Pyx_DECREF(__pyx_v___pyx_result->thread_trace_func); + __pyx_v___pyx_result->thread_trace_func = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_ThreadInfo__set_state(ThreadInfo __pyx_result, tuple __pyx_state): + * __pyx_result._can_create_dummy_thread = __pyx_state[0]; __pyx_result.additional_info = __pyx_state[1]; __pyx_result.force_stay_in_untraced_mode = __pyx_state[2]; __pyx_result.fully_initialized = __pyx_state[3]; __pyx_result.inside_frame_eval = __pyx_state[4]; __pyx_result.is_pydevd_thread = __pyx_state[5]; __pyx_result.thread_trace_func = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[7]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(1, 13, __pyx_L1_error) + } + __pyx_t_4 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_5 = ((__pyx_t_4 > 7) != 0); + if (__pyx_t_5) { + } else { + __pyx_t_2 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_6 = (__pyx_t_5 != 0); + __pyx_t_2 = __pyx_t_6; + __pyx_L4_bool_binop_done:; + if (__pyx_t_2) { + + /* "(tree fragment)":14 + * __pyx_result._can_create_dummy_thread = __pyx_state[0]; __pyx_result.additional_info = __pyx_state[1]; __pyx_result.force_stay_in_untraced_mode = __pyx_state[2]; __pyx_result.fully_initialized = __pyx_state[3]; __pyx_result.inside_frame_eval = __pyx_state[4]; __pyx_result.is_pydevd_thread = __pyx_state[5]; __pyx_result.thread_trace_func = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[7]) # <<<<<<<<<<<<<< + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_update); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 14, __pyx_L1_error) + } + __pyx_t_7 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 7, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_9, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_ThreadInfo__set_state(ThreadInfo __pyx_result, tuple __pyx_state): + * __pyx_result._can_create_dummy_thread = __pyx_state[0]; __pyx_result.additional_info = __pyx_state[1]; __pyx_result.force_stay_in_untraced_mode = __pyx_state[2]; __pyx_result.fully_initialized = __pyx_state[3]; __pyx_result.inside_frame_eval = __pyx_state[4]; __pyx_result.is_pydevd_thread = __pyx_state[5]; __pyx_result.thread_trace_func = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[7]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle_ThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_ThreadInfo__set_state(ThreadInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._can_create_dummy_thread = __pyx_state[0]; __pyx_result.additional_info = __pyx_state[1]; __pyx_result.force_stay_in_untraced_mode = __pyx_state[2]; __pyx_result.fully_initialized = __pyx_state[3]; __pyx_result.inside_frame_eval = __pyx_state[4]; __pyx_result.is_pydevd_thread = __pyx_state[5]; __pyx_result.thread_trace_func = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle_ThreadInfo__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle_FuncCodeInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_23__pyx_unpickle_FuncCodeInfo(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_23__pyx_unpickle_FuncCodeInfo = {"__pyx_unpickle_FuncCodeInfo", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_23__pyx_unpickle_FuncCodeInfo, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_23__pyx_unpickle_FuncCodeInfo(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_FuncCodeInfo (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FuncCodeInfo", 1, 3, 3, 1); __PYX_ERR(1, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FuncCodeInfo", 1, 3, 3, 2); __PYX_ERR(1, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_FuncCodeInfo") < 0)) __PYX_ERR(1, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(1, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FuncCodeInfo", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(1, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle_FuncCodeInfo", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_22__pyx_unpickle_FuncCodeInfo(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_22__pyx_unpickle_FuncCodeInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_FuncCodeInfo", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0xb3ee05d, 0x450d2d6, 0x956dcaa): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb3ee05d, 0x450d2d6, 0x956dcaa) = (always_skip_code, breakpoint_found, breakpoints_mtime, canonical_normalized_filename, co_filename, co_name, new_code))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__7, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0xb3ee05d, 0x450d2d6, 0x956dcaa): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb3ee05d, 0x450d2d6, 0x956dcaa) = (always_skip_code, breakpoint_found, breakpoints_mtime, canonical_normalized_filename, co_filename, co_name, new_code))" % __pyx_checksum) + * __pyx_result = FuncCodeInfo.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0xb3ee05d, 0x450d2d6, 0x956dcaa): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb3ee05d, 0x450d2d6, 0x956dcaa) = (always_skip_code, breakpoint_found, breakpoints_mtime, canonical_normalized_filename, co_filename, co_name, new_code))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = FuncCodeInfo.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_2, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(1, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0xb3ee05d, 0x450d2d6, 0x956dcaa): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb3ee05d, 0x450d2d6, 0x956dcaa) = (always_skip_code, breakpoint_found, breakpoints_mtime, canonical_normalized_filename, co_filename, co_name, new_code))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb3ee05d, 0x450d2d6, 0x956dcaa) = (always_skip_code, breakpoint_found, breakpoints_mtime, canonical_normalized_filename, co_filename, co_name, new_code))" % __pyx_checksum) + * __pyx_result = FuncCodeInfo.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_FuncCodeInfo__set_state( __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb3ee05d, 0x450d2d6, 0x956dcaa) = (always_skip_code, breakpoint_found, breakpoints_mtime, canonical_normalized_filename, co_filename, co_name, new_code))" % __pyx_checksum) + * __pyx_result = FuncCodeInfo.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_FuncCodeInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = FuncCodeInfo.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_FuncCodeInfo__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_FuncCodeInfo__set_state(FuncCodeInfo __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle_FuncCodeInfo__set_state(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb3ee05d, 0x450d2d6, 0x956dcaa) = (always_skip_code, breakpoint_found, breakpoints_mtime, canonical_normalized_filename, co_filename, co_name, new_code))" % __pyx_checksum) + * __pyx_result = FuncCodeInfo.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_FuncCodeInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_FuncCodeInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_FuncCodeInfo__set_state(FuncCodeInfo __pyx_result, tuple __pyx_state): + * __pyx_result.always_skip_code = __pyx_state[0]; __pyx_result.breakpoint_found = __pyx_state[1]; __pyx_result.breakpoints_mtime = __pyx_state[2]; __pyx_result.canonical_normalized_filename = __pyx_state[3]; __pyx_result.co_filename = __pyx_state[4]; __pyx_result.co_name = __pyx_state[5]; __pyx_result.new_code = __pyx_state[6] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_FuncCodeInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle_FuncCodeInfo", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_FuncCodeInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_FuncCodeInfo__set_state(FuncCodeInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.always_skip_code = __pyx_state[0]; __pyx_result.breakpoint_found = __pyx_state[1]; __pyx_result.breakpoints_mtime = __pyx_state[2]; __pyx_result.canonical_normalized_filename = __pyx_state[3]; __pyx_result.co_filename = __pyx_state[4]; __pyx_result.co_name = __pyx_state[5]; __pyx_result.new_code = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle_FuncCodeInfo__set_state(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + Py_ssize_t __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_FuncCodeInfo__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_FuncCodeInfo__set_state(FuncCodeInfo __pyx_result, tuple __pyx_state): + * __pyx_result.always_skip_code = __pyx_state[0]; __pyx_result.breakpoint_found = __pyx_state[1]; __pyx_result.breakpoints_mtime = __pyx_state[2]; __pyx_result.canonical_normalized_filename = __pyx_state[3]; __pyx_result.co_filename = __pyx_state[4]; __pyx_result.co_name = __pyx_state[5]; __pyx_result.new_code = __pyx_state[6] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[7]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->always_skip_code = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->breakpoint_found = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->breakpoints_mtime = __pyx_t_3; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->canonical_normalized_filename); + __Pyx_DECREF(__pyx_v___pyx_result->canonical_normalized_filename); + __pyx_v___pyx_result->canonical_normalized_filename = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 4, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->co_filename); + __Pyx_DECREF(__pyx_v___pyx_result->co_filename); + __pyx_v___pyx_result->co_filename = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 5, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyString_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->co_name); + __Pyx_DECREF(__pyx_v___pyx_result->co_name); + __pyx_v___pyx_result->co_name = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 6, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->new_code); + __Pyx_DECREF(__pyx_v___pyx_result->new_code); + __pyx_v___pyx_result->new_code = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_FuncCodeInfo__set_state(FuncCodeInfo __pyx_result, tuple __pyx_state): + * __pyx_result.always_skip_code = __pyx_state[0]; __pyx_result.breakpoint_found = __pyx_state[1]; __pyx_result.breakpoints_mtime = __pyx_state[2]; __pyx_result.canonical_normalized_filename = __pyx_state[3]; __pyx_result.co_filename = __pyx_state[4]; __pyx_result.co_name = __pyx_state[5]; __pyx_result.new_code = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[7]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(1, 13, __pyx_L1_error) + } + __pyx_t_4 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_5 = ((__pyx_t_4 > 7) != 0); + if (__pyx_t_5) { + } else { + __pyx_t_2 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_6 = (__pyx_t_5 != 0); + __pyx_t_2 = __pyx_t_6; + __pyx_L4_bool_binop_done:; + if (__pyx_t_2) { + + /* "(tree fragment)":14 + * __pyx_result.always_skip_code = __pyx_state[0]; __pyx_result.breakpoint_found = __pyx_state[1]; __pyx_result.breakpoints_mtime = __pyx_state[2]; __pyx_result.canonical_normalized_filename = __pyx_state[3]; __pyx_result.co_filename = __pyx_state[4]; __pyx_result.co_name = __pyx_state[5]; __pyx_result.new_code = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[7]) # <<<<<<<<<<<<<< + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_update); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 14, __pyx_L1_error) + } + __pyx_t_7 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 7, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_9, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_FuncCodeInfo__set_state(FuncCodeInfo __pyx_result, tuple __pyx_state): + * __pyx_result.always_skip_code = __pyx_state[0]; __pyx_result.breakpoint_found = __pyx_state[1]; __pyx_result.breakpoints_mtime = __pyx_state[2]; __pyx_result.canonical_normalized_filename = __pyx_state[3]; __pyx_result.co_filename = __pyx_state[4]; __pyx_result.co_name = __pyx_state[5]; __pyx_result.new_code = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[7]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle_FuncCodeInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_FuncCodeInfo__set_state(FuncCodeInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.always_skip_code = __pyx_state[0]; __pyx_result.breakpoint_found = __pyx_state[1]; __pyx_result.breakpoints_mtime = __pyx_state[2]; __pyx_result.canonical_normalized_filename = __pyx_state[3]; __pyx_result.co_filename = __pyx_state[4]; __pyx_result.co_name = __pyx_state[5]; __pyx_result.new_code = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle_FuncCodeInfo__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle__CodeLineInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_25__pyx_unpickle__CodeLineInfo(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_25__pyx_unpickle__CodeLineInfo = {"__pyx_unpickle__CodeLineInfo", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_25__pyx_unpickle__CodeLineInfo, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_25__pyx_unpickle__CodeLineInfo(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle__CodeLineInfo (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__CodeLineInfo", 1, 3, 3, 1); __PYX_ERR(1, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__CodeLineInfo", 1, 3, 3, 2); __PYX_ERR(1, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle__CodeLineInfo") < 0)) __PYX_ERR(1, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(1, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__CodeLineInfo", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(1, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle__CodeLineInfo", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_24__pyx_unpickle__CodeLineInfo(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_24__pyx_unpickle__CodeLineInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle__CodeLineInfo", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x3fbbd02, 0x5a9bcd5, 0x0267473): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3fbbd02, 0x5a9bcd5, 0x0267473) = (first_line, last_line, line_to_offset))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__8, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0x3fbbd02, 0x5a9bcd5, 0x0267473): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3fbbd02, 0x5a9bcd5, 0x0267473) = (first_line, last_line, line_to_offset))" % __pyx_checksum) + * __pyx_result = _CodeLineInfo.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0x3fbbd02, 0x5a9bcd5, 0x0267473): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3fbbd02, 0x5a9bcd5, 0x0267473) = (first_line, last_line, line_to_offset))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = _CodeLineInfo.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_3, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(1, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x3fbbd02, 0x5a9bcd5, 0x0267473): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3fbbd02, 0x5a9bcd5, 0x0267473) = (first_line, last_line, line_to_offset))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3fbbd02, 0x5a9bcd5, 0x0267473) = (first_line, last_line, line_to_offset))" % __pyx_checksum) + * __pyx_result = _CodeLineInfo.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle__CodeLineInfo__set_state(<_CodeLineInfo> __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3fbbd02, 0x5a9bcd5, 0x0267473) = (first_line, last_line, line_to_offset))" % __pyx_checksum) + * __pyx_result = _CodeLineInfo.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle__CodeLineInfo__set_state(<_CodeLineInfo> __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = _CodeLineInfo.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle__CodeLineInfo__set_state(<_CodeLineInfo> __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle__CodeLineInfo__set_state(_CodeLineInfo __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle__CodeLineInfo__set_state(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3fbbd02, 0x5a9bcd5, 0x0267473) = (first_line, last_line, line_to_offset))" % __pyx_checksum) + * __pyx_result = _CodeLineInfo.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle__CodeLineInfo__set_state(<_CodeLineInfo> __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle__CodeLineInfo__set_state(<_CodeLineInfo> __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle__CodeLineInfo__set_state(_CodeLineInfo __pyx_result, tuple __pyx_state): + * __pyx_result.first_line = __pyx_state[0]; __pyx_result.last_line = __pyx_state[1]; __pyx_result.line_to_offset = __pyx_state[2] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle__CodeLineInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle__CodeLineInfo", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle__CodeLineInfo__set_state(<_CodeLineInfo> __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle__CodeLineInfo__set_state(_CodeLineInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.first_line = __pyx_state[0]; __pyx_result.last_line = __pyx_state[1]; __pyx_result.line_to_offset = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle__CodeLineInfo__set_state(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + Py_ssize_t __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle__CodeLineInfo__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle__CodeLineInfo__set_state(_CodeLineInfo __pyx_result, tuple __pyx_state): + * __pyx_result.first_line = __pyx_state[0]; __pyx_result.last_line = __pyx_state[1]; __pyx_result.line_to_offset = __pyx_state[2] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[3]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->first_line = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result->last_line = __pyx_t_2; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyDict_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->line_to_offset); + __Pyx_DECREF(__pyx_v___pyx_result->line_to_offset); + __pyx_v___pyx_result->line_to_offset = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle__CodeLineInfo__set_state(_CodeLineInfo __pyx_result, tuple __pyx_state): + * __pyx_result.first_line = __pyx_state[0]; __pyx_result.last_line = __pyx_state[1]; __pyx_result.line_to_offset = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[3]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(1, 13, __pyx_L1_error) + } + __pyx_t_4 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_5 = ((__pyx_t_4 > 3) != 0); + if (__pyx_t_5) { + } else { + __pyx_t_3 = __pyx_t_5; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_5 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_6 = (__pyx_t_5 != 0); + __pyx_t_3 = __pyx_t_6; + __pyx_L4_bool_binop_done:; + if (__pyx_t_3) { + + /* "(tree fragment)":14 + * __pyx_result.first_line = __pyx_state[0]; __pyx_result.last_line = __pyx_state[1]; __pyx_result.line_to_offset = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[3]) # <<<<<<<<<<<<<< + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_update); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 14, __pyx_L1_error) + } + __pyx_t_7 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_9)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_9); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_9, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_7); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle__CodeLineInfo__set_state(_CodeLineInfo __pyx_result, tuple __pyx_state): + * __pyx_result.first_line = __pyx_state[0]; __pyx_result.last_line = __pyx_state[1]; __pyx_result.line_to_offset = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[3]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle__CodeLineInfo__set_state(<_CodeLineInfo> __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle__CodeLineInfo__set_state(_CodeLineInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.first_line = __pyx_state[0]; __pyx_result.last_line = __pyx_state[1]; __pyx_result.line_to_offset = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle__CodeLineInfo__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __pyx_unpickle__CacheValue(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_27__pyx_unpickle__CacheValue(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_27__pyx_unpickle__CacheValue = {"__pyx_unpickle__CacheValue", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_27__pyx_unpickle__CacheValue, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_27__pyx_unpickle__CacheValue(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle__CacheValue (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__CacheValue", 1, 3, 3, 1); __PYX_ERR(1, 1, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__CacheValue", 1, 3, 3, 2); __PYX_ERR(1, 1, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle__CacheValue") < 0)) __PYX_ERR(1, 1, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(1, 1, __pyx_L3_error) + __pyx_v___pyx_state = values[2]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle__CacheValue", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(1, 1, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle__CacheValue", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_26__pyx_unpickle__CacheValue(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_18_pydevd_frame_eval_22pydevd_frame_evaluator_26__pyx_unpickle__CacheValue(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_PickleError = 0; + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle__CacheValue", 0); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d481b9, 0xac42a46, 0xedff7c3): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d481b9, 0xac42a46, 0xedff7c3) = (breakpoints_hit_at_lines, code_line_info, code_lines_as_set, code_obj_py))" % __pyx_checksum) + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__9, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "(tree fragment)":5 + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d481b9, 0xac42a46, 0xedff7c3): + * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d481b9, 0xac42a46, 0xedff7c3) = (breakpoints_hit_at_lines, code_line_info, code_lines_as_set, code_obj_py))" % __pyx_checksum) + * __pyx_result = _CacheValue.__new__(__pyx_type) + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_PickleError); + __Pyx_GIVEREF(__pyx_n_s_PickleError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, -1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":6 + * if __pyx_checksum not in (0x3d481b9, 0xac42a46, 0xedff7c3): + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d481b9, 0xac42a46, 0xedff7c3) = (breakpoints_hit_at_lines, code_line_info, code_lines_as_set, code_obj_py))" % __pyx_checksum) # <<<<<<<<<<<<<< + * __pyx_result = _CacheValue.__new__(__pyx_type) + * if __pyx_state is not None: + */ + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_4, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_v___pyx_PickleError); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(1, 6, __pyx_L1_error) + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x3d481b9, 0xac42a46, 0xedff7c3): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d481b9, 0xac42a46, 0xedff7c3) = (breakpoints_hit_at_lines, code_line_info, code_lines_as_set, code_obj_py))" % __pyx_checksum) + */ + } + + /* "(tree fragment)":7 + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d481b9, 0xac42a46, 0xedff7c3) = (breakpoints_hit_at_lines, code_line_info, code_lines_as_set, code_obj_py))" % __pyx_checksum) + * __pyx_result = _CacheValue.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle__CacheValue__set_state(<_CacheValue> __pyx_result, __pyx_state) + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d481b9, 0xac42a46, 0xedff7c3) = (breakpoints_hit_at_lines, code_line_info, code_lines_as_set, code_obj_py))" % __pyx_checksum) + * __pyx_result = _CacheValue.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle__CacheValue__set_state(<_CacheValue> __pyx_result, __pyx_state) + * return __pyx_result + */ + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "(tree fragment)":9 + * __pyx_result = _CacheValue.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle__CacheValue__set_state(<_CacheValue> __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle__CacheValue__set_state(_CacheValue __pyx_result, tuple __pyx_state): + */ + if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) + __pyx_t_4 = __pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle__CacheValue__set_state(((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "(tree fragment)":8 + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x3d481b9, 0xac42a46, 0xedff7c3) = (breakpoints_hit_at_lines, code_line_info, code_lines_as_set, code_obj_py))" % __pyx_checksum) + * __pyx_result = _CacheValue.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle__CacheValue__set_state(<_CacheValue> __pyx_result, __pyx_state) + * return __pyx_result + */ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle__CacheValue__set_state(<_CacheValue> __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle__CacheValue__set_state(_CacheValue __pyx_result, tuple __pyx_state): + * __pyx_result.breakpoints_hit_at_lines = __pyx_state[0]; __pyx_result.code_line_info = __pyx_state[1]; __pyx_result.code_lines_as_set = __pyx_state[2]; __pyx_result.code_obj_py = __pyx_state[3] + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":1 + * def __pyx_unpickle__CacheValue(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle__CacheValue", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_PickleError); + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle__CacheValue__set_state(<_CacheValue> __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle__CacheValue__set_state(_CacheValue __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.breakpoints_hit_at_lines = __pyx_state[0]; __pyx_result.code_line_info = __pyx_state[1]; __pyx_result.code_lines_as_set = __pyx_state[2]; __pyx_result.code_obj_py = __pyx_state[3] + * if len(__pyx_state) > 4 and hasattr(__pyx_result, '__dict__'): + */ + +static PyObject *__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator___pyx_unpickle__CacheValue__set_state(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle__CacheValue__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle__CacheValue__set_state(_CacheValue __pyx_result, tuple __pyx_state): + * __pyx_result.breakpoints_hit_at_lines = __pyx_state[0]; __pyx_result.code_line_info = __pyx_state[1]; __pyx_result.code_lines_as_set = __pyx_state[2]; __pyx_result.code_obj_py = __pyx_state[3] # <<<<<<<<<<<<<< + * if len(__pyx_state) > 4 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[4]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PySet_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "set", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->breakpoints_hit_at_lines); + __Pyx_DECREF(__pyx_v___pyx_result->breakpoints_hit_at_lines); + __pyx_v___pyx_result->breakpoints_hit_at_lines = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo))))) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->code_line_info); + __Pyx_DECREF(((PyObject *)__pyx_v___pyx_result->code_line_info)); + __pyx_v___pyx_result->code_line_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PySet_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "set", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->code_lines_as_set); + __Pyx_DECREF(__pyx_v___pyx_result->code_lines_as_set); + __pyx_v___pyx_result->code_lines_as_set = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 12, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->code_obj_py); + __Pyx_DECREF(__pyx_v___pyx_result->code_obj_py); + __pyx_v___pyx_result->code_obj_py = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle__CacheValue__set_state(_CacheValue __pyx_result, tuple __pyx_state): + * __pyx_result.breakpoints_hit_at_lines = __pyx_state[0]; __pyx_result.code_line_info = __pyx_state[1]; __pyx_result.code_lines_as_set = __pyx_state[2]; __pyx_result.code_obj_py = __pyx_state[3] + * if len(__pyx_state) > 4 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[4]) + */ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(1, 13, __pyx_L1_error) + } + __pyx_t_3 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_4 = ((__pyx_t_3 > 4) != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_4 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + __pyx_t_5 = (__pyx_t_4 != 0); + __pyx_t_2 = __pyx_t_5; + __pyx_L4_bool_binop_done:; + if (__pyx_t_2) { + + /* "(tree fragment)":14 + * __pyx_result.breakpoints_hit_at_lines = __pyx_state[0]; __pyx_result.code_line_info = __pyx_state[1]; __pyx_result.code_lines_as_set = __pyx_state[2]; __pyx_result.code_obj_py = __pyx_state[3] + * if len(__pyx_state) > 4 and hasattr(__pyx_result, '__dict__'): + * __pyx_result.__dict__.update(__pyx_state[4]) # <<<<<<<<<<<<<< + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_update); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 14, __pyx_L1_error) + } + __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 4, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle__CacheValue__set_state(_CacheValue __pyx_result, tuple __pyx_state): + * __pyx_result.breakpoints_hit_at_lines = __pyx_state[0]; __pyx_result.code_line_info = __pyx_state[1]; __pyx_result.code_lines_as_set = __pyx_state[2]; __pyx_result.code_obj_py = __pyx_state[3] + * if len(__pyx_state) > 4 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< + * __pyx_result.__dict__.update(__pyx_state[4]) + */ + } + + /* "(tree fragment)":11 + * __pyx_unpickle__CacheValue__set_state(<_CacheValue> __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle__CacheValue__set_state(_CacheValue __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.breakpoints_hit_at_lines = __pyx_state[0]; __pyx_result.code_line_info = __pyx_state[1]; __pyx_result.code_lines_as_set = __pyx_state[2]; __pyx_result.code_obj_py = __pyx_state[3] + * if len(__pyx_state) > 4 and hasattr(__pyx_result, '__dict__'): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("_pydevd_frame_eval.pydevd_frame_evaluator.__pyx_unpickle__CacheValue__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} +static struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo __pyx_vtable_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo; + +static PyObject *__pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)o); + p->__pyx_vtab = __pyx_vtabptr_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo; + p->additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)Py_None); Py_INCREF(Py_None); + p->thread_trace_func = Py_None; Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo(PyObject *o) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->additional_info); + Py_CLEAR(p->thread_trace_func); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)o; + if (p->additional_info) { + e = (*v)(((PyObject *)p->additional_info), a); if (e) return e; + } + if (p->thread_trace_func) { + e = (*v)(p->thread_trace_func, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *)o; + tmp = ((PyObject*)p->additional_info); + p->additional_info = ((struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo *)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->thread_trace_func); + p->thread_trace_func = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_additional_info(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_additional_info(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_15additional_info_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_is_pydevd_thread(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_is_pydevd_thread(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_16is_pydevd_thread_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_inside_frame_eval(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_inside_frame_eval(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17inside_frame_eval_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_fully_initialized(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_fully_initialized(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17fully_initialized_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_thread_trace_func(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_thread_trace_func(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_17thread_trace_func_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_force_stay_in_untraced_mode(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_force_stay_in_untraced_mode(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_27force_stay_in_untraced_mode_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyMethodDef __pyx_methods_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo[] = { + {"__reduce_cython__", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_1__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_3__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo[] = { + {(char *)"additional_info", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_additional_info, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_additional_info, (char *)0, 0}, + {(char *)"is_pydevd_thread", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_is_pydevd_thread, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_is_pydevd_thread, (char *)0, 0}, + {(char *)"inside_frame_eval", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_inside_frame_eval, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_inside_frame_eval, (char *)0, 0}, + {(char *)"fully_initialized", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_fully_initialized, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_fully_initialized, (char *)0, 0}, + {(char *)"thread_trace_func", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_thread_trace_func, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_thread_trace_func, (char *)0, 0}, + {(char *)"force_stay_in_untraced_mode", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_force_stay_in_untraced_mode, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_force_stay_in_untraced_mode, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_frame_eval.pydevd_frame_evaluator.ThreadInfo", /*tp_name*/ + sizeof(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo, /*tp_traverse*/ + __pyx_tp_clear_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyObject *__pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)o); + p->co_filename = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->co_name = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->canonical_normalized_filename = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->new_code = Py_None; Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo(PyObject *o) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->co_filename); + Py_CLEAR(p->co_name); + Py_CLEAR(p->canonical_normalized_filename); + Py_CLEAR(p->new_code); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)o; + if (p->new_code) { + e = (*v)(p->new_code, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo *)o; + tmp = ((PyObject*)p->new_code); + p->new_code = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_co_filename(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_co_filename(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_11co_filename_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_co_name(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_co_name(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_7co_name_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_canonical_normalized_filename(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_canonical_normalized_filename(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_29canonical_normalized_filename_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_breakpoint_found(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_breakpoint_found(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_16breakpoint_found_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_new_code(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_new_code(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_8new_code_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_breakpoints_mtime(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_breakpoints_mtime(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_17breakpoints_mtime_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyMethodDef __pyx_methods_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo[] = { + {"__reduce_cython__", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_3__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_5__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo[] = { + {(char *)"co_filename", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_co_filename, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_co_filename, (char *)0, 0}, + {(char *)"co_name", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_co_name, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_co_name, (char *)0, 0}, + {(char *)"canonical_normalized_filename", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_canonical_normalized_filename, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_canonical_normalized_filename, (char *)0, 0}, + {(char *)"breakpoint_found", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_breakpoint_found, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_breakpoint_found, (char *)0, 0}, + {(char *)"new_code", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_new_code, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_new_code, (char *)0, 0}, + {(char *)"breakpoints_mtime", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_breakpoints_mtime, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_breakpoints_mtime, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_frame_eval.pydevd_frame_evaluator.FuncCodeInfo", /*tp_name*/ + sizeof(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo, /*tp_traverse*/ + __pyx_tp_clear_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_12FuncCodeInfo_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyObject *__pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)o); + p->line_to_offset = ((PyObject*)Py_None); Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo(PyObject *o) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->line_to_offset); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)o; + if (p->line_to_offset) { + e = (*v)(p->line_to_offset, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)o; + tmp = ((PyObject*)p->line_to_offset); + p->line_to_offset = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_line_to_offset(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_line_to_offset(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_14line_to_offset_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_first_line(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_first_line(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_10first_line_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_last_line(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_last_line(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_9last_line_3__set__(o, v); + } + else { + PyErr_SetString(PyExc_NotImplementedError, "__del__"); + return -1; + } +} + +static PyMethodDef __pyx_methods_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo[] = { + {"__reduce_cython__", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_3__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_5__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo[] = { + {(char *)"line_to_offset", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_line_to_offset, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_line_to_offset, (char *)0, 0}, + {(char *)"first_line", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_first_line, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_first_line, (char *)0, 0}, + {(char *)"last_line", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_last_line, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_last_line, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_frame_eval.pydevd_frame_evaluator._CodeLineInfo", /*tp_name*/ + sizeof(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo, /*tp_traverse*/ + __pyx_tp_clear_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_13_CodeLineInfo_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; +static struct __pyx_vtabstruct_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue __pyx_vtable_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue; + +static PyObject *__pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)o); + p->__pyx_vtab = __pyx_vtabptr_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue; + p->code_obj_py = Py_None; Py_INCREF(Py_None); + p->code_line_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)Py_None); Py_INCREF(Py_None); + p->breakpoints_hit_at_lines = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->code_lines_as_set = ((PyObject*)Py_None); Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue(PyObject *o) { + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->code_obj_py); + Py_CLEAR(p->code_line_info); + Py_CLEAR(p->breakpoints_hit_at_lines); + Py_CLEAR(p->code_lines_as_set); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)o; + if (p->code_obj_py) { + e = (*v)(p->code_obj_py, a); if (e) return e; + } + if (p->code_line_info) { + e = (*v)(((PyObject *)p->code_line_info), a); if (e) return e; + } + if (p->breakpoints_hit_at_lines) { + e = (*v)(p->breakpoints_hit_at_lines, a); if (e) return e; + } + if (p->code_lines_as_set) { + e = (*v)(p->code_lines_as_set, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *p = (struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *)o; + tmp = ((PyObject*)p->code_obj_py); + p->code_obj_py = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->code_line_info); + p->code_line_info = ((struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo *)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->breakpoints_hit_at_lines); + p->breakpoints_hit_at_lines = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->code_lines_as_set); + p->code_lines_as_set = ((PyObject*)Py_None); Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_obj_py(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_obj_py(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_11code_obj_py_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_line_info(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_line_info(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_14code_line_info_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_breakpoints_hit_at_lines(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_breakpoints_hit_at_lines(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_24breakpoints_hit_at_lines_5__del__(o); + } +} + +static PyObject *__pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_lines_as_set(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_1__get__(o); +} + +static int __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_lines_as_set(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) { + if (v) { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_3__set__(o, v); + } + else { + return __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_17code_lines_as_set_5__del__(o); + } +} + +static PyMethodDef __pyx_methods_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue[] = { + {"compute_force_stay_in_untraced_mode", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_3compute_force_stay_in_untraced_mode, METH_O, __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_2compute_force_stay_in_untraced_mode}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_5__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_7__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue[] = { + {(char *)"code_obj_py", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_obj_py, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_obj_py, (char *)0, 0}, + {(char *)"code_line_info", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_line_info, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_line_info, (char *)0, 0}, + {(char *)"breakpoints_hit_at_lines", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_breakpoints_hit_at_lines, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_breakpoints_hit_at_lines, (char *)0, 0}, + {(char *)"code_lines_as_set", __pyx_getprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_lines_as_set, __pyx_setprop_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_code_lines_as_set, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue = { + PyVarObject_HEAD_INIT(0, 0) + "_pydevd_frame_eval.pydevd_frame_evaluator._CacheValue", /*tp_name*/ + sizeof(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue, /*tp_traverse*/ + __pyx_tp_clear_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_pydevd_frame_evaluator(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_pydevd_frame_evaluator}, + {0, NULL} +}; +#endif + +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + "pydevd_frame_evaluator", + 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else + -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_s_, __pyx_k_, sizeof(__pyx_k_), 0, 0, 1, 0}, + {&__pyx_n_s_AttributeError, __pyx_k_AttributeError, sizeof(__pyx_k_AttributeError), 0, 0, 1, 1}, + {&__pyx_n_s_CacheValue, __pyx_k_CacheValue, sizeof(__pyx_k_CacheValue), 0, 0, 1, 1}, + {&__pyx_n_s_CodeLineInfo, __pyx_k_CodeLineInfo, sizeof(__pyx_k_CodeLineInfo), 0, 0, 1, 1}, + {&__pyx_n_s_DebugHelper, __pyx_k_DebugHelper, sizeof(__pyx_k_DebugHelper), 0, 0, 1, 1}, + {&__pyx_n_s_FuncCodeInfo, __pyx_k_FuncCodeInfo, sizeof(__pyx_k_FuncCodeInfo), 0, 0, 1, 1}, + {&__pyx_n_s_GlobalDebuggerHolder, __pyx_k_GlobalDebuggerHolder, sizeof(__pyx_k_GlobalDebuggerHolder), 0, 0, 1, 1}, + {&__pyx_kp_s_If_a_code_object_is_cached_that, __pyx_k_If_a_code_object_is_cached_that, sizeof(__pyx_k_If_a_code_object_is_cached_that), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_k_Incompatible_checksums_0x_x_vs_0, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_2, __pyx_k_Incompatible_checksums_0x_x_vs_0_2, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_2), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_3, __pyx_k_Incompatible_checksums_0x_x_vs_0_3, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_3), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_4, __pyx_k_Incompatible_checksums_0x_x_vs_0_4, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_4), 0, 0, 1, 0}, + {&__pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER, __pyx_k_NORM_PATHS_AND_BASE_CONTAINER, sizeof(__pyx_k_NORM_PATHS_AND_BASE_CONTAINER), 0, 0, 1, 1}, + {&__pyx_n_s_PickleError, __pyx_k_PickleError, sizeof(__pyx_k_PickleError), 0, 0, 1, 1}, + {&__pyx_n_s_SetTrace, __pyx_k_SetTrace, sizeof(__pyx_k_SetTrace), 0, 0, 1, 1}, + {&__pyx_n_s_ThreadInfo, __pyx_k_ThreadInfo, sizeof(__pyx_k_ThreadInfo), 0, 0, 1, 1}, + {&__pyx_kp_s__2, __pyx_k__2, sizeof(__pyx_k__2), 0, 0, 1, 0}, + {&__pyx_kp_s__3, __pyx_k__3, sizeof(__pyx_k__3), 0, 0, 1, 0}, + {&__pyx_kp_s__5, __pyx_k__5, sizeof(__pyx_k__5), 0, 0, 1, 0}, + {&__pyx_n_s_active, __pyx_k_active, sizeof(__pyx_k_active), 0, 0, 1, 1}, + {&__pyx_n_s_additional_info, __pyx_k_additional_info, sizeof(__pyx_k_additional_info), 0, 0, 1, 1}, + {&__pyx_n_s_arg, __pyx_k_arg, sizeof(__pyx_k_arg), 0, 0, 1, 1}, + {&__pyx_n_s_bootstrap, __pyx_k_bootstrap, sizeof(__pyx_k_bootstrap), 0, 0, 1, 1}, + {&__pyx_n_s_bootstrap_2, __pyx_k_bootstrap_2, sizeof(__pyx_k_bootstrap_2), 0, 0, 1, 1}, + {&__pyx_n_s_bootstrap_inner, __pyx_k_bootstrap_inner, sizeof(__pyx_k_bootstrap_inner), 0, 0, 1, 1}, + {&__pyx_n_s_bootstrap_inner_2, __pyx_k_bootstrap_inner_2, sizeof(__pyx_k_bootstrap_inner_2), 0, 0, 1, 1}, + {&__pyx_n_s_break_on_caught_exceptions, __pyx_k_break_on_caught_exceptions, sizeof(__pyx_k_break_on_caught_exceptions), 0, 0, 1, 1}, + {&__pyx_n_s_break_on_user_uncaught_exception, __pyx_k_break_on_user_uncaught_exception, sizeof(__pyx_k_break_on_user_uncaught_exception), 0, 0, 1, 1}, + {&__pyx_n_s_breakpoints, __pyx_k_breakpoints, sizeof(__pyx_k_breakpoints), 0, 0, 1, 1}, + {&__pyx_n_s_breakpoints_hit_at_lines, __pyx_k_breakpoints_hit_at_lines, sizeof(__pyx_k_breakpoints_hit_at_lines), 0, 0, 1, 1}, + {&__pyx_n_s_cache, __pyx_k_cache, sizeof(__pyx_k_cache), 0, 0, 1, 1}, + {&__pyx_n_s_call, __pyx_k_call, sizeof(__pyx_k_call), 0, 0, 1, 1}, + {&__pyx_n_s_call_2, __pyx_k_call_2, sizeof(__pyx_k_call_2), 0, 0, 1, 1}, + {&__pyx_n_s_can_skip, __pyx_k_can_skip, sizeof(__pyx_k_can_skip), 0, 0, 1, 1}, + {&__pyx_n_s_clear_thread_local_info, __pyx_k_clear_thread_local_info, sizeof(__pyx_k_clear_thread_local_info), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_code_line_info, __pyx_k_code_line_info, sizeof(__pyx_k_code_line_info), 0, 0, 1, 1}, + {&__pyx_n_s_code_obj, __pyx_k_code_obj, sizeof(__pyx_k_code_obj), 0, 0, 1, 1}, + {&__pyx_n_s_code_obj_py, __pyx_k_code_obj_py, sizeof(__pyx_k_code_obj_py), 0, 0, 1, 1}, + {&__pyx_n_s_compute_force_stay_in_untraced_m, __pyx_k_compute_force_stay_in_untraced_m, sizeof(__pyx_k_compute_force_stay_in_untraced_m), 0, 0, 1, 1}, + {&__pyx_n_s_current_thread, __pyx_k_current_thread, sizeof(__pyx_k_current_thread), 0, 0, 1, 1}, + {&__pyx_n_s_decref_py, __pyx_k_decref_py, sizeof(__pyx_k_decref_py), 0, 0, 1, 1}, + {&__pyx_n_s_dict, __pyx_k_dict, sizeof(__pyx_k_dict), 0, 0, 1, 1}, + {&__pyx_n_s_dis, __pyx_k_dis, sizeof(__pyx_k_dis), 0, 0, 1, 1}, + {&__pyx_n_s_dummy_trace_dispatch, __pyx_k_dummy_trace_dispatch, sizeof(__pyx_k_dummy_trace_dispatch), 0, 0, 1, 1}, + {&__pyx_n_s_dummy_tracing_holder, __pyx_k_dummy_tracing_holder, sizeof(__pyx_k_dummy_tracing_holder), 0, 0, 1, 1}, + {&__pyx_n_s_enter, __pyx_k_enter, sizeof(__pyx_k_enter), 0, 0, 1, 1}, + {&__pyx_n_s_event, __pyx_k_event, sizeof(__pyx_k_event), 0, 0, 1, 1}, + {&__pyx_n_s_exec, __pyx_k_exec, sizeof(__pyx_k_exec), 0, 0, 1, 1}, + {&__pyx_n_s_exit, __pyx_k_exit, sizeof(__pyx_k_exit), 0, 0, 1, 1}, + {&__pyx_n_s_f_back, __pyx_k_f_back, sizeof(__pyx_k_f_back), 0, 0, 1, 1}, + {&__pyx_n_s_f_trace, __pyx_k_f_trace, sizeof(__pyx_k_f_trace), 0, 0, 1, 1}, + {&__pyx_n_s_findlinestarts, __pyx_k_findlinestarts, sizeof(__pyx_k_findlinestarts), 0, 0, 1, 1}, + {&__pyx_n_s_first_line, __pyx_k_first_line, sizeof(__pyx_k_first_line), 0, 0, 1, 1}, + {&__pyx_n_s_fix_top_level_trace_and_get_trac, __pyx_k_fix_top_level_trace_and_get_trac, sizeof(__pyx_k_fix_top_level_trace_and_get_trac), 0, 0, 1, 1}, + {&__pyx_n_s_frame, __pyx_k_frame, sizeof(__pyx_k_frame), 0, 0, 1, 1}, + {&__pyx_n_s_frame_eval_func, __pyx_k_frame_eval_func, sizeof(__pyx_k_frame_eval_func), 0, 0, 1, 1}, + {&__pyx_n_s_function_breakpoint_name_to_brea, __pyx_k_function_breakpoint_name_to_brea, sizeof(__pyx_k_function_breakpoint_name_to_brea), 0, 0, 1, 1}, + {&__pyx_n_s_generate_code_with_breakpoints_p, __pyx_k_generate_code_with_breakpoints_p, sizeof(__pyx_k_generate_code_with_breakpoints_p), 0, 0, 1, 1}, + {&__pyx_n_s_get, __pyx_k_get, sizeof(__pyx_k_get), 0, 0, 1, 1}, + {&__pyx_n_s_get_abs_path_real_path_and_base, __pyx_k_get_abs_path_real_path_and_base, sizeof(__pyx_k_get_abs_path_real_path_and_base), 0, 0, 1, 1}, + {&__pyx_n_s_get_cache_file_type, __pyx_k_get_cache_file_type, sizeof(__pyx_k_get_cache_file_type), 0, 0, 1, 1}, + {&__pyx_n_s_get_cached_code_obj_info_py, __pyx_k_get_cached_code_obj_info_py, sizeof(__pyx_k_get_cached_code_obj_info_py), 0, 0, 1, 1}, + {&__pyx_n_s_get_code_line_info, __pyx_k_get_code_line_info, sizeof(__pyx_k_get_code_line_info), 0, 0, 1, 1}, + {&__pyx_n_s_get_file_type, __pyx_k_get_file_type, sizeof(__pyx_k_get_file_type), 0, 0, 1, 1}, + {&__pyx_n_s_get_func_code_info_py, __pyx_k_get_func_code_info_py, sizeof(__pyx_k_get_func_code_info_py), 0, 0, 1, 1}, + {&__pyx_n_s_get_ident, __pyx_k_get_ident, sizeof(__pyx_k_get_ident), 0, 0, 1, 1}, + {&__pyx_n_s_get_ident_2, __pyx_k_get_ident_2, sizeof(__pyx_k_get_ident_2), 0, 0, 1, 1}, + {&__pyx_n_s_get_thread_info_py, __pyx_k_get_thread_info_py, sizeof(__pyx_k_get_thread_info_py), 0, 0, 1, 1}, + {&__pyx_n_s_getstate, __pyx_k_getstate, sizeof(__pyx_k_getstate), 0, 0, 1, 1}, + {&__pyx_n_s_global_dbg, __pyx_k_global_dbg, sizeof(__pyx_k_global_dbg), 0, 0, 1, 1}, + {&__pyx_n_s_has_plugin_exception_breaks, __pyx_k_has_plugin_exception_breaks, sizeof(__pyx_k_has_plugin_exception_breaks), 0, 0, 1, 1}, + {&__pyx_n_s_has_plugin_line_breaks, __pyx_k_has_plugin_line_breaks, sizeof(__pyx_k_has_plugin_line_breaks), 0, 0, 1, 1}, + {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, + {&__pyx_n_s_insert_pydevd_breaks, __pyx_k_insert_pydevd_breaks, sizeof(__pyx_k_insert_pydevd_breaks), 0, 0, 1, 1}, + {&__pyx_n_s_intersection, __pyx_k_intersection, sizeof(__pyx_k_intersection), 0, 0, 1, 1}, + {&__pyx_n_s_is_pydev_daemon_thread, __pyx_k_is_pydev_daemon_thread, sizeof(__pyx_k_is_pydev_daemon_thread), 0, 0, 1, 1}, + {&__pyx_n_s_issuperset, __pyx_k_issuperset, sizeof(__pyx_k_issuperset), 0, 0, 1, 1}, + {&__pyx_n_s_last_line, __pyx_k_last_line, sizeof(__pyx_k_last_line), 0, 0, 1, 1}, + {&__pyx_n_s_line, __pyx_k_line, sizeof(__pyx_k_line), 0, 0, 1, 1}, + {&__pyx_n_s_line_to_offset, __pyx_k_line_to_offset, sizeof(__pyx_k_line_to_offset), 0, 0, 1, 1}, + {&__pyx_n_s_local, __pyx_k_local, sizeof(__pyx_k_local), 0, 0, 1, 1}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_main_2, __pyx_k_main_2, sizeof(__pyx_k_main_2), 0, 0, 1, 1}, + {&__pyx_n_s_max, __pyx_k_max, sizeof(__pyx_k_max), 0, 0, 1, 1}, + {&__pyx_n_s_min, __pyx_k_min, sizeof(__pyx_k_min), 0, 0, 1, 1}, + {&__pyx_n_s_mtime, __pyx_k_mtime, sizeof(__pyx_k_mtime), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_new, __pyx_k_new, sizeof(__pyx_k_new), 0, 0, 1, 1}, + {&__pyx_n_s_obj, __pyx_k_obj, sizeof(__pyx_k_obj), 0, 0, 1, 1}, + {&__pyx_n_s_offset, __pyx_k_offset, sizeof(__pyx_k_offset), 0, 0, 1, 1}, + {&__pyx_n_s_pickle, __pyx_k_pickle, sizeof(__pyx_k_pickle), 0, 0, 1, 1}, + {&__pyx_n_s_plugin, __pyx_k_plugin, sizeof(__pyx_k_plugin), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_bundle__pydev_saved_modul, __pyx_k_pydev_bundle__pydev_saved_modul, sizeof(__pyx_k_pydev_bundle__pydev_saved_modul), 0, 0, 1, 1}, + {&__pyx_n_s_pydev_monkey, __pyx_k_pydev_monkey, sizeof(__pyx_k_pydev_monkey), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd, __pyx_k_pydevd, sizeof(__pyx_k_pydevd), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle_pydevd_additional, __pyx_k_pydevd_bundle_pydevd_additional, sizeof(__pyx_k_pydevd_bundle_pydevd_additional), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle_pydevd_constants, __pyx_k_pydevd_bundle_pydevd_constants, sizeof(__pyx_k_pydevd_bundle_pydevd_constants), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_bundle_pydevd_trace_disp, __pyx_k_pydevd_bundle_pydevd_trace_disp, sizeof(__pyx_k_pydevd_bundle_pydevd_trace_disp), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_file_utils, __pyx_k_pydevd_file_utils, sizeof(__pyx_k_pydevd_file_utils), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_frame_eval_pydevd_frame, __pyx_k_pydevd_frame_eval_pydevd_frame, sizeof(__pyx_k_pydevd_frame_eval_pydevd_frame), 0, 0, 1, 1}, + {&__pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_k_pydevd_frame_eval_pydevd_frame_2, sizeof(__pyx_k_pydevd_frame_eval_pydevd_frame_2), 0, 0, 1, 0}, + {&__pyx_n_s_pydevd_frame_eval_pydevd_frame_3, __pyx_k_pydevd_frame_eval_pydevd_frame_3, sizeof(__pyx_k_pydevd_frame_eval_pydevd_frame_3), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_frame_eval_pydevd_modify, __pyx_k_pydevd_frame_eval_pydevd_modify, sizeof(__pyx_k_pydevd_frame_eval_pydevd_modify), 0, 0, 1, 1}, + {&__pyx_n_s_pydevd_tracing, __pyx_k_pydevd_tracing, sizeof(__pyx_k_pydevd_tracing), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_PickleError, __pyx_k_pyx_PickleError, sizeof(__pyx_k_pyx_PickleError), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_checksum, __pyx_k_pyx_checksum, sizeof(__pyx_k_pyx_checksum), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_result, __pyx_k_pyx_result, sizeof(__pyx_k_pyx_result), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_state, __pyx_k_pyx_state, sizeof(__pyx_k_pyx_state), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_type, __pyx_k_pyx_type, sizeof(__pyx_k_pyx_type), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle_FuncCodeInfo, __pyx_k_pyx_unpickle_FuncCodeInfo, sizeof(__pyx_k_pyx_unpickle_FuncCodeInfo), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle_ThreadInfo, __pyx_k_pyx_unpickle_ThreadInfo, sizeof(__pyx_k_pyx_unpickle_ThreadInfo), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle__CacheValue, __pyx_k_pyx_unpickle__CacheValue, sizeof(__pyx_k_pyx_unpickle__CacheValue), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_unpickle__CodeLineInfo, __pyx_k_pyx_unpickle__CodeLineInfo, sizeof(__pyx_k_pyx_unpickle__CodeLineInfo), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_vtable, __pyx_k_pyx_vtable, sizeof(__pyx_k_pyx_vtable), 0, 0, 1, 1}, + {&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1}, + {&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1}, + {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1}, + {&__pyx_n_s_rfind, __pyx_k_rfind, sizeof(__pyx_k_rfind), 0, 0, 1, 1}, + {&__pyx_n_s_run, __pyx_k_run, sizeof(__pyx_k_run), 0, 0, 1, 1}, + {&__pyx_n_s_set_additional_thread_info_lock, __pyx_k_set_additional_thread_info_lock, sizeof(__pyx_k_set_additional_thread_info_lock), 0, 0, 1, 1}, + {&__pyx_n_s_set_trace_func, __pyx_k_set_trace_func, sizeof(__pyx_k_set_trace_func), 0, 0, 1, 1}, + {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1}, + {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1}, + {&__pyx_n_s_show_return_values, __pyx_k_show_return_values, sizeof(__pyx_k_show_return_values), 0, 0, 1, 1}, + {&__pyx_n_s_signature_factory, __pyx_k_signature_factory, sizeof(__pyx_k_signature_factory), 0, 0, 1, 1}, + {&__pyx_n_s_state, __pyx_k_state, sizeof(__pyx_k_state), 0, 0, 1, 1}, + {&__pyx_n_s_stop_frame_eval, __pyx_k_stop_frame_eval, sizeof(__pyx_k_stop_frame_eval), 0, 0, 1, 1}, + {&__pyx_kp_s_stringsource, __pyx_k_stringsource, sizeof(__pyx_k_stringsource), 0, 0, 1, 0}, + {&__pyx_n_s_sys, __pyx_k_sys, sizeof(__pyx_k_sys), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {&__pyx_n_s_thread, __pyx_k_thread, sizeof(__pyx_k_thread), 0, 0, 1, 1}, + {&__pyx_n_s_thread_active, __pyx_k_thread_active, sizeof(__pyx_k_thread_active), 0, 0, 1, 1}, + {&__pyx_n_s_thread_info, __pyx_k_thread_info, sizeof(__pyx_k_thread_info), 0, 0, 1, 1}, + {&__pyx_n_s_thread_local_info, __pyx_k_thread_local_info, sizeof(__pyx_k_thread_local_info), 0, 0, 1, 1}, + {&__pyx_n_s_threading, __pyx_k_threading, sizeof(__pyx_k_threading), 0, 0, 1, 1}, + {&__pyx_n_s_trace_dispatch, __pyx_k_trace_dispatch, sizeof(__pyx_k_trace_dispatch), 0, 0, 1, 1}, + {&__pyx_n_s_update, __pyx_k_update, sizeof(__pyx_k_update), 0, 0, 1, 1}, + {&__pyx_n_s_update_globals_dict, __pyx_k_update_globals_dict, sizeof(__pyx_k_update_globals_dict), 0, 0, 1, 1}, + {&__pyx_n_s_version_info, __pyx_k_version_info, sizeof(__pyx_k_version_info), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_AttributeError = __Pyx_GetBuiltinName(__pyx_n_s_AttributeError); if (!__pyx_builtin_AttributeError) __PYX_ERR(0, 110, __pyx_L1_error) + __pyx_builtin_min = __Pyx_GetBuiltinName(__pyx_n_s_min); if (!__pyx_builtin_min) __PYX_ERR(0, 341, __pyx_L1_error) + __pyx_builtin_max = __Pyx_GetBuiltinName(__pyx_n_s_max); if (!__pyx_builtin_max) __PYX_ERR(0, 342, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":112 + * raise AttributeError() + * except: + * with _set_additional_thread_info_lock: # <<<<<<<<<<<<<< + * # If it's not there, set it within a lock to avoid any racing + * # conditions. + */ + __pyx_tuple__4 = PyTuple_Pack(3, Py_None, Py_None, Py_None); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 112, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__4); + __Pyx_GIVEREF(__pyx_tuple__4); + + /* "(tree fragment)":4 + * cdef object __pyx_PickleError + * cdef object __pyx_result + * if __pyx_checksum not in (0x0af4089, 0xe535b68, 0xb8148ba): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x0af4089, 0xe535b68, 0xb8148ba) = (_can_create_dummy_thread, additional_info, force_stay_in_untraced_mode, fully_initialized, inside_frame_eval, is_pydevd_thread, thread_trace_func))" % __pyx_checksum) + */ + __pyx_tuple__6 = PyTuple_Pack(3, __pyx_int_11485321, __pyx_int_240343912, __pyx_int_193022138); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__6); + __Pyx_GIVEREF(__pyx_tuple__6); + __pyx_tuple__7 = PyTuple_Pack(3, __pyx_int_188670045, __pyx_int_72405718, __pyx_int_156687530); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__7); + __Pyx_GIVEREF(__pyx_tuple__7); + __pyx_tuple__8 = PyTuple_Pack(3, __pyx_int_66829570, __pyx_int_95010005, __pyx_int_2520179); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__8); + __Pyx_GIVEREF(__pyx_tuple__8); + __pyx_tuple__9 = PyTuple_Pack(3, __pyx_int_64258489, __pyx_int_180628038, __pyx_int_249558979); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__9); + __Pyx_GIVEREF(__pyx_tuple__9); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":19 + * _thread_active = threading._active + * + * def clear_thread_local_info(): # <<<<<<<<<<<<<< + * global _thread_local_info + * _thread_local_info = threading.local() + */ + __pyx_codeobj__10 = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_clear_thread_local_info, 19, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__10)) __PYX_ERR(0, 19, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":152 + * + * + * def dummy_trace_dispatch(frame, str event, arg): # <<<<<<<<<<<<<< + * if event == 'call': + * if frame.f_trace is not None: + */ + __pyx_tuple__11 = PyTuple_Pack(3, __pyx_n_s_frame, __pyx_n_s_event, __pyx_n_s_arg); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(0, 152, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__11); + __Pyx_GIVEREF(__pyx_tuple__11); + __pyx_codeobj__12 = (PyObject*)__Pyx_PyCode_New(3, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__11, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_dummy_trace_dispatch, 152, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__12)) __PYX_ERR(0, 152, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":159 + * + * + * def get_thread_info_py() -> ThreadInfo: # <<<<<<<<<<<<<< + * return get_thread_info(PyEval_GetFrame()) + * + */ + __pyx_codeobj__13 = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_get_thread_info_py, 159, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__13)) __PYX_ERR(0, 159, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":196 + * + * + * def decref_py(obj): # <<<<<<<<<<<<<< + * ''' + * Helper to be called from Python. + */ + __pyx_tuple__14 = PyTuple_Pack(1, __pyx_n_s_obj); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__14); + __Pyx_GIVEREF(__pyx_tuple__14); + __pyx_codeobj__15 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_decref_py, 196, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__15)) __PYX_ERR(0, 196, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":203 + * + * + * def get_func_code_info_py(thread_info, frame, code_obj) -> FuncCodeInfo: # <<<<<<<<<<<<<< + * ''' + * Helper to be called from Python. + */ + __pyx_tuple__16 = PyTuple_Pack(3, __pyx_n_s_thread_info, __pyx_n_s_frame, __pyx_n_s_code_obj); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(0, 203, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__16); + __Pyx_GIVEREF(__pyx_tuple__16); + __pyx_codeobj__17 = (PyObject*)__Pyx_PyCode_New(3, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__16, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_get_func_code_info_py, 203, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__17)) __PYX_ERR(0, 203, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":329 + * + * # Note: this method has a version in pure-python too. + * def _get_code_line_info(code_obj): # <<<<<<<<<<<<<< + * line_to_offset: dict = {} + * first_line: int = None + */ + __pyx_tuple__18 = PyTuple_Pack(6, __pyx_n_s_code_obj, __pyx_n_s_line_to_offset, __pyx_n_s_first_line, __pyx_n_s_last_line, __pyx_n_s_offset, __pyx_n_s_line); if (unlikely(!__pyx_tuple__18)) __PYX_ERR(0, 329, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__18); + __Pyx_GIVEREF(__pyx_tuple__18); + __pyx_codeobj__19 = (PyObject*)__Pyx_PyCode_New(1, 0, 6, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__18, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_get_code_line_info, 329, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__19)) __PYX_ERR(0, 329, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":353 + * _cache: dict = {} + * + * def get_cached_code_obj_info_py(code_obj_py): # <<<<<<<<<<<<<< + * ''' + * :return _CacheValue: + */ + __pyx_tuple__20 = PyTuple_Pack(1, __pyx_n_s_code_obj_py); if (unlikely(!__pyx_tuple__20)) __PYX_ERR(0, 353, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__20); + __Pyx_GIVEREF(__pyx_tuple__20); + __pyx_codeobj__21 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__20, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_get_cached_code_obj_info_py, 353, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__21)) __PYX_ERR(0, 353, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":401 + * return breakpoint_found, force_stay_in_untraced_mode + * + * def generate_code_with_breakpoints_py(object code_obj_py, dict breakpoints): # <<<<<<<<<<<<<< + * return generate_code_with_breakpoints(code_obj_py, breakpoints) + * + */ + __pyx_tuple__22 = PyTuple_Pack(2, __pyx_n_s_code_obj_py, __pyx_n_s_breakpoints); if (unlikely(!__pyx_tuple__22)) __PYX_ERR(0, 401, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__22); + __Pyx_GIVEREF(__pyx_tuple__22); + __pyx_codeobj__23 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_generate_code_with_breakpoints_p, 401, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__23)) __PYX_ERR(0, 401, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":473 + * import sys + * + * cdef bint IS_PY_39_OWNARDS = sys.version_info[:2] >= (3, 9) # <<<<<<<<<<<<<< + * + * def frame_eval_func(): + */ + __pyx_slice__24 = PySlice_New(Py_None, __pyx_int_2, Py_None); if (unlikely(!__pyx_slice__24)) __PYX_ERR(0, 473, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice__24); + __Pyx_GIVEREF(__pyx_slice__24); + __pyx_tuple__25 = PyTuple_Pack(2, __pyx_int_3, __pyx_int_9); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(0, 473, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__25); + __Pyx_GIVEREF(__pyx_tuple__25); + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":475 + * cdef bint IS_PY_39_OWNARDS = sys.version_info[:2] >= (3, 9) + * + * def frame_eval_func(): # <<<<<<<<<<<<<< + * cdef PyThreadState *state = PyThreadState_Get() + * if IS_PY_39_OWNARDS: + */ + __pyx_tuple__26 = PyTuple_Pack(1, __pyx_n_s_state); if (unlikely(!__pyx_tuple__26)) __PYX_ERR(0, 475, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__26); + __Pyx_GIVEREF(__pyx_tuple__26); + __pyx_codeobj__27 = (PyObject*)__Pyx_PyCode_New(0, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__26, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_frame_eval_func, 475, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__27)) __PYX_ERR(0, 475, __pyx_L1_error) + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":484 + * + * + * def stop_frame_eval(): # <<<<<<<<<<<<<< + * cdef PyThreadState *state = PyThreadState_Get() + * state.interp.eval_frame = _PyEval_EvalFrameDefault + */ + __pyx_tuple__28 = PyTuple_Pack(1, __pyx_n_s_state); if (unlikely(!__pyx_tuple__28)) __PYX_ERR(0, 484, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__28); + __Pyx_GIVEREF(__pyx_tuple__28); + __pyx_codeobj__29 = (PyObject*)__Pyx_PyCode_New(0, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__28, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pydevd_frame_eval_pydevd_frame_2, __pyx_n_s_stop_frame_eval, 484, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__29)) __PYX_ERR(0, 484, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __pyx_unpickle_ThreadInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_tuple__30 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__30)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__30); + __Pyx_GIVEREF(__pyx_tuple__30); + __pyx_codeobj__31 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__30, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_ThreadInfo, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__31)) __PYX_ERR(1, 1, __pyx_L1_error) + __pyx_tuple__32 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__32)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__32); + __Pyx_GIVEREF(__pyx_tuple__32); + __pyx_codeobj__33 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__32, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_FuncCodeInfo, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__33)) __PYX_ERR(1, 1, __pyx_L1_error) + __pyx_tuple__34 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__34)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__34); + __Pyx_GIVEREF(__pyx_tuple__34); + __pyx_codeobj__35 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__34, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle__CodeLineInfo, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__35)) __PYX_ERR(1, 1, __pyx_L1_error) + __pyx_tuple__36 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__36)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__36); + __Pyx_GIVEREF(__pyx_tuple__36); + __pyx_codeobj__37 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__36, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle__CacheValue, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__37)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_3 = PyInt_FromLong(3); if (unlikely(!__pyx_int_3)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_9 = PyInt_FromLong(9); if (unlikely(!__pyx_int_9)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_2520179 = PyInt_FromLong(2520179L); if (unlikely(!__pyx_int_2520179)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_11485321 = PyInt_FromLong(11485321L); if (unlikely(!__pyx_int_11485321)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_64258489 = PyInt_FromLong(64258489L); if (unlikely(!__pyx_int_64258489)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_66829570 = PyInt_FromLong(66829570L); if (unlikely(!__pyx_int_66829570)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_72405718 = PyInt_FromLong(72405718L); if (unlikely(!__pyx_int_72405718)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_95010005 = PyInt_FromLong(95010005L); if (unlikely(!__pyx_int_95010005)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_156687530 = PyInt_FromLong(156687530L); if (unlikely(!__pyx_int_156687530)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_180628038 = PyInt_FromLong(180628038L); if (unlikely(!__pyx_int_180628038)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_188670045 = PyInt_FromLong(188670045L); if (unlikely(!__pyx_int_188670045)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_193022138 = PyInt_FromLong(193022138L); if (unlikely(!__pyx_int_193022138)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_240343912 = PyInt_FromLong(240343912L); if (unlikely(!__pyx_int_240343912)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_249558979 = PyInt_FromLong(249558979L); if (unlikely(!__pyx_int_249558979)) __PYX_ERR(0, 1, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __pyx_vtabptr_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo = &__pyx_vtable_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo; + __pyx_vtable_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo.initialize = (PyObject *(*)(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *, PyFrameObject *))__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_initialize; + __pyx_vtable_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo.initialize_if_possible = (PyObject *(*)(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo *))__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_10ThreadInfo_initialize_if_possible; + if (PyType_Ready(&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo) < 0) __PYX_ERR(0, 24, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo.tp_dictoffset && __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (__Pyx_SetVtable(__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo.tp_dict, __pyx_vtabptr_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo) < 0) __PYX_ERR(0, 24, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_ThreadInfo, (PyObject *)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo) < 0) __PYX_ERR(0, 24, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo) < 0) __PYX_ERR(0, 24, __pyx_L1_error) + __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo = &__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_ThreadInfo; + if (PyType_Ready(&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo) < 0) __PYX_ERR(0, 125, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo.tp_dictoffset && __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_FuncCodeInfo, (PyObject *)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo) < 0) __PYX_ERR(0, 125, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo) < 0) __PYX_ERR(0, 125, __pyx_L1_error) + __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo = &__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator_FuncCodeInfo; + if (PyType_Ready(&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo) < 0) __PYX_ERR(0, 316, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo.tp_dictoffset && __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_CodeLineInfo, (PyObject *)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo) < 0) __PYX_ERR(0, 316, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo) < 0) __PYX_ERR(0, 316, __pyx_L1_error) + __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo = &__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CodeLineInfo; + __pyx_vtabptr_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue = &__pyx_vtable_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue; + __pyx_vtable_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue.compute_force_stay_in_untraced_mode = (PyObject *(*)(struct __pyx_obj_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue *, PyObject *, int __pyx_skip_dispatch))__pyx_f_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue_compute_force_stay_in_untraced_mode; + if (PyType_Ready(&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue) < 0) __PYX_ERR(0, 361, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue.tp_dictoffset && __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + #if CYTHON_UPDATE_DESCRIPTOR_DOC + { + PyObject *wrapper = PyObject_GetAttrString((PyObject *)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue, "__init__"); if (unlikely(!wrapper)) __PYX_ERR(0, 361, __pyx_L1_error) + if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) { + __pyx_wrapperbase_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__ = *((PyWrapperDescrObject *)wrapper)->d_base; + __pyx_wrapperbase_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__.doc = __pyx_doc_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__; + ((PyWrapperDescrObject *)wrapper)->d_base = &__pyx_wrapperbase_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_CacheValue___init__; + } + } + #endif + if (__Pyx_SetVtable(__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue.tp_dict, __pyx_vtabptr_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue) < 0) __PYX_ERR(0, 361, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_CacheValue, (PyObject *)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue) < 0) __PYX_ERR(0, 361, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue) < 0) __PYX_ERR(0, 361, __pyx_L1_error) + __pyx_ptype_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue = &__pyx_type_18_pydevd_frame_eval_22pydevd_frame_evaluator__CacheValue; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule("_pydevd_bundle.pydevd_cython"); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo = __Pyx_ImportType(__pyx_t_1, "_pydevd_bundle.pydevd_cython", "PyDBAdditionalThreadInfo", sizeof(struct __pyx_obj_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_14_pydevd_bundle_13pydevd_cython_PyDBAdditionalThreadInfo) __PYX_ERR(2, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + +#ifndef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#elif PY_MAJOR_VERSION < 3 +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" void +#else +#define __Pyx_PyMODINIT_FUNC void +#endif +#else +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyObject * +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initpydevd_frame_evaluator(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initpydevd_frame_evaluator(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_pydevd_frame_evaluator(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_pydevd_frame_evaluator(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_pydevd_frame_evaluator(PyObject *__pyx_pyinit_module) +#endif +#endif +{ + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'pydevd_frame_evaluator' has already been imported. Re-initialisation is not supported."); + return -1; + } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_pydevd_frame_evaluator(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + PyEval_InitThreads(); + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("pydevd_frame_evaluator", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_b); + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_cython_runtime); + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main__pydevd_frame_eval__pydevd_frame_evaluator) { + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "_pydevd_frame_eval.pydevd_frame_evaluator")) { + if (unlikely(PyDict_SetItemString(modules, "_pydevd_frame_eval.pydevd_frame_evaluator", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + if (unlikely(__Pyx_modinit_type_init_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + if (unlikely(__Pyx_modinit_type_import_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":2 + * from __future__ import print_function + * from _pydev_bundle._pydev_saved_modules import threading, thread # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder + * import dis + */ + __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_threading); + __Pyx_GIVEREF(__pyx_n_s_threading); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_threading); + __Pyx_INCREF(__pyx_n_s_thread); + __Pyx_GIVEREF(__pyx_n_s_thread); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_thread); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydev_bundle__pydev_saved_modul, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_threading); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_threading, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_thread); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_thread, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":3 + * from __future__ import print_function + * from _pydev_bundle._pydev_saved_modules import threading, thread + * from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder # <<<<<<<<<<<<<< + * import dis + * import sys + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_GlobalDebuggerHolder); + __Pyx_GIVEREF(__pyx_n_s_GlobalDebuggerHolder); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_GlobalDebuggerHolder); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_constants, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_GlobalDebuggerHolder); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_GlobalDebuggerHolder, __pyx_t_2) < 0) __PYX_ERR(0, 3, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":4 + * from _pydev_bundle._pydev_saved_modules import threading, thread + * from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder + * import dis # <<<<<<<<<<<<<< + * import sys + * from _pydevd_frame_eval.pydevd_frame_tracing import update_globals_dict, dummy_tracing_holder + */ + __pyx_t_1 = __Pyx_Import(__pyx_n_s_dis, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_dis, __pyx_t_1) < 0) __PYX_ERR(0, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":5 + * from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder + * import dis + * import sys # <<<<<<<<<<<<<< + * from _pydevd_frame_eval.pydevd_frame_tracing import update_globals_dict, dummy_tracing_holder + * from _pydevd_frame_eval.pydevd_modify_bytecode import DebugHelper, insert_pydevd_breaks + */ + __pyx_t_1 = __Pyx_Import(__pyx_n_s_sys, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_sys, __pyx_t_1) < 0) __PYX_ERR(0, 5, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":6 + * import dis + * import sys + * from _pydevd_frame_eval.pydevd_frame_tracing import update_globals_dict, dummy_tracing_holder # <<<<<<<<<<<<<< + * from _pydevd_frame_eval.pydevd_modify_bytecode import DebugHelper, insert_pydevd_breaks + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER + */ + __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_update_globals_dict); + __Pyx_GIVEREF(__pyx_n_s_update_globals_dict); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_update_globals_dict); + __Pyx_INCREF(__pyx_n_s_dummy_tracing_holder); + __Pyx_GIVEREF(__pyx_n_s_dummy_tracing_holder); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_dummy_tracing_holder); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_frame_eval_pydevd_frame, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_update_globals_dict); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_update_globals_dict, __pyx_t_1) < 0) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_dummy_tracing_holder); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_dummy_tracing_holder, __pyx_t_1) < 0) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":7 + * import sys + * from _pydevd_frame_eval.pydevd_frame_tracing import update_globals_dict, dummy_tracing_holder + * from _pydevd_frame_eval.pydevd_modify_bytecode import DebugHelper, insert_pydevd_breaks # <<<<<<<<<<<<<< + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER + * from _pydevd_bundle.pydevd_trace_dispatch import fix_top_level_trace_and_get_trace_func + */ + __pyx_t_2 = PyList_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_DebugHelper); + __Pyx_GIVEREF(__pyx_n_s_DebugHelper); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_DebugHelper); + __Pyx_INCREF(__pyx_n_s_insert_pydevd_breaks); + __Pyx_GIVEREF(__pyx_n_s_insert_pydevd_breaks); + PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_insert_pydevd_breaks); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_frame_eval_pydevd_modify, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_DebugHelper); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_DebugHelper, __pyx_t_2) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_insert_pydevd_breaks); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_insert_pydevd_breaks, __pyx_t_2) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":8 + * from _pydevd_frame_eval.pydevd_frame_tracing import update_globals_dict, dummy_tracing_holder + * from _pydevd_frame_eval.pydevd_modify_bytecode import DebugHelper, insert_pydevd_breaks + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_trace_dispatch import fix_top_level_trace_and_get_trace_func + * + */ + __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_get_abs_path_real_path_and_base); + __Pyx_GIVEREF(__pyx_n_s_get_abs_path_real_path_and_base); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_get_abs_path_real_path_and_base); + __Pyx_INCREF(__pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); + __Pyx_GIVEREF(__pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_file_utils, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_get_abs_path_real_path_and_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_abs_path_real_path_and_base, __pyx_t_1) < 0) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_NORM_PATHS_AND_BASE_CONTAINER, __pyx_t_1) < 0) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":9 + * from _pydevd_frame_eval.pydevd_modify_bytecode import DebugHelper, insert_pydevd_breaks + * from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER + * from _pydevd_bundle.pydevd_trace_dispatch import fix_top_level_trace_and_get_trace_func # <<<<<<<<<<<<<< + * + * from _pydevd_bundle.pydevd_additional_thread_info import _set_additional_thread_info_lock + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_fix_top_level_trace_and_get_trac); + __Pyx_GIVEREF(__pyx_n_s_fix_top_level_trace_and_get_trac); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_fix_top_level_trace_and_get_trac); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_trace_disp, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_fix_top_level_trace_and_get_trac); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_fix_top_level_trace_and_get_trac, __pyx_t_2) < 0) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":11 + * from _pydevd_bundle.pydevd_trace_dispatch import fix_top_level_trace_and_get_trace_func + * + * from _pydevd_bundle.pydevd_additional_thread_info import _set_additional_thread_info_lock # <<<<<<<<<<<<<< + * from _pydevd_bundle.pydevd_cython cimport PyDBAdditionalThreadInfo + * from pydevd_tracing import SetTrace + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_set_additional_thread_info_lock); + __Pyx_GIVEREF(__pyx_n_s_set_additional_thread_info_lock); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_set_additional_thread_info_lock); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_pydevd_bundle_pydevd_additional, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_set_additional_thread_info_lock); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_set_additional_thread_info_lock, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":13 + * from _pydevd_bundle.pydevd_additional_thread_info import _set_additional_thread_info_lock + * from _pydevd_bundle.pydevd_cython cimport PyDBAdditionalThreadInfo + * from pydevd_tracing import SetTrace # <<<<<<<<<<<<<< + * + * _get_ident = threading.get_ident # Note this is py3 only, if py2 needed to be supported, _get_ident would be needed. + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_SetTrace); + __Pyx_GIVEREF(__pyx_n_s_SetTrace); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_SetTrace); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_pydevd_tracing, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_SetTrace); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_SetTrace, __pyx_t_2) < 0) __PYX_ERR(0, 13, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":15 + * from pydevd_tracing import SetTrace + * + * _get_ident = threading.get_ident # Note this is py3 only, if py2 needed to be supported, _get_ident would be needed. # <<<<<<<<<<<<<< + * _thread_local_info = threading.local() + * _thread_active = threading._active + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_threading); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_get_ident_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_ident, __pyx_t_2) < 0) __PYX_ERR(0, 15, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":16 + * + * _get_ident = threading.get_ident # Note this is py3 only, if py2 needed to be supported, _get_ident would be needed. + * _thread_local_info = threading.local() # <<<<<<<<<<<<<< + * _thread_active = threading._active + * + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_threading); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_local); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_d, __pyx_n_s_thread_local_info, __pyx_t_2) < 0) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":17 + * _get_ident = threading.get_ident # Note this is py3 only, if py2 needed to be supported, _get_ident would be needed. + * _thread_local_info = threading.local() + * _thread_active = threading._active # <<<<<<<<<<<<<< + * + * def clear_thread_local_info(): + */ + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_threading); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_active); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyDict_SetItem(__pyx_d, __pyx_n_s_thread_active, __pyx_t_1) < 0) __PYX_ERR(0, 17, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":19 + * _thread_active = threading._active + * + * def clear_thread_local_info(): # <<<<<<<<<<<<<< + * global _thread_local_info + * _thread_local_info = threading.local() + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_1clear_thread_local_info, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_clear_thread_local_info, __pyx_t_1) < 0) __PYX_ERR(0, 19, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":152 + * + * + * def dummy_trace_dispatch(frame, str event, arg): # <<<<<<<<<<<<<< + * if event == 'call': + * if frame.f_trace is not None: + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_3dummy_trace_dispatch, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 152, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_dummy_trace_dispatch, __pyx_t_1) < 0) __PYX_ERR(0, 152, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":159 + * + * + * def get_thread_info_py() -> ThreadInfo: # <<<<<<<<<<<<<< + * return get_thread_info(PyEval_GetFrame()) + * + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_5get_thread_info_py, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 159, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_thread_info_py, __pyx_t_1) < 0) __PYX_ERR(0, 159, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":196 + * + * + * def decref_py(obj): # <<<<<<<<<<<<<< + * ''' + * Helper to be called from Python. + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_7decref_py, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_decref_py, __pyx_t_1) < 0) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":203 + * + * + * def get_func_code_info_py(thread_info, frame, code_obj) -> FuncCodeInfo: # <<<<<<<<<<<<<< + * ''' + * Helper to be called from Python. + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_9get_func_code_info_py, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 203, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_func_code_info_py, __pyx_t_1) < 0) __PYX_ERR(0, 203, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":210 + * + * + * cdef int _code_extra_index = -1 # <<<<<<<<<<<<<< + * + * cdef FuncCodeInfo get_func_code_info(ThreadInfo thread_info, PyFrameObject * frame_obj, PyCodeObject * code_obj): + */ + __pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator__code_extra_index = -1; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":329 + * + * # Note: this method has a version in pure-python too. + * def _get_code_line_info(code_obj): # <<<<<<<<<<<<<< + * line_to_offset: dict = {} + * first_line: int = None + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_11_get_code_line_info, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 329, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_code_line_info, __pyx_t_1) < 0) __PYX_ERR(0, 329, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":351 + * # handled by the cython side in `FuncCodeInfo get_func_code_info` by providing the + * # same code info if the debugger mtime is still the same). + * _cache: dict = {} # <<<<<<<<<<<<<< + * + * def get_cached_code_obj_info_py(code_obj_py): + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 351, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_cache, __pyx_t_1) < 0) __PYX_ERR(0, 351, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":353 + * _cache: dict = {} + * + * def get_cached_code_obj_info_py(code_obj_py): # <<<<<<<<<<<<<< + * ''' + * :return _CacheValue: + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_13get_cached_code_obj_info_py, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 353, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_cached_code_obj_info_py, __pyx_t_1) < 0) __PYX_ERR(0, 353, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":401 + * return breakpoint_found, force_stay_in_untraced_mode + * + * def generate_code_with_breakpoints_py(object code_obj_py, dict breakpoints): # <<<<<<<<<<<<<< + * return generate_code_with_breakpoints(code_obj_py, breakpoints) + * + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_15generate_code_with_breakpoints_py, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 401, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_generate_code_with_breakpoints_p, __pyx_t_1) < 0) __PYX_ERR(0, 401, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":471 + * return breakpoint_found, code_obj_py + * + * import sys # <<<<<<<<<<<<<< + * + * cdef bint IS_PY_39_OWNARDS = sys.version_info[:2] >= (3, 9) + */ + __pyx_t_1 = __Pyx_Import(__pyx_n_s_sys, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 471, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_sys, __pyx_t_1) < 0) __PYX_ERR(0, 471, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":473 + * import sys + * + * cdef bint IS_PY_39_OWNARDS = sys.version_info[:2] >= (3, 9) # <<<<<<<<<<<<<< + * + * def frame_eval_func(): + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_sys); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 473, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_version_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 473, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_t_2, 0, 2, NULL, NULL, &__pyx_slice__24, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 473, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_tuple__25, Py_GE); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 473, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 473, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_18_pydevd_frame_eval_22pydevd_frame_evaluator_IS_PY_39_OWNARDS = __pyx_t_3; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":475 + * cdef bint IS_PY_39_OWNARDS = sys.version_info[:2] >= (3, 9) + * + * def frame_eval_func(): # <<<<<<<<<<<<<< + * cdef PyThreadState *state = PyThreadState_Get() + * if IS_PY_39_OWNARDS: + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_17frame_eval_func, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 475, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_frame_eval_func, __pyx_t_2) < 0) __PYX_ERR(0, 475, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":484 + * + * + * def stop_frame_eval(): # <<<<<<<<<<<<<< + * cdef PyThreadState *state = PyThreadState_Get() + * state.interp.eval_frame = _PyEval_EvalFrameDefault + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_19stop_frame_eval, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 484, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_stop_frame_eval, __pyx_t_2) < 0) __PYX_ERR(0, 484, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "(tree fragment)":1 + * def __pyx_unpickle_ThreadInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_21__pyx_unpickle_ThreadInfo, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_ThreadInfo, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "(tree fragment)":11 + * __pyx_unpickle_ThreadInfo__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_ThreadInfo__set_state(ThreadInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result._can_create_dummy_thread = __pyx_state[0]; __pyx_result.additional_info = __pyx_state[1]; __pyx_result.force_stay_in_untraced_mode = __pyx_state[2]; __pyx_result.fully_initialized = __pyx_state[3]; __pyx_result.inside_frame_eval = __pyx_state[4]; __pyx_result.is_pydevd_thread = __pyx_state[5]; __pyx_result.thread_trace_func = __pyx_state[6] + * if len(__pyx_state) > 7 and hasattr(__pyx_result, '__dict__'): + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_23__pyx_unpickle_FuncCodeInfo, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_FuncCodeInfo, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "(tree fragment)":1 + * def __pyx_unpickle__CodeLineInfo(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_25__pyx_unpickle__CodeLineInfo, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle__CodeLineInfo, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "(tree fragment)":11 + * __pyx_unpickle__CodeLineInfo__set_state(<_CodeLineInfo> __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle__CodeLineInfo__set_state(_CodeLineInfo __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< + * __pyx_result.first_line = __pyx_state[0]; __pyx_result.last_line = __pyx_state[1]; __pyx_result.line_to_offset = __pyx_state[2] + * if len(__pyx_state) > 3 and hasattr(__pyx_result, '__dict__'): + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_18_pydevd_frame_eval_22pydevd_frame_evaluator_27__pyx_unpickle__CacheValue, NULL, __pyx_n_s_pydevd_frame_eval_pydevd_frame_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle__CacheValue, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "_pydevd_frame_eval/pydevd_frame_evaluator.pyx":1 + * from __future__ import print_function # <<<<<<<<<<<<<< + * from _pydev_bundle._pydev_saved_modules import threading, thread + * from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder + */ + __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init _pydevd_frame_eval.pydevd_frame_evaluator", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init _pydevd_frame_eval.pydevd_frame_evaluator"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 + return __pyx_m; + #else + return; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* GetBuiltinName */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* PyDictVersioning */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ +#if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if !CYTHON_AVOID_BORROWED_REFS +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 + result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } else if (unlikely(PyErr_Occurred())) { + return NULL; + } +#else + result = PyDict_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } +#endif +#else + result = PyObject_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); +} + +/* PyFunctionFastCall */ +#if CYTHON_FAST_PYCALL +static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { + PyFrameObject *f; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject **fastlocals; + Py_ssize_t i; + PyObject *result; + assert(globals != NULL); + /* XXX Perhaps we should create a specialized + PyFrame_New() that doesn't take locals, but does + take builtins without sanity checking them. + */ + assert(tstate != NULL); + f = PyFrame_New(tstate, co, globals, NULL); + if (f == NULL) { + return NULL; + } + fastlocals = __Pyx_PyFrame_GetLocalsplus(f); + for (i = 0; i < na; i++) { + Py_INCREF(*args); + fastlocals[i] = *args++; + } + result = PyEval_EvalFrameEx(f,0); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return result; +} +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure; +#if PY_MAJOR_VERSION >= 3 + PyObject *kwdefs; +#endif + PyObject *kwtuple, **k; + PyObject **d; + Py_ssize_t nd; + Py_ssize_t nk; + PyObject *result; + assert(kwargs == NULL || PyDict_Check(kwargs)); + nk = kwargs ? PyDict_Size(kwargs) : 0; + if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { + return NULL; + } + if ( +#if PY_MAJOR_VERSION >= 3 + co->co_kwonlyargcount == 0 && +#endif + likely(kwargs == NULL || nk == 0) && + co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { + if (argdefs == NULL && co->co_argcount == nargs) { + result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); + goto done; + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); + goto done; + } + } + if (kwargs != NULL) { + Py_ssize_t pos, i; + kwtuple = PyTuple_New(2 * nk); + if (kwtuple == NULL) { + result = NULL; + goto done; + } + k = &PyTuple_GET_ITEM(kwtuple, 0); + pos = i = 0; + while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); + i += 2; + } + nk = i / 2; + } + else { + kwtuple = NULL; + k = NULL; + } + closure = PyFunction_GET_CLOSURE(func); +#if PY_MAJOR_VERSION >= 3 + kwdefs = PyFunction_GET_KW_DEFAULTS(func); +#endif + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = Py_SIZE(argdefs); + } + else { + d = NULL; + nd = 0; + } +#if PY_MAJOR_VERSION >= 3 + result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, kwdefs, closure); +#else + result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, closure); +#endif + Py_XDECREF(kwtuple); +done: + Py_LeaveRecursiveCall(); + return result; +} +#endif +#endif + +/* PyObjectCall */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = Py_TYPE(func)->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallNoArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, NULL, 0); + } +#endif +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) +#else + if (likely(PyCFunction_Check(func))) +#endif + { + if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { + return __Pyx_PyObject_CallMethO(func, NULL); + } + } + return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); +} +#endif + +/* PyCFunctionFastCall */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { + PyCFunctionObject *func = (PyCFunctionObject*)func_obj; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + assert(PyCFunction_Check(func)); + assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + /* _PyCFunction_FastCallDict() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller loses its exception */ + assert(!PyErr_Occurred()); + if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { + return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); + } else { + return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); + } +} +#endif + +/* PyObjectCallOneArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (__Pyx_PyFastCFunction_Check(func)) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* PyObjectCall2Args */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { + PyObject *args, *result = NULL; + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyFunction_FastCall(function, args, 2); + } + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyCFunction_FastCall(function, args, 2); + } + #endif + args = PyTuple_New(2); + if (unlikely(!args)) goto done; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + Py_INCREF(function); + result = __Pyx_PyObject_Call(function, args, NULL); + Py_DECREF(args); + Py_DECREF(function); +done: + return result; +} + +/* PyIntBinop */ +#if !CYTHON_COMPILING_IN_PYPY +static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, int inplace, int zerodivision_check) { + (void)inplace; + (void)zerodivision_check; + #if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(op1))) { + const long b = intval; + long x; + long a = PyInt_AS_LONG(op1); + x = (long)((unsigned long)a + b); + if (likely((x^a) >= 0 || (x^b) >= 0)) + return PyInt_FromLong(x); + return PyLong_Type.tp_as_number->nb_add(op1, op2); + } + #endif + #if CYTHON_USE_PYLONG_INTERNALS + if (likely(PyLong_CheckExact(op1))) { + const long b = intval; + long a, x; +#ifdef HAVE_LONG_LONG + const PY_LONG_LONG llb = intval; + PY_LONG_LONG lla, llx; +#endif + const digit* digits = ((PyLongObject*)op1)->ob_digit; + const Py_ssize_t size = Py_SIZE(op1); + if (likely(__Pyx_sst_abs(size) <= 1)) { + a = likely(size) ? digits[0] : 0; + if (size == -1) a = -a; + } else { + switch (size) { + case -2: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + a = -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 2: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case -3: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + a = -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 3: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case -4: + if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + a = -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 4: + if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + default: return PyLong_Type.tp_as_number->nb_add(op1, op2); + } + } + x = a + b; + return PyLong_FromLong(x); +#ifdef HAVE_LONG_LONG + long_long: + llx = lla + llb; + return PyLong_FromLongLong(llx); +#endif + + + } + #endif + if (PyFloat_CheckExact(op1)) { + const long b = intval; + double a = PyFloat_AS_DOUBLE(op1); + double result; + PyFPE_START_PROTECT("add", return NULL) + result = ((double)a) + (double)b; + PyFPE_END_PROTECT(result) + return PyFloat_FromDouble(result); + } + return (inplace ? PyNumber_InPlaceAdd : PyNumber_Add)(op1, op2); +} +#endif + +/* SliceObject */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj, + Py_ssize_t cstart, Py_ssize_t cstop, + PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice, + int has_cstart, int has_cstop, CYTHON_UNUSED int wraparound) { +#if CYTHON_USE_TYPE_SLOTS + PyMappingMethods* mp; +#if PY_MAJOR_VERSION < 3 + PySequenceMethods* ms = Py_TYPE(obj)->tp_as_sequence; + if (likely(ms && ms->sq_slice)) { + if (!has_cstart) { + if (_py_start && (*_py_start != Py_None)) { + cstart = __Pyx_PyIndex_AsSsize_t(*_py_start); + if ((cstart == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; + } else + cstart = 0; + } + if (!has_cstop) { + if (_py_stop && (*_py_stop != Py_None)) { + cstop = __Pyx_PyIndex_AsSsize_t(*_py_stop); + if ((cstop == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; + } else + cstop = PY_SSIZE_T_MAX; + } + if (wraparound && unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) { + Py_ssize_t l = ms->sq_length(obj); + if (likely(l >= 0)) { + if (cstop < 0) { + cstop += l; + if (cstop < 0) cstop = 0; + } + if (cstart < 0) { + cstart += l; + if (cstart < 0) cstart = 0; + } + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + goto bad; + PyErr_Clear(); + } + } + return ms->sq_slice(obj, cstart, cstop); + } +#endif + mp = Py_TYPE(obj)->tp_as_mapping; + if (likely(mp && mp->mp_subscript)) +#endif + { + PyObject* result; + PyObject *py_slice, *py_start, *py_stop; + if (_py_slice) { + py_slice = *_py_slice; + } else { + PyObject* owned_start = NULL; + PyObject* owned_stop = NULL; + if (_py_start) { + py_start = *_py_start; + } else { + if (has_cstart) { + owned_start = py_start = PyInt_FromSsize_t(cstart); + if (unlikely(!py_start)) goto bad; + } else + py_start = Py_None; + } + if (_py_stop) { + py_stop = *_py_stop; + } else { + if (has_cstop) { + owned_stop = py_stop = PyInt_FromSsize_t(cstop); + if (unlikely(!py_stop)) { + Py_XDECREF(owned_start); + goto bad; + } + } else + py_stop = Py_None; + } + py_slice = PySlice_New(py_start, py_stop, Py_None); + Py_XDECREF(owned_start); + Py_XDECREF(owned_stop); + if (unlikely(!py_slice)) goto bad; + } +#if CYTHON_USE_TYPE_SLOTS + result = mp->mp_subscript(obj, py_slice); +#else + result = PyObject_GetItem(obj, py_slice); +#endif + if (!_py_slice) { + Py_DECREF(py_slice); + } + return result; + } + PyErr_Format(PyExc_TypeError, + "'%.200s' object is unsliceable", Py_TYPE(obj)->tp_name); +bad: + return NULL; +} + +/* BytesEquals */ +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) { +#if CYTHON_COMPILING_IN_PYPY + return PyObject_RichCompareBool(s1, s2, equals); +#else + if (s1 == s2) { + return (equals == Py_EQ); + } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) { + const char *ps1, *ps2; + Py_ssize_t length = PyBytes_GET_SIZE(s1); + if (length != PyBytes_GET_SIZE(s2)) + return (equals == Py_NE); + ps1 = PyBytes_AS_STRING(s1); + ps2 = PyBytes_AS_STRING(s2); + if (ps1[0] != ps2[0]) { + return (equals == Py_NE); + } else if (length == 1) { + return (equals == Py_EQ); + } else { + int result; +#if CYTHON_USE_UNICODE_INTERNALS && (PY_VERSION_HEX < 0x030B0000) + Py_hash_t hash1, hash2; + hash1 = ((PyBytesObject*)s1)->ob_shash; + hash2 = ((PyBytesObject*)s2)->ob_shash; + if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { + return (equals == Py_NE); + } +#endif + result = memcmp(ps1, ps2, (size_t)length); + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) { + return (equals == Py_NE); + } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) { + return (equals == Py_NE); + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +#endif +} + +/* UnicodeEquals */ +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) { +#if CYTHON_COMPILING_IN_PYPY + return PyObject_RichCompareBool(s1, s2, equals); +#else +#if PY_MAJOR_VERSION < 3 + PyObject* owned_ref = NULL; +#endif + int s1_is_unicode, s2_is_unicode; + if (s1 == s2) { + goto return_eq; + } + s1_is_unicode = PyUnicode_CheckExact(s1); + s2_is_unicode = PyUnicode_CheckExact(s2); +#if PY_MAJOR_VERSION < 3 + if ((s1_is_unicode & (!s2_is_unicode)) && PyString_CheckExact(s2)) { + owned_ref = PyUnicode_FromObject(s2); + if (unlikely(!owned_ref)) + return -1; + s2 = owned_ref; + s2_is_unicode = 1; + } else if ((s2_is_unicode & (!s1_is_unicode)) && PyString_CheckExact(s1)) { + owned_ref = PyUnicode_FromObject(s1); + if (unlikely(!owned_ref)) + return -1; + s1 = owned_ref; + s1_is_unicode = 1; + } else if (((!s2_is_unicode) & (!s1_is_unicode))) { + return __Pyx_PyBytes_Equals(s1, s2, equals); + } +#endif + if (s1_is_unicode & s2_is_unicode) { + Py_ssize_t length; + int kind; + void *data1, *data2; + if (unlikely(__Pyx_PyUnicode_READY(s1) < 0) || unlikely(__Pyx_PyUnicode_READY(s2) < 0)) + return -1; + length = __Pyx_PyUnicode_GET_LENGTH(s1); + if (length != __Pyx_PyUnicode_GET_LENGTH(s2)) { + goto return_ne; + } +#if CYTHON_USE_UNICODE_INTERNALS + { + Py_hash_t hash1, hash2; + #if CYTHON_PEP393_ENABLED + hash1 = ((PyASCIIObject*)s1)->hash; + hash2 = ((PyASCIIObject*)s2)->hash; + #else + hash1 = ((PyUnicodeObject*)s1)->hash; + hash2 = ((PyUnicodeObject*)s2)->hash; + #endif + if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { + goto return_ne; + } + } +#endif + kind = __Pyx_PyUnicode_KIND(s1); + if (kind != __Pyx_PyUnicode_KIND(s2)) { + goto return_ne; + } + data1 = __Pyx_PyUnicode_DATA(s1); + data2 = __Pyx_PyUnicode_DATA(s2); + if (__Pyx_PyUnicode_READ(kind, data1, 0) != __Pyx_PyUnicode_READ(kind, data2, 0)) { + goto return_ne; + } else if (length == 1) { + goto return_eq; + } else { + int result = memcmp(data1, data2, (size_t)(length * kind)); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(owned_ref); + #endif + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & s2_is_unicode) { + goto return_ne; + } else if ((s2 == Py_None) & s1_is_unicode) { + goto return_ne; + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(owned_ref); + #endif + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +return_eq: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(owned_ref); + #endif + return (equals == Py_EQ); +return_ne: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(owned_ref); + #endif + return (equals == Py_NE); +#endif +} + +/* PyErrExceptionMatches */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; icurexc_type; + if (exc_type == err) return 1; + if (unlikely(!exc_type)) return 0; + if (unlikely(PyTuple_Check(err))) + return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); + return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); +} +#endif + +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* GetAttr */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) { +#if CYTHON_USE_TYPE_SLOTS +#if PY_MAJOR_VERSION >= 3 + if (likely(PyUnicode_Check(n))) +#else + if (likely(PyString_Check(n))) +#endif + return __Pyx_PyObject_GetAttrStr(o, n); +#endif + return PyObject_GetAttr(o, n); +} + +/* GetAttr3 */ +static PyObject *__Pyx_GetAttr3Default(PyObject *d) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + return NULL; + __Pyx_PyErr_Clear(); + Py_INCREF(d); + return d; +} +static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { + PyObject *r = __Pyx_GetAttr(o, n); + return (likely(r)) ? r : __Pyx_GetAttr3Default(d); +} + +/* RaiseException */ +#if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, + CYTHON_UNUSED PyObject *cause) { + __Pyx_PyThreadState_declare + Py_XINCREF(type); + if (!value || value == Py_None) + value = NULL; + else + Py_INCREF(value); + if (!tb || tb == Py_None) + tb = NULL; + else { + Py_INCREF(tb); + if (!PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + } + if (PyType_Check(type)) { +#if CYTHON_COMPILING_IN_PYPY + if (!value) { + Py_INCREF(Py_None); + value = Py_None; + } +#endif + PyErr_NormalizeException(&type, &value, &tb); + } else { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + value = type; + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + } + __Pyx_PyThreadState_assign + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} +#else +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + if (cause) { + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if CYTHON_COMPILING_IN_PYPY + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#else + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} +#endif + +/* GetTopmostException */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * +__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) +{ + _PyErr_StackItem *exc_info = tstate->exc_info; + while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + exc_info->previous_item != NULL) + { + exc_info = exc_info->previous_item; + } + return exc_info; +} +#endif + +/* SaveResetException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + *type = exc_info->exc_type; + *value = exc_info->exc_value; + *tb = exc_info->exc_traceback; + #else + *type = tstate->exc_type; + *value = tstate->exc_value; + *tb = tstate->exc_traceback; + #endif + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); +} +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = type; + exc_info->exc_value = value; + exc_info->exc_traceback = tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = type; + tstate->exc_value = value; + tstate->exc_traceback = tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +#endif + +/* GetException */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) +#endif +{ + PyObject *local_type, *local_value, *local_tb; +#if CYTHON_FAST_THREAD_STATE + PyObject *tmp_type, *tmp_value, *tmp_tb; + local_type = tstate->curexc_type; + local_value = tstate->curexc_value; + local_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +#else + PyErr_Fetch(&local_type, &local_value, &local_tb); +#endif + PyErr_NormalizeException(&local_type, &local_value, &local_tb); +#if CYTHON_FAST_THREAD_STATE + if (unlikely(tstate->curexc_type)) +#else + if (unlikely(PyErr_Occurred())) +#endif + goto bad; + #if PY_MAJOR_VERSION >= 3 + if (local_tb) { + if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) + goto bad; + } + #endif + Py_XINCREF(local_tb); + Py_XINCREF(local_type); + Py_XINCREF(local_value); + *type = local_type; + *value = local_value; + *tb = local_tb; +#if CYTHON_FAST_THREAD_STATE + #if CYTHON_USE_EXC_INFO_STACK + { + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = local_type; + exc_info->exc_value = local_value; + exc_info->exc_traceback = local_tb; + } + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = local_type; + tstate->exc_value = local_value; + tstate->exc_traceback = local_tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#else + PyErr_SetExcInfo(local_type, local_value, local_tb); +#endif + return 0; +bad: + *type = 0; + *value = 0; + *tb = 0; + Py_XDECREF(local_type); + Py_XDECREF(local_value); + Py_XDECREF(local_tb); + return -1; +} + +/* PyObjectSetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_setattro)) + return tp->tp_setattro(obj, attr_name, value); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_setattr)) + return tp->tp_setattr(obj, PyString_AS_STRING(attr_name), value); +#endif + return PyObject_SetAttr(obj, attr_name, value); +} +#endif + +/* None */ +static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { + PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); +} + +/* ExtTypeTest */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + if (likely(__Pyx_TypeCheck(obj, type))) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", + Py_TYPE(obj)->tp_name, type->tp_name); + return 0; +} + +/* SwapException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = *type; + exc_info->exc_value = *value; + exc_info->exc_traceback = *tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = *type; + tstate->exc_value = *value; + tstate->exc_traceback = *tb; + #endif + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb); + PyErr_SetExcInfo(*type, *value, *tb); + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#endif + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* KeywordStringCheck */ +static int __Pyx_CheckKeywordStrings( + PyObject *kwdict, + const char* function_name, + int kw_allowed) +{ + PyObject* key = 0; + Py_ssize_t pos = 0; +#if CYTHON_COMPILING_IN_PYPY + if (!kw_allowed && PyDict_Next(kwdict, &pos, &key, 0)) + goto invalid_keyword; + return 1; +#else + while (PyDict_Next(kwdict, &pos, &key, 0)) { + #if PY_MAJOR_VERSION < 3 + if (unlikely(!PyString_Check(key))) + #endif + if (unlikely(!PyUnicode_Check(key))) + goto invalid_keyword_type; + } + if ((!kw_allowed) && unlikely(key)) + goto invalid_keyword; + return 1; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + return 0; +#endif +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif + return 0; +} + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* ArgTypeTest */ +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) +{ + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + else if (exact) { + #if PY_MAJOR_VERSION == 2 + if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; + #endif + } + else { + if (likely(__Pyx_TypeCheck(obj, type))) return 1; + } + PyErr_Format(PyExc_TypeError, + "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); + return 0; +} + +/* DictGetItem */ +#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY +static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { + PyObject *value; + value = PyDict_GetItemWithError(d, key); + if (unlikely(!value)) { + if (!PyErr_Occurred()) { + if (unlikely(PyTuple_Check(key))) { + PyObject* args = PyTuple_Pack(1, key); + if (likely(args)) { + PyErr_SetObject(PyExc_KeyError, args); + Py_DECREF(args); + } + } else { + PyErr_SetObject(PyExc_KeyError, key); + } + } + return NULL; + } + Py_INCREF(value); + return value; +} +#endif + +/* GetItemInt */ +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (!j) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyList_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { + PyObject *r = PyList_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyTuple_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); + if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { + PyObject *r = PyList_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } + else if (PyTuple_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } else { + PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; + if (likely(m && m->sq_item)) { + if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { + Py_ssize_t l = m->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return NULL; + PyErr_Clear(); + } + } + return m->sq_item(o, i); + } + } +#else + if (is_list || PySequence_Check(o)) { + return PySequence_GetItem(o, i); + } +#endif + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +} + +/* RaiseTooManyValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { + PyErr_Format(PyExc_ValueError, + "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); +} + +/* RaiseNeedMoreValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", + index, (index == 1) ? "" : "s"); +} + +/* IterFinish */ +static CYTHON_INLINE int __Pyx_IterFinish(void) { +#if CYTHON_FAST_THREAD_STATE + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* exc_type = tstate->curexc_type; + if (unlikely(exc_type)) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) { + PyObject *exc_value, *exc_tb; + exc_value = tstate->curexc_value; + exc_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; + Py_DECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); + return 0; + } else { + return -1; + } + } + return 0; +#else + if (unlikely(PyErr_Occurred())) { + if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) { + PyErr_Clear(); + return 0; + } else { + return -1; + } + } + return 0; +#endif +} + +/* UnpackItemEndCheck */ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { + if (unlikely(retval)) { + Py_DECREF(retval); + __Pyx_RaiseTooManyValuesError(expected); + return -1; + } else { + return __Pyx_IterFinish(); + } + return 0; +} + +/* PyObjectGetMethod */ +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { + PyObject *attr; +#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP + PyTypeObject *tp = Py_TYPE(obj); + PyObject *descr; + descrgetfunc f = NULL; + PyObject **dictptr, *dict; + int meth_found = 0; + assert (*method == NULL); + if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; + } + if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { + return 0; + } + descr = _PyType_Lookup(tp, name); + if (likely(descr != NULL)) { + Py_INCREF(descr); +#if PY_MAJOR_VERSION >= 3 + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type))) + #endif +#else + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr))) + #endif +#endif + { + meth_found = 1; + } else { + f = Py_TYPE(descr)->tp_descr_get; + if (f != NULL && PyDescr_IsData(descr)) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + } + } + dictptr = _PyObject_GetDictPtr(obj); + if (dictptr != NULL && (dict = *dictptr) != NULL) { + Py_INCREF(dict); + attr = __Pyx_PyDict_GetItemStr(dict, name); + if (attr != NULL) { + Py_INCREF(attr); + Py_DECREF(dict); + Py_XDECREF(descr); + goto try_unpack; + } + Py_DECREF(dict); + } + if (meth_found) { + *method = descr; + return 1; + } + if (f != NULL) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + if (descr != NULL) { + *method = descr; + return 0; + } + PyErr_Format(PyExc_AttributeError, +#if PY_MAJOR_VERSION >= 3 + "'%.50s' object has no attribute '%U'", + tp->tp_name, name); +#else + "'%.50s' object has no attribute '%.400s'", + tp->tp_name, PyString_AS_STRING(name)); +#endif + return 0; +#else + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; +#endif +try_unpack: +#if CYTHON_UNPACK_METHODS + if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { + PyObject *function = PyMethod_GET_FUNCTION(attr); + Py_INCREF(function); + Py_DECREF(attr); + *method = function; + return 1; + } +#endif + *method = attr; + return 0; +} + +/* PyObjectCallMethod0 */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) { + PyObject *method = NULL, *result = NULL; + int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); + if (likely(is_method)) { + result = __Pyx_PyObject_CallOneArg(method, obj); + Py_DECREF(method); + return result; + } + if (unlikely(!method)) goto bad; + result = __Pyx_PyObject_CallNoArg(method); + Py_DECREF(method); +bad: + return result; +} + +/* RaiseNoneIterError */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); +} + +/* UnpackTupleError */ +static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) { + if (t == Py_None) { + __Pyx_RaiseNoneNotIterableError(); + } else if (PyTuple_GET_SIZE(t) < index) { + __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t)); + } else { + __Pyx_RaiseTooManyValuesError(index); + } +} + +/* UnpackTuple2 */ +static CYTHON_INLINE int __Pyx_unpack_tuple2_exact( + PyObject* tuple, PyObject** pvalue1, PyObject** pvalue2, int decref_tuple) { + PyObject *value1 = NULL, *value2 = NULL; +#if CYTHON_COMPILING_IN_PYPY + value1 = PySequence_ITEM(tuple, 0); if (unlikely(!value1)) goto bad; + value2 = PySequence_ITEM(tuple, 1); if (unlikely(!value2)) goto bad; +#else + value1 = PyTuple_GET_ITEM(tuple, 0); Py_INCREF(value1); + value2 = PyTuple_GET_ITEM(tuple, 1); Py_INCREF(value2); +#endif + if (decref_tuple) { + Py_DECREF(tuple); + } + *pvalue1 = value1; + *pvalue2 = value2; + return 0; +#if CYTHON_COMPILING_IN_PYPY +bad: + Py_XDECREF(value1); + Py_XDECREF(value2); + if (decref_tuple) { Py_XDECREF(tuple); } + return -1; +#endif +} +static int __Pyx_unpack_tuple2_generic(PyObject* tuple, PyObject** pvalue1, PyObject** pvalue2, + int has_known_size, int decref_tuple) { + Py_ssize_t index; + PyObject *value1 = NULL, *value2 = NULL, *iter = NULL; + iternextfunc iternext; + iter = PyObject_GetIter(tuple); + if (unlikely(!iter)) goto bad; + if (decref_tuple) { Py_DECREF(tuple); tuple = NULL; } + iternext = Py_TYPE(iter)->tp_iternext; + value1 = iternext(iter); if (unlikely(!value1)) { index = 0; goto unpacking_failed; } + value2 = iternext(iter); if (unlikely(!value2)) { index = 1; goto unpacking_failed; } + if (!has_known_size && unlikely(__Pyx_IternextUnpackEndCheck(iternext(iter), 2))) goto bad; + Py_DECREF(iter); + *pvalue1 = value1; + *pvalue2 = value2; + return 0; +unpacking_failed: + if (!has_known_size && __Pyx_IterFinish() == 0) + __Pyx_RaiseNeedMoreValuesError(index); +bad: + Py_XDECREF(iter); + Py_XDECREF(value1); + Py_XDECREF(value2); + if (decref_tuple) { Py_XDECREF(tuple); } + return -1; +} + +/* dict_iter */ +static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* iterable, int is_dict, PyObject* method_name, + Py_ssize_t* p_orig_length, int* p_source_is_dict) { + is_dict = is_dict || likely(PyDict_CheckExact(iterable)); + *p_source_is_dict = is_dict; + if (is_dict) { +#if !CYTHON_COMPILING_IN_PYPY + *p_orig_length = PyDict_Size(iterable); + Py_INCREF(iterable); + return iterable; +#elif PY_MAJOR_VERSION >= 3 + static PyObject *py_items = NULL, *py_keys = NULL, *py_values = NULL; + PyObject **pp = NULL; + if (method_name) { + const char *name = PyUnicode_AsUTF8(method_name); + if (strcmp(name, "iteritems") == 0) pp = &py_items; + else if (strcmp(name, "iterkeys") == 0) pp = &py_keys; + else if (strcmp(name, "itervalues") == 0) pp = &py_values; + if (pp) { + if (!*pp) { + *pp = PyUnicode_FromString(name + 4); + if (!*pp) + return NULL; + } + method_name = *pp; + } + } +#endif + } + *p_orig_length = 0; + if (method_name) { + PyObject* iter; + iterable = __Pyx_PyObject_CallMethod0(iterable, method_name); + if (!iterable) + return NULL; +#if !CYTHON_COMPILING_IN_PYPY + if (PyTuple_CheckExact(iterable) || PyList_CheckExact(iterable)) + return iterable; +#endif + iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + return iter; + } + return PyObject_GetIter(iterable); +} +static CYTHON_INLINE int __Pyx_dict_iter_next( + PyObject* iter_obj, CYTHON_NCP_UNUSED Py_ssize_t orig_length, CYTHON_NCP_UNUSED Py_ssize_t* ppos, + PyObject** pkey, PyObject** pvalue, PyObject** pitem, int source_is_dict) { + PyObject* next_item; +#if !CYTHON_COMPILING_IN_PYPY + if (source_is_dict) { + PyObject *key, *value; + if (unlikely(orig_length != PyDict_Size(iter_obj))) { + PyErr_SetString(PyExc_RuntimeError, "dictionary changed size during iteration"); + return -1; + } + if (unlikely(!PyDict_Next(iter_obj, ppos, &key, &value))) { + return 0; + } + if (pitem) { + PyObject* tuple = PyTuple_New(2); + if (unlikely(!tuple)) { + return -1; + } + Py_INCREF(key); + Py_INCREF(value); + PyTuple_SET_ITEM(tuple, 0, key); + PyTuple_SET_ITEM(tuple, 1, value); + *pitem = tuple; + } else { + if (pkey) { + Py_INCREF(key); + *pkey = key; + } + if (pvalue) { + Py_INCREF(value); + *pvalue = value; + } + } + return 1; + } else if (PyTuple_CheckExact(iter_obj)) { + Py_ssize_t pos = *ppos; + if (unlikely(pos >= PyTuple_GET_SIZE(iter_obj))) return 0; + *ppos = pos + 1; + next_item = PyTuple_GET_ITEM(iter_obj, pos); + Py_INCREF(next_item); + } else if (PyList_CheckExact(iter_obj)) { + Py_ssize_t pos = *ppos; + if (unlikely(pos >= PyList_GET_SIZE(iter_obj))) return 0; + *ppos = pos + 1; + next_item = PyList_GET_ITEM(iter_obj, pos); + Py_INCREF(next_item); + } else +#endif + { + next_item = PyIter_Next(iter_obj); + if (unlikely(!next_item)) { + return __Pyx_IterFinish(); + } + } + if (pitem) { + *pitem = next_item; + } else if (pkey && pvalue) { + if (__Pyx_unpack_tuple2(next_item, pkey, pvalue, source_is_dict, source_is_dict, 1)) + return -1; + } else if (pkey) { + *pkey = next_item; + } else { + *pvalue = next_item; + } + return 1; +} + +/* WriteUnraisableException */ +static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, + CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, + int full_traceback, CYTHON_UNUSED int nogil) { + PyObject *old_exc, *old_val, *old_tb; + PyObject *ctx; + __Pyx_PyThreadState_declare +#ifdef WITH_THREAD + PyGILState_STATE state; + if (nogil) + state = PyGILState_Ensure(); +#ifdef _MSC_VER + else state = (PyGILState_STATE)-1; +#endif +#endif + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); + if (full_traceback) { + Py_XINCREF(old_exc); + Py_XINCREF(old_val); + Py_XINCREF(old_tb); + __Pyx_ErrRestore(old_exc, old_val, old_tb); + PyErr_PrintEx(1); + } + #if PY_MAJOR_VERSION < 3 + ctx = PyString_FromString(name); + #else + ctx = PyUnicode_FromString(name); + #endif + __Pyx_ErrRestore(old_exc, old_val, old_tb); + if (!ctx) { + PyErr_WriteUnraisable(Py_None); + } else { + PyErr_WriteUnraisable(ctx); + Py_DECREF(ctx); + } +#ifdef WITH_THREAD + if (nogil) + PyGILState_Release(state); +#endif +} + +/* Import */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + #if PY_MAJOR_VERSION < 3 + PyObject *py_import; + py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); + if (!py_import) + goto bad; + #endif + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + { + #if PY_MAJOR_VERSION >= 3 + if (level == -1) { + if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) { + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, 1); + if (!module) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + goto bad; + PyErr_Clear(); + } + } + level = 0; + } + #endif + if (!module) { + #if PY_MAJOR_VERSION < 3 + PyObject *py_level = PyInt_FromLong(level); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); + Py_DECREF(py_level); + #else + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, level); + #endif + } + } +bad: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_import); + #endif + Py_XDECREF(empty_list); + Py_XDECREF(empty_dict); + return module; +} + +/* ImportFrom */ +static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { + PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); + if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_ImportError, + #if PY_MAJOR_VERSION < 3 + "cannot import name %.230s", PyString_AS_STRING(name)); + #else + "cannot import name %S", name); + #endif + } + return value; +} + +/* HasAttr */ +static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) { + PyObject *r; + if (unlikely(!__Pyx_PyBaseString_Check(n))) { + PyErr_SetString(PyExc_TypeError, + "hasattr(): attribute name must be string"); + return -1; + } + r = __Pyx_GetAttr(o, n); + if (unlikely(!r)) { + PyErr_Clear(); + return 0; + } else { + Py_DECREF(r); + return 1; + } +} + +/* PyObject_GenericGetAttrNoDict */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) { + PyErr_Format(PyExc_AttributeError, +#if PY_MAJOR_VERSION >= 3 + "'%.50s' object has no attribute '%U'", + tp->tp_name, attr_name); +#else + "'%.50s' object has no attribute '%.400s'", + tp->tp_name, PyString_AS_STRING(attr_name)); +#endif + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { + PyObject *descr; + PyTypeObject *tp = Py_TYPE(obj); + if (unlikely(!PyString_Check(attr_name))) { + return PyObject_GenericGetAttr(obj, attr_name); + } + assert(!tp->tp_dictoffset); + descr = _PyType_Lookup(tp, attr_name); + if (unlikely(!descr)) { + return __Pyx_RaiseGenericGetAttributeError(tp, attr_name); + } + Py_INCREF(descr); + #if PY_MAJOR_VERSION < 3 + if (likely(PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))) + #endif + { + descrgetfunc f = Py_TYPE(descr)->tp_descr_get; + if (unlikely(f)) { + PyObject *res = f(descr, obj, (PyObject *)tp); + Py_DECREF(descr); + return res; + } + } + return descr; +} +#endif + +/* PyObject_GenericGetAttr */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) { + if (unlikely(Py_TYPE(obj)->tp_dictoffset)) { + return PyObject_GenericGetAttr(obj, attr_name); + } + return __Pyx_PyObject_GenericGetAttrNoDict(obj, attr_name); +} +#endif + +/* SetVTable */ +static int __Pyx_SetVtable(PyObject *dict, void *vtable) { +#if PY_VERSION_HEX >= 0x02070000 + PyObject *ob = PyCapsule_New(vtable, 0, 0); +#else + PyObject *ob = PyCObject_FromVoidPtr(vtable, 0); +#endif + if (!ob) + goto bad; + if (PyDict_SetItem(dict, __pyx_n_s_pyx_vtable, ob) < 0) + goto bad; + Py_DECREF(ob); + return 0; +bad: + Py_XDECREF(ob); + return -1; +} + +/* PyObjectGetAttrStrNoError */ +static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + __Pyx_PyErr_Clear(); +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { + PyObject *result; +#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1 + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { + return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); + } +#endif + result = __Pyx_PyObject_GetAttrStr(obj, attr_name); + if (unlikely(!result)) { + __Pyx_PyObject_GetAttrStr_ClearAttributeError(); + } + return result; +} + +/* SetupReduce */ +static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { + int ret; + PyObject *name_attr; + name_attr = __Pyx_PyObject_GetAttrStr(meth, __pyx_n_s_name); + if (likely(name_attr)) { + ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); + } else { + ret = -1; + } + if (unlikely(ret < 0)) { + PyErr_Clear(); + ret = 0; + } + Py_XDECREF(name_attr); + return ret; +} +static int __Pyx_setup_reduce(PyObject* type_obj) { + int ret = 0; + PyObject *object_reduce = NULL; + PyObject *object_getstate = NULL; + PyObject *object_reduce_ex = NULL; + PyObject *reduce = NULL; + PyObject *reduce_ex = NULL; + PyObject *reduce_cython = NULL; + PyObject *setstate = NULL; + PyObject *setstate_cython = NULL; + PyObject *getstate = NULL; +#if CYTHON_USE_PYTYPE_LOOKUP + getstate = _PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate); +#else + getstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_getstate); + if (!getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } +#endif + if (getstate) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_getstate = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_getstate); +#else + object_getstate = __Pyx_PyObject_GetAttrStrNoError((PyObject*)&PyBaseObject_Type, __pyx_n_s_getstate); + if (!object_getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } +#endif + if (object_getstate != getstate) { + goto __PYX_GOOD; + } + } +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#else + object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#endif + reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_ex); if (unlikely(!reduce_ex)) goto __PYX_BAD; + if (reduce_ex == object_reduce_ex) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; +#else + object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; +#endif + reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce); if (unlikely(!reduce)) goto __PYX_BAD; + if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_n_s_reduce_cython)) { + reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_reduce_cython); + if (likely(reduce_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (reduce == object_reduce || PyErr_Occurred()) { + goto __PYX_BAD; + } + setstate = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate); + if (!setstate) PyErr_Clear(); + if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_n_s_setstate_cython)) { + setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_setstate_cython); + if (likely(setstate_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (!setstate || PyErr_Occurred()) { + goto __PYX_BAD; + } + } + PyType_Modified((PyTypeObject*)type_obj); + } + } + goto __PYX_GOOD; +__PYX_BAD: + if (!PyErr_Occurred()) + PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for %s", ((PyTypeObject*)type_obj)->tp_name); + ret = -1; +__PYX_GOOD: +#if !CYTHON_USE_PYTYPE_LOOKUP + Py_XDECREF(object_reduce); + Py_XDECREF(object_reduce_ex); + Py_XDECREF(object_getstate); + Py_XDECREF(getstate); +#endif + Py_XDECREF(reduce); + Py_XDECREF(reduce_ex); + Py_XDECREF(reduce_cython); + Py_XDECREF(setstate); + Py_XDECREF(setstate_cython); + return ret; +} + +/* TypeImport */ +#ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, + size_t size, enum __Pyx_ImportType_CheckSize check_size) +{ + PyObject *result = 0; + char warning[200]; + Py_ssize_t basicsize; +#ifdef Py_LIMITED_API + PyObject *py_basicsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if ((size_t)basicsize < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* CLineInTraceback */ +#ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; + #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; + py_srcfile = PyString_FromString(filename); + if (!py_srcfile) goto bad; + #endif + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + if (!py_funcname) goto bad; + #endif + } + #if PY_MAJOR_VERSION < 3 + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline + return py_code; +bad: + Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(int) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(int) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(int) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(int), + little, !is_unsigned); + } +} + +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} +#endif +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; i '9'); + break; + } + if (rt_from_call[i] != ctversion[i]) { + same = 0; + break; + } + } + if (!same) { + char rtversion[5] = {'\0'}; + char message[200]; + for (i=0; i<4; ++i) { + if (rt_from_call[i] == '.') { + if (found_dot) break; + found_dot = 1; + } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { + break; + } + rtversion[i] = rt_from_call[i]; + } + PyOS_snprintf(message, sizeof(message), + "compiletime version %s of module '%.100s' " + "does not match runtime version %s", + ctversion, __Pyx_MODULE_NAME, rtversion); + return PyErr_WarnEx(NULL, message, 1); + } + return 0; +} + +/* InitStrings */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { + while (t->p) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) +#else + if (likely(PyLong_Check(x))) +#endif + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + #if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = m->nb_int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = m->nb_long(x); + } + #else + if (likely(m && m->nb_int)) { + name = "int"; + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); + } +#endif + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { +#else + if (unlikely(!PyLong_CheckExact(res))) { +#endif + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ diff --git a/_pydevd_frame_eval/pydevd_frame_evaluator.pxd b/_pydevd_frame_eval/pydevd_frame_evaluator.pxd new file mode 100644 index 0000000..d8fb5f2 --- /dev/null +++ b/_pydevd_frame_eval/pydevd_frame_evaluator.pxd @@ -0,0 +1,131 @@ +from cpython.mem cimport PyMem_Malloc, PyMem_Free + +cdef extern from *: + ctypedef void PyObject + ctypedef struct PyCodeObject: + int co_argcount; # arguments, except *args */ + int co_kwonlyargcount; # keyword only arguments */ + int co_nlocals; # local variables */ + int co_stacksize; # entries needed for evaluation stack */ + int co_flags; # CO_..., see below */ + int co_firstlineno; # first source line number */ + PyObject *co_code; # instruction opcodes */ + PyObject *co_consts; # list (constants used) */ + PyObject *co_names; # list of strings (names used) */ + PyObject *co_varnames; # tuple of strings (local variable names) */ + PyObject *co_freevars; # tuple of strings (free variable names) */ + PyObject *co_cellvars; # tuple of strings (cell variable names) */ + unsigned char *co_cell2arg; # Maps cell vars which are arguments. */ + PyObject *co_filename; # unicode (where it was loaded from) */ + PyObject *co_name; # unicode (name, for reference) */ + PyObject *co_lnotab; # string (encoding addr<->lineno mapping) See + # Objects/lnotab_notes.txt for details. */ + void *co_zombieframe; # for optimization only (see frameobject.c) */ + PyObject *co_weakreflist; # to support weakrefs to code objects */ + void *co_extra; + +cdef extern from "frameobject.h": + ctypedef struct PyFrameObject: + PyFrameObject *f_back + PyCodeObject *f_code # code segment + PyObject *f_builtins # builtin symbol table (PyDictObject) + PyObject *f_globals # global symbol table (PyDictObject) */ + PyObject *f_locals # local symbol table (any mapping) */ + PyObject **f_valuestack # + PyObject **f_stacktop + PyObject *f_trace # Trace function */ + PyObject *f_exc_type + PyObject *f_exc_value + PyObject *f_exc_traceback + PyObject *f_gen; + + int f_lasti; #/* Last instruction if called */ + int f_lineno; #/* Current line number */ + int f_iblock; #/* index in f_blockstack */ + char f_executing; #/* whether the frame is still executing */ + PyObject *f_localsplus[1]; + +cdef extern from "release_mem.h": + void release_co_extra(void *) + +cdef extern from "code.h": + ctypedef void freefunc(void *) + int _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra) + int _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra) + +# TODO: Things are in a different place for Python 3.11. +# cdef extern from "cpython/code.h": +# ctypedef void freefunc(void *) +# int _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra) +# int _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra) + +cdef extern from "Python.h": + void Py_INCREF(object o) + void Py_DECREF(object o) + object PyImport_ImportModule(char *name) + PyObject* PyObject_CallFunction(PyObject *callable, const char *format, ...) + object PyObject_GetAttrString(object o, char *attr_name) + +cdef extern from "pystate.h": + # ctypedef PyObject* _PyFrameEvalFunction(PyThreadState* tstate, PyFrameObject *frame, int exc) + # ctypedef PyObject* _PyFrameEvalFunction(PyFrameObject *frame, int exc) + ctypedef PyObject* _PyFrameEvalFunction(...) + + ctypedef struct PyInterpreterState: + PyInterpreterState *next + PyInterpreterState *tstate_head + + PyObject *modules + + PyObject *modules_by_index + PyObject *sysdict + PyObject *builtins + PyObject *importlib + + PyObject *codec_search_path + PyObject *codec_search_cache + PyObject *codec_error_registry + int codecs_initialized + int fscodec_initialized + + int dlopenflags + + PyObject *builtins_copy + PyObject *import_func + # Initialized to PyEval_EvalFrameDefault(). + _PyFrameEvalFunction eval_frame + + ctypedef struct PyThreadState: + PyThreadState *prev + PyThreadState *next + PyInterpreterState *interp + # ... + + PyThreadState *PyThreadState_Get() + +cdef extern from "ceval.h": + ''' +#if PY_VERSION_HEX >= 0x03090000 +PyObject * noop(PyFrameObject *frame, int exc) { + return NULL; +} +#define CALL_EvalFrameDefault_38(a, b) noop(a, b) +#define CALL_EvalFrameDefault_39(a, b, c) _PyEval_EvalFrameDefault(a, b, c) +#else +PyObject * noop(PyThreadState* tstate, PyFrameObject *frame, int exc) { + return NULL; +} +#define CALL_EvalFrameDefault_39(a, b, c) noop(a, b, c) +#define CALL_EvalFrameDefault_38(a, b) _PyEval_EvalFrameDefault(a, b) +#endif + ''' + + int _PyEval_RequestCodeExtraIndex(freefunc) + PyFrameObject *PyEval_GetFrame() + PyObject* PyEval_CallFunction(PyObject *callable, const char *format, ...) + + # PyObject* _PyEval_EvalFrameDefault(PyThreadState* tstate, PyFrameObject *frame, int exc) + # PyObject* _PyEval_EvalFrameDefault(PyFrameObject *frame, int exc) + PyObject* _PyEval_EvalFrameDefault(...) + PyObject* CALL_EvalFrameDefault_38(PyFrameObject *frame, int exc) # Actually a macro. + PyObject* CALL_EvalFrameDefault_39(PyThreadState* tstate, PyFrameObject *frame, int exc) # Actually a macro. diff --git a/_pydevd_frame_eval/pydevd_frame_evaluator.template.pyx b/_pydevd_frame_eval/pydevd_frame_evaluator.template.pyx new file mode 100644 index 0000000..1bbf9f8 --- /dev/null +++ b/_pydevd_frame_eval/pydevd_frame_evaluator.template.pyx @@ -0,0 +1,613 @@ +from __future__ import print_function +from _pydev_bundle._pydev_saved_modules import threading, thread +from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder +import dis +import sys +from _pydevd_frame_eval.pydevd_frame_tracing import update_globals_dict, dummy_tracing_holder +from _pydevd_frame_eval.pydevd_modify_bytecode import DebugHelper, insert_pydevd_breaks +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER +from _pydevd_bundle.pydevd_trace_dispatch import fix_top_level_trace_and_get_trace_func + +from _pydevd_bundle.pydevd_additional_thread_info import _set_additional_thread_info_lock +from _pydevd_bundle.pydevd_cython cimport PyDBAdditionalThreadInfo +from pydevd_tracing import SetTrace + +_get_ident = threading.get_ident # Note this is py3 only, if py2 needed to be supported, _get_ident would be needed. +_thread_local_info = threading.local() +_thread_active = threading._active + +def clear_thread_local_info(): + global _thread_local_info + _thread_local_info = threading.local() + + +cdef class ThreadInfo: + + cdef public PyDBAdditionalThreadInfo additional_info + cdef public bint is_pydevd_thread + cdef public int inside_frame_eval + cdef public bint fully_initialized + cdef public object thread_trace_func + cdef bint _can_create_dummy_thread + + # Note: whenever get_func_code_info is called, this value is reset (we're using + # it as a thread-local value info). + # If True the debugger should not go into trace mode even if the new + # code for a function is None and there are breakpoints. + cdef public bint force_stay_in_untraced_mode + + cdef initialize(self, PyFrameObject * frame_obj): + # Places that create a ThreadInfo should verify that + # a current Python frame is being executed! + assert frame_obj != NULL + + self.additional_info = None + self.is_pydevd_thread = False + self.inside_frame_eval = 0 + self.fully_initialized = False + self.thread_trace_func = None + + # Get the root (if it's not a Thread initialized from the threading + # module, create the dummy thread entry so that we can debug it -- + # otherwise, we have to wait for the threading module itself to + # create the Thread entry). + while frame_obj.f_back != NULL: + frame_obj = frame_obj.f_back + + basename = frame_obj.f_code.co_filename + i = basename.rfind('/') + j = basename.rfind('\\') + if j > i: + i = j + if i >= 0: + basename = basename[i + 1:] + # remove ext + i = basename.rfind('.') + if i >= 0: + basename = basename[:i] + + co_name = frame_obj.f_code.co_name + + # In these cases we cannot create a dummy thread (an actual + # thread will be created later or tracing will already be set). + if basename == 'threading' and co_name in ('__bootstrap', '_bootstrap', '__bootstrap_inner', '_bootstrap_inner'): + self._can_create_dummy_thread = False + elif basename == 'pydev_monkey' and co_name == '__call__': + self._can_create_dummy_thread = False + elif basename == 'pydevd' and co_name in ('run', 'main', '_exec'): + self._can_create_dummy_thread = False + elif basename == 'pydevd_tracing': + self._can_create_dummy_thread = False + else: + self._can_create_dummy_thread = True + + # print('Can create dummy thread for thread started in: %s %s' % (basename, co_name)) + + cdef initialize_if_possible(self): + # Don't call threading.currentThread because if we're too early in the process + # we may create a dummy thread. + self.inside_frame_eval += 1 + + try: + thread_ident = _get_ident() + t = _thread_active.get(thread_ident) + if t is None: + if self._can_create_dummy_thread: + # Initialize the dummy thread and set the tracing (both are needed to + # actually stop on breakpoints). + t = threading.current_thread() + SetTrace(dummy_trace_dispatch) + else: + return # Cannot initialize until thread becomes active. + + if getattr(t, 'is_pydev_daemon_thread', False): + self.is_pydevd_thread = True + self.fully_initialized = True + else: + try: + additional_info = t.additional_info + if additional_info is None: + raise AttributeError() + except: + with _set_additional_thread_info_lock: + # If it's not there, set it within a lock to avoid any racing + # conditions. + additional_info = getattr(thread, 'additional_info', None) + if additional_info is None: + additional_info = PyDBAdditionalThreadInfo() + t.additional_info = additional_info + self.additional_info = additional_info + self.fully_initialized = True + finally: + self.inside_frame_eval -= 1 + + +cdef class FuncCodeInfo: + + cdef public str co_filename + cdef public str co_name + cdef public str canonical_normalized_filename + cdef bint always_skip_code + cdef public bint breakpoint_found + cdef public object new_code + + # When breakpoints_mtime != PyDb.mtime the validity of breakpoints have + # to be re-evaluated (if invalid a new FuncCodeInfo must be created and + # tracing can't be disabled for the related frames). + cdef public int breakpoints_mtime + + def __init__(self): + self.co_filename = '' + self.canonical_normalized_filename = '' + self.always_skip_code = False + + # If breakpoints are found but new_code is None, + # this means we weren't able to actually add the code + # where needed, so, fallback to tracing. + self.breakpoint_found = False + self.new_code = None + self.breakpoints_mtime = -1 + + +def dummy_trace_dispatch(frame, str event, arg): + if event == 'call': + if frame.f_trace is not None: + return frame.f_trace(frame, event, arg) + return None + + +def get_thread_info_py() -> ThreadInfo: + return get_thread_info(PyEval_GetFrame()) + + +cdef ThreadInfo get_thread_info(PyFrameObject * frame_obj): + ''' + Provides thread-related info. + + May return None if the thread is still not active. + ''' + cdef ThreadInfo thread_info + try: + # Note: changing to a `dict[thread.ident] = thread_info` had almost no + # effect in the performance. + thread_info = _thread_local_info.thread_info + except: + if frame_obj == NULL: + return None + thread_info = ThreadInfo() + thread_info.initialize(frame_obj) + thread_info.inside_frame_eval += 1 + try: + _thread_local_info.thread_info = thread_info + + # Note: _code_extra_index is not actually thread-related, + # but this is a good point to initialize it. + global _code_extra_index + if _code_extra_index == -1: + _code_extra_index = _PyEval_RequestCodeExtraIndex(release_co_extra) + + thread_info.initialize_if_possible() + finally: + thread_info.inside_frame_eval -= 1 + + return thread_info + + +def decref_py(obj): + ''' + Helper to be called from Python. + ''' + Py_DECREF(obj) + + +def get_func_code_info_py(thread_info, frame, code_obj) -> FuncCodeInfo: + ''' + Helper to be called from Python. + ''' + return get_func_code_info( thread_info, frame, code_obj) + + +cdef int _code_extra_index = -1 + +cdef FuncCodeInfo get_func_code_info(ThreadInfo thread_info, PyFrameObject * frame_obj, PyCodeObject * code_obj): + ''' + Provides code-object related info. + + Stores the gathered info in a cache in the code object itself. Note that + multiple threads can get the same info. + + get_thread_info() *must* be called at least once before get_func_code_info() + to initialize _code_extra_index. + + ''' + # f_code = code_obj + # DEBUG = f_code.co_filename.endswith('_debugger_case_multiprocessing.py') + # if DEBUG: + # print('get_func_code_info', f_code.co_name, f_code.co_filename) + + cdef object main_debugger = GlobalDebuggerHolder.global_dbg + thread_info.force_stay_in_untraced_mode = False # This is an output value of the function. + + cdef PyObject * extra + _PyCode_GetExtra( code_obj, _code_extra_index, & extra) + if extra is not NULL: + extra_obj = extra + if extra_obj is not NULL: + func_code_info_obj = extra_obj + if func_code_info_obj.breakpoints_mtime == main_debugger.mtime: + # if DEBUG: + # print('get_func_code_info: matched mtime', f_code.co_name, f_code.co_filename) + + return func_code_info_obj + + cdef str co_filename = code_obj.co_filename + cdef str co_name = code_obj.co_name + cdef dict cache_file_type + cdef tuple cache_file_type_key + + func_code_info = FuncCodeInfo() + func_code_info.breakpoints_mtime = main_debugger.mtime + + func_code_info.co_filename = co_filename + func_code_info.co_name = co_name + + if not func_code_info.always_skip_code: + try: + abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[co_filename] + except: + abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame_obj) + + func_code_info.canonical_normalized_filename = abs_path_real_path_and_base[1] + + cache_file_type = main_debugger.get_cache_file_type() + # Note: this cache key must be the same from PyDB.get_file_type() -- see it for comments + # on the cache. + cache_file_type_key = (frame_obj.f_code.co_firstlineno, abs_path_real_path_and_base[0], frame_obj.f_code) + try: + file_type = cache_file_type[cache_file_type_key] # Make it faster + except: + file_type = main_debugger.get_file_type(frame_obj, abs_path_real_path_and_base) # we don't want to debug anything related to pydevd + + if file_type is not None: + func_code_info.always_skip_code = True + + if not func_code_info.always_skip_code: + if main_debugger is not None: + + breakpoints: dict = main_debugger.breakpoints.get(func_code_info.canonical_normalized_filename) + function_breakpoint: object = main_debugger.function_breakpoint_name_to_breakpoint.get(func_code_info.co_name) + # print('\n---') + # print(main_debugger.breakpoints) + # print(func_code_info.canonical_normalized_filename) + # print(main_debugger.breakpoints.get(func_code_info.canonical_normalized_filename)) + code_obj_py: object = code_obj + cached_code_obj_info: object = _cache.get(code_obj_py) + if cached_code_obj_info: + # The cache is for new code objects, so, in this case it's already + # using the new code and we can't change it as this is a generator! + # There's still a catch though: even though we don't replace the code, + # we may not want to go into tracing mode (as would usually happen + # when the new_code is None). + func_code_info.new_code = None + breakpoint_found, thread_info.force_stay_in_untraced_mode = \ + cached_code_obj_info.compute_force_stay_in_untraced_mode(breakpoints) + func_code_info.breakpoint_found = breakpoint_found + + elif function_breakpoint: + # Go directly into tracing mode + func_code_info.breakpoint_found = True + func_code_info.new_code = None + + elif breakpoints: + # if DEBUG: + # print('found breakpoints', code_obj_py.co_name, breakpoints) + + # Note: new_code can be None if unable to generate. + # It should automatically put the new code object in the cache. + breakpoint_found, func_code_info.new_code = generate_code_with_breakpoints(code_obj_py, breakpoints) + func_code_info.breakpoint_found = breakpoint_found + + Py_INCREF(func_code_info) + _PyCode_SetExtra( code_obj, _code_extra_index, func_code_info) + + return func_code_info + + +cdef class _CodeLineInfo: + + cdef public dict line_to_offset + cdef public int first_line + cdef public int last_line + + def __init__(self, dict line_to_offset, int first_line, int last_line): + self.line_to_offset = line_to_offset + self.first_line = first_line + self.last_line = last_line + + +# Note: this method has a version in pure-python too. +def _get_code_line_info(code_obj): + line_to_offset: dict = {} + first_line: int = None + last_line: int = None + + cdef int offset + cdef int line + + for offset, line in dis.findlinestarts(code_obj): + line_to_offset[line] = offset + + if line_to_offset: + first_line = min(line_to_offset) + last_line = max(line_to_offset) + return _CodeLineInfo(line_to_offset, first_line, last_line) + + +# Note: this is a cache where the key is the code objects we create ourselves so that +# we always return the same code object for generators. +# (so, we don't have a cache from the old code to the new info -- that's actually +# handled by the cython side in `FuncCodeInfo get_func_code_info` by providing the +# same code info if the debugger mtime is still the same). +_cache: dict = {} + +def get_cached_code_obj_info_py(code_obj_py): + ''' + :return _CacheValue: + :note: on cython use _cache.get(code_obj_py) directly. + ''' + return _cache.get(code_obj_py) + + +cdef class _CacheValue(object): + + cdef public object code_obj_py + cdef public _CodeLineInfo code_line_info + cdef public set breakpoints_hit_at_lines + cdef public set code_lines_as_set + + def __init__(self, object code_obj_py, _CodeLineInfo code_line_info, set breakpoints_hit_at_lines): + ''' + :param code_obj_py: + :param _CodeLineInfo code_line_info: + :param set[int] breakpoints_hit_at_lines: + ''' + self.code_obj_py = code_obj_py + self.code_line_info = code_line_info + self.breakpoints_hit_at_lines = breakpoints_hit_at_lines + self.code_lines_as_set = set(code_line_info.line_to_offset) + + cpdef compute_force_stay_in_untraced_mode(self, breakpoints): + ''' + :param breakpoints: + set(breakpoint_lines) or dict(breakpoint_line->breakpoint info) + :return tuple(breakpoint_found, force_stay_in_untraced_mode) + ''' + cdef bint force_stay_in_untraced_mode + cdef bint breakpoint_found + cdef set target_breakpoints + + force_stay_in_untraced_mode = False + + target_breakpoints = self.code_lines_as_set.intersection(breakpoints) + breakpoint_found = bool(target_breakpoints) + + if not breakpoint_found: + force_stay_in_untraced_mode = True + else: + force_stay_in_untraced_mode = self.breakpoints_hit_at_lines.issuperset(set(breakpoints)) + + return breakpoint_found, force_stay_in_untraced_mode + +def generate_code_with_breakpoints_py(object code_obj_py, dict breakpoints): + return generate_code_with_breakpoints(code_obj_py, breakpoints) + +# DEBUG = True +# debug_helper = DebugHelper() + +cdef generate_code_with_breakpoints(object code_obj_py, dict breakpoints): + ''' + :param breakpoints: + dict where the keys are the breakpoint lines. + :return tuple(breakpoint_found, new_code) + ''' + # The cache is needed for generator functions, because after each yield a new frame + # is created but the former code object is used (so, check if code_to_modify is + # already there and if not cache based on the new code generated). + + cdef bint success + cdef int breakpoint_line + cdef bint breakpoint_found + cdef _CacheValue cache_value + cdef set breakpoints_hit_at_lines + cdef dict line_to_offset + + assert code_obj_py not in _cache, 'If a code object is cached, that same code object must be reused.' + +# if DEBUG: +# initial_code_obj_py = code_obj_py + + code_line_info = _get_code_line_info(code_obj_py) + + success = True + + breakpoints_hit_at_lines = set() + line_to_offset = code_line_info.line_to_offset + + for breakpoint_line in breakpoints: + if breakpoint_line in line_to_offset: + breakpoints_hit_at_lines.add(breakpoint_line) + + if breakpoints_hit_at_lines: + success, new_code = insert_pydevd_breaks( + code_obj_py, + breakpoints_hit_at_lines, + code_line_info + ) + + if not success: + code_obj_py = None + else: + code_obj_py = new_code + + breakpoint_found = bool(breakpoints_hit_at_lines) + if breakpoint_found and success: +# if DEBUG: +# op_number = debug_helper.write_dis( +# 'inserting code, breaks at: %s' % (list(breakpoints),), +# initial_code_obj_py +# ) +# +# debug_helper.write_dis( +# 'after inserting code, breaks at: %s' % (list(breakpoints,)), +# code_obj_py, +# op_number=op_number, +# ) + + cache_value = _CacheValue(code_obj_py, code_line_info, breakpoints_hit_at_lines) + _cache[code_obj_py] = cache_value + + return breakpoint_found, code_obj_py + +import sys + +cdef bint IS_PY_39_OWNARDS = sys.version_info[:2] >= (3, 9) + +def frame_eval_func(): + cdef PyThreadState *state = PyThreadState_Get() + if IS_PY_39_OWNARDS: + state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_39 + else: + state.interp.eval_frame = <_PyFrameEvalFunction *> get_bytecode_while_frame_eval_38 + dummy_tracing_holder.set_trace_func(dummy_trace_dispatch) + + +def stop_frame_eval(): + cdef PyThreadState *state = PyThreadState_Get() + state.interp.eval_frame = _PyEval_EvalFrameDefault + +# During the build we'll generate 2 versions of the code below so that we're compatible with +# Python 3.9, which receives a "PyThreadState* tstate" as the first parameter and Python 3.6-3.8 +# which doesn't. +### TEMPLATE_START +cdef PyObject * get_bytecode_while_frame_eval(PyFrameObject * frame_obj, int exc): + ''' + This function makes the actual evaluation and changes the bytecode to a version + where programmatic breakpoints are added. + ''' + if GlobalDebuggerHolder is None or _thread_local_info is None or exc: + # Sometimes during process shutdown these global variables become None + return CALL_EvalFrameDefault + + # co_filename: str = frame_obj.f_code.co_filename + # if co_filename.endswith('threading.py'): + # return CALL_EvalFrameDefault + + cdef ThreadInfo thread_info + cdef int STATE_SUSPEND = 2 + cdef int CMD_STEP_INTO = 107 + cdef int CMD_STEP_OVER = 108 + cdef int CMD_STEP_OVER_MY_CODE = 159 + cdef int CMD_STEP_INTO_MY_CODE = 144 + cdef int CMD_STEP_INTO_COROUTINE = 206 + cdef int CMD_SMART_STEP_INTO = 128 + cdef bint can_skip = True + try: + thread_info = _thread_local_info.thread_info + except: + thread_info = get_thread_info(frame_obj) + if thread_info is None: + return CALL_EvalFrameDefault + + if thread_info.inside_frame_eval: + return CALL_EvalFrameDefault + + if not thread_info.fully_initialized: + thread_info.initialize_if_possible() + if not thread_info.fully_initialized: + return CALL_EvalFrameDefault + + # Can only get additional_info when fully initialized. + cdef PyDBAdditionalThreadInfo additional_info = thread_info.additional_info + if thread_info.is_pydevd_thread or additional_info.is_tracing: + # Make sure that we don't trace pydevd threads or inside our own calls. + return CALL_EvalFrameDefault + + # frame = frame_obj + # DEBUG = frame.f_code.co_filename.endswith('_debugger_case_tracing.py') + # if DEBUG: + # print('get_bytecode_while_frame_eval', frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename) + + thread_info.inside_frame_eval += 1 + additional_info.is_tracing = True + try: + main_debugger: object = GlobalDebuggerHolder.global_dbg + if main_debugger is None: + return CALL_EvalFrameDefault + frame = frame_obj + + if thread_info.thread_trace_func is None: + trace_func, apply_to_global = fix_top_level_trace_and_get_trace_func(main_debugger, frame) + if apply_to_global: + thread_info.thread_trace_func = trace_func + + if additional_info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, CMD_SMART_STEP_INTO) or \ + main_debugger.break_on_caught_exceptions or \ + main_debugger.break_on_user_uncaught_exceptions or \ + main_debugger.has_plugin_exception_breaks or \ + main_debugger.signature_factory or \ + additional_info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop: + + # if DEBUG: + # print('get_bytecode_while_frame_eval enabled trace') + if thread_info.thread_trace_func is not None: + frame.f_trace = thread_info.thread_trace_func + else: + frame.f_trace = main_debugger.trace_dispatch + else: + func_code_info: FuncCodeInfo = get_func_code_info(thread_info, frame_obj, frame_obj.f_code) + # if DEBUG: + # print('get_bytecode_while_frame_eval always skip', func_code_info.always_skip_code) + if not func_code_info.always_skip_code: + + if main_debugger.has_plugin_line_breaks or main_debugger.has_plugin_exception_breaks: + can_skip = main_debugger.plugin.can_skip(main_debugger, frame_obj) + + if not can_skip: + # if DEBUG: + # print('get_bytecode_while_frame_eval not can_skip') + if thread_info.thread_trace_func is not None: + frame.f_trace = thread_info.thread_trace_func + else: + frame.f_trace = main_debugger.trace_dispatch + + if can_skip and func_code_info.breakpoint_found: + # if DEBUG: + # print('get_bytecode_while_frame_eval new_code', func_code_info.new_code) + if not thread_info.force_stay_in_untraced_mode: + # If breakpoints are found but new_code is None, + # this means we weren't able to actually add the code + # where needed, so, fallback to tracing. + if func_code_info.new_code is None: + if thread_info.thread_trace_func is not None: + frame.f_trace = thread_info.thread_trace_func + else: + frame.f_trace = main_debugger.trace_dispatch + else: + # print('Using frame eval break for', frame_obj.f_code.co_name) + update_globals_dict( frame_obj.f_globals) + Py_INCREF(func_code_info.new_code) + old = frame_obj.f_code + frame_obj.f_code = func_code_info.new_code + Py_DECREF(old) + else: + # When we're forcing to stay in traced mode we need to + # update the globals dict (because this means that we're reusing + # a previous code which had breakpoints added in a new frame). + update_globals_dict( frame_obj.f_globals) + + finally: + thread_info.inside_frame_eval -= 1 + additional_info.is_tracing = False + + return CALL_EvalFrameDefault +### TEMPLATE_END diff --git a/_pydevd_frame_eval/pydevd_frame_tracing.py b/_pydevd_frame_eval/pydevd_frame_tracing.py new file mode 100644 index 0000000..7b34cd5 --- /dev/null +++ b/_pydevd_frame_eval/pydevd_frame_tracing.py @@ -0,0 +1,122 @@ +import sys + +from _pydev_bundle import pydev_log +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle.pydevd_comm import get_global_debugger +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER +from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info + + +class DummyTracingHolder: + dummy_trace_func = None + + def set_trace_func(self, trace_func): + self.dummy_trace_func = trace_func + + +dummy_tracing_holder = DummyTracingHolder() + + +def update_globals_dict(globals_dict): + new_globals = {'_pydev_stop_at_break': _pydev_stop_at_break} + globals_dict.update(new_globals) + + +def _get_line_for_frame(frame): + # it's absolutely necessary to reset tracing function for frame in order to get the real line number + tracing_func = frame.f_trace + frame.f_trace = None + line = frame.f_lineno + frame.f_trace = tracing_func + return line + + +def _pydev_stop_at_break(line): + frame = sys._getframe(1) + # print('pydevd SET TRACING at ', line, 'curr line', frame.f_lineno) + t = threading.current_thread() + try: + additional_info = t.additional_info + except: + additional_info = set_additional_thread_info(t) + + if additional_info.is_tracing: + return + + additional_info.is_tracing += 1 + try: + py_db = get_global_debugger() + if py_db is None: + return + + pydev_log.debug("Setting f_trace due to frame eval mode in file: %s on line %s", frame.f_code.co_filename, line) + additional_info.trace_suspend_type = 'frame_eval' + + pydevd_frame_eval_cython_wrapper = sys.modules['_pydevd_frame_eval.pydevd_frame_eval_cython_wrapper'] + thread_info = pydevd_frame_eval_cython_wrapper.get_thread_info_py() + if thread_info.thread_trace_func is not None: + frame.f_trace = thread_info.thread_trace_func + else: + frame.f_trace = py_db.get_thread_local_trace_func() + finally: + additional_info.is_tracing -= 1 + + +def _pydev_needs_stop_at_break(line): + ''' + We separate the functionality into 2 functions so that we can generate a bytecode which + generates a spurious line change so that we can do: + + if _pydev_needs_stop_at_break(): + # Set line to line -1 + _pydev_stop_at_break() + # then, proceed to go to the current line + # (which will then trigger a line event). + ''' + t = threading.current_thread() + try: + additional_info = t.additional_info + except: + additional_info = set_additional_thread_info(t) + + if additional_info.is_tracing: + return False + + additional_info.is_tracing += 1 + try: + frame = sys._getframe(1) + # print('pydev needs stop at break?', line, 'curr line', frame.f_lineno, 'curr trace', frame.f_trace) + if frame.f_trace is not None: + # i.e.: this frame is already being traced, thus, we don't need to use programmatic breakpoints. + return False + + py_db = get_global_debugger() + if py_db is None: + return False + + try: + abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + except: + abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) + canonical_normalized_filename = abs_path_real_path_and_base[1] + + try: + python_breakpoint = py_db.breakpoints[canonical_normalized_filename][line] + except: + # print("Couldn't find breakpoint in the file %s on line %s" % (frame.f_code.co_filename, line)) + # Could be KeyError if line is not there or TypeError if breakpoints_for_file is None. + # Note: using catch-all exception for performance reasons (if the user adds a breakpoint + # and then removes it after hitting it once, this method added for the programmatic + # breakpoint will keep on being called and one of those exceptions will always be raised + # here). + return False + + if python_breakpoint: + # print('YES') + return True + + finally: + additional_info.is_tracing -= 1 + + return False + diff --git a/_pydevd_frame_eval/pydevd_modify_bytecode.py b/_pydevd_frame_eval/pydevd_modify_bytecode.py new file mode 100644 index 0000000..7e76358 --- /dev/null +++ b/_pydevd_frame_eval/pydevd_modify_bytecode.py @@ -0,0 +1,365 @@ +from collections import namedtuple +import dis +from functools import partial +import itertools +import os.path +import sys + +from _pydevd_frame_eval.vendored import bytecode +from _pydevd_frame_eval.vendored.bytecode.instr import Instr, Label +from _pydev_bundle import pydev_log +from _pydevd_frame_eval.pydevd_frame_tracing import _pydev_stop_at_break, _pydev_needs_stop_at_break + +DEBUG = False + + +class DebugHelper(object): + + def __init__(self): + self._debug_dir = os.path.join(os.path.dirname(__file__), 'debug_info') + try: + os.makedirs(self._debug_dir) + except: + pass + self._next = partial(next, itertools.count(0)) + + def _get_filename(self, op_number=None, prefix=''): + if op_number is None: + op_number = self._next() + name = '%03d_before.txt' % op_number + else: + name = '%03d_change.txt' % op_number + + filename = os.path.join(self._debug_dir, prefix + name) + return filename, op_number + + def write_bytecode(self, b, op_number=None, prefix=''): + filename, op_number = self._get_filename(op_number, prefix) + with open(filename, 'w') as stream: + bytecode.dump_bytecode(b, stream=stream, lineno=True) + return op_number + + def write_dis(self, code_to_modify, op_number=None, prefix=''): + filename, op_number = self._get_filename(op_number, prefix) + with open(filename, 'w') as stream: + stream.write('-------- ') + stream.write('-------- ') + stream.write('id(code_to_modify): %s' % id(code_to_modify)) + stream.write('\n\n') + dis.dis(code_to_modify, file=stream) + return op_number + + +_CodeLineInfo = namedtuple('_CodeLineInfo', 'line_to_offset, first_line, last_line') + + +# Note: this method has a version in cython too (that one is usually used, this is just for tests). +def _get_code_line_info(code_obj): + line_to_offset = {} + first_line = None + last_line = None + + for offset, line in dis.findlinestarts(code_obj): + line_to_offset[line] = offset + + if line_to_offset: + first_line = min(line_to_offset) + last_line = max(line_to_offset) + return _CodeLineInfo(line_to_offset, first_line, last_line) + + +if DEBUG: + debug_helper = DebugHelper() + + +def get_instructions_to_add( + stop_at_line, + _pydev_stop_at_break=_pydev_stop_at_break, + _pydev_needs_stop_at_break=_pydev_needs_stop_at_break + ): + ''' + This is the bytecode for something as: + + if _pydev_needs_stop_at_break(): + _pydev_stop_at_break() + + but with some special handling for lines. + ''' + # Good reference to how things work regarding line numbers and jumps: + # https://github.com/python/cpython/blob/3.6/Objects/lnotab_notes.txt + + # Usually use a stop line -1, but if that'd be 0, using line +1 is ok too. + spurious_line = stop_at_line - 1 + if spurious_line <= 0: + spurious_line = stop_at_line + 1 + + label = Label() + return [ + # -- if _pydev_needs_stop_at_break(): + Instr("LOAD_CONST", _pydev_needs_stop_at_break, lineno=stop_at_line), + Instr("LOAD_CONST", stop_at_line, lineno=stop_at_line), + Instr("CALL_FUNCTION", 1, lineno=stop_at_line), + Instr("POP_JUMP_IF_FALSE", label, lineno=stop_at_line), + + # -- _pydev_stop_at_break() + # + # Note that this has line numbers -1 so that when the NOP just below + # is executed we have a spurious line event. + Instr("LOAD_CONST", _pydev_stop_at_break, lineno=spurious_line), + Instr("LOAD_CONST", stop_at_line, lineno=spurious_line), + Instr("CALL_FUNCTION", 1, lineno=spurious_line), + Instr("POP_TOP", lineno=spurious_line), + + # Reason for the NOP: Python will give us a 'line' trace event whenever we forward jump to + # the first instruction of a line, so, in the case where we haven't added a programmatic + # breakpoint (either because we didn't hit a breakpoint anymore or because it was already + # tracing), we don't want the spurious line event due to the line change, so, we make a jump + # to the instruction right after the NOP so that the spurious line event is NOT generated in + # this case (otherwise we'd have a line event even if the line didn't change). + Instr("NOP", lineno=stop_at_line), + label, + ] + + +class _Node(object): + + def __init__(self, data): + self.prev = None + self.next = None + self.data = data + + def append(self, data): + node = _Node(data) + + curr_next = self.next + + node.next = self.next + node.prev = self + self.next = node + + if curr_next is not None: + curr_next.prev = node + + return node + + def prepend(self, data): + node = _Node(data) + + curr_prev = self.prev + + node.prev = self.prev + node.next = self + self.prev = node + + if curr_prev is not None: + curr_prev.next = node + + return node + + +class _HelperBytecodeList(object): + ''' + A helper double-linked list to make the manipulation a bit easier (so that we don't need + to keep track of indices that change) and performant (because adding multiple items to + the middle of a regular list isn't ideal). + ''' + + def __init__(self, lst=None): + self._head = None + self._tail = None + if lst: + node = self + for item in lst: + node = node.append(item) + + def append(self, data): + if self._tail is None: + node = _Node(data) + self._head = self._tail = node + return node + else: + node = self._tail = self.tail.append(data) + return node + + @property + def head(self): + node = self._head + # Manipulating the node directly may make it unsynchronized. + while node.prev: + self._head = node = node.prev + return node + + @property + def tail(self): + node = self._tail + # Manipulating the node directly may make it unsynchronized. + while node.next: + self._tail = node = node.next + return node + + def __iter__(self): + node = self.head + + while node: + yield node.data + node = node.next + + +_PREDICT_TABLE = { + 'LIST_APPEND': ('JUMP_ABSOLUTE',), + 'SET_ADD': ('JUMP_ABSOLUTE',), + 'GET_ANEXT': ('LOAD_CONST',), + 'GET_AWAITABLE': ('LOAD_CONST',), + 'DICT_MERGE': ('CALL_FUNCTION_EX',), + 'MAP_ADD': ('JUMP_ABSOLUTE',), + 'COMPARE_OP': ('POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE',), + 'IS_OP': ('POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE',), + 'CONTAINS_OP': ('POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE',), + + # Note: there are some others with PREDICT on ceval, but they have more logic + # and it needs more experimentation to know how it behaves in the static generated + # code (and it's only an issue for us if there's actually a line change between + # those, so, we don't have to really handle all the cases, only the one where + # the line number actually changes from one instruction to the predicted one). +} + +# 3.10 optimizations include copying code branches multiple times (for instance +# if the body of a finally has a single assign statement it can copy the assign to the case +# where an exception happens and doesn't happen for optimization purposes) and as such +# we need to add the programmatic breakpoint multiple times. +TRACK_MULTIPLE_BRANCHES = sys.version_info[:2] >= (3, 10) + +# When tracking multiple branches, we try to fix the bytecodes which would be PREDICTED in the +# Python eval loop so that we don't have spurious line events that wouldn't usually be issued +# in the tracing as they're ignored due to the eval prediction (even though they're in the bytecode). +FIX_PREDICT = sys.version_info[:2] >= (3, 10) + + +def insert_pydevd_breaks( + code_to_modify, + breakpoint_lines, + code_line_info=None, + _pydev_stop_at_break=_pydev_stop_at_break, + _pydev_needs_stop_at_break=_pydev_needs_stop_at_break, + ): + """ + Inserts pydevd programmatic breaks into the code (at the given lines). + + :param breakpoint_lines: set with the lines where we should add breakpoints. + :return: tuple(boolean flag whether insertion was successful, modified code). + """ + if code_line_info is None: + code_line_info = _get_code_line_info(code_to_modify) + + if not code_line_info.line_to_offset: + return False, code_to_modify + + # Create a copy (and make sure we're dealing with a set). + breakpoint_lines = set(breakpoint_lines) + + # Note that we can even generate breakpoints on the first line of code + # now, since we generate a spurious line event -- it may be a bit pointless + # as we'll stop in the first line and we don't currently stop the tracing after the + # user resumes, but in the future, if we do that, this would be a nice + # improvement. + # if code_to_modify.co_firstlineno in breakpoint_lines: + # return False, code_to_modify + + for line in breakpoint_lines: + if line <= 0: + # The first line is line 1, so, a break at line 0 is not valid. + pydev_log.info('Trying to add breakpoint in invalid line: %s', line) + return False, code_to_modify + + try: + b = bytecode.Bytecode.from_code(code_to_modify) + + if DEBUG: + op_number_bytecode = debug_helper.write_bytecode(b, prefix='bytecode.') + + helper_list = _HelperBytecodeList(b) + + modified_breakpoint_lines = breakpoint_lines.copy() + + curr_node = helper_list.head + added_breaks_in_lines = set() + last_lineno = None + while curr_node is not None: + instruction = curr_node.data + instruction_lineno = getattr(instruction, 'lineno', None) + curr_name = getattr(instruction, 'name', None) + + if FIX_PREDICT: + predict_targets = _PREDICT_TABLE.get(curr_name) + if predict_targets: + # Odd case: the next instruction may have a line number but it doesn't really + # appear in the tracing due to the PREDICT() in ceval, so, fix the bytecode so + # that it does things the way that ceval actually interprets it. + # See: https://mail.python.org/archives/list/python-dev@python.org/thread/CP2PTFCMTK57KM3M3DLJNWGO66R5RVPB/ + next_instruction = curr_node.next.data + next_name = getattr(next_instruction, 'name', None) + if next_name in predict_targets: + next_instruction_lineno = getattr(next_instruction, 'lineno', None) + if next_instruction_lineno: + next_instruction.lineno = None + + if instruction_lineno is not None: + if TRACK_MULTIPLE_BRANCHES: + if last_lineno is None: + last_lineno = instruction_lineno + else: + if last_lineno == instruction_lineno: + # If the previous is a label, someone may jump into it, so, we need to add + # the break even if it's in the same line. + if curr_node.prev.data.__class__ != Label: + # Skip adding this as the line is still the same. + curr_node = curr_node.next + continue + last_lineno = instruction_lineno + else: + if instruction_lineno in added_breaks_in_lines: + curr_node = curr_node.next + continue + + if instruction_lineno in modified_breakpoint_lines: + added_breaks_in_lines.add(instruction_lineno) + if curr_node.prev is not None and curr_node.prev.data.__class__ == Label \ + and curr_name == 'POP_TOP': + + # If we have a SETUP_FINALLY where the target is a POP_TOP, we can't change + # the target to be the breakpoint instruction (this can crash the interpreter). + + for new_instruction in get_instructions_to_add( + instruction_lineno, + _pydev_stop_at_break=_pydev_stop_at_break, + _pydev_needs_stop_at_break=_pydev_needs_stop_at_break, + ): + curr_node = curr_node.append(new_instruction) + + else: + for new_instruction in get_instructions_to_add( + instruction_lineno, + _pydev_stop_at_break=_pydev_stop_at_break, + _pydev_needs_stop_at_break=_pydev_needs_stop_at_break, + ): + curr_node.prepend(new_instruction) + + curr_node = curr_node.next + + b[:] = helper_list + + if DEBUG: + debug_helper.write_bytecode(b, op_number_bytecode, prefix='bytecode.') + + new_code = b.to_code() + + except: + pydev_log.exception('Error inserting pydevd breaks.') + return False, code_to_modify + + if DEBUG: + op_number = debug_helper.write_dis(code_to_modify) + debug_helper.write_dis(new_code, op_number) + + return True, new_code + diff --git a/_pydevd_frame_eval/release_mem.h b/_pydevd_frame_eval/release_mem.h new file mode 100644 index 0000000..cc6e3d9 --- /dev/null +++ b/_pydevd_frame_eval/release_mem.h @@ -0,0 +1,5 @@ +#include "Python.h" + +void release_co_extra(void *obj) { + Py_XDECREF(obj); +} diff --git a/build_tools/build.py b/build_tools/build.py new file mode 100644 index 0000000..a0b998d --- /dev/null +++ b/build_tools/build.py @@ -0,0 +1,175 @@ +''' +Helper to build pydevd. + +It should: + * recreate our generated files + * compile cython deps (properly setting up the environment first). + +Note that it's used in the CI to build the cython deps based on the PYDEVD_USE_CYTHON environment variable. +''' +from __future__ import print_function + +import os +import subprocess +import sys + +from generate_code import remove_if_exists, root_dir, is_python_64bit, generate_dont_trace_files, generate_cython_module + + +def validate_pair(ob): + try: + if not (len(ob) == 2): + print("Unexpected result:", ob, file=sys.stderr) + raise ValueError + except: + return False + return True + + +def consume(it): + try: + while True: + next(it) + except StopIteration: + pass + + +def get_environment_from_batch_command(env_cmd, initial=None): + """ + Take a command (either a single command or list of arguments) + and return the environment created after running that command. + Note that if the command must be a batch file or .cmd file, or the + changes to the environment will not be captured. + + If initial is supplied, it is used as the initial environment passed + to the child process. + """ + if not isinstance(env_cmd, (list, tuple)): + env_cmd = [env_cmd] + if not os.path.exists(env_cmd[0]): + raise RuntimeError('Error: %s does not exist' % (env_cmd[0],)) + + # construct the command that will alter the environment + env_cmd = subprocess.list2cmdline(env_cmd) + # create a tag so we can tell in the output when the proc is done + tag = 'Done running command' + # construct a cmd.exe command to do accomplish this + cmd = 'cmd.exe /s /c "{env_cmd} && echo "{tag}" && set"'.format(**vars()) + # launch the process + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial) + # parse the output sent to stdout + lines = proc.stdout + # consume whatever output occurs until the tag is reached + for line in lines: + line = line.decode('utf-8') + if 'The specified configuration type is missing.' in line: + raise AssertionError('Error executing %s. View http://blog.ionelmc.ro/2014/12/21/compiling-python-extensions-on-windows/ for details.' % (env_cmd)) + if tag in line: + break + if sys.version_info[0] > 2: + # define a way to handle each KEY=VALUE line + handle_line = lambda l: l.decode('utf-8').rstrip().split('=', 1) + else: + # define a way to handle each KEY=VALUE line + handle_line = lambda l: l.rstrip().split('=', 1) + # parse key/values into pairs + pairs = map(handle_line, lines) + # make sure the pairs are valid + valid_pairs = filter(validate_pair, pairs) + # construct a dictionary of the pairs + result = dict(valid_pairs) + # let the process finish + proc.communicate() + return result + + +def remove_binaries(suffixes): + for f in os.listdir(os.path.join(root_dir, '_pydevd_bundle')): + for suffix in suffixes: + if f.endswith(suffix): + remove_if_exists(os.path.join(root_dir, '_pydevd_bundle', f)) + + +def build(): + if '--no-remove-binaries' not in sys.argv: + remove_binaries(['.pyd', '.so']) + + os.chdir(root_dir) + + env = None + if sys.platform == 'win32': + # "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat" + # set MSSdk=1 + # set DISTUTILS_USE_SDK=1 + # set VS100COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools + + env = os.environ.copy() + if sys.version_info[:2] in ((2, 6), (2, 7), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (3, 10), (3, 11)): + import setuptools # We have to import it first for the compiler to be found + from distutils import msvc9compiler + + if sys.version_info[:2] in ((2, 6), (2, 7)): + vcvarsall = msvc9compiler.find_vcvarsall(9.0) + elif sys.version_info[:2] in ((3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (3, 10), (3, 11)): + vcvarsall = msvc9compiler.find_vcvarsall(14.0) + if vcvarsall is None or not os.path.exists(vcvarsall): + raise RuntimeError('Error finding vcvarsall.') + + if is_python_64bit(): + env.update(get_environment_from_batch_command( + [vcvarsall, 'amd64'], + initial=os.environ.copy())) + else: + env.update(get_environment_from_batch_command( + [vcvarsall, 'x86'], + initial=os.environ.copy())) + + elif sys.version_info[:2] in ((3, 3), (3, 4)): + if is_python_64bit(): + env.update(get_environment_from_batch_command( + [r"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd", '/x64'], + initial=os.environ.copy())) + else: + env.update(get_environment_from_batch_command( + [r"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd", '/x86'], + initial=os.environ.copy())) + + else: + raise AssertionError('Unable to setup environment for Python: %s' % (sys.version,)) + + env['MSSdk'] = '1' + env['DISTUTILS_USE_SDK'] = '1' + + additional_args = [] + for arg in sys.argv: + if arg.startswith('--target-pyd-name='): + additional_args.append(arg) + if arg.startswith('--target-pyd-frame-eval='): + additional_args.append(arg) + break + else: + additional_args.append('--force-cython') # Build always forces cython! + + args = [ + sys.executable, os.path.join(os.path.dirname(__file__), '..', 'setup_pydevd_cython.py'), 'build_ext', '--inplace', + ] + additional_args + print('Calling args: %s' % (args,)) + subprocess.check_call(args, env=env,) + + +if __name__ == '__main__': + use_cython = os.getenv('PYDEVD_USE_CYTHON', '').lower() + # Note: don't import pydevd during build (so, accept just yes/no in this case). + if use_cython == 'yes': + build() + elif use_cython == 'no': + remove_binaries(['.pyd', '.so']) + elif not use_cython: + # Regular process + if '--no-regenerate-files' not in sys.argv: + generate_dont_trace_files() + generate_cython_module() + build() + else: + raise RuntimeError('Unexpected value for PYDEVD_USE_CYTHON: %s (accepted: yes, no)' % (use_cython,)) + diff --git a/build_tools/build_binaries_osx.py b/build_tools/build_binaries_osx.py new file mode 100644 index 0000000..a3e376f --- /dev/null +++ b/build_tools/build_binaries_osx.py @@ -0,0 +1,60 @@ + +from __future__ import unicode_literals + +import os +import subprocess +import sys + +miniconda64_envs = os.getenv('MINICONDA64_ENVS') +python_installations = [ + r'%s/py34_64/bin/python' % miniconda64_envs, + r'%s/py35_64/bin/python' % miniconda64_envs, + r'%s/py36_64/bin/python' % miniconda64_envs, + r'%s/py37_64/bin/python' % miniconda64_envs, + ] +root_dir = os.path.dirname(os.path.dirname(__file__)) + + +def list_binaries(): + for f in os.listdir(os.path.join(root_dir, '_pydevd_bundle')): + if f.endswith('.so'): + yield f + + +def extract_version(python_install): + return python_install.split('/')[-3][2:] + + +def main(): + from generate_code import generate_dont_trace_files + from generate_code import generate_cython_module + + # First, make sure that our code is up to date. + generate_dont_trace_files() + generate_cython_module() + + for python_install in python_installations: + assert os.path.exists(python_install) + + from build import remove_binaries + remove_binaries(['.so']) + + for f in list_binaries(): + raise AssertionError('Binary not removed: %s' % (f,)) + + for i, python_install in enumerate(python_installations): + new_name = 'pydevd_cython_%s_%s' % (sys.platform, extract_version(python_install)) + args = [ + python_install, os.path.join(root_dir, 'build_tools', 'build.py'), '--no-remove-binaries', '--target-pyd-name=%s' % new_name, '--force-cython'] + if i != 0: + args.append('--no-regenerate-files') + version_number = extract_version(python_install) + if version_number.startswith('36') or version_number.startswith('37'): + name_frame_eval = 'pydevd_frame_evaluator_%s_%s' % (sys.platform, extract_version(python_install)) + args.append('--target-pyd-frame-eval=%s' % name_frame_eval) + print('Calling: %s' % (' '.join(args))) + subprocess.check_call(args) + + +if __name__ == '__main__': + main() diff --git a/build_tools/build_binaries_windows.py b/build_tools/build_binaries_windows.py new file mode 100644 index 0000000..e2224fe --- /dev/null +++ b/build_tools/build_binaries_windows.py @@ -0,0 +1,91 @@ +r''' +Creating the needed environments for creating the pre-compiled distribution on Windows: + +See: + +build_tools\pydevd_release_process.txt + +for building binaries/release process. +''' + +from __future__ import unicode_literals +import os +import subprocess +import sys + +miniconda_envs = os.getenv('MINICONDA_ENVS', r'C:\bin\Miniconda3\envs') + +python_installations = [ + + r'%s\py36_32\python.exe' % miniconda_envs, + r'%s\py37_32\python.exe' % miniconda_envs, + r'%s\py38_32\python.exe' % miniconda_envs, + r'%s\py39_32\python.exe' % miniconda_envs, + r'%s\py310_32\python.exe' % miniconda_envs, + + r'%s\py36_64\python.exe' % miniconda_envs, + r'%s\py37_64\python.exe' % miniconda_envs, + r'%s\py38_64\python.exe' % miniconda_envs, + r'%s\py39_64\python.exe' % miniconda_envs, + r'%s\py310_64\python.exe' % miniconda_envs, +] + +root_dir = os.path.dirname(os.path.dirname(__file__)) + + +def list_binaries(): + for f in os.listdir(os.path.join(root_dir, '_pydevd_bundle')): + if f.endswith('.pyd'): + yield f + + +def extract_version(python_install): + return python_install.split('\\')[-2][2:] + + +def main(): + from generate_code import generate_dont_trace_files + from generate_code import generate_cython_module + + # First, make sure that our code is up to date. + generate_dont_trace_files() + generate_cython_module() + + for python_install in python_installations: + assert os.path.exists(python_install), '%s does not exist.' % (python_install,) + + from build import remove_binaries + remove_binaries(['.pyd']) + + for f in list_binaries(): + raise AssertionError('Binary not removed: %s' % (f,)) + + for i, python_install in enumerate(python_installations): + print() + print('*' * 80) + print('*' * 80) + print() + new_name = 'pydevd_cython_%s_%s' % (sys.platform, extract_version(python_install)) + args = [ + python_install, os.path.join(root_dir, 'build_tools', 'build.py'), '--no-remove-binaries', '--target-pyd-name=%s' % new_name, '--force-cython'] + if i != 0: + args.append('--no-regenerate-files') + name_frame_eval = 'pydevd_frame_evaluator_%s_%s' % (sys.platform, extract_version(python_install)) + args.append('--target-pyd-frame-eval=%s' % name_frame_eval) + print('Calling: %s' % (' '.join(args))) + + env = os.environ.copy() + python_exe_dir = os.path.dirname(python_install) + env['PATH'] = env['PATH'] + ';' + os.path.join(python_exe_dir, 'DLLs') + ';' + os.path.join(python_exe_dir, 'Library', 'bin') + subprocess.check_call(args, env=env) + + +if __name__ == '__main__': + main() + +# To run do: +# See: +# +# build_tools\pydevd_release_process.txt +# +# for building binaries/release process. diff --git a/build_tools/check_no_git_modifications.py b/build_tools/check_no_git_modifications.py new file mode 100644 index 0000000..3bad1a0 --- /dev/null +++ b/build_tools/check_no_git_modifications.py @@ -0,0 +1,32 @@ +import sys + + +def main(): + import subprocess + process = subprocess.Popen( + 'git status --porcelain'.split(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE) + output, _ = process.communicate() + if output: + if sys.version_info[0] > 2: + output = output.decode('utf-8') + + files = set() + for line in output.splitlines(): + filename = line[3:] + files.add(filename.strip()) + + files.discard('.travis_install_python_deps.sh') + files.discard('miniconda.sh') + if files: + # If there are modifications, show a diff of the modifications and fail the script. + # (we're mostly interested in modifications to the .c generated files by cython). + print('Found modifications in git:\n%s ' % (output,)) + print('Files: %s' % (files,)) + print('----------- diff -------------') + subprocess.call('git diff'.split()) + print('----------- end diff -------------') + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/build_tools/generate_code.py b/build_tools/generate_code.py new file mode 100644 index 0000000..ccdd399 --- /dev/null +++ b/build_tools/generate_code.py @@ -0,0 +1,228 @@ +''' +This module should be run to recreate the files that we generate automatically +(i.e.: modules that shouldn't be traced and cython .pyx) +''' + +from __future__ import print_function + +import os +import struct +import re + + +def is_python_64bit(): + return (struct.calcsize('P') == 8) + + +root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + + +def get_cython_contents(filename): + if filename.endswith('.pyc'): + filename = filename[:-1] + + state = 'regular' + + replacements = [] + + new_contents = [] + with open(filename, 'r') as stream: + for line in stream: + strip = line.strip() + if state == 'regular': + if strip == '# IFDEF CYTHON': + state = 'cython' + + new_contents.append('%s -- DONT EDIT THIS FILE (it is automatically generated)\n' % line.replace('\n', '').replace('\r', '')) + continue + + new_contents.append(line) + + elif state == 'cython': + if strip == '# ELSE': + state = 'nocython' + new_contents.append(line) + continue + + elif strip == '# ENDIF': + state = 'regular' + new_contents.append(line) + continue + + if strip == '#': + continue + + assert strip.startswith('# '), 'Line inside # IFDEF CYTHON must start with "# ". Found: %s' % (strip,) + strip = strip.replace('# ', '', 1).strip() + + if strip.startswith('cython_inline_constant:'): + strip = strip.replace('cython_inline_constant:', '') + word_to_replace, replacement = strip.split('=') + replacements.append((word_to_replace.strip(), replacement.strip())) + continue + + line = line.replace('# ', '', 1) + new_contents.append(line) + + elif state == 'nocython': + if strip == '# ENDIF': + state = 'regular' + new_contents.append(line) + continue + new_contents.append('# %s' % line) + + assert state == 'regular', 'Error: # IFDEF CYTHON found without # ENDIF' + + ret = ''.join(new_contents) + + for (word_to_replace, replacement) in replacements: + ret = re.sub(r"\b%s\b" % (word_to_replace,), replacement, ret) + + return ret + + +def _generate_cython_from_files(target, modules): + contents = ['''from __future__ import print_function + +# Important: Autogenerated file. + +# DO NOT edit manually! +# DO NOT edit manually! +'''] + + for mod in modules: + contents.append(get_cython_contents(mod.__file__)) + + with open(target, 'w') as stream: + stream.write(''.join(contents)) + + +def generate_dont_trace_files(): + template = '''# Important: Autogenerated file. + +# DO NOT edit manually! +# DO NOT edit manually! + +LIB_FILE = 1 +PYDEV_FILE = 2 + +DONT_TRACE_DIRS = { +%(pydev_dirs)s +} + +DONT_TRACE = { + # commonly used things from the stdlib that we don't want to trace + 'Queue.py':LIB_FILE, + 'queue.py':LIB_FILE, + 'socket.py':LIB_FILE, + 'weakref.py':LIB_FILE, + '_weakrefset.py':LIB_FILE, + 'linecache.py':LIB_FILE, + 'threading.py':LIB_FILE, + 'dis.py':LIB_FILE, + + # things from pydev that we don't want to trace +%(pydev_files)s +} + +# if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716) +DONT_TRACE['io.py'] = LIB_FILE + +# Don't trace common encodings too +DONT_TRACE['cp1252.py'] = LIB_FILE +DONT_TRACE['utf_8.py'] = LIB_FILE +DONT_TRACE['codecs.py'] = LIB_FILE +''' + + pydev_files = [] + pydev_dirs = [] + + exclude_dirs = [ + '.git', + '.settings', + 'build', + 'build_tools', + 'dist', + 'pydevd.egg-info', + 'pydevd_attach_to_process', + 'pydev_sitecustomize', + 'stubs', + 'tests', + 'tests_mainloop', + 'tests_python', + 'tests_runfiles', + 'test_pydevd_reload', + 'third_party', + '__pycache__', + 'pydev_ipython', + 'vendored', + '.mypy_cache', + 'pydevd.egg-info', + ] + + for root, dirs, files in os.walk(root_dir): + + for d in dirs: + if 'pydev' in d and d != 'pydevd.egg-info': + # print(os.path.join(root, d)) + pydev_dirs.append(" '%s': PYDEV_FILE," % (d,)) + + for d in exclude_dirs: + try: + dirs.remove(d) + except: + pass + + for f in files: + if f.endswith('.py'): + if f not in ( + '__init__.py', + 'runfiles.py', + 'pydev_coverage.py', + 'pydev_pysrc.py', + 'setup.py', + 'setup_pydevd_cython.py', + 'interpreterInfo.py', + 'conftest.py', + ): + pydev_files.append(" '%s': PYDEV_FILE," % (f,)) + + contents = template % (dict( + pydev_files='\n'.join(sorted(set(pydev_files))), + pydev_dirs='\n'.join(sorted(set(pydev_dirs))), + )) + assert 'pydevd.py' in contents + assert 'pydevd_dont_trace.py' in contents + with open(os.path.join(root_dir, '_pydevd_bundle', 'pydevd_dont_trace_files.py'), 'w') as stream: + stream.write(contents) + + +def remove_if_exists(f): + try: + if os.path.exists(f): + os.remove(f) + except: + import traceback;traceback.print_exc() + + +def generate_cython_module(): + remove_if_exists(os.path.join(root_dir, '_pydevd_bundle', 'pydevd_cython.pyx')) + + target = os.path.join(root_dir, '_pydevd_bundle', 'pydevd_cython.pyx') + curr = os.environ.get('PYDEVD_USE_CYTHON') + try: + os.environ['PYDEVD_USE_CYTHON'] = 'NO' + + from _pydevd_bundle import pydevd_additional_thread_info_regular + from _pydevd_bundle import pydevd_frame, pydevd_trace_dispatch_regular + _generate_cython_from_files(target, [pydevd_additional_thread_info_regular, pydevd_frame, pydevd_trace_dispatch_regular]) + finally: + if curr is None: + del os.environ['PYDEVD_USE_CYTHON'] + else: + os.environ['PYDEVD_USE_CYTHON'] = curr + + +if __name__ == '__main__': + generate_dont_trace_files() + generate_cython_module() diff --git a/build_tools/names_to_rename.py b/build_tools/names_to_rename.py new file mode 100644 index 0000000..1525974 --- /dev/null +++ b/build_tools/names_to_rename.py @@ -0,0 +1,318 @@ +''' +Helper module to hold the names to rename while doing refactoring to convert to pep8. +''' +NAMES = ''' +# sendCaughtExceptionStack +# sendBreakpointConditionException +# setSuspend +# processThreadNotAlive +# sendCaughtExceptionStackProceeded +# doWaitSuspend +# SetTraceForFrameAndParents +# prepareToRun +# processCommandLine +# initStdoutRedirect +# initStderrRedirect +# OnRun +# doKillPydevThread +# stopTrace +# handleExcept +# processCommand +# processNetCommand +# addCommand +# StartClient +# getNextSeq +# makeMessage +# StartServer +# threadToXML +# makeErrorMessage +# makeThreadCreatedMessage +# makeCustomFrameCreatedMessage +# makeListThreadsMessage +# makeVariableChangedMessage +# makeIoMessage +# makeVersionMessage +# makeThreadKilledMessage +# makeThreadSuspendStr +# makeValidXmlValue +# makeThreadSuspendMessage +# makeThreadRunMessage +# makeGetVariableMessage +# makeGetArrayMessage +# makeGetFrameMessage +# makeEvaluateExpressionMessage +# makeGetCompletionsMessage +# makeGetFileContents +# makeSendBreakpointExceptionMessage +# makeSendCurrExceptionTraceMessage +# makeSendCurrExceptionTraceProceededMessage +# makeSendConsoleMessage +# makeCustomOperationMessage +# makeLoadSourceMessage +# makeShowConsoleMessage +# makeExitMessage +# canBeExecutedBy +# doIt +# additionalInfo +# cmdFactory +# GetExceptionTracebackStr +# _GetStackStr +# _InternalSetTrace +# ReplaceSysSetTraceFunc +# RestoreSysSetTraceFunc + + + +# AddContent +# AddException +# AddObserver +# # Call -- skip +# # Call1 -- skip +# # Call2 -- skip +# # Call3 -- skip +# # Call4 -- skip +# ChangePythonPath +# CheckArgs +# CheckChar +# CompleteFromDir +# CreateDbFrame +# CustomFramesContainerInit +# DictContains +# DictItems +# DictIterItems +# DictIterValues +# DictKeys +# DictPop +# DictValues + + +# DoExit +# DoFind +# EndRedirect +# # Exec -- skip +# ExecuteTestsInParallel +# # Find -- skip +# FinishDebuggingSession +# FlattenTestSuite +# GenerateCompletionsAsXML +# GenerateImportsTipForModule +# GenerateTip + + +# testAddExec +# testComplete +# testCompleteDoesNotDoPythonMatches +# testCompletionSocketsAndMessages +# testConsoleHello +# testConsoleRequests +# testDotNetLibraries +# testEdit +# testGetCompletions +# testGetNamespace +# testGetReferrers1 +# testGetReferrers2 +# testGetReferrers3 +# testGetReferrers4 +# testGetReferrers5 +# testGetReferrers6 +# testGetReferrers7 +# testGettingInfoOnJython +# testGui +# testHistory +# testImports +# testImports1 +# testImports1a +# testImports1b +# testImports1c +# testImports2 +# testImports2a +# testImports2b +# testImports2c +# testImports3 +# testImports4 +# testImports5 +# testInspect +# testIt +# testMessage +# testPrint +# testProperty +# testProperty2 +# testProperty3 +# testQuestionMark +# testSearch +# testSearchOnJython +# testServer +# testTipOnString +# toXML +# updateCustomFrame +# varToXML + +# +# GetContents +# GetCoverageFiles +# GetFile +# GetFileNameAndBaseFromFile +# GetFilenameAndBase +# GetFrame +# GetGlobalDebugger # -- renamed but kept backward-compatibility +# GetNormPathsAndBase +# GetNormPathsAndBaseFromFile +# GetTestsToRun -- skip +# GetThreadId +# GetVmType +# IPythonEditor -- skip +# ImportName +# InitializeServer +# IterFrames + + +# Method1 -- skip +# Method1a -- skip +# Method2 -- skip +# Method3 -- skip + +# NewConsolidate +# NormFileToClient +# NormFileToServer +# # Notify -- skip +# # NotifyFinished -- skip +# OnFunButton +# # OnInit -- skip +# OnTimeToClose +# PydevdFindThreadById +# PydevdLog +# # RequestInput -- skip + + +# Search -- manual: search_definition +# ServerProxy -- skip +# SetGlobalDebugger + +# SetServer +# SetUp +# SetTrace -- skip + + +# SetVmType +# SetupType +# StartCoverageSupport +# StartCoverageSupportFromParams +# StartPydevNosePluginSingleton +# StartRedirect +# ToTuple + +# addAdditionalFrameById +# removeAdditionalFrameById +# removeCustomFrame +# addCustomFrame +# addError -- skip +# addExec +# addFailure -- skip +# addSuccess -- skip +# assertArgs +# assertIn + +# basicAsStr +# changeAttrExpression +# # changeVariable -- skip (part of public API for console) +# checkOutput +# checkOutputRedirect +# clearBuffer + +# # connectToDebugger -- skip (part of public API for console) +# connectToServer +# consoleExec +# createConnections +# createStdIn +# customOperation +# dirObj +# doAddExec +# doExecCode +# dumpFrames + +# # enableGui -- skip (part of public API for console) +# evalInContext +# evaluateExpression +# # execLine -- skip (part of public API for console) +# # execMultipleLines -- skip (part of public API for console) +# findFrame +# orig_findFrame +# finishExec +# fixGetpass + +# forceServerKill +# formatArg +# formatCompletionMessage +# formatParamClassName +# frameVarsToXML +# fullyNormalizePath + +# getArray -- skip (part of public API for console) +# getAsDoc +# getCapturedOutput +# getCompletions -- skip (part of public API for console) + +# getCompletionsMessage +# getCustomFrame +# # getDescription -- skip (part of public API for console) +# getDictionary +# # getFrame -- skip (part of public API for console) +# getFrameName + + + +# getFrameStack +# getFreeAddresses +# getInternalQueue +# getIoFromError +# getNamespace +# getTestName +# getTokenAndData +# getType + +# getVariable -- skip (part of public API for console) + +# # haveAliveThreads -> has_threads_alive +# initializeNetwork +# isThreadAlive +# # iterFrames -> _iter_frames +# # keyStr -> key_to_str +# killAllPydevThreads +# longRunning +# # metA -- skip +# nativePath + +# needMore +# needMoreForCode +# # notifyCommands -- skip (part of public API) +# # notifyConnected -- skip (part of public API) +# # notifyStartTest -- skip (part of public API) +# # notifyTest -- skip (part of public API) +# # notifyTestRunFinished -- skip (part of public API) +# # notifyTestsCollected -- skip (part of public API) +# postInternalCommand +# processInternalCommands +# readMsg + + +# redirectStdout +# removeInvalidChars +# reportCond +# resolveCompoundVariable +# resolveVar +# restoreStdout +# sendKillMsg +# sendSignatureCallTrace +# setTracingForUntracedContexts +# startClientThread +# startDebuggerServerThread +# startExec + +# startTest -- skip +# stopTest -- skip +# setUp -- skip +# setUpClass -- skip +# setUpModule -- skip +# tearDown -- skip + +''' \ No newline at end of file diff --git a/build_tools/pydevd_release_process.txt b/build_tools/pydevd_release_process.txt new file mode 100644 index 0000000..3a1fa6c --- /dev/null +++ b/build_tools/pydevd_release_process.txt @@ -0,0 +1,216 @@ +1. Update version +================= + +__version_info__ in pydevd.py + + +2. Create conda envs +===================== + +set CONDA_FORCE_32BIT=1 + +conda create -y -f -n py36_32 python=3.6 cython numpy nose ipython pip +activate py36_32 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +conda create -y -f -n py37_32 python=3.7 cython numpy pip +activate py37_32 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +conda create -y -f -n py38_32 python=3.8 cython pip +activate py38_32 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +conda create -y -f -n py39_32 python=3.9 cython pip +activate py39_32 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +conda create -y -f -n py310_32 python=3.10 cython pip +activate py310_32 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + + +set CONDA_FORCE_32BIT= + +conda create -y -f -n py36_64 python=3.6 cython numpy nose ipython pip +activate py36_64 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +conda create -y -f -n py37_64 python=3.7 cython numpy nose ipython pip +activate py37_64 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +conda create -y -f -n py38_64 python=3.8 cython numpy nose ipython pip +activate py38_64 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +conda create -y -f -n py39_64 python=3.9 cython pip +activate py39_64 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +conda create -y -f -n py310_64 python=3.10 cython pip +activate py310_64 +pip install "django>=1.9" +pip install -U "setuptools>=0.9" +pip install -U "pip>=1.4" "wheel>=0.21" twine +conda deactivate + +### UPDATE CYTHON + +set CONDA_FORCE_32BIT=1 + +activate py36_32 +pip install cython==0.29.28 +conda deactivate + +activate py37_32 +pip install cython==0.29.28 +conda deactivate + +activate py38_32 +pip install cython==0.29.28 +conda deactivate + +activate py39_32 +pip install cython==0.29.28 +conda deactivate + +activate py310_32 +pip install cython==0.29.28 +conda deactivate + +set CONDA_FORCE_32BIT= + +activate py36_64 +pip install cython==0.29.28 +conda deactivate + +activate py37_64 +pip install cython==0.29.28 +conda deactivate + +activate py38_64 +pip install cython==0.29.28 +conda deactivate + +activate py39_64 +pip install cython==0.29.28 +conda deactivate + +activate py310_64 +pip install cython==0.29.28 +conda deactivate + +4. Regenerate the .pyx and .c +=============================== + +cd /D x:\pydev\plugins\org.python.pydev.core\pysrc +set PYTHONPATH=x:\pydev\plugins\org.python.pydev.core\pysrc +python build_tools\build.py + +${ptvsd_folder} +cd /D X:\ptvsd_workspace\ptvsd\src\debugpy\_vendored\pydevd +set PYTHONPATH=X:\ptvsd_workspace\ptvsd\src\debugpy\_vendored\pydevd +python build_tools\build.py + + +cd ~/Desktop/Pydev/plugins/org.python.pydev.core/pysrc +export PYTHONPATH=~/Desktop/Pydev/plugins/org.python.pydev.core/pysrc +python build_tools/build.py + +3. Generate new version +====================== + +cd /D x:\PyDev.Debugger + +set PYTHONPATH=x:\PyDev.Debugger +set MINICONDA_ENVS=C:\bin\Miniconda3\envs +conda deactivate +C:\bin\Python38-32\python build_tools\build.py +C:\bin\Python38-32\python build_tools\build_binaries_windows.py + +rm dist/pydevd* + +activate py36_32 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py37_32 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py38_32 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py39_32 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py310_32 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py36_64 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py37_64 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py38_64 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py39_64 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +activate py310_64 +python setup.py sdist bdist_wheel +conda deactivate +dir dist + +# Note: uploading with twine gives an error in the end, but apparently it works (check final result in pypi). +twine upload dist/pydevd* + +git tag pydev_debugger_2_8_0 -a -m "PyDev.Debugger 2.8.0" +git push --tags + diff --git a/build_tools/rename_pep8.py b/build_tools/rename_pep8.py new file mode 100644 index 0000000..9a01203 --- /dev/null +++ b/build_tools/rename_pep8.py @@ -0,0 +1,131 @@ +''' +Helper module to do refactoring to convert names to pep8. +''' +import re +import os +import names_to_rename + +_CAMEL_RE = re.compile(r'(?<=[a-z])([A-Z])') +_CAMEL_DEF_RE = re.compile(r'(def )((([A-Z0-9]+|[a-z0-9])[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*)') + + +def _normalize(name): + return _CAMEL_RE.sub(lambda x: '_' + x.group(1).lower(), name).lower() + + +def find_matches_in_contents(contents): + return [x[1] for x in re.findall(_CAMEL_DEF_RE, contents)] + + +def iter_files_in_dir(dirname): + for root, dirs, files in os.walk(dirname): + for name in ('pydevd_attach_to_process', '.git', 'stubs', 'pydev_ipython', 'third_party', 'pydev_ipython'): + try: + dirs.remove(name) + except: + pass + for filename in files: + if filename.endswith('.py') and filename not in ('rename_pep8.py', 'names_to_rename.py'): + path = os.path.join(root, filename) + with open(path, 'rb') as stream: + initial_contents = stream.read() + + yield path, initial_contents + + +def find_matches(): + found = set() + for path, initial_contents in iter_files_in_dir(os.path.dirname(os.path.dirname(__file__))): + found.update(find_matches_in_contents(initial_contents)) + print('\n'.join(sorted(found))) + print('Total', len(found)) + + +def substitute_contents(re_name_to_new_val, initial_contents): + contents = initial_contents + for key, val in re_name_to_new_val.iteritems(): + contents = re.sub(key, val, contents) + return contents + + +def make_replace(): + re_name_to_new_val = load_re_to_new_val(names_to_rename.NAMES) + # traverse root directory, and list directories as dirs and files as files + for path, initial_contents in iter_files_in_dir(os.path.dirname(os.path.dirname(__file__))): + contents = substitute_contents(re_name_to_new_val, initial_contents) + if contents != initial_contents: + print('Changed something at: %s' % (path,)) + + for val in re_name_to_new_val.itervalues(): + # Check in initial contents to see if it already existed! + if re.findall(r'\b%s\b' % (val,), initial_contents): + raise AssertionError('Error in:\n%s\n%s is already being used (and changes may conflict).' % (path, val,)) + + with open(path, 'wb') as stream: + stream.write(contents) + + +def load_re_to_new_val(names): + name_to_new_val = {} + for n in names.splitlines(): + n = n.strip() + if not n.startswith('#') and n: + name_to_new_val[r'\b' + n + r'\b'] = _normalize(n) + return name_to_new_val + + +def test(): + assert _normalize('RestoreSysSetTraceFunc') == 'restore_sys_set_trace_func' + assert _normalize('restoreSysSetTraceFunc') == 'restore_sys_set_trace_func' + assert _normalize('Restore') == 'restore' + matches = find_matches_in_contents(''' + def CamelCase() + def camelCase() + def ignore() + def ignore_this() + def Camel() + def CamelCaseAnother() + ''') + assert matches == ['CamelCase', 'camelCase', 'Camel', 'CamelCaseAnother'] + re_name_to_new_val = load_re_to_new_val(''' +# Call -- skip +# Call1 -- skip +# Call2 -- skip +# Call3 -- skip +# Call4 -- skip +CustomFramesContainerInit +DictContains +DictItems +DictIterItems +DictIterValues +DictKeys +DictPop +DictValues +''') + assert re_name_to_new_val == {'\\bDictPop\\b': 'dict_pop', '\\bDictItems\\b': 'dict_items', '\\bDictIterValues\\b': 'dict_iter_values', '\\bDictKeys\\b': 'dict_keys', '\\bDictContains\\b': 'dict_contains', '\\bDictIterItems\\b': 'dict_iter_items', '\\bCustomFramesContainerInit\\b': 'custom_frames_container_init', '\\bDictValues\\b': 'dict_values'} + assert substitute_contents(re_name_to_new_val, ''' +CustomFramesContainerInit +DictContains +DictItems +DictIterItems +DictIterValues +DictKeys +DictPop +DictValues +''') == ''' +custom_frames_container_init +dict_contains +dict_items +dict_iter_items +dict_iter_values +dict_keys +dict_pop +dict_values +''' + + +if __name__ == '__main__': +# find_matches() + make_replace() +# test() + diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..c46c3f9 --- /dev/null +++ b/conftest.py @@ -0,0 +1,369 @@ +import pytest +import sys +from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_IRONPYTHON +from tests_python.debug_constants import TEST_CYTHON +from tests_python.debug_constants import PYDEVD_TEST_VM +import site +import os +from _pydev_bundle import pydev_log + + +def pytest_report_header(config): + print('PYDEVD_USE_CYTHON: %s' % (TEST_CYTHON,)) + print('PYDEVD_TEST_VM: %s' % (PYDEVD_TEST_VM,)) + try: + import multiprocessing + except ImportError: + pass + else: + print('Number of processors: %s' % (multiprocessing.cpu_count(),)) + + print('Relevant system paths:') + print('sys.executable: %s' % (sys.executable,)) + print('sys.prefix: %s' % (sys.prefix,)) + + if hasattr(sys, 'base_prefix'): + print('sys.base_prefix: %s' % (sys.base_prefix,)) + + if hasattr(sys, 'real_prefix'): + print('sys.real_prefix: %s' % (sys.real_prefix,)) + + if hasattr(site, 'getusersitepackages'): + print('site.getusersitepackages(): %s' % (site.getusersitepackages(),)) + + if hasattr(site, 'getsitepackages'): + print('site.getsitepackages(): %s' % (site.getsitepackages(),)) + + for path in sys.path: + if os.path.exists(path) and os.path.basename(path) == 'site-packages': + print('Folder with "site-packages" in sys.path: %s' % (path,)) + + +_started_monitoring_threads = False + + +def _start_monitoring_threads(): + # After the session finishes, wait 20 seconds to see if everything finished properly + # and if it doesn't report an error. + global _started_monitoring_threads + if _started_monitoring_threads: + return + + _started_monitoring_threads = True + import threading + if hasattr(sys, '_current_frames') and hasattr(threading, 'enumerate'): + import time + import traceback + + class DumpThreads(threading.Thread): + + def run(self): + time.sleep(20) + + thread_id_to_name = {} + try: + for t in threading.enumerate(): + thread_id_to_name[t.ident] = '%s (daemon: %s)' % (t.name, t.daemon) + except: + pass + + stack_trace = [ + '===============================================================================', + 'pydev pyunit runner: Threads still found running after tests finished', + '================================= Thread Dump ================================='] + + for thread_id, stack in sys._current_frames().items(): + stack_trace.append('\n-------------------------------------------------------------------------------') + stack_trace.append(" Thread %s" % thread_id_to_name.get(thread_id, thread_id)) + stack_trace.append('') + + if 'self' in stack.f_locals: + sys.stderr.write(str(stack.f_locals['self']) + '\n') + + for filename, lineno, name, line in traceback.extract_stack(stack): + stack_trace.append(' File "%s", line %d, in %s' % (filename, lineno, name)) + if line: + stack_trace.append(" %s" % (line.strip())) + stack_trace.append('\n=============================== END Thread Dump ===============================') + sys.stderr.write('\n'.join(stack_trace)) + + # Force thread run to finish + import os + os._exit(123) + + dump_current_frames_thread = DumpThreads() + dump_current_frames_thread.daemon = True # Daemon so that this thread doesn't halt it! + dump_current_frames_thread.start() + + +def pytest_unconfigure(): + _start_monitoring_threads() + + +@pytest.fixture(scope="session", autouse=True) +def check_no_threads(): + yield + _start_monitoring_threads() + + +# see: http://goo.gl/kTQMs +SYMBOLS = { + 'customary': ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'), + 'customary_ext': ('byte', 'kilo', 'mega', 'giga', 'tera', 'peta', 'exa', + 'zetta', 'iotta'), + 'iec': ('Bi', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'), + 'iec_ext': ('byte', 'kibi', 'mebi', 'gibi', 'tebi', 'pebi', 'exbi', + 'zebi', 'yobi'), +} + + +def bytes2human(n, format='%(value).1f %(symbol)s', symbols='customary'): + """ + Bytes-to-human / human-to-bytes converter. + Based on: http://goo.gl/kTQMs + Working with Python 2.x and 3.x. + + Author: Giampaolo Rodola' + License: MIT + """ + + """ + Convert n bytes into a human readable string based on format. + symbols can be either "customary", "customary_ext", "iec" or "iec_ext", + see: http://goo.gl/kTQMs + + >>> bytes2human(0) + '0.0 B' + >>> bytes2human(0.9) + '0.0 B' + >>> bytes2human(1) + '1.0 B' + >>> bytes2human(1.9) + '1.0 B' + >>> bytes2human(1024) + '1.0 K' + >>> bytes2human(1048576) + '1.0 M' + >>> bytes2human(1099511627776127398123789121) + '909.5 Y' + + >>> bytes2human(9856, symbols="customary") + '9.6 K' + >>> bytes2human(9856, symbols="customary_ext") + '9.6 kilo' + >>> bytes2human(9856, symbols="iec") + '9.6 Ki' + >>> bytes2human(9856, symbols="iec_ext") + '9.6 kibi' + + >>> bytes2human(10000, "%(value).1f %(symbol)s/sec") + '9.8 K/sec' + + >>> # precision can be adjusted by playing with %f operator + >>> bytes2human(10000, format="%(value).5f %(symbol)s") + '9.76562 K' + """ + n = int(n) + if n < 0: + raise ValueError("n < 0") + symbols = SYMBOLS[symbols] + prefix = {} + for i, s in enumerate(symbols[1:]): + prefix[s] = 1 << (i + 1) * 10 + for symbol in reversed(symbols[1:]): + if n >= prefix[symbol]: + value = float(n) / prefix[symbol] + return format % locals() + return format % dict(symbol=symbols[0], value=n) + + +def format_memory_info(memory_info, curr_proc_memory_info): + return 'Total: %s, Available: %s, Used: %s %%, Curr process: %s' % ( + bytes2human(memory_info.total), bytes2human(memory_info.available), memory_info.percent, format_process_memory_info(curr_proc_memory_info)) + + +def format_process_memory_info(proc_memory_info): + return bytes2human(proc_memory_info.rss) + + +DEBUG_MEMORY_INFO = False + +_global_collect_info = False + +PRINT_MEMORY_BEFORE_AFTER_TEST = False # This makes running tests slower (but it may be handy to diagnose memory issues). + + +@pytest.fixture(autouse=PRINT_MEMORY_BEFORE_AFTER_TEST) +def before_after_each_function(request): + global _global_collect_info + + try: + import psutil # Don't fail if not there + except ImportError: + yield + return + + current_pids = set(proc.pid for proc in psutil.process_iter()) + before_curr_proc_memory_info = psutil.Process().memory_info() + + if _global_collect_info and DEBUG_MEMORY_INFO: + try: + from pympler import summary, muppy + sum1 = summary.summarize(muppy.get_objects()) + except: + pydev_log.exception() + + sys.stdout.write( +''' +=============================================================================== +Memory before: %s +%s +=============================================================================== +''' % (request.function, format_memory_info(psutil.virtual_memory(), before_curr_proc_memory_info))) + yield + + processes_info = [] + for proc in psutil.process_iter(): + if proc.pid not in current_pids: + try: + try: + cmdline = proc.cmdline() + except: + cmdline = '' + processes_info.append( + 'New Process: %s(%s - %s) - %s' % ( + proc.name(), + proc.pid, + cmdline, + format_process_memory_info(proc.memory_info()) + ) + ) + except (psutil.NoSuchProcess, psutil.AccessDenied): + pass # The process could've died in the meanwhile + + after_curr_proc_memory_info = psutil.Process().memory_info() + + if DEBUG_MEMORY_INFO: + try: + if after_curr_proc_memory_info.rss - before_curr_proc_memory_info.rss > 10 * 1000 * 1000: + # 10 MB leak + if _global_collect_info: + sum2 = summary.summarize(muppy.get_objects()) + diff = summary.get_diff(sum1, sum2) + sys.stdout.write('===============================================================================\n') + sys.stdout.write('Leak info:\n') + sys.stdout.write('===============================================================================\n') + summary.print_(diff) + sys.stdout.write('===============================================================================\n') + + _global_collect_info = True + # We'll only really collect the info on the next test (i.e.: if at one test + # we used too much memory, the next one will start collecting) + else: + _global_collect_info = False + except: + pydev_log.exception() + + sys.stdout.write( +''' +=============================================================================== +Memory after: %s +%s%s +=============================================================================== + + +''' % ( + request.function, + format_memory_info(psutil.virtual_memory(), after_curr_proc_memory_info), + '' if not processes_info else '\nLeaked processes:\n' + '\n'.join(processes_info)), + ) + + +from tests_python.regression_check import data_regression, datadir, original_datadir + + +@pytest.fixture +def pyfile(request, tmpdir): + """ + Based on debugpy pyfile fixture (adapter for older versions of Python) + + A fixture providing a factory function that generates .py files. + + The returned factory takes a single function with an empty argument list, + generates a temporary file that contains the code corresponding to the + function body, and returns the full path to the generated file. Idiomatic + use is as a decorator, e.g.: + + @pyfile + def script_file(): + print('fizz') + print('buzz') + + will produce a temporary file named script_file.py containing: + + print('fizz') + print('buzz') + + and the variable script_file will contain the path to that file. + + In order for the factory to be able to extract the function body properly, + function header ("def") must all be on a single line, with nothing after + the colon but whitespace. + + Note that because the code is physically in a separate file when it runs, + it cannot reuse top-level module imports - it must import all the modules + that it uses locally. When linter complains, use #noqa. + + Returns a py.path.local instance that has the additional attribute "lines". + After the source is writen to disk, tests.code.get_marked_line_numbers() is + invoked on the resulting file to compute the value of that attribute. + """ + import types + import inspect + + def factory(source): + assert isinstance(source, types.FunctionType) + name = source.__name__ + source, _ = inspect.getsourcelines(source) + + # First, find the "def" line. + def_lineno = 0 + for line in source: + line = line.strip() + if line.startswith("def") and line.endswith(":"): + break + def_lineno += 1 + else: + raise ValueError("Failed to locate function header.") + + # Remove everything up to and including "def". + source = source[def_lineno + 1:] + assert source + + # Now we need to adjust indentation. Compute how much the first line of + # the body is indented by, then dedent all lines by that amount. Blank + # lines don't matter indentation-wise, and might not be indented to begin + # with, so just replace them with a simple newline. + for line in source: + if line.strip(): + break # i.e.: use first non-empty line + indent = len(line) - len(line.lstrip()) + source = [l[indent:] if l.strip() else "\n" for l in source] + source = "".join(source) + + # Write it to file. + tmpfile = os.path.join(str(tmpdir), name + ".py") + assert not os.path.exists(tmpfile), '%s already exists.' % (tmpfile,) + with open(tmpfile, 'w') as stream: + stream.write(source) + + return tmpfile + + return factory + + +if IS_JYTHON or IS_IRONPYTHON: + + # On Jython and IronPython, it's a no-op. + def before_after_each_function(): + pass diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..9ee9ac9 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Feb 04 13:39:02 CET 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..9d82f78 --- /dev/null +++ b/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/interpreterInfo.py b/interpreterInfo.py new file mode 100644 index 0000000..de6aa00 --- /dev/null +++ b/interpreterInfo.py @@ -0,0 +1,255 @@ +''' +This module was created to get information available in the interpreter, such as libraries, +paths, etc. + +what is what: +sys.builtin_module_names: contains the builtin modules embeeded in python (rigth now, we specify all manually). +sys.prefix: A string giving the site-specific directory prefix where the platform independent Python files are installed + +format is something as +EXECUTABLE:python.exe|libs@compiled_dlls$builtin_mods + +all internal are separated by | +''' +import sys + +try: + import os.path + + def fully_normalize_path(path): + '''fixes the path so that the format of the path really reflects the directories in the system + ''' + return os.path.normpath(path) + + join = os.path.join +except: # ImportError or AttributeError. + + # See: http://stackoverflow.com/questions/10254353/error-while-installing-jython-for-pydev + def fully_normalize_path(path): + '''fixes the path so that the format of the path really reflects the directories in the system + ''' + return path + + def join(a, b): + if a.endswith('/') or a.endswith('\\'): + return a + b + return a + '/' + b + +IS_PYTHON_3_ONWARDS = 0 + +try: + IS_PYTHON_3_ONWARDS = sys.version_info[0] >= 3 +except: + # That's OK, not all versions of python have sys.version_info + pass + +try: + # Just check if False and True are defined (depends on version, not whether it's jython/python) + False + True +except: + exec ('True, False = 1,0') # An exec is used so that python 3k does not give a syntax error + +if sys.platform == "cygwin": + + import ctypes + + def native_path(path): + MAX_PATH = 512 # On cygwin NT, its 260 lately, but just need BIG ENOUGH buffer + '''Get the native form of the path, like c:\\Foo for /cygdrive/c/Foo''' + + retval = ctypes.create_string_buffer(MAX_PATH) + path = fully_normalize_path(path) + path = tobytes(path) + CCP_POSIX_TO_WIN_A = 0 + cygwin1dll = ctypes.cdll.LoadLibrary('cygwin1.dll') + cygwin1dll.cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, retval, MAX_PATH) + + return retval.value + +else: + + def native_path(path): + return fully_normalize_path(path) + + +def __getfilesystemencoding(): + ''' + Note: there's a copy of this method in _pydev_filesystem_encoding.py + ''' + try: + ret = sys.getfilesystemencoding() + if not ret: + raise RuntimeError('Unable to get encoding.') + return ret + except: + try: + # Handle Jython + from java.lang import System # @UnresolvedImport + env = System.getProperty("os.name").lower() + if env.find('win') != -1: + return 'ISO-8859-1' # mbcs does not work on Jython, so, use a (hopefully) suitable replacement + return 'utf-8' + except: + pass + + # Only available from 2.3 onwards. + if sys.platform == 'win32': + return 'mbcs' + return 'utf-8' + + +def getfilesystemencoding(): + try: + ret = __getfilesystemencoding() + + # Check if the encoding is actually there to be used! + if hasattr('', 'encode'): + ''.encode(ret) + if hasattr('', 'decode'): + ''.decode(ret) + + return ret + except: + return 'utf-8' + + +file_system_encoding = getfilesystemencoding() + +if IS_PYTHON_3_ONWARDS: + unicode_type = str + bytes_type = bytes + +else: + unicode_type = unicode + bytes_type = str + + +def tounicode(s): + if hasattr(s, 'decode'): + if not isinstance(s, unicode_type): + # Depending on the platform variant we may have decode on string or not. + return s.decode(file_system_encoding) + return s + + +def tobytes(s): + if hasattr(s, 'encode'): + if not isinstance(s, bytes_type): + return s.encode(file_system_encoding) + return s + + +def toasciimxl(s): + # output for xml without a declared encoding + + # As the output is xml, we have to encode chars (< and > are ok as they're not accepted in the filesystem name -- + # if it was allowed, we'd have to do things more selectively so that < and > don't get wrongly replaced). + s = s.replace("&", "&") + + try: + ret = s.encode('ascii', 'xmlcharrefreplace') + except: + # use workaround + ret = '' + for c in s: + try: + ret += c.encode('ascii') + except: + try: + # Python 2: unicode is a valid identifier + ret += unicode("&#%d;") % ord(c) + except: + # Python 3: a string is already unicode, so, just doing it directly should work. + ret += "&#%d;" % ord(c) + return ret + + +if __name__ == '__main__': + try: + # just give some time to get the reading threads attached (just in case) + import time + time.sleep(0.1) + except: + pass + + try: + executable = tounicode(native_path(sys.executable)) + except: + executable = tounicode(sys.executable) + + if sys.platform == "cygwin" and not executable.endswith(tounicode('.exe')): + executable += tounicode('.exe') + + try: + major = str(sys.version_info[0]) + minor = str(sys.version_info[1]) + except AttributeError: + # older versions of python don't have version_info + import string + s = string.split(sys.version, ' ')[0] + s = string.split(s, '.') + major = s[0] + minor = s[1] + + s = tounicode('%s.%s') % (tounicode(major), tounicode(minor)) + + contents = [tounicode('')] + contents.append(tounicode('%s') % (tounicode(s),)) + + contents.append(tounicode('%s') % tounicode(executable)) + + # this is the new implementation to get the system folders + # (still need to check if it works in linux) + # (previously, we were getting the executable dir, but that is not always correct...) + prefix = tounicode(native_path(sys.prefix)) + # print_ 'prefix is', prefix + + result = [] + + path_used = sys.path + try: + path_used = path_used[1:] # Use a copy (and don't include the directory of this script as a path.) + except: + pass # just ignore it... + + for p in path_used: + p = tounicode(native_path(p)) + + try: + import string # to be compatible with older versions + if string.find(p, prefix) == 0: # was startswith + result.append((p, True)) + else: + result.append((p, False)) + except (ImportError, AttributeError): + # python 3k also does not have it + # jython may not have it (depending on how are things configured) + if p.startswith(prefix): # was startswith + result.append((p, True)) + else: + result.append((p, False)) + + for p, b in result: + if b: + contents.append(tounicode('%s') % (p,)) + else: + contents.append(tounicode('%s') % (p,)) + + # no compiled libs + # nor forced libs + + for builtinMod in sys.builtin_module_names: + contents.append(tounicode('%s') % tounicode(builtinMod)) + + contents.append(tounicode('')) + unic = tounicode('\n').join(contents) + inasciixml = toasciimxl(unic) + if IS_PYTHON_3_ONWARDS: + # This is the 'official' way of writing binary output in Py3K (see: http://bugs.python.org/issue4571) + sys.stdout.buffer.write(inasciixml) + else: + sys.stdout.write(inasciixml) + + sys.stdout.flush() + sys.stderr.flush() diff --git a/pycompletionserver.py b/pycompletionserver.py new file mode 100644 index 0000000..2fb04f8 --- /dev/null +++ b/pycompletionserver.py @@ -0,0 +1,372 @@ +''' +Entry-point module to start the code-completion server for PyDev. + +@author Fabio Zadrozny +''' +from _pydevd_bundle.pydevd_constants import IS_JYTHON + +if IS_JYTHON: + import java.lang # @UnresolvedImport + SERVER_NAME = 'jycompletionserver' + from _pydev_bundle import _pydev_jy_imports_tipper + _pydev_imports_tipper = _pydev_jy_imports_tipper + +else: + # it is python + SERVER_NAME = 'pycompletionserver' + from _pydev_bundle import _pydev_imports_tipper + +from _pydev_bundle._pydev_saved_modules import socket + +import sys +if sys.platform == "darwin": + # See: https://sourceforge.net/projects/pydev/forums/forum/293649/topic/3454227 + try: + import _CF # Don't fail if it doesn't work -- do it because it must be loaded on the main thread! @UnresolvedImport @UnusedImport + except: + pass + +# initial sys.path +_sys_path = [] +for p in sys.path: + # changed to be compatible with 1.5 + _sys_path.append(p) + +# initial sys.modules +_sys_modules = {} +for name, mod in sys.modules.items(): + _sys_modules[name] = mod + +import traceback + +from io import StringIO + +from urllib.parse import quote_plus, unquote_plus + +INFO1 = 1 +INFO2 = 2 +WARN = 4 +ERROR = 8 + +DEBUG = INFO1 | ERROR + + +def dbg(s, prior): + if prior & DEBUG != 0: + sys.stdout.write('%s\n' % (s,)) +# f = open('c:/temp/test.txt', 'a') +# print_ >> f, s +# f.close() + + +from _pydev_bundle import pydev_localhost +HOST = pydev_localhost.get_localhost() # Symbolic name meaning the local host + +MSG_KILL_SERVER = '@@KILL_SERVER_END@@' +MSG_COMPLETIONS = '@@COMPLETIONS' +MSG_END = 'END@@' +MSG_INVALID_REQUEST = '@@INVALID_REQUEST' +MSG_JYTHON_INVALID_REQUEST = '@@JYTHON_INVALID_REQUEST' +MSG_CHANGE_DIR = '@@CHANGE_DIR:' +MSG_OK = '@@MSG_OK_END@@' +MSG_IMPORTS = '@@IMPORTS:' +MSG_PYTHONPATH = '@@PYTHONPATH_END@@' +MSG_CHANGE_PYTHONPATH = '@@CHANGE_PYTHONPATH:' +MSG_JEDI = '@@MSG_JEDI:' +MSG_SEARCH = '@@SEARCH' + +BUFFER_SIZE = 1024 + +currDirModule = None + + +def complete_from_dir(directory): + ''' + This is necessary so that we get the imports from the same directory where the file + we are completing is located. + ''' + global currDirModule + if currDirModule is not None: + if len(sys.path) > 0 and sys.path[0] == currDirModule: + del sys.path[0] + + currDirModule = directory + sys.path.insert(0, directory) + + +def change_python_path(pythonpath): + '''Changes the pythonpath (clears all the previous pythonpath) + + @param pythonpath: string with paths separated by | + ''' + + split = pythonpath.split('|') + sys.path = [] + for path in split: + path = path.strip() + if len(path) > 0: + sys.path.append(path) + + +class Processor: + + def __init__(self): + # nothing to do + return + + def remove_invalid_chars(self, msg): + try: + msg = str(msg) + except UnicodeDecodeError: + pass + + if msg: + try: + return quote_plus(msg) + except: + sys.stdout.write('error making quote plus in %s\n' % (msg,)) + raise + return ' ' + + def format_completion_message(self, defFile, completionsList): + ''' + Format the completions suggestions in the following format: + @@COMPLETIONS(modFile(token,description),(token,description),(token,description))END@@ + ''' + compMsg = [] + compMsg.append('%s' % defFile) + for tup in completionsList: + compMsg.append(',') + + compMsg.append('(') + compMsg.append(str(self.remove_invalid_chars(tup[0]))) # token + compMsg.append(',') + compMsg.append(self.remove_invalid_chars(tup[1])) # description + + if(len(tup) > 2): + compMsg.append(',') + compMsg.append(self.remove_invalid_chars(tup[2])) # args - only if function. + + if(len(tup) > 3): + compMsg.append(',') + compMsg.append(self.remove_invalid_chars(tup[3])) # TYPE + + compMsg.append(')') + + return '%s(%s)%s' % (MSG_COMPLETIONS, ''.join(compMsg), MSG_END) + + +class Exit(Exception): + pass + + +class CompletionServer: + + def __init__(self, port): + self.ended = False + self.port = port + self.socket = None # socket to send messages. + self.exit_process_on_kill = True + self.processor = Processor() + + def connect_to_server(self): + from _pydev_bundle._pydev_saved_modules import socket + + self.socket = s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect((HOST, self.port)) + except: + sys.stderr.write('Error on connect_to_server with parameters: host: %s port: %s\n' % (HOST, self.port)) + raise + + def get_completions_message(self, defFile, completionsList): + ''' + get message with completions. + ''' + return self.processor.format_completion_message(defFile, completionsList) + + def get_token_and_data(self, data): + ''' + When we receive this, we have 'token):data' + ''' + token = '' + for c in data: + if c != ')': + token = token + c + else: + break; + + return token, data.lstrip(token + '):') + + def emulated_sendall(self, msg): + MSGLEN = 1024 * 20 + + totalsent = 0 + while totalsent < MSGLEN: + sent = self.socket.send(msg[totalsent:]) + if sent == 0: + return + totalsent = totalsent + sent + + def send(self, msg): + self.socket.sendall(bytearray(msg, 'utf-8')) + + def run(self): + # Echo server program + try: + from _pydev_bundle import _pydev_log + log = _pydev_log.Log() + + dbg(SERVER_NAME + ' connecting to java server on %s (%s)' % (HOST, self.port) , INFO1) + # after being connected, create a socket as a client. + self.connect_to_server() + + dbg(SERVER_NAME + ' Connected to java server', INFO1) + + while not self.ended: + data = '' + + while data.find(MSG_END) == -1: + received = self.socket.recv(BUFFER_SIZE) + if len(received) == 0: + raise Exit() # ok, connection ended + data = data + received.decode('utf-8') + + try: + try: + if data.find(MSG_KILL_SERVER) != -1: + dbg(SERVER_NAME + ' kill message received', INFO1) + # break if we received kill message. + self.ended = True + raise Exit() + + dbg(SERVER_NAME + ' starting keep alive thread', INFO2) + + if data.find(MSG_PYTHONPATH) != -1: + comps = [] + for p in _sys_path: + comps.append((p, ' ')) + self.send(self.get_completions_message(None, comps)) + + else: + data = data[:data.rfind(MSG_END)] + + if data.startswith(MSG_IMPORTS): + data = data[len(MSG_IMPORTS):] + data = unquote_plus(data) + defFile, comps = _pydev_imports_tipper.generate_tip(data, log) + self.send(self.get_completions_message(defFile, comps)) + + elif data.startswith(MSG_CHANGE_PYTHONPATH): + data = data[len(MSG_CHANGE_PYTHONPATH):] + data = unquote_plus(data) + change_python_path(data) + self.send(MSG_OK) + + elif data.startswith(MSG_JEDI): + data = data[len(MSG_JEDI):] + data = unquote_plus(data) + line, column, encoding, path, source = data.split('|', 4) + try: + import jedi # @UnresolvedImport + except: + self.send(self.get_completions_message(None, [('Error on import jedi', 'Error importing jedi', '')])) + else: + script = jedi.Script( + # Line +1 because it expects lines 1-based (and col 0-based) + source=source, + line=int(line) + 1, + column=int(column), + source_encoding=encoding, + path=path, + ) + lst = [] + for completion in script.completions(): + t = completion.type + if t == 'class': + t = '1' + + elif t == 'function': + t = '2' + + elif t == 'import': + t = '0' + + elif t == 'keyword': + continue # Keywords are already handled in PyDev + + elif t == 'statement': + t = '3' + + else: + t = '-1' + + # gen list(tuple(name, doc, args, type)) + lst.append((completion.name, '', '', t)) + self.send(self.get_completions_message('empty', lst)) + + elif data.startswith(MSG_SEARCH): + data = data[len(MSG_SEARCH):] + data = unquote_plus(data) + (f, line, col), foundAs = _pydev_imports_tipper.search_definition(data) + self.send(self.get_completions_message(f, [(line, col, foundAs)])) + + elif data.startswith(MSG_CHANGE_DIR): + data = data[len(MSG_CHANGE_DIR):] + data = unquote_plus(data) + complete_from_dir(data) + self.send(MSG_OK) + + else: + self.send(MSG_INVALID_REQUEST) + except Exit: + e = sys.exc_info()[1] + msg = self.get_completions_message(None, [('Exit:', 'SystemExit', '')]) + try: + self.send(msg) + except socket.error: + pass # Ok, may be closed already + + raise e # raise original error. + + except: + dbg(SERVER_NAME + ' exception occurred', ERROR) + s = StringIO() + traceback.print_exc(file=s) + + err = s.getvalue() + dbg(SERVER_NAME + ' received error: ' + str(err), ERROR) + msg = self.get_completions_message(None, [('ERROR:', '%s\nLog:%s' % (err, log.get_contents()), '')]) + try: + self.send(msg) + except socket.error: + pass # Ok, may be closed already + + finally: + log.clear_log() + + self.socket.close() + self.ended = True + raise Exit() # connection broken + + except Exit: + if self.exit_process_on_kill: + sys.exit(0) + # No need to log SystemExit error + except: + s = StringIO() + exc_info = sys.exc_info() + + traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], limit=None, file=s) + err = s.getvalue() + dbg(SERVER_NAME + ' received error: ' + str(err), ERROR) + raise + + +if __name__ == '__main__': + + port = int(sys.argv[1]) # this is from where we want to receive messages. + + t = CompletionServer(port) + dbg(SERVER_NAME + ' will start', INFO1) + t.run() diff --git a/pydev_app_engine_debug_startup.py b/pydev_app_engine_debug_startup.py new file mode 100644 index 0000000..464f0dd --- /dev/null +++ b/pydev_app_engine_debug_startup.py @@ -0,0 +1,21 @@ +if False: + config = None + + +# See: https://docs.google.com/document/d/1CCSaRiIWCLgbD3OwmuKsRoHHDfBffbROWyVWWL0ZXN4/edit +if ':' not in config.version_id: + # The default server version_id does not contain ':' + import json + import os + import sys + + startup = config.python_config.startup_args + if not startup: + raise AssertionError('Expected --python_startup_args to be passed from the pydev debugger.') + + setup = json.loads(startup) + pydevd_path = setup['pydevd'] + sys.path.append(os.path.dirname(pydevd_path)) + + import pydevd + pydevd.settrace(setup['client'], port=setup['port'], suspend=False, trace_only_current_thread=False) diff --git a/pydev_coverage.py b/pydev_coverage.py new file mode 100644 index 0000000..665e87b --- /dev/null +++ b/pydev_coverage.py @@ -0,0 +1,94 @@ +''' +Entry point module to run code-coverage. +''' + + +def is_valid_py_file(path): + ''' + Checks whether the file can be read by the coverage module. This is especially + needed for .pyx files and .py files with syntax errors. + ''' + import os + + is_valid = False + if os.path.isfile(path) and not os.path.splitext(path)[1] == '.pyx': + try: + with open(path, 'rb') as f: + compile(f.read(), path, 'exec') + is_valid = True + except: + pass + return is_valid + + +def execute(): + import os + import sys + + files = None + if 'combine' not in sys.argv: + + if '--pydev-analyze' in sys.argv: + + # Ok, what we want here is having the files passed through stdin (because + # there may be too many files for passing in the command line -- we could + # just pass a dir and make the find files here, but as that's already + # given in the java side, let's just gather that info here). + sys.argv.remove('--pydev-analyze') + s = input() + s = s.replace('\r', '') + s = s.replace('\n', '') + + files = [] + invalid_files = [] + for v in s.split('|'): + if is_valid_py_file(v): + files.append(v) + else: + invalid_files.append(v) + if invalid_files: + sys.stderr.write('Invalid files not passed to coverage: %s\n' + % ', '.join(invalid_files)) + + # Note that in this case we'll already be in the working dir with the coverage files, + # so, the coverage file location is not passed. + + else: + # For all commands, the coverage file is configured in pydev, and passed as the first + # argument in the command line, so, let's make sure this gets to the coverage module. + os.environ['COVERAGE_FILE'] = sys.argv[1] + del sys.argv[1] + + try: + import coverage # @UnresolvedImport + except: + sys.stderr.write('Error: coverage module could not be imported\n') + sys.stderr.write('Please make sure that the coverage module ' + '(http://nedbatchelder.com/code/coverage/)\n') + sys.stderr.write('is properly installed in your interpreter: %s\n' % (sys.executable,)) + + import traceback;traceback.print_exc() + return + + if hasattr(coverage, '__version__'): + version = tuple(map(int, coverage.__version__.split('.')[:2])) + if version < (4, 3): + sys.stderr.write('Error: minimum supported coverage version is 4.3.' + '\nFound: %s\nLocation: %s\n' + % ('.'.join(str(x) for x in version), coverage.__file__)) + sys.exit(1) + else: + sys.stderr.write('Warning: Could not determine version of python module coverage.' + '\nEnsure coverage version is >= 4.3\n') + + from coverage.cmdline import main # @UnresolvedImport + + if files is not None: + sys.argv.append('xml') + sys.argv += files + + main() + + +if __name__ == '__main__': + execute() diff --git a/pydev_ipython/README b/pydev_ipython/README new file mode 100644 index 0000000..185d417 --- /dev/null +++ b/pydev_ipython/README @@ -0,0 +1,8 @@ +# Parts of IPython, files from: https://github.com/ipython/ipython/tree/rel-1.0.0/IPython +# The files in this package are extracted from IPython to aid the main loop integration +# See tests_mainloop for some manually runable tests + +# What we are doing is reusing the "inputhook" functionality (i.e. what in IPython +# ends up on PyOS_InputHook) and using it in the pydevconsole context. +# Rather that having the callbacks called in PyOS_InputHook, we use a custom XML-RPC +# Server (HookableXMLRPCServer) that calls the inputhook when idle diff --git a/pydev_ipython/__init__.py b/pydev_ipython/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pydev_ipython/inputhook.py b/pydev_ipython/inputhook.py new file mode 100644 index 0000000..fe08846 --- /dev/null +++ b/pydev_ipython/inputhook.py @@ -0,0 +1,592 @@ +# coding: utf-8 +""" +Inputhook management for GUI event loop integration. +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2011 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import sys +import select + +#----------------------------------------------------------------------------- +# Constants +#----------------------------------------------------------------------------- + +# Constants for identifying the GUI toolkits. +GUI_WX = 'wx' +GUI_QT = 'qt' +GUI_QT4 = 'qt4' +GUI_QT5 = 'qt5' +GUI_GTK = 'gtk' +GUI_TK = 'tk' +GUI_OSX = 'osx' +GUI_GLUT = 'glut' +GUI_PYGLET = 'pyglet' +GUI_GTK3 = 'gtk3' +GUI_NONE = 'none' # i.e. disable + +#----------------------------------------------------------------------------- +# Utilities +#----------------------------------------------------------------------------- + + +def ignore_CTRL_C(): + """Ignore CTRL+C (not implemented).""" + pass + + +def allow_CTRL_C(): + """Take CTRL+C into account (not implemented).""" + pass + +#----------------------------------------------------------------------------- +# Main InputHookManager class +#----------------------------------------------------------------------------- + + +class InputHookManager(object): + """Manage PyOS_InputHook for different GUI toolkits. + + This class installs various hooks under ``PyOSInputHook`` to handle + GUI event loop integration. + """ + + def __init__(self): + self._return_control_callback = None + self._apps = {} + self._reset() + self.pyplot_imported = False + + def _reset(self): + self._callback_pyfunctype = None + self._callback = None + self._current_gui = None + + def set_return_control_callback(self, return_control_callback): + self._return_control_callback = return_control_callback + + def get_return_control_callback(self): + return self._return_control_callback + + def return_control(self): + return self._return_control_callback() + + def get_inputhook(self): + return self._callback + + def set_inputhook(self, callback): + """Set inputhook to callback.""" + # We don't (in the context of PyDev console) actually set PyOS_InputHook, but rather + # while waiting for input on xmlrpc we run this code + self._callback = callback + + def clear_inputhook(self, app=None): + """Clear input hook. + + Parameters + ---------- + app : optional, ignored + This parameter is allowed only so that clear_inputhook() can be + called with a similar interface as all the ``enable_*`` methods. But + the actual value of the parameter is ignored. This uniform interface + makes it easier to have user-level entry points in the main IPython + app like :meth:`enable_gui`.""" + self._reset() + + def clear_app_refs(self, gui=None): + """Clear IPython's internal reference to an application instance. + + Whenever we create an app for a user on qt4 or wx, we hold a + reference to the app. This is needed because in some cases bad things + can happen if a user doesn't hold a reference themselves. This + method is provided to clear the references we are holding. + + Parameters + ---------- + gui : None or str + If None, clear all app references. If ('wx', 'qt4') clear + the app for that toolkit. References are not held for gtk or tk + as those toolkits don't have the notion of an app. + """ + if gui is None: + self._apps = {} + elif gui in self._apps: + del self._apps[gui] + + def enable_wx(self, app=None): + """Enable event loop integration with wxPython. + + Parameters + ---------- + app : WX Application, optional. + Running application to use. If not given, we probe WX for an + existing application object, and create a new one if none is found. + + Notes + ----- + This methods sets the ``PyOS_InputHook`` for wxPython, which allows + the wxPython to integrate with terminal based applications like + IPython. + + If ``app`` is not given we probe for an existing one, and return it if + found. If no existing app is found, we create an :class:`wx.App` as + follows:: + + import wx + app = wx.App(redirect=False, clearSigInt=False) + """ + import wx + from distutils.version import LooseVersion as V + wx_version = V(wx.__version__).version # @UndefinedVariable + + if wx_version < [2, 8]: + raise ValueError("requires wxPython >= 2.8, but you have %s" % wx.__version__) # @UndefinedVariable + + from pydev_ipython.inputhookwx import inputhook_wx + self.set_inputhook(inputhook_wx) + self._current_gui = GUI_WX + + if app is None: + app = wx.GetApp() # @UndefinedVariable + if app is None: + app = wx.App(redirect=False, clearSigInt=False) # @UndefinedVariable + app._in_event_loop = True + self._apps[GUI_WX] = app + return app + + def disable_wx(self): + """Disable event loop integration with wxPython. + + This merely sets PyOS_InputHook to NULL. + """ + if GUI_WX in self._apps: + self._apps[GUI_WX]._in_event_loop = False + self.clear_inputhook() + + def enable_qt(self, app=None): + from pydev_ipython.qt_for_kernel import QT_API, QT_API_PYQT5 + if QT_API == QT_API_PYQT5: + self.enable_qt5(app) + else: + self.enable_qt4(app) + + def enable_qt4(self, app=None): + """Enable event loop integration with PyQt4. + + Parameters + ---------- + app : Qt Application, optional. + Running application to use. If not given, we probe Qt for an + existing application object, and create a new one if none is found. + + Notes + ----- + This methods sets the PyOS_InputHook for PyQt4, which allows + the PyQt4 to integrate with terminal based applications like + IPython. + + If ``app`` is not given we probe for an existing one, and return it if + found. If no existing app is found, we create an :class:`QApplication` + as follows:: + + from PyQt4 import QtCore + app = QtGui.QApplication(sys.argv) + """ + from pydev_ipython.inputhookqt4 import create_inputhook_qt4 + app, inputhook_qt4 = create_inputhook_qt4(self, app) + self.set_inputhook(inputhook_qt4) + + self._current_gui = GUI_QT4 + app._in_event_loop = True + self._apps[GUI_QT4] = app + return app + + def disable_qt4(self): + """Disable event loop integration with PyQt4. + + This merely sets PyOS_InputHook to NULL. + """ + if GUI_QT4 in self._apps: + self._apps[GUI_QT4]._in_event_loop = False + self.clear_inputhook() + + def enable_qt5(self, app=None): + from pydev_ipython.inputhookqt5 import create_inputhook_qt5 + app, inputhook_qt5 = create_inputhook_qt5(self, app) + self.set_inputhook(inputhook_qt5) + + self._current_gui = GUI_QT5 + app._in_event_loop = True + self._apps[GUI_QT5] = app + return app + + def disable_qt5(self): + if GUI_QT5 in self._apps: + self._apps[GUI_QT5]._in_event_loop = False + self.clear_inputhook() + + def enable_gtk(self, app=None): + """Enable event loop integration with PyGTK. + + Parameters + ---------- + app : ignored + Ignored, it's only a placeholder to keep the call signature of all + gui activation methods consistent, which simplifies the logic of + supporting magics. + + Notes + ----- + This methods sets the PyOS_InputHook for PyGTK, which allows + the PyGTK to integrate with terminal based applications like + IPython. + """ + from pydev_ipython.inputhookgtk import create_inputhook_gtk + self.set_inputhook(create_inputhook_gtk(self._stdin_file)) + self._current_gui = GUI_GTK + + def disable_gtk(self): + """Disable event loop integration with PyGTK. + + This merely sets PyOS_InputHook to NULL. + """ + self.clear_inputhook() + + def enable_tk(self, app=None): + """Enable event loop integration with Tk. + + Parameters + ---------- + app : toplevel :class:`Tkinter.Tk` widget, optional. + Running toplevel widget to use. If not given, we probe Tk for an + existing one, and create a new one if none is found. + + Notes + ----- + If you have already created a :class:`Tkinter.Tk` object, the only + thing done by this method is to register with the + :class:`InputHookManager`, since creating that object automatically + sets ``PyOS_InputHook``. + """ + self._current_gui = GUI_TK + if app is None: + try: + import Tkinter as _TK + except: + # Python 3 + import tkinter as _TK # @UnresolvedImport + app = _TK.Tk() + app.withdraw() + self._apps[GUI_TK] = app + + from pydev_ipython.inputhooktk import create_inputhook_tk + self.set_inputhook(create_inputhook_tk(app)) + return app + + def disable_tk(self): + """Disable event loop integration with Tkinter. + + This merely sets PyOS_InputHook to NULL. + """ + self.clear_inputhook() + + def enable_glut(self, app=None): + """ Enable event loop integration with GLUT. + + Parameters + ---------- + + app : ignored + Ignored, it's only a placeholder to keep the call signature of all + gui activation methods consistent, which simplifies the logic of + supporting magics. + + Notes + ----- + + This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to + integrate with terminal based applications like IPython. Due to GLUT + limitations, it is currently not possible to start the event loop + without first creating a window. You should thus not create another + window but use instead the created one. See 'gui-glut.py' in the + docs/examples/lib directory. + + The default screen mode is set to: + glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH + """ + + import OpenGL.GLUT as glut # @UnresolvedImport + from pydev_ipython.inputhookglut import glut_display_mode, \ + glut_close, glut_display, \ + glut_idle, inputhook_glut + + if GUI_GLUT not in self._apps: + argv = getattr(sys, 'argv', []) + glut.glutInit(argv) + glut.glutInitDisplayMode(glut_display_mode) + # This is specific to freeglut + if bool(glut.glutSetOption): + glut.glutSetOption(glut.GLUT_ACTION_ON_WINDOW_CLOSE, + glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS) + glut.glutCreateWindow(argv[0] if len(argv) > 0 else '') + glut.glutReshapeWindow(1, 1) + glut.glutHideWindow() + glut.glutWMCloseFunc(glut_close) + glut.glutDisplayFunc(glut_display) + glut.glutIdleFunc(glut_idle) + else: + glut.glutWMCloseFunc(glut_close) + glut.glutDisplayFunc(glut_display) + glut.glutIdleFunc(glut_idle) + self.set_inputhook(inputhook_glut) + self._current_gui = GUI_GLUT + self._apps[GUI_GLUT] = True + + def disable_glut(self): + """Disable event loop integration with glut. + + This sets PyOS_InputHook to NULL and set the display function to a + dummy one and set the timer to a dummy timer that will be triggered + very far in the future. + """ + import OpenGL.GLUT as glut # @UnresolvedImport + from glut_support import glutMainLoopEvent # @UnresolvedImport + + glut.glutHideWindow() # This is an event to be processed below + glutMainLoopEvent() + self.clear_inputhook() + + def enable_pyglet(self, app=None): + """Enable event loop integration with pyglet. + + Parameters + ---------- + app : ignored + Ignored, it's only a placeholder to keep the call signature of all + gui activation methods consistent, which simplifies the logic of + supporting magics. + + Notes + ----- + This methods sets the ``PyOS_InputHook`` for pyglet, which allows + pyglet to integrate with terminal based applications like + IPython. + + """ + from pydev_ipython.inputhookpyglet import inputhook_pyglet + self.set_inputhook(inputhook_pyglet) + self._current_gui = GUI_PYGLET + return app + + def disable_pyglet(self): + """Disable event loop integration with pyglet. + + This merely sets PyOS_InputHook to NULL. + """ + self.clear_inputhook() + + def enable_gtk3(self, app=None): + """Enable event loop integration with Gtk3 (gir bindings). + + Parameters + ---------- + app : ignored + Ignored, it's only a placeholder to keep the call signature of all + gui activation methods consistent, which simplifies the logic of + supporting magics. + + Notes + ----- + This methods sets the PyOS_InputHook for Gtk3, which allows + the Gtk3 to integrate with terminal based applications like + IPython. + """ + from pydev_ipython.inputhookgtk3 import create_inputhook_gtk3 + self.set_inputhook(create_inputhook_gtk3(self._stdin_file)) + self._current_gui = GUI_GTK + + def disable_gtk3(self): + """Disable event loop integration with PyGTK. + + This merely sets PyOS_InputHook to NULL. + """ + self.clear_inputhook() + + def enable_mac(self, app=None): + """ Enable event loop integration with MacOSX. + + We call function pyplot.pause, which updates and displays active + figure during pause. It's not MacOSX-specific, but it enables to + avoid inputhooks in native MacOSX backend. + Also we shouldn't import pyplot, until user does it. Cause it's + possible to choose backend before importing pyplot for the first + time only. + """ + + def inputhook_mac(app=None): + if self.pyplot_imported: + pyplot = sys.modules['matplotlib.pyplot'] + try: + pyplot.pause(0.01) + except: + pass + else: + if 'matplotlib.pyplot' in sys.modules: + self.pyplot_imported = True + + self.set_inputhook(inputhook_mac) + self._current_gui = GUI_OSX + + def disable_mac(self): + self.clear_inputhook() + + def current_gui(self): + """Return a string indicating the currently active GUI or None.""" + return self._current_gui + + +inputhook_manager = InputHookManager() + +enable_wx = inputhook_manager.enable_wx +disable_wx = inputhook_manager.disable_wx +enable_qt = inputhook_manager.enable_qt +enable_qt4 = inputhook_manager.enable_qt4 +disable_qt4 = inputhook_manager.disable_qt4 +enable_qt5 = inputhook_manager.enable_qt5 +disable_qt5 = inputhook_manager.disable_qt5 +enable_gtk = inputhook_manager.enable_gtk +disable_gtk = inputhook_manager.disable_gtk +enable_tk = inputhook_manager.enable_tk +disable_tk = inputhook_manager.disable_tk +enable_glut = inputhook_manager.enable_glut +disable_glut = inputhook_manager.disable_glut +enable_pyglet = inputhook_manager.enable_pyglet +disable_pyglet = inputhook_manager.disable_pyglet +enable_gtk3 = inputhook_manager.enable_gtk3 +disable_gtk3 = inputhook_manager.disable_gtk3 +enable_mac = inputhook_manager.enable_mac +disable_mac = inputhook_manager.disable_mac +clear_inputhook = inputhook_manager.clear_inputhook +set_inputhook = inputhook_manager.set_inputhook +current_gui = inputhook_manager.current_gui +clear_app_refs = inputhook_manager.clear_app_refs + +# We maintain this as stdin_ready so that the individual inputhooks +# can diverge as little as possible from their IPython sources +stdin_ready = inputhook_manager.return_control +set_return_control_callback = inputhook_manager.set_return_control_callback +get_return_control_callback = inputhook_manager.get_return_control_callback +get_inputhook = inputhook_manager.get_inputhook + + +# Convenience function to switch amongst them +def enable_gui(gui=None, app=None): + """Switch amongst GUI input hooks by name. + + This is just a utility wrapper around the methods of the InputHookManager + object. + + Parameters + ---------- + gui : optional, string or None + If None (or 'none'), clears input hook, otherwise it must be one + of the recognized GUI names (see ``GUI_*`` constants in module). + + app : optional, existing application object. + For toolkits that have the concept of a global app, you can supply an + existing one. If not given, the toolkit will be probed for one, and if + none is found, a new one will be created. Note that GTK does not have + this concept, and passing an app if ``gui=="GTK"`` will raise an error. + + Returns + ------- + The output of the underlying gui switch routine, typically the actual + PyOS_InputHook wrapper object or the GUI toolkit app created, if there was + one. + """ + + if get_return_control_callback() is None: + raise ValueError("A return_control_callback must be supplied as a reference before a gui can be enabled") + + guis = {GUI_NONE: clear_inputhook, + GUI_OSX: enable_mac, + GUI_TK: enable_tk, + GUI_GTK: enable_gtk, + GUI_WX: enable_wx, + GUI_QT: enable_qt, + GUI_QT4: enable_qt4, + GUI_QT5: enable_qt5, + GUI_GLUT: enable_glut, + GUI_PYGLET: enable_pyglet, + GUI_GTK3: enable_gtk3, + } + try: + gui_hook = guis[gui] + except KeyError: + if gui is None or gui == '': + gui_hook = clear_inputhook + else: + e = "Invalid GUI request %r, valid ones are:%s" % (gui, list(guis.keys())) + raise ValueError(e) + return gui_hook(app) + + +__all__ = [ + "GUI_WX", + "GUI_QT", + "GUI_QT4", + "GUI_QT5", + "GUI_GTK", + "GUI_TK", + "GUI_OSX", + "GUI_GLUT", + "GUI_PYGLET", + "GUI_GTK3", + "GUI_NONE", + + "ignore_CTRL_C", + "allow_CTRL_C", + + "InputHookManager", + + "inputhook_manager", + + "enable_wx", + "disable_wx", + "enable_qt", + "enable_qt4", + "disable_qt4", + "enable_qt5", + "disable_qt5", + "enable_gtk", + "disable_gtk", + "enable_tk", + "disable_tk", + "enable_glut", + "disable_glut", + "enable_pyglet", + "disable_pyglet", + "enable_gtk3", + "disable_gtk3", + "enable_mac", + "disable_mac", + "clear_inputhook", + "set_inputhook", + "current_gui", + "clear_app_refs", + + "stdin_ready", + "set_return_control_callback", + "get_return_control_callback", + "get_inputhook", + + "enable_gui"] diff --git a/pydev_ipython/inputhookglut.py b/pydev_ipython/inputhookglut.py new file mode 100644 index 0000000..d65add9 --- /dev/null +++ b/pydev_ipython/inputhookglut.py @@ -0,0 +1,154 @@ +# coding: utf-8 +""" +GLUT Inputhook support functions +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2011 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +# GLUT is quite an old library and it is difficult to ensure proper +# integration within IPython since original GLUT does not allow to handle +# events one by one. Instead, it requires for the mainloop to be entered +# and never returned (there is not even a function to exit he +# mainloop). Fortunately, there are alternatives such as freeglut +# (available for linux and windows) and the OSX implementation gives +# access to a glutCheckLoop() function that blocks itself until a new +# event is received. This means we have to setup the idle callback to +# ensure we got at least one event that will unblock the function. +# +# Furthermore, it is not possible to install these handlers without a window +# being first created. We choose to make this window invisible. This means that +# display mode options are set at this level and user won't be able to change +# them later without modifying the code. This should probably be made available +# via IPython options system. + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- +import os +import sys +from _pydev_bundle._pydev_saved_modules import time +import signal +import OpenGL.GLUT as glut # @UnresolvedImport +import OpenGL.platform as platform # @UnresolvedImport +from timeit import default_timer as clock +from pydev_ipython.inputhook import stdin_ready + +#----------------------------------------------------------------------------- +# Constants +#----------------------------------------------------------------------------- + +# Frame per second : 60 +# Should probably be an IPython option +glut_fps = 60 + +# Display mode : double buffeed + rgba + depth +# Should probably be an IPython option +glut_display_mode = (glut.GLUT_DOUBLE | + glut.GLUT_RGBA | + glut.GLUT_DEPTH) + +glutMainLoopEvent = None +if sys.platform == 'darwin': + try: + glutCheckLoop = platform.createBaseFunction( + 'glutCheckLoop', dll=platform.GLUT, resultType=None, + argTypes=[], + doc='glutCheckLoop( ) -> None', + argNames=(), + ) + except AttributeError: + raise RuntimeError( + '''Your glut implementation does not allow interactive sessions''' + '''Consider installing freeglut.''') + glutMainLoopEvent = glutCheckLoop +elif glut.HAVE_FREEGLUT: + glutMainLoopEvent = glut.glutMainLoopEvent +else: + raise RuntimeError( + '''Your glut implementation does not allow interactive sessions. ''' + '''Consider installing freeglut.''') + +#----------------------------------------------------------------------------- +# Callback functions +#----------------------------------------------------------------------------- + + +def glut_display(): + # Dummy display function + pass + + +def glut_idle(): + # Dummy idle function + pass + + +def glut_close(): + # Close function only hides the current window + glut.glutHideWindow() + glutMainLoopEvent() + + +def glut_int_handler(signum, frame): + # Catch sigint and print the defautl message + signal.signal(signal.SIGINT, signal.default_int_handler) + print('\nKeyboardInterrupt') + # Need to reprint the prompt at this stage + + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- +def inputhook_glut(): + """Run the pyglet event loop by processing pending events only. + + This keeps processing pending events until stdin is ready. After + processing all pending events, a call to time.sleep is inserted. This is + needed, otherwise, CPU usage is at 100%. This sleep time should be tuned + though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + + signal.signal(signal.SIGINT, glut_int_handler) + + try: + t = clock() + + # Make sure the default window is set after a window has been closed + if glut.glutGetWindow() == 0: + glut.glutSetWindow(1) + glutMainLoopEvent() + return 0 + + while not stdin_ready(): + glutMainLoopEvent() + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + except KeyboardInterrupt: + pass + return 0 diff --git a/pydev_ipython/inputhookgtk.py b/pydev_ipython/inputhookgtk.py new file mode 100644 index 0000000..53006cd --- /dev/null +++ b/pydev_ipython/inputhookgtk.py @@ -0,0 +1,36 @@ +# encoding: utf-8 +""" +Enable pygtk to be used interacive by setting PyOS_InputHook. + +Authors: Brian Granger +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2011 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import gtk, gobject # @UnresolvedImport + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + + +def _main_quit(*args, **kwargs): + gtk.main_quit() + return False + +def create_inputhook_gtk(stdin_file): + def inputhook_gtk(): + gobject.io_add_watch(stdin_file, gobject.IO_IN, _main_quit) + gtk.main() + return 0 + return inputhook_gtk + diff --git a/pydev_ipython/inputhookgtk3.py b/pydev_ipython/inputhookgtk3.py new file mode 100644 index 0000000..f2ca39f --- /dev/null +++ b/pydev_ipython/inputhookgtk3.py @@ -0,0 +1,35 @@ +# encoding: utf-8 +""" +Enable Gtk3 to be used interacive by IPython. + +Authors: Thomi Richards +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2012, the IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +from gi.repository import Gtk, GLib # @UnresolvedImport + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + +def _main_quit(*args, **kwargs): + Gtk.main_quit() + return False + + +def create_inputhook_gtk3(stdin_file): + def inputhook_gtk3(): + GLib.io_add_watch(stdin_file, GLib.IO_IN, _main_quit) + Gtk.main() + return 0 + return inputhook_gtk3 diff --git a/pydev_ipython/inputhookpyglet.py b/pydev_ipython/inputhookpyglet.py new file mode 100644 index 0000000..5529307 --- /dev/null +++ b/pydev_ipython/inputhookpyglet.py @@ -0,0 +1,92 @@ +# encoding: utf-8 +""" +Enable pyglet to be used interacive by setting PyOS_InputHook. + +Authors +------- + +* Nicolas P. Rougier +* Fernando Perez +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2011 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import os +import sys +from _pydev_bundle._pydev_saved_modules import time +from timeit import default_timer as clock +import pyglet # @UnresolvedImport +from pydev_ipython.inputhook import stdin_ready + + +# On linux only, window.flip() has a bug that causes an AttributeError on +# window close. For details, see: +# http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e + +if sys.platform.startswith('linux'): + def flip(window): + try: + window.flip() + except AttributeError: + pass +else: + def flip(window): + window.flip() + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + +def inputhook_pyglet(): + """Run the pyglet event loop by processing pending events only. + + This keeps processing pending events until stdin is ready. After + processing all pending events, a call to time.sleep is inserted. This is + needed, otherwise, CPU usage is at 100%. This sleep time should be tuned + though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + try: + t = clock() + while not stdin_ready(): + pyglet.clock.tick() + for window in pyglet.app.windows: + window.switch_to() + window.dispatch_events() + window.dispatch_event('on_draw') + flip(window) + + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + except KeyboardInterrupt: + pass + return 0 diff --git a/pydev_ipython/inputhookqt4.py b/pydev_ipython/inputhookqt4.py new file mode 100644 index 0000000..b7e1cf0 --- /dev/null +++ b/pydev_ipython/inputhookqt4.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- +""" +Qt4's inputhook support function + +Author: Christian Boos +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2011 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import os +import signal + +import threading + + +from pydev_ipython.qt_for_kernel import QtCore, QtGui +from pydev_ipython.inputhook import allow_CTRL_C, ignore_CTRL_C, stdin_ready + +# To minimise future merging complexity, rather than edit the entire code base below +# we fake InteractiveShell here +class InteractiveShell: + _instance = None + @classmethod + def instance(cls): + if cls._instance is None: + cls._instance = cls() + return cls._instance + def set_hook(self, *args, **kwargs): + # We don't consider the pre_prompt_hook because we don't have + # KeyboardInterrupts to consider since we are running under PyDev + pass + + +#----------------------------------------------------------------------------- +# Module Globals +#----------------------------------------------------------------------------- + +got_kbdint = False +sigint_timer = None + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + +def create_inputhook_qt4(mgr, app=None): + """Create an input hook for running the Qt4 application event loop. + + Parameters + ---------- + mgr : an InputHookManager + + app : Qt Application, optional. + Running application to use. If not given, we probe Qt for an + existing application object, and create a new one if none is found. + + Returns + ------- + A pair consisting of a Qt Application (either the one given or the + one found or created) and a inputhook. + + Notes + ----- + We use a custom input hook instead of PyQt4's default one, as it + interacts better with the readline packages (issue #481). + + The inputhook function works in tandem with a 'pre_prompt_hook' + which automatically restores the hook as an inputhook in case the + latter has been temporarily disabled after having intercepted a + KeyboardInterrupt. + """ + + if app is None: + app = QtCore.QCoreApplication.instance() + if app is None: + app = QtGui.QApplication([" "]) + + # Re-use previously created inputhook if any + ip = InteractiveShell.instance() + if hasattr(ip, '_inputhook_qt4'): + return app, ip._inputhook_qt4 + + # Otherwise create the inputhook_qt4/preprompthook_qt4 pair of + # hooks (they both share the got_kbdint flag) + + def inputhook_qt4(): + """PyOS_InputHook python hook for Qt4. + + Process pending Qt events and if there's no pending keyboard + input, spend a short slice of time (50ms) running the Qt event + loop. + + As a Python ctypes callback can't raise an exception, we catch + the KeyboardInterrupt and temporarily deactivate the hook, + which will let a *second* CTRL+C be processed normally and go + back to a clean prompt line. + """ + try: + allow_CTRL_C() + app = QtCore.QCoreApplication.instance() + if not app: # shouldn't happen, but safer if it happens anyway... + return 0 + app.processEvents(QtCore.QEventLoop.AllEvents, 300) + if not stdin_ready(): + # Generally a program would run QCoreApplication::exec() + # from main() to enter and process the Qt event loop until + # quit() or exit() is called and the program terminates. + # + # For our input hook integration, we need to repeatedly + # enter and process the Qt event loop for only a short + # amount of time (say 50ms) to ensure that Python stays + # responsive to other user inputs. + # + # A naive approach would be to repeatedly call + # QCoreApplication::exec(), using a timer to quit after a + # short amount of time. Unfortunately, QCoreApplication + # emits an aboutToQuit signal before stopping, which has + # the undesirable effect of closing all modal windows. + # + # To work around this problem, we instead create a + # QEventLoop and call QEventLoop::exec(). Other than + # setting some state variables which do not seem to be + # used anywhere, the only thing QCoreApplication adds is + # the aboutToQuit signal which is precisely what we are + # trying to avoid. + timer = QtCore.QTimer() + event_loop = QtCore.QEventLoop() + timer.timeout.connect(event_loop.quit) + while not stdin_ready(): + timer.start(50) + event_loop.exec_() + timer.stop() + except KeyboardInterrupt: + global got_kbdint, sigint_timer + + ignore_CTRL_C() + got_kbdint = True + mgr.clear_inputhook() + + # This generates a second SIGINT so the user doesn't have to + # press CTRL+C twice to get a clean prompt. + # + # Since we can't catch the resulting KeyboardInterrupt here + # (because this is a ctypes callback), we use a timer to + # generate the SIGINT after we leave this callback. + # + # Unfortunately this doesn't work on Windows (SIGINT kills + # Python and CTRL_C_EVENT doesn't work). + if(os.name == 'posix'): + pid = os.getpid() + if(not sigint_timer): + sigint_timer = threading.Timer(.01, os.kill, + args=[pid, signal.SIGINT] ) + sigint_timer.start() + else: + print("\nKeyboardInterrupt - Ctrl-C again for new prompt") + + + except: # NO exceptions are allowed to escape from a ctypes callback + ignore_CTRL_C() + from traceback import print_exc + print_exc() + print("Got exception from inputhook_qt4, unregistering.") + mgr.clear_inputhook() + finally: + allow_CTRL_C() + return 0 + + def preprompthook_qt4(ishell): + """'pre_prompt_hook' used to restore the Qt4 input hook + + (in case the latter was temporarily deactivated after a + CTRL+C) + """ + global got_kbdint, sigint_timer + + if(sigint_timer): + sigint_timer.cancel() + sigint_timer = None + + if got_kbdint: + mgr.set_inputhook(inputhook_qt4) + got_kbdint = False + + ip._inputhook_qt4 = inputhook_qt4 + ip.set_hook('pre_prompt_hook', preprompthook_qt4) + + return app, inputhook_qt4 diff --git a/pydev_ipython/inputhookqt5.py b/pydev_ipython/inputhookqt5.py new file mode 100644 index 0000000..15222df --- /dev/null +++ b/pydev_ipython/inputhookqt5.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +""" +Qt5's inputhook support function + +Author: Christian Boos +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2011 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import os +import signal + +import threading + +from pydev_ipython.qt_for_kernel import QtCore, QtGui +from pydev_ipython.inputhook import allow_CTRL_C, ignore_CTRL_C, stdin_ready + + +# To minimise future merging complexity, rather than edit the entire code base below +# we fake InteractiveShell here +class InteractiveShell: + _instance = None + + @classmethod + def instance(cls): + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def set_hook(self, *args, **kwargs): + # We don't consider the pre_prompt_hook because we don't have + # KeyboardInterrupts to consider since we are running under PyDev + pass + +#----------------------------------------------------------------------------- +# Module Globals +#----------------------------------------------------------------------------- + + +got_kbdint = False +sigint_timer = None + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + + +def create_inputhook_qt5(mgr, app=None): + """Create an input hook for running the Qt5 application event loop. + + Parameters + ---------- + mgr : an InputHookManager + + app : Qt Application, optional. + Running application to use. If not given, we probe Qt for an + existing application object, and create a new one if none is found. + + Returns + ------- + A pair consisting of a Qt Application (either the one given or the + one found or created) and a inputhook. + + Notes + ----- + We use a custom input hook instead of PyQt5's default one, as it + interacts better with the readline packages (issue #481). + + The inputhook function works in tandem with a 'pre_prompt_hook' + which automatically restores the hook as an inputhook in case the + latter has been temporarily disabled after having intercepted a + KeyboardInterrupt. + """ + + if app is None: + app = QtCore.QCoreApplication.instance() + if app is None: + from PyQt5 import QtWidgets + app = QtWidgets.QApplication([" "]) + + # Re-use previously created inputhook if any + ip = InteractiveShell.instance() + if hasattr(ip, '_inputhook_qt5'): + return app, ip._inputhook_qt5 + + # Otherwise create the inputhook_qt5/preprompthook_qt5 pair of + # hooks (they both share the got_kbdint flag) + + def inputhook_qt5(): + """PyOS_InputHook python hook for Qt5. + + Process pending Qt events and if there's no pending keyboard + input, spend a short slice of time (50ms) running the Qt event + loop. + + As a Python ctypes callback can't raise an exception, we catch + the KeyboardInterrupt and temporarily deactivate the hook, + which will let a *second* CTRL+C be processed normally and go + back to a clean prompt line. + """ + try: + allow_CTRL_C() + app = QtCore.QCoreApplication.instance() + if not app: # shouldn't happen, but safer if it happens anyway... + return 0 + app.processEvents(QtCore.QEventLoop.AllEvents, 300) + if not stdin_ready(): + # Generally a program would run QCoreApplication::exec() + # from main() to enter and process the Qt event loop until + # quit() or exit() is called and the program terminates. + # + # For our input hook integration, we need to repeatedly + # enter and process the Qt event loop for only a short + # amount of time (say 50ms) to ensure that Python stays + # responsive to other user inputs. + # + # A naive approach would be to repeatedly call + # QCoreApplication::exec(), using a timer to quit after a + # short amount of time. Unfortunately, QCoreApplication + # emits an aboutToQuit signal before stopping, which has + # the undesirable effect of closing all modal windows. + # + # To work around this problem, we instead create a + # QEventLoop and call QEventLoop::exec(). Other than + # setting some state variables which do not seem to be + # used anywhere, the only thing QCoreApplication adds is + # the aboutToQuit signal which is precisely what we are + # trying to avoid. + timer = QtCore.QTimer() + event_loop = QtCore.QEventLoop() + timer.timeout.connect(event_loop.quit) + while not stdin_ready(): + timer.start(50) + event_loop.exec_() + timer.stop() + except KeyboardInterrupt: + global got_kbdint, sigint_timer + + ignore_CTRL_C() + got_kbdint = True + mgr.clear_inputhook() + + # This generates a second SIGINT so the user doesn't have to + # press CTRL+C twice to get a clean prompt. + # + # Since we can't catch the resulting KeyboardInterrupt here + # (because this is a ctypes callback), we use a timer to + # generate the SIGINT after we leave this callback. + # + # Unfortunately this doesn't work on Windows (SIGINT kills + # Python and CTRL_C_EVENT doesn't work). + if(os.name == 'posix'): + pid = os.getpid() + if(not sigint_timer): + sigint_timer = threading.Timer(.01, os.kill, + args=[pid, signal.SIGINT]) + sigint_timer.start() + else: + print("\nKeyboardInterrupt - Ctrl-C again for new prompt") + + except: # NO exceptions are allowed to escape from a ctypes callback + ignore_CTRL_C() + from traceback import print_exc + print_exc() + print("Got exception from inputhook_qt5, unregistering.") + mgr.clear_inputhook() + finally: + allow_CTRL_C() + return 0 + + def preprompthook_qt5(ishell): + """'pre_prompt_hook' used to restore the Qt5 input hook + + (in case the latter was temporarily deactivated after a + CTRL+C) + """ + global got_kbdint, sigint_timer + + if(sigint_timer): + sigint_timer.cancel() + sigint_timer = None + + if got_kbdint: + mgr.set_inputhook(inputhook_qt5) + got_kbdint = False + + ip._inputhook_qt5 = inputhook_qt5 + ip.set_hook('pre_prompt_hook', preprompthook_qt5) + + return app, inputhook_qt5 diff --git a/pydev_ipython/inputhooktk.py b/pydev_ipython/inputhooktk.py new file mode 100644 index 0000000..e245cc0 --- /dev/null +++ b/pydev_ipython/inputhooktk.py @@ -0,0 +1,23 @@ +# encoding: utf-8 +# Unlike what IPython does, we need to have an explicit inputhook because tkinter handles +# input hook in the C Source code + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +from pydev_ipython.inputhook import stdin_ready + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + +TCL_DONT_WAIT = 1 << 1 + +def create_inputhook_tk(app): + def inputhook_tk(): + while app.dooneevent(TCL_DONT_WAIT) == 1: + if stdin_ready(): + break + return 0 + return inputhook_tk diff --git a/pydev_ipython/inputhookwx.py b/pydev_ipython/inputhookwx.py new file mode 100644 index 0000000..c2e4b91 --- /dev/null +++ b/pydev_ipython/inputhookwx.py @@ -0,0 +1,169 @@ +# encoding: utf-8 +""" +Enable wxPython to be used interacive by setting PyOS_InputHook. + +Authors: Robin Dunn, Brian Granger, Ondrej Certik +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2011 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import sys +import signal +from _pydev_bundle._pydev_saved_modules import time +from timeit import default_timer as clock +import wx + +from pydev_ipython.inputhook import stdin_ready + + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + +def inputhook_wx1(): + """Run the wx event loop by processing pending events only. + + This approach seems to work, but its performance is not great as it + relies on having PyOS_InputHook called regularly. + """ + try: + app = wx.GetApp() # @UndefinedVariable + if app is not None: + assert wx.Thread_IsMain() # @UndefinedVariable + + # Make a temporary event loop and process system events until + # there are no more waiting, then allow idle events (which + # will also deal with pending or posted wx events.) + evtloop = wx.EventLoop() # @UndefinedVariable + ea = wx.EventLoopActivator(evtloop) # @UndefinedVariable + while evtloop.Pending(): + evtloop.Dispatch() + app.ProcessIdle() + del ea + except KeyboardInterrupt: + pass + return 0 + +class EventLoopTimer(wx.Timer): # @UndefinedVariable + + def __init__(self, func): + self.func = func + wx.Timer.__init__(self) # @UndefinedVariable + + def Notify(self): + self.func() + +class EventLoopRunner(object): + + def Run(self, time): + self.evtloop = wx.EventLoop() # @UndefinedVariable + self.timer = EventLoopTimer(self.check_stdin) + self.timer.Start(time) + self.evtloop.Run() + + def check_stdin(self): + if stdin_ready(): + self.timer.Stop() + self.evtloop.Exit() + +def inputhook_wx2(): + """Run the wx event loop, polling for stdin. + + This version runs the wx eventloop for an undetermined amount of time, + during which it periodically checks to see if anything is ready on + stdin. If anything is ready on stdin, the event loop exits. + + The argument to elr.Run controls how often the event loop looks at stdin. + This determines the responsiveness at the keyboard. A setting of 1000 + enables a user to type at most 1 char per second. I have found that a + setting of 10 gives good keyboard response. We can shorten it further, + but eventually performance would suffer from calling select/kbhit too + often. + """ + try: + app = wx.GetApp() # @UndefinedVariable + if app is not None: + assert wx.Thread_IsMain() # @UndefinedVariable + elr = EventLoopRunner() + # As this time is made shorter, keyboard response improves, but idle + # CPU load goes up. 10 ms seems like a good compromise. + elr.Run(time=10) # CHANGE time here to control polling interval + except KeyboardInterrupt: + pass + return 0 + +def inputhook_wx3(): + """Run the wx event loop by processing pending events only. + + This is like inputhook_wx1, but it keeps processing pending events + until stdin is ready. After processing all pending events, a call to + time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%. + This sleep time should be tuned though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + try: + app = wx.GetApp() # @UndefinedVariable + if app is not None: + if hasattr(wx, 'IsMainThread'): + assert wx.IsMainThread() # @UndefinedVariable + else: + assert wx.Thread_IsMain() # @UndefinedVariable + + # The import of wx on Linux sets the handler for signal.SIGINT + # to 0. This is a bug in wx or gtk. We fix by just setting it + # back to the Python default. + if not callable(signal.getsignal(signal.SIGINT)): + signal.signal(signal.SIGINT, signal.default_int_handler) + + evtloop = wx.EventLoop() # @UndefinedVariable + ea = wx.EventLoopActivator(evtloop) # @UndefinedVariable + t = clock() + while not stdin_ready(): + while evtloop.Pending(): + t = clock() + evtloop.Dispatch() + app.ProcessIdle() + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + del ea + except KeyboardInterrupt: + pass + return 0 + +if sys.platform == 'darwin': + # On OSX, evtloop.Pending() always returns True, regardless of there being + # any events pending. As such we can't use implementations 1 or 3 of the + # inputhook as those depend on a pending/dispatch loop. + inputhook_wx = inputhook_wx2 +else: + # This is our default implementation + inputhook_wx = inputhook_wx3 diff --git a/pydev_ipython/matplotlibtools.py b/pydev_ipython/matplotlibtools.py new file mode 100644 index 0000000..71f0264 --- /dev/null +++ b/pydev_ipython/matplotlibtools.py @@ -0,0 +1,149 @@ + +import sys +from _pydev_bundle import pydev_log + +backends = {'tk': 'TkAgg', + 'gtk': 'GTKAgg', + 'wx': 'WXAgg', + 'qt': 'QtAgg', # Auto-choose qt4/5 + 'qt4': 'Qt4Agg', + 'qt5': 'Qt5Agg', + 'osx': 'MacOSX'} + +# We also need a reverse backends2guis mapping that will properly choose which +# GUI support to activate based on the desired matplotlib backend. For the +# most part it's just a reverse of the above dict, but we also need to add a +# few others that map to the same GUI manually: +backend2gui = dict(zip(backends.values(), backends.keys())) +# In the reverse mapping, there are a few extra valid matplotlib backends that +# map to the same GUI support +backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk' +backend2gui['WX'] = 'wx' +backend2gui['CocoaAgg'] = 'osx' + + +def do_enable_gui(guiname): + from _pydev_bundle.pydev_versioncheck import versionok_for_gui + if versionok_for_gui(): + try: + from pydev_ipython.inputhook import enable_gui + enable_gui(guiname) + except: + sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname) + pydev_log.exception() + elif guiname not in ['none', '', None]: + # Only print a warning if the guiname was going to do something + sys.stderr.write("Debug console: Python version does not support GUI event loop integration for '%s'\n" % guiname) + # Return value does not matter, so return back what was sent + return guiname + + +def find_gui_and_backend(): + """Return the gui and mpl backend.""" + matplotlib = sys.modules['matplotlib'] + # WARNING: this assumes matplotlib 1.1 or newer!! + backend = matplotlib.rcParams['backend'] + # In this case, we need to find what the appropriate gui selection call + # should be for IPython, so we can activate inputhook accordingly + gui = backend2gui.get(backend, None) + return gui, backend + + +def is_interactive_backend(backend): + """ Check if backend is interactive """ + matplotlib = sys.modules['matplotlib'] + from matplotlib.rcsetup import interactive_bk, non_interactive_bk # @UnresolvedImport + if backend in interactive_bk: + return True + elif backend in non_interactive_bk: + return False + else: + return matplotlib.is_interactive() + + +def patch_use(enable_gui_function): + """ Patch matplotlib function 'use' """ + matplotlib = sys.modules['matplotlib'] + + def patched_use(*args, **kwargs): + matplotlib.real_use(*args, **kwargs) + gui, backend = find_gui_and_backend() + enable_gui_function(gui) + + matplotlib.real_use = matplotlib.use + matplotlib.use = patched_use + + +def patch_is_interactive(): + """ Patch matplotlib function 'use' """ + matplotlib = sys.modules['matplotlib'] + + def patched_is_interactive(): + return matplotlib.rcParams['interactive'] + + matplotlib.real_is_interactive = matplotlib.is_interactive + matplotlib.is_interactive = patched_is_interactive + + +def activate_matplotlib(enable_gui_function): + """Set interactive to True for interactive backends. + enable_gui_function - Function which enables gui, should be run in the main thread. + """ + matplotlib = sys.modules['matplotlib'] + gui, backend = find_gui_and_backend() + is_interactive = is_interactive_backend(backend) + if is_interactive: + enable_gui_function(gui) + if not matplotlib.is_interactive(): + sys.stdout.write("Backend %s is interactive backend. Turning interactive mode on.\n" % backend) + matplotlib.interactive(True) + else: + if matplotlib.is_interactive(): + sys.stdout.write("Backend %s is non-interactive backend. Turning interactive mode off.\n" % backend) + matplotlib.interactive(False) + patch_use(enable_gui_function) + patch_is_interactive() + + +def flag_calls(func): + """Wrap a function to detect and flag when it gets called. + + This is a decorator which takes a function and wraps it in a function with + a 'called' attribute. wrapper.called is initialized to False. + + The wrapper.called attribute is set to False right before each call to the + wrapped function, so if the call fails it remains False. After the call + completes, wrapper.called is set to True and the output is returned. + + Testing for truth in wrapper.called allows you to determine if a call to + func() was attempted and succeeded.""" + + # don't wrap twice + if hasattr(func, 'called'): + return func + + def wrapper(*args, **kw): + wrapper.called = False + out = func(*args, **kw) + wrapper.called = True + return out + + wrapper.called = False + wrapper.__doc__ = func.__doc__ + return wrapper + + +def activate_pylab(): + pylab = sys.modules['pylab'] + pylab.show._needmain = False + # We need to detect at runtime whether show() is called by the user. + # For this, we wrap it into a decorator which adds a 'called' flag. + pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive) + + +def activate_pyplot(): + pyplot = sys.modules['matplotlib.pyplot'] + pyplot.show._needmain = False + # We need to detect at runtime whether show() is called by the user. + # For this, we wrap it into a decorator which adds a 'called' flag. + pyplot.draw_if_interactive = flag_calls(pyplot.draw_if_interactive) diff --git a/pydev_ipython/qt.py b/pydev_ipython/qt.py new file mode 100644 index 0000000..222c81b --- /dev/null +++ b/pydev_ipython/qt.py @@ -0,0 +1,23 @@ +""" A Qt API selector that can be used to switch between PyQt and PySide. + +This uses the ETS 4.0 selection pattern of: +PySide first, PyQt with API v2. second. + +Do not use this if you need PyQt with the old QString/QVariant API. +""" + +import os + +from pydev_ipython.qt_loaders import (load_qt, QT_API_PYSIDE, + QT_API_PYQT, QT_API_PYQT5) + +QT_API = os.environ.get('QT_API', None) +if QT_API not in [QT_API_PYSIDE, QT_API_PYQT, QT_API_PYQT5, None]: + raise RuntimeError("Invalid Qt API %r, valid values are: %r, %r" % + (QT_API, QT_API_PYSIDE, QT_API_PYQT, QT_API_PYQT5)) +if QT_API is None: + api_opts = [QT_API_PYSIDE, QT_API_PYQT, QT_API_PYQT5] +else: + api_opts = [QT_API] + +QtCore, QtGui, QtSvg, QT_API = load_qt(api_opts) diff --git a/pydev_ipython/qt_for_kernel.py b/pydev_ipython/qt_for_kernel.py new file mode 100644 index 0000000..500d25a --- /dev/null +++ b/pydev_ipython/qt_for_kernel.py @@ -0,0 +1,119 @@ +""" Import Qt in a manner suitable for an IPython kernel. + +This is the import used for the `gui=qt` or `matplotlib=qt` initialization. + +Import Priority: + +if Qt4 has been imported anywhere else: + use that + +if matplotlib has been imported and doesn't support v2 (<= 1.0.1): + use PyQt4 @v1 + +Next, ask ETS' QT_API env variable + +if QT_API not set: + ask matplotlib via rcParams['backend.qt4'] + if it said PyQt: + use PyQt4 @v1 + elif it said PySide: + use PySide + + else: (matplotlib said nothing) + # this is the default path - nobody told us anything + try: + PyQt @v1 + except: + fallback on PySide +else: + use PyQt @v2 or PySide, depending on QT_API + because ETS doesn't work with PyQt @v1. + +""" + +import os +import sys + +from pydev_ipython.version import check_version +from pydev_ipython.qt_loaders import (load_qt, QT_API_PYSIDE, QT_API_PYSIDE2, + QT_API_PYQT, QT_API_PYQT_DEFAULT, + loaded_api, QT_API_PYQT5) + + +# Constraints placed on an imported matplotlib +def matplotlib_options(mpl): + if mpl is None: + return + + # #PyDev-779: In pysrc/pydev_ipython/qt_for_kernel.py, matplotlib_options should be replaced with latest from ipython + # (i.e.: properly check backend to decide upon qt4/qt5). + + backend = mpl.rcParams.get('backend', None) + if backend == 'Qt4Agg': + mpqt = mpl.rcParams.get('backend.qt4', None) + if mpqt is None: + return None + if mpqt.lower() == 'pyside': + return [QT_API_PYSIDE] + elif mpqt.lower() == 'pyqt4': + return [QT_API_PYQT_DEFAULT] + elif mpqt.lower() == 'pyqt4v2': + return [QT_API_PYQT] + raise ImportError("unhandled value for backend.qt4 from matplotlib: %r" % + mpqt) + + elif backend == 'Qt5Agg': + mpqt = mpl.rcParams.get('backend.qt5', None) + if mpqt is None: + return None + if mpqt.lower() == 'pyqt5': + return [QT_API_PYQT5] + raise ImportError("unhandled value for backend.qt5 from matplotlib: %r" % + mpqt) + + # Fallback without checking backend (previous code) + mpqt = mpl.rcParams.get('backend.qt4', None) + if mpqt is None: + mpqt = mpl.rcParams.get('backend.qt5', None) + + if mpqt is None: + return None + if mpqt.lower() == 'pyside': + return [QT_API_PYSIDE] + elif mpqt.lower() == 'pyqt4': + return [QT_API_PYQT_DEFAULT] + elif mpqt.lower() == 'pyqt5': + return [QT_API_PYQT5] + raise ImportError("unhandled value for qt backend from matplotlib: %r" % + mpqt) + + +def get_options(): + """Return a list of acceptable QT APIs, in decreasing order of + preference + """ + # already imported Qt somewhere. Use that + loaded = loaded_api() + if loaded is not None: + return [loaded] + + mpl = sys.modules.get('matplotlib', None) + + if mpl is not None and not check_version(mpl.__version__, '1.0.2'): + # 1.0.1 only supports PyQt4 v1 + return [QT_API_PYQT_DEFAULT] + + if os.environ.get('QT_API', None) is None: + # no ETS variable. Ask mpl, then use either + return matplotlib_options(mpl) or [QT_API_PYQT_DEFAULT, QT_API_PYSIDE, QT_API_PYSIDE2, QT_API_PYQT5] + + # ETS variable present. Will fallback to external.qt + return None + + +api_opts = get_options() +if api_opts is not None: + QtCore, QtGui, QtSvg, QT_API = load_qt(api_opts) + +else: # use ETS variable + from pydev_ipython.qt import QtCore, QtGui, QtSvg, QT_API diff --git a/pydev_ipython/qt_loaders.py b/pydev_ipython/qt_loaders.py new file mode 100644 index 0000000..0e30d49 --- /dev/null +++ b/pydev_ipython/qt_loaders.py @@ -0,0 +1,301 @@ +""" +This module contains factory functions that attempt +to return Qt submodules from the various python Qt bindings. + +It also protects against double-importing Qt with different +bindings, which is unstable and likely to crash + +This is used primarily by qt and qt_for_kernel, and shouldn't +be accessed directly from the outside +""" +import sys +from functools import partial + +from pydev_ipython.version import check_version + +# Available APIs. +QT_API_PYQT = 'pyqt' +QT_API_PYQTv1 = 'pyqtv1' +QT_API_PYQT_DEFAULT = 'pyqtdefault' # don't set SIP explicitly +QT_API_PYSIDE = 'pyside' +QT_API_PYSIDE2 = 'pyside2' +QT_API_PYQT5 = 'pyqt5' + + +class ImportDenier(object): + """Import Hook that will guard against bad Qt imports + once IPython commits to a specific binding + """ + + def __init__(self): + self.__forbidden = set() + + def forbid(self, module_name): + sys.modules.pop(module_name, None) + self.__forbidden.add(module_name) + + def find_module(self, fullname, path=None): + if path: + return + if fullname in self.__forbidden: + return self + + def load_module(self, fullname): + raise ImportError(""" + Importing %s disabled by IPython, which has + already imported an Incompatible QT Binding: %s + """ % (fullname, loaded_api())) + + +ID = ImportDenier() +sys.meta_path.append(ID) + + +def commit_api(api): + """Commit to a particular API, and trigger ImportErrors on subsequent + dangerous imports""" + + if api == QT_API_PYSIDE: + ID.forbid('PyQt4') + ID.forbid('PyQt5') + else: + ID.forbid('PySide') + ID.forbid('PySide2') + + +def loaded_api(): + """Return which API is loaded, if any + + If this returns anything besides None, + importing any other Qt binding is unsafe. + + Returns + ------- + None, 'pyside', 'pyside2', 'pyqt', or 'pyqtv1' + """ + if 'PyQt4.QtCore' in sys.modules: + if qtapi_version() == 2: + return QT_API_PYQT + else: + return QT_API_PYQTv1 + elif 'PySide.QtCore' in sys.modules: + return QT_API_PYSIDE + elif 'PySide2.QtCore' in sys.modules: + return QT_API_PYSIDE2 + elif 'PyQt5.QtCore' in sys.modules: + return QT_API_PYQT5 + return None + + +def has_binding(api): + """Safely check for PyQt4 or PySide, without importing + submodules + + Parameters + ---------- + api : str [ 'pyqtv1' | 'pyqt' | 'pyside' | 'pyqtdefault'] + Which module to check for + + Returns + ------- + True if the relevant module appears to be importable + """ + # we can't import an incomplete pyside and pyqt4 + # this will cause a crash in sip (#1431) + # check for complete presence before importing + module_name = {QT_API_PYSIDE: 'PySide', + QT_API_PYSIDE2: 'PySide2', + QT_API_PYQT: 'PyQt4', + QT_API_PYQTv1: 'PyQt4', + QT_API_PYQT_DEFAULT: 'PyQt4', + QT_API_PYQT5: 'PyQt5', + } + module_name = module_name[api] + + import imp + try: + # importing top level PyQt4/PySide module is ok... + mod = __import__(module_name) + # ...importing submodules is not + imp.find_module('QtCore', mod.__path__) + imp.find_module('QtGui', mod.__path__) + imp.find_module('QtSvg', mod.__path__) + + # we can also safely check PySide version + if api == QT_API_PYSIDE: + return check_version(mod.__version__, '1.0.3') + else: + return True + except ImportError: + return False + + +def qtapi_version(): + """Return which QString API has been set, if any + + Returns + ------- + The QString API version (1 or 2), or None if not set + """ + try: + import sip + except ImportError: + return + try: + return sip.getapi('QString') + except ValueError: + return + + +def can_import(api): + """Safely query whether an API is importable, without importing it""" + if not has_binding(api): + return False + + current = loaded_api() + if api == QT_API_PYQT_DEFAULT: + return current in [QT_API_PYQT, QT_API_PYQTv1, QT_API_PYQT5, None] + else: + return current in [api, None] + + +def import_pyqt4(version=2): + """ + Import PyQt4 + + Parameters + ---------- + version : 1, 2, or None + Which QString/QVariant API to use. Set to None to use the system + default + + ImportErrors raised within this function are non-recoverable + """ + # The new-style string API (version=2) automatically + # converts QStrings to Unicode Python strings. Also, automatically unpacks + # QVariants to their underlying objects. + import sip + + if version is not None: + sip.setapi('QString', version) + sip.setapi('QVariant', version) + + from PyQt4 import QtGui, QtCore, QtSvg + + if not check_version(QtCore.PYQT_VERSION_STR, '4.7'): + raise ImportError("IPython requires PyQt4 >= 4.7, found %s" % + QtCore.PYQT_VERSION_STR) + + # Alias PyQt-specific functions for PySide compatibility. + QtCore.Signal = QtCore.pyqtSignal + QtCore.Slot = QtCore.pyqtSlot + + # query for the API version (in case version == None) + version = sip.getapi('QString') + api = QT_API_PYQTv1 if version == 1 else QT_API_PYQT + return QtCore, QtGui, QtSvg, api + + +def import_pyqt5(): + """ + Import PyQt5 + + ImportErrors raised within this function are non-recoverable + """ + from PyQt5 import QtGui, QtCore, QtSvg + + # Alias PyQt-specific functions for PySide compatibility. + QtCore.Signal = QtCore.pyqtSignal + QtCore.Slot = QtCore.pyqtSlot + + return QtCore, QtGui, QtSvg, QT_API_PYQT5 + + +def import_pyside(): + """ + Import PySide + + ImportErrors raised within this function are non-recoverable + """ + from PySide import QtGui, QtCore, QtSvg # @UnresolvedImport + return QtCore, QtGui, QtSvg, QT_API_PYSIDE + + +def import_pyside2(): + """ + Import PySide2 + + ImportErrors raised within this function are non-recoverable + """ + from PySide2 import QtGui, QtCore, QtSvg # @UnresolvedImport + return QtCore, QtGui, QtSvg, QT_API_PYSIDE + + +def load_qt(api_options): + """ + Attempt to import Qt, given a preference list + of permissible bindings + + It is safe to call this function multiple times. + + Parameters + ---------- + api_options: List of strings + The order of APIs to try. Valid items are 'pyside', + 'pyqt', and 'pyqtv1' + + Returns + ------- + + A tuple of QtCore, QtGui, QtSvg, QT_API + The first three are the Qt modules. The last is the + string indicating which module was loaded. + + Raises + ------ + ImportError, if it isn't possible to import any requested + bindings (either becaues they aren't installed, or because + an incompatible library has already been installed) + """ + loaders = {QT_API_PYSIDE: import_pyside, + QT_API_PYSIDE2: import_pyside2, + QT_API_PYQT: import_pyqt4, + QT_API_PYQTv1: partial(import_pyqt4, version=1), + QT_API_PYQT_DEFAULT: partial(import_pyqt4, version=None), + QT_API_PYQT5: import_pyqt5, + } + + for api in api_options: + + if api not in loaders: + raise RuntimeError( + "Invalid Qt API %r, valid values are: %r, %r, %r, %r, %r, %r" % + (api, QT_API_PYSIDE, QT_API_PYSIDE, QT_API_PYQT, + QT_API_PYQTv1, QT_API_PYQT_DEFAULT, QT_API_PYQT5)) + + if not can_import(api): + continue + + # cannot safely recover from an ImportError during this + result = loaders[api]() + api = result[-1] # changed if api = QT_API_PYQT_DEFAULT + commit_api(api) + return result + else: + raise ImportError(""" + Could not load requested Qt binding. Please ensure that + PyQt4 >= 4.7 or PySide >= 1.0.3 is available, + and only one is imported per session. + + Currently-imported Qt library: %r + PyQt4 installed: %s + PyQt5 installed: %s + PySide >= 1.0.3 installed: %s + PySide2 installed: %s + Tried to load: %r + """ % (loaded_api(), + has_binding(QT_API_PYQT), + has_binding(QT_API_PYQT5), + has_binding(QT_API_PYSIDE), + has_binding(QT_API_PYSIDE2), + api_options)) diff --git a/pydev_ipython/version.py b/pydev_ipython/version.py new file mode 100644 index 0000000..1de0047 --- /dev/null +++ b/pydev_ipython/version.py @@ -0,0 +1,36 @@ +# encoding: utf-8 +""" +Utilities for version comparison + +It is a bit ridiculous that we need these. +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2013 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +from distutils.version import LooseVersion + +#----------------------------------------------------------------------------- +# Code +#----------------------------------------------------------------------------- + +def check_version(v, check): + """check version string v >= check + + If dev/prerelease tags result in TypeError for string-number comparison, + it is assumed that the dependency is satisfied. + Users on dev branches are responsible for keeping their own packages up to date. + """ + try: + return LooseVersion(v) >= LooseVersion(check) + except TypeError: + return True + diff --git a/pydev_pysrc.py b/pydev_pysrc.py new file mode 100644 index 0000000..b9ed49e --- /dev/null +++ b/pydev_pysrc.py @@ -0,0 +1 @@ +'''An empty file in pysrc that can be imported (from sitecustomize) to find the location of pysrc''' \ No newline at end of file diff --git a/pydev_run_in_console.py b/pydev_run_in_console.py new file mode 100644 index 0000000..a87a0e4 --- /dev/null +++ b/pydev_run_in_console.py @@ -0,0 +1,153 @@ +''' +Entry point module to run a file in the interactive console. +''' +import os +import sys +import traceback +from pydevconsole import InterpreterInterface, process_exec_queue, start_console_server, init_mpl_in_console +from _pydev_bundle._pydev_saved_modules import threading, _queue + +from _pydev_bundle import pydev_imports +from _pydevd_bundle.pydevd_utils import save_main_module +from _pydev_bundle.pydev_console_utils import StdIn +from pydevd_file_utils import get_fullname + + +def run_file(file, globals=None, locals=None, is_module=False): + module_name = None + entry_point_fn = None + if is_module: + file, _, entry_point_fn = file.partition(':') + module_name = file + filename = get_fullname(file) + if filename is None: + sys.stderr.write("No module named %s\n" % file) + return + else: + file = filename + + if os.path.isdir(file): + new_target = os.path.join(file, '__main__.py') + if os.path.isfile(new_target): + file = new_target + + if globals is None: + m = save_main_module(file, 'pydev_run_in_console') + + globals = m.__dict__ + try: + globals['__builtins__'] = __builtins__ + except NameError: + pass # Not there on Jython... + + if locals is None: + locals = globals + + if not is_module: + sys.path.insert(0, os.path.split(file)[0]) + + print('Running %s' % file) + try: + if not is_module: + pydev_imports.execfile(file, globals, locals) # execute the script + else: + # treat ':' as a seperator between module and entry point function + # if there is no entry point we run we same as with -m switch. Otherwise we perform + # an import and execute the entry point + if entry_point_fn: + mod = __import__(module_name, level=0, fromlist=[entry_point_fn], globals=globals, locals=locals) + func = getattr(mod, entry_point_fn) + func() + else: + # Run with the -m switch + from _pydevd_bundle import pydevd_runpy + pydevd_runpy._run_module_as_main(module_name) + except: + traceback.print_exc() + + return globals + + +def skip_successful_exit(*args): + """ System exit in file shouldn't kill interpreter (i.e. in `timeit`)""" + if len(args) == 1 and args[0] in (0, None): + pass + else: + raise SystemExit(*args) + + +def process_args(argv): + setup_args = {'file': '', 'module': False} + + setup_args['port'] = argv[1] + del argv[1] + setup_args['client_port'] = argv[1] + del argv[1] + + module_flag = "--module" + if module_flag in argv: + i = argv.index(module_flag) + if i != -1: + setup_args['module'] = True + setup_args['file'] = argv[i + 1] + del sys.argv[i] + else: + setup_args['file'] = argv[1] + + del argv[0] + + return setup_args + + +#======================================================================================================================= +# main +#======================================================================================================================= +if __name__ == '__main__': + setup = process_args(sys.argv) + + port = setup['port'] + client_port = setup['client_port'] + file = setup['file'] + is_module = setup['module'] + + from _pydev_bundle import pydev_localhost + + if int(port) == 0 and int(client_port) == 0: + (h, p) = pydev_localhost.get_socket_name() + client_port = p + + host = pydev_localhost.get_localhost() + + # replace exit (see comments on method) + # note that this does not work in jython!!! (sys method can't be replaced). + sys.exit = skip_successful_exit + + connect_status_queue = _queue.Queue() + interpreter = InterpreterInterface(host, int(client_port), threading.current_thread(), connect_status_queue=connect_status_queue) + + server_thread = threading.Thread(target=start_console_server, + name='ServerThread', + args=(host, int(port), interpreter)) + server_thread.daemon = True + server_thread.start() + + sys.stdin = StdIn(interpreter, host, client_port, sys.stdin) + + init_mpl_in_console(interpreter) + + try: + success = connect_status_queue.get(True, 60) + if not success: + raise ValueError() + except: + sys.stderr.write("Console server didn't start\n") + sys.stderr.flush() + sys.exit(1) + + globals = run_file(file, None, None, is_module) + + interpreter.get_namespace().update(globals) + + interpreter.ShowConsole() + + process_exec_queue(interpreter) diff --git a/pydev_sitecustomize/__not_in_default_pythonpath.txt b/pydev_sitecustomize/__not_in_default_pythonpath.txt new file mode 100644 index 0000000..29cdc5b --- /dev/null +++ b/pydev_sitecustomize/__not_in_default_pythonpath.txt @@ -0,0 +1 @@ +(no __init__.py file) \ No newline at end of file diff --git a/pydev_sitecustomize/sitecustomize.py b/pydev_sitecustomize/sitecustomize.py new file mode 100644 index 0000000..8b51eba --- /dev/null +++ b/pydev_sitecustomize/sitecustomize.py @@ -0,0 +1,237 @@ +''' + This module will: + - change the input() and raw_input() commands to change \r\n or \r into \n + - execute the user site customize -- if available + - change raw_input() and input() to also remove any trailing \r + + Up to PyDev 3.4 it also was setting the default encoding, but it was removed because of differences when + running from a shell (i.e.: now we just set the PYTHONIOENCODING related to that -- which is properly + treated on Py 2.7 onwards). +''' +DEBUG = 0 #0 or 1 because of jython + +import sys +encoding = None + +IS_PYTHON_3_ONWARDS = 0 + +try: + IS_PYTHON_3_ONWARDS = sys.version_info[0] >= 3 +except: + #That's OK, not all versions of python have sys.version_info + if DEBUG: + import traceback;traceback.print_exc() #@Reimport + +#----------------------------------------------------------------------------------------------------------------------- +#Line buffering +if IS_PYTHON_3_ONWARDS: + #Python 3 has a bug (http://bugs.python.org/issue4705) in which -u doesn't properly make output/input unbuffered + #so, we need to enable that ourselves here. + try: + sys.stdout._line_buffering = True + except: + pass + try: + sys.stderr._line_buffering = True + except: + pass + try: + sys.stdin._line_buffering = True + except: + pass + + +try: + import org.python.core.PyDictionary #@UnresolvedImport @UnusedImport -- just to check if it could be valid + def dict_contains(d, key): + return d.has_key(key) +except: + try: + #Py3k does not have has_key anymore, and older versions don't have __contains__ + dict_contains = dict.__contains__ + except: + try: + dict_contains = dict.has_key + except NameError: + def dict_contains(d, key): + return d.has_key(key) + +def install_breakpointhook(): + def custom_sitecustomize_breakpointhook(*args, **kwargs): + import os + hookname = os.getenv('PYTHONBREAKPOINT') + if ( + hookname is not None + and len(hookname) > 0 + and hasattr(sys, '__breakpointhook__') + and sys.__breakpointhook__ != custom_sitecustomize_breakpointhook + ): + sys.__breakpointhook__(*args, **kwargs) + else: + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + import pydevd + kwargs.setdefault('stop_at_frame', sys._getframe().f_back) + pydevd.settrace(*args, **kwargs) + + if sys.version_info[0:2] >= (3, 7): + # There are some choices on how to provide the breakpoint hook. Namely, we can provide a + # PYTHONBREAKPOINT which provides the import path for a method to be executed or we + # can override sys.breakpointhook. + # pydevd overrides sys.breakpointhook instead of providing an environment variable because + # it's possible that the debugger starts the user program but is not available in the + # PYTHONPATH (and would thus fail to be imported if PYTHONBREAKPOINT was set to pydevd.settrace). + # Note that the implementation still takes PYTHONBREAKPOINT in account (so, if it was provided + # by someone else, it'd still work). + sys.breakpointhook = custom_sitecustomize_breakpointhook + else: + if sys.version_info[0] >= 3: + import builtins as __builtin__ # Py3 + else: + import __builtin__ + + # In older versions, breakpoint() isn't really available, so, install the hook directly + # in the builtins. + __builtin__.breakpoint = custom_sitecustomize_breakpointhook + sys.__breakpointhook__ = custom_sitecustomize_breakpointhook + +# Install the breakpoint hook at import time. +install_breakpointhook() + +#----------------------------------------------------------------------------------------------------------------------- +#now that we've finished the needed pydev sitecustomize, let's run the default one (if available) + +#Ok, some weirdness going on in Python 3k: when removing this module from the sys.module to import the 'real' +#sitecustomize, all the variables in this scope become None (as if it was garbage-collected), so, the the reference +#below is now being kept to create a cyclic reference so that it neven dies) +__pydev_sitecustomize_module__ = sys.modules.get('sitecustomize') #A ref to this module + + +#remove the pydev site customize (and the pythonpath for it) +paths_removed = [] +try: + for c in sys.path[:]: + #Pydev controls the whole classpath in Jython already, so, we don't want a a duplicate for + #what we've already added there (this is needed to support Jython 2.5b1 onwards -- otherwise, as + #we added the sitecustomize to the pythonpath and to the classpath, we'd have to remove it from the + #classpath too -- and I don't think there's a way to do that... or not?) + if c.find('pydev_sitecustomize') != -1 or c == '__classpath__' or c == '__pyclasspath__' or \ + c == '__classpath__/' or c == '__pyclasspath__/' or c == '__classpath__\\' or c == '__pyclasspath__\\': + sys.path.remove(c) + if c.find('pydev_sitecustomize') == -1: + #We'll re-add any paths removed but the pydev_sitecustomize we added from pydev. + paths_removed.append(c) + + if dict_contains(sys.modules, 'sitecustomize'): + del sys.modules['sitecustomize'] #this module +except: + #print the error... should never happen (so, always show, and not only on debug)! + import traceback;traceback.print_exc() #@Reimport +else: + #Now, execute the default sitecustomize + try: + import sitecustomize #@UnusedImport + sitecustomize.__pydev_sitecustomize_module__ = __pydev_sitecustomize_module__ + except: + pass + + if not dict_contains(sys.modules, 'sitecustomize'): + #If there was no sitecustomize, re-add the pydev sitecustomize (pypy gives a KeyError if it's not there) + sys.modules['sitecustomize'] = __pydev_sitecustomize_module__ + + try: + if paths_removed: + if sys is None: + import sys + if sys is not None: + #And after executing the default sitecustomize, restore the paths (if we didn't remove it before, + #the import sitecustomize would recurse). + sys.path.extend(paths_removed) + except: + #print the error... should never happen (so, always show, and not only on debug)! + import traceback;traceback.print_exc() #@Reimport + + + + +if sys.version_info[0] < 3: + try: + #Redefine input and raw_input only after the original sitecustomize was executed + #(because otherwise, the original raw_input and input would still not be defined) + import __builtin__ + original_raw_input = __builtin__.raw_input + original_input = __builtin__.input + + + def raw_input(prompt=''): + #the original raw_input would only remove a trailing \n, so, at + #this point if we had a \r\n the \r would remain (which is valid for eclipse) + #so, let's remove the remaining \r which python didn't expect. + ret = original_raw_input(prompt) + + if ret.endswith('\r'): + return ret[:-1] + + return ret + raw_input.__doc__ = original_raw_input.__doc__ + + def input(prompt=''): + #input must also be rebinded for using the new raw_input defined + return eval(raw_input(prompt)) + input.__doc__ = original_input.__doc__ + + + __builtin__.raw_input = raw_input + __builtin__.input = input + + except: + #Don't report errors at this stage + if DEBUG: + import traceback;traceback.print_exc() #@Reimport + +else: + try: + import builtins #Python 3.0 does not have the __builtin__ module @UnresolvedImport + original_input = builtins.input + def input(prompt=''): + #the original input would only remove a trailing \n, so, at + #this point if we had a \r\n the \r would remain (which is valid for eclipse) + #so, let's remove the remaining \r which python didn't expect. + ret = original_input(prompt) + + if ret.endswith('\r'): + return ret[:-1] + + return ret + input.__doc__ = original_input.__doc__ + builtins.input = input + except: + #Don't report errors at this stage + if DEBUG: + import traceback;traceback.print_exc() #@Reimport + + + +try: + #The original getpass doesn't work from the eclipse console, so, let's put a replacement + #here (note that it'll not go into echo mode in the console, so, what' the user writes + #will actually be seen) + #Note: same thing from the fix_getpass module -- but we don't want to import it in this + #custom sitecustomize. + def fix_get_pass(): + try: + import getpass + except ImportError: + return #If we can't import it, we can't fix it + import warnings + fallback = getattr(getpass, 'fallback_getpass', None) # >= 2.6 + if not fallback: + fallback = getpass.default_getpass # <= 2.5 + getpass.getpass = fallback + if hasattr(getpass, 'GetPassWarning'): + warnings.simplefilter("ignore", category=getpass.GetPassWarning) + fix_get_pass() + +except: + #Don't report errors at this stage + if DEBUG: + import traceback;traceback.print_exc() #@Reimport diff --git a/pydevconsole.py b/pydevconsole.py new file mode 100644 index 0000000..6b13788 --- /dev/null +++ b/pydevconsole.py @@ -0,0 +1,603 @@ +''' +Entry point module to start the interactive console. +''' +from _pydev_bundle._pydev_saved_modules import thread, _code +from _pydevd_bundle.pydevd_constants import IS_JYTHON +start_new_thread = thread.start_new_thread + +from _pydevd_bundle.pydevconsole_code import InteractiveConsole + +compile_command = _code.compile_command +InteractiveInterpreter = _code.InteractiveInterpreter + +import os +import sys + +from _pydev_bundle._pydev_saved_modules import threading +from _pydevd_bundle.pydevd_constants import INTERACTIVE_MODE_AVAILABLE + +import traceback +from _pydev_bundle import pydev_log + +from _pydevd_bundle import pydevd_save_locals + +from _pydev_bundle.pydev_imports import Exec, _queue + +import builtins as __builtin__ + +from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface, BaseStdIn # @UnusedImport +from _pydev_bundle.pydev_console_utils import CodeFragment + + +class Command: + + def __init__(self, interpreter, code_fragment): + """ + :type code_fragment: CodeFragment + :type interpreter: InteractiveConsole + """ + self.interpreter = interpreter + self.code_fragment = code_fragment + self.more = None + + def symbol_for_fragment(code_fragment): + if code_fragment.is_single_line: + symbol = 'single' + else: + if IS_JYTHON: + symbol = 'single' # Jython doesn't support exec + else: + symbol = 'exec' + return symbol + + symbol_for_fragment = staticmethod(symbol_for_fragment) + + def run(self): + text = self.code_fragment.text + symbol = self.symbol_for_fragment(self.code_fragment) + + self.more = self.interpreter.runsource(text, '', symbol) + + +try: + from _pydev_bundle.pydev_imports import execfile + + __builtin__.execfile = execfile +except: + pass + +# Pull in runfile, the interface to UMD that wraps execfile +from _pydev_bundle.pydev_umd import runfile, _set_globals_function +if sys.version_info[0] >= 3: + __builtin__.runfile = runfile +else: + __builtin__.runfile = runfile + + +#======================================================================================================================= +# InterpreterInterface +#======================================================================================================================= +class InterpreterInterface(BaseInterpreterInterface): + ''' + The methods in this class should be registered in the xml-rpc server. + ''' + + def __init__(self, host, client_port, mainThread, connect_status_queue=None): + BaseInterpreterInterface.__init__(self, mainThread, connect_status_queue) + self.client_port = client_port + self.host = host + self.namespace = {} + self.interpreter = InteractiveConsole(self.namespace) + self._input_error_printed = False + + def do_add_exec(self, codeFragment): + command = Command(self.interpreter, codeFragment) + command.run() + return command.more + + def get_namespace(self): + return self.namespace + + def getCompletions(self, text, act_tok): + try: + from _pydev_bundle._pydev_completer import Completer + + completer = Completer(self.namespace, None) + return completer.complete(act_tok) + except: + pydev_log.exception() + return [] + + def close(self): + sys.exit(0) + + def get_greeting_msg(self): + return 'PyDev console: starting.\n' + + +class _ProcessExecQueueHelper: + _debug_hook = None + _return_control_osc = False + + +def set_debug_hook(debug_hook): + _ProcessExecQueueHelper._debug_hook = debug_hook + + +def activate_mpl_if_already_imported(interpreter): + if interpreter.mpl_modules_for_patching: + for module in list(interpreter.mpl_modules_for_patching): + if module in sys.modules: + activate_function = interpreter.mpl_modules_for_patching.pop(module) + activate_function() + + +def init_set_return_control_back(interpreter): + from pydev_ipython.inputhook import set_return_control_callback + + def return_control(): + ''' A function that the inputhooks can call (via inputhook.stdin_ready()) to find + out if they should cede control and return ''' + if _ProcessExecQueueHelper._debug_hook: + # Some of the input hooks check return control without doing + # a single operation, so we don't return True on every + # call when the debug hook is in place to allow the GUI to run + # XXX: Eventually the inputhook code will have diverged enough + # from the IPython source that it will be worthwhile rewriting + # it rather than pretending to maintain the old API + _ProcessExecQueueHelper._return_control_osc = not _ProcessExecQueueHelper._return_control_osc + if _ProcessExecQueueHelper._return_control_osc: + return True + + if not interpreter.exec_queue.empty(): + return True + return False + + set_return_control_callback(return_control) + + +def init_mpl_in_console(interpreter): + init_set_return_control_back(interpreter) + + if not INTERACTIVE_MODE_AVAILABLE: + return + + activate_mpl_if_already_imported(interpreter) + from _pydev_bundle.pydev_import_hook import import_hook_manager + for mod in list(interpreter.mpl_modules_for_patching): + import_hook_manager.add_module_name(mod, interpreter.mpl_modules_for_patching.pop(mod)) + + +if sys.platform != 'win32': + + if not hasattr(os, 'kill'): # Jython may not have it. + + def pid_exists(pid): + return True + + else: + + def pid_exists(pid): + # Note that this function in the face of errors will conservatively consider that + # the pid is still running (because we'll exit the current process when it's + # no longer running, so, we need to be 100% sure it actually exited). + + import errno + if pid == 0: + # According to "man 2 kill" PID 0 has a special meaning: + # it refers to <> so we don't want to go any further. + # If we get here it means this UNIX platform *does* have + # a process with id 0. + return True + try: + os.kill(pid, 0) + except OSError as err: + if err.errno == errno.ESRCH: + # ESRCH == No such process + return False + elif err.errno == errno.EPERM: + # EPERM clearly means there's a process to deny access to + return True + else: + # According to "man 2 kill" possible error values are + # (EINVAL, EPERM, ESRCH) therefore we should never get + # here. If we do, although it's an error, consider it + # exists (see first comment in this function). + return True + else: + return True + +else: + + def pid_exists(pid): + # Note that this function in the face of errors will conservatively consider that + # the pid is still running (because we'll exit the current process when it's + # no longer running, so, we need to be 100% sure it actually exited). + import ctypes + kernel32 = ctypes.windll.kernel32 + + PROCESS_QUERY_INFORMATION = 0x0400 + PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 + ERROR_INVALID_PARAMETER = 0x57 + STILL_ACTIVE = 259 + + process = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, 0, pid) + if not process: + err = kernel32.GetLastError() + if err == ERROR_INVALID_PARAMETER: + # Means it doesn't exist (pid parameter is wrong). + return False + + # There was some unexpected error (such as access denied), so + # consider it exists (although it could be something else, but we don't want + # to raise any errors -- so, just consider it exists). + return True + + try: + zero = ctypes.c_int(0) + exit_code = ctypes.pointer(zero) + + exit_code_suceeded = kernel32.GetExitCodeProcess(process, exit_code) + if not exit_code_suceeded: + # There was some unexpected error (such as access denied), so + # consider it exists (although it could be something else, but we don't want + # to raise any errors -- so, just consider it exists). + return True + + elif bool(exit_code.contents.value) and int(exit_code.contents.value) != STILL_ACTIVE: + return False + finally: + kernel32.CloseHandle(process) + + return True + + +def process_exec_queue(interpreter): + init_mpl_in_console(interpreter) + from pydev_ipython.inputhook import get_inputhook + try: + kill_if_pid_not_alive = int(os.environ.get('PYDEV_ECLIPSE_PID', '-1')) + except: + kill_if_pid_not_alive = -1 + + while 1: + if kill_if_pid_not_alive != -1: + if not pid_exists(kill_if_pid_not_alive): + exit() + + # Running the request may have changed the inputhook in use + inputhook = get_inputhook() + + if _ProcessExecQueueHelper._debug_hook: + _ProcessExecQueueHelper._debug_hook() + + if inputhook: + try: + # Note: it'll block here until return_control returns True. + inputhook() + except: + pydev_log.exception() + try: + try: + code_fragment = interpreter.exec_queue.get(block=True, timeout=1 / 20.) # 20 calls/second + except _queue.Empty: + continue + + if callable(code_fragment): + # It can be a callable (i.e.: something that must run in the main + # thread can be put in the queue for later execution). + code_fragment() + else: + more = interpreter.add_exec(code_fragment) + except KeyboardInterrupt: + interpreter.buffer = None + continue + except SystemExit: + raise + except: + pydev_log.exception('Error processing queue on pydevconsole.') + exit() + + +if 'IPYTHONENABLE' in os.environ: + IPYTHON = os.environ['IPYTHONENABLE'] == 'True' +else: + # By default, don't use IPython because occasionally changes + # in IPython break pydevd. + IPYTHON = False + +try: + try: + exitfunc = sys.exitfunc + except AttributeError: + exitfunc = None + + if IPYTHON: + from _pydev_bundle.pydev_ipython_console import InterpreterInterface + if exitfunc is not None: + sys.exitfunc = exitfunc + else: + try: + delattr(sys, 'exitfunc') + except: + pass +except: + IPYTHON = False + pass + + +#======================================================================================================================= +# _DoExit +#======================================================================================================================= +def do_exit(*args): + ''' + We have to override the exit because calling sys.exit will only actually exit the main thread, + and as we're in a Xml-rpc server, that won't work. + ''' + + try: + import java.lang.System + + java.lang.System.exit(1) + except ImportError: + if len(args) == 1: + os._exit(args[0]) + else: + os._exit(0) + + +#======================================================================================================================= +# start_console_server +#======================================================================================================================= +def start_console_server(host, port, interpreter): + try: + if port == 0: + host = '' + + # I.e.: supporting the internal Jython version in PyDev to create a Jython interactive console inside Eclipse. + from _pydev_bundle.pydev_imports import SimpleXMLRPCServer as XMLRPCServer # @Reimport + + try: + server = XMLRPCServer((host, port), logRequests=False, allow_none=True) + + except: + sys.stderr.write('Error starting server with host: "%s", port: "%s", client_port: "%s"\n' % (host, port, interpreter.client_port)) + sys.stderr.flush() + raise + + # Tell UMD the proper default namespace + _set_globals_function(interpreter.get_namespace) + + server.register_function(interpreter.execLine) + server.register_function(interpreter.execMultipleLines) + server.register_function(interpreter.getCompletions) + server.register_function(interpreter.getFrame) + server.register_function(interpreter.getVariable) + server.register_function(interpreter.changeVariable) + server.register_function(interpreter.getDescription) + server.register_function(interpreter.close) + server.register_function(interpreter.interrupt) + server.register_function(interpreter.handshake) + server.register_function(interpreter.connectToDebugger) + server.register_function(interpreter.hello) + server.register_function(interpreter.getArray) + server.register_function(interpreter.evaluate) + server.register_function(interpreter.ShowConsole) + server.register_function(interpreter.loadFullValue) + + # Functions for GUI main loop integration + server.register_function(interpreter.enableGui) + + if port == 0: + (h, port) = server.socket.getsockname() + + print(port) + print(interpreter.client_port) + + while True: + try: + server.serve_forever() + except: + # Ugly code to be py2/3 compatible + # https://sw-brainwy.rhcloud.com/tracker/PyDev/534: + # Unhandled "interrupted system call" error in the pydevconsol.py + e = sys.exc_info()[1] + retry = False + try: + retry = e.args[0] == 4 # errno.EINTR + except: + pass + if not retry: + raise + # Otherwise, keep on going + return server + except: + pydev_log.exception() + # Notify about error to avoid long waiting + connection_queue = interpreter.get_connect_status_queue() + if connection_queue is not None: + connection_queue.put(False) + + +def start_server(host, port, client_port): + # replace exit (see comments on method) + # note that this does not work in jython!!! (sys method can't be replaced). + sys.exit = do_exit + + interpreter = InterpreterInterface(host, client_port, threading.current_thread()) + + start_new_thread(start_console_server, (host, port, interpreter)) + + process_exec_queue(interpreter) + + +def get_ipython_hidden_vars(): + if IPYTHON and hasattr(__builtin__, 'interpreter'): + interpreter = get_interpreter() + return interpreter.get_ipython_hidden_vars_dict() + + +def get_interpreter(): + try: + interpreterInterface = getattr(__builtin__, 'interpreter') + except AttributeError: + interpreterInterface = InterpreterInterface(None, None, threading.current_thread()) + __builtin__.interpreter = interpreterInterface + sys.stderr.write(interpreterInterface.get_greeting_msg()) + sys.stderr.flush() + + return interpreterInterface + + +def get_completions(text, token, globals, locals): + interpreterInterface = get_interpreter() + + interpreterInterface.interpreter.update(globals, locals) + + return interpreterInterface.getCompletions(text, token) + +#=============================================================================== +# Debugger integration +#=============================================================================== + + +def exec_code(code, globals, locals, debugger): + interpreterInterface = get_interpreter() + interpreterInterface.interpreter.update(globals, locals) + + res = interpreterInterface.need_more(code) + + if res: + return True + + interpreterInterface.add_exec(code, debugger) + + return False + + +class ConsoleWriter(InteractiveInterpreter): + skip = 0 + + def __init__(self, locals=None): + InteractiveInterpreter.__init__(self, locals) + + def write(self, data): + # if (data.find("global_vars") == -1 and data.find("pydevd") == -1): + if self.skip > 0: + self.skip -= 1 + else: + if data == "Traceback (most recent call last):\n": + self.skip = 1 + sys.stderr.write(data) + + def showsyntaxerror(self, filename=None): + """Display the syntax error that just occurred.""" + # Override for avoid using sys.excepthook PY-12600 + type, value, tb = sys.exc_info() + sys.last_type = type + sys.last_value = value + sys.last_traceback = tb + if filename and type is SyntaxError: + # Work hard to stuff the correct filename in the exception + try: + msg, (dummy_filename, lineno, offset, line) = value.args + except ValueError: + # Not the format we expect; leave it alone + pass + else: + # Stuff in the right filename + value = SyntaxError(msg, (filename, lineno, offset, line)) + sys.last_value = value + list = traceback.format_exception_only(type, value) + sys.stderr.write(''.join(list)) + + def showtraceback(self, *args, **kwargs): + """Display the exception that just occurred.""" + # Override for avoid using sys.excepthook PY-12600 + try: + type, value, tb = sys.exc_info() + sys.last_type = type + sys.last_value = value + sys.last_traceback = tb + tblist = traceback.extract_tb(tb) + del tblist[:1] + lines = traceback.format_list(tblist) + if lines: + lines.insert(0, "Traceback (most recent call last):\n") + lines.extend(traceback.format_exception_only(type, value)) + finally: + tblist = tb = None + sys.stderr.write(''.join(lines)) + + +def console_exec(thread_id, frame_id, expression, dbg): + """returns 'False' in case expression is partially correct + """ + frame = dbg.find_frame(thread_id, frame_id) + + is_multiline = expression.count('@LINE@') > 1 + expression = str(expression.replace('@LINE@', '\n')) + + # Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329 + # (Names not resolved in generator expression in method) + # See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html + updated_globals = {} + updated_globals.update(frame.f_globals) + updated_globals.update(frame.f_locals) # locals later because it has precedence over the actual globals + + if IPYTHON: + need_more = exec_code(CodeFragment(expression), updated_globals, frame.f_locals, dbg) + if not need_more: + pydevd_save_locals.save_locals(frame) + return need_more + + interpreter = ConsoleWriter() + + if not is_multiline: + try: + code = compile_command(expression) + except (OverflowError, SyntaxError, ValueError): + # Case 1 + interpreter.showsyntaxerror() + return False + if code is None: + # Case 2 + return True + else: + code = expression + + # Case 3 + + try: + Exec(code, updated_globals, frame.f_locals) + + except SystemExit: + raise + except: + interpreter.showtraceback() + else: + pydevd_save_locals.save_locals(frame) + return False + + +#======================================================================================================================= +# main +#======================================================================================================================= +if __name__ == '__main__': + # Important: don't use this module directly as the __main__ module, rather, import itself as pydevconsole + # so that we don't get multiple pydevconsole modules if it's executed directly (otherwise we'd have multiple + # representations of its classes). + # See: https://sw-brainwy.rhcloud.com/tracker/PyDev/446: + # 'Variables' and 'Expressions' views stopped working when debugging interactive console + import pydevconsole + sys.stdin = pydevconsole.BaseStdIn(sys.stdin) + port, client_port = sys.argv[1:3] + from _pydev_bundle import pydev_localhost + + if int(port) == 0 and int(client_port) == 0: + (h, p) = pydev_localhost.get_socket_name() + + client_port = p + + pydevconsole.start_server(pydev_localhost.get_localhost(), int(port), int(client_port)) diff --git a/pydevd.py b/pydevd.py new file mode 100644 index 0000000..6452031 --- /dev/null +++ b/pydevd.py @@ -0,0 +1,3461 @@ +''' +Entry point module (keep at root): + +This module starts the debugger. +''' +import sys # @NoMove +if sys.version_info[:2] < (3, 6): + raise RuntimeError('The PyDev.Debugger requires Python 3.6 onwards to be run. If you need to use an older Python version, use an older version of the debugger.') +import os + +try: + # Just empty packages to check if they're in the PYTHONPATH. + import _pydev_bundle +except ImportError: + # On the first import of a pydevd module, add pydevd itself to the PYTHONPATH + # if its dependencies cannot be imported. + sys.path.append(os.path.dirname(os.path.abspath(__file__))) + import _pydev_bundle + +# Import this first as it'll check for shadowed modules and will make sure that we import +# things as needed for gevent. +from _pydevd_bundle import pydevd_constants + +import atexit +import dis +import io +from collections import defaultdict +from contextlib import contextmanager +from functools import partial +import itertools +import traceback +import weakref +import getpass as getpass_mod +import functools + +import pydevd_file_utils +from _pydev_bundle import pydev_imports, pydev_log +from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding +from _pydev_bundle.pydev_is_thread_alive import is_thread_alive +from _pydev_bundle.pydev_override import overrides +from _pydev_bundle._pydev_saved_modules import threading, time, thread +from _pydevd_bundle import pydevd_extension_utils, pydevd_frame_utils +from _pydevd_bundle.pydevd_filtering import FilesFiltering, glob_matches_path +from _pydevd_bundle import pydevd_io, pydevd_vm_type +from _pydevd_bundle import pydevd_utils +from _pydevd_bundle import pydevd_runpy +from _pydev_bundle.pydev_console_utils import DebugConsoleStdIn +from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info +from _pydevd_bundle.pydevd_breakpoints import ExceptionBreakpoint, get_exception_breakpoint +from _pydevd_bundle.pydevd_comm_constants import (CMD_THREAD_SUSPEND, CMD_STEP_INTO, CMD_SET_BREAK, + CMD_STEP_INTO_MY_CODE, CMD_STEP_OVER, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, + CMD_SET_NEXT_STATEMENT, CMD_STEP_RETURN, CMD_ADD_EXCEPTION_BREAK, CMD_STEP_RETURN_MY_CODE, + CMD_STEP_OVER_MY_CODE, constant_to_str, CMD_STEP_INTO_COROUTINE) +from _pydevd_bundle.pydevd_constants import (get_thread_id, get_current_thread_id, + DebugInfoHolder, PYTHON_SUSPEND, STATE_SUSPEND, STATE_RUN, get_frame, + clear_cached_thread_id, INTERACTIVE_MODE_AVAILABLE, SHOW_DEBUG_INFO_ENV, NULL, + NO_FTRACE, IS_IRONPYTHON, JSON_PROTOCOL, IS_CPYTHON, HTTP_JSON_PROTOCOL, USE_CUSTOM_SYS_CURRENT_FRAMES_MAP, call_only_once, + ForkSafeLock, IGNORE_BASENAMES_STARTING_WITH, EXCEPTION_TYPE_UNHANDLED, SUPPORT_GEVENT, + PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING, PYDEVD_IPYTHON_CONTEXT) +from _pydevd_bundle.pydevd_defaults import PydevdCustomization # Note: import alias used on pydev_monkey. +from _pydevd_bundle.pydevd_custom_frames import CustomFramesContainer, custom_frames_container_init +from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE, PYDEV_FILE, LIB_FILE, DONT_TRACE_DIRS +from _pydevd_bundle.pydevd_extension_api import DebuggerEventHandler +from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, remove_exception_from_frame +from _pydevd_bundle.pydevd_net_command_factory_xml import NetCommandFactory +from _pydevd_bundle.pydevd_trace_dispatch import ( + trace_dispatch as _trace_dispatch, global_cache_skips, global_cache_frame_skips, fix_top_level_trace_and_get_trace_func, USING_CYTHON) +from _pydevd_bundle.pydevd_utils import save_main_module, is_current_thread_main_thread, \ + import_attr_from_module +from _pydevd_frame_eval.pydevd_frame_eval_main import ( + frame_eval_func, dummy_trace_dispatch, USING_FRAME_EVAL) +import pydev_ipython # @UnusedImport +from _pydevd_bundle.pydevd_source_mapping import SourceMapping +from _pydevd_bundle.pydevd_concurrency_analyser.pydevd_concurrency_logger import ThreadingLogger, AsyncioLogger, send_concurrency_message, cur_time +from _pydevd_bundle.pydevd_concurrency_analyser.pydevd_thread_wrappers import wrap_threads +from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER +from pydevd_file_utils import get_fullname, get_package_dir +from os.path import abspath as os_path_abspath +import pydevd_tracing +from _pydevd_bundle.pydevd_comm import (InternalThreadCommand, InternalThreadCommandForAnyThread, + create_server_socket, FSNotifyThread) +from _pydevd_bundle.pydevd_comm import(InternalConsoleExec, + _queue, ReaderThread, GetGlobalDebugger, get_global_debugger, + set_global_debugger, WriterThread, + start_client, start_server, InternalGetBreakpointException, InternalSendCurrExceptionTrace, + InternalSendCurrExceptionTraceProceeded) +from _pydevd_bundle.pydevd_daemon_thread import PyDBDaemonThread, mark_as_pydevd_daemon_thread +from _pydevd_bundle.pydevd_process_net_command_json import PyDevJsonCommandProcessor +from _pydevd_bundle.pydevd_process_net_command import process_net_command +from _pydevd_bundle.pydevd_net_command import NetCommand, NULL_NET_COMMAND + +from _pydevd_bundle.pydevd_breakpoints import stop_on_unhandled_exception +from _pydevd_bundle.pydevd_collect_bytecode_info import collect_try_except_info, collect_return_info, collect_try_except_info_from_source +from _pydevd_bundle.pydevd_suspended_frames import SuspendedFramesManager +from socket import SHUT_RDWR +from _pydevd_bundle.pydevd_api import PyDevdAPI +from _pydevd_bundle.pydevd_timeout import TimeoutTracker +from _pydevd_bundle.pydevd_thread_lifecycle import suspend_all_threads, mark_thread_suspended + +pydevd_gevent_integration = None + +if SUPPORT_GEVENT: + try: + from _pydevd_bundle import pydevd_gevent_integration + except: + pydev_log.exception( + 'pydevd: GEVENT_SUPPORT is set but gevent is not available in the environment.\n' + 'Please unset GEVENT_SUPPORT from the environment variables or install gevent.') + else: + pydevd_gevent_integration.log_gevent_debug_info() + +if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP: + from _pydevd_bundle.pydevd_constants import constructed_tid_to_last_frame + +__version_info__ = (2, 8, 0) +__version_info_str__ = [] +for v in __version_info__: + __version_info_str__.append(str(v)) + +__version__ = '.'.join(__version_info_str__) + +# IMPORTANT: pydevd_constants must be the 1st thing defined because it'll keep a reference to the original sys._getframe + + +def install_breakpointhook(pydevd_breakpointhook=None): + if pydevd_breakpointhook is None: + + def pydevd_breakpointhook(*args, **kwargs): + hookname = os.getenv('PYTHONBREAKPOINT') + if ( + hookname is not None + and len(hookname) > 0 + and hasattr(sys, '__breakpointhook__') + and sys.__breakpointhook__ != pydevd_breakpointhook + ): + sys.__breakpointhook__(*args, **kwargs) + else: + settrace(*args, **kwargs) + + if sys.version_info[0:2] >= (3, 7): + # There are some choices on how to provide the breakpoint hook. Namely, we can provide a + # PYTHONBREAKPOINT which provides the import path for a method to be executed or we + # can override sys.breakpointhook. + # pydevd overrides sys.breakpointhook instead of providing an environment variable because + # it's possible that the debugger starts the user program but is not available in the + # PYTHONPATH (and would thus fail to be imported if PYTHONBREAKPOINT was set to pydevd.settrace). + # Note that the implementation still takes PYTHONBREAKPOINT in account (so, if it was provided + # by someone else, it'd still work). + sys.breakpointhook = pydevd_breakpointhook + else: + if sys.version_info[0] >= 3: + import builtins as __builtin__ # Py3 noqa + else: + import __builtin__ # noqa + + # In older versions, breakpoint() isn't really available, so, install the hook directly + # in the builtins. + __builtin__.breakpoint = pydevd_breakpointhook + sys.__breakpointhook__ = pydevd_breakpointhook + + +# Install the breakpoint hook at import time. +install_breakpointhook() + +from _pydevd_bundle.pydevd_plugin_utils import PluginManager + +threadingEnumerate = threading.enumerate +threadingCurrentThread = threading.current_thread + +try: + 'dummy'.encode('utf-8') # Added because otherwise Jython 2.2.1 wasn't finding the encoding (if it wasn't loaded in the main thread). +except: + pass + +_global_redirect_stdout_to_server = False +_global_redirect_stderr_to_server = False + +file_system_encoding = getfilesystemencoding() + +_CACHE_FILE_TYPE = {} + +pydev_log.debug('Using GEVENT_SUPPORT: %s', pydevd_constants.SUPPORT_GEVENT) +pydev_log.debug('Using GEVENT_SHOW_PAUSED_GREENLETS: %s', pydevd_constants.GEVENT_SHOW_PAUSED_GREENLETS) +pydev_log.debug('pydevd __file__: %s', os.path.abspath(__file__)) +pydev_log.debug('Using PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING: %s', pydevd_constants.PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING) +if pydevd_constants.PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING: + pydev_log.debug('PYDEVD_IPYTHON_CONTEXT: %s', pydevd_constants.PYDEVD_IPYTHON_CONTEXT) + + +#======================================================================================================================= +# PyDBCommandThread +#======================================================================================================================= +class PyDBCommandThread(PyDBDaemonThread): + + def __init__(self, py_db): + PyDBDaemonThread.__init__(self, py_db) + self._py_db_command_thread_event = py_db._py_db_command_thread_event + self.name = 'pydevd.CommandThread' + + @overrides(PyDBDaemonThread._on_run) + def _on_run(self): + # Delay a bit this initialization to wait for the main program to start. + self._py_db_command_thread_event.wait(0.3) + + if self._kill_received: + return + + try: + while not self._kill_received: + try: + self.py_db.process_internal_commands() + except: + pydev_log.info('Finishing debug communication...(2)') + self._py_db_command_thread_event.clear() + self._py_db_command_thread_event.wait(0.3) + except: + try: + pydev_log.debug(sys.exc_info()[0]) + except: + # In interpreter shutdown many things can go wrong (any module variables may + # be None, streams can be closed, etc). + pass + + # only got this error in interpreter shutdown + # pydev_log.info('Finishing debug communication...(3)') + + @overrides(PyDBDaemonThread.do_kill_pydev_thread) + def do_kill_pydev_thread(self): + PyDBDaemonThread.do_kill_pydev_thread(self) + # Set flag so that it can exit before the usual timeout. + self._py_db_command_thread_event.set() + + +#======================================================================================================================= +# CheckAliveThread +# Non-daemon thread: guarantees that all data is written even if program is finished +#======================================================================================================================= +class CheckAliveThread(PyDBDaemonThread): + + def __init__(self, py_db): + PyDBDaemonThread.__init__(self, py_db) + self.name = 'pydevd.CheckAliveThread' + self.daemon = False + self._wait_event = threading.Event() + + @overrides(PyDBDaemonThread._on_run) + def _on_run(self): + py_db = self.py_db + + def can_exit(): + with py_db._main_lock: + # Note: it's important to get the lock besides checking that it's empty (this + # means that we're not in the middle of some command processing). + writer = py_db.writer + writer_empty = writer is not None and writer.empty() + + return not py_db.has_user_threads_alive() and writer_empty + + try: + while not self._kill_received: + self._wait_event.wait(0.3) + if can_exit(): + break + + py_db.check_output_redirect() + + if can_exit(): + pydev_log.debug("No threads alive, finishing debug session") + py_db.dispose_and_kill_all_pydevd_threads() + except: + pydev_log.exception() + + def join(self, timeout=None): + # If someone tries to join this thread, mark it to be killed. + # This is the case for CherryPy when auto-reload is turned on. + self.do_kill_pydev_thread() + PyDBDaemonThread.join(self, timeout=timeout) + + @overrides(PyDBDaemonThread.do_kill_pydev_thread) + def do_kill_pydev_thread(self): + PyDBDaemonThread.do_kill_pydev_thread(self) + # Set flag so that it can exit before the usual timeout. + self._wait_event.set() + + +class AbstractSingleNotificationBehavior(object): + ''' + The basic usage should be: + + # Increment the request time for the suspend. + single_notification_behavior.increment_suspend_time() + + # Notify that this is a pause request (when a pause, not a breakpoint). + single_notification_behavior.on_pause() + + # Mark threads to be suspended. + set_suspend(...) + + # On do_wait_suspend, use notify_thread_suspended: + def do_wait_suspend(...): + with single_notification_behavior.notify_thread_suspended(thread_id): + ... + ''' + + __slots__ = [ + '_last_resume_notification_time', + '_last_suspend_notification_time', + '_lock', + '_next_request_time', + '_suspend_time_request', + '_suspended_thread_ids', + '_pause_requested', + '_py_db', + ] + + NOTIFY_OF_PAUSE_TIMEOUT = .5 + + def __init__(self, py_db): + self._py_db = weakref.ref(py_db) + self._next_request_time = partial(next, itertools.count()) + self._last_suspend_notification_time = -1 + self._last_resume_notification_time = -1 + self._suspend_time_request = self._next_request_time() + self._lock = thread.allocate_lock() + self._suspended_thread_ids = set() + self._pause_requested = False + + def send_suspend_notification(self, thread_id, stop_reason): + raise AssertionError('abstract: subclasses must override.') + + def send_resume_notification(self, thread_id): + raise AssertionError('abstract: subclasses must override.') + + def increment_suspend_time(self): + with self._lock: + self._suspend_time_request = self._next_request_time() + + def on_pause(self): + # Upon a pause, we should force sending new suspend notifications + # if no notification is sent after some time and there's some thread already stopped. + with self._lock: + self._pause_requested = True + global_suspend_time = self._suspend_time_request + py_db = self._py_db() + if py_db is not None: + py_db.timeout_tracker.call_on_timeout( + self.NOTIFY_OF_PAUSE_TIMEOUT, + self._notify_after_timeout, + kwargs={'global_suspend_time': global_suspend_time} + ) + + def _notify_after_timeout(self, global_suspend_time): + with self._lock: + if self._suspended_thread_ids: + if global_suspend_time > self._last_suspend_notification_time: + self._last_suspend_notification_time = global_suspend_time + # Notify about any thread which is currently suspended. + pydev_log.info('Sending suspend notification after timeout.') + self.send_suspend_notification(next(iter(self._suspended_thread_ids)), CMD_THREAD_SUSPEND) + + def on_thread_suspend(self, thread_id, stop_reason): + with self._lock: + pause_requested = self._pause_requested + if pause_requested: + # When a suspend notification is sent, reset the pause flag. + self._pause_requested = False + + self._suspended_thread_ids.add(thread_id) + + # CMD_THREAD_SUSPEND should always be a side-effect of a break, so, only + # issue for a CMD_THREAD_SUSPEND if a pause is pending. + if stop_reason != CMD_THREAD_SUSPEND or pause_requested: + if self._suspend_time_request > self._last_suspend_notification_time: + pydev_log.info('Sending suspend notification.') + self._last_suspend_notification_time = self._suspend_time_request + self.send_suspend_notification(thread_id, stop_reason) + else: + pydev_log.info( + 'Suspend not sent (it was already sent). Last suspend % <= Last resume %s', + self._last_suspend_notification_time, + self._last_resume_notification_time, + ) + else: + pydev_log.info( + 'Suspend not sent because stop reason is thread suspend and pause was not requested.', + ) + + def on_thread_resume(self, thread_id): + # on resume (step, continue all): + with self._lock: + self._suspended_thread_ids.remove(thread_id) + if self._last_resume_notification_time < self._last_suspend_notification_time: + pydev_log.info('Sending resume notification.') + self._last_resume_notification_time = self._last_suspend_notification_time + self.send_resume_notification(thread_id) + else: + pydev_log.info( + 'Resume not sent (it was already sent). Last resume %s >= Last suspend %s', + self._last_resume_notification_time, + self._last_suspend_notification_time, + ) + + @contextmanager + def notify_thread_suspended(self, thread_id, stop_reason): + self.on_thread_suspend(thread_id, stop_reason) + try: + yield # At this point the thread must be actually suspended. + finally: + self.on_thread_resume(thread_id) + + +class ThreadsSuspendedSingleNotification(AbstractSingleNotificationBehavior): + + __slots__ = AbstractSingleNotificationBehavior.__slots__ + [ + 'multi_threads_single_notification', '_callbacks', '_callbacks_lock'] + + def __init__(self, py_db): + AbstractSingleNotificationBehavior.__init__(self, py_db) + # If True, pydevd will send a single notification when all threads are suspended/resumed. + self.multi_threads_single_notification = False + self._callbacks_lock = threading.Lock() + self._callbacks = [] + + def add_on_resumed_callback(self, callback): + with self._callbacks_lock: + self._callbacks.append(callback) + + @overrides(AbstractSingleNotificationBehavior.send_resume_notification) + def send_resume_notification(self, thread_id): + py_db = self._py_db() + if py_db is not None: + py_db.writer.add_command(py_db.cmd_factory.make_thread_resume_single_notification(thread_id)) + + with self._callbacks_lock: + callbacks = self._callbacks + self._callbacks = [] + + for callback in callbacks: + callback() + + @overrides(AbstractSingleNotificationBehavior.send_suspend_notification) + def send_suspend_notification(self, thread_id, stop_reason): + py_db = self._py_db() + if py_db is not None: + py_db.writer.add_command(py_db.cmd_factory.make_thread_suspend_single_notification(py_db, thread_id, stop_reason)) + + @overrides(AbstractSingleNotificationBehavior.notify_thread_suspended) + @contextmanager + def notify_thread_suspended(self, thread_id, stop_reason): + if self.multi_threads_single_notification: + with AbstractSingleNotificationBehavior.notify_thread_suspended(self, thread_id, stop_reason): + yield + else: + yield + + +class _Authentication(object): + + __slots__ = ['access_token', 'client_access_token', '_authenticated', '_wrong_attempts'] + + def __init__(self): + # A token to be send in the command line or through the settrace api -- when such token + # is given, the first message sent to the IDE must pass the same token to authenticate. + # Note that if a disconnect is sent, the same message must be resent to authenticate. + self.access_token = None + + # This token is the one that the client requires to accept a connection from pydevd + # (it's stored here and just passed back when required, it's not used internally + # for anything else). + self.client_access_token = None + + self._authenticated = None + + self._wrong_attempts = 0 + + def is_authenticated(self): + if self._authenticated is None: + return self.access_token is None + return self._authenticated + + def login(self, access_token): + if self._wrong_attempts >= 10: # A user can fail to authenticate at most 10 times. + return + + self._authenticated = access_token == self.access_token + if not self._authenticated: + self._wrong_attempts += 1 + else: + self._wrong_attempts = 0 + + def logout(self): + self._authenticated = None + self._wrong_attempts = 0 + + +class PyDB(object): + """ Main debugging class + Lots of stuff going on here: + + PyDB starts two threads on startup that connect to remote debugger (RDB) + The threads continuously read & write commands to RDB. + PyDB communicates with these threads through command queues. + Every RDB command is processed by calling process_net_command. + Every PyDB net command is sent to the net by posting NetCommand to WriterThread queue + + Some commands need to be executed on the right thread (suspend/resume & friends) + These are placed on the internal command queue. + """ + + # Direct child pids which should not be terminated when terminating processes. + # Note: class instance because it should outlive PyDB instances. + dont_terminate_child_pids = set() + + def __init__(self, set_as_global=True): + if set_as_global: + pydevd_tracing.replace_sys_set_trace_func() + + self.authentication = _Authentication() + + self.reader = None + self.writer = None + self._fsnotify_thread = None + self.created_pydb_daemon_threads = {} + self._waiting_for_connection_thread = None + self._on_configuration_done_event = threading.Event() + self.check_alive_thread = None + self.py_db_command_thread = None + self.quitting = None + self.cmd_factory = NetCommandFactory() + self._cmd_queue = defaultdict(_queue.Queue) # Key is thread id or '*', value is Queue + self.suspended_frames_manager = SuspendedFramesManager() + self._files_filtering = FilesFiltering() + self.timeout_tracker = TimeoutTracker(self) + + # Note: when the source mapping is changed we also have to clear the file types cache + # (because if a given file is a part of the project or not may depend on it being + # defined in the source mapping). + self.source_mapping = SourceMapping(on_source_mapping_changed=self._clear_filters_caches) + + # Determines whether we should terminate child processes when asked to terminate. + self.terminate_child_processes = True + + # These are the breakpoints received by the PyDevdAPI. They are meant to store + # the breakpoints in the api -- its actual contents are managed by the api. + self.api_received_breakpoints = {} + + # These are the breakpoints meant to be consumed during runtime. + self.breakpoints = {} + self.function_breakpoint_name_to_breakpoint = {} + + # Set communication protocol + PyDevdAPI().set_protocol(self, 0, PydevdCustomization.DEFAULT_PROTOCOL) + + self.variable_presentation = PyDevdAPI.VariablePresentation() + + # mtime to be raised when breakpoints change + self.mtime = 0 + + self.file_to_id_to_line_breakpoint = {} + self.file_to_id_to_plugin_breakpoint = {} + + # Note: breakpoints dict should not be mutated: a copy should be created + # and later it should be assigned back (to prevent concurrency issues). + self.break_on_uncaught_exceptions = {} + self.break_on_caught_exceptions = {} + self.break_on_user_uncaught_exceptions = {} + + self.ready_to_run = False + self._main_lock = thread.allocate_lock() + self._lock_running_thread_ids = thread.allocate_lock() + self._lock_create_fs_notify = thread.allocate_lock() + self._py_db_command_thread_event = threading.Event() + if set_as_global: + CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event + + self.pydb_disposed = False + self._wait_for_threads_to_finish_called = False + self._wait_for_threads_to_finish_called_lock = thread.allocate_lock() + self._wait_for_threads_to_finish_called_event = threading.Event() + + self.terminate_requested = False + self._disposed_lock = thread.allocate_lock() + self.signature_factory = None + self.SetTrace = pydevd_tracing.SetTrace + self.skip_on_exceptions_thrown_in_same_context = False + self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True + + # Suspend debugger even if breakpoint condition raises an exception. + # May be changed with CMD_PYDEVD_JSON_CONFIG. + self.skip_suspend_on_breakpoint_exception = () # By default suspend on any Exception. + self.skip_print_breakpoint_exception = () # By default print on any Exception. + + # By default user can step into properties getter/setter/deleter methods + self.disable_property_trace = False + self.disable_property_getter_trace = False + self.disable_property_setter_trace = False + self.disable_property_deleter_trace = False + + # this is a dict of thread ids pointing to thread ids. Whenever a command is passed to the java end that + # acknowledges that a thread was created, the thread id should be passed here -- and if at some time we do not + # find that thread alive anymore, we must remove it from this list and make the java side know that the thread + # was killed. + self._running_thread_ids = {} + # Note: also access '_enable_thread_notifications' with '_lock_running_thread_ids' + self._enable_thread_notifications = False + + self._set_breakpoints_with_id = False + + # This attribute holds the file-> lines which have an @IgnoreException. + self.filename_to_lines_where_exceptions_are_ignored = {} + + # working with plugins (lazily initialized) + self.plugin = None + self.has_plugin_line_breaks = False + self.has_plugin_exception_breaks = False + self.thread_analyser = None + self.asyncio_analyser = None + + # The GUI event loop that's going to run. + # Possible values: + # matplotlib - Whatever GUI backend matplotlib is using. + # 'wx'/'qt'/'none'/... - GUI toolkits that have bulitin support. See pydevd_ipython/inputhook.py:24. + # Other - A custom function that'll be imported and run. + self._gui_event_loop = 'matplotlib' + self._installed_gui_support = False + self.gui_in_use = False + + # GUI event loop support in debugger + self.activate_gui_function = None + + # matplotlib support in debugger and debug console + self.mpl_hooks_in_debug_console = False + self.mpl_modules_for_patching = {} + + self._filename_to_not_in_scope = {} + self.first_breakpoint_reached = False + self._exclude_filters_enabled = self._files_filtering.use_exclude_filters() + self._is_libraries_filter_enabled = self._files_filtering.use_libraries_filter() + self.is_files_filter_enabled = self._exclude_filters_enabled or self._is_libraries_filter_enabled + self.show_return_values = False + self.remove_return_values_flag = False + self.redirect_output = False + # Note that besides the `redirect_output` flag, we also need to consider that someone + # else is already redirecting (i.e.: debugpy). + self.is_output_redirected = False + + # this flag disables frame evaluation even if it's available + self.use_frame_eval = True + + # If True, pydevd will send a single notification when all threads are suspended/resumed. + self._threads_suspended_single_notification = ThreadsSuspendedSingleNotification(self) + + # If True a step command will do a step in one thread and will also resume all other threads. + self.stepping_resumes_all_threads = False + + self._local_thread_trace_func = threading.local() + + self._server_socket_ready_event = threading.Event() + self._server_socket_name = None + + # Bind many locals to the debugger because upon teardown those names may become None + # in the namespace (and thus can't be relied upon unless the reference was previously + # saved). + if IS_IRONPYTHON: + + # A partial() cannot be used in IronPython for sys.settrace. + def new_trace_dispatch(frame, event, arg): + return _trace_dispatch(self, frame, event, arg) + + self.trace_dispatch = new_trace_dispatch + else: + self.trace_dispatch = partial(_trace_dispatch, self) + self.fix_top_level_trace_and_get_trace_func = fix_top_level_trace_and_get_trace_func + self.frame_eval_func = frame_eval_func + self.dummy_trace_dispatch = dummy_trace_dispatch + + # Note: this is different from pydevd_constants.thread_get_ident because we want Jython + # to be None here because it also doesn't have threading._active. + try: + self.threading_get_ident = threading.get_ident # Python 3 + self.threading_active = threading._active + except: + try: + self.threading_get_ident = threading._get_ident # Python 2 noqa + self.threading_active = threading._active + except: + self.threading_get_ident = None # Jython + self.threading_active = None + self.threading_current_thread = threading.currentThread + self.set_additional_thread_info = set_additional_thread_info + self.stop_on_unhandled_exception = stop_on_unhandled_exception + self.collect_return_info = collect_return_info + self.get_exception_breakpoint = get_exception_breakpoint + self._dont_trace_get_file_type = DONT_TRACE.get + self._dont_trace_dirs_get_file_type = DONT_TRACE_DIRS.get + self.PYDEV_FILE = PYDEV_FILE + self.LIB_FILE = LIB_FILE + + self._in_project_scope_cache = {} + self._exclude_by_filter_cache = {} + self._apply_filter_cache = {} + self._ignore_system_exit_codes = set() + + # DAP related + self._dap_messages_listeners = [] + + if set_as_global: + # Set as the global instance only after it's initialized. + set_global_debugger(self) + + # Stop the tracing as the last thing before the actual shutdown for a clean exit. + atexit.register(stoptrace) + + def collect_try_except_info(self, code_obj): + filename = code_obj.co_filename + try: + if os.path.exists(filename): + pydev_log.debug('Collecting try..except info from source for %s', filename) + try_except_infos = collect_try_except_info_from_source(filename) + if try_except_infos: + # Filter for the current function + max_line = -1 + min_line = sys.maxsize + for _, line in dis.findlinestarts(code_obj): + + if line > max_line: + max_line = line + + if line < min_line: + min_line = line + + try_except_infos = [x for x in try_except_infos if min_line <= x.try_line <= max_line] + return try_except_infos + + except: + pydev_log.exception('Error collecting try..except info from source (%s)', filename) + + pydev_log.debug('Collecting try..except info from bytecode for %s', filename) + return collect_try_except_info(code_obj) + + def setup_auto_reload_watcher(self, enable_auto_reload, watch_dirs, poll_target_time, exclude_patterns, include_patterns): + try: + with self._lock_create_fs_notify: + + # When setting up, dispose of the previous one (if any). + if self._fsnotify_thread is not None: + self._fsnotify_thread.do_kill_pydev_thread() + self._fsnotify_thread = None + + if not enable_auto_reload: + return + + exclude_patterns = tuple(exclude_patterns) + include_patterns = tuple(include_patterns) + + def accept_directory(absolute_filename, cache={}): + try: + return cache[absolute_filename] + except: + if absolute_filename and absolute_filename[-1] not in ('/', '\\'): + # I.e.: for directories we always end with '/' or '\\' so that + # we match exclusions such as "**/node_modules/**" + absolute_filename += os.path.sep + + # First include what we want + for include_pattern in include_patterns: + if glob_matches_path(absolute_filename, include_pattern): + cache[absolute_filename] = True + return True + + # Then exclude what we don't want + for exclude_pattern in exclude_patterns: + if glob_matches_path(absolute_filename, exclude_pattern): + cache[absolute_filename] = False + return False + + # By default track all directories not excluded. + cache[absolute_filename] = True + return True + + def accept_file(absolute_filename, cache={}): + try: + return cache[absolute_filename] + except: + # First include what we want + for include_pattern in include_patterns: + if glob_matches_path(absolute_filename, include_pattern): + cache[absolute_filename] = True + return True + + # Then exclude what we don't want + for exclude_pattern in exclude_patterns: + if glob_matches_path(absolute_filename, exclude_pattern): + cache[absolute_filename] = False + return False + + # By default don't track files not included. + cache[absolute_filename] = False + return False + + self._fsnotify_thread = FSNotifyThread(self, PyDevdAPI(), watch_dirs) + watcher = self._fsnotify_thread.watcher + watcher.accept_directory = accept_directory + watcher.accept_file = accept_file + + watcher.target_time_for_single_scan = poll_target_time + watcher.target_time_for_notification = poll_target_time + self._fsnotify_thread.start() + except: + pydev_log.exception('Error setting up auto-reload.') + + def get_arg_ppid(self): + try: + setup = SetupHolder.setup + if setup: + return int(setup.get('ppid', 0)) + except: + pydev_log.exception('Error getting ppid.') + + return 0 + + def wait_for_ready_to_run(self): + while not self.ready_to_run: + # busy wait until we receive run command + self.process_internal_commands() + self._py_db_command_thread_event.clear() + self._py_db_command_thread_event.wait(0.1) + + def on_initialize(self): + ''' + Note: only called when using the DAP (Debug Adapter Protocol). + ''' + self._on_configuration_done_event.clear() + + def on_configuration_done(self): + ''' + Note: only called when using the DAP (Debug Adapter Protocol). + ''' + self._on_configuration_done_event.set() + self._py_db_command_thread_event.set() + + def is_attached(self): + return self._on_configuration_done_event.is_set() + + def on_disconnect(self): + ''' + Note: only called when using the DAP (Debug Adapter Protocol). + ''' + self.authentication.logout() + self._on_configuration_done_event.clear() + + def set_ignore_system_exit_codes(self, ignore_system_exit_codes): + assert isinstance(ignore_system_exit_codes, (list, tuple, set)) + self._ignore_system_exit_codes = set(ignore_system_exit_codes) + + def ignore_system_exit_code(self, system_exit_exc): + if hasattr(system_exit_exc, 'code'): + return system_exit_exc.code in self._ignore_system_exit_codes + else: + return system_exit_exc in self._ignore_system_exit_codes + + def block_until_configuration_done(self, cancel=None): + if cancel is None: + cancel = NULL + + while not cancel.is_set(): + if self._on_configuration_done_event.is_set(): + cancel.set() # Set cancel to prevent reuse + return + + self.process_internal_commands() + self._py_db_command_thread_event.clear() + self._py_db_command_thread_event.wait(1 / 15.) + + def add_fake_frame(self, thread_id, frame_id, frame): + self.suspended_frames_manager.add_fake_frame(thread_id, frame_id, frame) + + def handle_breakpoint_condition(self, info, pybreakpoint, new_frame): + condition = pybreakpoint.condition + try: + if pybreakpoint.handle_hit_condition(new_frame): + return True + + if not condition: + return False + + return eval(condition, new_frame.f_globals, new_frame.f_locals) + except Exception as e: + if not isinstance(e, self.skip_print_breakpoint_exception): + stack_trace = io.StringIO() + etype, value, tb = sys.exc_info() + traceback.print_exception(etype, value, tb.tb_next, file=stack_trace) + + msg = 'Error while evaluating expression in conditional breakpoint: %s\n%s' % ( + condition, stack_trace.getvalue()) + api = PyDevdAPI() + api.send_error_message(self, msg) + + if not isinstance(e, self.skip_suspend_on_breakpoint_exception): + try: + # add exception_type and stacktrace into thread additional info + etype, value, tb = sys.exc_info() + error = ''.join(traceback.format_exception_only(etype, value)) + stack = traceback.extract_stack(f=tb.tb_frame.f_back) + + # On self.set_suspend(thread, CMD_SET_BREAK) this info will be + # sent to the client. + info.conditional_breakpoint_exception = \ + ('Condition:\n' + condition + '\n\nError:\n' + error, stack) + except: + pydev_log.exception() + return True + + return False + + finally: + etype, value, tb = None, None, None + + def handle_breakpoint_expression(self, pybreakpoint, info, new_frame): + try: + try: + val = eval(pybreakpoint.expression, new_frame.f_globals, new_frame.f_locals) + except: + val = sys.exc_info()[1] + finally: + if val is not None: + info.pydev_message = str(val) + + def _internal_get_file_type(self, abs_real_path_and_basename): + basename = abs_real_path_and_basename[-1] + if ( + basename.startswith(IGNORE_BASENAMES_STARTING_WITH) or + abs_real_path_and_basename[0].startswith(IGNORE_BASENAMES_STARTING_WITH) + ): + # Note: these are the files that are completely ignored (they aren't shown to the user + # as user nor library code as it's usually just noise in the frame stack). + return self.PYDEV_FILE + file_type = self._dont_trace_get_file_type(basename) + if file_type is not None: + return file_type + + if basename.startswith('__init__.py'): + # i.e.: ignore the __init__ files inside pydevd (the other + # files are ignored just by their name). + abs_path = abs_real_path_and_basename[0] + i = max(abs_path.rfind('/'), abs_path.rfind('\\')) + if i: + abs_path = abs_path[0:i] + i = max(abs_path.rfind('/'), abs_path.rfind('\\')) + if i: + dirname = abs_path[i + 1:] + # At this point, something as: + # "my_path\_pydev_runfiles\__init__.py" + # is now "_pydev_runfiles". + return self._dont_trace_dirs_get_file_type(dirname) + return None + + def dont_trace_external_files(self, abs_path): + ''' + :param abs_path: + The result from get_abs_path_real_path_and_base_from_file or + get_abs_path_real_path_and_base_from_frame. + + :return + True : + If files should NOT be traced. + + False: + If files should be traced. + ''' + # By default all external files are traced. Note: this function is expected to + # be changed for another function in PyDevdAPI.set_dont_trace_start_end_patterns. + return False + + def get_file_type(self, frame, abs_real_path_and_basename=None, _cache_file_type=_CACHE_FILE_TYPE): + ''' + :param abs_real_path_and_basename: + The result from get_abs_path_real_path_and_base_from_file or + get_abs_path_real_path_and_base_from_frame. + + :return + _pydevd_bundle.pydevd_dont_trace_files.PYDEV_FILE: + If it's a file internal to the debugger which shouldn't be + traced nor shown to the user. + + _pydevd_bundle.pydevd_dont_trace_files.LIB_FILE: + If it's a file in a library which shouldn't be traced. + + None: + If it's a regular user file which should be traced. + ''' + if abs_real_path_and_basename is None: + try: + # Make fast path faster! + abs_real_path_and_basename = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + except: + abs_real_path_and_basename = get_abs_path_real_path_and_base_from_frame(frame) + + # Note 1: we have to take into account that we may have files as '', and that in + # this case the cache key can't rely only on the filename. With the current cache, there's + # still a potential miss if 2 functions which have exactly the same content are compiled + # with '', but in practice as we only separate the one from python -c from the rest + # this shouldn't be a problem in practice. + + # Note 2: firstlineno added to make misses faster in the first comparison. + + # Note 3: this cache key is repeated in pydevd_frame_evaluator.pyx:get_func_code_info (for + # speedups). + cache_key = (frame.f_code.co_firstlineno, abs_real_path_and_basename[0], frame.f_code) + try: + return _cache_file_type[cache_key] + except: + if abs_real_path_and_basename[0] == '': + + # Consider it an untraceable file unless there's no back frame (ignoring + # internal files and runpy.py). + f = frame.f_back + while f is not None: + if (self.get_file_type(f) != self.PYDEV_FILE and + pydevd_file_utils.basename(f.f_code.co_filename) not in ('runpy.py', '')): + # We found some back frame that's not internal, which means we must consider + # this a library file. + # This is done because we only want to trace files as if they don't + # have any back frame (which is the case for python -c ...), for all other + # cases we don't want to trace them because we can't show the source to the + # user (at least for now...). + + # Note that we return as a LIB_FILE and not PYDEV_FILE because we still want + # to show it in the stack. + _cache_file_type[cache_key] = LIB_FILE + return LIB_FILE + f = f.f_back + else: + # This is a top-level file (used in python -c), so, trace it as usual... we + # still won't be able to show the sources, but some tests require this to work. + _cache_file_type[cache_key] = None + return None + + file_type = self._internal_get_file_type(abs_real_path_and_basename) + if file_type is None: + if self.dont_trace_external_files(abs_real_path_and_basename[0]): + file_type = PYDEV_FILE + + _cache_file_type[cache_key] = file_type + return file_type + + def is_cache_file_type_empty(self): + return not _CACHE_FILE_TYPE + + def get_cache_file_type(self, _cache=_CACHE_FILE_TYPE): # i.e.: Make it local. + return _cache + + def get_thread_local_trace_func(self): + try: + thread_trace_func = self._local_thread_trace_func.thread_trace_func + except AttributeError: + thread_trace_func = self.trace_dispatch + return thread_trace_func + + def enable_tracing(self, thread_trace_func=None, apply_to_all_threads=False): + ''' + Enables tracing. + + If in regular mode (tracing), will set the tracing function to the tracing + function for this thread -- by default it's `PyDB.trace_dispatch`, but after + `PyDB.enable_tracing` is called with a `thread_trace_func`, the given function will + be the default for the given thread. + + :param bool apply_to_all_threads: + If True we'll set the tracing function in all threads, not only in the current thread. + If False only the tracing for the current function should be changed. + In general apply_to_all_threads should only be true if this is the first time + this function is called on a multi-threaded program (either programmatically or attach + to pid). + ''' + if pydevd_gevent_integration is not None: + pydevd_gevent_integration.enable_gevent_integration() + + if self.frame_eval_func is not None: + self.frame_eval_func() + pydevd_tracing.SetTrace(self.dummy_trace_dispatch) + + if IS_CPYTHON and apply_to_all_threads: + pydevd_tracing.set_trace_to_threads(self.dummy_trace_dispatch) + return + + if apply_to_all_threads: + # If applying to all threads, don't use the local thread trace function. + assert thread_trace_func is not None + else: + if thread_trace_func is None: + thread_trace_func = self.get_thread_local_trace_func() + else: + self._local_thread_trace_func.thread_trace_func = thread_trace_func + + pydevd_tracing.SetTrace(thread_trace_func) + if IS_CPYTHON and apply_to_all_threads: + pydevd_tracing.set_trace_to_threads(thread_trace_func) + + def disable_tracing(self): + pydevd_tracing.SetTrace(None) + + def on_breakpoints_changed(self, removed=False): + ''' + When breakpoints change, we have to re-evaluate all the assumptions we've made so far. + ''' + if not self.ready_to_run: + # No need to do anything if we're still not running. + return + + self.mtime += 1 + if not removed: + # When removing breakpoints we can leave tracing as was, but if a breakpoint was added + # we have to reset the tracing for the existing functions to be re-evaluated. + self.set_tracing_for_untraced_contexts() + + def set_tracing_for_untraced_contexts(self): + # Enable the tracing for existing threads (because there may be frames being executed that + # are currently untraced). + + if IS_CPYTHON: + # Note: use sys._current_frames instead of threading.enumerate() because this way + # we also see C/C++ threads, not only the ones visible to the threading module. + tid_to_frame = sys._current_frames() + + ignore_thread_ids = set( + t.ident for t in threadingEnumerate() + if getattr(t, 'is_pydev_daemon_thread', False) or getattr(t, 'pydev_do_not_trace', False) + ) + + for thread_id, frame in tid_to_frame.items(): + if thread_id not in ignore_thread_ids: + self.set_trace_for_frame_and_parents(frame) + + else: + try: + threads = threadingEnumerate() + for t in threads: + if getattr(t, 'is_pydev_daemon_thread', False) or getattr(t, 'pydev_do_not_trace', False): + continue + + additional_info = set_additional_thread_info(t) + frame = additional_info.get_topmost_frame(t) + try: + if frame is not None: + self.set_trace_for_frame_and_parents(frame) + finally: + frame = None + finally: + frame = None + t = None + threads = None + additional_info = None + + @property + def multi_threads_single_notification(self): + return self._threads_suspended_single_notification.multi_threads_single_notification + + @multi_threads_single_notification.setter + def multi_threads_single_notification(self, notify): + self._threads_suspended_single_notification.multi_threads_single_notification = notify + + @property + def threads_suspended_single_notification(self): + return self._threads_suspended_single_notification + + def get_plugin_lazy_init(self): + if self.plugin is None: + self.plugin = PluginManager(self) + return self.plugin + + def in_project_scope(self, frame, absolute_filename=None): + ''' + Note: in general this method should not be used (apply_files_filter should be used + in most cases as it also handles the project scope check). + + :param frame: + The frame we want to check. + + :param absolute_filename: + Must be the result from get_abs_path_real_path_and_base_from_frame(frame)[0] (can + be used to speed this function a bit if it's already available to the caller, but + in general it's not needed). + ''' + try: + if absolute_filename is None: + try: + # Make fast path faster! + abs_real_path_and_basename = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + except: + abs_real_path_and_basename = get_abs_path_real_path_and_base_from_frame(frame) + + absolute_filename = abs_real_path_and_basename[0] + + cache_key = (frame.f_code.co_firstlineno, absolute_filename, frame.f_code) + + return self._in_project_scope_cache[cache_key] + except KeyError: + cache = self._in_project_scope_cache + try: + abs_real_path_and_basename # If we've gotten it previously, use it again. + except NameError: + abs_real_path_and_basename = get_abs_path_real_path_and_base_from_frame(frame) + + # pydevd files are never considered to be in the project scope. + file_type = self.get_file_type(frame, abs_real_path_and_basename) + if file_type == self.PYDEV_FILE: + cache[cache_key] = False + + elif absolute_filename == '': + # Special handling for '' + if file_type == self.LIB_FILE: + cache[cache_key] = False + else: + cache[cache_key] = True + + elif self.source_mapping.has_mapping_entry(absolute_filename): + cache[cache_key] = True + + else: + cache[cache_key] = self._files_filtering.in_project_roots(absolute_filename) + + return cache[cache_key] + + def in_project_roots_filename_uncached(self, absolute_filename): + return self._files_filtering.in_project_roots(absolute_filename) + + def _clear_filters_caches(self): + self._in_project_scope_cache.clear() + self._exclude_by_filter_cache.clear() + self._apply_filter_cache.clear() + self._exclude_filters_enabled = self._files_filtering.use_exclude_filters() + self._is_libraries_filter_enabled = self._files_filtering.use_libraries_filter() + self.is_files_filter_enabled = self._exclude_filters_enabled or self._is_libraries_filter_enabled + + def clear_dont_trace_start_end_patterns_caches(self): + # When start/end patterns are changed we must clear all caches which would be + # affected by a change in get_file_type() and reset the tracing function + # as places which were traced may no longer need to be traced and vice-versa. + self.on_breakpoints_changed() + _CACHE_FILE_TYPE.clear() + self._clear_filters_caches() + self._clear_skip_caches() + + def _exclude_by_filter(self, frame, absolute_filename): + ''' + :return: True if it should be excluded, False if it should be included and None + if no rule matched the given file. + + :note: it'll be normalized as needed inside of this method. + ''' + cache_key = (absolute_filename, frame.f_code.co_name, frame.f_code.co_firstlineno) + try: + return self._exclude_by_filter_cache[cache_key] + except KeyError: + cache = self._exclude_by_filter_cache + + # pydevd files are always filtered out + if self.get_file_type(frame) == self.PYDEV_FILE: + cache[cache_key] = True + else: + module_name = None + if self._files_filtering.require_module: + module_name = frame.f_globals.get('__name__', '') + cache[cache_key] = self._files_filtering.exclude_by_filter(absolute_filename, module_name) + + return cache[cache_key] + + def apply_files_filter(self, frame, original_filename, force_check_project_scope): + ''' + Should only be called if `self.is_files_filter_enabled == True` or `force_check_project_scope == True`. + + Note that it covers both the filter by specific paths includes/excludes as well + as the check which filters out libraries if not in the project scope. + + :param original_filename: + Note can either be the original filename or the absolute version of that filename. + + :param force_check_project_scope: + Check that the file is in the project scope even if the global setting + is off. + + :return bool: + True if it should be excluded when stepping and False if it should be + included. + ''' + cache_key = (frame.f_code.co_firstlineno, original_filename, force_check_project_scope, frame.f_code) + try: + return self._apply_filter_cache[cache_key] + except KeyError: + if self.plugin is not None and (self.has_plugin_line_breaks or self.has_plugin_exception_breaks): + # If it's explicitly needed by some plugin, we can't skip it. + if not self.plugin.can_skip(self, frame): + pydev_log.debug_once('File traced (included by plugins): %s', original_filename) + self._apply_filter_cache[cache_key] = False + return False + + if self._exclude_filters_enabled: + absolute_filename = pydevd_file_utils.absolute_path(original_filename) + exclude_by_filter = self._exclude_by_filter(frame, absolute_filename) + if exclude_by_filter is not None: + if exclude_by_filter: + # ignore files matching stepping filters + pydev_log.debug_once('File not traced (excluded by filters): %s', original_filename) + + self._apply_filter_cache[cache_key] = True + return True + else: + pydev_log.debug_once('File traced (explicitly included by filters): %s', original_filename) + + self._apply_filter_cache[cache_key] = False + return False + + if (self._is_libraries_filter_enabled or force_check_project_scope) and not self.in_project_scope(frame): + # ignore library files while stepping + self._apply_filter_cache[cache_key] = True + if force_check_project_scope: + pydev_log.debug_once('File not traced (not in project): %s', original_filename) + else: + pydev_log.debug_once('File not traced (not in project - force_check_project_scope): %s', original_filename) + + return True + + if force_check_project_scope: + pydev_log.debug_once('File traced: %s (force_check_project_scope)', original_filename) + else: + pydev_log.debug_once('File traced: %s', original_filename) + self._apply_filter_cache[cache_key] = False + return False + + def exclude_exception_by_filter(self, exception_breakpoint, trace): + if not exception_breakpoint.ignore_libraries and not self._exclude_filters_enabled: + return False + + if trace is None: + return True + + ignore_libraries = exception_breakpoint.ignore_libraries + exclude_filters_enabled = self._exclude_filters_enabled + + if (ignore_libraries and not self.in_project_scope(trace.tb_frame)) \ + or (exclude_filters_enabled and self._exclude_by_filter( + trace.tb_frame, + pydevd_file_utils.absolute_path(trace.tb_frame.f_code.co_filename))): + return True + + return False + + def set_project_roots(self, project_roots): + self._files_filtering.set_project_roots(project_roots) + self._clear_skip_caches() + self._clear_filters_caches() + + def set_exclude_filters(self, exclude_filters): + self._files_filtering.set_exclude_filters(exclude_filters) + self._clear_skip_caches() + self._clear_filters_caches() + + def set_use_libraries_filter(self, use_libraries_filter): + self._files_filtering.set_use_libraries_filter(use_libraries_filter) + self._clear_skip_caches() + self._clear_filters_caches() + + def get_use_libraries_filter(self): + return self._files_filtering.use_libraries_filter() + + def get_require_module_for_filters(self): + return self._files_filtering.require_module + + def has_user_threads_alive(self): + for t in pydevd_utils.get_non_pydevd_threads(): + if isinstance(t, PyDBDaemonThread): + pydev_log.error_once( + 'Error in debugger: Found PyDBDaemonThread not marked with is_pydev_daemon_thread=True.\n') + + if is_thread_alive(t): + if not t.daemon or hasattr(t, "__pydevd_main_thread"): + return True + + return False + + def initialize_network(self, sock, terminate_on_socket_close=True): + assert sock is not None + try: + sock.settimeout(None) # infinite, no timeouts from now on - jython does not have it + except: + pass + curr_reader = getattr(self, 'reader', None) + curr_writer = getattr(self, 'writer', None) + if curr_reader: + curr_reader.do_kill_pydev_thread() + if curr_writer: + curr_writer.do_kill_pydev_thread() + + self.writer = WriterThread(sock, self, terminate_on_socket_close=terminate_on_socket_close) + self.reader = ReaderThread( + sock, + self, + PyDevJsonCommandProcessor=PyDevJsonCommandProcessor, + process_net_command=process_net_command, + terminate_on_socket_close=terminate_on_socket_close + ) + self.writer.start() + self.reader.start() + + time.sleep(0.1) # give threads time to start + + def connect(self, host, port): + if host: + s = start_client(host, port) + else: + s = start_server(port) + + self.initialize_network(s) + + def create_wait_for_connection_thread(self): + if self._waiting_for_connection_thread is not None: + raise AssertionError('There is already another thread waiting for a connection.') + + self._server_socket_ready_event.clear() + self._waiting_for_connection_thread = self._WaitForConnectionThread(self) + self._waiting_for_connection_thread.start() + + def set_server_socket_ready(self): + self._server_socket_ready_event.set() + + def wait_for_server_socket_ready(self): + self._server_socket_ready_event.wait() + + @property + def dap_messages_listeners(self): + return self._dap_messages_listeners + + def add_dap_messages_listener(self, listener): + self._dap_messages_listeners.append(listener) + + class _WaitForConnectionThread(PyDBDaemonThread): + + def __init__(self, py_db): + PyDBDaemonThread.__init__(self, py_db) + self._server_socket = None + + def run(self): + host = SetupHolder.setup['client'] + port = SetupHolder.setup['port'] + + self._server_socket = create_server_socket(host=host, port=port) + self.py_db._server_socket_name = self._server_socket.getsockname() + self.py_db.set_server_socket_ready() + + while not self._kill_received: + try: + s = self._server_socket + if s is None: + return + + s.listen(1) + new_socket, _addr = s.accept() + if self._kill_received: + pydev_log.info("Connection (from wait_for_attach) accepted but ignored as kill was already received.") + return + + pydev_log.info("Connection (from wait_for_attach) accepted.") + reader = getattr(self.py_db, 'reader', None) + if reader is not None: + # This is needed if a new connection is done without the client properly + # sending a disconnect for the previous connection. + api = PyDevdAPI() + api.request_disconnect(self.py_db, resume_threads=False) + + self.py_db.initialize_network(new_socket, terminate_on_socket_close=False) + + except: + if DebugInfoHolder.DEBUG_TRACE_LEVEL > 0: + pydev_log.exception() + pydev_log.debug("Exiting _WaitForConnectionThread: %s\n", port) + + def do_kill_pydev_thread(self): + PyDBDaemonThread.do_kill_pydev_thread(self) + s = self._server_socket + if s is not None: + try: + s.close() + except: + pass + self._server_socket = None + + def get_internal_queue(self, thread_id): + """ returns internal command queue for a given thread. + if new queue is created, notify the RDB about it """ + if thread_id.startswith('__frame__'): + thread_id = thread_id[thread_id.rfind('|') + 1:] + return self._cmd_queue[thread_id] + + def post_method_as_internal_command(self, thread_id, method, *args, **kwargs): + if thread_id == '*': + internal_cmd = InternalThreadCommandForAnyThread(thread_id, method, *args, **kwargs) + else: + internal_cmd = InternalThreadCommand(thread_id, method, *args, **kwargs) + self.post_internal_command(internal_cmd, thread_id) + if thread_id == '*': + # Notify so that the command is handled as soon as possible. + self._py_db_command_thread_event.set() + + def post_internal_command(self, int_cmd, thread_id): + """ if thread_id is *, post to the '*' queue""" + queue = self.get_internal_queue(thread_id) + queue.put(int_cmd) + + def enable_output_redirection(self, redirect_stdout, redirect_stderr): + global _global_redirect_stdout_to_server + global _global_redirect_stderr_to_server + + _global_redirect_stdout_to_server = redirect_stdout + _global_redirect_stderr_to_server = redirect_stderr + self.redirect_output = redirect_stdout or redirect_stderr + if _global_redirect_stdout_to_server: + _init_stdout_redirect() + if _global_redirect_stderr_to_server: + _init_stderr_redirect() + + def check_output_redirect(self): + global _global_redirect_stdout_to_server + global _global_redirect_stderr_to_server + + if _global_redirect_stdout_to_server: + _init_stdout_redirect() + + if _global_redirect_stderr_to_server: + _init_stderr_redirect() + + def init_matplotlib_in_debug_console(self): + # import hook and patches for matplotlib support in debug console + from _pydev_bundle.pydev_import_hook import import_hook_manager + if is_current_thread_main_thread(): + for module in list(self.mpl_modules_for_patching): + import_hook_manager.add_module_name(module, self.mpl_modules_for_patching.pop(module)) + + def init_gui_support(self): + if self._installed_gui_support: + return + self._installed_gui_support = True + + # enable_gui and enable_gui_function in activate_matplotlib should be called in main thread. Unlike integrated console, + # in the debug console we have no interpreter instance with exec_queue, but we run this code in the main + # thread and can call it directly. + class _ReturnGuiLoopControlHelper: + _return_control_osc = False + + def return_control(): + # Some of the input hooks (e.g. Qt4Agg) check return control without doing + # a single operation, so we don't return True on every + # call when the debug hook is in place to allow the GUI to run + _ReturnGuiLoopControlHelper._return_control_osc = not _ReturnGuiLoopControlHelper._return_control_osc + return _ReturnGuiLoopControlHelper._return_control_osc + + from pydev_ipython.inputhook import set_return_control_callback, enable_gui + + set_return_control_callback(return_control) + + if self._gui_event_loop == 'matplotlib': + # prepare debugger for matplotlib integration with GUI event loop + from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot, do_enable_gui + + self.mpl_modules_for_patching = {"matplotlib": lambda: activate_matplotlib(do_enable_gui), + "matplotlib.pyplot": activate_pyplot, + "pylab": activate_pylab } + else: + self.activate_gui_function = enable_gui + + def _activate_gui_if_needed(self): + if self.gui_in_use: + return + + if len(self.mpl_modules_for_patching) > 0: + if is_current_thread_main_thread(): # Note that we call only in the main thread. + for module in list(self.mpl_modules_for_patching): + if module in sys.modules: + activate_function = self.mpl_modules_for_patching.pop(module, None) + if activate_function is not None: + activate_function() + self.gui_in_use = True + + if self.activate_gui_function: + if is_current_thread_main_thread(): # Only call enable_gui in the main thread. + try: + # First try to activate builtin GUI event loops. + self.activate_gui_function(self._gui_event_loop) + self.activate_gui_function = None + self.gui_in_use = True + except ValueError: + # The user requested a custom GUI event loop, try to import it. + from pydev_ipython.inputhook import set_inputhook + try: + inputhook_function = import_attr_from_module(self._gui_event_loop) + set_inputhook(inputhook_function) + self.gui_in_use = True + except Exception as e: + pydev_log.debug("Cannot activate custom GUI event loop {}: {}".format(self._gui_event_loop, e)) + finally: + self.activate_gui_function = None + + def _call_input_hook(self): + try: + from pydev_ipython.inputhook import get_inputhook + inputhook = get_inputhook() + if inputhook: + inputhook() + except: + pass + + def notify_skipped_step_in_because_of_filters(self, frame): + self.writer.add_command(self.cmd_factory.make_skipped_step_in_because_of_filters(self, frame)) + + def notify_thread_created(self, thread_id, thread, use_lock=True): + if self.writer is None: + # Protect about threads being created before the communication structure is in place + # (note that they will appear later on anyways as pydevd does reconcile live/dead threads + # when processing internal commands, albeit it may take longer and in general this should + # not be usual as it's expected that the debugger is live before other threads are created). + return + + with self._lock_running_thread_ids if use_lock else NULL: + if not self._enable_thread_notifications: + return + + if thread_id in self._running_thread_ids: + return + + additional_info = set_additional_thread_info(thread) + if additional_info.pydev_notify_kill: + # After we notify it should be killed, make sure we don't notify it's alive (on a racing condition + # this could happen as we may notify before the thread is stopped internally). + return + + self._running_thread_ids[thread_id] = thread + + self.writer.add_command(self.cmd_factory.make_thread_created_message(thread)) + + def notify_thread_not_alive(self, thread_id, use_lock=True): + """ if thread is not alive, cancel trace_dispatch processing """ + if self.writer is None: + return + + with self._lock_running_thread_ids if use_lock else NULL: + if not self._enable_thread_notifications: + return + + thread = self._running_thread_ids.pop(thread_id, None) + if thread is None: + return + + additional_info = set_additional_thread_info(thread) + was_notified = additional_info.pydev_notify_kill + if not was_notified: + additional_info.pydev_notify_kill = True + + self.writer.add_command(self.cmd_factory.make_thread_killed_message(thread_id)) + + def set_enable_thread_notifications(self, enable): + with self._lock_running_thread_ids: + if self._enable_thread_notifications != enable: + self._enable_thread_notifications = enable + + if enable: + # As it was previously disabled, we have to notify about existing threads again + # (so, clear the cache related to that). + self._running_thread_ids = {} + + def process_internal_commands(self): + ''' + This function processes internal commands. + ''' + # If this method is being called before the debugger is ready to run we should not notify + # about threads and should only process commands sent to all threads. + ready_to_run = self.ready_to_run + + dispose = False + with self._main_lock: + program_threads_alive = {} + if ready_to_run: + self.check_output_redirect() + + all_threads = threadingEnumerate() + program_threads_dead = [] + with self._lock_running_thread_ids: + reset_cache = not self._running_thread_ids + + for t in all_threads: + if getattr(t, 'is_pydev_daemon_thread', False): + pass # I.e.: skip the DummyThreads created from pydev daemon threads + elif isinstance(t, PyDBDaemonThread): + pydev_log.error_once('Error in debugger: Found PyDBDaemonThread not marked with is_pydev_daemon_thread=True.') + + elif is_thread_alive(t): + if reset_cache: + # Fix multiprocessing debug with breakpoints in both main and child processes + # (https://youtrack.jetbrains.com/issue/PY-17092) When the new process is created, the main + # thread in the new process already has the attribute 'pydevd_id', so the new thread doesn't + # get new id with its process number and the debugger loses access to both threads. + # Therefore we should update thread_id for every main thread in the new process. + clear_cached_thread_id(t) + + thread_id = get_thread_id(t) + program_threads_alive[thread_id] = t + + self.notify_thread_created(thread_id, t, use_lock=False) + + # Compute and notify about threads which are no longer alive. + thread_ids = list(self._running_thread_ids.keys()) + for thread_id in thread_ids: + if thread_id not in program_threads_alive: + program_threads_dead.append(thread_id) + + for thread_id in program_threads_dead: + self.notify_thread_not_alive(thread_id, use_lock=False) + + cmds_to_execute = [] + + # Without self._lock_running_thread_ids + if len(program_threads_alive) == 0 and ready_to_run: + dispose = True + else: + # Actually process the commands now (make sure we don't have a lock for _lock_running_thread_ids + # acquired at this point as it could lead to a deadlock if some command evaluated tried to + # create a thread and wait for it -- which would try to notify about it getting that lock). + curr_thread_id = get_current_thread_id(threadingCurrentThread()) + if ready_to_run: + process_thread_ids = (curr_thread_id, '*') + else: + process_thread_ids = ('*',) + + for thread_id in process_thread_ids: + queue = self.get_internal_queue(thread_id) + + # some commands must be processed by the thread itself... if that's the case, + # we will re-add the commands to the queue after executing. + cmds_to_add_back = [] + + try: + while True: + int_cmd = queue.get(False) + + if not self.mpl_hooks_in_debug_console and isinstance(int_cmd, InternalConsoleExec) and not self.gui_in_use: + # add import hooks for matplotlib patches if only debug console was started + try: + self.init_matplotlib_in_debug_console() + self.gui_in_use = True + except: + pydev_log.debug("Matplotlib support in debug console failed", traceback.format_exc()) + self.mpl_hooks_in_debug_console = True + + if int_cmd.can_be_executed_by(curr_thread_id): + cmds_to_execute.append(int_cmd) + else: + pydev_log.verbose("NOT processing internal command: %s ", int_cmd) + cmds_to_add_back.append(int_cmd) + + except _queue.Empty: # @UndefinedVariable + # this is how we exit + for int_cmd in cmds_to_add_back: + queue.put(int_cmd) + + if dispose: + # Note: must be called without the main lock to avoid deadlocks. + self.dispose_and_kill_all_pydevd_threads() + else: + # Actually execute the commands without the main lock! + for int_cmd in cmds_to_execute: + pydev_log.verbose("processing internal command: %s", int_cmd) + try: + int_cmd.do_it(self) + except: + pydev_log.exception('Error processing internal command.') + + def consolidate_breakpoints(self, canonical_normalized_filename, id_to_breakpoint, file_to_line_to_breakpoints): + break_dict = {} + for _breakpoint_id, pybreakpoint in id_to_breakpoint.items(): + break_dict[pybreakpoint.line] = pybreakpoint + + file_to_line_to_breakpoints[canonical_normalized_filename] = break_dict + self._clear_skip_caches() + + def _clear_skip_caches(self): + global_cache_skips.clear() + global_cache_frame_skips.clear() + + def add_break_on_exception( + self, + exception, + condition, + expression, + notify_on_handled_exceptions, + notify_on_unhandled_exceptions, + notify_on_user_unhandled_exceptions, + notify_on_first_raise_only, + ignore_libraries=False + ): + try: + eb = ExceptionBreakpoint( + exception, + condition, + expression, + notify_on_handled_exceptions, + notify_on_unhandled_exceptions, + notify_on_user_unhandled_exceptions, + notify_on_first_raise_only, + ignore_libraries + ) + except ImportError: + pydev_log.critical("Error unable to add break on exception for: %s (exception could not be imported).", exception) + return None + + if eb.notify_on_unhandled_exceptions: + cp = self.break_on_uncaught_exceptions.copy() + cp[exception] = eb + pydev_log.info("Exceptions to hook on terminate: %s.", cp) + self.break_on_uncaught_exceptions = cp + + if eb.notify_on_handled_exceptions: + cp = self.break_on_caught_exceptions.copy() + cp[exception] = eb + pydev_log.info("Exceptions to hook always: %s.", cp) + self.break_on_caught_exceptions = cp + + if eb.notify_on_user_unhandled_exceptions: + cp = self.break_on_user_uncaught_exceptions.copy() + cp[exception] = eb + pydev_log.info("Exceptions to hook on user uncaught code: %s.", cp) + self.break_on_user_uncaught_exceptions = cp + + return eb + + def set_suspend(self, thread, stop_reason, suspend_other_threads=False, is_pause=False, original_step_cmd=-1): + ''' + :param thread: + The thread which should be suspended. + + :param stop_reason: + Reason why the thread was suspended. + + :param suspend_other_threads: + Whether to force other threads to be suspended (i.e.: when hitting a breakpoint + with a suspend all threads policy). + + :param is_pause: + If this is a pause to suspend all threads, any thread can be considered as the 'main' + thread paused. + + :param original_step_cmd: + If given we may change the stop reason to this. + ''' + self._threads_suspended_single_notification.increment_suspend_time() + if is_pause: + self._threads_suspended_single_notification.on_pause() + + info = mark_thread_suspended(thread, stop_reason, original_step_cmd=original_step_cmd) + + if is_pause: + # Must set tracing after setting the state to suspend. + frame = info.get_topmost_frame(thread) + if frame is not None: + try: + self.set_trace_for_frame_and_parents(frame) + finally: + frame = None + + # If conditional breakpoint raises any exception during evaluation send the details to the client. + if stop_reason == CMD_SET_BREAK and info.conditional_breakpoint_exception is not None: + conditional_breakpoint_exception_tuple = info.conditional_breakpoint_exception + info.conditional_breakpoint_exception = None + self._send_breakpoint_condition_exception(thread, conditional_breakpoint_exception_tuple) + + if not suspend_other_threads and self.multi_threads_single_notification: + # In the mode which gives a single notification when all threads are + # stopped, stop all threads whenever a set_suspend is issued. + suspend_other_threads = True + + if suspend_other_threads: + # Suspend all except the current one (which we're currently suspending already). + suspend_all_threads(self, except_thread=thread) + + def _send_breakpoint_condition_exception(self, thread, conditional_breakpoint_exception_tuple): + """If conditional breakpoint raises an exception during evaluation + send exception details to java + """ + thread_id = get_thread_id(thread) + # conditional_breakpoint_exception_tuple - should contain 2 values (exception_type, stacktrace) + if conditional_breakpoint_exception_tuple and len(conditional_breakpoint_exception_tuple) == 2: + exc_type, stacktrace = conditional_breakpoint_exception_tuple + int_cmd = InternalGetBreakpointException(thread_id, exc_type, stacktrace) + self.post_internal_command(int_cmd, thread_id) + + def send_caught_exception_stack(self, thread, arg, curr_frame_id): + """Sends details on the exception which was caught (and where we stopped) to the java side. + + arg is: exception type, description, traceback object + """ + thread_id = get_thread_id(thread) + int_cmd = InternalSendCurrExceptionTrace(thread_id, arg, curr_frame_id) + self.post_internal_command(int_cmd, thread_id) + + def send_caught_exception_stack_proceeded(self, thread): + """Sends that some thread was resumed and is no longer showing an exception trace. + """ + thread_id = get_thread_id(thread) + int_cmd = InternalSendCurrExceptionTraceProceeded(thread_id) + self.post_internal_command(int_cmd, thread_id) + self.process_internal_commands() + + def send_process_created_message(self): + """Sends a message that a new process has been created. + """ + if self.writer is None or self.cmd_factory is None: + return + cmd = self.cmd_factory.make_process_created_message() + self.writer.add_command(cmd) + + def send_process_about_to_be_replaced(self): + """Sends a message that a new process has been created. + """ + if self.writer is None or self.cmd_factory is None: + return + cmd = self.cmd_factory.make_process_about_to_be_replaced_message() + if cmd is NULL_NET_COMMAND: + return + + sent = [False] + + def after_sent(*args, **kwargs): + sent[0] = True + + cmd.call_after_send(after_sent) + self.writer.add_command(cmd) + + timeout = 5 # Wait up to 5 seconds + initial_time = time.time() + while not sent[0]: + time.sleep(.05) + + if (time.time() - initial_time) > timeout: + pydev_log.critical('pydevd: Sending message related to process being replaced timed-out after %s seconds', timeout) + break + + def set_next_statement(self, frame, event, func_name, next_line): + stop = False + response_msg = "" + old_line = frame.f_lineno + if event == 'line' or event == 'exception': + # If we're already in the correct context, we have to stop it now, because we can act only on + # line events -- if a return was the next statement it wouldn't work (so, we have this code + # repeated at pydevd_frame). + + curr_func_name = frame.f_code.co_name + + # global context is set with an empty name + if curr_func_name in ('?', ''): + curr_func_name = '' + + if func_name == '*' or curr_func_name == func_name: + line = next_line + frame.f_trace = self.trace_dispatch + frame.f_lineno = line + stop = True + else: + response_msg = "jump is available only within the bottom frame" + return stop, old_line, response_msg + + def cancel_async_evaluation(self, thread_id, frame_id): + with self._main_lock: + try: + all_threads = threadingEnumerate() + for t in all_threads: + if getattr(t, 'is_pydev_daemon_thread', False) and hasattr(t, 'cancel_event') and t.thread_id == thread_id and \ + t.frame_id == frame_id: + t.cancel_event.set() + except: + pydev_log.exception() + + def find_frame(self, thread_id, frame_id): + """ returns a frame on the thread that has a given frame_id """ + return self.suspended_frames_manager.find_frame(thread_id, frame_id) + + def do_wait_suspend(self, thread, frame, event, arg, exception_type=None): # @UnusedVariable + """ busy waits until the thread state changes to RUN + it expects thread's state as attributes of the thread. + Upon running, processes any outstanding Stepping commands. + + :param exception_type: + If pausing due to an exception, its type. + """ + if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP: + constructed_tid_to_last_frame[thread.ident] = sys._getframe() + self.process_internal_commands() + + thread_id = get_current_thread_id(thread) + + # print('do_wait_suspend %s %s %s %s %s %s (%s)' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event, arg, constant_to_str(thread.additional_info.pydev_step_cmd), constant_to_str(thread.additional_info.pydev_original_step_cmd))) + # print('--- stack ---') + # print(traceback.print_stack(file=sys.stdout)) + # print('--- end stack ---') + + # Send the suspend message + message = thread.additional_info.pydev_message + suspend_type = thread.additional_info.trace_suspend_type + thread.additional_info.trace_suspend_type = 'trace' # Reset to trace mode for next call. + stop_reason = thread.stop_reason + + frames_list = None + + if arg is not None and event == 'exception': + # arg must be the exception info (tuple(exc_type, exc, traceback)) + exc_type, exc_desc, trace_obj = arg + if trace_obj is not None: + frames_list = pydevd_frame_utils.create_frames_list_from_traceback(trace_obj, frame, exc_type, exc_desc, exception_type=exception_type) + + if frames_list is None: + frames_list = pydevd_frame_utils.create_frames_list_from_frame(frame) + + if DebugInfoHolder.DEBUG_TRACE_LEVEL > 2: + pydev_log.debug( + 'PyDB.do_wait_suspend\nname: %s (line: %s)\n file: %s\n event: %s\n arg: %s\n step: %s (original step: %s)\n thread: %s, thread id: %s, id(thread): %s', + frame.f_code.co_name, + frame.f_lineno, + frame.f_code.co_filename, + event, + arg, + constant_to_str(thread.additional_info.pydev_step_cmd), + constant_to_str(thread.additional_info.pydev_original_step_cmd), + thread, + thread_id, + id(thread), + ) + for f in frames_list: + pydev_log.debug(' Stack: %s, %s, %s', f.f_code.co_filename, f.f_code.co_name, f.f_lineno) + + with self.suspended_frames_manager.track_frames(self) as frames_tracker: + frames_tracker.track(thread_id, frames_list) + cmd = frames_tracker.create_thread_suspend_command(thread_id, stop_reason, message, suspend_type) + self.writer.add_command(cmd) + + with CustomFramesContainer.custom_frames_lock: # @UndefinedVariable + from_this_thread = [] + + for frame_custom_thread_id, custom_frame in CustomFramesContainer.custom_frames.items(): + if custom_frame.thread_id == thread.ident: + frames_tracker.track(thread_id, pydevd_frame_utils.create_frames_list_from_frame(custom_frame.frame), frame_custom_thread_id=frame_custom_thread_id) + # print('Frame created as thread: %s' % (frame_custom_thread_id,)) + + self.writer.add_command(self.cmd_factory.make_custom_frame_created_message( + frame_custom_thread_id, custom_frame.name)) + + self.writer.add_command( + frames_tracker.create_thread_suspend_command(frame_custom_thread_id, CMD_THREAD_SUSPEND, "", suspend_type)) + + from_this_thread.append(frame_custom_thread_id) + + with self._threads_suspended_single_notification.notify_thread_suspended(thread_id, stop_reason): + keep_suspended = self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker) + + frames_list = None + + if keep_suspended: + # This means that we should pause again after a set next statement. + self._threads_suspended_single_notification.increment_suspend_time() + self.do_wait_suspend(thread, frame, event, arg, exception_type) + if DebugInfoHolder.DEBUG_TRACE_LEVEL > 2: + pydev_log.debug('Leaving PyDB.do_wait_suspend: %s (%s) %s', thread, thread_id, id(thread)) + + def _do_wait_suspend(self, thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker): + info = thread.additional_info + info.step_in_initial_location = None + keep_suspended = False + + with self._main_lock: # Use lock to check if suspended state changed + activate_gui = info.pydev_state == STATE_SUSPEND and not self.pydb_disposed + + in_main_thread = is_current_thread_main_thread() + if activate_gui and in_main_thread: + # before every stop check if matplotlib modules were imported inside script code + # or some GUI event loop needs to be activated + self._activate_gui_if_needed() + + while True: + with self._main_lock: # Use lock to check if suspended state changed + if info.pydev_state != STATE_SUSPEND or (self.pydb_disposed and not self.terminate_requested): + # Note: we can't exit here if terminate was requested while a breakpoint was hit. + break + + if in_main_thread and self.gui_in_use: + # call input hooks if only GUI is in use + self._call_input_hook() + + self.process_internal_commands() + time.sleep(0.01) + + self.cancel_async_evaluation(get_current_thread_id(thread), str(id(frame))) + + # process any stepping instructions + if info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE): + info.step_in_initial_location = (frame, frame.f_lineno) + if frame.f_code.co_flags & 0x80: # CO_COROUTINE = 0x80 + # When in a coroutine we switch to CMD_STEP_INTO_COROUTINE. + info.pydev_step_cmd = CMD_STEP_INTO_COROUTINE + info.pydev_step_stop = frame + self.set_trace_for_frame_and_parents(frame) + else: + info.pydev_step_stop = None + self.set_trace_for_frame_and_parents(frame) + + elif info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE, CMD_SMART_STEP_INTO): + info.pydev_step_stop = frame + self.set_trace_for_frame_and_parents(frame) + + elif info.pydev_step_cmd == CMD_RUN_TO_LINE or info.pydev_step_cmd == CMD_SET_NEXT_STATEMENT: + info.pydev_step_stop = None + self.set_trace_for_frame_and_parents(frame) + stop = False + response_msg = "" + try: + stop, _old_line, response_msg = self.set_next_statement(frame, event, info.pydev_func_name, info.pydev_next_line) + except ValueError as e: + response_msg = "%s" % e + finally: + seq = info.pydev_message + cmd = self.cmd_factory.make_set_next_stmnt_status_message(seq, stop, response_msg) + self.writer.add_command(cmd) + info.pydev_message = '' + + if stop: + # Uninstall the current frames tracker before running it. + frames_tracker.untrack_all() + cmd = self.cmd_factory.make_thread_run_message(get_current_thread_id(thread), info.pydev_step_cmd) + self.writer.add_command(cmd) + info.pydev_state = STATE_SUSPEND + thread.stop_reason = CMD_SET_NEXT_STATEMENT + keep_suspended = True + + else: + # Set next did not work... + info.pydev_original_step_cmd = -1 + info.pydev_step_cmd = -1 + info.pydev_state = STATE_SUSPEND + thread.stop_reason = CMD_THREAD_SUSPEND + # return to the suspend state and wait for other command (without sending any + # additional notification to the client). + return self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker) + + elif info.pydev_step_cmd in (CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE): + back_frame = frame.f_back + force_check_project_scope = info.pydev_step_cmd == CMD_STEP_RETURN_MY_CODE + + if force_check_project_scope or self.is_files_filter_enabled: + while back_frame is not None: + if self.apply_files_filter(back_frame, back_frame.f_code.co_filename, force_check_project_scope): + frame = back_frame + back_frame = back_frame.f_back + else: + break + + if back_frame is not None: + # steps back to the same frame (in a return call it will stop in the 'back frame' for the user) + info.pydev_step_stop = frame + self.set_trace_for_frame_and_parents(frame) + else: + # No back frame?!? -- this happens in jython when we have some frame created from an awt event + # (the previous frame would be the awt event, but this doesn't make part of 'jython', only 'java') + # so, if we're doing a step return in this situation, it's the same as just making it run + info.pydev_step_stop = None + info.pydev_original_step_cmd = -1 + info.pydev_step_cmd = -1 + info.pydev_state = STATE_RUN + + if PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING: + info.pydev_use_scoped_step_frame = False + if info.pydev_step_cmd in ( + CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE, + CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE + ): + # i.e.: We're stepping: check if the stepping should be scoped (i.e.: in ipython + # each line is executed separately in a new frame, in which case we need to consider + # the next line as if it was still in the same frame). + f = frame.f_back + if f and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[1]: + f = f.f_back + if f and f.f_code.co_name == PYDEVD_IPYTHON_CONTEXT[2]: + info.pydev_use_scoped_step_frame = True + pydev_log.info('Using (ipython) scoped stepping.') + del f + + del frame + cmd = self.cmd_factory.make_thread_run_message(get_current_thread_id(thread), info.pydev_step_cmd) + self.writer.add_command(cmd) + + with CustomFramesContainer.custom_frames_lock: + # The ones that remained on last_running must now be removed. + for frame_id in from_this_thread: + # print('Removing created frame: %s' % (frame_id,)) + self.writer.add_command(self.cmd_factory.make_thread_killed_message(frame_id)) + + return keep_suspended + + def do_stop_on_unhandled_exception(self, thread, frame, frames_byid, arg): + pydev_log.debug("We are stopping in unhandled exception.") + try: + add_exception_to_frame(frame, arg) + self.send_caught_exception_stack(thread, arg, id(frame)) + try: + self.set_suspend(thread, CMD_ADD_EXCEPTION_BREAK) + self.do_wait_suspend(thread, frame, 'exception', arg, EXCEPTION_TYPE_UNHANDLED) + except: + self.send_caught_exception_stack_proceeded(thread) + except: + pydev_log.exception("We've got an error while stopping in unhandled exception: %s.", arg[0]) + finally: + remove_exception_from_frame(frame) + frame = None + + def set_trace_for_frame_and_parents(self, frame, **kwargs): + disable = kwargs.pop('disable', False) + assert not kwargs + + while frame is not None: + # Don't change the tracing on debugger-related files + file_type = self.get_file_type(frame) + + if file_type is None: + if disable: + pydev_log.debug('Disable tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name) + if frame.f_trace is not None and frame.f_trace is not NO_FTRACE: + frame.f_trace = NO_FTRACE + + elif frame.f_trace is not self.trace_dispatch: + pydev_log.debug('Set tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name) + frame.f_trace = self.trace_dispatch + else: + pydev_log.debug('SKIP set tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name) + + frame = frame.f_back + + del frame + + def _create_pydb_command_thread(self): + curr_pydb_command_thread = self.py_db_command_thread + if curr_pydb_command_thread is not None: + curr_pydb_command_thread.do_kill_pydev_thread() + + new_pydb_command_thread = self.py_db_command_thread = PyDBCommandThread(self) + new_pydb_command_thread.start() + + def _create_check_output_thread(self): + curr_output_checker_thread = self.check_alive_thread + if curr_output_checker_thread is not None: + curr_output_checker_thread.do_kill_pydev_thread() + + check_alive_thread = self.check_alive_thread = CheckAliveThread(self) + check_alive_thread.start() + + def start_auxiliary_daemon_threads(self): + self._create_pydb_command_thread() + self._create_check_output_thread() + + def __wait_for_threads_to_finish(self, timeout): + try: + with self._wait_for_threads_to_finish_called_lock: + wait_for_threads_to_finish_called = self._wait_for_threads_to_finish_called + self._wait_for_threads_to_finish_called = True + + if wait_for_threads_to_finish_called: + # Make sure that we wait for the previous call to be finished. + self._wait_for_threads_to_finish_called_event.wait(timeout=timeout) + else: + try: + + def get_pydb_daemon_threads_to_wait(): + pydb_daemon_threads = set(self.created_pydb_daemon_threads) + pydb_daemon_threads.discard(self.check_alive_thread) + pydb_daemon_threads.discard(threading.current_thread()) + return pydb_daemon_threads + + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads waiting for pydb daemon threads to finish") + started_at = time.time() + # Note: we wait for all except the check_alive_thread (which is not really a daemon + # thread and it can call this method itself). + while time.time() < started_at + timeout: + if len(get_pydb_daemon_threads_to_wait()) == 0: + break + time.sleep(1 / 10.) + else: + thread_names = [t.name for t in get_pydb_daemon_threads_to_wait()] + if thread_names: + pydev_log.debug("The following pydb threads may not have finished correctly: %s", + ', '.join(thread_names)) + finally: + self._wait_for_threads_to_finish_called_event.set() + except: + pydev_log.exception() + + def dispose_and_kill_all_pydevd_threads(self, wait=True, timeout=.5): + ''' + When this method is called we finish the debug session, terminate threads + and if this was registered as the global instance, unregister it -- afterwards + it should be possible to create a new instance and set as global to start + a new debug session. + + :param bool wait: + If True we'll wait for the threads to be actually finished before proceeding + (based on the available timeout). + Note that this must be thread-safe and if one thread is waiting the other thread should + also wait. + ''' + try: + back_frame = sys._getframe().f_back + pydev_log.debug( + 'PyDB.dispose_and_kill_all_pydevd_threads (called from: File "%s", line %s, in %s)', + back_frame.f_code.co_filename, back_frame.f_lineno, back_frame.f_code.co_name + ) + back_frame = None + with self._disposed_lock: + disposed = self.pydb_disposed + self.pydb_disposed = True + + if disposed: + if wait: + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads (already disposed - wait)") + self.__wait_for_threads_to_finish(timeout) + else: + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads (already disposed - no wait)") + return + + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads (first call)") + + # Wait until a time when there are no commands being processed to kill the threads. + started_at = time.time() + while time.time() < started_at + timeout: + with self._main_lock: + writer = self.writer + if writer is None or writer.empty(): + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads no commands being processed.") + break + else: + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads timed out waiting for writer to be empty.") + + pydb_daemon_threads = set(self.created_pydb_daemon_threads) + for t in pydb_daemon_threads: + if hasattr(t, 'do_kill_pydev_thread'): + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads killing thread: %s", t) + t.do_kill_pydev_thread() + + if wait: + self.__wait_for_threads_to_finish(timeout) + else: + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads: no wait") + + py_db = get_global_debugger() + if py_db is self: + set_global_debugger(None) + except: + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads: exception") + try: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 3: + pydev_log.exception() + except: + pass + finally: + pydev_log.debug("PyDB.dispose_and_kill_all_pydevd_threads: finished") + + def prepare_to_run(self): + ''' Shared code to prepare debugging by installing traces and registering threads ''' + self.patch_threads() + self.start_auxiliary_daemon_threads() + + def patch_threads(self): + try: + # not available in jython! + threading.settrace(self.trace_dispatch) # for all future threads + except: + pass + + from _pydev_bundle.pydev_monkey import patch_thread_modules + patch_thread_modules() + + def run(self, file, globals=None, locals=None, is_module=False, set_trace=True): + module_name = None + entry_point_fn = '' + if is_module: + # When launching with `python -m `, python automatically adds + # an empty path to the PYTHONPATH which resolves files in the current + # directory, so, depending how pydevd itself is launched, we may need + # to manually add such an entry to properly resolve modules in the + # current directory (see: https://github.com/Microsoft/ptvsd/issues/1010). + if '' not in sys.path: + sys.path.insert(0, '') + file, _, entry_point_fn = file.partition(':') + module_name = file + filename = get_fullname(file) + if filename is None: + mod_dir = get_package_dir(module_name) + if mod_dir is None: + sys.stderr.write("No module named %s\n" % file) + return + else: + filename = get_fullname("%s.__main__" % module_name) + if filename is None: + sys.stderr.write("No module named %s\n" % file) + return + else: + file = filename + else: + file = filename + mod_dir = os.path.dirname(filename) + main_py = os.path.join(mod_dir, '__main__.py') + main_pyc = os.path.join(mod_dir, '__main__.pyc') + if filename.endswith('__init__.pyc'): + if os.path.exists(main_pyc): + filename = main_pyc + elif os.path.exists(main_py): + filename = main_py + elif filename.endswith('__init__.py'): + if os.path.exists(main_pyc) and not os.path.exists(main_py): + filename = main_pyc + elif os.path.exists(main_py): + filename = main_py + + sys.argv[0] = filename + + if os.path.isdir(file): + new_target = os.path.join(file, '__main__.py') + if os.path.isfile(new_target): + file = new_target + + m = None + if globals is None: + m = save_main_module(file, 'pydevd') + globals = m.__dict__ + try: + globals['__builtins__'] = __builtins__ + except NameError: + pass # Not there on Jython... + + if locals is None: + locals = globals + + # Predefined (writable) attributes: __name__ is the module's name; + # __doc__ is the module's documentation string, or None if unavailable; + # __file__ is the pathname of the file from which the module was loaded, + # if it was loaded from a file. The __file__ attribute is not present for + # C modules that are statically linked into the interpreter; for extension modules + # loaded dynamically from a shared library, it is the pathname of the shared library file. + + # I think this is an ugly hack, bug it works (seems to) for the bug that says that sys.path should be the same in + # debug and run. + if sys.path[0] != '' and m is not None and m.__file__.startswith(sys.path[0]): + # print >> sys.stderr, 'Deleting: ', sys.path[0] + del sys.path[0] + + if not is_module: + # now, the local directory has to be added to the pythonpath + # sys.path.insert(0, os.getcwd()) + # Changed: it's not the local directory, but the directory of the file launched + # The file being run must be in the pythonpath (even if it was not before) + sys.path.insert(0, os.path.split(os_path_abspath(file))[0]) + + if set_trace: + self.wait_for_ready_to_run() + + # call prepare_to_run when we already have all information about breakpoints + self.prepare_to_run() + + t = threadingCurrentThread() + thread_id = get_current_thread_id(t) + + if self.thread_analyser is not None: + wrap_threads() + self.thread_analyser.set_start_time(cur_time()) + send_concurrency_message("threading_event", 0, t.name, thread_id, "thread", "start", file, 1, None, parent=thread_id) + + if self.asyncio_analyser is not None: + # we don't have main thread in asyncio graph, so we should add a fake event + send_concurrency_message("asyncio_event", 0, "Task", "Task", "thread", "stop", file, 1, frame=None, parent=None) + + try: + if INTERACTIVE_MODE_AVAILABLE: + self.init_gui_support() + except: + pydev_log.exception("Matplotlib support in debugger failed") + + if hasattr(sys, 'exc_clear'): + # we should clean exception information in Python 2, before user's code execution + sys.exc_clear() + + # Notify that the main thread is created. + self.notify_thread_created(thread_id, t) + + # Note: important: set the tracing right before calling _exec. + if set_trace: + self.enable_tracing() + + return self._exec(is_module, entry_point_fn, module_name, file, globals, locals) + + def _exec(self, is_module, entry_point_fn, module_name, file, globals, locals): + ''' + This function should have frames tracked by unhandled exceptions (the `_exec` name is important). + ''' + if not is_module: + globals = pydevd_runpy.run_path(file, globals, '__main__') + else: + # treat ':' as a separator between module and entry point function + # if there is no entry point we run we same as with -m switch. Otherwise we perform + # an import and execute the entry point + if entry_point_fn: + mod = __import__(module_name, level=0, fromlist=[entry_point_fn], globals=globals, locals=locals) + func = getattr(mod, entry_point_fn) + func() + else: + # Run with the -m switch + globals = pydevd_runpy._run_module_as_main(module_name, alter_argv=False) + return globals + + def wait_for_commands(self, globals): + self._activate_gui_if_needed() + + thread = threading.current_thread() + from _pydevd_bundle import pydevd_frame_utils + frame = pydevd_frame_utils.Frame(None, -1, pydevd_frame_utils.FCode("Console", + os.path.abspath(os.path.dirname(__file__))), globals, globals) + thread_id = get_current_thread_id(thread) + self.add_fake_frame(thread_id, id(frame), frame) + + cmd = self.cmd_factory.make_show_console_message(self, thread_id, frame) + if self.writer is not None: + self.writer.add_command(cmd) + + while True: + if self.gui_in_use: + # call input hooks if only GUI is in use + self._call_input_hook() + self.process_internal_commands() + time.sleep(0.01) + + +class IDAPMessagesListener(object): + + def before_send(self, message_as_dict): + ''' + Called just before a message is sent to the IDE. + + :type message_as_dict: dict + ''' + + def after_receive(self, message_as_dict): + ''' + Called just after a message is received from the IDE. + + :type message_as_dict: dict + ''' + + +def add_dap_messages_listener(dap_messages_listener): + ''' + Adds a listener for the DAP (debug adapter protocol) messages. + + :type dap_messages_listener: IDAPMessagesListener + + :note: messages from the xml backend are not notified through this API. + + :note: the notifications are sent from threads and they are not synchronized (so, + it's possible that a message is sent and received from different threads at the same time). + ''' + py_db = get_global_debugger() + if py_db is None: + raise AssertionError('PyDB is still not setup.') + + py_db.add_dap_messages_listener(dap_messages_listener) + + +def send_json_message(msg): + ''' + API to send some custom json message. + + :param dict|pydevd_schema.BaseSchema msg: + The custom message to be sent. + + :return bool: + True if the message was added to the queue to be sent and False otherwise. + ''' + py_db = get_global_debugger() + if py_db is None: + return False + + writer = py_db.writer + if writer is None: + return False + + cmd = NetCommand(-1, 0, msg, is_json=True) + writer.add_command(cmd) + return True + + +def enable_qt_support(qt_support_mode): + from _pydev_bundle import pydev_monkey_qt + pydev_monkey_qt.patch_qt(qt_support_mode) + + +def start_dump_threads_thread(filename_template, timeout, recurrent): + ''' + Helper to dump threads after a timeout. + + :param filename_template: + A template filename, such as 'c:/temp/thread_dump_%s.txt', where the %s will + be replaced by the time for the dump. + :param timeout: + The timeout (in seconds) for the dump. + :param recurrent: + If True we'll keep on doing thread dumps. + ''' + assert filename_template.count('%s') == 1, \ + 'Expected one %%s to appear in: %s' % (filename_template,) + + def _threads_on_timeout(): + try: + while True: + time.sleep(timeout) + filename = filename_template % (time.time(),) + try: + os.makedirs(os.path.dirname(filename)) + except Exception: + pass + with open(filename, 'w') as stream: + dump_threads(stream) + if not recurrent: + return + except Exception: + pydev_log.exception() + + t = threading.Thread(target=_threads_on_timeout) + mark_as_pydevd_daemon_thread(t) + t.start() + + +def dump_threads(stream=None): + ''' + Helper to dump thread info (default is printing to stderr). + ''' + pydevd_utils.dump_threads(stream) + + +def usage(doExit=0): + sys.stdout.write('Usage:\n') + sys.stdout.write('pydevd.py --port N [(--client hostname) | --server] --file executable [file_options]\n') + if doExit: + sys.exit(0) + + +def _init_stdout_redirect(): + pydevd_io.redirect_stream_to_pydb_io_messages(std='stdout') + + +def _init_stderr_redirect(): + pydevd_io.redirect_stream_to_pydb_io_messages(std='stderr') + + +def _enable_attach( + address, + dont_trace_start_patterns=(), + dont_trace_end_patterns=(), + patch_multiprocessing=False, + access_token=None, + client_access_token=None, + ): + ''' + Starts accepting connections at the given host/port. The debugger will not be initialized nor + configured, it'll only start accepting connections (and will have the tracing setup in this + thread). + + Meant to be used with the DAP (Debug Adapter Protocol) with _wait_for_attach(). + + :param address: (host, port) + :type address: tuple(str, int) + ''' + host = address[0] + port = int(address[1]) + + if SetupHolder.setup is not None: + if port != SetupHolder.setup['port']: + raise AssertionError('Unable to listen in port: %s (already listening in port: %s)' % (port, SetupHolder.setup['port'])) + settrace( + host=host, + port=port, + suspend=False, + wait_for_ready_to_run=False, + block_until_connected=False, + dont_trace_start_patterns=dont_trace_start_patterns, + dont_trace_end_patterns=dont_trace_end_patterns, + patch_multiprocessing=patch_multiprocessing, + access_token=access_token, + client_access_token=client_access_token, + ) + + py_db = get_global_debugger() + py_db.wait_for_server_socket_ready() + return py_db._server_socket_name + + +def _wait_for_attach(cancel=None): + ''' + Meant to be called after _enable_attach() -- the current thread will only unblock after a + connection is in place and the DAP (Debug Adapter Protocol) sends the ConfigurationDone + request. + ''' + py_db = get_global_debugger() + if py_db is None: + raise AssertionError('Debugger still not created. Please use _enable_attach() before using _wait_for_attach().') + + py_db.block_until_configuration_done(cancel=cancel) + + +def _is_attached(): + ''' + Can be called any time to check if the connection was established and the DAP (Debug Adapter Protocol) has sent + the ConfigurationDone request. + ''' + py_db = get_global_debugger() + return (py_db is not None) and py_db.is_attached() + + +#======================================================================================================================= +# settrace +#======================================================================================================================= +def settrace( + host=None, + stdout_to_server=False, + stderr_to_server=False, + port=5678, + suspend=True, + trace_only_current_thread=False, + overwrite_prev_trace=False, + patch_multiprocessing=False, + stop_at_frame=None, + block_until_connected=True, + wait_for_ready_to_run=True, + dont_trace_start_patterns=(), + dont_trace_end_patterns=(), + access_token=None, + client_access_token=None, + notify_stdin=True, + **kwargs + ): + '''Sets the tracing function with the pydev debug function and initializes needed facilities. + + :param host: the user may specify another host, if the debug server is not in the same machine (default is the local + host) + + :param stdout_to_server: when this is true, the stdout is passed to the debug server + + :param stderr_to_server: when this is true, the stderr is passed to the debug server + so that they are printed in its console and not in this process console. + + :param port: specifies which port to use for communicating with the server (note that the server must be started + in the same port). @note: currently it's hard-coded at 5678 in the client + + :param suspend: whether a breakpoint should be emulated as soon as this function is called. + + :param trace_only_current_thread: determines if only the current thread will be traced or all current and future + threads will also have the tracing enabled. + + :param overwrite_prev_trace: deprecated + + :param patch_multiprocessing: if True we'll patch the functions which create new processes so that launched + processes are debugged. + + :param stop_at_frame: if passed it'll stop at the given frame, otherwise it'll stop in the function which + called this method. + + :param wait_for_ready_to_run: if True settrace will block until the ready_to_run flag is set to True, + otherwise, it'll set ready_to_run to True and this function won't block. + + Note that if wait_for_ready_to_run == False, there are no guarantees that the debugger is synchronized + with what's configured in the client (IDE), the only guarantee is that when leaving this function + the debugger will be already connected. + + :param dont_trace_start_patterns: if set, then any path that starts with one fo the patterns in the collection + will not be traced + + :param dont_trace_end_patterns: if set, then any path that ends with one fo the patterns in the collection + will not be traced + + :param access_token: token to be sent from the client (i.e.: IDE) to the debugger when a connection + is established (verified by the debugger). + + :param client_access_token: token to be sent from the debugger to the client (i.e.: IDE) when + a connection is established (verified by the client). + + :param notify_stdin: + If True sys.stdin will be patched to notify the client when a message is requested + from the IDE. This is done so that when reading the stdin the client is notified. + Clients may need this to know when something that is being written should be interpreted + as an input to the process or as a command to be evaluated. + Note that parallel-python has issues with this (because it tries to assert that sys.stdin + is of a given type instead of just checking that it has what it needs). + ''' + + stdout_to_server = stdout_to_server or kwargs.get('stdoutToServer', False) # Backward compatibility + stderr_to_server = stderr_to_server or kwargs.get('stderrToServer', False) # Backward compatibility + + # Internal use (may be used to set the setup info directly for subprocesess). + __setup_holder__ = kwargs.get('__setup_holder__') + + with _set_trace_lock: + _locked_settrace( + host, + stdout_to_server, + stderr_to_server, + port, + suspend, + trace_only_current_thread, + patch_multiprocessing, + stop_at_frame, + block_until_connected, + wait_for_ready_to_run, + dont_trace_start_patterns, + dont_trace_end_patterns, + access_token, + client_access_token, + __setup_holder__=__setup_holder__, + notify_stdin=notify_stdin, + ) + + +_set_trace_lock = ForkSafeLock() + + +def _locked_settrace( + host, + stdout_to_server, + stderr_to_server, + port, + suspend, + trace_only_current_thread, + patch_multiprocessing, + stop_at_frame, + block_until_connected, + wait_for_ready_to_run, + dont_trace_start_patterns, + dont_trace_end_patterns, + access_token, + client_access_token, + __setup_holder__, + notify_stdin, + ): + if patch_multiprocessing: + try: + from _pydev_bundle import pydev_monkey + except: + pass + else: + pydev_monkey.patch_new_process_functions() + + if host is None: + from _pydev_bundle import pydev_localhost + host = pydev_localhost.get_localhost() + + global _global_redirect_stdout_to_server + global _global_redirect_stderr_to_server + + py_db = get_global_debugger() + if __setup_holder__: + SetupHolder.setup = __setup_holder__ + if py_db is None: + py_db = PyDB() + pydevd_vm_type.setup_type() + + if SetupHolder.setup is None: + setup = { + 'client': host, # dispatch expects client to be set to the host address when server is False + 'server': False, + 'port': int(port), + 'multiprocess': patch_multiprocessing, + 'skip-notify-stdin': not notify_stdin, + } + SetupHolder.setup = setup + + if access_token is not None: + py_db.authentication.access_token = access_token + SetupHolder.setup['access-token'] = access_token + if client_access_token is not None: + py_db.authentication.client_access_token = client_access_token + SetupHolder.setup['client-access-token'] = client_access_token + + if block_until_connected: + py_db.connect(host, port) # Note: connect can raise error. + else: + # Create a dummy writer and wait for the real connection. + py_db.writer = WriterThread(NULL, py_db, terminate_on_socket_close=False) + py_db.create_wait_for_connection_thread() + + if dont_trace_start_patterns or dont_trace_end_patterns: + PyDevdAPI().set_dont_trace_start_end_patterns(py_db, dont_trace_start_patterns, dont_trace_end_patterns) + + _global_redirect_stdout_to_server = stdout_to_server + _global_redirect_stderr_to_server = stderr_to_server + + if _global_redirect_stdout_to_server: + _init_stdout_redirect() + + if _global_redirect_stderr_to_server: + _init_stderr_redirect() + + if notify_stdin: + patch_stdin() + + t = threadingCurrentThread() + additional_info = set_additional_thread_info(t) + + if not wait_for_ready_to_run: + py_db.ready_to_run = True + + py_db.wait_for_ready_to_run() + py_db.start_auxiliary_daemon_threads() + + try: + if INTERACTIVE_MODE_AVAILABLE: + py_db.init_gui_support() + except: + pydev_log.exception("Matplotlib support in debugger failed") + + if trace_only_current_thread: + py_db.enable_tracing() + else: + # Trace future threads. + py_db.patch_threads() + + py_db.enable_tracing(py_db.trace_dispatch, apply_to_all_threads=True) + + # As this is the first connection, also set tracing for any untraced threads + py_db.set_tracing_for_untraced_contexts() + + py_db.set_trace_for_frame_and_parents(get_frame().f_back) + + with CustomFramesContainer.custom_frames_lock: # @UndefinedVariable + for _frameId, custom_frame in CustomFramesContainer.custom_frames.items(): + py_db.set_trace_for_frame_and_parents(custom_frame.frame) + + else: + # ok, we're already in debug mode, with all set, so, let's just set the break + if access_token is not None: + py_db.authentication.access_token = access_token + if client_access_token is not None: + py_db.authentication.client_access_token = client_access_token + + py_db.set_trace_for_frame_and_parents(get_frame().f_back) + + t = threadingCurrentThread() + additional_info = set_additional_thread_info(t) + + if trace_only_current_thread: + py_db.enable_tracing() + else: + # Trace future threads. + py_db.patch_threads() + py_db.enable_tracing(py_db.trace_dispatch, apply_to_all_threads=True) + + # Suspend as the last thing after all tracing is in place. + if suspend: + if stop_at_frame is not None: + # If the step was set we have to go to run state and + # set the proper frame for it to stop. + additional_info.pydev_state = STATE_RUN + additional_info.pydev_original_step_cmd = CMD_STEP_OVER + additional_info.pydev_step_cmd = CMD_STEP_OVER + additional_info.pydev_step_stop = stop_at_frame + additional_info.suspend_type = PYTHON_SUSPEND + else: + # Ask to break as soon as possible. + py_db.set_suspend(t, CMD_SET_BREAK) + + +def stoptrace(): + pydev_log.debug("pydevd.stoptrace()") + pydevd_tracing.restore_sys_set_trace_func() + sys.settrace(None) + try: + # not available in jython! + threading.settrace(None) # for all future threads + except: + pass + + from _pydev_bundle.pydev_monkey import undo_patch_thread_modules + undo_patch_thread_modules() + + # Either or both standard streams can be closed at this point, + # in which case flush() will fail. + try: + sys.stdout.flush() + except: + pass + try: + sys.stderr.flush() + except: + pass + + py_db = get_global_debugger() + + if py_db is not None: + py_db.dispose_and_kill_all_pydevd_threads() + + +class Dispatcher(object): + + def __init__(self): + self.port = None + + def connect(self, host, port): + self.host = host + self.port = port + self.client = start_client(self.host, self.port) + self.reader = DispatchReader(self) + self.reader.pydev_do_not_trace = False # we run reader in the same thread so we don't want to loose tracing + self.reader.run() + + def close(self): + try: + self.reader.do_kill_pydev_thread() + except: + pass + + +class DispatchReader(ReaderThread): + + def __init__(self, dispatcher): + self.dispatcher = dispatcher + + ReaderThread.__init__( + self, + get_global_debugger(), + self.dispatcher.client, + PyDevJsonCommandProcessor=PyDevJsonCommandProcessor, + process_net_command=process_net_command, + ) + + @overrides(ReaderThread._on_run) + def _on_run(self): + dummy_thread = threading.current_thread() + dummy_thread.is_pydev_daemon_thread = False + return ReaderThread._on_run(self) + + @overrides(PyDBDaemonThread.do_kill_pydev_thread) + def do_kill_pydev_thread(self): + if not self._kill_received: + ReaderThread.do_kill_pydev_thread(self) + try: + self.sock.shutdown(SHUT_RDWR) + except: + pass + try: + self.sock.close() + except: + pass + + def process_command(self, cmd_id, seq, text): + if cmd_id == 99: + self.dispatcher.port = int(text) + self._kill_received = True + + +DISPATCH_APPROACH_NEW_CONNECTION = 1 # Used by PyDev +DISPATCH_APPROACH_EXISTING_CONNECTION = 2 # Used by PyCharm +DISPATCH_APPROACH = DISPATCH_APPROACH_NEW_CONNECTION + + +def dispatch(): + setup = SetupHolder.setup + host = setup['client'] + port = setup['port'] + if DISPATCH_APPROACH == DISPATCH_APPROACH_EXISTING_CONNECTION: + dispatcher = Dispatcher() + try: + dispatcher.connect(host, port) + port = dispatcher.port + finally: + dispatcher.close() + return host, port + + +def settrace_forked(setup_tracing=True): + ''' + When creating a fork from a process in the debugger, we need to reset the whole debugger environment! + ''' + from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder + py_db = GlobalDebuggerHolder.global_dbg + if py_db is not None: + py_db.created_pydb_daemon_threads = {} # Just making sure we won't touch those (paused) threads. + py_db = None + + GlobalDebuggerHolder.global_dbg = None + threading.current_thread().additional_info = None + + # Make sure that we keep the same access tokens for subprocesses started through fork. + setup = SetupHolder.setup + if setup is None: + setup = {} + else: + # i.e.: Get the ppid at this point as it just changed. + # If we later do an exec() it should remain the same ppid. + setup[pydevd_constants.ARGUMENT_PPID] = PyDevdAPI().get_ppid() + access_token = setup.get('access-token') + client_access_token = setup.get('client-access-token') + + if setup_tracing: + from _pydevd_frame_eval.pydevd_frame_eval_main import clear_thread_local_info + host, port = dispatch() + + import pydevd_tracing + pydevd_tracing.restore_sys_set_trace_func() + + if setup_tracing: + if port is not None: + custom_frames_container_init() + + if clear_thread_local_info is not None: + clear_thread_local_info() + + settrace( + host, + port=port, + suspend=False, + trace_only_current_thread=False, + overwrite_prev_trace=True, + patch_multiprocessing=True, + access_token=access_token, + client_access_token=client_access_token, + ) + + +@contextmanager +def skip_subprocess_arg_patch(): + ''' + May be used to skip the monkey-patching that pydevd does to + skip changing arguments to embed the debugger into child processes. + + i.e.: + + with pydevd.skip_subprocess_arg_patch(): + subprocess.call(...) + ''' + from _pydev_bundle import pydev_monkey + with pydev_monkey.skip_subprocess_arg_patch(): + yield + + +def add_dont_terminate_child_pid(pid): + ''' + May be used to ask pydevd to skip the termination of some process + when it's asked to terminate (debug adapter protocol only). + + :param int pid: + The pid to be ignored. + + i.e.: + + process = subprocess.Popen(...) + pydevd.add_dont_terminate_child_pid(process.pid) + ''' + py_db = get_global_debugger() + if py_db is not None: + py_db.dont_terminate_child_pids.add(pid) + + +class SetupHolder: + + setup = None + + +def apply_debugger_options(setup_options): + """ + + :type setup_options: dict[str, bool] + """ + default_options = {'save-signatures': False, 'qt-support': ''} + default_options.update(setup_options) + setup_options = default_options + + debugger = get_global_debugger() + if setup_options['save-signatures']: + if pydevd_vm_type.get_vm_type() == pydevd_vm_type.PydevdVmType.JYTHON: + sys.stderr.write("Collecting run-time type information is not supported for Jython\n") + else: + # Only import it if we're going to use it! + from _pydevd_bundle.pydevd_signature import SignatureFactory + debugger.signature_factory = SignatureFactory() + + if setup_options['qt-support']: + enable_qt_support(setup_options['qt-support']) + + +@call_only_once +def patch_stdin(): + _internal_patch_stdin(None, sys, getpass_mod) + + +def _internal_patch_stdin(py_db=None, sys=None, getpass_mod=None): + ''' + Note: don't use this function directly, use `patch_stdin()` instead. + (this function is only meant to be used on test-cases to avoid patching the actual globals). + ''' + # Patch stdin so that we notify when readline() is called. + original_sys_stdin = sys.stdin + debug_console_stdin = DebugConsoleStdIn(py_db, original_sys_stdin) + sys.stdin = debug_console_stdin + + _original_getpass = getpass_mod.getpass + + @functools.wraps(_original_getpass) + def getpass(*args, **kwargs): + with DebugConsoleStdIn.notify_input_requested(debug_console_stdin): + try: + curr_stdin = sys.stdin + if curr_stdin is debug_console_stdin: + sys.stdin = original_sys_stdin + return _original_getpass(*args, **kwargs) + finally: + sys.stdin = curr_stdin + + getpass_mod.getpass = getpass + +# Dispatch on_debugger_modules_loaded here, after all primary py_db modules are loaded + + +for handler in pydevd_extension_utils.extensions_of_type(DebuggerEventHandler): + handler.on_debugger_modules_loaded(debugger_version=__version__) + + +def log_to(log_file:str, log_level=3) -> None: + ''' + In pydevd it's possible to log by setting the following environment variables: + + PYDEVD_DEBUG=1 (sets the default log level to 3 along with other default options) + PYDEVD_DEBUG_FILE= + + Note that the file will have the pid of the process added to it (so, logging to + /path/to/file.log would actually start logging to /path/to/file..log -- if subprocesses are + logged, each new subprocess will have the logging set to its own pid). + + Usually setting the environment variable is preferred as it'd log information while + pydevd is still doing its imports and not just after this method is called, but on + cases where this is hard to do this function may be called to set the tracing after + pydevd itself is already imported. + ''' + pydev_log.log_to(log_file, log_level) + + +def _log_initial_info(): + pydev_log.debug("Initial arguments: %s", (sys.argv,)) + pydev_log.debug("Current pid: %s", os.getpid()) + pydev_log.debug("Using cython: %s", USING_CYTHON) + pydev_log.debug("Using frame eval: %s", USING_FRAME_EVAL) + pydev_log.debug("Using gevent mode: %s / imported gevent module support: %s", SUPPORT_GEVENT, bool(pydevd_gevent_integration)) + + +#======================================================================================================================= +# main +#======================================================================================================================= +def main(): + + # parse the command line. --file is our last argument that is required + _log_initial_info() + try: + from _pydevd_bundle.pydevd_command_line_handling import process_command_line + setup = process_command_line(sys.argv) + SetupHolder.setup = setup + except ValueError: + pydev_log.exception() + usage(1) + + log_trace_level = setup.get('log-level') + + # Note: the logging info could've been changed (this would happen if this is a + # subprocess and the value in the environment variable does not match the value in the + # argument because the user used `pydevd.log_to` instead of supplying the environment + # variable). If this is the case, update the logging info and re-log some information + # in the new target. + new_debug_file = setup.get('log-file') + if new_debug_file and DebugInfoHolder.PYDEVD_DEBUG_FILE != new_debug_file: + # The debug file can't be set directly, we need to use log_to() so that the a + # new stream is actually created for the new file. + log_to(new_debug_file, log_trace_level if log_trace_level is not None else 3) + _log_initial_info() # The redirection info just changed, log it again. + + elif log_trace_level is not None: + # The log file was not specified + DebugInfoHolder.DEBUG_TRACE_LEVEL = log_trace_level + + if setup['print-in-debugger-startup']: + try: + pid = ' (pid: %s)' % os.getpid() + except: + pid = '' + sys.stderr.write("pydev debugger: starting%s\n" % pid) + + pydev_log.debug("Executing file %s", setup['file']) + pydev_log.debug("arguments: %s", (sys.argv,)) + + pydevd_vm_type.setup_type(setup.get('vm_type', None)) + + port = setup['port'] + host = setup['client'] + f = setup['file'] + fix_app_engine_debug = False + + debugger = get_global_debugger() + if debugger is None: + debugger = PyDB() + + try: + from _pydev_bundle import pydev_monkey + except: + pass # Not usable on jython 2.1 + else: + if setup['multiprocess']: # PyDev + pydev_monkey.patch_new_process_functions() + + elif setup['multiproc']: # PyCharm + pydev_log.debug("Started in multiproc mode\n") + global DISPATCH_APPROACH + DISPATCH_APPROACH = DISPATCH_APPROACH_EXISTING_CONNECTION + + dispatcher = Dispatcher() + try: + dispatcher.connect(host, port) + if dispatcher.port is not None: + port = dispatcher.port + pydev_log.debug("Received port %d\n", port) + pydev_log.info("pydev debugger: process %d is connecting\n" % os.getpid()) + + try: + pydev_monkey.patch_new_process_functions() + except: + pydev_log.exception("Error patching process functions.") + else: + pydev_log.critical("pydev debugger: couldn't get port for new debug process.") + finally: + dispatcher.close() + else: + try: + pydev_monkey.patch_new_process_functions_with_warning() + except: + pydev_log.exception("Error patching process functions.") + + # Only do this patching if we're not running with multiprocess turned on. + if f.find('dev_appserver.py') != -1: + if os.path.basename(f).startswith('dev_appserver.py'): + appserver_dir = os.path.dirname(f) + version_file = os.path.join(appserver_dir, 'VERSION') + if os.path.exists(version_file): + try: + stream = open(version_file, 'r') + try: + for line in stream.read().splitlines(): + line = line.strip() + if line.startswith('release:'): + line = line[8:].strip() + version = line.replace('"', '') + version = version.split('.') + if int(version[0]) > 1: + fix_app_engine_debug = True + + elif int(version[0]) == 1: + if int(version[1]) >= 7: + # Only fix from 1.7 onwards + fix_app_engine_debug = True + break + finally: + stream.close() + except: + pydev_log.exception() + + try: + # In the default run (i.e.: run directly on debug mode), we try to patch stackless as soon as possible + # on a run where we have a remote debug, we may have to be more careful because patching stackless means + # that if the user already had a stackless.set_schedule_callback installed, he'd loose it and would need + # to call it again (because stackless provides no way of getting the last function which was registered + # in set_schedule_callback). + # + # So, ideally, if there's an application using stackless and the application wants to use the remote debugger + # and benefit from stackless debugging, the application itself must call: + # + # import pydevd_stackless + # pydevd_stackless.patch_stackless() + # + # itself to be able to benefit from seeing the tasklets created before the remote debugger is attached. + from _pydevd_bundle import pydevd_stackless + pydevd_stackless.patch_stackless() + except: + # It's ok not having stackless there... + try: + if hasattr(sys, 'exc_clear'): + sys.exc_clear() # the exception information should be cleaned in Python 2 + except: + pass + + is_module = setup['module'] + if not setup['skip-notify-stdin']: + patch_stdin() + + if setup[pydevd_constants.ARGUMENT_JSON_PROTOCOL]: + PyDevdAPI().set_protocol(debugger, 0, JSON_PROTOCOL) + + elif setup[pydevd_constants.ARGUMENT_HTTP_JSON_PROTOCOL]: + PyDevdAPI().set_protocol(debugger, 0, HTTP_JSON_PROTOCOL) + + elif setup[pydevd_constants.ARGUMENT_HTTP_PROTOCOL]: + PyDevdAPI().set_protocol(debugger, 0, pydevd_constants.HTTP_PROTOCOL) + + elif setup[pydevd_constants.ARGUMENT_QUOTED_LINE_PROTOCOL]: + PyDevdAPI().set_protocol(debugger, 0, pydevd_constants.QUOTED_LINE_PROTOCOL) + + access_token = setup['access-token'] + if access_token: + debugger.authentication.access_token = access_token + + client_access_token = setup['client-access-token'] + if client_access_token: + debugger.authentication.client_access_token = client_access_token + + if fix_app_engine_debug: + sys.stderr.write("pydev debugger: google app engine integration enabled\n") + curr_dir = os.path.dirname(__file__) + app_engine_startup_file = os.path.join(curr_dir, 'pydev_app_engine_debug_startup.py') + + sys.argv.insert(1, '--python_startup_script=' + app_engine_startup_file) + import json + setup['pydevd'] = __file__ + sys.argv.insert(2, '--python_startup_args=%s' % json.dumps(setup),) + sys.argv.insert(3, '--automatic_restart=no') + sys.argv.insert(4, '--max_module_instances=1') + + # Run the dev_appserver + debugger.run(setup['file'], None, None, is_module, set_trace=False) + else: + if setup['save-threading']: + debugger.thread_analyser = ThreadingLogger() + if setup['save-asyncio']: + debugger.asyncio_analyser = AsyncioLogger() + + apply_debugger_options(setup) + + try: + debugger.connect(host, port) + except: + sys.stderr.write("Could not connect to %s: %s\n" % (host, port)) + pydev_log.exception() + sys.exit(1) + + globals = debugger.run(setup['file'], None, None, is_module) + + if setup['cmd-line']: + debugger.wait_for_commands(globals) + + +if __name__ == '__main__': + main() diff --git a/pydevd_attach_to_process/README.txt b/pydevd_attach_to_process/README.txt new file mode 100644 index 0000000..6bf2f03 --- /dev/null +++ b/pydevd_attach_to_process/README.txt @@ -0,0 +1,27 @@ +This folder contains the utilities to attach a target process to the pydev debugger. + +The main module to be called for the attach is: + +attach_pydevd.py + +it should be called as; + +python attach_pydevd.py --port 5678 --pid 1234 + +Note that the client is responsible for having a remote debugger alive in the given port for the attach to work. + + +The binaries are now compiled at: +- https://github.com/fabioz/PyDev.Debugger.binaries/actions +(after generation the binaries are copied to this repo) + + +To copy: +cd /D X:\PyDev.Debugger +"C:\Program Files\7-Zip\7z" e C:\Users\fabio\Downloads\win_binaries.zip -oX:\PyDev.Debugger\pydevd_attach_to_process * -r -y +"C:\Program Files\7-Zip\7z" e C:\Users\fabio\Downloads\linux_binaries.zip -oX:\PyDev.Debugger\pydevd_attach_to_process * -r -y +"C:\Program Files\7-Zip\7z" e C:\Users\fabio\Downloads\mac_binaries.zip -oX:\PyDev.Debugger\pydevd_attach_to_process * -r -y +git add *.exe +git add *.dll +git add *.dylib +git add *.so diff --git a/pydevd_attach_to_process/_always_live_program.py b/pydevd_attach_to_process/_always_live_program.py new file mode 100644 index 0000000..6369508 --- /dev/null +++ b/pydevd_attach_to_process/_always_live_program.py @@ -0,0 +1,32 @@ +import sys +import struct +print('Executable: %s' % sys.executable) +import os +def loop_in_thread(): + while True: + import time + time.sleep(.5) + sys.stdout.write('#') + sys.stdout.flush() + +import threading +threading.Thread(target=loop_in_thread).start() + + +def is_python_64bit(): + return (struct.calcsize('P') == 8) + +print('Is 64: %s' % is_python_64bit()) + +if __name__ == '__main__': + print('pid:%s' % (os.getpid())) + i = 0 + while True: + i += 1 + import time + time.sleep(.5) + sys.stdout.write('.') + sys.stdout.flush() + if i % 40 == 0: + sys.stdout.write('\n') + sys.stdout.flush() diff --git a/pydevd_attach_to_process/_check.py b/pydevd_attach_to_process/_check.py new file mode 100644 index 0000000..2dbeafe --- /dev/null +++ b/pydevd_attach_to_process/_check.py @@ -0,0 +1,2 @@ +import add_code_to_python_process +print(add_code_to_python_process.run_python_code(3736, "print(20)", connect_debugger_tracing=False)) diff --git a/pydevd_attach_to_process/_test_attach_to_process.py b/pydevd_attach_to_process/_test_attach_to_process.py new file mode 100644 index 0000000..daeee93 --- /dev/null +++ b/pydevd_attach_to_process/_test_attach_to_process.py @@ -0,0 +1,9 @@ +import subprocess +import sys +print(sys.executable) + +if __name__ == '__main__': + p = subprocess.Popen([sys.executable, '-u', '_always_live_program.py']) + import attach_pydevd + attach_pydevd.main(attach_pydevd.process_command_line(['--pid', str(p.pid), '--protocol', 'http'])) + p.wait() diff --git a/pydevd_attach_to_process/_test_attach_to_process_linux.py b/pydevd_attach_to_process/_test_attach_to_process_linux.py new file mode 100644 index 0000000..842e71a --- /dev/null +++ b/pydevd_attach_to_process/_test_attach_to_process_linux.py @@ -0,0 +1,74 @@ +''' +This module is just for testing concepts. It should be erased later on. + +Experiments: + +// gdb -p 4957 +// call dlopen("/home/fabioz/Desktop/dev/PyDev.Debugger/pydevd_attach_to_process/linux/attach_linux.so", 2) +// call dlsym($1, "hello") +// call hello() + + +// call open("/home/fabioz/Desktop/dev/PyDev.Debugger/pydevd_attach_to_process/linux/attach_linux.so", 2) +// call mmap(0, 6672, 1 | 2 | 4, 1, 3 , 0) +// add-symbol-file +// cat /proc/pid/maps + +// call dlopen("/home/fabioz/Desktop/dev/PyDev.Debugger/pydevd_attach_to_process/linux/attach_linux.so", 1|8) +// call dlsym($1, "hello") +// call hello() +''' + +import subprocess +import sys +import os +import time + +if __name__ == '__main__': + + linux_dir = os.path.join(os.path.dirname(__file__), 'linux') + os.chdir(linux_dir) + so_location = os.path.join(linux_dir, 'attach_linux.so') + try: + os.remove(so_location) + except: + pass + subprocess.call('g++ -shared -o attach_linux.so -fPIC -nostartfiles attach_linux.c'.split()) + print('Finished compiling') + assert os.path.exists('/home/fabioz/Desktop/dev/PyDev.Debugger/pydevd_attach_to_process/linux/attach_linux.so') + os.chdir(os.path.dirname(linux_dir)) +# import attach_pydevd +# attach_pydevd.main(attach_pydevd.process_command_line(['--pid', str(p.pid)])) + p = subprocess.Popen([sys.executable, '-u', '_always_live_program.py']) + print('Size of file: %s' % (os.stat(so_location).st_size)) + + # (gdb) set architecture + # Requires an argument. Valid arguments are i386, i386:x86-64, i386:x64-32, i8086, i386:intel, i386:x86-64:intel, i386:x64-32:intel, i386:nacl, i386:x86-64:nacl, i386:x64-32:nacl, auto. + + cmd = [ + 'gdb', + '--pid', + str(p.pid), + '--batch', + ] + + arch = 'i386:x86-64' + if arch: + cmd.extend(["--eval-command='set architecture %s'" % arch]) + + cmd.extend([ + "--eval-command='call dlopen(\"/home/fabioz/Desktop/dev/PyDev.Debugger/pydevd_attach_to_process/linux/attach_linux.so\", 2)'", + "--eval-command='call (int)DoAttach(1, \"print(\\\"check11111check\\\")\", 0)'", + # "--eval-command='call (int)SetSysTraceFunc(1, 0)'", -- never call this way, always use "--command='...gdb_threads_settrace.py'", + # So that threads are all stopped! + ]) + + print(' '.join(cmd)) + time.sleep(.5) + env = os.environ.copy() + env.pop('PYTHONIOENCODING', None) + env.pop('PYTHONPATH', None) + p2 = subprocess.call(' '.join(cmd), env=env, shell=True) + + time.sleep(1) + p.kill() diff --git a/pydevd_attach_to_process/add_code_to_python_process.py b/pydevd_attach_to_process/add_code_to_python_process.py new file mode 100644 index 0000000..462feae --- /dev/null +++ b/pydevd_attach_to_process/add_code_to_python_process.py @@ -0,0 +1,606 @@ +r''' +Copyright: Brainwy Software Ltda. + +License: EPL. +============= + +Works for Windows by using an executable that'll inject a dll to a process and call a function. + +Note: https://github.com/fabioz/winappdbg is used just to determine if the target process is 32 or 64 bits. + +Works for Linux relying on gdb. + +Limitations: +============ + + Linux: + ------ + + 1. It possible that ptrace is disabled: /etc/sysctl.d/10-ptrace.conf + + Note that even enabling it in /etc/sysctl.d/10-ptrace.conf (i.e.: making the + ptrace_scope=0), it's possible that we need to run the application that'll use ptrace (or + gdb in this case) as root (so, we must sudo the python which'll run this module). + + 2. It currently doesn't work in debug builds (i.e.: python_d) + + +Other implementations: +- pyrasite.com: + GPL + Windows/linux (in Linux it also uses gdb to connect -- although specifics are different as we use a dll to execute + code with other threads stopped). It's Windows approach is more limited because it doesn't seem to deal properly with + Python 3 if threading is disabled. + +- https://github.com/google/pyringe: + Apache v2. + Only linux/Python 2. + +- http://pytools.codeplex.com: + Apache V2 + Windows Only (but supports mixed mode debugging) + Our own code relies heavily on a part of it: http://pytools.codeplex.com/SourceControl/latest#Python/Product/PyDebugAttach/PyDebugAttach.cpp + to overcome some limitations of attaching and running code in the target python executable on Python 3. + See: attach.cpp + +Linux: References if we wanted to use a pure-python debugger: + https://bitbucket.org/haypo/python-ptrace/ + http://stackoverflow.com/questions/7841573/how-to-get-an-error-message-for-errno-value-in-python + Jugaad: + https://www.defcon.org/images/defcon-19/dc-19-presentations/Jakhar/DEFCON-19-Jakhar-Jugaad-Linux-Thread-Injection.pdf + https://github.com/aseemjakhar/jugaad + +Something else (general and not Python related): +- http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces + +Other references: +- https://github.com/haypo/faulthandler +- http://nedbatchelder.com/text/trace-function.html +- https://github.com/python-git/python/blob/master/Python/sysmodule.c (sys_settrace) +- https://github.com/python-git/python/blob/master/Python/ceval.c (PyEval_SetTrace) +- https://github.com/python-git/python/blob/master/Python/thread.c (PyThread_get_key_value) + + +To build the dlls needed on windows, visual studio express 13 was used (see compile_dll.bat) + +See: attach_pydevd.py to attach the pydev debugger to a running python process. +''' + +# Note: to work with nasm compiling asm to code and decompiling to see asm with shellcode: +# x:\nasm\nasm-2.07-win32\nasm-2.07\nasm.exe +# nasm.asm&x:\nasm\nasm-2.07-win32\nasm-2.07\ndisasm.exe -b arch nasm +import ctypes +import os +import struct +import subprocess +import sys +import time +from contextlib import contextmanager +import platform +import traceback + +try: + TimeoutError = TimeoutError # @ReservedAssignment +except NameError: + + class TimeoutError(RuntimeError): # @ReservedAssignment + pass + + +@contextmanager +def _create_win_event(name): + from winappdbg.win32.kernel32 import CreateEventA, WaitForSingleObject, CloseHandle + + manual_reset = False # i.e.: after someone waits it, automatically set to False. + initial_state = False + if not isinstance(name, bytes): + name = name.encode('utf-8') + event = CreateEventA(None, manual_reset, initial_state, name) + if not event: + raise ctypes.WinError() + + class _WinEvent(object): + + def wait_for_event_set(self, timeout=None): + ''' + :param timeout: in seconds + ''' + if timeout is None: + timeout = 0xFFFFFFFF + else: + timeout = int(timeout * 1000) + ret = WaitForSingleObject(event, timeout) + if ret in (0, 0x80): + return True + elif ret == 0x102: + # Timed out + return False + else: + raise ctypes.WinError() + + try: + yield _WinEvent() + finally: + CloseHandle(event) + + +IS_WINDOWS = sys.platform == 'win32' +IS_LINUX = sys.platform in ('linux', 'linux2') +IS_MAC = sys.platform == 'darwin' + + +def is_python_64bit(): + return (struct.calcsize('P') == 8) + + +def get_target_filename(is_target_process_64=None, prefix=None, extension=None): + # Note: we have an independent (and similar -- but not equal) version of this method in + # `pydevd_tracing.py` which should be kept synchronized with this one (we do a copy + # because the `pydevd_attach_to_process` is mostly independent and shouldn't be imported in the + # debugger -- the only situation where it's imported is if the user actually does an attach to + # process, through `attach_pydevd.py`, but this should usually be called from the IDE directly + # and not from the debugger). + libdir = os.path.dirname(__file__) + + if is_target_process_64 is None: + if IS_WINDOWS: + # i.e.: On windows the target process could have a different bitness (32bit is emulated on 64bit). + raise AssertionError("On windows it's expected that the target bitness is specified.") + + # For other platforms, just use the the same bitness of the process we're running in. + is_target_process_64 = is_python_64bit() + + arch = '' + if IS_WINDOWS: + # prefer not using platform.machine() when possible (it's a bit heavyweight as it may + # spawn a subprocess). + arch = os.environ.get("PROCESSOR_ARCHITEW6432", os.environ.get('PROCESSOR_ARCHITECTURE', '')) + + if not arch: + arch = platform.machine() + if not arch: + print('platform.machine() did not return valid value.') # This shouldn't happen... + return None + + if IS_WINDOWS: + if not extension: + extension = '.dll' + suffix_64 = 'amd64' + suffix_32 = 'x86' + + elif IS_LINUX: + if not extension: + extension = '.so' + suffix_64 = 'amd64' + suffix_32 = 'x86' + + elif IS_MAC: + if not extension: + extension = '.dylib' + suffix_64 = 'x86_64' + suffix_32 = 'x86' + + else: + print('Unable to attach to process in platform: %s', sys.platform) + return None + + if arch.lower() not in ('amd64', 'x86', 'x86_64', 'i386', 'x86'): + # We don't support this processor by default. Still, let's support the case where the + # user manually compiled it himself with some heuristics. + # + # Ideally the user would provide a library in the format: "attach_." + # based on the way it's currently compiled -- see: + # - windows/compile_windows.bat + # - linux_and_mac/compile_linux.sh + # - linux_and_mac/compile_mac.sh + + try: + found = [name for name in os.listdir(libdir) if name.startswith('attach_') and name.endswith(extension)] + except: + print('Error listing dir: %s' % (libdir,)) + traceback.print_exc() + return None + + if prefix: + expected_name = prefix + arch + extension + expected_name_linux = prefix + 'linux_' + arch + extension + else: + # Default is looking for the attach_ / attach_linux + expected_name = 'attach_' + arch + extension + expected_name_linux = 'attach_linux_' + arch + extension + + filename = None + if expected_name in found: # Heuristic: user compiled with "attach_." + filename = os.path.join(libdir, expected_name) + + elif IS_LINUX and expected_name_linux in found: # Heuristic: user compiled with "attach_linux_." + filename = os.path.join(libdir, expected_name_linux) + + elif len(found) == 1: # Heuristic: user removed all libraries and just left his own lib. + filename = os.path.join(libdir, found[0]) + + else: # Heuristic: there's one additional library which doesn't seem to be our own. Find the odd one. + filtered = [name for name in found if not name.endswith((suffix_64 + extension, suffix_32 + extension))] + if len(filtered) == 1: # If more than one is available we can't be sure... + filename = os.path.join(libdir, found[0]) + + if filename is None: + print( + 'Unable to attach to process in arch: %s (did not find %s in %s).' % ( + arch, expected_name, libdir + ) + ) + return None + + print('Using %s in arch: %s.' % (filename, arch)) + + else: + if is_target_process_64: + suffix = suffix_64 + else: + suffix = suffix_32 + + if not prefix: + # Default is looking for the attach_ / attach_linux + if IS_WINDOWS or IS_MAC: # just the extension changes + prefix = 'attach_' + elif IS_LINUX: + prefix = 'attach_linux_' # historically it has a different name + else: + print('Unable to attach to process in platform: %s' % (sys.platform,)) + return None + + filename = os.path.join(libdir, '%s%s%s' % (prefix, suffix, extension)) + + if not os.path.exists(filename): + print('Expected: %s to exist.' % (filename,)) + return None + + return filename + + +def run_python_code_windows(pid, python_code, connect_debugger_tracing=False, show_debug_info=0): + assert '\'' not in python_code, 'Having a single quote messes with our command.' + from winappdbg.process import Process + if not isinstance(python_code, bytes): + python_code = python_code.encode('utf-8') + + process = Process(pid) + bits = process.get_bits() + is_target_process_64 = bits == 64 + + # Note: this restriction no longer applies (we create a process with the proper bitness from + # this process so that the attach works). + # if is_target_process_64 != is_python_64bit(): + # raise RuntimeError("The architecture of the Python used to connect doesn't match the architecture of the target.\n" + # "Target 64 bits: %s\n" + # "Current Python 64 bits: %s" % (is_target_process_64, is_python_64bit())) + + with _acquire_mutex('_pydevd_pid_attach_mutex_%s' % (pid,), 10): + print('--- Connecting to %s bits target (current process is: %s) ---' % (bits, 64 if is_python_64bit() else 32)) + + with _win_write_to_shared_named_memory(python_code, pid): + + target_executable = get_target_filename(is_target_process_64, 'inject_dll_', '.exe') + if not target_executable: + raise RuntimeError('Could not find expected .exe file to inject dll in attach to process.') + + target_dll = get_target_filename(is_target_process_64) + if not target_dll: + raise RuntimeError('Could not find expected .dll file in attach to process.') + + print('\n--- Injecting attach dll: %s into pid: %s ---' % (os.path.basename(target_dll), pid)) + args = [target_executable, str(pid), target_dll] + subprocess.check_call(args) + + # Now, if the first injection worked, go on to the second which will actually + # run the code. + target_dll_run_on_dllmain = get_target_filename(is_target_process_64, 'run_code_on_dllmain_', '.dll') + if not target_dll_run_on_dllmain: + raise RuntimeError('Could not find expected .dll in attach to process.') + + with _create_win_event('_pydevd_pid_event_%s' % (pid,)) as event: + print('\n--- Injecting run code dll: %s into pid: %s ---' % (os.path.basename(target_dll_run_on_dllmain), pid)) + args = [target_executable, str(pid), target_dll_run_on_dllmain] + subprocess.check_call(args) + + if not event.wait_for_event_set(10): + print('Timeout error: the attach may not have completed.') + print('--- Finished dll injection ---\n') + + return 0 + + +@contextmanager +def _acquire_mutex(mutex_name, timeout): + ''' + Only one process may be attaching to a pid, so, create a system mutex + to make sure this holds in practice. + ''' + from winappdbg.win32.kernel32 import CreateMutex, GetLastError, CloseHandle + from winappdbg.win32.defines import ERROR_ALREADY_EXISTS + + initial_time = time.time() + while True: + mutex = CreateMutex(None, True, mutex_name) + acquired = GetLastError() != ERROR_ALREADY_EXISTS + if acquired: + break + if time.time() - initial_time > timeout: + raise TimeoutError('Unable to acquire mutex to make attach before timeout.') + time.sleep(.2) + + try: + yield + finally: + CloseHandle(mutex) + + +@contextmanager +def _win_write_to_shared_named_memory(python_code, pid): + # Use the definitions from winappdbg when possible. + from winappdbg.win32 import defines + from winappdbg.win32.kernel32 import ( + CreateFileMapping, + MapViewOfFile, + CloseHandle, + UnmapViewOfFile, + ) + + memmove = ctypes.cdll.msvcrt.memmove + memmove.argtypes = [ + ctypes.c_void_p, + ctypes.c_void_p, + defines.SIZE_T, + ] + memmove.restype = ctypes.c_void_p + + # Note: BUFSIZE must be the same from run_code_in_memory.hpp + BUFSIZE = 2048 + assert isinstance(python_code, bytes) + assert len(python_code) > 0, 'Python code must not be empty.' + # Note: -1 so that we're sure we'll add a \0 to the end. + assert len(python_code) < BUFSIZE - 1, 'Python code must have at most %s bytes (found: %s)' % (BUFSIZE - 1, len(python_code)) + + python_code += b'\0' * (BUFSIZE - len(python_code)) + assert python_code.endswith(b'\0') + + INVALID_HANDLE_VALUE = -1 + PAGE_READWRITE = 0x4 + FILE_MAP_WRITE = 0x2 + filemap = CreateFileMapping( + INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, BUFSIZE, u"__pydevd_pid_code_to_run__%s" % (pid,)) + + if filemap == INVALID_HANDLE_VALUE or filemap is None: + raise Exception("Failed to create named file mapping (ctypes: CreateFileMapping): %s" % (filemap,)) + try: + view = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0) + if not view: + raise Exception("Failed to create view of named file mapping (ctypes: MapViewOfFile).") + + try: + memmove(view, python_code, BUFSIZE) + yield + finally: + UnmapViewOfFile(view) + finally: + CloseHandle(filemap) + + +def run_python_code_linux(pid, python_code, connect_debugger_tracing=False, show_debug_info=0): + assert '\'' not in python_code, 'Having a single quote messes with our command.' + + target_dll = get_target_filename() + if not target_dll: + raise RuntimeError('Could not find .so for attach to process.') + target_dll_name = os.path.splitext(os.path.basename(target_dll))[0] + + # Note: we currently don't support debug builds + is_debug = 0 + # Note that the space in the beginning of each line in the multi-line is important! + cmd = [ + 'gdb', + '--nw', # no gui interface + '--nh', # no ~/.gdbinit + '--nx', # no .gdbinit +# '--quiet', # no version number on startup + '--pid', + str(pid), + '--batch', +# '--batch-silent', + ] + + # PYDEVD_GDB_SCAN_SHARED_LIBRARIES can be a list of strings with the shared libraries + # which should be scanned by default to make the attach to process (i.e.: libdl, libltdl, libc, libfreebl3). + # + # The default is scanning all shared libraries, but on some cases this can be in the 20-30 + # seconds range for some corner cases. + # See: https://github.com/JetBrains/intellij-community/pull/1608 + # + # By setting PYDEVD_GDB_SCAN_SHARED_LIBRARIES (to a comma-separated string), it's possible to + # specify just a few libraries to be loaded (not many are needed for the attach, + # but it can be tricky to pre-specify for all Linux versions as this may change + # across different versions). + # + # See: https://github.com/microsoft/debugpy/issues/762#issuecomment-947103844 + # for a comment that explains the basic steps on how to discover what should be available + # in each case (mostly trying different versions based on the output of gdb). + # + # The upside is that for cases when too many libraries are loaded the attach could be slower + # and just specifying the one that is actually needed for the attach can make it much faster. + # + # The downside is that it may be dependent on the Linux version being attached to (which is the + # reason why this is no longer done by default -- see: https://github.com/microsoft/debugpy/issues/882). + gdb_load_shared_libraries = os.environ.get('PYDEVD_GDB_SCAN_SHARED_LIBRARIES', '').strip() + if gdb_load_shared_libraries: + cmd.extend(["--init-eval-command='set auto-solib-add off'"]) # Don't scan all libraries. + + for lib in gdb_load_shared_libraries.split(','): + lib = lib.strip() + cmd.extend(["--eval-command='sharedlibrary %s'" % (lib,)]) # Scan the specified library + + cmd.extend(["--eval-command='set scheduler-locking off'"]) # If on we'll deadlock. + + # Leave auto by default (it should do the right thing as we're attaching to a process in the + # current host). + cmd.extend(["--eval-command='set architecture auto'"]) + + cmd.extend([ + "--eval-command='call (void*)dlopen(\"%s\", 2)'" % target_dll, + "--eval-command='sharedlibrary %s'" % target_dll_name, + "--eval-command='call (int)DoAttach(%s, \"%s\", %s)'" % ( + is_debug, python_code, show_debug_info) + ]) + + # print ' '.join(cmd) + + env = os.environ.copy() + # Remove the PYTHONPATH (if gdb has a builtin Python it could fail if we + # have the PYTHONPATH for a different python version or some forced encoding). + env.pop('PYTHONIOENCODING', None) + env.pop('PYTHONPATH', None) + print('Running: %s' % (' '.join(cmd))) + p = subprocess.Popen( + ' '.join(cmd), + shell=True, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + print('Running gdb in target process.') + out, err = p.communicate() + print('stdout: %s' % (out,)) + print('stderr: %s' % (err,)) + return out, err + + +def find_helper_script(filedir, script_name): + target_filename = os.path.join(filedir, 'linux_and_mac', script_name) + target_filename = os.path.normpath(target_filename) + if not os.path.exists(target_filename): + raise RuntimeError('Could not find helper script: %s' % target_filename) + + return target_filename + + +def run_python_code_mac(pid, python_code, connect_debugger_tracing=False, show_debug_info=0): + assert '\'' not in python_code, 'Having a single quote messes with our command.' + + target_dll = get_target_filename() + if not target_dll: + raise RuntimeError('Could not find .dylib for attach to process.') + + libdir = os.path.dirname(__file__) + lldb_prepare_file = find_helper_script(libdir, 'lldb_prepare.py') + # Note: we currently don't support debug builds + + is_debug = 0 + # Note that the space in the beginning of each line in the multi-line is important! + cmd = [ + 'lldb', + '--no-lldbinit', # Do not automatically parse any '.lldbinit' files. + # '--attach-pid', + # str(pid), + # '--arch', + # arch, + '--script-language', + 'Python' + # '--batch-silent', + ] + + cmd.extend([ + "-o 'process attach --pid %d'" % pid, + "-o 'command script import \"%s\"'" % (lldb_prepare_file,), + "-o 'load_lib_and_attach \"%s\" %s \"%s\" %s'" % (target_dll, + is_debug, python_code, show_debug_info), + ]) + + cmd.extend([ + "-o 'process detach'", + "-o 'script import os; os._exit(1)'", + ]) + + # print ' '.join(cmd) + + env = os.environ.copy() + # Remove the PYTHONPATH (if gdb has a builtin Python it could fail if we + # have the PYTHONPATH for a different python version or some forced encoding). + env.pop('PYTHONIOENCODING', None) + env.pop('PYTHONPATH', None) + print('Running: %s' % (' '.join(cmd))) + p = subprocess.Popen( + ' '.join(cmd), + shell=True, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + print('Running lldb in target process.') + out, err = p.communicate() + print('stdout: %s' % (out,)) + print('stderr: %s' % (err,)) + return out, err + + +if IS_WINDOWS: + run_python_code = run_python_code_windows +elif IS_MAC: + run_python_code = run_python_code_mac +elif IS_LINUX: + run_python_code = run_python_code_linux +else: + + def run_python_code(*args, **kwargs): + print('Unable to attach to process in platform: %s', sys.platform) + + +def test(): + print('Running with: %s' % (sys.executable,)) + code = ''' +import os, time, sys +print(os.getpid()) +#from threading import Thread +#Thread(target=str).start() +if __name__ == '__main__': + while True: + time.sleep(.5) + sys.stdout.write('.\\n') + sys.stdout.flush() +''' + + p = subprocess.Popen([sys.executable, '-u', '-c', code]) + try: + code = 'print("It worked!")\n' + + # Real code will be something as: + # code = '''import sys;sys.path.append(r'X:\winappdbg-code\examples'); import imported;''' + run_python_code(p.pid, python_code=code) + print('\nRun a 2nd time...\n') + run_python_code(p.pid, python_code=code) + + time.sleep(3) + finally: + p.kill() + + +def main(args): + # Otherwise, assume the first parameter is the pid and anything else is code to be executed + # in the target process. + pid = int(args[0]) + del args[0] + python_code = ';'.join(args) + + # Note: on Linux the python code may not have a single quote char: ' + run_python_code(pid, python_code) + + +if __name__ == '__main__': + args = sys.argv[1:] + if not args: + print('Expected pid and Python code to execute in target process.') + else: + if '--test' == args[0]: + test() + else: + main(args) + diff --git a/pydevd_attach_to_process/attach_pydevd.py b/pydevd_attach_to_process/attach_pydevd.py new file mode 100644 index 0000000..48b7489 --- /dev/null +++ b/pydevd_attach_to_process/attach_pydevd.py @@ -0,0 +1,73 @@ +import sys +import os + + +def process_command_line(argv): + setup = {} + setup['port'] = 5678 # Default port for PyDev remote debugger + setup['pid'] = 0 + setup['host'] = '127.0.0.1' + setup['protocol'] = '' + + i = 0 + while i < len(argv): + if argv[i] == '--port': + del argv[i] + setup['port'] = int(argv[i]) + del argv[i] + + elif argv[i] == '--pid': + del argv[i] + setup['pid'] = int(argv[i]) + del argv[i] + + elif argv[i] == '--host': + del argv[i] + setup['host'] = argv[i] + del argv[i] + + elif argv[i] == '--protocol': + del argv[i] + setup['protocol'] = argv[i] + del argv[i] + + if not setup['pid']: + sys.stderr.write('Expected --pid to be passed.\n') + sys.exit(1) + return setup + + +def main(setup): + sys.path.append(os.path.dirname(__file__)) + import add_code_to_python_process + show_debug_info_on_target_process = 0 + + pydevd_dirname = os.path.dirname(os.path.dirname(__file__)) + + if sys.platform == 'win32': + setup['pythonpath'] = pydevd_dirname.replace('\\', '/') + setup['pythonpath2'] = os.path.dirname(__file__).replace('\\', '/') + python_code = '''import sys; +sys.path.append("%(pythonpath)s"); +sys.path.append("%(pythonpath2)s"); +import attach_script; +attach_script.attach(port=%(port)s, host="%(host)s", protocol="%(protocol)s"); +'''.replace('\r\n', '').replace('\r', '').replace('\n', '') + else: + setup['pythonpath'] = pydevd_dirname + setup['pythonpath2'] = os.path.dirname(__file__) + # We have to pass it a bit differently for gdb + python_code = '''import sys; +sys.path.append(\\\"%(pythonpath)s\\\"); +sys.path.append(\\\"%(pythonpath2)s\\\"); +import attach_script; +attach_script.attach(port=%(port)s, host=\\\"%(host)s\\\", protocol=\\\"%(protocol)s\\\"); +'''.replace('\r\n', '').replace('\r', '').replace('\n', '') + + python_code = python_code % setup + add_code_to_python_process.run_python_code( + setup['pid'], python_code, connect_debugger_tracing=True, show_debug_info=show_debug_info_on_target_process) + + +if __name__ == '__main__': + main(process_command_line(sys.argv[1:])) diff --git a/pydevd_attach_to_process/attach_script.py b/pydevd_attach_to_process/attach_script.py new file mode 100644 index 0000000..9c636a4 --- /dev/null +++ b/pydevd_attach_to_process/attach_script.py @@ -0,0 +1,184 @@ + + +def get_main_thread_instance(threading): + if hasattr(threading, 'main_thread'): + return threading.main_thread() + else: + # On Python 2 we don't really have an API to get the main thread, + # so, we just get it from the 'shutdown' bound method. + return threading._shutdown.im_self + + +def get_main_thread_id(unlikely_thread_id=None): + ''' + :param unlikely_thread_id: + Pass to mark some thread id as not likely the main thread. + + :return tuple(thread_id, critical_warning) + ''' + import sys + import os + + current_frames = sys._current_frames() + possible_thread_ids = [] + for thread_ident, frame in current_frames.items(): + while frame.f_back is not None: + frame = frame.f_back + + basename = os.path.basename(frame.f_code.co_filename) + if basename.endswith(('.pyc', '.pyo')): + basename = basename[:-1] + + if (frame.f_code.co_name, basename) in [ + ('_run_module_as_main', 'runpy.py'), + ('_run_module_as_main', ''), + ('run_module_as_main', 'runpy.py'), + ('run_module', 'runpy.py'), + ('run_path', 'runpy.py'), + ]: + # This is the case for python -m (this is an ideal match, so, + # let's return it). + return thread_ident, '' + + if frame.f_code.co_name == '': + if frame.f_globals.get('__name__') == '__main__': + possible_thread_ids.insert(0, thread_ident) # Add with higher priority + continue + + # Usually the main thread will be started in the , whereas others would + # be started in another place (but when Python is embedded, this may not be + # correct, so, just add to the available possibilities as we'll have to choose + # one if there are multiple). + possible_thread_ids.append(thread_ident) + + if len(possible_thread_ids) > 0: + if len(possible_thread_ids) == 1: + return possible_thread_ids[0], '' # Ideal: only one match + + while unlikely_thread_id in possible_thread_ids: + possible_thread_ids.remove(unlikely_thread_id) + + if len(possible_thread_ids) == 1: + return possible_thread_ids[0], '' # Ideal: only one match + + elif len(possible_thread_ids) > 1: + # Bad: we can't really be certain of anything at this point. + return possible_thread_ids[0], \ + 'Multiple thread ids found (%s). Choosing main thread id randomly (%s).' % ( + possible_thread_ids, possible_thread_ids[0]) + + # If we got here we couldn't discover the main thread id. + return None, 'Unable to discover main thread id.' + + +def fix_main_thread_id(on_warn=lambda msg:None, on_exception=lambda msg:None, on_critical=lambda msg:None): + # This means that we weren't able to import threading in the main thread (which most + # likely means that the main thread is paused or in some very long operation). + # In this case we'll import threading here and hotfix what may be wrong in the threading + # module (if we're on Windows where we create a thread to do the attach and on Linux + # we are not certain on which thread we're executing this code). + # + # The code below is a workaround for https://bugs.python.org/issue37416 + import sys + import threading + + try: + with threading._active_limbo_lock: + main_thread_instance = get_main_thread_instance(threading) + + if sys.platform == 'win32': + # On windows this code would be called in a secondary thread, so, + # the current thread is unlikely to be the main thread. + if hasattr(threading, '_get_ident'): + unlikely_thread_id = threading._get_ident() # py2 + else: + unlikely_thread_id = threading.get_ident() # py3 + else: + unlikely_thread_id = None + + main_thread_id, critical_warning = get_main_thread_id(unlikely_thread_id) + + if main_thread_id is not None: + main_thread_id_attr = '_ident' + if not hasattr(main_thread_instance, main_thread_id_attr): + main_thread_id_attr = '_Thread__ident' + assert hasattr(main_thread_instance, main_thread_id_attr) + + if main_thread_id != getattr(main_thread_instance, main_thread_id_attr): + # Note that we also have to reset the '_tstack_lock' for a regular lock. + # This is needed to avoid an error on shutdown because this lock is bound + # to the thread state and will be released when the secondary thread + # that initialized the lock is finished -- making an assert fail during + # process shutdown. + main_thread_instance._tstate_lock = threading._allocate_lock() + main_thread_instance._tstate_lock.acquire() + + # Actually patch the thread ident as well as the threading._active dict + # (we should have the _active_limbo_lock to do that). + threading._active.pop(getattr(main_thread_instance, main_thread_id_attr), None) + setattr(main_thread_instance, main_thread_id_attr, main_thread_id) + threading._active[getattr(main_thread_instance, main_thread_id_attr)] = main_thread_instance + + # Note: only import from pydevd after the patching is done (we want to do the minimum + # possible when doing that patching). + on_warn('The threading module was not imported by user code in the main thread. The debugger will attempt to work around https://bugs.python.org/issue37416.') + + if critical_warning: + on_critical('Issue found when debugger was trying to work around https://bugs.python.org/issue37416:\n%s' % (critical_warning,)) + except: + on_exception('Error patching main thread id.') + + +def attach(port, host, protocol=''): + try: + import sys + fix_main_thread = 'threading' not in sys.modules + + if fix_main_thread: + + def on_warn(msg): + from _pydev_bundle import pydev_log + pydev_log.warn(msg) + + def on_exception(msg): + from _pydev_bundle import pydev_log + pydev_log.exception(msg) + + def on_critical(msg): + from _pydev_bundle import pydev_log + pydev_log.critical(msg) + + fix_main_thread_id(on_warn=on_warn, on_exception=on_exception, on_critical=on_critical) + + else: + from _pydev_bundle import pydev_log # @Reimport + pydev_log.debug('The threading module is already imported by user code.') + + if protocol: + from _pydevd_bundle import pydevd_defaults + pydevd_defaults.PydevdCustomization.DEFAULT_PROTOCOL = protocol + + import pydevd + + # I.e.: disconnect/reset if already connected. + + pydevd.SetupHolder.setup = None + + py_db = pydevd.get_global_debugger() + if py_db is not None: + py_db.dispose_and_kill_all_pydevd_threads(wait=False) + + # pydevd.DebugInfoHolder.DEBUG_TRACE_LEVEL = 3 + pydevd.settrace( + port=port, + host=host, + stdoutToServer=True, + stderrToServer=True, + overwrite_prev_trace=True, + suspend=False, + trace_only_current_thread=False, + patch_multiprocessing=False, + ) + except: + import traceback + traceback.print_exc() diff --git a/pydevd_attach_to_process/common/py_custom_pyeval_settrace.hpp b/pydevd_attach_to_process/common/py_custom_pyeval_settrace.hpp new file mode 100644 index 0000000..510f916 --- /dev/null +++ b/pydevd_attach_to_process/common/py_custom_pyeval_settrace.hpp @@ -0,0 +1,193 @@ +#ifndef _PY_CUSTOM_PYEVAL_SETTRACE_HPP_ +#define _PY_CUSTOM_PYEVAL_SETTRACE_HPP_ + +#include "python.h" +#include "py_utils.hpp" +#include "py_custom_pyeval_settrace_common.hpp" +#include "py_custom_pyeval_settrace_310.hpp" +#include "py_custom_pyeval_settrace_311.hpp" + +// On Python 3.7 onwards the thread state is not kept in PyThread_set_key_value (rather +// it uses PyThread_tss_set using PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) +// and we don't have access to that key from here (thus, we can't use the previous approach which +// made CPython think that the current thread had the thread state where we wanted to set the tracing). +// +// So, the solution implemented here is not faking that change and reimplementing PyEval_SetTrace. +// The implementation is mostly the same from the one in CPython, but we have one shortcoming: +// +// When CPython sets the tracing for a thread it increments _Py_TracingPossible (actually +// _PyRuntime.ceval.tracing_possible). This implementation has one issue: it only works on +// deltas when the tracing is set (so, a settrace(func) will increase the _Py_TracingPossible global value and a +// settrace(None) will decrease it, but when a thread dies it's kept as is and is not decreased). +// -- as we don't currently have access to _PyRuntime we have to create a thread, set the tracing +// and let it die so that the count is increased (this is really hacky, but better than having +// to create a local copy of the whole _PyRuntime (defined in pystate.h with several inner structs) +// which would need to be kept up to date for each new CPython version just to increment that variable). + + + +/** + * This version is used in internalInitializeCustomPyEvalSetTrace->pyObject_FastCallDict on older + * versions of CPython (pre 3.7). + */ + static PyObject * + PyObject_FastCallDictCustom(PyObject* callback, PyObject *stack[3], int ignoredStackSizeAlways3, void* ignored) + { + PyObject *args = internalInitializeCustomPyEvalSetTrace->pyTuple_New(3); + PyObject *result; + + if (args == NULL) { + return NULL; + } + + IncRef(stack[0]); + IncRef(stack[1]); + IncRef(stack[2]); + + // I.e.: same thing as: PyTuple_SET_ITEM(args, 0, stack[0]); + reinterpret_cast(args)->ob_item[0] = stack[0]; + reinterpret_cast(args)->ob_item[1] = stack[1]; + reinterpret_cast(args)->ob_item[2] = stack[2]; + + /* call the Python-level function */ + result = internalInitializeCustomPyEvalSetTrace->pyEval_CallObjectWithKeywords(callback, args, (PyObject*)NULL); + + /* cleanup */ + DecRef(args, internalInitializeCustomPyEvalSetTrace->isDebug); + return result; +} + +static PyObject * +InternalCallTrampoline(PyObject* callback, + PyFrameObjectBaseUpTo39 *frame, int what, PyObject *arg) +{ + PyObject *result; + PyObject *stack[3]; + +// Note: this is commented out from CPython (we shouldn't need it and it adds a reasonable overhead). +// if (PyFrame_FastToLocalsWithError(frame) < 0) { +// return NULL; +// } +// + stack[0] = (PyObject *)frame; + stack[1] = InternalWhatstrings_37[what]; + stack[2] = (arg != NULL) ? arg : internalInitializeCustomPyEvalSetTrace->pyNone; + + + // Helpers to print info. + // printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[0]))); + // printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[1]))); + // printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[2]))); + // printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)callback))); + + // call the Python-level function + // result = _PyObject_FastCall(callback, stack, 3); + // + // Note that _PyObject_FastCall is actually a define: + // #define _PyObject_FastCall(func, args, nargs) _PyObject_FastCallDict((func), (args), (nargs), NULL) + + result = internalInitializeCustomPyEvalSetTrace->pyObject_FastCallDict(callback, stack, 3, NULL); + + +// Note: this is commented out from CPython (we shouldn't need it and it adds a reasonable overhead). +// PyFrame_LocalsToFast(frame, 1); + + if (result == NULL) { + internalInitializeCustomPyEvalSetTrace->pyTraceBack_Here(frame); + } + + return result; +} + +static int +InternalTraceTrampoline(PyObject *self, PyFrameObject *frameParam, + int what, PyObject *arg) +{ + PyObject *callback; + PyObject *result; + + PyFrameObjectBaseUpTo39 *frame = reinterpret_cast(frameParam); + + if (what == PyTrace_CALL){ + callback = self; + } else { + callback = frame->f_trace; + } + + if (callback == NULL){ + return 0; + } + + result = InternalCallTrampoline(callback, frame, what, arg); + if (result == NULL) { + // Note: calling the original sys.settrace here. + internalInitializeCustomPyEvalSetTrace->pyEval_SetTrace(NULL, NULL); + PyObject *temp_f_trace = frame->f_trace; + frame->f_trace = NULL; + if(temp_f_trace != NULL){ + DecRef(temp_f_trace, internalInitializeCustomPyEvalSetTrace->isDebug); + } + return -1; + } + if (result != internalInitializeCustomPyEvalSetTrace->pyNone) { + PyObject *tmp = frame->f_trace; + frame->f_trace = result; + DecRef(tmp, internalInitializeCustomPyEvalSetTrace->isDebug); + } + else { + DecRef(result, internalInitializeCustomPyEvalSetTrace->isDebug); + } + return 0; +} + +// Based on ceval.c (PyEval_SetTrace(Py_tracefunc func, PyObject *arg)) +template +void InternalPySetTrace_Template(T tstate, PyObjectHolder* traceFunc, bool isDebug) +{ + PyObject *temp = tstate->c_traceobj; + + // We can't increase _Py_TracingPossible. Everything else should be equal to CPython. + // runtime->ceval.tracing_possible += (func != NULL) - (tstate->c_tracefunc != NULL); + + PyObject *arg = traceFunc->ToPython(); + IncRef(arg); + tstate->c_tracefunc = NULL; + tstate->c_traceobj = NULL; + /* Must make sure that profiling is not ignored if 'temp' is freed */ + tstate->use_tracing = tstate->c_profilefunc != NULL; + if(temp != NULL){ + DecRef(temp, isDebug); + } + tstate->c_tracefunc = InternalTraceTrampoline; + tstate->c_traceobj = arg; + /* Flag that tracing or profiling is turned on */ + tstate->use_tracing = ((InternalTraceTrampoline != NULL) + || (tstate->c_profilefunc != NULL)); + +}; + + +void InternalPySetTrace(PyThreadState* curThread, PyObjectHolder* traceFunc, bool isDebug, PythonVersion version) +{ + if (PyThreadState_25_27::IsFor(version)) { + InternalPySetTrace_Template(reinterpret_cast(curThread), traceFunc, isDebug); + } else if (PyThreadState_30_33::IsFor(version)) { + InternalPySetTrace_Template(reinterpret_cast(curThread), traceFunc, isDebug); + } else if (PyThreadState_34_36::IsFor(version)) { + InternalPySetTrace_Template(reinterpret_cast(curThread), traceFunc, isDebug); + } else if (PyThreadState_37_38::IsFor(version)) { + InternalPySetTrace_Template(reinterpret_cast(curThread), traceFunc, isDebug); + } else if (PyThreadState_39::IsFor(version)) { + InternalPySetTrace_Template(reinterpret_cast(curThread), traceFunc, isDebug); + } else if (PyThreadState_310::IsFor(version)) { + // 3.10 has other changes on the actual algorithm (use_tracing is per-frame now), so, we have a full new version for it. + InternalPySetTrace_Template310(reinterpret_cast(curThread), traceFunc, isDebug); + } else if (PyThreadState_311::IsFor(version)) { + InternalPySetTrace_Template311(reinterpret_cast(curThread), traceFunc, isDebug); + } else { + printf("Unable to set trace to target thread with Python version: %d", version); + } +} + + +#endif //_PY_CUSTOM_PYEVAL_SETTRACE_HPP_ \ No newline at end of file diff --git a/pydevd_attach_to_process/common/py_custom_pyeval_settrace_310.hpp b/pydevd_attach_to_process/common/py_custom_pyeval_settrace_310.hpp new file mode 100644 index 0000000..d4fe89b --- /dev/null +++ b/pydevd_attach_to_process/common/py_custom_pyeval_settrace_310.hpp @@ -0,0 +1,113 @@ +#ifndef _PY_CUSTOM_PYEVAL_SETTRACE_310_HPP_ +#define _PY_CUSTOM_PYEVAL_SETTRACE_310_HPP_ + +#include "python.h" +#include "py_utils.hpp" + +static PyObject * +InternalCallTrampoline310(PyObject* callback, + PyFrameObject310 *frame, int what, PyObject *arg) +{ + PyObject *result; + PyObject *stack[3]; + +// Note: this is commented out from CPython (we shouldn't need it and it adds a reasonable overhead). +// if (PyFrame_FastToLocalsWithError(frame) < 0) { +// return NULL; +// } +// + stack[0] = (PyObject *)frame; + stack[1] = InternalWhatstrings_37[what]; + stack[2] = (arg != NULL) ? arg : internalInitializeCustomPyEvalSetTrace->pyNone; + + + // Helper to print info. + // printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[0]))); + // printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[1]))); + // printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[2]))); + // printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)callback))); + + result = internalInitializeCustomPyEvalSetTrace->pyObject_FastCallDict(callback, stack, 3, NULL); + +// Note: this is commented out from CPython (we shouldn't need it and it adds a reasonable overhead). +// PyFrame_LocalsToFast(frame, 1); + + if (result == NULL) { + internalInitializeCustomPyEvalSetTrace->pyTraceBack_Here(frame); + } + + return result; +} + +// See: static int trace_trampoline(PyObject *self, PyFrameObject *frame, int what, PyObject *arg) +// in: https://github.com/python/cpython/blob/3.10/Python/sysmodule.c +static int +InternalTraceTrampoline310(PyObject *self, PyFrameObject *frameParam, + int what, PyObject *arg) +{ + PyObject *callback; + PyObject *result; + + PyFrameObject310 *frame = reinterpret_cast(frameParam); + + if (what == PyTrace_CALL){ + callback = self; + } else { + callback = frame->f_trace; + } + + if (callback == NULL){ + return 0; + } + + result = InternalCallTrampoline310(callback, frame, what, arg); + if (result == NULL) { + // Note: calling the original sys.settrace here. + internalInitializeCustomPyEvalSetTrace->pyEval_SetTrace(NULL, NULL); + PyObject *temp_f_trace = frame->f_trace; + frame->f_trace = NULL; + if(temp_f_trace != NULL){ + DecRef(temp_f_trace, internalInitializeCustomPyEvalSetTrace->isDebug); + } + return -1; + } + if (result != internalInitializeCustomPyEvalSetTrace->pyNone) { + PyObject *tmp = frame->f_trace; + frame->f_trace = result; + DecRef(tmp, internalInitializeCustomPyEvalSetTrace->isDebug); + } + else { + DecRef(result, internalInitializeCustomPyEvalSetTrace->isDebug); + } + return 0; +} + +// Based on ceval.c (PyEval_SetTrace(Py_tracefunc func, PyObject *arg)) +// https://github.com/python/cpython/blob/3.10/Python/ceval.c +template +void InternalPySetTrace_Template310(T tstate, PyObjectHolder* traceFunc, bool isDebug) +{ + PyObject *temp = tstate->c_traceobj; + + PyObject *arg = traceFunc->ToPython(); + IncRef(arg); + tstate->c_tracefunc = NULL; + tstate->c_traceobj = NULL; + + // This is different (previously it was just: tstate->use_tracing, now + // this flag is per-frame). + tstate->cframe->use_tracing = tstate->c_profilefunc != NULL; + + if(temp != NULL){ + DecRef(temp, isDebug); + } + tstate->c_tracefunc = InternalTraceTrampoline310; + tstate->c_traceobj = arg; + /* Flag that tracing or profiling is turned on */ + tstate->cframe->use_tracing = ((InternalTraceTrampoline310 != NULL) + || (tstate->c_profilefunc != NULL)); + +}; + + +#endif //_PY_CUSTOM_PYEVAL_SETTRACE_310_HPP_ \ No newline at end of file diff --git a/pydevd_attach_to_process/common/py_custom_pyeval_settrace_311.hpp b/pydevd_attach_to_process/common/py_custom_pyeval_settrace_311.hpp new file mode 100644 index 0000000..d3086ad --- /dev/null +++ b/pydevd_attach_to_process/common/py_custom_pyeval_settrace_311.hpp @@ -0,0 +1,120 @@ +#ifndef _PY_CUSTOM_PYEVAL_SETTRACE_311_HPP_ +#define _PY_CUSTOM_PYEVAL_SETTRACE_311_HPP_ + +#include "python.h" +#include "py_utils.hpp" + +static PyObject * +InternalCallTrampoline311(PyObject* callback, + PyFrameObject311 *frame, int what, PyObject *arg) +{ + PyObject *result; + PyObject *stack[3]; + +// Note: this is commented out from CPython (we shouldn't need it and it adds a reasonable overhead). +// if (PyFrame_FastToLocalsWithError(frame) < 0) { +// return NULL; +// } +// + stack[0] = (PyObject *)frame; + stack[1] = InternalWhatstrings_37[what]; + stack[2] = (arg != NULL) ? arg : internalInitializeCustomPyEvalSetTrace->pyNone; + + + // Helper to print info. + //printf("--- start\n"); + //printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[0]))); + //printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[1]))); + //printf("%s\n", internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8(internalInitializeCustomPyEvalSetTrace->pyObject_Repr((PyObject *)stack[2]))); + //printf("--- end\n"); + + result = internalInitializeCustomPyEvalSetTrace->pyObject_FastCallDict(callback, stack, 3, NULL); + +// Note: this is commented out from CPython (we shouldn't need it and it adds a reasonable overhead). +// PyFrame_LocalsToFast(frame, 1); + + if (result == NULL) { + internalInitializeCustomPyEvalSetTrace->pyTraceBack_Here(frame); + } + + return result; +} + +// See: static int trace_trampoline(PyObject *self, PyFrameObject *frame, int what, PyObject *arg) +// in: https://github.com/python/cpython/blob/3.11/Python/sysmodule.c +static int +InternalTraceTrampoline311(PyObject *self, PyFrameObject *frameParam, + int what, PyObject *arg) +{ + PyObject *callback; + PyObject *result; + + PyFrameObject311 *frame = reinterpret_cast(frameParam); + + if (what == PyTrace_CALL){ + callback = self; + } else { + callback = frame->f_trace; + } + + if (callback == NULL){ + return 0; + } + + result = InternalCallTrampoline311(callback, frame, what, arg); + if (result == NULL) { + // Note: calling the original sys.settrace here. + internalInitializeCustomPyEvalSetTrace->pyEval_SetTrace(NULL, NULL); + PyObject *temp_f_trace = frame->f_trace; + frame->f_trace = NULL; + if(temp_f_trace != NULL){ + DecRef(temp_f_trace, internalInitializeCustomPyEvalSetTrace->isDebug); + } + return -1; + } + if (result != internalInitializeCustomPyEvalSetTrace->pyNone) { + PyObject *tmp = frame->f_trace; + frame->f_trace = result; + DecRef(tmp, internalInitializeCustomPyEvalSetTrace->isDebug); + } + else { + DecRef(result, internalInitializeCustomPyEvalSetTrace->isDebug); + } + return 0; +} + +// Based on ceval.c (PyEval_SetTrace(Py_tracefunc func, PyObject *arg)) +// https://github.com/python/cpython/blob/3.11/Python/ceval.c +template +void InternalPySetTrace_Template311(T tstate, PyObjectHolder* traceFunc, bool isDebug) +{ + PyObject *traceobj = tstate->c_traceobj; + + PyObject *arg = traceFunc->ToPython(); + IncRef(arg); + tstate->c_tracefunc = NULL; + tstate->c_traceobj = NULL; + + // This is different (previously it was just: tstate->use_tracing, now + // this flag is per-frame). + int use_tracing = (tstate->c_profilefunc != NULL); + + // Note: before 3.11 this was just 1 or 0, now it needs to be 255 or 0. + tstate->cframe->use_tracing = (use_tracing ? 255 : 0); + + if(traceobj != NULL){ + DecRef(traceobj, isDebug); + } + tstate->c_tracefunc = InternalTraceTrampoline311; + tstate->c_traceobj = arg; + /* Flag that tracing or profiling is turned on */ + use_tracing = ((InternalTraceTrampoline311 != NULL) + || (tstate->c_profilefunc != NULL)); + + // Note: before 3.11 this was just 1 or 0, now it needs to be 255 or 0. + tstate->cframe->use_tracing = (use_tracing ? 255 : 0); + +}; + + +#endif //_PY_CUSTOM_PYEVAL_SETTRACE_311_HPP_ \ No newline at end of file diff --git a/pydevd_attach_to_process/common/py_custom_pyeval_settrace_common.hpp b/pydevd_attach_to_process/common/py_custom_pyeval_settrace_common.hpp new file mode 100644 index 0000000..12f9e22 --- /dev/null +++ b/pydevd_attach_to_process/common/py_custom_pyeval_settrace_common.hpp @@ -0,0 +1,62 @@ +#ifndef _PY_CUSTOM_PYEVAL_SETTRACE_COMMON_HPP_ +#define _PY_CUSTOM_PYEVAL_SETTRACE_COMMON_HPP_ + +#include "python.h" +#include "py_utils.hpp" + +struct InternalInitializeCustomPyEvalSetTrace { + PyObject* pyNone; + PyTuple_New* pyTuple_New; + _PyObject_FastCallDict* pyObject_FastCallDict; + PyEval_CallObjectWithKeywords* pyEval_CallObjectWithKeywords; + PyUnicode_InternFromString* pyUnicode_InternFromString; // Note: in Py2 will be PyString_InternFromString. + PyTraceBack_Here* pyTraceBack_Here; + PyEval_SetTrace* pyEval_SetTrace; + bool isDebug; + PyUnicode_AsUTF8* pyUnicode_AsUTF8; + PyObject_Repr* pyObject_Repr; +}; + +/** + * Helper information to access CPython internals. + */ +static InternalInitializeCustomPyEvalSetTrace *internalInitializeCustomPyEvalSetTrace = NULL; + +/* + * Cached interned string objects used for calling the profile and + * trace functions. Initialized by InternalTraceInit(). + */ +static PyObject *InternalWhatstrings_37[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + + +static int +InternalIsTraceInitialized() +{ + return internalInitializeCustomPyEvalSetTrace != NULL; +} + + + +static int +InternalTraceInit(InternalInitializeCustomPyEvalSetTrace *p_internalInitializeSettrace_37) +{ + internalInitializeCustomPyEvalSetTrace = p_internalInitializeSettrace_37; + static const char * const whatnames[8] = { + "call", "exception", "line", "return", + "c_call", "c_exception", "c_return", + "opcode" + }; + PyObject *name; + int i; + for (i = 0; i < 8; ++i) { + if (InternalWhatstrings_37[i] == NULL) { + name = internalInitializeCustomPyEvalSetTrace->pyUnicode_InternFromString(whatnames[i]); + if (name == NULL) + return -1; + InternalWhatstrings_37[i] = name; + } + } + return 0; +} + +#endif //_PY_CUSTOM_PYEVAL_SETTRACE_COMMON_HPP_ \ No newline at end of file diff --git a/pydevd_attach_to_process/common/py_settrace.hpp b/pydevd_attach_to_process/common/py_settrace.hpp new file mode 100644 index 0000000..ba6c25f --- /dev/null +++ b/pydevd_attach_to_process/common/py_settrace.hpp @@ -0,0 +1,193 @@ +#ifndef _PY_SETTRACE_HPP_ +#define _PY_SETTRACE_HPP_ + +#include "ref_utils.hpp" +#include "py_utils.hpp" +#include "python.h" +#include "py_custom_pyeval_settrace.hpp" +#include + + +#ifdef _WIN32 + +typedef HMODULE MODULE_TYPE; +#else // LINUX ----------------------------------------------------------------- + +typedef void* MODULE_TYPE; +typedef ssize_t SSIZE_T; +typedef unsigned int DWORD; + +#endif + +DWORD GetPythonThreadId(PythonVersion version, PyThreadState* curThread) { + DWORD threadId = 0; + if (PyThreadState_25_27::IsFor(version)) { + threadId = (DWORD)((PyThreadState_25_27*)curThread)->thread_id; + } else if (PyThreadState_30_33::IsFor(version)) { + threadId = (DWORD)((PyThreadState_30_33*)curThread)->thread_id; + } else if (PyThreadState_34_36::IsFor(version)) { + threadId = (DWORD)((PyThreadState_34_36*)curThread)->thread_id; + } else if (PyThreadState_37_38::IsFor(version)) { + threadId = (DWORD)((PyThreadState_37_38*)curThread)->thread_id; + } else if (PyThreadState_39::IsFor(version)) { + threadId = (DWORD)((PyThreadState_39*)curThread)->thread_id; + } else if (PyThreadState_310::IsFor(version)) { + threadId = (DWORD)((PyThreadState_310*)curThread)->thread_id; + } else if (PyThreadState_311::IsFor(version)) { + threadId = (DWORD)((PyThreadState_311*)curThread)->thread_id; + } + return threadId; +} + + +/** + * This function may be called to set a tracing function to existing python threads. + */ +int InternalSetSysTraceFunc( + MODULE_TYPE module, + bool isDebug, + bool showDebugInfo, + PyObjectHolder* traceFunc, + PyObjectHolder* setTraceFunc, + unsigned int threadId, + PyObjectHolder* pyNone) +{ + + if(showDebugInfo){ + PRINT("InternalSetSysTraceFunc started."); + } + + DEFINE_PROC(isInit, Py_IsInitialized*, "Py_IsInitialized", 100); + if (!isInit()) { + PRINT("Py_IsInitialized returned false."); + return 110; + } + + auto version = GetPythonVersion(module); + + // found initialized Python runtime, gather and check the APIs we need. + + DEFINE_PROC(interpHead, PyInterpreterState_Head*, "PyInterpreterState_Head", 120); + DEFINE_PROC(gilEnsure, PyGILState_Ensure*, "PyGILState_Ensure", 130); + DEFINE_PROC(gilRelease, PyGILState_Release*, "PyGILState_Release", 140); + DEFINE_PROC(threadHead, PyInterpreterState_ThreadHead*, "PyInterpreterState_ThreadHead", 150); + DEFINE_PROC(threadNext, PyThreadState_Next*, "PyThreadState_Next", 160); + DEFINE_PROC(threadSwap, PyThreadState_Swap*, "PyThreadState_Swap", 170); + DEFINE_PROC(call, PyObject_CallFunctionObjArgs*, "PyObject_CallFunctionObjArgs", 180); + + PyInt_FromLong* intFromLong; + + if (version >= PythonVersion_30) { + DEFINE_PROC(intFromLongPy3, PyInt_FromLong*, "PyLong_FromLong", 190); + intFromLong = intFromLongPy3; + } else { + DEFINE_PROC(intFromLongPy2, PyInt_FromLong*, "PyInt_FromLong", 200); + intFromLong = intFromLongPy2; + } + + DEFINE_PROC(pyGetAttr, PyObject_GetAttrString*, "PyObject_GetAttrString", 250); + DEFINE_PROC(pyHasAttr, PyObject_HasAttrString*, "PyObject_HasAttrString", 260); + DEFINE_PROC_NO_CHECK(PyCFrame_Type, PyTypeObject*, "PyCFrame_Type", 300); // optional + + DEFINE_PROC_NO_CHECK(curPythonThread, PyThreadState**, "_PyThreadState_Current", 310); // optional + DEFINE_PROC_NO_CHECK(getPythonThread, _PyThreadState_UncheckedGet*, "_PyThreadState_UncheckedGet", 320); // optional + + if (curPythonThread == nullptr && getPythonThread == nullptr) { + // we're missing some APIs, we cannot attach. + PRINT("Error, missing Python threading API!!"); + return 330; + } + + auto head = interpHead(); + if (head == nullptr) { + // this interpreter is loaded but not initialized. + PRINT("Interpreter not initialized!"); + return 340; + } + + GilHolder gilLock(gilEnsure, gilRelease); // acquire and hold the GIL until done... + + int retVal = 0; + // find what index is holding onto the thread state... + auto curPyThread = getPythonThread ? getPythonThread() : *curPythonThread; + + if(curPyThread == nullptr){ + PRINT("Getting the current python thread returned nullptr."); + return 345; + } + + + // We do what PyEval_SetTrace does, but for any target thread. + PyUnicode_InternFromString* pyUnicode_InternFromString; + if (version >= PythonVersion_30) { + DEFINE_PROC(unicodeFromString, PyUnicode_InternFromString*, "PyUnicode_InternFromString", 520); + pyUnicode_InternFromString = unicodeFromString; + } else { + DEFINE_PROC(stringFromString, PyUnicode_InternFromString*, "PyString_InternFromString", 525); + pyUnicode_InternFromString = stringFromString; + } + + DEFINE_PROC_NO_CHECK(pyObject_FastCallDict, _PyObject_FastCallDict*, "_PyObject_FastCallDict", 530); + DEFINE_PROC(pyTuple_New, PyTuple_New*, "PyTuple_New", 531); + DEFINE_PROC(pyEval_CallObjectWithKeywords, PyEval_CallObjectWithKeywords*, "PyEval_CallObjectWithKeywords", 532); + + if(pyObject_FastCallDict == nullptr) { + DEFINE_PROC_NO_CHECK(pyObject_FastCallDict, _PyObject_FastCallDict*, "PyObject_VectorcallDict", 533); + } + + if(pyObject_FastCallDict == nullptr) { + // we have to use PyObject_FastCallDictCustom for older versions of CPython (pre 3.7). + pyObject_FastCallDict = reinterpret_cast<_PyObject_FastCallDict*>(&PyObject_FastCallDictCustom); + } + + + DEFINE_PROC(pyTraceBack_Here, PyTraceBack_Here*, "PyTraceBack_Here", 540); + DEFINE_PROC(pyEval_SetTrace, PyEval_SetTrace*, "PyEval_SetTrace", 550); + + // These are defined mostly for printing info while debugging, so, if they're not there, don't bother reporting. + DEFINE_PROC_NO_CHECK(pyObject_Repr, PyObject_Repr*, "PyObject_Repr", 551); + DEFINE_PROC_NO_CHECK(pyUnicode_AsUTF8, PyUnicode_AsUTF8*, "PyUnicode_AsUTF8", 552); + + + bool found = false; + for (PyThreadState* curThread = threadHead(head); curThread != nullptr; curThread = threadNext(curThread)) { + if (GetPythonThreadId(version, curThread) != threadId) { + continue; + } + found = true; + + if(showDebugInfo){ + printf("setting trace for thread: %d\n", threadId); + } + + if(!InternalIsTraceInitialized()) + { + InternalInitializeCustomPyEvalSetTrace *internalInitializeCustomPyEvalSetTrace = new InternalInitializeCustomPyEvalSetTrace(); + + IncRef(pyNone->ToPython()); + internalInitializeCustomPyEvalSetTrace->pyNone = pyNone->ToPython(); + + internalInitializeCustomPyEvalSetTrace->pyUnicode_InternFromString = pyUnicode_InternFromString; + internalInitializeCustomPyEvalSetTrace->pyObject_FastCallDict = pyObject_FastCallDict; + internalInitializeCustomPyEvalSetTrace->isDebug = isDebug; + internalInitializeCustomPyEvalSetTrace->pyTraceBack_Here = pyTraceBack_Here; + internalInitializeCustomPyEvalSetTrace->pyEval_SetTrace = pyEval_SetTrace; + internalInitializeCustomPyEvalSetTrace->pyTuple_New = pyTuple_New; + internalInitializeCustomPyEvalSetTrace->pyEval_CallObjectWithKeywords = pyEval_CallObjectWithKeywords; + internalInitializeCustomPyEvalSetTrace->pyObject_Repr = pyObject_Repr; + internalInitializeCustomPyEvalSetTrace->pyUnicode_AsUTF8 = pyUnicode_AsUTF8; + + InternalTraceInit(internalInitializeCustomPyEvalSetTrace); + } + InternalPySetTrace(curThread, traceFunc, isDebug, version); + break; + } + if(!found) { + retVal = 501; + } + + return retVal; + +} + +#endif // _PY_SETTRACE_HPP_ diff --git a/pydevd_attach_to_process/common/py_utils.hpp b/pydevd_attach_to_process/common/py_utils.hpp new file mode 100644 index 0000000..97163a4 --- /dev/null +++ b/pydevd_attach_to_process/common/py_utils.hpp @@ -0,0 +1,84 @@ +#ifndef _PY_UTILS_HPP_ +#define _PY_UTILS_HPP_ + +typedef int (Py_IsInitialized)(); +typedef PyInterpreterState* (PyInterpreterState_Head)(); +typedef enum { PyGILState_LOCKED, PyGILState_UNLOCKED } PyGILState_STATE; +typedef PyGILState_STATE(PyGILState_Ensure)(); +typedef void (PyGILState_Release)(PyGILState_STATE); +typedef int (PyRun_SimpleString)(const char *command); +typedef PyThreadState* (PyInterpreterState_ThreadHead)(PyInterpreterState* interp); +typedef PyThreadState* (PyThreadState_Next)(PyThreadState *tstate); +typedef PyThreadState* (PyThreadState_Swap)(PyThreadState *tstate); +typedef PyThreadState* (_PyThreadState_UncheckedGet)(); +typedef PyObject* (PyObject_CallFunctionObjArgs)(PyObject *callable, ...); // call w/ varargs, last arg should be nullptr +typedef PyObject* (PyInt_FromLong)(long); +typedef PyObject* (PyErr_Occurred)(); +typedef void (PyErr_Fetch)(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback); +typedef void (PyErr_Restore)(PyObject *type, PyObject *value, PyObject *traceback); +typedef PyObject* (PyImport_ImportModule) (const char *name); +typedef PyObject* (PyImport_ImportModuleNoBlock) (const char *name); +typedef PyObject* (PyObject_GetAttrString)(PyObject *o, const char *attr_name); +typedef PyObject* (PyObject_HasAttrString)(PyObject *o, const char *attr_name); +typedef void* (PyThread_get_key_value)(int); +typedef int (PyThread_set_key_value)(int, void*); +typedef void (PyThread_delete_key_value)(int); +typedef int (PyObject_Not) (PyObject *o); +typedef PyObject* (PyDict_New)(); +typedef PyObject* (PyUnicode_InternFromString)(const char *u); +typedef PyObject * (_PyObject_FastCallDict)( + PyObject *callable, PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs); +typedef int (PyTraceBack_Here)(PyFrameObject *frame); + +typedef PyObject* PyTuple_New(Py_ssize_t len); +typedef PyObject* PyEval_CallObjectWithKeywords(PyObject *callable, PyObject *args, PyObject *kwargs); + +typedef void (PyEval_SetTrace)(Py_tracefunc, PyObject *); +typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *frame, int, PyObject *); +typedef int (_PyEval_SetTrace)(PyThreadState *tstate, Py_tracefunc func, PyObject *arg); + +typedef PyObject* PyObject_Repr(PyObject *); +typedef const char* PyUnicode_AsUTF8(PyObject *unicode); + +// holder to ensure we release the GIL even in error conditions +class GilHolder { + PyGILState_STATE _gilState; + PyGILState_Release* _release; +public: + GilHolder(PyGILState_Ensure* acquire, PyGILState_Release* release) { + _gilState = acquire(); + _release = release; + } + + ~GilHolder() { + _release(_gilState); + } +}; + +#ifdef _WIN32 + +#define PRINT(msg) {std::cout << msg << std::endl << std::flush;} + +#define DEFINE_PROC_NO_CHECK(func, funcType, funcNameStr, errorCode) \ + funcType func=reinterpret_cast(GetProcAddress(module, funcNameStr)); + +#define DEFINE_PROC(func, funcType, funcNameStr, errorCode) \ + DEFINE_PROC_NO_CHECK(func, funcType, funcNameStr, errorCode); \ + if(func == nullptr){std::cout << funcNameStr << " not found." << std::endl << std::flush; return errorCode;}; + +#else // LINUX ----------------------------------------------------------------- + +#define PRINT(msg) {printf(msg); printf("\n");} + +#define CHECK_NULL(ptr, msg, errorCode) if(ptr == nullptr){printf(msg); return errorCode;} + +#define DEFINE_PROC_NO_CHECK(func, funcType, funcNameStr, errorCode) \ + funcType func; *(void**)(&func) = dlsym(module, funcNameStr); + +#define DEFINE_PROC(func, funcType, funcNameStr, errorCode) \ + DEFINE_PROC_NO_CHECK(func, funcType, funcNameStr, errorCode); \ + if(func == nullptr){printf(funcNameStr); printf(" not found.\n"); return errorCode;}; + +#endif //_WIN32 + +#endif //_PY_UTILS_HPP_ \ No newline at end of file diff --git a/pydevd_attach_to_process/common/py_version.hpp b/pydevd_attach_to_process/common/py_version.hpp new file mode 100644 index 0000000..be73692 --- /dev/null +++ b/pydevd_attach_to_process/common/py_version.hpp @@ -0,0 +1,90 @@ + +#ifndef __PY_VERSION_HPP__ +#define __PY_VERSION_HPP__ + + +#include + +enum PythonVersion { + PythonVersion_Unknown, + PythonVersion_25 = 0x0205, + PythonVersion_26 = 0x0206, + PythonVersion_27 = 0x0207, + PythonVersion_30 = 0x0300, + PythonVersion_31 = 0x0301, + PythonVersion_32 = 0x0302, + PythonVersion_33 = 0x0303, + PythonVersion_34 = 0x0304, + PythonVersion_35 = 0x0305, + PythonVersion_36 = 0x0306, + PythonVersion_37 = 0x0307, + PythonVersion_38 = 0x0308, + PythonVersion_39 = 0x0309, + PythonVersion_310 = 0x030A, + PythonVersion_311 = 0x030B +}; + + +#ifdef _WIN32 + +typedef const char* (GetVersionFunc)(); + +static PythonVersion GetPythonVersion(HMODULE hMod) { + auto versionFunc = reinterpret_cast(GetProcAddress(hMod, "Py_GetVersion")); + if (versionFunc == nullptr) { + return PythonVersion_Unknown; + } + const char* version = versionFunc(); + + +#else // LINUX ----------------------------------------------------------------- + +typedef const char* (*GetVersionFunc) (); + +static PythonVersion GetPythonVersion(void *module) { + GetVersionFunc versionFunc; + *(void**)(&versionFunc) = dlsym(module, "Py_GetVersion"); + if(versionFunc == nullptr) { + return PythonVersion_Unknown; + } + const char* version = versionFunc(); + +#endif //_WIN32 + + if (version != nullptr && strlen(version) >= 3 && version[1] == '.') { + if (version[0] == '2') { + switch (version[2]) { + case '5': return PythonVersion_25; + case '6': return PythonVersion_26; + case '7': return PythonVersion_27; + } + } + else if (version[0] == '3') { + switch (version[2]) { + case '0': return PythonVersion_30; + case '1': + if(strlen(version) >= 4){ + if(version[3] == '0'){ + return PythonVersion_310; + } + if(version[3] == '1'){ + return PythonVersion_311; + } + } + return PythonVersion_Unknown; // we don't care about 3.1 anymore... + + case '2': return PythonVersion_32; + case '3': return PythonVersion_33; + case '4': return PythonVersion_34; + case '5': return PythonVersion_35; + case '6': return PythonVersion_36; + case '7': return PythonVersion_37; + case '8': return PythonVersion_38; + case '9': return PythonVersion_39; + } + } + } + return PythonVersion_Unknown; +} + +#endif \ No newline at end of file diff --git a/pydevd_attach_to_process/common/python.h b/pydevd_attach_to_process/common/python.h new file mode 100644 index 0000000..ce5dc98 --- /dev/null +++ b/pydevd_attach_to_process/common/python.h @@ -0,0 +1,704 @@ +// Python Tools for Visual Studio +// Copyright(c) Microsoft Corporation +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the License); you may not use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.apache.org/licenses/LICENSE-2.0 +// +// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS +// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY +// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +// MERCHANTABILITY OR NON-INFRINGEMENT. +// +// See the Apache Version 2.0 License for specific language governing +// permissions and limitations under the License. + +#ifndef __PYTHON_H__ +#define __PYTHON_H__ + +#include "../common/py_version.hpp" + +#include + +#ifndef _WIN32 +typedef unsigned int DWORD; +typedef ssize_t SSIZE_T; +#endif +typedef SSIZE_T Py_ssize_t; + +// defines limited header of Python API for compatible access across a number of Pythons. + +class PyTypeObject; +class PyThreadState; + +#define PyObject_HEAD \ + size_t ob_refcnt; \ + PyTypeObject *ob_type; + +#define PyObject_VAR_HEAD \ + PyObject_HEAD \ + size_t ob_size; /* Number of items in variable part */ + +class PyObject { +public: + PyObject_HEAD +}; + +class PyVarObject : public PyObject { +public: + size_t ob_size; /* Number of items in variable part */ +}; + +// 2.5 - 3.7 +class PyFunctionObject : public PyObject { +public: + PyObject *func_code; /* A code object */ +}; + +// 2.5 - 2.7 compatible +class PyStringObject : public PyVarObject { +public: + long ob_shash; + int ob_sstate; + char ob_sval[1]; + + /* Invariants: + * ob_sval contains space for 'ob_size+1' elements. + * ob_sval[ob_size] == 0. + * ob_shash is the hash of the string or -1 if not computed yet. + * ob_sstate != 0 iff the string object is in stringobject.c's + * 'interned' dictionary; in this case the two references + * from 'interned' to this object are *not counted* in ob_refcnt. + */ +}; + +// 2.4 - 3.7 compatible +typedef struct { + PyObject_HEAD + size_t length; /* Length of raw Unicode data in buffer */ + wchar_t *str; /* Raw Unicode buffer */ + long hash; /* Hash value; -1 if not set */ +} PyUnicodeObject; + + +class PyFrameObject : public PyObject { + // After 3.10 we don't really have things we want to reuse common, so, + // create an empty base (it's not based on PyVarObject because on Python 3.11 + // it's just a PyObject and no longer a PyVarObject -- the part related to + // the var object must be declared in ech subclass in this case). +}; + +// 2.4 - 3.7 compatible +class PyFrameObjectBaseUpTo39 : public PyFrameObject { +public: + size_t ob_size; /* Number of items in variable part -- i.e.: PyVarObject*/ + + PyFrameObjectBaseUpTo39 *f_back; /* previous frame, or nullptr */ + PyObject *f_code; /* code segment */ + PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ + PyObject *f_globals; /* global symbol table (PyDictObject) */ + PyObject *f_locals; /* local symbol table (any mapping) */ + PyObject **f_valuestack; /* points after the last local */ + /* Next free slot in f_valuestack. Frame creation sets to f_valuestack. + Frame evaluation usually NULLs it, but a frame that yields sets it + to the current stack top. */ + PyObject **f_stacktop; + PyObject *f_trace; /* Trace function */ + + // It has more things, but we're only interested in things up to f_trace. + +}; + + +// https://github.com/python/cpython/blob/3.10/Include/cpython/frameobject.h +class PyFrameObject310 : public PyFrameObject { +public: + size_t ob_size; /* Number of items in variable part -- i.e.: PyVarObject*/ + + PyFrameObject310 *f_back; /* previous frame, or NULL */ + PyObject *f_code; /* code segment */ + PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ + PyObject *f_globals; /* global symbol table (PyDictObject) */ + PyObject *f_locals; /* local symbol table (any mapping) */ + PyObject **f_valuestack; /* points after the last local */ + PyObject *f_trace; /* Trace function */ + + // It has more things, but we're only interested in things up to f_trace. +}; + +typedef uint16_t _Py_CODEUNIT; + +// https://github.com/python/cpython/blob/3.11/Include/internal/pycore_frame.h +typedef struct _PyInterpreterFrame311 { + /* "Specials" section */ + PyFunctionObject *f_func; /* Strong reference */ + PyObject *f_globals; /* Borrowed reference */ + PyObject *f_builtins; /* Borrowed reference */ + PyObject *f_locals; /* Strong reference, may be NULL */ + void *f_code; /* Strong reference */ + void *frame_obj; /* Strong reference, may be NULL */ + /* Linkage section */ + struct _PyInterpreterFrame311 *previous; + // NOTE: This is not necessarily the last instruction started in the given + // frame. Rather, it is the code unit *prior to* the *next* instruction. For + // example, it may be an inline CACHE entry, an instruction we just jumped + // over, or (in the case of a newly-created frame) a totally invalid value: + _Py_CODEUNIT *prev_instr; + int stacktop; /* Offset of TOS from localsplus */ + bool is_entry; // Whether this is the "root" frame for the current _PyCFrame. + char owner; + /* Locals and stack */ + PyObject *localsplus[1]; +} _PyInterpreterFrame311; + +// https://github.com/python/cpython/blob/3.11/Include/internal/pycore_frame.h +// Note that in 3.11 it's no longer a "PyVarObject". +class PyFrameObject311 : public PyFrameObject { +public: + PyFrameObject311 *f_back; /* previous frame, or NULL */ + struct _PyInterpreterFrame311 *f_frame; /* points to the frame data */ + PyObject *f_trace; /* Trace function */ + int f_lineno; /* Current line number. Only valid if non-zero */ + char f_trace_lines; /* Emit per-line trace events? */ + char f_trace_opcodes; /* Emit per-opcode trace events? */ + char f_fast_as_locals; /* Have the fast locals of this frame been converted to a dict? */ + // It has more things, but we're not interested on those. +}; + + +typedef void (*destructor)(PyObject *); + +// 2.4 - 3.7 +class PyMethodDef { +public: + char *ml_name; /* The name of the built-in function/method */ +}; + + +// +// 2.5 - 3.7 +// While these are compatible there are fields only available on later versions. +class PyTypeObject : public PyVarObject { +public: + const char *tp_name; /* For printing, in format "." */ + size_t tp_basicsize, tp_itemsize; /* For allocation */ + + /* Methods to implement standard operations */ + + destructor tp_dealloc; + void *tp_print; + void *tp_getattr; + void *tp_setattr; + union { + void *tp_compare; /* 2.4 - 3.4 */ + void *tp_as_async; /* 3.5 - 3.7 */ + }; + void *tp_repr; + + /* Method suites for standard classes */ + + void *tp_as_number; + void *tp_as_sequence; + void *tp_as_mapping; + + /* More standard operations (here for binary compatibility) */ + + void *tp_hash; + void *tp_call; + void *tp_str; + void *tp_getattro; + void *tp_setattro; + + /* Functions to access object as input/output buffer */ + void *tp_as_buffer; + + /* Flags to define presence of optional/expanded features */ + long tp_flags; + + const char *tp_doc; /* Documentation string */ + + /* Assigned meaning in release 2.0 */ + /* call function for all accessible objects */ + void *tp_traverse; + + /* delete references to contained objects */ + void *tp_clear; + + /* Assigned meaning in release 2.1 */ + /* rich comparisons */ + void *tp_richcompare; + + /* weak reference enabler */ + size_t tp_weaklistoffset; + + /* Added in release 2.2 */ + /* Iterators */ + void *tp_iter; + void *tp_iternext; + + /* Attribute descriptor and subclassing stuff */ + PyMethodDef *tp_methods; + struct PyMemberDef *tp_members; + struct PyGetSetDef *tp_getset; + struct _typeobject *tp_base; + PyObject *tp_dict; + void *tp_descr_get; + void *tp_descr_set; + size_t tp_dictoffset; + void *tp_init; + void *tp_alloc; + void *tp_new; + void *tp_free; /* Low-level free-memory routine */ + void *tp_is_gc; /* For PyObject_IS_GC */ + PyObject *tp_bases; + PyObject *tp_mro; /* method resolution order */ + PyObject *tp_cache; + PyObject *tp_subclasses; + PyObject *tp_weaklist; + void *tp_del; + + /* Type attribute cache version tag. Added in version 2.6 */ + unsigned int tp_version_tag; +}; + +// 2.4 - 3.7 +class PyTupleObject : public PyVarObject { +public: + PyObject *ob_item[1]; + + /* ob_item contains space for 'ob_size' elements. + * Items must normally not be nullptr, except during construction when + * the tuple is not yet visible outside the function that builds it. + */ +}; + +// 2.4 - 3.7 +class PyCFunctionObject : public PyObject { +public: + PyMethodDef *m_ml; /* Description of the C function to call */ + PyObject *m_self; /* Passed as 'self' arg to the C func, can be nullptr */ + PyObject *m_module; /* The __module__ attribute, can be anything */ +}; + +typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *); + +#define PyTrace_CALL 0 +#define PyTrace_EXCEPTION 1 +#define PyTrace_LINE 2 +#define PyTrace_RETURN 3 +#define PyTrace_C_CALL 4 +#define PyTrace_C_EXCEPTION 5 +#define PyTrace_C_RETURN 6 + +class PyInterpreterState { +}; + +class PyThreadState { }; + +class PyThreadState_25_27 : public PyThreadState { +public: + /* See Python/ceval.c for comments explaining most fields */ + + PyThreadState *next; + PyInterpreterState *interp; + + PyFrameObjectBaseUpTo39 *frame; + int recursion_depth; + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int tracing; + int use_tracing; + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + PyObject *exc_type; + PyObject *exc_value; + PyObject *exc_traceback; + + PyObject *dict; /* Stores per-thread state */ + + /* tick_counter is incremented whenever the check_interval ticker + * reaches zero. The purpose is to give a useful measure of the number + * of interpreted bytecode instructions in a given thread. This + * extremely lightweight statistic collector may be of interest to + * profilers (like psyco.jit()), although nothing in the core uses it. + */ + int tick_counter; + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + long thread_id; /* Thread id where this tstate was created */ + + /* XXX signal handlers should also be here */ + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 2 && (minorVersion >= 5 && minorVersion <= 7); + } + + static bool IsFor(PythonVersion version) { + return version >= PythonVersion_25 && version <= PythonVersion_27; + } +}; + +class PyThreadState_30_33 : public PyThreadState { +public: + PyThreadState *next; + PyInterpreterState *interp; + + PyFrameObjectBaseUpTo39 *frame; + int recursion_depth; + char overflowed; /* The stack has overflowed. Allow 50 more calls + to handle the runtime error. */ + char recursion_critical; /* The current calls must not cause + a stack overflow. */ + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int tracing; + int use_tracing; + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + PyObject *exc_type; + PyObject *exc_value; + PyObject *exc_traceback; + + PyObject *dict; /* Stores per-thread state */ + + /* tick_counter is incremented whenever the check_interval ticker + * reaches zero. The purpose is to give a useful measure of the number + * of interpreted bytecode instructions in a given thread. This + * extremely lightweight statistic collector may be of interest to + * profilers (like psyco.jit()), although nothing in the core uses it. + */ + int tick_counter; + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + long thread_id; /* Thread id where this tstate was created */ + + /* XXX signal handlers should also be here */ + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && (minorVersion >= 0 && minorVersion <= 3); + } + + static bool IsFor(PythonVersion version) { + return version >= PythonVersion_30 && version <= PythonVersion_33; + } +}; + +class PyThreadState_34_36 : public PyThreadState { +public: + PyThreadState *prev; + PyThreadState *next; + PyInterpreterState *interp; + + PyFrameObjectBaseUpTo39 *frame; + int recursion_depth; + char overflowed; /* The stack has overflowed. Allow 50 more calls + to handle the runtime error. */ + char recursion_critical; /* The current calls must not cause + a stack overflow. */ + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int tracing; + int use_tracing; + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + PyObject *exc_type; + PyObject *exc_value; + PyObject *exc_traceback; + + PyObject *dict; /* Stores per-thread state */ + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + + long thread_id; /* Thread id where this tstate was created */ + /* XXX signal handlers should also be here */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && minorVersion >= 4 && minorVersion <= 6; + } + + static bool IsFor(PythonVersion version) { + return version >= PythonVersion_34 && version <= PythonVersion_36; + } +}; + +struct _PyErr_StackItem { + PyObject *exc_type, *exc_value, *exc_traceback; + struct _PyErr_StackItem *previous_item; +}; + + +class PyThreadState_37_38 : public PyThreadState { +public: + PyThreadState *prev; + PyThreadState *next; + PyInterpreterState *interp; + + PyFrameObjectBaseUpTo39 *frame; + int recursion_depth; + char overflowed; /* The stack has overflowed. Allow 50 more calls + to handle the runtime error. */ + char recursion_critical; /* The current calls must not cause + a stack overflow. */ + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int stackcheck_counter; + + int tracing; + int use_tracing; + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + _PyErr_StackItem exc_state; + _PyErr_StackItem *exc_info; + + PyObject *dict; /* Stores per-thread state */ + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + + unsigned long thread_id; /* Thread id where this tstate was created */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && (minorVersion == 7 || minorVersion == 8); + } + + static bool IsFor(PythonVersion version) { + return version == PythonVersion_37 || version == PythonVersion_38; + } +}; + +// i.e.: https://github.com/python/cpython/blob/master/Include/cpython/pystate.h +class PyThreadState_39 : public PyThreadState { +public: + PyThreadState *prev; + PyThreadState *next; + PyInterpreterState *interp; + + PyFrameObjectBaseUpTo39 *frame; + int recursion_depth; + char overflowed; /* The stack has overflowed. Allow 50 more calls + to handle the runtime error. */ + int stackcheck_counter; + + int tracing; + int use_tracing; + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + _PyErr_StackItem exc_state; + _PyErr_StackItem *exc_info; + + PyObject *dict; /* Stores per-thread state */ + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + + unsigned long thread_id; /* Thread id where this tstate was created */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && minorVersion == 9; + } + + static bool IsFor(PythonVersion version) { + return version == PythonVersion_39; + } +}; + +typedef struct _cframe { + /* This struct will be threaded through the C stack + * allowing fast access to per-thread state that needs + * to be accessed quickly by the interpreter, but can + * be modified outside of the interpreter. + * + * WARNING: This makes data on the C stack accessible from + * heap objects. Care must be taken to maintain stack + * discipline and make sure that instances of this struct cannot + * accessed outside of their lifetime. + */ + int use_tracing; + struct _cframe *previous; +} CFrame; + +// i.e.: https://github.com/python/cpython/blob/master/Include/cpython/pystate.h +class PyThreadState_310 : public PyThreadState { +public: + PyThreadState *prev; + PyThreadState *next; + PyInterpreterState *interp; + + PyFrameObject310 *frame; + int recursion_depth; + int recursion_headroom; /* Allow 50 more calls to handle any errors. */ + int stackcheck_counter; + + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int tracing; + + /* Pointer to current CFrame in the C stack frame of the currently, + * or most recently, executing _PyEval_EvalFrameDefault. */ + CFrame *cframe; + + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + _PyErr_StackItem exc_state; + _PyErr_StackItem *exc_info; + + PyObject *dict; /* Stores per-thread state */ + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + + unsigned long thread_id; /* Thread id where this tstate was created */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && minorVersion == 10; + } + + static bool IsFor(PythonVersion version) { + return version == PythonVersion_310; + } +}; + +// i.e.: https://github.com/python/cpython/blob/3.11/Include/cpython/pystate.h +class PyThreadState_311 : public PyThreadState { +public: + PyThreadState *prev; + PyThreadState *next; + PyInterpreterState *interp; + + int _initialized; + + int _static; + + int recursion_remaining; + int recursion_limit; + int recursion_headroom; /* Allow 50 more calls to handle any errors. */ + + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int tracing; + int tracing_what; + + /* Pointer to current CFrame in the C stack frame of the currently, + * or most recently, executing _PyEval_EvalFrameDefault. */ + CFrame *cframe; + + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + _PyErr_StackItem *exc_info; + + PyObject *dict; /* Stores per-thread state */ + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + + unsigned long thread_id; /* Thread id where this tstate was created */ + + static bool IsFor(int majorVersion, int minorVersion) { + return majorVersion == 3 && minorVersion == 11; + } + + static bool IsFor(PythonVersion version) { + return version == PythonVersion_311; + } +}; + +class PyIntObject : public PyObject { +public: + long ob_ival; +}; + +class Py3kLongObject : public PyVarObject { +public: + DWORD ob_digit[1]; +}; + +class PyOldStyleClassObject : public PyObject { +public: + PyObject *cl_bases; /* A tuple of class objects */ + PyObject *cl_dict; /* A dictionary */ + PyObject *cl_name; /* A string */ + /* The following three are functions or nullptr */ + PyObject *cl_getattr; + PyObject *cl_setattr; + PyObject *cl_delattr; +}; + +class PyInstanceObject : public PyObject { +public: + PyOldStyleClassObject *in_class; /* The class object */ + PyObject *in_dict; /* A dictionary */ + PyObject *in_weakreflist; /* List of weak references */ +}; + +#endif diff --git a/pydevd_attach_to_process/common/ref_utils.hpp b/pydevd_attach_to_process/common/ref_utils.hpp new file mode 100644 index 0000000..d1fa07d --- /dev/null +++ b/pydevd_attach_to_process/common/ref_utils.hpp @@ -0,0 +1,63 @@ +#ifndef _REF_UTILS_HPP_ +#define _REF_UTILS_HPP_ + + +PyObject* GetPyObjectPointerNoDebugInfo(bool isDebug, PyObject* object) { + if (object != nullptr && isDebug) { + // debug builds have 2 extra pointers at the front that we don't care about + return (PyObject*)((size_t*)object + 2); + } + return object; +} + +void DecRef(PyObject* object, bool isDebug) { + auto noDebug = GetPyObjectPointerNoDebugInfo(isDebug, object); + + if (noDebug != nullptr && --noDebug->ob_refcnt == 0) { + ((PyTypeObject*)GetPyObjectPointerNoDebugInfo(isDebug, noDebug->ob_type))->tp_dealloc(object); + } +} + +void IncRef(PyObject* object) { + object->ob_refcnt++; +} + +class PyObjectHolder { +private: + PyObject* _object; +public: + bool _isDebug; + + PyObjectHolder(bool isDebug) { + _object = nullptr; + _isDebug = isDebug; + } + + PyObjectHolder(bool isDebug, PyObject *object) { + _object = object; + _isDebug = isDebug; + }; + + PyObjectHolder(bool isDebug, PyObject *object, bool addRef) { + _object = object; + _isDebug = isDebug; + if (_object != nullptr && addRef) { + GetPyObjectPointerNoDebugInfo(_isDebug, _object)->ob_refcnt++; + } + }; + + PyObject* ToPython() { + return _object; + } + + ~PyObjectHolder() { + DecRef(_object, _isDebug); + } + + PyObject* operator* () { + return GetPyObjectPointerNoDebugInfo(_isDebug, _object); + } +}; + + +#endif //_REF_UTILS_HPP_ \ No newline at end of file diff --git a/pydevd_attach_to_process/linux_and_mac/.gitignore b/pydevd_attach_to_process/linux_and_mac/.gitignore new file mode 100644 index 0000000..826fe93 --- /dev/null +++ b/pydevd_attach_to_process/linux_and_mac/.gitignore @@ -0,0 +1,4 @@ +/attach_x86.dylib +/attach_x86_64.dylib +/attach_linux_x86.o +/attach_linux_x86_64.o diff --git a/pydevd_attach_to_process/linux_and_mac/attach.cpp b/pydevd_attach_to_process/linux_and_mac/attach.cpp new file mode 100644 index 0000000..6502c06 --- /dev/null +++ b/pydevd_attach_to_process/linux_and_mac/attach.cpp @@ -0,0 +1,111 @@ +// This is much simpler than the windows version because we're using gdb and +// we assume that gdb will call things in the correct thread already. + +//compile with: g++ -shared -o attach_linux.so -fPIC -nostartfiles attach_linux.c + + +#include +#include +#include +#include + +#include "../common/python.h" +#include "../common/ref_utils.hpp" +#include "../common/py_utils.hpp" +#include "../common/py_settrace.hpp" +//#include used for usleep + +// Exported function: hello(): Just to print something and check that we've been +// able to connect. +extern "C" int hello(void); + +int hello() +{ + printf("Hello world!\n"); + + void *module = dlopen(nullptr, 0x2); + + void *hndl = dlsym (module, "PyGILState_Ensure"); + if(hndl == nullptr){ + printf("nullptr\n"); + + }else{ + printf("Worked (found PyGILState_Ensure)!\n"); + } + + printf("%d", GetPythonVersion(module)); + + + return 2; +} + + +// Internal function to keep on the tracing +int _PYDEVD_ExecWithGILSetSysStrace(bool showDebugInfo, bool isDebug); + +// Implementation details below +typedef PyObject* (PyImport_ImportModuleNoBlock) (const char *name); +typedef int (*PyEval_ThreadsInitialized)(); +typedef unsigned long (*_PyEval_GetSwitchInterval)(void); +typedef void (*_PyEval_SetSwitchInterval)(unsigned long microseconds); + +// isDebug is pretty important! Must be true on python debug builds (python_d) +// If this value is passed wrongly the program will crash. +extern "C" int DoAttach(bool isDebug, const char *command, bool showDebugInfo); + +int DoAttach(bool isDebug, const char *command, bool showDebugInfo) +{ + void *module = dlopen(nullptr, 0x2); + DEFINE_PROC(isInitFunc, Py_IsInitialized*, "Py_IsInitialized", 1); + DEFINE_PROC(gilEnsure, PyGILState_Ensure*, "PyGILState_Ensure", 51); + DEFINE_PROC(gilRelease, PyGILState_Release*, "PyGILState_Release", 51); + + + if(!isInitFunc()){ + if(showDebugInfo){ + printf("Py_IsInitialized returned false.\n"); + } + return 2; + } + + PythonVersion version = GetPythonVersion(module); + + DEFINE_PROC(interpHead, PyInterpreterState_Head*, "PyInterpreterState_Head", 51); + + auto head = interpHead(); + if (head == nullptr) { + // this interpreter is loaded but not initialized. + if(showDebugInfo){ + printf("Interpreter not initialized!\n"); + } + return 54; + } + + // Note: unlike windows where we have to do many things to enable threading + // to work to get the gil, here we'll be executing in an existing thread, + // so, it's mostly a matter of getting the GIL and running it and we shouldn't + // have any more problems. + + DEFINE_PROC(pyRun_SimpleString, PyRun_SimpleString*, "PyRun_SimpleString", 51); + + GilHolder gilLock(gilEnsure, gilRelease); // acquire and hold the GIL until done... + + pyRun_SimpleString(command); + return 0; +} + + +// This is the function which enables us to set the sys.settrace for all the threads +// which are already running. +extern "C" int AttachDebuggerTracing(bool showDebugInfo, void* pSetTraceFunc, void* pTraceFunc, unsigned int threadId, void* pPyNone); + +int AttachDebuggerTracing(bool showDebugInfo, void* pSetTraceFunc, void* pTraceFunc, unsigned int threadId, void* pPyNone) +{ + void *module = dlopen(nullptr, 0x2); + bool isDebug = false; + PyObjectHolder traceFunc(isDebug, (PyObject*) pTraceFunc, true); + PyObjectHolder setTraceFunc(isDebug, (PyObject*) pSetTraceFunc, true); + PyObjectHolder pyNone(isDebug, reinterpret_cast(pPyNone), true); + return InternalSetSysTraceFunc(module, isDebug, showDebugInfo, &traceFunc, &setTraceFunc, threadId, &pyNone); +} + diff --git a/pydevd_attach_to_process/linux_and_mac/compile_linux.sh b/pydevd_attach_to_process/linux_and_mac/compile_linux.sh new file mode 100755 index 0000000..3a1ebc2 --- /dev/null +++ b/pydevd_attach_to_process/linux_and_mac/compile_linux.sh @@ -0,0 +1,9 @@ +g++ -m64 -shared -o attach_linux_amd64.so -fPIC -nostartfiles attach.cpp +mv attach_linux_amd64.so ../attach_linux_amd64.so +echo Compiled amd64 + +echo Note: may need "sudo apt-get install libx32gcc-4.8-dev" and "sudo apt-get install libc6-dev-i386" and "sudo apt-get install g++-multilib" to compile 32 bits + +g++ -m32 -shared -o attach_linux_x86.so -fPIC -nostartfiles attach.cpp +mv attach_linux_x86.so ../attach_linux_x86.so +echo Compiled x86 diff --git a/pydevd_attach_to_process/linux_and_mac/compile_mac.sh b/pydevd_attach_to_process/linux_and_mac/compile_mac.sh new file mode 100755 index 0000000..5c614fe --- /dev/null +++ b/pydevd_attach_to_process/linux_and_mac/compile_mac.sh @@ -0,0 +1,5 @@ +g++ -fPIC -D_REENTRANT -std=c++11 -arch x86_64 -c -o attach_x86_64.o attach.cpp +g++ -dynamiclib -nostartfiles -arch x86_64 -o attach_x86_64.dylib attach_x86_64.o -lc +rm attach_x86_64.o +mv attach_x86_64.dylib ../attach_x86_64.dylib + diff --git a/pydevd_attach_to_process/linux_and_mac/compile_manylinux.cmd b/pydevd_attach_to_process/linux_and_mac/compile_manylinux.cmd new file mode 100644 index 0000000..e55f0bf --- /dev/null +++ b/pydevd_attach_to_process/linux_and_mac/compile_manylinux.cmd @@ -0,0 +1,10 @@ +:: WARNING: manylinux1 images are based on CentOS 5, which requires vsyscall to be available on +:: the host. For any recent version of Linux, this requires passing vsyscall=emulate during boot. +:: For WSL, add the following to your .wslconfig: +:: +:: [wsl2] +:: kernelCommandLine = vsyscall=emulate + +docker run --rm -v %~dp0/..:/src quay.io/pypa/manylinux1_x86_64 g++ -std=c++11 -shared -o /src/attach_linux_amd64.so -fPIC -nostartfiles /src/linux_and_mac/attach.cpp + +docker run --rm -v %~dp0/..:/src quay.io/pypa/manylinux1_i686 g++ -std=c++11 -shared -o /src/attach_linux_x86.so -fPIC -nostartfiles /src/linux_and_mac/attach.cpp diff --git a/pydevd_attach_to_process/linux_and_mac/lldb_prepare.py b/pydevd_attach_to_process/linux_and_mac/lldb_prepare.py new file mode 100644 index 0000000..8a22054 --- /dev/null +++ b/pydevd_attach_to_process/linux_and_mac/lldb_prepare.py @@ -0,0 +1,54 @@ +# This file is meant to be run inside lldb +# It registers command to load library and invoke attach function +# Also it marks process threads to to distinguish them from debugger +# threads later while settings trace in threads + +def load_lib_and_attach(debugger, command, result, internal_dict): + import shlex + args = shlex.split(command) + + dll = args[0] + is_debug = args[1] + python_code = args[2] + show_debug_info = args[3] + + import lldb + options = lldb.SBExpressionOptions() + options.SetFetchDynamicValue() + options.SetTryAllThreads(run_others=False) + options.SetTimeoutInMicroSeconds(timeout=10000000) + + print(dll) + target = debugger.GetSelectedTarget() + res = target.EvaluateExpression("(void*)dlopen(\"%s\", 2);" % ( + dll), options) + error = res.GetError() + if error: + print(error) + + print(python_code) + res = target.EvaluateExpression("(int)DoAttach(%s, \"%s\", %s);" % ( + is_debug, python_code.replace('"', "'"), show_debug_info), options) + error = res.GetError() + if error: + print(error) + +def __lldb_init_module(debugger, internal_dict): + import lldb + + debugger.HandleCommand('command script add -f lldb_prepare.load_lib_and_attach load_lib_and_attach') + + try: + target = debugger.GetSelectedTarget() + if target: + process = target.GetProcess() + if process: + for thread in process: + # print('Marking process thread %d'%thread.GetThreadID()) + internal_dict['_thread_%d' % thread.GetThreadID()] = True + # thread.Suspend() + except: + import traceback;traceback.print_exc() + + + diff --git a/pydevd_attach_to_process/winappdbg/__init__.py b/pydevd_attach_to_process/winappdbg/__init__.py new file mode 100644 index 0000000..aa138cc --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/__init__.py @@ -0,0 +1,263 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Windows application debugging engine for Python. + +by Mario Vilas (mvilas at gmail.com) + +Project: U{http://sourceforge.net/projects/winappdbg/} + +Web: U{http://winappdbg.sourceforge.net/} + +Blog: U{http://breakingcode.wordpress.com} + +@group Debugging: + Debug, EventHandler, EventSift, DebugLog + +@group Instrumentation: + System, Process, Thread, Module, Window, Registry + +@group Disassemblers: + Disassembler, + BeaEngine, DistormEngine, PyDasmEngine + +@group Crash reporting: + Crash, CrashDump, CrashDAO, CrashDictionary + +@group Memory search: + Search, + Pattern, + BytePattern, + TextPattern, + RegExpPattern, + HexPattern + +@group Debug events: + Event, + NoEvent, + CreateProcessEvent, + CreateThreadEvent, + ExitProcessEvent, + ExitThreadEvent, + LoadDLLEvent, + UnloadDLLEvent, + OutputDebugStringEvent, + RIPEvent, + ExceptionEvent + +@group Win32 API wrappers: + win32, Handle, ProcessHandle, ThreadHandle, FileHandle + +@group Helpers: + HexInput, HexOutput, HexDump, Color, Table, Logger, + PathOperations, + MemoryAddresses, + CustomAddressIterator, + DataAddressIterator, + ImageAddressIterator, + MappedAddressIterator, + ExecutableAddressIterator, + ReadableAddressIterator, + WriteableAddressIterator, + ExecutableAndWriteableAddressIterator, + DebugRegister, + Regenerator + +@group Warnings: + MixedBitsWarning, BreakpointWarning, BreakpointCallbackWarning, + EventCallbackWarning, DebugSymbolsWarning, CrashWarning + +@group Deprecated classes: + CrashContainer, CrashTable, CrashTableMSSQL, + VolatileCrashContainer, DummyCrashContainer + +@type version_number: float +@var version_number: This WinAppDbg major and minor version, + as a floating point number. Use this for compatibility checking. + +@type version: str +@var version: This WinAppDbg release version, + as a printable string. Use this to show to the user. + +@undocumented: plugins +""" + +__revision__ = "$Id$" + +# List of all public symbols +__all__ = [ + # Library version + 'version', + 'version_number', + + # from breakpoint import * +## 'Breakpoint', +## 'CodeBreakpoint', +## 'PageBreakpoint', +## 'HardwareBreakpoint', +## 'Hook', +## 'ApiHook', +## 'BufferWatch', + 'BreakpointWarning', + 'BreakpointCallbackWarning', + + # from crash import * + 'Crash', + 'CrashWarning', + 'CrashDictionary', + 'CrashContainer', + 'CrashTable', + 'CrashTableMSSQL', + 'VolatileCrashContainer', + 'DummyCrashContainer', + + # from debug import * + 'Debug', + 'MixedBitsWarning', + + # from disasm import * + 'Disassembler', + 'BeaEngine', + 'DistormEngine', + 'PyDasmEngine', + + # from event import * + 'EventHandler', + 'EventSift', +## 'EventFactory', +## 'EventDispatcher', + 'EventCallbackWarning', + 'Event', +## 'NoEvent', + 'CreateProcessEvent', + 'CreateThreadEvent', + 'ExitProcessEvent', + 'ExitThreadEvent', + 'LoadDLLEvent', + 'UnloadDLLEvent', + 'OutputDebugStringEvent', + 'RIPEvent', + 'ExceptionEvent', + + # from interactive import * +## 'ConsoleDebugger', + + # from module import * + 'Module', + 'DebugSymbolsWarning', + + # from process import * + 'Process', + + # from system import * + 'System', + + # from search import * + 'Search', + 'Pattern', + 'BytePattern', + 'TextPattern', + 'RegExpPattern', + 'HexPattern', + + # from registry import * + 'Registry', + + # from textio import * + 'HexDump', + 'HexInput', + 'HexOutput', + 'Color', + 'Table', + 'CrashDump', + 'DebugLog', + 'Logger', + + # from thread import * + 'Thread', + + # from util import * + 'PathOperations', + 'MemoryAddresses', + 'CustomAddressIterator', + 'DataAddressIterator', + 'ImageAddressIterator', + 'MappedAddressIterator', + 'ExecutableAddressIterator', + 'ReadableAddressIterator', + 'WriteableAddressIterator', + 'ExecutableAndWriteableAddressIterator', + 'DebugRegister', + + # from window import * + 'Window', + + # import win32 + 'win32', + + # from win32 import Handle, ProcessHandle, ThreadHandle, FileHandle + 'Handle', + 'ProcessHandle', + 'ThreadHandle', + 'FileHandle', + ] + +# Import all public symbols +from winappdbg.breakpoint import * +from winappdbg.crash import * +from winappdbg.debug import * +from winappdbg.disasm import * +from winappdbg.event import * +from winappdbg.interactive import * +from winappdbg.module import * +from winappdbg.process import * +from winappdbg.registry import * +from winappdbg.system import * +from winappdbg.search import * +from winappdbg.textio import * +from winappdbg.thread import * +from winappdbg.util import * +from winappdbg.window import * + +import winappdbg.win32 +from winappdbg.win32 import Handle, ProcessHandle, ThreadHandle, FileHandle + +try: + from sql import * + __all__.append('CrashDAO') +except ImportError: + import warnings + warnings.warn("No SQL database support present (missing dependencies?)", + ImportWarning) + +# Library version +version_number = 1.5 +version = "Version %s" % version_number diff --git a/pydevd_attach_to_process/winappdbg/breakpoint.py b/pydevd_attach_to_process/winappdbg/breakpoint.py new file mode 100644 index 0000000..3b9ca73 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/breakpoint.py @@ -0,0 +1,4822 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Breakpoints. + +@group Breakpoints: + Breakpoint, CodeBreakpoint, PageBreakpoint, HardwareBreakpoint, + BufferWatch, Hook, ApiHook + +@group Warnings: + BreakpointWarning, BreakpointCallbackWarning +""" + +__revision__ = "$Id$" + +__all__ = [ + + # Base class for breakpoints + 'Breakpoint', + + # Breakpoint implementations + 'CodeBreakpoint', + 'PageBreakpoint', + 'HardwareBreakpoint', + + # Hooks and watches + 'Hook', + 'ApiHook', + 'BufferWatch', + + # Warnings + 'BreakpointWarning', + 'BreakpointCallbackWarning', + + ] + +from winappdbg import win32 +from winappdbg import compat +import sys +from winappdbg.process import Process, Thread +from winappdbg.util import DebugRegister, MemoryAddresses +from winappdbg.textio import HexDump + +import ctypes +import warnings +import traceback + +#============================================================================== + +class BreakpointWarning (UserWarning): + """ + This warning is issued when a non-fatal error occurs that's related to + breakpoints. + """ + +class BreakpointCallbackWarning (RuntimeWarning): + """ + This warning is issued when an uncaught exception was raised by a + breakpoint's user-defined callback. + """ + +#============================================================================== + +class Breakpoint (object): + """ + Base class for breakpoints. + Here's the breakpoints state machine. + + @see: L{CodeBreakpoint}, L{PageBreakpoint}, L{HardwareBreakpoint} + + @group Breakpoint states: + DISABLED, ENABLED, ONESHOT, RUNNING + @group State machine: + hit, disable, enable, one_shot, running, + is_disabled, is_enabled, is_one_shot, is_running, + get_state, get_state_name + @group Information: + get_address, get_size, get_span, is_here + @group Conditional breakpoints: + is_conditional, is_unconditional, + get_condition, set_condition, eval_condition + @group Automatic breakpoints: + is_automatic, is_interactive, + get_action, set_action, run_action + + @cvar DISABLED: I{Disabled} S{->} Enabled, OneShot + @cvar ENABLED: I{Enabled} S{->} I{Running}, Disabled + @cvar ONESHOT: I{OneShot} S{->} I{Disabled} + @cvar RUNNING: I{Running} S{->} I{Enabled}, Disabled + + @type DISABLED: int + @type ENABLED: int + @type ONESHOT: int + @type RUNNING: int + + @type stateNames: dict E{lb} int S{->} str E{rb} + @cvar stateNames: User-friendly names for each breakpoint state. + + @type typeName: str + @cvar typeName: User friendly breakpoint type string. + """ + + # I don't think transitions Enabled <-> OneShot should be allowed... plus + # it would require special handling to avoid setting the same bp twice + + DISABLED = 0 + ENABLED = 1 + ONESHOT = 2 + RUNNING = 3 + + typeName = 'breakpoint' + + stateNames = { + DISABLED : 'disabled', + ENABLED : 'enabled', + ONESHOT : 'one shot', + RUNNING : 'running', + } + + def __init__(self, address, size = 1, condition = True, action = None): + """ + Breakpoint object. + + @type address: int + @param address: Memory address for breakpoint. + + @type size: int + @param size: Size of breakpoint in bytes (defaults to 1). + + @type condition: function + @param condition: (Optional) Condition callback function. + + The callback signature is:: + + def condition_callback(event): + return True # returns True or False + + Where B{event} is an L{Event} object, + and the return value is a boolean + (C{True} to dispatch the event, C{False} otherwise). + + @type action: function + @param action: (Optional) Action callback function. + If specified, the event is handled by this callback instead of + being dispatched normally. + + The callback signature is:: + + def action_callback(event): + pass # no return value + + Where B{event} is an L{Event} object. + """ + self.__address = address + self.__size = size + self.__state = self.DISABLED + + self.set_condition(condition) + self.set_action(action) + + def __repr__(self): + if self.is_disabled(): + state = 'Disabled' + else: + state = 'Active (%s)' % self.get_state_name() + if self.is_conditional(): + condition = 'conditional' + else: + condition = 'unconditional' + name = self.typeName + size = self.get_size() + if size == 1: + address = HexDump.address( self.get_address() ) + else: + begin = self.get_address() + end = begin + size + begin = HexDump.address(begin) + end = HexDump.address(end) + address = "range %s-%s" % (begin, end) + msg = "<%s %s %s at remote address %s>" + msg = msg % (state, condition, name, address) + return msg + +#------------------------------------------------------------------------------ + + def is_disabled(self): + """ + @rtype: bool + @return: C{True} if the breakpoint is in L{DISABLED} state. + """ + return self.get_state() == self.DISABLED + + def is_enabled(self): + """ + @rtype: bool + @return: C{True} if the breakpoint is in L{ENABLED} state. + """ + return self.get_state() == self.ENABLED + + def is_one_shot(self): + """ + @rtype: bool + @return: C{True} if the breakpoint is in L{ONESHOT} state. + """ + return self.get_state() == self.ONESHOT + + def is_running(self): + """ + @rtype: bool + @return: C{True} if the breakpoint is in L{RUNNING} state. + """ + return self.get_state() == self.RUNNING + + def is_here(self, address): + """ + @rtype: bool + @return: C{True} if the address is within the range of the breakpoint. + """ + begin = self.get_address() + end = begin + self.get_size() + return begin <= address < end + + def get_address(self): + """ + @rtype: int + @return: The target memory address for the breakpoint. + """ + return self.__address + + def get_size(self): + """ + @rtype: int + @return: The size in bytes of the breakpoint. + """ + return self.__size + + def get_span(self): + """ + @rtype: tuple( int, int ) + @return: + Starting and ending address of the memory range + covered by the breakpoint. + """ + address = self.get_address() + size = self.get_size() + return ( address, address + size ) + + def get_state(self): + """ + @rtype: int + @return: The current state of the breakpoint + (L{DISABLED}, L{ENABLED}, L{ONESHOT}, L{RUNNING}). + """ + return self.__state + + def get_state_name(self): + """ + @rtype: str + @return: The name of the current state of the breakpoint. + """ + return self.stateNames[ self.get_state() ] + +#------------------------------------------------------------------------------ + + def is_conditional(self): + """ + @see: L{__init__} + @rtype: bool + @return: C{True} if the breakpoint has a condition callback defined. + """ + # Do not evaluate as boolean! Test for identity with True instead. + return self.__condition is not True + + def is_unconditional(self): + """ + @rtype: bool + @return: C{True} if the breakpoint doesn't have a condition callback defined. + """ + # Do not evaluate as boolean! Test for identity with True instead. + return self.__condition is True + + def get_condition(self): + """ + @rtype: bool, function + @return: Returns the condition callback for conditional breakpoints. + Returns C{True} for unconditional breakpoints. + """ + return self.__condition + + def set_condition(self, condition = True): + """ + Sets a new condition callback for the breakpoint. + + @see: L{__init__} + + @type condition: function + @param condition: (Optional) Condition callback function. + """ + if condition is None: + self.__condition = True + else: + self.__condition = condition + + def eval_condition(self, event): + """ + Evaluates the breakpoint condition, if any was set. + + @type event: L{Event} + @param event: Debug event triggered by the breakpoint. + + @rtype: bool + @return: C{True} to dispatch the event, C{False} otherwise. + """ + condition = self.get_condition() + if condition is True: # shortcut for unconditional breakpoints + return True + if callable(condition): + try: + return bool( condition(event) ) + except Exception: + e = sys.exc_info()[1] + msg = ("Breakpoint condition callback %r" + " raised an exception: %s") + msg = msg % (condition, traceback.format_exc(e)) + warnings.warn(msg, BreakpointCallbackWarning) + return False + return bool( condition ) # force evaluation now + +#------------------------------------------------------------------------------ + + def is_automatic(self): + """ + @rtype: bool + @return: C{True} if the breakpoint has an action callback defined. + """ + return self.__action is not None + + def is_interactive(self): + """ + @rtype: bool + @return: + C{True} if the breakpoint doesn't have an action callback defined. + """ + return self.__action is None + + def get_action(self): + """ + @rtype: bool, function + @return: Returns the action callback for automatic breakpoints. + Returns C{None} for interactive breakpoints. + """ + return self.__action + + def set_action(self, action = None): + """ + Sets a new action callback for the breakpoint. + + @type action: function + @param action: (Optional) Action callback function. + """ + self.__action = action + + def run_action(self, event): + """ + Executes the breakpoint action callback, if any was set. + + @type event: L{Event} + @param event: Debug event triggered by the breakpoint. + """ + action = self.get_action() + if action is not None: + try: + return bool( action(event) ) + except Exception: + e = sys.exc_info()[1] + msg = ("Breakpoint action callback %r" + " raised an exception: %s") + msg = msg % (action, traceback.format_exc(e)) + warnings.warn(msg, BreakpointCallbackWarning) + return False + return True + +#------------------------------------------------------------------------------ + + def __bad_transition(self, state): + """ + Raises an C{AssertionError} exception for an invalid state transition. + + @see: L{stateNames} + + @type state: int + @param state: Intended breakpoint state. + + @raise Exception: Always. + """ + statemsg = "" + oldState = self.stateNames[ self.get_state() ] + newState = self.stateNames[ state ] + msg = "Invalid state transition (%s -> %s)" \ + " for breakpoint at address %s" + msg = msg % (oldState, newState, HexDump.address(self.get_address())) + raise AssertionError(msg) + + def disable(self, aProcess, aThread): + """ + Transition to L{DISABLED} state. + - When hit: OneShot S{->} Disabled + - Forced by user: Enabled, OneShot, Running S{->} Disabled + - Transition from running state may require special handling + by the breakpoint implementation class. + + @type aProcess: L{Process} + @param aProcess: Process object. + + @type aThread: L{Thread} + @param aThread: Thread object. + """ +## if self.__state not in (self.ENABLED, self.ONESHOT, self.RUNNING): +## self.__bad_transition(self.DISABLED) + self.__state = self.DISABLED + + def enable(self, aProcess, aThread): + """ + Transition to L{ENABLED} state. + - When hit: Running S{->} Enabled + - Forced by user: Disabled, Running S{->} Enabled + - Transition from running state may require special handling + by the breakpoint implementation class. + + @type aProcess: L{Process} + @param aProcess: Process object. + + @type aThread: L{Thread} + @param aThread: Thread object. + """ +## if self.__state not in (self.DISABLED, self.RUNNING): +## self.__bad_transition(self.ENABLED) + self.__state = self.ENABLED + + def one_shot(self, aProcess, aThread): + """ + Transition to L{ONESHOT} state. + - Forced by user: Disabled S{->} OneShot + + @type aProcess: L{Process} + @param aProcess: Process object. + + @type aThread: L{Thread} + @param aThread: Thread object. + """ +## if self.__state != self.DISABLED: +## self.__bad_transition(self.ONESHOT) + self.__state = self.ONESHOT + + def running(self, aProcess, aThread): + """ + Transition to L{RUNNING} state. + - When hit: Enabled S{->} Running + + @type aProcess: L{Process} + @param aProcess: Process object. + + @type aThread: L{Thread} + @param aThread: Thread object. + """ + if self.__state != self.ENABLED: + self.__bad_transition(self.RUNNING) + self.__state = self.RUNNING + + def hit(self, event): + """ + Notify a breakpoint that it's been hit. + + This triggers the corresponding state transition and sets the + C{breakpoint} property of the given L{Event} object. + + @see: L{disable}, L{enable}, L{one_shot}, L{running} + + @type event: L{Event} + @param event: Debug event to handle (depends on the breakpoint type). + + @raise AssertionError: Disabled breakpoints can't be hit. + """ + aProcess = event.get_process() + aThread = event.get_thread() + state = self.get_state() + + event.breakpoint = self + + if state == self.ENABLED: + self.running(aProcess, aThread) + + elif state == self.RUNNING: + self.enable(aProcess, aThread) + + elif state == self.ONESHOT: + self.disable(aProcess, aThread) + + elif state == self.DISABLED: + # this should not happen + msg = "Hit a disabled breakpoint at address %s" + msg = msg % HexDump.address( self.get_address() ) + warnings.warn(msg, BreakpointWarning) + +#============================================================================== + +# XXX TODO +# Check if the user is trying to set a code breakpoint on a memory mapped file, +# so we don't end up writing the int3 instruction in the file by accident. + +class CodeBreakpoint (Breakpoint): + """ + Code execution breakpoints (using an int3 opcode). + + @see: L{Debug.break_at} + + @type bpInstruction: str + @cvar bpInstruction: Breakpoint instruction for the current processor. + """ + + typeName = 'code breakpoint' + + if win32.arch in (win32.ARCH_I386, win32.ARCH_AMD64): + bpInstruction = '\xCC' # int 3 + + def __init__(self, address, condition = True, action = None): + """ + Code breakpoint object. + + @see: L{Breakpoint.__init__} + + @type address: int + @param address: Memory address for breakpoint. + + @type condition: function + @param condition: (Optional) Condition callback function. + + @type action: function + @param action: (Optional) Action callback function. + """ + if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64): + msg = "Code breakpoints not supported for %s" % win32.arch + raise NotImplementedError(msg) + Breakpoint.__init__(self, address, len(self.bpInstruction), + condition, action) + self.__previousValue = self.bpInstruction + + def __set_bp(self, aProcess): + """ + Writes a breakpoint instruction at the target address. + + @type aProcess: L{Process} + @param aProcess: Process object. + """ + address = self.get_address() + self.__previousValue = aProcess.read(address, len(self.bpInstruction)) + if self.__previousValue == self.bpInstruction: + msg = "Possible overlapping code breakpoints at %s" + msg = msg % HexDump.address(address) + warnings.warn(msg, BreakpointWarning) + aProcess.write(address, self.bpInstruction) + + def __clear_bp(self, aProcess): + """ + Restores the original byte at the target address. + + @type aProcess: L{Process} + @param aProcess: Process object. + """ + address = self.get_address() + currentValue = aProcess.read(address, len(self.bpInstruction)) + if currentValue == self.bpInstruction: + # Only restore the previous value if the int3 is still there. + aProcess.write(self.get_address(), self.__previousValue) + else: + self.__previousValue = currentValue + msg = "Overwritten code breakpoint at %s" + msg = msg % HexDump.address(address) + warnings.warn(msg, BreakpointWarning) + + def disable(self, aProcess, aThread): + if not self.is_disabled() and not self.is_running(): + self.__clear_bp(aProcess) + super(CodeBreakpoint, self).disable(aProcess, aThread) + + def enable(self, aProcess, aThread): + if not self.is_enabled() and not self.is_one_shot(): + self.__set_bp(aProcess) + super(CodeBreakpoint, self).enable(aProcess, aThread) + + def one_shot(self, aProcess, aThread): + if not self.is_enabled() and not self.is_one_shot(): + self.__set_bp(aProcess) + super(CodeBreakpoint, self).one_shot(aProcess, aThread) + + # FIXME race condition here (however unlikely) + # If another thread runs on over the target address while + # the breakpoint is in RUNNING state, we'll miss it. There + # is a solution to this but it's somewhat complicated, so + # I'm leaving it for another version of the debugger. :( + def running(self, aProcess, aThread): + if self.is_enabled(): + self.__clear_bp(aProcess) + aThread.set_tf() + super(CodeBreakpoint, self).running(aProcess, aThread) + +#============================================================================== + +# TODO: +# * If the original page was already a guard page, the exception should be +# passed to the debugee instead of being handled by the debugger. +# * If the original page was already a guard page, it should NOT be converted +# to a no-access page when disabling the breakpoint. +# * If the page permissions were modified after the breakpoint was enabled, +# no change should be done on them when disabling the breakpoint. For this +# we need to remember the original page permissions instead of blindly +# setting and clearing the guard page bit on them. +# * Some pages seem to be "magic" and resist all attempts at changing their +# protect bits (for example the pages where the PEB and TEB reside). Maybe +# a more descriptive error message could be shown in this case. + +class PageBreakpoint (Breakpoint): + """ + Page access breakpoint (using guard pages). + + @see: L{Debug.watch_buffer} + + @group Information: + get_size_in_pages + """ + + typeName = 'page breakpoint' + +#------------------------------------------------------------------------------ + + def __init__(self, address, pages = 1, condition = True, action = None): + """ + Page breakpoint object. + + @see: L{Breakpoint.__init__} + + @type address: int + @param address: Memory address for breakpoint. + + @type pages: int + @param address: Size of breakpoint in pages. + + @type condition: function + @param condition: (Optional) Condition callback function. + + @type action: function + @param action: (Optional) Action callback function. + """ + Breakpoint.__init__(self, address, pages * MemoryAddresses.pageSize, + condition, action) +## if (address & 0x00000FFF) != 0: + floordiv_align = long(address) // long(MemoryAddresses.pageSize) + truediv_align = float(address) / float(MemoryAddresses.pageSize) + if floordiv_align != truediv_align: + msg = "Address of page breakpoint " \ + "must be aligned to a page size boundary " \ + "(value %s received)" % HexDump.address(address) + raise ValueError(msg) + + def get_size_in_pages(self): + """ + @rtype: int + @return: The size in pages of the breakpoint. + """ + # The size is always a multiple of the page size. + return self.get_size() // MemoryAddresses.pageSize + + def __set_bp(self, aProcess): + """ + Sets the target pages as guard pages. + + @type aProcess: L{Process} + @param aProcess: Process object. + """ + lpAddress = self.get_address() + dwSize = self.get_size() + flNewProtect = aProcess.mquery(lpAddress).Protect + flNewProtect = flNewProtect | win32.PAGE_GUARD + aProcess.mprotect(lpAddress, dwSize, flNewProtect) + + def __clear_bp(self, aProcess): + """ + Restores the original permissions of the target pages. + + @type aProcess: L{Process} + @param aProcess: Process object. + """ + lpAddress = self.get_address() + flNewProtect = aProcess.mquery(lpAddress).Protect + flNewProtect = flNewProtect & (0xFFFFFFFF ^ win32.PAGE_GUARD) # DWORD + aProcess.mprotect(lpAddress, self.get_size(), flNewProtect) + + def disable(self, aProcess, aThread): + if not self.is_disabled(): + self.__clear_bp(aProcess) + super(PageBreakpoint, self).disable(aProcess, aThread) + + def enable(self, aProcess, aThread): + if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64): + msg = "Only one-shot page breakpoints are supported for %s" + raise NotImplementedError(msg % win32.arch) + if not self.is_enabled() and not self.is_one_shot(): + self.__set_bp(aProcess) + super(PageBreakpoint, self).enable(aProcess, aThread) + + def one_shot(self, aProcess, aThread): + if not self.is_enabled() and not self.is_one_shot(): + self.__set_bp(aProcess) + super(PageBreakpoint, self).one_shot(aProcess, aThread) + + def running(self, aProcess, aThread): + aThread.set_tf() + super(PageBreakpoint, self).running(aProcess, aThread) + +#============================================================================== + +class HardwareBreakpoint (Breakpoint): + """ + Hardware breakpoint (using debug registers). + + @see: L{Debug.watch_variable} + + @group Information: + get_slot, get_trigger, get_watch + + @group Trigger flags: + BREAK_ON_EXECUTION, BREAK_ON_WRITE, BREAK_ON_ACCESS + + @group Watch size flags: + WATCH_BYTE, WATCH_WORD, WATCH_DWORD, WATCH_QWORD + + @type BREAK_ON_EXECUTION: int + @cvar BREAK_ON_EXECUTION: Break on execution. + + @type BREAK_ON_WRITE: int + @cvar BREAK_ON_WRITE: Break on write. + + @type BREAK_ON_ACCESS: int + @cvar BREAK_ON_ACCESS: Break on read or write. + + @type WATCH_BYTE: int + @cvar WATCH_BYTE: Watch a byte. + + @type WATCH_WORD: int + @cvar WATCH_WORD: Watch a word (2 bytes). + + @type WATCH_DWORD: int + @cvar WATCH_DWORD: Watch a double word (4 bytes). + + @type WATCH_QWORD: int + @cvar WATCH_QWORD: Watch one quad word (8 bytes). + + @type validTriggers: tuple + @cvar validTriggers: Valid trigger flag values. + + @type validWatchSizes: tuple + @cvar validWatchSizes: Valid watch flag values. + """ + + typeName = 'hardware breakpoint' + + BREAK_ON_EXECUTION = DebugRegister.BREAK_ON_EXECUTION + BREAK_ON_WRITE = DebugRegister.BREAK_ON_WRITE + BREAK_ON_ACCESS = DebugRegister.BREAK_ON_ACCESS + + WATCH_BYTE = DebugRegister.WATCH_BYTE + WATCH_WORD = DebugRegister.WATCH_WORD + WATCH_DWORD = DebugRegister.WATCH_DWORD + WATCH_QWORD = DebugRegister.WATCH_QWORD + + validTriggers = ( + BREAK_ON_EXECUTION, + BREAK_ON_WRITE, + BREAK_ON_ACCESS, + ) + + validWatchSizes = ( + WATCH_BYTE, + WATCH_WORD, + WATCH_DWORD, + WATCH_QWORD, + ) + + def __init__(self, address, triggerFlag = BREAK_ON_ACCESS, + sizeFlag = WATCH_DWORD, + condition = True, + action = None): + """ + Hardware breakpoint object. + + @see: L{Breakpoint.__init__} + + @type address: int + @param address: Memory address for breakpoint. + + @type triggerFlag: int + @param triggerFlag: Trigger of breakpoint. Must be one of the following: + + - L{BREAK_ON_EXECUTION} + + Break on code execution. + + - L{BREAK_ON_WRITE} + + Break on memory read or write. + + - L{BREAK_ON_ACCESS} + + Break on memory write. + + @type sizeFlag: int + @param sizeFlag: Size of breakpoint. Must be one of the following: + + - L{WATCH_BYTE} + + One (1) byte in size. + + - L{WATCH_WORD} + + Two (2) bytes in size. + + - L{WATCH_DWORD} + + Four (4) bytes in size. + + - L{WATCH_QWORD} + + Eight (8) bytes in size. + + @type condition: function + @param condition: (Optional) Condition callback function. + + @type action: function + @param action: (Optional) Action callback function. + """ + if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64): + msg = "Hardware breakpoints not supported for %s" % win32.arch + raise NotImplementedError(msg) + if sizeFlag == self.WATCH_BYTE: + size = 1 + elif sizeFlag == self.WATCH_WORD: + size = 2 + elif sizeFlag == self.WATCH_DWORD: + size = 4 + elif sizeFlag == self.WATCH_QWORD: + size = 8 + else: + msg = "Invalid size flag for hardware breakpoint (%s)" + msg = msg % repr(sizeFlag) + raise ValueError(msg) + + if triggerFlag not in self.validTriggers: + msg = "Invalid trigger flag for hardware breakpoint (%s)" + msg = msg % repr(triggerFlag) + raise ValueError(msg) + + Breakpoint.__init__(self, address, size, condition, action) + self.__trigger = triggerFlag + self.__watch = sizeFlag + self.__slot = None + + def __clear_bp(self, aThread): + """ + Clears this breakpoint from the debug registers. + + @type aThread: L{Thread} + @param aThread: Thread object. + """ + if self.__slot is not None: + aThread.suspend() + try: + ctx = aThread.get_context(win32.CONTEXT_DEBUG_REGISTERS) + DebugRegister.clear_bp(ctx, self.__slot) + aThread.set_context(ctx) + self.__slot = None + finally: + aThread.resume() + + def __set_bp(self, aThread): + """ + Sets this breakpoint in the debug registers. + + @type aThread: L{Thread} + @param aThread: Thread object. + """ + if self.__slot is None: + aThread.suspend() + try: + ctx = aThread.get_context(win32.CONTEXT_DEBUG_REGISTERS) + self.__slot = DebugRegister.find_slot(ctx) + if self.__slot is None: + msg = "No available hardware breakpoint slots for thread ID %d" + msg = msg % aThread.get_tid() + raise RuntimeError(msg) + DebugRegister.set_bp(ctx, self.__slot, self.get_address(), + self.__trigger, self.__watch) + aThread.set_context(ctx) + finally: + aThread.resume() + + def get_slot(self): + """ + @rtype: int + @return: The debug register number used by this breakpoint, + or C{None} if the breakpoint is not active. + """ + return self.__slot + + def get_trigger(self): + """ + @see: L{validTriggers} + @rtype: int + @return: The breakpoint trigger flag. + """ + return self.__trigger + + def get_watch(self): + """ + @see: L{validWatchSizes} + @rtype: int + @return: The breakpoint watch flag. + """ + return self.__watch + + def disable(self, aProcess, aThread): + if not self.is_disabled(): + self.__clear_bp(aThread) + super(HardwareBreakpoint, self).disable(aProcess, aThread) + + def enable(self, aProcess, aThread): + if not self.is_enabled() and not self.is_one_shot(): + self.__set_bp(aThread) + super(HardwareBreakpoint, self).enable(aProcess, aThread) + + def one_shot(self, aProcess, aThread): + if not self.is_enabled() and not self.is_one_shot(): + self.__set_bp(aThread) + super(HardwareBreakpoint, self).one_shot(aProcess, aThread) + + def running(self, aProcess, aThread): + self.__clear_bp(aThread) + super(HardwareBreakpoint, self).running(aProcess, aThread) + aThread.set_tf() + +#============================================================================== + +# XXX FIXME +# +# The implementation of function hooks is very simple. A breakpoint is set at +# the entry point. Each time it's hit the "pre" callback is executed. If a +# "post" callback was defined, a one-shot breakpoint is set at the return +# address - and when that breakpoint hits, the "post" callback is executed. +# +# Functions hooks, as they are implemented now, don't work correctly for +# recursive functions. The problem is we don't know when to remove the +# breakpoint at the return address. Also there could be more than one return +# address. +# +# One possible solution would involve a dictionary of lists, where the key +# would be the thread ID and the value a stack of return addresses. But we +# still don't know what to do if the "wrong" return address is hit for some +# reason (maybe check the stack pointer?). Or if both a code and a hardware +# breakpoint are hit simultaneously. +# +# For now, the workaround for the user is to set only the "pre" callback for +# functions that are known to be recursive. +# +# If an exception is thrown by a hooked function and caught by one of it's +# parent functions, the "post" callback won't be called and weird stuff may +# happen. A possible solution is to put a breakpoint in the system call that +# unwinds the stack, to detect this case and remove the "post" breakpoint. +# +# Hooks may also behave oddly if the return address is overwritten by a buffer +# overflow bug (this is similar to the exception problem). But it's probably a +# minor issue since when you're fuzzing a function for overflows you're usually +# not interested in the return value anyway. + +# TODO: an API to modify the hooked function's arguments + +class Hook (object): + """ + Factory class to produce hook objects. Used by L{Debug.hook_function} and + L{Debug.stalk_function}. + + When you try to instance this class, one of the architecture specific + implementations is returned instead. + + Instances act as an action callback for code breakpoints set at the + beginning of a function. It automatically retrieves the parameters from + the stack, sets a breakpoint at the return address and retrieves the + return value from the function call. + + @see: L{_Hook_i386}, L{_Hook_amd64} + + @type useHardwareBreakpoints: bool + @cvar useHardwareBreakpoints: C{True} to try to use hardware breakpoints, + C{False} otherwise. + """ + + # This is a factory class that returns + # the architecture specific implementation. + def __new__(cls, *argv, **argd): + try: + arch = argd['arch'] + del argd['arch'] + except KeyError: + try: + arch = argv[4] + argv = argv[:4] + argv[5:] + except IndexError: + raise TypeError("Missing 'arch' argument!") + if arch is None: + arch = win32.arch + if arch == win32.ARCH_I386: + return _Hook_i386(*argv, **argd) + if arch == win32.ARCH_AMD64: + return _Hook_amd64(*argv, **argd) + return object.__new__(cls, *argv, **argd) + + # XXX FIXME + # + # Hardware breakpoints don't work correctly (or al all) in old VirtualBox + # versions (3.0 and below). + # + # Maybe there should be a way to autodetect the buggy VirtualBox versions + # and tell Hook objects not to use hardware breakpoints? + # + # For now the workaround is to manually set this variable to True when + # WinAppDbg is installed on a physical machine. + # + useHardwareBreakpoints = False + + def __init__(self, preCB = None, postCB = None, + paramCount = None, signature = None, + arch = None): + """ + @type preCB: function + @param preCB: (Optional) Callback triggered on function entry. + + The signature for the callback should be something like this:: + + def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags): + + # return address + ra = params[0] + + # function arguments start from here... + szFilename = event.get_process().peek_string(lpFilename) + + # (...) + + Note that all pointer types are treated like void pointers, so your + callback won't get the string or structure pointed to by it, but + the remote memory address instead. This is so to prevent the ctypes + library from being "too helpful" and trying to dereference the + pointer. To get the actual data being pointed to, use one of the + L{Process.read} methods. + + @type postCB: function + @param postCB: (Optional) Callback triggered on function exit. + + The signature for the callback should be something like this:: + + def post_LoadLibraryEx(event, return_value): + + # (...) + + @type paramCount: int + @param paramCount: + (Optional) Number of parameters for the C{preCB} callback, + not counting the return address. Parameters are read from + the stack and assumed to be DWORDs in 32 bits and QWORDs in 64. + + This is a faster way to pull stack parameters in 32 bits, but in 64 + bits (or with some odd APIs in 32 bits) it won't be useful, since + not all arguments to the hooked function will be of the same size. + + For a more reliable and cross-platform way of hooking use the + C{signature} argument instead. + + @type signature: tuple + @param signature: + (Optional) Tuple of C{ctypes} data types that constitute the + hooked function signature. When the function is called, this will + be used to parse the arguments from the stack. Overrides the + C{paramCount} argument. + + @type arch: str + @param arch: (Optional) Target architecture. Defaults to the current + architecture. See: L{win32.arch} + """ + self.__preCB = preCB + self.__postCB = postCB + self.__paramStack = dict() # tid -> list of tuple( arg, arg, arg... ) + + self._paramCount = paramCount + + if win32.arch != win32.ARCH_I386: + self.useHardwareBreakpoints = False + + if win32.bits == 64 and paramCount and not signature: + signature = (win32.QWORD,) * paramCount + + if signature: + self._signature = self._calc_signature(signature) + else: + self._signature = None + + def _cast_signature_pointers_to_void(self, signature): + c_void_p = ctypes.c_void_p + c_char_p = ctypes.c_char_p + c_wchar_p = ctypes.c_wchar_p + _Pointer = ctypes._Pointer + cast = ctypes.cast + for i in compat.xrange(len(signature)): + t = signature[i] + if t is not c_void_p and (issubclass(t, _Pointer) \ + or t in [c_char_p, c_wchar_p]): + signature[i] = cast(t, c_void_p) + + def _calc_signature(self, signature): + raise NotImplementedError( + "Hook signatures are not supported for architecture: %s" \ + % win32.arch) + + def _get_return_address(self, aProcess, aThread): + return None + + def _get_function_arguments(self, aProcess, aThread): + if self._signature or self._paramCount: + raise NotImplementedError( + "Hook signatures are not supported for architecture: %s" \ + % win32.arch) + return () + + def _get_return_value(self, aThread): + return None + + # By using break_at() to set a process-wide breakpoint on the function's + # return address, we might hit a race condition when more than one thread + # is being debugged. + # + # Hardware breakpoints should be used instead. But since a thread can run + # out of those, we need to fall back to this method when needed. + + def __call__(self, event): + """ + Handles the breakpoint event on entry of the function. + + @type event: L{ExceptionEvent} + @param event: Breakpoint hit event. + + @raise WindowsError: An error occured. + """ + debug = event.debug + + dwProcessId = event.get_pid() + dwThreadId = event.get_tid() + aProcess = event.get_process() + aThread = event.get_thread() + + # Get the return address and function arguments. + ra = self._get_return_address(aProcess, aThread) + params = self._get_function_arguments(aProcess, aThread) + + # Keep the function arguments for later use. + self.__push_params(dwThreadId, params) + + # If we need to hook the return from the function... + bHookedReturn = False + if ra is not None and self.__postCB is not None: + + # Try to set a one shot hardware breakpoint at the return address. + useHardwareBreakpoints = self.useHardwareBreakpoints + if useHardwareBreakpoints: + try: + debug.define_hardware_breakpoint( + dwThreadId, + ra, + event.debug.BP_BREAK_ON_EXECUTION, + event.debug.BP_WATCH_BYTE, + True, + self.__postCallAction_hwbp + ) + debug.enable_one_shot_hardware_breakpoint(dwThreadId, ra) + bHookedReturn = True + except Exception: + e = sys.exc_info()[1] + useHardwareBreakpoints = False + msg = ("Failed to set hardware breakpoint" + " at address %s for thread ID %d") + msg = msg % (HexDump.address(ra), dwThreadId) + warnings.warn(msg, BreakpointWarning) + + # If not possible, set a code breakpoint instead. + if not useHardwareBreakpoints: + try: + debug.break_at(dwProcessId, ra, + self.__postCallAction_codebp) + bHookedReturn = True + except Exception: + e = sys.exc_info()[1] + msg = ("Failed to set code breakpoint" + " at address %s for process ID %d") + msg = msg % (HexDump.address(ra), dwProcessId) + warnings.warn(msg, BreakpointWarning) + + # Call the "pre" callback. + try: + self.__callHandler(self.__preCB, event, ra, *params) + + # If no "post" callback is defined, forget the function arguments. + finally: + if not bHookedReturn: + self.__pop_params(dwThreadId) + + def __postCallAction_hwbp(self, event): + """ + Handles hardware breakpoint events on return from the function. + + @type event: L{ExceptionEvent} + @param event: Single step event. + """ + + # Remove the one shot hardware breakpoint + # at the return address location in the stack. + tid = event.get_tid() + address = event.breakpoint.get_address() + event.debug.erase_hardware_breakpoint(tid, address) + + # Call the "post" callback. + try: + self.__postCallAction(event) + + # Forget the parameters. + finally: + self.__pop_params(tid) + + def __postCallAction_codebp(self, event): + """ + Handles code breakpoint events on return from the function. + + @type event: L{ExceptionEvent} + @param event: Breakpoint hit event. + """ + + # If the breakpoint was accidentally hit by another thread, + # pass it to the debugger instead of calling the "post" callback. + # + # XXX FIXME: + # I suppose this check will fail under some weird conditions... + # + tid = event.get_tid() + if tid not in self.__paramStack: + return True + + # Remove the code breakpoint at the return address. + pid = event.get_pid() + address = event.breakpoint.get_address() + event.debug.dont_break_at(pid, address) + + # Call the "post" callback. + try: + self.__postCallAction(event) + + # Forget the parameters. + finally: + self.__pop_params(tid) + + def __postCallAction(self, event): + """ + Calls the "post" callback. + + @type event: L{ExceptionEvent} + @param event: Breakpoint hit event. + """ + aThread = event.get_thread() + retval = self._get_return_value(aThread) + self.__callHandler(self.__postCB, event, retval) + + def __callHandler(self, callback, event, *params): + """ + Calls a "pre" or "post" handler, if set. + + @type callback: function + @param callback: Callback function to call. + + @type event: L{ExceptionEvent} + @param event: Breakpoint hit event. + + @type params: tuple + @param params: Parameters for the callback function. + """ + if callback is not None: + event.hook = self + callback(event, *params) + + def __push_params(self, tid, params): + """ + Remembers the arguments tuple for the last call to the hooked function + from this thread. + + @type tid: int + @param tid: Thread global ID. + + @type params: tuple( arg, arg, arg... ) + @param params: Tuple of arguments. + """ + stack = self.__paramStack.get( tid, [] ) + stack.append(params) + self.__paramStack[tid] = stack + + def __pop_params(self, tid): + """ + Forgets the arguments tuple for the last call to the hooked function + from this thread. + + @type tid: int + @param tid: Thread global ID. + """ + stack = self.__paramStack[tid] + stack.pop() + if not stack: + del self.__paramStack[tid] + + def get_params(self, tid): + """ + Returns the parameters found in the stack when the hooked function + was last called by this thread. + + @type tid: int + @param tid: Thread global ID. + + @rtype: tuple( arg, arg, arg... ) + @return: Tuple of arguments. + """ + try: + params = self.get_params_stack(tid)[-1] + except IndexError: + msg = "Hooked function called from thread %d already returned" + raise IndexError(msg % tid) + return params + + def get_params_stack(self, tid): + """ + Returns the parameters found in the stack each time the hooked function + was called by this thread and hasn't returned yet. + + @type tid: int + @param tid: Thread global ID. + + @rtype: list of tuple( arg, arg, arg... ) + @return: List of argument tuples. + """ + try: + stack = self.__paramStack[tid] + except KeyError: + msg = "Hooked function was not called from thread %d" + raise KeyError(msg % tid) + return stack + + def hook(self, debug, pid, address): + """ + Installs the function hook at a given process and address. + + @see: L{unhook} + + @warning: Do not call from an function hook callback. + + @type debug: L{Debug} + @param debug: Debug object. + + @type pid: int + @param pid: Process ID. + + @type address: int + @param address: Function address. + """ + return debug.break_at(pid, address, self) + + def unhook(self, debug, pid, address): + """ + Removes the function hook at a given process and address. + + @see: L{hook} + + @warning: Do not call from an function hook callback. + + @type debug: L{Debug} + @param debug: Debug object. + + @type pid: int + @param pid: Process ID. + + @type address: int + @param address: Function address. + """ + return debug.dont_break_at(pid, address) + +class _Hook_i386 (Hook): + """ + Implementation details for L{Hook} on the L{win32.ARCH_I386} architecture. + """ + + # We don't want to inherit the parent class __new__ method. + __new__ = object.__new__ + + def _calc_signature(self, signature): + self._cast_signature_pointers_to_void(signature) + class Arguments (ctypes.Structure): + _fields_ = [ ("arg_%s" % i, signature[i]) \ + for i in compat.xrange(len(signature) - 1, -1, -1) ] + return Arguments + + def _get_return_address(self, aProcess, aThread): + return aProcess.read_pointer( aThread.get_sp() ) + + def _get_function_arguments(self, aProcess, aThread): + if self._signature: + params = aThread.read_stack_structure(self._signature, + offset = win32.sizeof(win32.LPVOID)) + elif self._paramCount: + params = aThread.read_stack_dwords(self._paramCount, + offset = win32.sizeof(win32.LPVOID)) + else: + params = () + return params + + def _get_return_value(self, aThread): + ctx = aThread.get_context(win32.CONTEXT_INTEGER) + return ctx['Eax'] + +class _Hook_amd64 (Hook): + """ + Implementation details for L{Hook} on the L{win32.ARCH_AMD64} architecture. + """ + + # We don't want to inherit the parent class __new__ method. + __new__ = object.__new__ + + # Make a list of floating point types. + __float_types = ( + ctypes.c_double, + ctypes.c_float, + ) + # Long doubles are not supported in old versions of ctypes! + try: + __float_types += (ctypes.c_longdouble,) + except AttributeError: + pass + + def _calc_signature(self, signature): + self._cast_signature_pointers_to_void(signature) + + float_types = self.__float_types + c_sizeof = ctypes.sizeof + reg_size = c_sizeof(ctypes.c_size_t) + + reg_int_sig = [] + reg_float_sig = [] + stack_sig = [] + + for i in compat.xrange(len(signature)): + arg = signature[i] + name = "arg_%d" % i + stack_sig.insert( 0, (name, arg) ) + if i < 4: + if type(arg) in float_types: + reg_float_sig.append( (name, arg) ) + elif c_sizeof(arg) <= reg_size: + reg_int_sig.append( (name, arg) ) + else: + msg = ("Hook signatures don't support structures" + " within the first 4 arguments of a function" + " for the %s architecture") % win32.arch + raise NotImplementedError(msg) + + if reg_int_sig: + class RegisterArguments (ctypes.Structure): + _fields_ = reg_int_sig + else: + RegisterArguments = None + if reg_float_sig: + class FloatArguments (ctypes.Structure): + _fields_ = reg_float_sig + else: + FloatArguments = None + if stack_sig: + class StackArguments (ctypes.Structure): + _fields_ = stack_sig + else: + StackArguments = None + + return (len(signature), + RegisterArguments, + FloatArguments, + StackArguments) + + def _get_return_address(self, aProcess, aThread): + return aProcess.read_pointer( aThread.get_sp() ) + + def _get_function_arguments(self, aProcess, aThread): + if self._signature: + (args_count, + RegisterArguments, + FloatArguments, + StackArguments) = self._signature + arguments = {} + if StackArguments: + address = aThread.get_sp() + win32.sizeof(win32.LPVOID) + stack_struct = aProcess.read_structure(address, + StackArguments) + stack_args = dict( + [ (name, stack_struct.__getattribute__(name)) + for (name, type) in stack_struct._fields_ ] + ) + arguments.update(stack_args) + flags = 0 + if RegisterArguments: + flags = flags | win32.CONTEXT_INTEGER + if FloatArguments: + flags = flags | win32.CONTEXT_MMX_REGISTERS + if flags: + ctx = aThread.get_context(flags) + if RegisterArguments: + buffer = (win32.QWORD * 4)(ctx['Rcx'], ctx['Rdx'], + ctx['R8'], ctx['R9']) + reg_args = self._get_arguments_from_buffer(buffer, + RegisterArguments) + arguments.update(reg_args) + if FloatArguments: + buffer = (win32.M128A * 4)(ctx['XMM0'], ctx['XMM1'], + ctx['XMM2'], ctx['XMM3']) + float_args = self._get_arguments_from_buffer(buffer, + FloatArguments) + arguments.update(float_args) + params = tuple( [ arguments["arg_%d" % i] + for i in compat.xrange(args_count) ] ) + else: + params = () + return params + + def _get_arguments_from_buffer(self, buffer, structure): + b_ptr = ctypes.pointer(buffer) + v_ptr = ctypes.cast(b_ptr, ctypes.c_void_p) + s_ptr = ctypes.cast(v_ptr, ctypes.POINTER(structure)) + struct = s_ptr.contents + return dict( + [ (name, struct.__getattribute__(name)) + for (name, type) in struct._fields_ ] + ) + + def _get_return_value(self, aThread): + ctx = aThread.get_context(win32.CONTEXT_INTEGER) + return ctx['Rax'] + +#------------------------------------------------------------------------------ + +# This class acts as a factory of Hook objects, one per target process. +# Said objects are deleted by the unhook() method. + +class ApiHook (object): + """ + Used by L{EventHandler}. + + This class acts as an action callback for code breakpoints set at the + beginning of a function. It automatically retrieves the parameters from + the stack, sets a breakpoint at the return address and retrieves the + return value from the function call. + + @see: L{EventHandler.apiHooks} + + @type modName: str + @ivar modName: Module name. + + @type procName: str + @ivar procName: Procedure name. + """ + + def __init__(self, eventHandler, modName, procName, paramCount = None, + signature = None): + """ + @type eventHandler: L{EventHandler} + @param eventHandler: Event handler instance. This is where the hook + callbacks are to be defined (see below). + + @type modName: str + @param modName: Module name. + + @type procName: str + @param procName: Procedure name. + The pre and post callbacks will be deduced from it. + + For example, if the procedure is "LoadLibraryEx" the callback + routines will be "pre_LoadLibraryEx" and "post_LoadLibraryEx". + + The signature for the callbacks should be something like this:: + + def pre_LoadLibraryEx(self, event, ra, lpFilename, hFile, dwFlags): + + # return address + ra = params[0] + + # function arguments start from here... + szFilename = event.get_process().peek_string(lpFilename) + + # (...) + + def post_LoadLibraryEx(self, event, return_value): + + # (...) + + Note that all pointer types are treated like void pointers, so your + callback won't get the string or structure pointed to by it, but + the remote memory address instead. This is so to prevent the ctypes + library from being "too helpful" and trying to dereference the + pointer. To get the actual data being pointed to, use one of the + L{Process.read} methods. + + @type paramCount: int + @param paramCount: + (Optional) Number of parameters for the C{preCB} callback, + not counting the return address. Parameters are read from + the stack and assumed to be DWORDs in 32 bits and QWORDs in 64. + + This is a faster way to pull stack parameters in 32 bits, but in 64 + bits (or with some odd APIs in 32 bits) it won't be useful, since + not all arguments to the hooked function will be of the same size. + + For a more reliable and cross-platform way of hooking use the + C{signature} argument instead. + + @type signature: tuple + @param signature: + (Optional) Tuple of C{ctypes} data types that constitute the + hooked function signature. When the function is called, this will + be used to parse the arguments from the stack. Overrides the + C{paramCount} argument. + """ + self.__modName = modName + self.__procName = procName + self.__paramCount = paramCount + self.__signature = signature + self.__preCB = getattr(eventHandler, 'pre_%s' % procName, None) + self.__postCB = getattr(eventHandler, 'post_%s' % procName, None) + self.__hook = dict() + + def __call__(self, event): + """ + Handles the breakpoint event on entry of the function. + + @type event: L{ExceptionEvent} + @param event: Breakpoint hit event. + + @raise WindowsError: An error occured. + """ + pid = event.get_pid() + try: + hook = self.__hook[pid] + except KeyError: + hook = Hook(self.__preCB, self.__postCB, + self.__paramCount, self.__signature, + event.get_process().get_arch() ) + self.__hook[pid] = hook + return hook(event) + + @property + def modName(self): + return self.__modName + + @property + def procName(self): + return self.__procName + + def hook(self, debug, pid): + """ + Installs the API hook on a given process and module. + + @warning: Do not call from an API hook callback. + + @type debug: L{Debug} + @param debug: Debug object. + + @type pid: int + @param pid: Process ID. + """ + label = "%s!%s" % (self.__modName, self.__procName) + try: + hook = self.__hook[pid] + except KeyError: + try: + aProcess = debug.system.get_process(pid) + except KeyError: + aProcess = Process(pid) + hook = Hook(self.__preCB, self.__postCB, + self.__paramCount, self.__signature, + aProcess.get_arch() ) + self.__hook[pid] = hook + hook.hook(debug, pid, label) + + def unhook(self, debug, pid): + """ + Removes the API hook from the given process and module. + + @warning: Do not call from an API hook callback. + + @type debug: L{Debug} + @param debug: Debug object. + + @type pid: int + @param pid: Process ID. + """ + try: + hook = self.__hook[pid] + except KeyError: + return + label = "%s!%s" % (self.__modName, self.__procName) + hook.unhook(debug, pid, label) + del self.__hook[pid] + +#============================================================================== + +class BufferWatch (object): + """ + Returned by L{Debug.watch_buffer}. + + This object uniquely references a buffer being watched, even if there are + multiple watches set on the exact memory region. + + @type pid: int + @ivar pid: Process ID. + + @type start: int + @ivar start: Memory address of the start of the buffer. + + @type end: int + @ivar end: Memory address of the end of the buffer. + + @type action: callable + @ivar action: Action callback. + + @type oneshot: bool + @ivar oneshot: C{True} for one shot breakpoints, C{False} otherwise. + """ + + def __init__(self, pid, start, end, action = None, oneshot = False): + self.__pid = pid + self.__start = start + self.__end = end + self.__action = action + self.__oneshot = oneshot + + @property + def pid(self): + return self.__pid + + @property + def start(self): + return self.__start + + @property + def end(self): + return self.__end + + @property + def action(self): + return self.__action + + @property + def oneshot(self): + return self.__oneshot + + def match(self, address): + """ + Determine if the given memory address lies within the watched buffer. + + @rtype: bool + @return: C{True} if the given memory address lies within the watched + buffer, C{False} otherwise. + """ + return self.__start <= address < self.__end + +#============================================================================== + +class _BufferWatchCondition (object): + """ + Used by L{Debug.watch_buffer}. + + This class acts as a condition callback for page breakpoints. + It emulates page breakpoints that can overlap and/or take up less + than a page's size. + """ + + def __init__(self): + self.__ranges = list() # list of BufferWatch in definition order + + def add(self, bw): + """ + Adds a buffer watch identifier. + + @type bw: L{BufferWatch} + @param bw: + Buffer watch identifier. + """ + self.__ranges.append(bw) + + def remove(self, bw): + """ + Removes a buffer watch identifier. + + @type bw: L{BufferWatch} + @param bw: + Buffer watch identifier. + + @raise KeyError: The buffer watch identifier was already removed. + """ + try: + self.__ranges.remove(bw) + except KeyError: + if not bw.oneshot: + raise + + def remove_last_match(self, address, size): + """ + Removes the last buffer from the watch object + to match the given address and size. + + @type address: int + @param address: Memory address of buffer to stop watching. + + @type size: int + @param size: Size in bytes of buffer to stop watching. + + @rtype: int + @return: Number of matching elements found. Only the last one to be + added is actually deleted upon calling this method. + + This counter allows you to know if there are more matching elements + and how many. + """ + count = 0 + start = address + end = address + size - 1 + matched = None + for item in self.__ranges: + if item.match(start) and item.match(end): + matched = item + count += 1 + self.__ranges.remove(matched) + return count + + def count(self): + """ + @rtype: int + @return: Number of buffers being watched. + """ + return len(self.__ranges) + + def __call__(self, event): + """ + Breakpoint condition callback. + + This method will also call the action callbacks for each + buffer being watched. + + @type event: L{ExceptionEvent} + @param event: Guard page exception event. + + @rtype: bool + @return: C{True} if the address being accessed belongs + to at least one of the buffers that was being watched + and had no action callback. + """ + address = event.get_exception_information(1) + bCondition = False + for bw in self.__ranges: + bMatched = bw.match(address) + try: + action = bw.action + if bMatched and action is not None: + try: + action(event) + except Exception: + e = sys.exc_info()[1] + msg = ("Breakpoint action callback %r" + " raised an exception: %s") + msg = msg % (action, traceback.format_exc(e)) + warnings.warn(msg, BreakpointCallbackWarning) + else: + bCondition = bCondition or bMatched + finally: + if bMatched and bw.oneshot: + event.debug.dont_watch_buffer(bw) + return bCondition + +#============================================================================== + +class _BreakpointContainer (object): + """ + Encapsulates the capability to contain Breakpoint objects. + + @group Breakpoints: + break_at, watch_variable, watch_buffer, hook_function, + dont_break_at, dont_watch_variable, dont_watch_buffer, + dont_hook_function, unhook_function, + break_on_error, dont_break_on_error + + @group Stalking: + stalk_at, stalk_variable, stalk_buffer, stalk_function, + dont_stalk_at, dont_stalk_variable, dont_stalk_buffer, + dont_stalk_function + + @group Tracing: + is_tracing, get_traced_tids, + start_tracing, stop_tracing, + start_tracing_process, stop_tracing_process, + start_tracing_all, stop_tracing_all + + @group Symbols: + resolve_label, resolve_exported_function + + @group Advanced breakpoint use: + define_code_breakpoint, + define_page_breakpoint, + define_hardware_breakpoint, + has_code_breakpoint, + has_page_breakpoint, + has_hardware_breakpoint, + get_code_breakpoint, + get_page_breakpoint, + get_hardware_breakpoint, + erase_code_breakpoint, + erase_page_breakpoint, + erase_hardware_breakpoint, + enable_code_breakpoint, + enable_page_breakpoint, + enable_hardware_breakpoint, + enable_one_shot_code_breakpoint, + enable_one_shot_page_breakpoint, + enable_one_shot_hardware_breakpoint, + disable_code_breakpoint, + disable_page_breakpoint, + disable_hardware_breakpoint + + @group Listing breakpoints: + get_all_breakpoints, + get_all_code_breakpoints, + get_all_page_breakpoints, + get_all_hardware_breakpoints, + get_process_breakpoints, + get_process_code_breakpoints, + get_process_page_breakpoints, + get_process_hardware_breakpoints, + get_thread_hardware_breakpoints, + get_all_deferred_code_breakpoints, + get_process_deferred_code_breakpoints + + @group Batch operations on breakpoints: + enable_all_breakpoints, + enable_one_shot_all_breakpoints, + disable_all_breakpoints, + erase_all_breakpoints, + enable_process_breakpoints, + enable_one_shot_process_breakpoints, + disable_process_breakpoints, + erase_process_breakpoints + + @group Breakpoint types: + BP_TYPE_ANY, BP_TYPE_CODE, BP_TYPE_PAGE, BP_TYPE_HARDWARE + @group Breakpoint states: + BP_STATE_DISABLED, BP_STATE_ENABLED, BP_STATE_ONESHOT, BP_STATE_RUNNING + @group Memory breakpoint trigger flags: + BP_BREAK_ON_EXECUTION, BP_BREAK_ON_WRITE, BP_BREAK_ON_ACCESS + @group Memory breakpoint size flags: + BP_WATCH_BYTE, BP_WATCH_WORD, BP_WATCH_DWORD, BP_WATCH_QWORD + + @type BP_TYPE_ANY: int + @cvar BP_TYPE_ANY: To get all breakpoints + @type BP_TYPE_CODE: int + @cvar BP_TYPE_CODE: To get code breakpoints only + @type BP_TYPE_PAGE: int + @cvar BP_TYPE_PAGE: To get page breakpoints only + @type BP_TYPE_HARDWARE: int + @cvar BP_TYPE_HARDWARE: To get hardware breakpoints only + + @type BP_STATE_DISABLED: int + @cvar BP_STATE_DISABLED: Breakpoint is disabled. + @type BP_STATE_ENABLED: int + @cvar BP_STATE_ENABLED: Breakpoint is enabled. + @type BP_STATE_ONESHOT: int + @cvar BP_STATE_ONESHOT: Breakpoint is enabled for one shot. + @type BP_STATE_RUNNING: int + @cvar BP_STATE_RUNNING: Breakpoint is running (recently hit). + + @type BP_BREAK_ON_EXECUTION: int + @cvar BP_BREAK_ON_EXECUTION: Break on code execution. + @type BP_BREAK_ON_WRITE: int + @cvar BP_BREAK_ON_WRITE: Break on memory write. + @type BP_BREAK_ON_ACCESS: int + @cvar BP_BREAK_ON_ACCESS: Break on memory read or write. + """ + + # Breakpoint types + BP_TYPE_ANY = 0 # to get all breakpoints + BP_TYPE_CODE = 1 + BP_TYPE_PAGE = 2 + BP_TYPE_HARDWARE = 3 + + # Breakpoint states + BP_STATE_DISABLED = Breakpoint.DISABLED + BP_STATE_ENABLED = Breakpoint.ENABLED + BP_STATE_ONESHOT = Breakpoint.ONESHOT + BP_STATE_RUNNING = Breakpoint.RUNNING + + # Memory breakpoint trigger flags + BP_BREAK_ON_EXECUTION = HardwareBreakpoint.BREAK_ON_EXECUTION + BP_BREAK_ON_WRITE = HardwareBreakpoint.BREAK_ON_WRITE + BP_BREAK_ON_ACCESS = HardwareBreakpoint.BREAK_ON_ACCESS + + # Memory breakpoint size flags + BP_WATCH_BYTE = HardwareBreakpoint.WATCH_BYTE + BP_WATCH_WORD = HardwareBreakpoint.WATCH_WORD + BP_WATCH_QWORD = HardwareBreakpoint.WATCH_QWORD + BP_WATCH_DWORD = HardwareBreakpoint.WATCH_DWORD + + def __init__(self): + self.__codeBP = dict() # (pid, address) -> CodeBreakpoint + self.__pageBP = dict() # (pid, address) -> PageBreakpoint + self.__hardwareBP = dict() # tid -> [ HardwareBreakpoint ] + self.__runningBP = dict() # tid -> set( Breakpoint ) + self.__tracing = set() # set( tid ) + self.__deferredBP = dict() # pid -> label -> (action, oneshot) + +#------------------------------------------------------------------------------ + + # This operates on the dictionary of running breakpoints. + # Since the bps are meant to stay alive no cleanup is done here. + + def __get_running_bp_set(self, tid): + "Auxiliary method." + return self.__runningBP.get(tid, ()) + + def __add_running_bp(self, tid, bp): + "Auxiliary method." + if tid not in self.__runningBP: + self.__runningBP[tid] = set() + self.__runningBP[tid].add(bp) + + def __del_running_bp(self, tid, bp): + "Auxiliary method." + self.__runningBP[tid].remove(bp) + if not self.__runningBP[tid]: + del self.__runningBP[tid] + + def __del_running_bp_from_all_threads(self, bp): + "Auxiliary method." + for (tid, bpset) in compat.iteritems(self.__runningBP): + if bp in bpset: + bpset.remove(bp) + self.system.get_thread(tid).clear_tf() + +#------------------------------------------------------------------------------ + + # This is the cleanup code. Mostly called on response to exit/unload debug + # events. If possible it shouldn't raise exceptions on runtime errors. + # The main goal here is to avoid memory or handle leaks. + + def __cleanup_breakpoint(self, event, bp): + "Auxiliary method." + try: + process = event.get_process() + thread = event.get_thread() + bp.disable(process, thread) # clear the debug regs / trap flag + except Exception: + pass + bp.set_condition(True) # break possible circular reference + bp.set_action(None) # break possible circular reference + + def __cleanup_thread(self, event): + """ + Auxiliary method for L{_notify_exit_thread} + and L{_notify_exit_process}. + """ + tid = event.get_tid() + + # Cleanup running breakpoints + try: + for bp in self.__runningBP[tid]: + self.__cleanup_breakpoint(event, bp) + del self.__runningBP[tid] + except KeyError: + pass + + # Cleanup hardware breakpoints + try: + for bp in self.__hardwareBP[tid]: + self.__cleanup_breakpoint(event, bp) + del self.__hardwareBP[tid] + except KeyError: + pass + + # Cleanup set of threads being traced + if tid in self.__tracing: + self.__tracing.remove(tid) + + def __cleanup_process(self, event): + """ + Auxiliary method for L{_notify_exit_process}. + """ + pid = event.get_pid() + process = event.get_process() + + # Cleanup code breakpoints + for (bp_pid, bp_address) in compat.keys(self.__codeBP): + if bp_pid == pid: + bp = self.__codeBP[ (bp_pid, bp_address) ] + self.__cleanup_breakpoint(event, bp) + del self.__codeBP[ (bp_pid, bp_address) ] + + # Cleanup page breakpoints + for (bp_pid, bp_address) in compat.keys(self.__pageBP): + if bp_pid == pid: + bp = self.__pageBP[ (bp_pid, bp_address) ] + self.__cleanup_breakpoint(event, bp) + del self.__pageBP[ (bp_pid, bp_address) ] + + # Cleanup deferred code breakpoints + try: + del self.__deferredBP[pid] + except KeyError: + pass + + def __cleanup_module(self, event): + """ + Auxiliary method for L{_notify_unload_dll}. + """ + pid = event.get_pid() + process = event.get_process() + module = event.get_module() + + # Cleanup thread breakpoints on this module + for tid in process.iter_thread_ids(): + thread = process.get_thread(tid) + + # Running breakpoints + if tid in self.__runningBP: + bplist = list(self.__runningBP[tid]) + for bp in bplist: + bp_address = bp.get_address() + if process.get_module_at_address(bp_address) == module: + self.__cleanup_breakpoint(event, bp) + self.__runningBP[tid].remove(bp) + + # Hardware breakpoints + if tid in self.__hardwareBP: + bplist = list(self.__hardwareBP[tid]) + for bp in bplist: + bp_address = bp.get_address() + if process.get_module_at_address(bp_address) == module: + self.__cleanup_breakpoint(event, bp) + self.__hardwareBP[tid].remove(bp) + + # Cleanup code breakpoints on this module + for (bp_pid, bp_address) in compat.keys(self.__codeBP): + if bp_pid == pid: + if process.get_module_at_address(bp_address) == module: + bp = self.__codeBP[ (bp_pid, bp_address) ] + self.__cleanup_breakpoint(event, bp) + del self.__codeBP[ (bp_pid, bp_address) ] + + # Cleanup page breakpoints on this module + for (bp_pid, bp_address) in compat.keys(self.__pageBP): + if bp_pid == pid: + if process.get_module_at_address(bp_address) == module: + bp = self.__pageBP[ (bp_pid, bp_address) ] + self.__cleanup_breakpoint(event, bp) + del self.__pageBP[ (bp_pid, bp_address) ] + +#------------------------------------------------------------------------------ + + # Defining breakpoints. + + # Code breakpoints. + def define_code_breakpoint(self, dwProcessId, address, condition = True, + action = None): + """ + Creates a disabled code breakpoint at the given address. + + @see: + L{has_code_breakpoint}, + L{get_code_breakpoint}, + L{enable_code_breakpoint}, + L{enable_one_shot_code_breakpoint}, + L{disable_code_breakpoint}, + L{erase_code_breakpoint} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of the code instruction to break at. + + @type condition: function + @param condition: (Optional) Condition callback function. + + The callback signature is:: + + def condition_callback(event): + return True # returns True or False + + Where B{event} is an L{Event} object, + and the return value is a boolean + (C{True} to dispatch the event, C{False} otherwise). + + @type action: function + @param action: (Optional) Action callback function. + If specified, the event is handled by this callback instead of + being dispatched normally. + + The callback signature is:: + + def action_callback(event): + pass # no return value + + Where B{event} is an L{Event} object, + and the return value is a boolean + (C{True} to dispatch the event, C{False} otherwise). + + @rtype: L{CodeBreakpoint} + @return: The code breakpoint object. + """ + process = self.system.get_process(dwProcessId) + bp = CodeBreakpoint(address, condition, action) + + key = (dwProcessId, bp.get_address()) + if key in self.__codeBP: + msg = "Already exists (PID %d) : %r" + raise KeyError(msg % (dwProcessId, self.__codeBP[key])) + self.__codeBP[key] = bp + return bp + + # Page breakpoints. + def define_page_breakpoint(self, dwProcessId, address, pages = 1, + condition = True, + action = None): + """ + Creates a disabled page breakpoint at the given address. + + @see: + L{has_page_breakpoint}, + L{get_page_breakpoint}, + L{enable_page_breakpoint}, + L{enable_one_shot_page_breakpoint}, + L{disable_page_breakpoint}, + L{erase_page_breakpoint} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of the first page to watch. + + @type pages: int + @param pages: Number of pages to watch. + + @type condition: function + @param condition: (Optional) Condition callback function. + + The callback signature is:: + + def condition_callback(event): + return True # returns True or False + + Where B{event} is an L{Event} object, + and the return value is a boolean + (C{True} to dispatch the event, C{False} otherwise). + + @type action: function + @param action: (Optional) Action callback function. + If specified, the event is handled by this callback instead of + being dispatched normally. + + The callback signature is:: + + def action_callback(event): + pass # no return value + + Where B{event} is an L{Event} object, + and the return value is a boolean + (C{True} to dispatch the event, C{False} otherwise). + + @rtype: L{PageBreakpoint} + @return: The page breakpoint object. + """ + process = self.system.get_process(dwProcessId) + bp = PageBreakpoint(address, pages, condition, action) + begin = bp.get_address() + end = begin + bp.get_size() + + address = begin + pageSize = MemoryAddresses.pageSize + while address < end: + key = (dwProcessId, address) + if key in self.__pageBP: + msg = "Already exists (PID %d) : %r" + msg = msg % (dwProcessId, self.__pageBP[key]) + raise KeyError(msg) + address = address + pageSize + + address = begin + while address < end: + key = (dwProcessId, address) + self.__pageBP[key] = bp + address = address + pageSize + return bp + + # Hardware breakpoints. + def define_hardware_breakpoint(self, dwThreadId, address, + triggerFlag = BP_BREAK_ON_ACCESS, + sizeFlag = BP_WATCH_DWORD, + condition = True, + action = None): + """ + Creates a disabled hardware breakpoint at the given address. + + @see: + L{has_hardware_breakpoint}, + L{get_hardware_breakpoint}, + L{enable_hardware_breakpoint}, + L{enable_one_shot_hardware_breakpoint}, + L{disable_hardware_breakpoint}, + L{erase_hardware_breakpoint} + + @note: + Hardware breakpoints do not seem to work properly on VirtualBox. + See U{http://www.virtualbox.org/ticket/477}. + + @type dwThreadId: int + @param dwThreadId: Thread global ID. + + @type address: int + @param address: Memory address to watch. + + @type triggerFlag: int + @param triggerFlag: Trigger of breakpoint. Must be one of the following: + + - L{BP_BREAK_ON_EXECUTION} + + Break on code execution. + + - L{BP_BREAK_ON_WRITE} + + Break on memory read or write. + + - L{BP_BREAK_ON_ACCESS} + + Break on memory write. + + @type sizeFlag: int + @param sizeFlag: Size of breakpoint. Must be one of the following: + + - L{BP_WATCH_BYTE} + + One (1) byte in size. + + - L{BP_WATCH_WORD} + + Two (2) bytes in size. + + - L{BP_WATCH_DWORD} + + Four (4) bytes in size. + + - L{BP_WATCH_QWORD} + + Eight (8) bytes in size. + + @type condition: function + @param condition: (Optional) Condition callback function. + + The callback signature is:: + + def condition_callback(event): + return True # returns True or False + + Where B{event} is an L{Event} object, + and the return value is a boolean + (C{True} to dispatch the event, C{False} otherwise). + + @type action: function + @param action: (Optional) Action callback function. + If specified, the event is handled by this callback instead of + being dispatched normally. + + The callback signature is:: + + def action_callback(event): + pass # no return value + + Where B{event} is an L{Event} object, + and the return value is a boolean + (C{True} to dispatch the event, C{False} otherwise). + + @rtype: L{HardwareBreakpoint} + @return: The hardware breakpoint object. + """ + thread = self.system.get_thread(dwThreadId) + bp = HardwareBreakpoint(address, triggerFlag, sizeFlag, condition, + action) + begin = bp.get_address() + end = begin + bp.get_size() + + if dwThreadId in self.__hardwareBP: + bpSet = self.__hardwareBP[dwThreadId] + for oldbp in bpSet: + old_begin = oldbp.get_address() + old_end = old_begin + oldbp.get_size() + if MemoryAddresses.do_ranges_intersect(begin, end, old_begin, + old_end): + msg = "Already exists (TID %d) : %r" % (dwThreadId, oldbp) + raise KeyError(msg) + else: + bpSet = set() + self.__hardwareBP[dwThreadId] = bpSet + bpSet.add(bp) + return bp + +#------------------------------------------------------------------------------ + + # Checking breakpoint definitions. + + def has_code_breakpoint(self, dwProcessId, address): + """ + Checks if a code breakpoint is defined at the given address. + + @see: + L{define_code_breakpoint}, + L{get_code_breakpoint}, + L{erase_code_breakpoint}, + L{enable_code_breakpoint}, + L{enable_one_shot_code_breakpoint}, + L{disable_code_breakpoint} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + + @rtype: bool + @return: C{True} if the breakpoint is defined, C{False} otherwise. + """ + return (dwProcessId, address) in self.__codeBP + + def has_page_breakpoint(self, dwProcessId, address): + """ + Checks if a page breakpoint is defined at the given address. + + @see: + L{define_page_breakpoint}, + L{get_page_breakpoint}, + L{erase_page_breakpoint}, + L{enable_page_breakpoint}, + L{enable_one_shot_page_breakpoint}, + L{disable_page_breakpoint} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + + @rtype: bool + @return: C{True} if the breakpoint is defined, C{False} otherwise. + """ + return (dwProcessId, address) in self.__pageBP + + def has_hardware_breakpoint(self, dwThreadId, address): + """ + Checks if a hardware breakpoint is defined at the given address. + + @see: + L{define_hardware_breakpoint}, + L{get_hardware_breakpoint}, + L{erase_hardware_breakpoint}, + L{enable_hardware_breakpoint}, + L{enable_one_shot_hardware_breakpoint}, + L{disable_hardware_breakpoint} + + @type dwThreadId: int + @param dwThreadId: Thread global ID. + + @type address: int + @param address: Memory address of breakpoint. + + @rtype: bool + @return: C{True} if the breakpoint is defined, C{False} otherwise. + """ + if dwThreadId in self.__hardwareBP: + bpSet = self.__hardwareBP[dwThreadId] + for bp in bpSet: + if bp.get_address() == address: + return True + return False + +#------------------------------------------------------------------------------ + + # Getting breakpoints. + + def get_code_breakpoint(self, dwProcessId, address): + """ + Returns the internally used breakpoint object, + for the code breakpoint defined at the given address. + + @warning: It's usually best to call the L{Debug} methods + instead of accessing the breakpoint objects directly. + + @see: + L{define_code_breakpoint}, + L{has_code_breakpoint}, + L{enable_code_breakpoint}, + L{enable_one_shot_code_breakpoint}, + L{disable_code_breakpoint}, + L{erase_code_breakpoint} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address where the breakpoint is defined. + + @rtype: L{CodeBreakpoint} + @return: The code breakpoint object. + """ + key = (dwProcessId, address) + if key not in self.__codeBP: + msg = "No breakpoint at process %d, address %s" + address = HexDump.address(address) + raise KeyError(msg % (dwProcessId, address)) + return self.__codeBP[key] + + def get_page_breakpoint(self, dwProcessId, address): + """ + Returns the internally used breakpoint object, + for the page breakpoint defined at the given address. + + @warning: It's usually best to call the L{Debug} methods + instead of accessing the breakpoint objects directly. + + @see: + L{define_page_breakpoint}, + L{has_page_breakpoint}, + L{enable_page_breakpoint}, + L{enable_one_shot_page_breakpoint}, + L{disable_page_breakpoint}, + L{erase_page_breakpoint} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address where the breakpoint is defined. + + @rtype: L{PageBreakpoint} + @return: The page breakpoint object. + """ + key = (dwProcessId, address) + if key not in self.__pageBP: + msg = "No breakpoint at process %d, address %s" + address = HexDump.addresS(address) + raise KeyError(msg % (dwProcessId, address)) + return self.__pageBP[key] + + def get_hardware_breakpoint(self, dwThreadId, address): + """ + Returns the internally used breakpoint object, + for the code breakpoint defined at the given address. + + @warning: It's usually best to call the L{Debug} methods + instead of accessing the breakpoint objects directly. + + @see: + L{define_hardware_breakpoint}, + L{has_hardware_breakpoint}, + L{get_code_breakpoint}, + L{enable_hardware_breakpoint}, + L{enable_one_shot_hardware_breakpoint}, + L{disable_hardware_breakpoint}, + L{erase_hardware_breakpoint} + + @type dwThreadId: int + @param dwThreadId: Thread global ID. + + @type address: int + @param address: Memory address where the breakpoint is defined. + + @rtype: L{HardwareBreakpoint} + @return: The hardware breakpoint object. + """ + if dwThreadId not in self.__hardwareBP: + msg = "No hardware breakpoints set for thread %d" + raise KeyError(msg % dwThreadId) + for bp in self.__hardwareBP[dwThreadId]: + if bp.is_here(address): + return bp + msg = "No hardware breakpoint at thread %d, address %s" + raise KeyError(msg % (dwThreadId, HexDump.address(address))) + +#------------------------------------------------------------------------------ + + # Enabling and disabling breakpoints. + + def enable_code_breakpoint(self, dwProcessId, address): + """ + Enables the code breakpoint at the given address. + + @see: + L{define_code_breakpoint}, + L{has_code_breakpoint}, + L{enable_one_shot_code_breakpoint}, + L{disable_code_breakpoint} + L{erase_code_breakpoint}, + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + p = self.system.get_process(dwProcessId) + bp = self.get_code_breakpoint(dwProcessId, address) + if bp.is_running(): + self.__del_running_bp_from_all_threads(bp) + bp.enable(p, None) # XXX HACK thread is not used + + def enable_page_breakpoint(self, dwProcessId, address): + """ + Enables the page breakpoint at the given address. + + @see: + L{define_page_breakpoint}, + L{has_page_breakpoint}, + L{get_page_breakpoint}, + L{enable_one_shot_page_breakpoint}, + L{disable_page_breakpoint} + L{erase_page_breakpoint}, + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + p = self.system.get_process(dwProcessId) + bp = self.get_page_breakpoint(dwProcessId, address) + if bp.is_running(): + self.__del_running_bp_from_all_threads(bp) + bp.enable(p, None) # XXX HACK thread is not used + + def enable_hardware_breakpoint(self, dwThreadId, address): + """ + Enables the hardware breakpoint at the given address. + + @see: + L{define_hardware_breakpoint}, + L{has_hardware_breakpoint}, + L{get_hardware_breakpoint}, + L{enable_one_shot_hardware_breakpoint}, + L{disable_hardware_breakpoint} + L{erase_hardware_breakpoint}, + + @note: Do not set hardware breakpoints while processing the system + breakpoint event. + + @type dwThreadId: int + @param dwThreadId: Thread global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + t = self.system.get_thread(dwThreadId) + bp = self.get_hardware_breakpoint(dwThreadId, address) + if bp.is_running(): + self.__del_running_bp_from_all_threads(bp) + bp.enable(None, t) # XXX HACK process is not used + + def enable_one_shot_code_breakpoint(self, dwProcessId, address): + """ + Enables the code breakpoint at the given address for only one shot. + + @see: + L{define_code_breakpoint}, + L{has_code_breakpoint}, + L{get_code_breakpoint}, + L{enable_code_breakpoint}, + L{disable_code_breakpoint} + L{erase_code_breakpoint}, + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + p = self.system.get_process(dwProcessId) + bp = self.get_code_breakpoint(dwProcessId, address) + if bp.is_running(): + self.__del_running_bp_from_all_threads(bp) + bp.one_shot(p, None) # XXX HACK thread is not used + + def enable_one_shot_page_breakpoint(self, dwProcessId, address): + """ + Enables the page breakpoint at the given address for only one shot. + + @see: + L{define_page_breakpoint}, + L{has_page_breakpoint}, + L{get_page_breakpoint}, + L{enable_page_breakpoint}, + L{disable_page_breakpoint} + L{erase_page_breakpoint}, + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + p = self.system.get_process(dwProcessId) + bp = self.get_page_breakpoint(dwProcessId, address) + if bp.is_running(): + self.__del_running_bp_from_all_threads(bp) + bp.one_shot(p, None) # XXX HACK thread is not used + + def enable_one_shot_hardware_breakpoint(self, dwThreadId, address): + """ + Enables the hardware breakpoint at the given address for only one shot. + + @see: + L{define_hardware_breakpoint}, + L{has_hardware_breakpoint}, + L{get_hardware_breakpoint}, + L{enable_hardware_breakpoint}, + L{disable_hardware_breakpoint} + L{erase_hardware_breakpoint}, + + @type dwThreadId: int + @param dwThreadId: Thread global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + t = self.system.get_thread(dwThreadId) + bp = self.get_hardware_breakpoint(dwThreadId, address) + if bp.is_running(): + self.__del_running_bp_from_all_threads(bp) + bp.one_shot(None, t) # XXX HACK process is not used + + def disable_code_breakpoint(self, dwProcessId, address): + """ + Disables the code breakpoint at the given address. + + @see: + L{define_code_breakpoint}, + L{has_code_breakpoint}, + L{get_code_breakpoint}, + L{enable_code_breakpoint} + L{enable_one_shot_code_breakpoint}, + L{erase_code_breakpoint}, + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + p = self.system.get_process(dwProcessId) + bp = self.get_code_breakpoint(dwProcessId, address) + if bp.is_running(): + self.__del_running_bp_from_all_threads(bp) + bp.disable(p, None) # XXX HACK thread is not used + + def disable_page_breakpoint(self, dwProcessId, address): + """ + Disables the page breakpoint at the given address. + + @see: + L{define_page_breakpoint}, + L{has_page_breakpoint}, + L{get_page_breakpoint}, + L{enable_page_breakpoint} + L{enable_one_shot_page_breakpoint}, + L{erase_page_breakpoint}, + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + p = self.system.get_process(dwProcessId) + bp = self.get_page_breakpoint(dwProcessId, address) + if bp.is_running(): + self.__del_running_bp_from_all_threads(bp) + bp.disable(p, None) # XXX HACK thread is not used + + def disable_hardware_breakpoint(self, dwThreadId, address): + """ + Disables the hardware breakpoint at the given address. + + @see: + L{define_hardware_breakpoint}, + L{has_hardware_breakpoint}, + L{get_hardware_breakpoint}, + L{enable_hardware_breakpoint} + L{enable_one_shot_hardware_breakpoint}, + L{erase_hardware_breakpoint}, + + @type dwThreadId: int + @param dwThreadId: Thread global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + t = self.system.get_thread(dwThreadId) + p = t.get_process() + bp = self.get_hardware_breakpoint(dwThreadId, address) + if bp.is_running(): + self.__del_running_bp(dwThreadId, bp) + bp.disable(p, t) + +#------------------------------------------------------------------------------ + + # Undefining (erasing) breakpoints. + + def erase_code_breakpoint(self, dwProcessId, address): + """ + Erases the code breakpoint at the given address. + + @see: + L{define_code_breakpoint}, + L{has_code_breakpoint}, + L{get_code_breakpoint}, + L{enable_code_breakpoint}, + L{enable_one_shot_code_breakpoint}, + L{disable_code_breakpoint} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + bp = self.get_code_breakpoint(dwProcessId, address) + if not bp.is_disabled(): + self.disable_code_breakpoint(dwProcessId, address) + del self.__codeBP[ (dwProcessId, address) ] + + def erase_page_breakpoint(self, dwProcessId, address): + """ + Erases the page breakpoint at the given address. + + @see: + L{define_page_breakpoint}, + L{has_page_breakpoint}, + L{get_page_breakpoint}, + L{enable_page_breakpoint}, + L{enable_one_shot_page_breakpoint}, + L{disable_page_breakpoint} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + bp = self.get_page_breakpoint(dwProcessId, address) + begin = bp.get_address() + end = begin + bp.get_size() + if not bp.is_disabled(): + self.disable_page_breakpoint(dwProcessId, address) + address = begin + pageSize = MemoryAddresses.pageSize + while address < end: + del self.__pageBP[ (dwProcessId, address) ] + address = address + pageSize + + def erase_hardware_breakpoint(self, dwThreadId, address): + """ + Erases the hardware breakpoint at the given address. + + @see: + L{define_hardware_breakpoint}, + L{has_hardware_breakpoint}, + L{get_hardware_breakpoint}, + L{enable_hardware_breakpoint}, + L{enable_one_shot_hardware_breakpoint}, + L{disable_hardware_breakpoint} + + @type dwThreadId: int + @param dwThreadId: Thread global ID. + + @type address: int + @param address: Memory address of breakpoint. + """ + bp = self.get_hardware_breakpoint(dwThreadId, address) + if not bp.is_disabled(): + self.disable_hardware_breakpoint(dwThreadId, address) + bpSet = self.__hardwareBP[dwThreadId] + bpSet.remove(bp) + if not bpSet: + del self.__hardwareBP[dwThreadId] + +#------------------------------------------------------------------------------ + + # Listing breakpoints. + + def get_all_breakpoints(self): + """ + Returns all breakpoint objects as a list of tuples. + + Each tuple contains: + - Process global ID to which the breakpoint applies. + - Thread global ID to which the breakpoint applies, or C{None}. + - The L{Breakpoint} object itself. + + @note: If you're only interested in a specific breakpoint type, or in + breakpoints for a specific process or thread, it's probably faster + to call one of the following methods: + - L{get_all_code_breakpoints} + - L{get_all_page_breakpoints} + - L{get_all_hardware_breakpoints} + - L{get_process_code_breakpoints} + - L{get_process_page_breakpoints} + - L{get_process_hardware_breakpoints} + - L{get_thread_hardware_breakpoints} + + @rtype: list of tuple( pid, tid, bp ) + @return: List of all breakpoints. + """ + bplist = list() + + # Get the code breakpoints. + for (pid, bp) in self.get_all_code_breakpoints(): + bplist.append( (pid, None, bp) ) + + # Get the page breakpoints. + for (pid, bp) in self.get_all_page_breakpoints(): + bplist.append( (pid, None, bp) ) + + # Get the hardware breakpoints. + for (tid, bp) in self.get_all_hardware_breakpoints(): + pid = self.system.get_thread(tid).get_pid() + bplist.append( (pid, tid, bp) ) + + # Return the list of breakpoints. + return bplist + + def get_all_code_breakpoints(self): + """ + @rtype: list of tuple( int, L{CodeBreakpoint} ) + @return: All code breakpoints as a list of tuples (pid, bp). + """ + return [ (pid, bp) for ((pid, address), bp) in compat.iteritems(self.__codeBP) ] + + def get_all_page_breakpoints(self): + """ + @rtype: list of tuple( int, L{PageBreakpoint} ) + @return: All page breakpoints as a list of tuples (pid, bp). + """ +## return list( set( [ (pid, bp) for ((pid, address), bp) in compat.iteritems(self.__pageBP) ] ) ) + result = set() + for ((pid, address), bp) in compat.iteritems(self.__pageBP): + result.add( (pid, bp) ) + return list(result) + + def get_all_hardware_breakpoints(self): + """ + @rtype: list of tuple( int, L{HardwareBreakpoint} ) + @return: All hardware breakpoints as a list of tuples (tid, bp). + """ + result = list() + for (tid, bplist) in compat.iteritems(self.__hardwareBP): + for bp in bplist: + result.append( (tid, bp) ) + return result + + def get_process_breakpoints(self, dwProcessId): + """ + Returns all breakpoint objects for the given process as a list of tuples. + + Each tuple contains: + - Process global ID to which the breakpoint applies. + - Thread global ID to which the breakpoint applies, or C{None}. + - The L{Breakpoint} object itself. + + @note: If you're only interested in a specific breakpoint type, or in + breakpoints for a specific process or thread, it's probably faster + to call one of the following methods: + - L{get_all_code_breakpoints} + - L{get_all_page_breakpoints} + - L{get_all_hardware_breakpoints} + - L{get_process_code_breakpoints} + - L{get_process_page_breakpoints} + - L{get_process_hardware_breakpoints} + - L{get_thread_hardware_breakpoints} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @rtype: list of tuple( pid, tid, bp ) + @return: List of all breakpoints for the given process. + """ + bplist = list() + + # Get the code breakpoints. + for bp in self.get_process_code_breakpoints(dwProcessId): + bplist.append( (dwProcessId, None, bp) ) + + # Get the page breakpoints. + for bp in self.get_process_page_breakpoints(dwProcessId): + bplist.append( (dwProcessId, None, bp) ) + + # Get the hardware breakpoints. + for (tid, bp) in self.get_process_hardware_breakpoints(dwProcessId): + pid = self.system.get_thread(tid).get_pid() + bplist.append( (dwProcessId, tid, bp) ) + + # Return the list of breakpoints. + return bplist + + def get_process_code_breakpoints(self, dwProcessId): + """ + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @rtype: list of L{CodeBreakpoint} + @return: All code breakpoints for the given process. + """ + return [ bp for ((pid, address), bp) in compat.iteritems(self.__codeBP) \ + if pid == dwProcessId ] + + def get_process_page_breakpoints(self, dwProcessId): + """ + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @rtype: list of L{PageBreakpoint} + @return: All page breakpoints for the given process. + """ + return [ bp for ((pid, address), bp) in compat.iteritems(self.__pageBP) \ + if pid == dwProcessId ] + + def get_thread_hardware_breakpoints(self, dwThreadId): + """ + @see: L{get_process_hardware_breakpoints} + + @type dwThreadId: int + @param dwThreadId: Thread global ID. + + @rtype: list of L{HardwareBreakpoint} + @return: All hardware breakpoints for the given thread. + """ + result = list() + for (tid, bplist) in compat.iteritems(self.__hardwareBP): + if tid == dwThreadId: + for bp in bplist: + result.append(bp) + return result + + def get_process_hardware_breakpoints(self, dwProcessId): + """ + @see: L{get_thread_hardware_breakpoints} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @rtype: list of tuple( int, L{HardwareBreakpoint} ) + @return: All hardware breakpoints for each thread in the given process + as a list of tuples (tid, bp). + """ + result = list() + aProcess = self.system.get_process(dwProcessId) + for dwThreadId in aProcess.iter_thread_ids(): + if dwThreadId in self.__hardwareBP: + bplist = self.__hardwareBP[dwThreadId] + for bp in bplist: + result.append( (dwThreadId, bp) ) + return result + +## def get_all_hooks(self): +## """ +## @see: L{get_process_hooks} +## +## @rtype: list of tuple( int, int, L{Hook} ) +## @return: All defined hooks as a list of tuples (pid, address, hook). +## """ +## return [ (pid, address, hook) \ +## for ((pid, address), hook) in self.__hook_objects ] +## +## def get_process_hooks(self, dwProcessId): +## """ +## @see: L{get_all_hooks} +## +## @type dwProcessId: int +## @param dwProcessId: Process global ID. +## +## @rtype: list of tuple( int, int, L{Hook} ) +## @return: All hooks for the given process as a list of tuples +## (pid, address, hook). +## """ +## return [ (pid, address, hook) \ +## for ((pid, address), hook) in self.__hook_objects \ +## if pid == dwProcessId ] + +#------------------------------------------------------------------------------ + + # Batch operations on all breakpoints. + + def enable_all_breakpoints(self): + """ + Enables all disabled breakpoints in all processes. + + @see: + enable_code_breakpoint, + enable_page_breakpoint, + enable_hardware_breakpoint + """ + + # disable code breakpoints + for (pid, bp) in self.get_all_code_breakpoints(): + if bp.is_disabled(): + self.enable_code_breakpoint(pid, bp.get_address()) + + # disable page breakpoints + for (pid, bp) in self.get_all_page_breakpoints(): + if bp.is_disabled(): + self.enable_page_breakpoint(pid, bp.get_address()) + + # disable hardware breakpoints + for (tid, bp) in self.get_all_hardware_breakpoints(): + if bp.is_disabled(): + self.enable_hardware_breakpoint(tid, bp.get_address()) + + def enable_one_shot_all_breakpoints(self): + """ + Enables for one shot all disabled breakpoints in all processes. + + @see: + enable_one_shot_code_breakpoint, + enable_one_shot_page_breakpoint, + enable_one_shot_hardware_breakpoint + """ + + # disable code breakpoints for one shot + for (pid, bp) in self.get_all_code_breakpoints(): + if bp.is_disabled(): + self.enable_one_shot_code_breakpoint(pid, bp.get_address()) + + # disable page breakpoints for one shot + for (pid, bp) in self.get_all_page_breakpoints(): + if bp.is_disabled(): + self.enable_one_shot_page_breakpoint(pid, bp.get_address()) + + # disable hardware breakpoints for one shot + for (tid, bp) in self.get_all_hardware_breakpoints(): + if bp.is_disabled(): + self.enable_one_shot_hardware_breakpoint(tid, bp.get_address()) + + def disable_all_breakpoints(self): + """ + Disables all breakpoints in all processes. + + @see: + disable_code_breakpoint, + disable_page_breakpoint, + disable_hardware_breakpoint + """ + + # disable code breakpoints + for (pid, bp) in self.get_all_code_breakpoints(): + self.disable_code_breakpoint(pid, bp.get_address()) + + # disable page breakpoints + for (pid, bp) in self.get_all_page_breakpoints(): + self.disable_page_breakpoint(pid, bp.get_address()) + + # disable hardware breakpoints + for (tid, bp) in self.get_all_hardware_breakpoints(): + self.disable_hardware_breakpoint(tid, bp.get_address()) + + def erase_all_breakpoints(self): + """ + Erases all breakpoints in all processes. + + @see: + erase_code_breakpoint, + erase_page_breakpoint, + erase_hardware_breakpoint + """ + + # This should be faster but let's not trust the GC so much :P + # self.disable_all_breakpoints() + # self.__codeBP = dict() + # self.__pageBP = dict() + # self.__hardwareBP = dict() + # self.__runningBP = dict() + # self.__hook_objects = dict() + +## # erase hooks +## for (pid, address, hook) in self.get_all_hooks(): +## self.dont_hook_function(pid, address) + + # erase code breakpoints + for (pid, bp) in self.get_all_code_breakpoints(): + self.erase_code_breakpoint(pid, bp.get_address()) + + # erase page breakpoints + for (pid, bp) in self.get_all_page_breakpoints(): + self.erase_page_breakpoint(pid, bp.get_address()) + + # erase hardware breakpoints + for (tid, bp) in self.get_all_hardware_breakpoints(): + self.erase_hardware_breakpoint(tid, bp.get_address()) + +#------------------------------------------------------------------------------ + + # Batch operations on breakpoints per process. + + def enable_process_breakpoints(self, dwProcessId): + """ + Enables all disabled breakpoints for the given process. + + @type dwProcessId: int + @param dwProcessId: Process global ID. + """ + + # enable code breakpoints + for bp in self.get_process_code_breakpoints(dwProcessId): + if bp.is_disabled(): + self.enable_code_breakpoint(dwProcessId, bp.get_address()) + + # enable page breakpoints + for bp in self.get_process_page_breakpoints(dwProcessId): + if bp.is_disabled(): + self.enable_page_breakpoint(dwProcessId, bp.get_address()) + + # enable hardware breakpoints + if self.system.has_process(dwProcessId): + aProcess = self.system.get_process(dwProcessId) + else: + aProcess = Process(dwProcessId) + aProcess.scan_threads() + for aThread in aProcess.iter_threads(): + dwThreadId = aThread.get_tid() + for bp in self.get_thread_hardware_breakpoints(dwThreadId): + if bp.is_disabled(): + self.enable_hardware_breakpoint(dwThreadId, bp.get_address()) + + def enable_one_shot_process_breakpoints(self, dwProcessId): + """ + Enables for one shot all disabled breakpoints for the given process. + + @type dwProcessId: int + @param dwProcessId: Process global ID. + """ + + # enable code breakpoints for one shot + for bp in self.get_process_code_breakpoints(dwProcessId): + if bp.is_disabled(): + self.enable_one_shot_code_breakpoint(dwProcessId, bp.get_address()) + + # enable page breakpoints for one shot + for bp in self.get_process_page_breakpoints(dwProcessId): + if bp.is_disabled(): + self.enable_one_shot_page_breakpoint(dwProcessId, bp.get_address()) + + # enable hardware breakpoints for one shot + if self.system.has_process(dwProcessId): + aProcess = self.system.get_process(dwProcessId) + else: + aProcess = Process(dwProcessId) + aProcess.scan_threads() + for aThread in aProcess.iter_threads(): + dwThreadId = aThread.get_tid() + for bp in self.get_thread_hardware_breakpoints(dwThreadId): + if bp.is_disabled(): + self.enable_one_shot_hardware_breakpoint(dwThreadId, bp.get_address()) + + def disable_process_breakpoints(self, dwProcessId): + """ + Disables all breakpoints for the given process. + + @type dwProcessId: int + @param dwProcessId: Process global ID. + """ + + # disable code breakpoints + for bp in self.get_process_code_breakpoints(dwProcessId): + self.disable_code_breakpoint(dwProcessId, bp.get_address()) + + # disable page breakpoints + for bp in self.get_process_page_breakpoints(dwProcessId): + self.disable_page_breakpoint(dwProcessId, bp.get_address()) + + # disable hardware breakpoints + if self.system.has_process(dwProcessId): + aProcess = self.system.get_process(dwProcessId) + else: + aProcess = Process(dwProcessId) + aProcess.scan_threads() + for aThread in aProcess.iter_threads(): + dwThreadId = aThread.get_tid() + for bp in self.get_thread_hardware_breakpoints(dwThreadId): + self.disable_hardware_breakpoint(dwThreadId, bp.get_address()) + + def erase_process_breakpoints(self, dwProcessId): + """ + Erases all breakpoints for the given process. + + @type dwProcessId: int + @param dwProcessId: Process global ID. + """ + + # disable breakpoints first + # if an error occurs, no breakpoint is erased + self.disable_process_breakpoints(dwProcessId) + +## # erase hooks +## for address, hook in self.get_process_hooks(dwProcessId): +## self.dont_hook_function(dwProcessId, address) + + # erase code breakpoints + for bp in self.get_process_code_breakpoints(dwProcessId): + self.erase_code_breakpoint(dwProcessId, bp.get_address()) + + # erase page breakpoints + for bp in self.get_process_page_breakpoints(dwProcessId): + self.erase_page_breakpoint(dwProcessId, bp.get_address()) + + # erase hardware breakpoints + if self.system.has_process(dwProcessId): + aProcess = self.system.get_process(dwProcessId) + else: + aProcess = Process(dwProcessId) + aProcess.scan_threads() + for aThread in aProcess.iter_threads(): + dwThreadId = aThread.get_tid() + for bp in self.get_thread_hardware_breakpoints(dwThreadId): + self.erase_hardware_breakpoint(dwThreadId, bp.get_address()) + +#------------------------------------------------------------------------------ + + # Internal handlers of debug events. + + def _notify_guard_page(self, event): + """ + Notify breakpoints of a guard page exception event. + + @type event: L{ExceptionEvent} + @param event: Guard page exception event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + address = event.get_fault_address() + pid = event.get_pid() + bCallHandler = True + + # Align address to page boundary. + mask = ~(MemoryAddresses.pageSize - 1) + address = address & mask + + # Do we have an active page breakpoint there? + key = (pid, address) + if key in self.__pageBP: + bp = self.__pageBP[key] + if bp.is_enabled() or bp.is_one_shot(): + + # Breakpoint is ours. + event.continueStatus = win32.DBG_CONTINUE +## event.continueStatus = win32.DBG_EXCEPTION_HANDLED + + # Hit the breakpoint. + bp.hit(event) + + # Remember breakpoints in RUNNING state. + if bp.is_running(): + tid = event.get_tid() + self.__add_running_bp(tid, bp) + + # Evaluate the breakpoint condition. + bCondition = bp.eval_condition(event) + + # If the breakpoint is automatic, run the action. + # If not, notify the user. + if bCondition and bp.is_automatic(): + bp.run_action(event) + bCallHandler = False + else: + bCallHandler = bCondition + + # If we don't have a breakpoint here pass the exception to the debugee. + # This is a normally occurring exception so we shouldn't swallow it. + else: + event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED + + return bCallHandler + + def _notify_breakpoint(self, event): + """ + Notify breakpoints of a breakpoint exception event. + + @type event: L{ExceptionEvent} + @param event: Breakpoint exception event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + address = event.get_exception_address() + pid = event.get_pid() + bCallHandler = True + + # Do we have an active code breakpoint there? + key = (pid, address) + if key in self.__codeBP: + bp = self.__codeBP[key] + if not bp.is_disabled(): + + # Change the program counter (PC) to the exception address. + # This accounts for the change in PC caused by + # executing the breakpoint instruction, no matter + # the size of it. + aThread = event.get_thread() + aThread.set_pc(address) + + # Swallow the exception. + event.continueStatus = win32.DBG_CONTINUE + + # Hit the breakpoint. + bp.hit(event) + + # Remember breakpoints in RUNNING state. + if bp.is_running(): + tid = event.get_tid() + self.__add_running_bp(tid, bp) + + # Evaluate the breakpoint condition. + bCondition = bp.eval_condition(event) + + # If the breakpoint is automatic, run the action. + # If not, notify the user. + if bCondition and bp.is_automatic(): + bCallHandler = bp.run_action(event) + else: + bCallHandler = bCondition + + # Handle the system breakpoint. + # TODO: examine the stack trace to figure out if it's really a + # system breakpoint or an antidebug trick. The caller should be + # inside ntdll if it's legit. + elif event.get_process().is_system_defined_breakpoint(address): + event.continueStatus = win32.DBG_CONTINUE + + # In hostile mode, if we don't have a breakpoint here pass the + # exception to the debugee. In normal mode assume all breakpoint + # exceptions are to be handled by the debugger. + else: + if self.in_hostile_mode(): + event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED + else: + event.continueStatus = win32.DBG_CONTINUE + + return bCallHandler + + def _notify_single_step(self, event): + """ + Notify breakpoints of a single step exception event. + + @type event: L{ExceptionEvent} + @param event: Single step exception event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + pid = event.get_pid() + tid = event.get_tid() + aThread = event.get_thread() + aProcess = event.get_process() + bCallHandler = True + bIsOurs = False + + # In hostile mode set the default to pass the exception to the debugee. + # If we later determine the exception is ours, hide it instead. + old_continueStatus = event.continueStatus + try: + if self.in_hostile_mode(): + event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED + + # Single step support is implemented on x86/x64 architectures only. + if self.system.arch not in (win32.ARCH_I386, win32.ARCH_AMD64): + return bCallHandler + + # In hostile mode, read the last executed bytes to try to detect + # some antidebug tricks. Skip this check in normal mode because + # it'd slow things down. + # + # FIXME: weird opcode encodings may bypass this check! + # + # bFakeSingleStep: Ice Breakpoint undocumented instruction. + # bHideTrapFlag: Don't let pushf instructions get the real value of + # the trap flag. + # bNextIsPopFlags: Don't let popf instructions clear the trap flag. + # + bFakeSingleStep = False + bLastIsPushFlags = False + bNextIsPopFlags = False + if self.in_hostile_mode(): + pc = aThread.get_pc() + c = aProcess.read_char(pc - 1) + if c == 0xF1: # int1 + bFakeSingleStep = True + elif c == 0x9C: # pushf + bLastIsPushFlags = True + c = aProcess.peek_char(pc) + if c == 0x66: # the only valid prefix for popf + c = aProcess.peek_char(pc + 1) + if c == 0x9D: # popf + if bLastIsPushFlags: + bLastIsPushFlags = False # they cancel each other out + else: + bNextIsPopFlags = True + + # When the thread is in tracing mode, + # don't pass the exception to the debugee + # and set the trap flag again. + if self.is_tracing(tid): + bIsOurs = True + if not bFakeSingleStep: + event.continueStatus = win32.DBG_CONTINUE + aThread.set_tf() + + # Don't let the debugee read or write the trap flag. + # This code works in 32 and 64 bits thanks to the endianness. + if bLastIsPushFlags or bNextIsPopFlags: + sp = aThread.get_sp() + flags = aProcess.read_dword(sp) + if bLastIsPushFlags: + flags &= ~Thread.Flags.Trap + else: # if bNextIsPopFlags: + flags |= Thread.Flags.Trap + aProcess.write_dword(sp, flags) + + # Handle breakpoints in RUNNING state. + running = self.__get_running_bp_set(tid) + if running: + bIsOurs = True + if not bFakeSingleStep: + event.continueStatus = win32.DBG_CONTINUE + bCallHandler = False + while running: + try: + running.pop().hit(event) + except Exception: + e = sys.exc_info()[1] + warnings.warn(str(e), BreakpointWarning) + + # Handle hardware breakpoints. + if tid in self.__hardwareBP: + ctx = aThread.get_context(win32.CONTEXT_DEBUG_REGISTERS) + Dr6 = ctx['Dr6'] + ctx['Dr6'] = Dr6 & DebugRegister.clearHitMask + aThread.set_context(ctx) + bFoundBreakpoint = False + bCondition = False + hwbpList = [ bp for bp in self.__hardwareBP[tid] ] + for bp in hwbpList: + if not bp in self.__hardwareBP[tid]: + continue # it was removed by a user-defined callback + slot = bp.get_slot() + if (slot is not None) and \ + (Dr6 & DebugRegister.hitMask[slot]): + if not bFoundBreakpoint: #set before actions are called + if not bFakeSingleStep: + event.continueStatus = win32.DBG_CONTINUE + bFoundBreakpoint = True + bIsOurs = True + bp.hit(event) + if bp.is_running(): + self.__add_running_bp(tid, bp) + bThisCondition = bp.eval_condition(event) + if bThisCondition and bp.is_automatic(): + bp.run_action(event) + bThisCondition = False + bCondition = bCondition or bThisCondition + if bFoundBreakpoint: + bCallHandler = bCondition + + # Always call the user-defined handler + # when the thread is in tracing mode. + if self.is_tracing(tid): + bCallHandler = True + + # If we're not in hostile mode, by default we assume all single + # step exceptions are caused by the debugger. + if not bIsOurs and not self.in_hostile_mode(): + aThread.clear_tf() + + # If the user hit Control-C while we were inside the try block, + # set the default continueStatus back. + except: + event.continueStatus = old_continueStatus + raise + + return bCallHandler + + def _notify_load_dll(self, event): + """ + Notify the loading of a DLL. + + @type event: L{LoadDLLEvent} + @param event: Load DLL event. + + @rtype: bool + @return: C{True} to call the user-defined handler, C{False} otherwise. + """ + self.__set_deferred_breakpoints(event) + return True + + def _notify_unload_dll(self, event): + """ + Notify the unloading of a DLL. + + @type event: L{UnloadDLLEvent} + @param event: Unload DLL event. + + @rtype: bool + @return: C{True} to call the user-defined handler, C{False} otherwise. + """ + self.__cleanup_module(event) + return True + + def _notify_exit_thread(self, event): + """ + Notify the termination of a thread. + + @type event: L{ExitThreadEvent} + @param event: Exit thread event. + + @rtype: bool + @return: C{True} to call the user-defined handler, C{False} otherwise. + """ + self.__cleanup_thread(event) + return True + + def _notify_exit_process(self, event): + """ + Notify the termination of a process. + + @type event: L{ExitProcessEvent} + @param event: Exit process event. + + @rtype: bool + @return: C{True} to call the user-defined handler, C{False} otherwise. + """ + self.__cleanup_process(event) + self.__cleanup_thread(event) + return True + +#------------------------------------------------------------------------------ + + # This is the high level breakpoint interface. Here we don't have to care + # about defining or enabling breakpoints, and many errors are ignored + # (like for example setting the same breakpoint twice, here the second + # breakpoint replaces the first, much like in WinDBG). It should be easier + # and more intuitive, if less detailed. It also allows the use of deferred + # breakpoints. + +#------------------------------------------------------------------------------ + + # Code breakpoints + + def __set_break(self, pid, address, action, oneshot): + """ + Used by L{break_at} and L{stalk_at}. + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_code_breakpoint} for more details. + + @type oneshot: bool + @param oneshot: C{True} for one-shot breakpoints, C{False} otherwise. + + @rtype: L{Breakpoint} + @return: Returns the new L{Breakpoint} object, or C{None} if the label + couldn't be resolved and the breakpoint was deferred. Deferred + breakpoints are set when the DLL they point to is loaded. + """ + if type(address) not in (int, long): + label = address + try: + address = self.system.get_process(pid).resolve_label(address) + if not address: + raise Exception() + except Exception: + try: + deferred = self.__deferredBP[pid] + except KeyError: + deferred = dict() + self.__deferredBP[pid] = deferred + if label in deferred: + msg = "Redefined deferred code breakpoint at %s in process ID %d" + msg = msg % (label, pid) + warnings.warn(msg, BreakpointWarning) + deferred[label] = (action, oneshot) + return None + if self.has_code_breakpoint(pid, address): + bp = self.get_code_breakpoint(pid, address) + if bp.get_action() != action: # can't use "is not", fails for bound methods + bp.set_action(action) + msg = "Redefined code breakpoint at %s in process ID %d" + msg = msg % (label, pid) + warnings.warn(msg, BreakpointWarning) + else: + self.define_code_breakpoint(pid, address, True, action) + bp = self.get_code_breakpoint(pid, address) + if oneshot: + if not bp.is_one_shot(): + self.enable_one_shot_code_breakpoint(pid, address) + else: + if not bp.is_enabled(): + self.enable_code_breakpoint(pid, address) + return bp + + def __clear_break(self, pid, address): + """ + Used by L{dont_break_at} and L{dont_stalk_at}. + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + """ + if type(address) not in (int, long): + unknown = True + label = address + try: + deferred = self.__deferredBP[pid] + del deferred[label] + unknown = False + except KeyError: +## traceback.print_last() # XXX DEBUG + pass + aProcess = self.system.get_process(pid) + try: + address = aProcess.resolve_label(label) + if not address: + raise Exception() + except Exception: +## traceback.print_last() # XXX DEBUG + if unknown: + msg = ("Can't clear unknown code breakpoint" + " at %s in process ID %d") + msg = msg % (label, pid) + warnings.warn(msg, BreakpointWarning) + return + if self.has_code_breakpoint(pid, address): + self.erase_code_breakpoint(pid, address) + + def __set_deferred_breakpoints(self, event): + """ + Used internally. Sets all deferred breakpoints for a DLL when it's + loaded. + + @type event: L{LoadDLLEvent} + @param event: Load DLL event. + """ + pid = event.get_pid() + try: + deferred = self.__deferredBP[pid] + except KeyError: + return + aProcess = event.get_process() + for (label, (action, oneshot)) in deferred.items(): + try: + address = aProcess.resolve_label(label) + except Exception: + continue + del deferred[label] + try: + self.__set_break(pid, address, action, oneshot) + except Exception: + msg = "Can't set deferred breakpoint %s at process ID %d" + msg = msg % (label, pid) + warnings.warn(msg, BreakpointWarning) + + def get_all_deferred_code_breakpoints(self): + """ + Returns a list of deferred code breakpoints. + + @rtype: tuple of (int, str, callable, bool) + @return: Tuple containing the following elements: + - Process ID where to set the breakpoint. + - Label pointing to the address where to set the breakpoint. + - Action callback for the breakpoint. + - C{True} of the breakpoint is one-shot, C{False} otherwise. + """ + result = [] + for pid, deferred in compat.iteritems(self.__deferredBP): + for (label, (action, oneshot)) in compat.iteritems(deferred): + result.add( (pid, label, action, oneshot) ) + return result + + def get_process_deferred_code_breakpoints(self, dwProcessId): + """ + Returns a list of deferred code breakpoints. + + @type dwProcessId: int + @param dwProcessId: Process ID. + + @rtype: tuple of (int, str, callable, bool) + @return: Tuple containing the following elements: + - Label pointing to the address where to set the breakpoint. + - Action callback for the breakpoint. + - C{True} of the breakpoint is one-shot, C{False} otherwise. + """ + return [ (label, action, oneshot) + for (label, (action, oneshot)) + in compat.iteritems(self.__deferredBP.get(dwProcessId, {})) ] + + def stalk_at(self, pid, address, action = None): + """ + Sets a one shot code breakpoint at the given process and address. + + If instead of an address you pass a label, the breakpoint may be + deferred until the DLL it points to is loaded. + + @see: L{break_at}, L{dont_stalk_at} + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_code_breakpoint} for more details. + + @rtype: bool + @return: C{True} if the breakpoint was set immediately, or C{False} if + it was deferred. + """ + bp = self.__set_break(pid, address, action, oneshot = True) + return bp is not None + + def break_at(self, pid, address, action = None): + """ + Sets a code breakpoint at the given process and address. + + If instead of an address you pass a label, the breakpoint may be + deferred until the DLL it points to is loaded. + + @see: L{stalk_at}, L{dont_break_at} + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_code_breakpoint} for more details. + + @rtype: bool + @return: C{True} if the breakpoint was set immediately, or C{False} if + it was deferred. + """ + bp = self.__set_break(pid, address, action, oneshot = False) + return bp is not None + + def dont_break_at(self, pid, address): + """ + Clears a code breakpoint set by L{break_at}. + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + """ + self.__clear_break(pid, address) + + def dont_stalk_at(self, pid, address): + """ + Clears a code breakpoint set by L{stalk_at}. + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + """ + self.__clear_break(pid, address) + +#------------------------------------------------------------------------------ + + # Function hooks + + def hook_function(self, pid, address, + preCB = None, postCB = None, + paramCount = None, signature = None): + """ + Sets a function hook at the given address. + + If instead of an address you pass a label, the hook may be + deferred until the DLL it points to is loaded. + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + + @type preCB: function + @param preCB: (Optional) Callback triggered on function entry. + + The signature for the callback should be something like this:: + + def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags): + + # return address + ra = params[0] + + # function arguments start from here... + szFilename = event.get_process().peek_string(lpFilename) + + # (...) + + Note that all pointer types are treated like void pointers, so your + callback won't get the string or structure pointed to by it, but + the remote memory address instead. This is so to prevent the ctypes + library from being "too helpful" and trying to dereference the + pointer. To get the actual data being pointed to, use one of the + L{Process.read} methods. + + @type postCB: function + @param postCB: (Optional) Callback triggered on function exit. + + The signature for the callback should be something like this:: + + def post_LoadLibraryEx(event, return_value): + + # (...) + + @type paramCount: int + @param paramCount: + (Optional) Number of parameters for the C{preCB} callback, + not counting the return address. Parameters are read from + the stack and assumed to be DWORDs in 32 bits and QWORDs in 64. + + This is a faster way to pull stack parameters in 32 bits, but in 64 + bits (or with some odd APIs in 32 bits) it won't be useful, since + not all arguments to the hooked function will be of the same size. + + For a more reliable and cross-platform way of hooking use the + C{signature} argument instead. + + @type signature: tuple + @param signature: + (Optional) Tuple of C{ctypes} data types that constitute the + hooked function signature. When the function is called, this will + be used to parse the arguments from the stack. Overrides the + C{paramCount} argument. + + @rtype: bool + @return: C{True} if the hook was set immediately, or C{False} if + it was deferred. + """ + try: + aProcess = self.system.get_process(pid) + except KeyError: + aProcess = Process(pid) + arch = aProcess.get_arch() + hookObj = Hook(preCB, postCB, paramCount, signature, arch) + bp = self.break_at(pid, address, hookObj) + return bp is not None + + def stalk_function(self, pid, address, + preCB = None, postCB = None, + paramCount = None, signature = None): + """ + Sets a one-shot function hook at the given address. + + If instead of an address you pass a label, the hook may be + deferred until the DLL it points to is loaded. + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + + @type preCB: function + @param preCB: (Optional) Callback triggered on function entry. + + The signature for the callback should be something like this:: + + def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags): + + # return address + ra = params[0] + + # function arguments start from here... + szFilename = event.get_process().peek_string(lpFilename) + + # (...) + + Note that all pointer types are treated like void pointers, so your + callback won't get the string or structure pointed to by it, but + the remote memory address instead. This is so to prevent the ctypes + library from being "too helpful" and trying to dereference the + pointer. To get the actual data being pointed to, use one of the + L{Process.read} methods. + + @type postCB: function + @param postCB: (Optional) Callback triggered on function exit. + + The signature for the callback should be something like this:: + + def post_LoadLibraryEx(event, return_value): + + # (...) + + @type paramCount: int + @param paramCount: + (Optional) Number of parameters for the C{preCB} callback, + not counting the return address. Parameters are read from + the stack and assumed to be DWORDs in 32 bits and QWORDs in 64. + + This is a faster way to pull stack parameters in 32 bits, but in 64 + bits (or with some odd APIs in 32 bits) it won't be useful, since + not all arguments to the hooked function will be of the same size. + + For a more reliable and cross-platform way of hooking use the + C{signature} argument instead. + + @type signature: tuple + @param signature: + (Optional) Tuple of C{ctypes} data types that constitute the + hooked function signature. When the function is called, this will + be used to parse the arguments from the stack. Overrides the + C{paramCount} argument. + + @rtype: bool + @return: C{True} if the breakpoint was set immediately, or C{False} if + it was deferred. + """ + try: + aProcess = self.system.get_process(pid) + except KeyError: + aProcess = Process(pid) + arch = aProcess.get_arch() + hookObj = Hook(preCB, postCB, paramCount, signature, arch) + bp = self.stalk_at(pid, address, hookObj) + return bp is not None + + def dont_hook_function(self, pid, address): + """ + Removes a function hook set by L{hook_function}. + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + """ + self.dont_break_at(pid, address) + + # alias + unhook_function = dont_hook_function + + def dont_stalk_function(self, pid, address): + """ + Removes a function hook set by L{stalk_function}. + + @type pid: int + @param pid: Process global ID. + + @type address: int or str + @param address: + Memory address of code instruction to break at. It can be an + integer value for the actual address or a string with a label + to be resolved. + """ + self.dont_stalk_at(pid, address) + +#------------------------------------------------------------------------------ + + # Variable watches + + def __set_variable_watch(self, tid, address, size, action): + """ + Used by L{watch_variable} and L{stalk_variable}. + + @type tid: int + @param tid: Thread global ID. + + @type address: int + @param address: Memory address of variable to watch. + + @type size: int + @param size: Size of variable to watch. The only supported sizes are: + byte (1), word (2), dword (4) and qword (8). + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_hardware_breakpoint} for more details. + + @rtype: L{HardwareBreakpoint} + @return: Hardware breakpoint at the requested address. + """ + + # TODO + # We should merge the breakpoints instead of overwriting them. + # We'll have the same problem as watch_buffer and we'll need to change + # the API again. + + if size == 1: + sizeFlag = self.BP_WATCH_BYTE + elif size == 2: + sizeFlag = self.BP_WATCH_WORD + elif size == 4: + sizeFlag = self.BP_WATCH_DWORD + elif size == 8: + sizeFlag = self.BP_WATCH_QWORD + else: + raise ValueError("Bad size for variable watch: %r" % size) + + if self.has_hardware_breakpoint(tid, address): + warnings.warn( + "Hardware breakpoint in thread %d at address %s was overwritten!" \ + % (tid, HexDump.address(address, + self.system.get_thread(tid).get_bits())), + BreakpointWarning) + + bp = self.get_hardware_breakpoint(tid, address) + if bp.get_trigger() != self.BP_BREAK_ON_ACCESS or \ + bp.get_watch() != sizeFlag: + self.erase_hardware_breakpoint(tid, address) + self.define_hardware_breakpoint(tid, address, + self.BP_BREAK_ON_ACCESS, sizeFlag, True, action) + bp = self.get_hardware_breakpoint(tid, address) + + else: + self.define_hardware_breakpoint(tid, address, + self.BP_BREAK_ON_ACCESS, sizeFlag, True, action) + bp = self.get_hardware_breakpoint(tid, address) + + return bp + + def __clear_variable_watch(self, tid, address): + """ + Used by L{dont_watch_variable} and L{dont_stalk_variable}. + + @type tid: int + @param tid: Thread global ID. + + @type address: int + @param address: Memory address of variable to stop watching. + """ + if self.has_hardware_breakpoint(tid, address): + self.erase_hardware_breakpoint(tid, address) + + def watch_variable(self, tid, address, size, action = None): + """ + Sets a hardware breakpoint at the given thread, address and size. + + @see: L{dont_watch_variable} + + @type tid: int + @param tid: Thread global ID. + + @type address: int + @param address: Memory address of variable to watch. + + @type size: int + @param size: Size of variable to watch. The only supported sizes are: + byte (1), word (2), dword (4) and qword (8). + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_hardware_breakpoint} for more details. + """ + bp = self.__set_variable_watch(tid, address, size, action) + if not bp.is_enabled(): + self.enable_hardware_breakpoint(tid, address) + + def stalk_variable(self, tid, address, size, action = None): + """ + Sets a one-shot hardware breakpoint at the given thread, + address and size. + + @see: L{dont_watch_variable} + + @type tid: int + @param tid: Thread global ID. + + @type address: int + @param address: Memory address of variable to watch. + + @type size: int + @param size: Size of variable to watch. The only supported sizes are: + byte (1), word (2), dword (4) and qword (8). + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_hardware_breakpoint} for more details. + """ + bp = self.__set_variable_watch(tid, address, size, action) + if not bp.is_one_shot(): + self.enable_one_shot_hardware_breakpoint(tid, address) + + def dont_watch_variable(self, tid, address): + """ + Clears a hardware breakpoint set by L{watch_variable}. + + @type tid: int + @param tid: Thread global ID. + + @type address: int + @param address: Memory address of variable to stop watching. + """ + self.__clear_variable_watch(tid, address) + + def dont_stalk_variable(self, tid, address): + """ + Clears a hardware breakpoint set by L{stalk_variable}. + + @type tid: int + @param tid: Thread global ID. + + @type address: int + @param address: Memory address of variable to stop watching. + """ + self.__clear_variable_watch(tid, address) + +#------------------------------------------------------------------------------ + + # Buffer watches + + def __set_buffer_watch(self, pid, address, size, action, bOneShot): + """ + Used by L{watch_buffer} and L{stalk_buffer}. + + @type pid: int + @param pid: Process global ID. + + @type address: int + @param address: Memory address of buffer to watch. + + @type size: int + @param size: Size in bytes of buffer to watch. + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_page_breakpoint} for more details. + + @type bOneShot: bool + @param bOneShot: + C{True} to set a one-shot breakpoint, + C{False} to set a normal breakpoint. + """ + + # Check the size isn't zero or negative. + if size < 1: + raise ValueError("Bad size for buffer watch: %r" % size) + + # Create the buffer watch identifier. + bw = BufferWatch(pid, address, address + size, action, bOneShot) + + # Get the base address and size in pages required for this buffer. + base = MemoryAddresses.align_address_to_page_start(address) + limit = MemoryAddresses.align_address_to_page_end(address + size) + pages = MemoryAddresses.get_buffer_size_in_pages(address, size) + + try: + + # For each page: + # + if a page breakpoint exists reuse it + # + if it doesn't exist define it + + bset = set() # all breakpoints used + nset = set() # newly defined breakpoints + cset = set() # condition objects + + page_addr = base + pageSize = MemoryAddresses.pageSize + while page_addr < limit: + + # If a breakpoints exists, reuse it. + if self.has_page_breakpoint(pid, page_addr): + bp = self.get_page_breakpoint(pid, page_addr) + if bp not in bset: + condition = bp.get_condition() + if not condition in cset: + if not isinstance(condition,_BufferWatchCondition): + # this shouldn't happen unless you tinkered + # with it or defined your own page breakpoints + # manually. + msg = "Can't watch buffer at page %s" + msg = msg % HexDump.address(page_addr) + raise RuntimeError(msg) + cset.add(condition) + bset.add(bp) + + # If it doesn't, define it. + else: + condition = _BufferWatchCondition() + bp = self.define_page_breakpoint(pid, page_addr, 1, + condition = condition) + bset.add(bp) + nset.add(bp) + cset.add(condition) + + # Next page. + page_addr = page_addr + pageSize + + # For each breakpoint, enable it if needed. + aProcess = self.system.get_process(pid) + for bp in bset: + if bp.is_disabled() or bp.is_one_shot(): + bp.enable(aProcess, None) + + # On error... + except: + + # Erase the newly defined breakpoints. + for bp in nset: + try: + self.erase_page_breakpoint(pid, bp.get_address()) + except: + pass + + # Pass the exception to the caller + raise + + # For each condition object, add the new buffer. + for condition in cset: + condition.add(bw) + + def __clear_buffer_watch_old_method(self, pid, address, size): + """ + Used by L{dont_watch_buffer} and L{dont_stalk_buffer}. + + @warn: Deprecated since WinAppDbg 1.5. + + @type pid: int + @param pid: Process global ID. + + @type address: int + @param address: Memory address of buffer to stop watching. + + @type size: int + @param size: Size in bytes of buffer to stop watching. + """ + warnings.warn("Deprecated since WinAppDbg 1.5", DeprecationWarning) + + # Check the size isn't zero or negative. + if size < 1: + raise ValueError("Bad size for buffer watch: %r" % size) + + # Get the base address and size in pages required for this buffer. + base = MemoryAddresses.align_address_to_page_start(address) + limit = MemoryAddresses.align_address_to_page_end(address + size) + pages = MemoryAddresses.get_buffer_size_in_pages(address, size) + + # For each page, get the breakpoint and it's condition object. + # For each condition, remove the buffer. + # For each breakpoint, if no buffers are on watch, erase it. + cset = set() # condition objects + page_addr = base + pageSize = MemoryAddresses.pageSize + while page_addr < limit: + if self.has_page_breakpoint(pid, page_addr): + bp = self.get_page_breakpoint(pid, page_addr) + condition = bp.get_condition() + if condition not in cset: + if not isinstance(condition, _BufferWatchCondition): + # this shouldn't happen unless you tinkered with it + # or defined your own page breakpoints manually. + continue + cset.add(condition) + condition.remove_last_match(address, size) + if condition.count() == 0: + try: + self.erase_page_breakpoint(pid, bp.get_address()) + except WindowsError: + pass + page_addr = page_addr + pageSize + + def __clear_buffer_watch(self, bw): + """ + Used by L{dont_watch_buffer} and L{dont_stalk_buffer}. + + @type bw: L{BufferWatch} + @param bw: Buffer watch identifier. + """ + + # Get the PID and the start and end addresses of the buffer. + pid = bw.pid + start = bw.start + end = bw.end + + # Get the base address and size in pages required for the buffer. + base = MemoryAddresses.align_address_to_page_start(start) + limit = MemoryAddresses.align_address_to_page_end(end) + pages = MemoryAddresses.get_buffer_size_in_pages(start, end - start) + + # For each page, get the breakpoint and it's condition object. + # For each condition, remove the buffer. + # For each breakpoint, if no buffers are on watch, erase it. + cset = set() # condition objects + page_addr = base + pageSize = MemoryAddresses.pageSize + while page_addr < limit: + if self.has_page_breakpoint(pid, page_addr): + bp = self.get_page_breakpoint(pid, page_addr) + condition = bp.get_condition() + if condition not in cset: + if not isinstance(condition, _BufferWatchCondition): + # this shouldn't happen unless you tinkered with it + # or defined your own page breakpoints manually. + continue + cset.add(condition) + condition.remove(bw) + if condition.count() == 0: + try: + self.erase_page_breakpoint(pid, bp.get_address()) + except WindowsError: + msg = "Cannot remove page breakpoint at address %s" + msg = msg % HexDump.address( bp.get_address() ) + warnings.warn(msg, BreakpointWarning) + page_addr = page_addr + pageSize + + def watch_buffer(self, pid, address, size, action = None): + """ + Sets a page breakpoint and notifies when the given buffer is accessed. + + @see: L{dont_watch_variable} + + @type pid: int + @param pid: Process global ID. + + @type address: int + @param address: Memory address of buffer to watch. + + @type size: int + @param size: Size in bytes of buffer to watch. + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_page_breakpoint} for more details. + + @rtype: L{BufferWatch} + @return: Buffer watch identifier. + """ + self.__set_buffer_watch(pid, address, size, action, False) + + def stalk_buffer(self, pid, address, size, action = None): + """ + Sets a one-shot page breakpoint and notifies + when the given buffer is accessed. + + @see: L{dont_watch_variable} + + @type pid: int + @param pid: Process global ID. + + @type address: int + @param address: Memory address of buffer to watch. + + @type size: int + @param size: Size in bytes of buffer to watch. + + @type action: function + @param action: (Optional) Action callback function. + + See L{define_page_breakpoint} for more details. + + @rtype: L{BufferWatch} + @return: Buffer watch identifier. + """ + self.__set_buffer_watch(pid, address, size, action, True) + + def dont_watch_buffer(self, bw, *argv, **argd): + """ + Clears a page breakpoint set by L{watch_buffer}. + + @type bw: L{BufferWatch} + @param bw: + Buffer watch identifier returned by L{watch_buffer}. + """ + + # The sane way to do it. + if not (argv or argd): + self.__clear_buffer_watch(bw) + + # Backwards compatibility with WinAppDbg 1.4. + else: + argv = list(argv) + argv.insert(0, bw) + if 'pid' in argd: + argv.insert(0, argd.pop('pid')) + if 'address' in argd: + argv.insert(1, argd.pop('address')) + if 'size' in argd: + argv.insert(2, argd.pop('size')) + if argd: + raise TypeError("Wrong arguments for dont_watch_buffer()") + try: + pid, address, size = argv + except ValueError: + raise TypeError("Wrong arguments for dont_watch_buffer()") + self.__clear_buffer_watch_old_method(pid, address, size) + + def dont_stalk_buffer(self, bw, *argv, **argd): + """ + Clears a page breakpoint set by L{stalk_buffer}. + + @type bw: L{BufferWatch} + @param bw: + Buffer watch identifier returned by L{stalk_buffer}. + """ + self.dont_watch_buffer(bw, *argv, **argd) + +#------------------------------------------------------------------------------ + + # Tracing + +# XXX TODO +# Add "action" parameter to tracing mode + + def __start_tracing(self, thread): + """ + @type thread: L{Thread} + @param thread: Thread to start tracing. + """ + tid = thread.get_tid() + if not tid in self.__tracing: + thread.set_tf() + self.__tracing.add(tid) + + def __stop_tracing(self, thread): + """ + @type thread: L{Thread} + @param thread: Thread to stop tracing. + """ + tid = thread.get_tid() + if tid in self.__tracing: + self.__tracing.remove(tid) + if thread.is_alive(): + thread.clear_tf() + + def is_tracing(self, tid): + """ + @type tid: int + @param tid: Thread global ID. + + @rtype: bool + @return: C{True} if the thread is being traced, C{False} otherwise. + """ + return tid in self.__tracing + + def get_traced_tids(self): + """ + Retrieves the list of global IDs of all threads being traced. + + @rtype: list( int... ) + @return: List of thread global IDs. + """ + tids = list(self.__tracing) + tids.sort() + return tids + + def start_tracing(self, tid): + """ + Start tracing mode in the given thread. + + @type tid: int + @param tid: Global ID of thread to start tracing. + """ + if not self.is_tracing(tid): + thread = self.system.get_thread(tid) + self.__start_tracing(thread) + + def stop_tracing(self, tid): + """ + Stop tracing mode in the given thread. + + @type tid: int + @param tid: Global ID of thread to stop tracing. + """ + if self.is_tracing(tid): + thread = self.system.get_thread(tid) + self.__stop_tracing(thread) + + def start_tracing_process(self, pid): + """ + Start tracing mode for all threads in the given process. + + @type pid: int + @param pid: Global ID of process to start tracing. + """ + for thread in self.system.get_process(pid).iter_threads(): + self.__start_tracing(thread) + + def stop_tracing_process(self, pid): + """ + Stop tracing mode for all threads in the given process. + + @type pid: int + @param pid: Global ID of process to stop tracing. + """ + for thread in self.system.get_process(pid).iter_threads(): + self.__stop_tracing(thread) + + def start_tracing_all(self): + """ + Start tracing mode for all threads in all debugees. + """ + for pid in self.get_debugee_pids(): + self.start_tracing_process(pid) + + def stop_tracing_all(self): + """ + Stop tracing mode for all threads in all debugees. + """ + for pid in self.get_debugee_pids(): + self.stop_tracing_process(pid) + +#------------------------------------------------------------------------------ + + # Break on LastError values (only available since Windows Server 2003) + + def break_on_error(self, pid, errorCode): + """ + Sets or clears the system breakpoint for a given Win32 error code. + + Use L{Process.is_system_defined_breakpoint} to tell if a breakpoint + exception was caused by a system breakpoint or by the application + itself (for example because of a failed assertion in the code). + + @note: This functionality is only available since Windows Server 2003. + In 2003 it only breaks on error values set externally to the + kernel32.dll library, but this was fixed in Windows Vista. + + @warn: This method will fail if the debug symbols for ntdll (kernel32 + in Windows 2003) are not present. For more information see: + L{System.fix_symbol_store_path}. + + @see: U{http://www.nynaeve.net/?p=147} + + @type pid: int + @param pid: Process ID. + + @type errorCode: int + @param errorCode: Win32 error code to stop on. Set to C{0} or + C{ERROR_SUCCESS} to clear the breakpoint instead. + + @raise NotImplementedError: + The functionality is not supported in this system. + + @raise WindowsError: + An error occurred while processing this request. + """ + aProcess = self.system.get_process(pid) + address = aProcess.get_break_on_error_ptr() + if not address: + raise NotImplementedError( + "The functionality is not supported in this system.") + aProcess.write_dword(address, errorCode) + + def dont_break_on_error(self, pid): + """ + Alias to L{break_on_error}C{(pid, ERROR_SUCCESS)}. + + @type pid: int + @param pid: Process ID. + + @raise NotImplementedError: + The functionality is not supported in this system. + + @raise WindowsError: + An error occurred while processing this request. + """ + self.break_on_error(pid, 0) + +#------------------------------------------------------------------------------ + + # Simplified symbol resolving, useful for hooking functions + + def resolve_exported_function(self, pid, modName, procName): + """ + Resolves the exported DLL function for the given process. + + @type pid: int + @param pid: Process global ID. + + @type modName: str + @param modName: Name of the module that exports the function. + + @type procName: str + @param procName: Name of the exported function to resolve. + + @rtype: int, None + @return: On success, the address of the exported function. + On failure, returns C{None}. + """ + aProcess = self.system.get_process(pid) + aModule = aProcess.get_module_by_name(modName) + if not aModule: + aProcess.scan_modules() + aModule = aProcess.get_module_by_name(modName) + if aModule: + address = aModule.resolve(procName) + return address + return None + + def resolve_label(self, pid, label): + """ + Resolves a label for the given process. + + @type pid: int + @param pid: Process global ID. + + @type label: str + @param label: Label to resolve. + + @rtype: int + @return: Memory address pointed to by the label. + + @raise ValueError: The label is malformed or impossible to resolve. + @raise RuntimeError: Cannot resolve the module or function. + """ + return self.get_process(pid).resolve_label(label) diff --git a/pydevd_attach_to_process/winappdbg/compat.py b/pydevd_attach_to_process/winappdbg/compat.py new file mode 100644 index 0000000..ad64901 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/compat.py @@ -0,0 +1,183 @@ +# Partial copy of https://bitbucket.org/gutworth/six/src/8e634686c53a35092dd705172440a9231c90ddd1/six.py?at=default +# With some differences to take into account that the iterXXX version may be defined in user code. + +# Original __author__ = "Benjamin Peterson " +# Base __version__ = "1.7.3" + +# Copyright (c) 2010-2014 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import types + + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +if PY3: + xrange = range + unicode = str + bytes = bytes + def iterkeys(d, **kw): + if hasattr(d, 'iterkeys'): + return iter(d.iterkeys(**kw)) + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + if hasattr(d, 'itervalues'): + return iter(d.itervalues(**kw)) + return iter(d.values(**kw)) + + def iteritems(d, **kw): + if hasattr(d, 'iteritems'): + return iter(d.iteritems(**kw)) + return iter(d.items(**kw)) + + def iterlists(d, **kw): + if hasattr(d, 'iterlists'): + return iter(d.iterlists(**kw)) + return iter(d.lists(**kw)) + + def keys(d, **kw): + return list(iterkeys(d, **kw)) +else: + unicode = unicode + xrange = xrange + bytes = str + def keys(d, **kw): + return d.keys(**kw) + + def iterkeys(d, **kw): + return iter(d.iterkeys(**kw)) + + def itervalues(d, **kw): + return iter(d.itervalues(**kw)) + + def iteritems(d, **kw): + return iter(d.iteritems(**kw)) + + def iterlists(d, **kw): + return iter(d.iterlists(**kw)) + +if PY3: + import builtins + exec_ = getattr(builtins, "exec") + + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if PY3: + import operator + def b(s): + if isinstance(s, str): + return s.encode("latin-1") + assert isinstance(s, bytes) + return s + def u(s): + return s + unichr = chr + if sys.version_info[1] <= 1: + def int2byte(i): + return bytes((i,)) + else: + # This is about 2x faster than the implementation above on 3.2+ + int2byte = operator.methodcaller("to_bytes", 1, "big") + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO +else: + def b(s): + return s + # Workaround for standalone backslash + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + def byte2int(bs): + return ord(bs[0]) + def indexbytes(buf, i): + return ord(buf[i]) + def iterbytes(buf): + return (ord(byte) for byte in buf) + import StringIO + StringIO = BytesIO = StringIO.StringIO \ No newline at end of file diff --git a/pydevd_attach_to_process/winappdbg/crash.py b/pydevd_attach_to_process/winappdbg/crash.py new file mode 100644 index 0000000..a53172e --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/crash.py @@ -0,0 +1,1853 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Crash dump support. + +@group Crash reporting: + Crash, CrashDictionary + +@group Warnings: + CrashWarning + +@group Deprecated classes: + CrashContainer, CrashTable, CrashTableMSSQL, + VolatileCrashContainer, DummyCrashContainer +""" + +__revision__ = "$Id$" + +__all__ = [ + + # Object that represents a crash in the debugee. + 'Crash', + + # Crash storage. + 'CrashDictionary', + + # Warnings. + 'CrashWarning', + + # Backwards compatibility with WinAppDbg 1.4 and before. + 'CrashContainer', + 'CrashTable', + 'CrashTableMSSQL', + 'VolatileCrashContainer', + 'DummyCrashContainer', +] + +from winappdbg import win32 +from winappdbg import compat +from winappdbg.system import System +from winappdbg.textio import HexDump, CrashDump +from winappdbg.util import StaticClass, MemoryAddresses, PathOperations + +import sys +import os +import time +import zlib +import warnings + +# lazy imports +sql = None +anydbm = None + +#============================================================================== + +# Secure alternative to pickle, use it if present. +try: + import cerealizer + pickle = cerealizer + + # There is no optimization function for cerealized objects. + def optimize(picklestring): + return picklestring + + # There is no HIGHEST_PROTOCOL in cerealizer. + HIGHEST_PROTOCOL = 0 + + # Note: it's important NOT to provide backwards compatibility, otherwise + # it'd be just the same as not having this! + # + # To disable this security upgrade simply uncomment the following line: + # + # raise ImportError("Fallback to pickle for backwards compatibility") + +# If cerealizer is not present fallback to the insecure pickle module. +except ImportError: + + # Faster implementation of the pickle module as a C extension. + try: + import cPickle as pickle + + # If all fails fallback to the classic pickle module. + except ImportError: + import pickle + + # Fetch the highest protocol version. + HIGHEST_PROTOCOL = pickle.HIGHEST_PROTOCOL + + # Try to use the pickle optimizer if found. + try: + from pickletools import optimize + except ImportError: + def optimize(picklestring): + return picklestring + +class Marshaller (StaticClass): + """ + Custom pickler for L{Crash} objects. Optimizes the pickled data when using + the standard C{pickle} (or C{cPickle}) module. The pickled data is then + compressed using zlib. + """ + + @staticmethod + def dumps(obj, protocol=HIGHEST_PROTOCOL): + return zlib.compress(optimize(pickle.dumps(obj)), 9) + + @staticmethod + def loads(data): + return pickle.loads(zlib.decompress(data)) + +#============================================================================== + +class CrashWarning (Warning): + """ + An error occurred while gathering crash data. + Some data may be incomplete or missing. + """ + +#============================================================================== + +# Crash object. Must be serializable. +class Crash (object): + """ + Represents a crash, bug, or another interesting event in the debugee. + + @group Basic information: + timeStamp, signature, eventCode, eventName, pid, tid, arch, os, bits, + registers, labelPC, pc, sp, fp + + @group Optional information: + debugString, + modFileName, + lpBaseOfDll, + exceptionCode, + exceptionName, + exceptionDescription, + exceptionAddress, + exceptionLabel, + firstChance, + faultType, + faultAddress, + faultLabel, + isOurBreakpoint, + isSystemBreakpoint, + stackTrace, + stackTracePC, + stackTraceLabels, + stackTracePretty + + @group Extra information: + commandLine, + environment, + environmentData, + registersPeek, + stackRange, + stackFrame, + stackPeek, + faultCode, + faultMem, + faultPeek, + faultDisasm, + memoryMap + + @group Report: + briefReport, fullReport, notesReport, environmentReport, isExploitable + + @group Notes: + addNote, getNotes, iterNotes, hasNotes, clearNotes, notes + + @group Miscellaneous: + fetch_extra_data + + @type timeStamp: float + @ivar timeStamp: Timestamp as returned by time.time(). + + @type signature: object + @ivar signature: Approximately unique signature for the Crash object. + + This signature can be used as an heuristic to determine if two crashes + were caused by the same software error. Ideally it should be treated as + as opaque serializable object that can be tested for equality. + + @type notes: list( str ) + @ivar notes: List of strings, each string is a note. + + @type eventCode: int + @ivar eventCode: Event code as defined by the Win32 API. + + @type eventName: str + @ivar eventName: Event code user-friendly name. + + @type pid: int + @ivar pid: Process global ID. + + @type tid: int + @ivar tid: Thread global ID. + + @type arch: str + @ivar arch: Processor architecture. + + @type os: str + @ivar os: Operating system version. + + May indicate a 64 bit version even if L{arch} and L{bits} indicate 32 + bits. This means the crash occurred inside a WOW64 process. + + @type bits: int + @ivar bits: C{32} or C{64} bits. + + @type commandLine: None or str + @ivar commandLine: Command line for the target process. + + C{None} if unapplicable or unable to retrieve. + + @type environmentData: None or list of str + @ivar environmentData: Environment data for the target process. + + C{None} if unapplicable or unable to retrieve. + + @type environment: None or dict( str S{->} str ) + @ivar environment: Environment variables for the target process. + + C{None} if unapplicable or unable to retrieve. + + @type registers: dict( str S{->} int ) + @ivar registers: Dictionary mapping register names to their values. + + @type registersPeek: None or dict( str S{->} str ) + @ivar registersPeek: Dictionary mapping register names to the data they point to. + + C{None} if unapplicable or unable to retrieve. + + @type labelPC: None or str + @ivar labelPC: Label pointing to the program counter. + + C{None} or invalid if unapplicable or unable to retrieve. + + @type debugString: None or str + @ivar debugString: Debug string sent by the debugee. + + C{None} if unapplicable or unable to retrieve. + + @type exceptionCode: None or int + @ivar exceptionCode: Exception code as defined by the Win32 API. + + C{None} if unapplicable or unable to retrieve. + + @type exceptionName: None or str + @ivar exceptionName: Exception code user-friendly name. + + C{None} if unapplicable or unable to retrieve. + + @type exceptionDescription: None or str + @ivar exceptionDescription: Exception description. + + C{None} if unapplicable or unable to retrieve. + + @type exceptionAddress: None or int + @ivar exceptionAddress: Memory address where the exception occured. + + C{None} if unapplicable or unable to retrieve. + + @type exceptionLabel: None or str + @ivar exceptionLabel: Label pointing to the exception address. + + C{None} or invalid if unapplicable or unable to retrieve. + + @type faultType: None or int + @ivar faultType: Access violation type. + Only applicable to memory faults. + Should be one of the following constants: + + - L{win32.ACCESS_VIOLATION_TYPE_READ} + - L{win32.ACCESS_VIOLATION_TYPE_WRITE} + - L{win32.ACCESS_VIOLATION_TYPE_DEP} + + C{None} if unapplicable or unable to retrieve. + + @type faultAddress: None or int + @ivar faultAddress: Access violation memory address. + Only applicable to memory faults. + + C{None} if unapplicable or unable to retrieve. + + @type faultLabel: None or str + @ivar faultLabel: Label pointing to the access violation memory address. + Only applicable to memory faults. + + C{None} if unapplicable or unable to retrieve. + + @type firstChance: None or bool + @ivar firstChance: + C{True} for first chance exceptions, C{False} for second chance. + + C{None} if unapplicable or unable to retrieve. + + @type isOurBreakpoint: bool + @ivar isOurBreakpoint: + C{True} for breakpoints defined by the L{Debug} class, + C{False} otherwise. + + C{None} if unapplicable. + + @type isSystemBreakpoint: bool + @ivar isSystemBreakpoint: + C{True} for known system-defined breakpoints, + C{False} otherwise. + + C{None} if unapplicable. + + @type modFileName: None or str + @ivar modFileName: File name of module where the program counter points to. + + C{None} or invalid if unapplicable or unable to retrieve. + + @type lpBaseOfDll: None or int + @ivar lpBaseOfDll: Base of module where the program counter points to. + + C{None} if unapplicable or unable to retrieve. + + @type stackTrace: None or tuple of tuple( int, int, str ) + @ivar stackTrace: + Stack trace of the current thread as a tuple of + ( frame pointer, return address, module filename ). + + C{None} or empty if unapplicable or unable to retrieve. + + @type stackTracePretty: None or tuple of tuple( int, str ) + @ivar stackTracePretty: + Stack trace of the current thread as a tuple of + ( frame pointer, return location ). + + C{None} or empty if unapplicable or unable to retrieve. + + @type stackTracePC: None or tuple( int... ) + @ivar stackTracePC: Tuple of return addresses in the stack trace. + + C{None} or empty if unapplicable or unable to retrieve. + + @type stackTraceLabels: None or tuple( str... ) + @ivar stackTraceLabels: + Tuple of labels pointing to the return addresses in the stack trace. + + C{None} or empty if unapplicable or unable to retrieve. + + @type stackRange: tuple( int, int ) + @ivar stackRange: + Stack beginning and end pointers, in memory addresses order. + + C{None} if unapplicable or unable to retrieve. + + @type stackFrame: None or str + @ivar stackFrame: Data pointed to by the stack pointer. + + C{None} or empty if unapplicable or unable to retrieve. + + @type stackPeek: None or dict( int S{->} str ) + @ivar stackPeek: Dictionary mapping stack offsets to the data they point to. + + C{None} or empty if unapplicable or unable to retrieve. + + @type faultCode: None or str + @ivar faultCode: Data pointed to by the program counter. + + C{None} or empty if unapplicable or unable to retrieve. + + @type faultMem: None or str + @ivar faultMem: Data pointed to by the exception address. + + C{None} or empty if unapplicable or unable to retrieve. + + @type faultPeek: None or dict( intS{->} str ) + @ivar faultPeek: Dictionary mapping guessed pointers at L{faultMem} to the data they point to. + + C{None} or empty if unapplicable or unable to retrieve. + + @type faultDisasm: None or tuple of tuple( long, int, str, str ) + @ivar faultDisasm: Dissassembly around the program counter. + + C{None} or empty if unapplicable or unable to retrieve. + + @type memoryMap: None or list of L{win32.MemoryBasicInformation} objects. + @ivar memoryMap: Memory snapshot of the program. May contain the actual + data from the entire process memory if requested. + See L{fetch_extra_data} for more details. + + C{None} or empty if unapplicable or unable to retrieve. + + @type _rowid: int + @ivar _rowid: Row ID in the database. Internally used by the DAO layer. + Only present in crash dumps retrieved from the database. Do not rely + on this property to be present in future versions of WinAppDbg. + """ + + def __init__(self, event): + """ + @type event: L{Event} + @param event: Event object for crash. + """ + + # First of all, take the timestamp. + self.timeStamp = time.time() + + # Notes are initially empty. + self.notes = list() + + # Get the process and thread, but dont't store them in the DB. + process = event.get_process() + thread = event.get_thread() + + # Determine the architecture. + self.os = System.os + self.arch = process.get_arch() + self.bits = process.get_bits() + + # The following properties are always retrieved for all events. + self.eventCode = event.get_event_code() + self.eventName = event.get_event_name() + self.pid = event.get_pid() + self.tid = event.get_tid() + self.registers = dict(thread.get_context()) + self.labelPC = process.get_label_at_address(self.pc) + + # The following properties are only retrieved for some events. + self.commandLine = None + self.environment = None + self.environmentData = None + self.registersPeek = None + self.debugString = None + self.modFileName = None + self.lpBaseOfDll = None + self.exceptionCode = None + self.exceptionName = None + self.exceptionDescription = None + self.exceptionAddress = None + self.exceptionLabel = None + self.firstChance = None + self.faultType = None + self.faultAddress = None + self.faultLabel = None + self.isOurBreakpoint = None + self.isSystemBreakpoint = None + self.stackTrace = None + self.stackTracePC = None + self.stackTraceLabels = None + self.stackTracePretty = None + self.stackRange = None + self.stackFrame = None + self.stackPeek = None + self.faultCode = None + self.faultMem = None + self.faultPeek = None + self.faultDisasm = None + self.memoryMap = None + + # Get information for debug string events. + if self.eventCode == win32.OUTPUT_DEBUG_STRING_EVENT: + self.debugString = event.get_debug_string() + + # Get information for module load and unload events. + # For create and exit process events, get the information + # for the main module. + elif self.eventCode in (win32.CREATE_PROCESS_DEBUG_EVENT, + win32.EXIT_PROCESS_DEBUG_EVENT, + win32.LOAD_DLL_DEBUG_EVENT, + win32.UNLOAD_DLL_DEBUG_EVENT): + aModule = event.get_module() + self.modFileName = event.get_filename() + if not self.modFileName: + self.modFileName = aModule.get_filename() + self.lpBaseOfDll = event.get_module_base() + if not self.lpBaseOfDll: + self.lpBaseOfDll = aModule.get_base() + + # Get some information for exception events. + # To get the remaining information call fetch_extra_data(). + elif self.eventCode == win32.EXCEPTION_DEBUG_EVENT: + + # Exception information. + self.exceptionCode = event.get_exception_code() + self.exceptionName = event.get_exception_name() + self.exceptionDescription = event.get_exception_description() + self.exceptionAddress = event.get_exception_address() + self.firstChance = event.is_first_chance() + self.exceptionLabel = process.get_label_at_address( + self.exceptionAddress) + if self.exceptionCode in (win32.EXCEPTION_ACCESS_VIOLATION, + win32.EXCEPTION_GUARD_PAGE, + win32.EXCEPTION_IN_PAGE_ERROR): + self.faultType = event.get_fault_type() + self.faultAddress = event.get_fault_address() + self.faultLabel = process.get_label_at_address( + self.faultAddress) + elif self.exceptionCode in (win32.EXCEPTION_BREAKPOINT, + win32.EXCEPTION_SINGLE_STEP): + self.isOurBreakpoint = hasattr(event, 'breakpoint') \ + and event.breakpoint + self.isSystemBreakpoint = \ + process.is_system_defined_breakpoint(self.exceptionAddress) + + # Stack trace. + try: + self.stackTracePretty = thread.get_stack_trace_with_labels() + except Exception: + e = sys.exc_info()[1] + warnings.warn( + "Cannot get stack trace with labels, reason: %s" % str(e), + CrashWarning) + try: + self.stackTrace = thread.get_stack_trace() + stackTracePC = [ ra for (_,ra,_) in self.stackTrace ] + self.stackTracePC = tuple(stackTracePC) + stackTraceLabels = [ process.get_label_at_address(ra) \ + for ra in self.stackTracePC ] + self.stackTraceLabels = tuple(stackTraceLabels) + except Exception: + e = sys.exc_info()[1] + warnings.warn("Cannot get stack trace, reason: %s" % str(e), + CrashWarning) + + def fetch_extra_data(self, event, takeMemorySnapshot = 0): + """ + Fetch extra data from the L{Event} object. + + @note: Since this method may take a little longer to run, it's best to + call it only after you've determined the crash is interesting and + you want to save it. + + @type event: L{Event} + @param event: Event object for crash. + + @type takeMemorySnapshot: int + @param takeMemorySnapshot: + Memory snapshot behavior: + - C{0} to take no memory information (default). + - C{1} to take only the memory map. + See L{Process.get_memory_map}. + - C{2} to take a full memory snapshot. + See L{Process.take_memory_snapshot}. + - C{3} to take a live memory snapshot. + See L{Process.generate_memory_snapshot}. + """ + + # Get the process and thread, we'll use them below. + process = event.get_process() + thread = event.get_thread() + + # Get the command line for the target process. + try: + self.commandLine = process.get_command_line() + except Exception: + e = sys.exc_info()[1] + warnings.warn("Cannot get command line, reason: %s" % str(e), + CrashWarning) + + # Get the environment variables for the target process. + try: + self.environmentData = process.get_environment_data() + self.environment = process.parse_environment_data( + self.environmentData) + except Exception: + e = sys.exc_info()[1] + warnings.warn("Cannot get environment, reason: %s" % str(e), + CrashWarning) + + # Data pointed to by registers. + self.registersPeek = thread.peek_pointers_in_registers() + + # Module where execution is taking place. + aModule = process.get_module_at_address(self.pc) + if aModule is not None: + self.modFileName = aModule.get_filename() + self.lpBaseOfDll = aModule.get_base() + + # Contents of the stack frame. + try: + self.stackRange = thread.get_stack_range() + except Exception: + e = sys.exc_info()[1] + warnings.warn("Cannot get stack range, reason: %s" % str(e), + CrashWarning) + try: + self.stackFrame = thread.get_stack_frame() + stackFrame = self.stackFrame + except Exception: + self.stackFrame = thread.peek_stack_data() + stackFrame = self.stackFrame[:64] + if stackFrame: + self.stackPeek = process.peek_pointers_in_data(stackFrame) + + # Code being executed. + self.faultCode = thread.peek_code_bytes() + try: + self.faultDisasm = thread.disassemble_around_pc(32) + except Exception: + e = sys.exc_info()[1] + warnings.warn("Cannot disassemble, reason: %s" % str(e), + CrashWarning) + + # For memory related exceptions, get the memory contents + # of the location that caused the exception to be raised. + if self.eventCode == win32.EXCEPTION_DEBUG_EVENT: + if self.pc != self.exceptionAddress and self.exceptionCode in ( + win32.EXCEPTION_ACCESS_VIOLATION, + win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED, + win32.EXCEPTION_DATATYPE_MISALIGNMENT, + win32.EXCEPTION_IN_PAGE_ERROR, + win32.EXCEPTION_STACK_OVERFLOW, + win32.EXCEPTION_GUARD_PAGE, + ): + self.faultMem = process.peek(self.exceptionAddress, 64) + if self.faultMem: + self.faultPeek = process.peek_pointers_in_data( + self.faultMem) + + # TODO: maybe add names and versions of DLLs and EXE? + + # Take a snapshot of the process memory. Additionally get the + # memory contents if requested. + if takeMemorySnapshot == 1: + self.memoryMap = process.get_memory_map() + mappedFilenames = process.get_mapped_filenames(self.memoryMap) + for mbi in self.memoryMap: + mbi.filename = mappedFilenames.get(mbi.BaseAddress, None) + mbi.content = None + elif takeMemorySnapshot == 2: + self.memoryMap = process.take_memory_snapshot() + elif takeMemorySnapshot == 3: + self.memoryMap = process.generate_memory_snapshot() + + @property + def pc(self): + """ + Value of the program counter register. + + @rtype: int + """ + try: + return self.registers['Eip'] # i386 + except KeyError: + return self.registers['Rip'] # amd64 + + @property + def sp(self): + """ + Value of the stack pointer register. + + @rtype: int + """ + try: + return self.registers['Esp'] # i386 + except KeyError: + return self.registers['Rsp'] # amd64 + + @property + def fp(self): + """ + Value of the frame pointer register. + + @rtype: int + """ + try: + return self.registers['Ebp'] # i386 + except KeyError: + return self.registers['Rbp'] # amd64 + + def __str__(self): + return self.fullReport() + + def key(self): + """ + Alias of L{signature}. Deprecated since WinAppDbg 1.5. + """ + warnings.warn("Crash.key() method was deprecated in WinAppDbg 1.5", + DeprecationWarning) + return self.signature + + @property + def signature(self): + if self.labelPC: + pc = self.labelPC + else: + pc = self.pc + if self.stackTraceLabels: + trace = self.stackTraceLabels + else: + trace = self.stackTracePC + return ( + self.arch, + self.eventCode, + self.exceptionCode, + pc, + trace, + self.debugString, + ) + # TODO + # add the name and version of the binary where the crash happened? + + def isExploitable(self): + """ + Guess how likely is it that the bug causing the crash can be leveraged + into an exploitable vulnerability. + + @note: Don't take this as an equivalent of a real exploitability + analysis, that can only be done by a human being! This is only + a guideline, useful for example to sort crashes - placing the most + interesting ones at the top. + + @see: The heuristics are similar to those of the B{!exploitable} + extension for I{WinDBG}, which can be downloaded from here: + + U{http://www.codeplex.com/msecdbg} + + @rtype: tuple( str, str, str ) + @return: The first element of the tuple is the result of the analysis, + being one of the following: + + - Not an exception + - Not exploitable + - Not likely exploitable + - Unknown + - Probably exploitable + - Exploitable + + The second element of the tuple is a code to identify the matched + heuristic rule. + + The third element of the tuple is a description string of the + reason behind the result. + """ + + # Terminal rules + + if self.eventCode != win32.EXCEPTION_DEBUG_EVENT: + return ("Not an exception", "NotAnException", "The event is not an exception.") + + if self.stackRange and self.pc is not None and self.stackRange[0] <= self.pc < self.stackRange[1]: + return ("Exploitable", "StackCodeExecution", "Code execution from the stack is considered exploitable.") + + # This rule is NOT from !exploitable + if self.stackRange and self.sp is not None and not (self.stackRange[0] <= self.sp < self.stackRange[1]): + return ("Exploitable", "StackPointerCorruption", "Stack pointer corruption is considered exploitable.") + + if self.exceptionCode == win32.EXCEPTION_ILLEGAL_INSTRUCTION: + return ("Exploitable", "IllegalInstruction", "An illegal instruction exception indicates that the attacker controls execution flow.") + + if self.exceptionCode == win32.EXCEPTION_PRIV_INSTRUCTION: + return ("Exploitable", "PrivilegedInstruction", "A privileged instruction exception indicates that the attacker controls execution flow.") + + if self.exceptionCode == win32.EXCEPTION_GUARD_PAGE: + return ("Exploitable", "GuardPage", "A guard page violation indicates a stack overflow has occured, and the stack of another thread was reached (possibly the overflow length is not controlled by the attacker).") + + if self.exceptionCode == win32.STATUS_STACK_BUFFER_OVERRUN: + return ("Exploitable", "GSViolation", "An overrun of a protected stack buffer has been detected. This is considered exploitable, and must be fixed.") + + if self.exceptionCode == win32.STATUS_HEAP_CORRUPTION: + return ("Exploitable", "HeapCorruption", "Heap Corruption has been detected. This is considered exploitable, and must be fixed.") + + if self.exceptionCode == win32.EXCEPTION_ACCESS_VIOLATION: + nearNull = self.faultAddress is None or MemoryAddresses.align_address_to_page_start(self.faultAddress) == 0 + controlFlow = self.__is_control_flow() + blockDataMove = self.__is_block_data_move() + if self.faultType == win32.EXCEPTION_EXECUTE_FAULT: + if nearNull: + return ("Probably exploitable", "DEPViolation", "User mode DEP access violations are probably exploitable if near NULL.") + else: + return ("Exploitable", "DEPViolation", "User mode DEP access violations are exploitable.") + elif self.faultType == win32.EXCEPTION_WRITE_FAULT: + if nearNull: + return ("Probably exploitable", "WriteAV", "User mode write access violations that are near NULL are probably exploitable.") + else: + return ("Exploitable", "WriteAV", "User mode write access violations that are not near NULL are exploitable.") + elif self.faultType == win32.EXCEPTION_READ_FAULT: + if self.faultAddress == self.pc: + if nearNull: + return ("Probably exploitable", "ReadAVonIP", "Access violations at the instruction pointer are probably exploitable if near NULL.") + else: + return ("Exploitable", "ReadAVonIP", "Access violations at the instruction pointer are exploitable if not near NULL.") + if controlFlow: + if nearNull: + return ("Probably exploitable", "ReadAVonControlFlow", "Access violations near null in control flow instructions are considered probably exploitable.") + else: + return ("Exploitable", "ReadAVonControlFlow", "Access violations not near null in control flow instructions are considered exploitable.") + if blockDataMove: + return ("Probably exploitable", "ReadAVonBlockMove", "This is a read access violation in a block data move, and is therefore classified as probably exploitable.") + + # Rule: Tainted information used to control branch addresses is considered probably exploitable + # Rule: Tainted information used to control the target of a later write is probably exploitable + + # Non terminal rules + + # XXX TODO add rule to check if code is in writeable memory (probably exploitable) + + # XXX TODO maybe we should be returning a list of tuples instead? + + result = ("Unknown", "Unknown", "Exploitability unknown.") + + if self.exceptionCode == win32.EXCEPTION_ACCESS_VIOLATION: + if self.faultType == win32.EXCEPTION_READ_FAULT: + if nearNull: + result = ("Not likely exploitable", "ReadAVNearNull", "This is a user mode read access violation near null, and is probably not exploitable.") + + elif self.exceptionCode == win32.EXCEPTION_INT_DIVIDE_BY_ZERO: + result = ("Not likely exploitable", "DivideByZero", "This is an integer divide by zero, and is probably not exploitable.") + + elif self.exceptionCode == win32.EXCEPTION_FLT_DIVIDE_BY_ZERO: + result = ("Not likely exploitable", "DivideByZero", "This is a floating point divide by zero, and is probably not exploitable.") + + elif self.exceptionCode in (win32.EXCEPTION_BREAKPOINT, win32.STATUS_WX86_BREAKPOINT): + result = ("Unknown", "Breakpoint", "While a breakpoint itself is probably not exploitable, it may also be an indication that an attacker is testing a target. In either case breakpoints should not exist in production code.") + + # Rule: If the stack contains unknown symbols in user mode, call that out + # Rule: Tainted information used to control the source of a later block move unknown, but called out explicitly + # Rule: Tainted information used as an argument to a function is an unknown risk, but called out explicitly + # Rule: Tainted information used to control branch selection is an unknown risk, but called out explicitly + + return result + + def __is_control_flow(self): + """ + Private method to tell if the instruction pointed to by the program + counter is a control flow instruction. + + Currently only works for x86 and amd64 architectures. + """ + jump_instructions = ( + 'jmp', 'jecxz', 'jcxz', + 'ja', 'jnbe', 'jae', 'jnb', 'jb', 'jnae', 'jbe', 'jna', 'jc', 'je', + 'jz', 'jnc', 'jne', 'jnz', 'jnp', 'jpo', 'jp', 'jpe', 'jg', 'jnle', + 'jge', 'jnl', 'jl', 'jnge', 'jle', 'jng', 'jno', 'jns', 'jo', 'js' + ) + call_instructions = ( 'call', 'ret', 'retn' ) + loop_instructions = ( 'loop', 'loopz', 'loopnz', 'loope', 'loopne' ) + control_flow_instructions = call_instructions + loop_instructions + \ + jump_instructions + isControlFlow = False + instruction = None + if self.pc is not None and self.faultDisasm: + for disasm in self.faultDisasm: + if disasm[0] == self.pc: + instruction = disasm[2].lower().strip() + break + if instruction: + for x in control_flow_instructions: + if x in instruction: + isControlFlow = True + break + return isControlFlow + + def __is_block_data_move(self): + """ + Private method to tell if the instruction pointed to by the program + counter is a block data move instruction. + + Currently only works for x86 and amd64 architectures. + """ + block_data_move_instructions = ('movs', 'stos', 'lods') + isBlockDataMove = False + instruction = None + if self.pc is not None and self.faultDisasm: + for disasm in self.faultDisasm: + if disasm[0] == self.pc: + instruction = disasm[2].lower().strip() + break + if instruction: + for x in block_data_move_instructions: + if x in instruction: + isBlockDataMove = True + break + return isBlockDataMove + + def briefReport(self): + """ + @rtype: str + @return: Short description of the event. + """ + if self.exceptionCode is not None: + if self.exceptionCode == win32.EXCEPTION_BREAKPOINT: + if self.isOurBreakpoint: + what = "Breakpoint hit" + elif self.isSystemBreakpoint: + what = "System breakpoint hit" + else: + what = "Assertion failed" + elif self.exceptionDescription: + what = self.exceptionDescription + elif self.exceptionName: + what = self.exceptionName + else: + what = "Exception %s" % \ + HexDump.integer(self.exceptionCode, self.bits) + if self.firstChance: + chance = 'first' + else: + chance = 'second' + if self.exceptionLabel: + where = self.exceptionLabel + elif self.exceptionAddress: + where = HexDump.address(self.exceptionAddress, self.bits) + elif self.labelPC: + where = self.labelPC + else: + where = HexDump.address(self.pc, self.bits) + msg = "%s (%s chance) at %s" % (what, chance, where) + elif self.debugString is not None: + if self.labelPC: + where = self.labelPC + else: + where = HexDump.address(self.pc, self.bits) + msg = "Debug string from %s: %r" % (where, self.debugString) + else: + if self.labelPC: + where = self.labelPC + else: + where = HexDump.address(self.pc, self.bits) + msg = "%s (%s) at %s" % ( + self.eventName, + HexDump.integer(self.eventCode, self.bits), + where + ) + return msg + + def fullReport(self, bShowNotes = True): + """ + @type bShowNotes: bool + @param bShowNotes: C{True} to show the user notes, C{False} otherwise. + + @rtype: str + @return: Long description of the event. + """ + msg = self.briefReport() + msg += '\n' + + if self.bits == 32: + width = 16 + else: + width = 8 + + if self.eventCode == win32.EXCEPTION_DEBUG_EVENT: + (exploitability, expcode, expdescription) = self.isExploitable() + msg += '\nSecurity risk level: %s\n' % exploitability + msg += ' %s\n' % expdescription + + if bShowNotes and self.notes: + msg += '\nNotes:\n' + msg += self.notesReport() + + if self.commandLine: + msg += '\nCommand line: %s\n' % self.commandLine + + if self.environment: + msg += '\nEnvironment:\n' + msg += self.environmentReport() + + if not self.labelPC: + base = HexDump.address(self.lpBaseOfDll, self.bits) + if self.modFileName: + fn = PathOperations.pathname_to_filename(self.modFileName) + msg += '\nRunning in %s (%s)\n' % (fn, base) + else: + msg += '\nRunning in module at %s\n' % base + + if self.registers: + msg += '\nRegisters:\n' + msg += CrashDump.dump_registers(self.registers) + if self.registersPeek: + msg += '\n' + msg += CrashDump.dump_registers_peek(self.registers, + self.registersPeek, + width = width) + + if self.faultDisasm: + msg += '\nCode disassembly:\n' + msg += CrashDump.dump_code(self.faultDisasm, self.pc, + bits = self.bits) + + if self.stackTrace: + msg += '\nStack trace:\n' + if self.stackTracePretty: + msg += CrashDump.dump_stack_trace_with_labels( + self.stackTracePretty, + bits = self.bits) + else: + msg += CrashDump.dump_stack_trace(self.stackTrace, + bits = self.bits) + + if self.stackFrame: + if self.stackPeek: + msg += '\nStack pointers:\n' + msg += CrashDump.dump_stack_peek(self.stackPeek, width = width) + msg += '\nStack dump:\n' + msg += HexDump.hexblock(self.stackFrame, self.sp, + bits = self.bits, width = width) + + if self.faultCode and not self.modFileName: + msg += '\nCode dump:\n' + msg += HexDump.hexblock(self.faultCode, self.pc, + bits = self.bits, width = width) + + if self.faultMem: + if self.faultPeek: + msg += '\nException address pointers:\n' + msg += CrashDump.dump_data_peek(self.faultPeek, + self.exceptionAddress, + bits = self.bits, + width = width) + msg += '\nException address dump:\n' + msg += HexDump.hexblock(self.faultMem, self.exceptionAddress, + bits = self.bits, width = width) + + if self.memoryMap: + msg += '\nMemory map:\n' + mappedFileNames = dict() + for mbi in self.memoryMap: + if hasattr(mbi, 'filename') and mbi.filename: + mappedFileNames[mbi.BaseAddress] = mbi.filename + msg += CrashDump.dump_memory_map(self.memoryMap, mappedFileNames, + bits = self.bits) + + if not msg.endswith('\n\n'): + if not msg.endswith('\n'): + msg += '\n' + msg += '\n' + return msg + + def environmentReport(self): + """ + @rtype: str + @return: The process environment variables, + merged and formatted for a report. + """ + msg = '' + if self.environment: + for key, value in compat.iteritems(self.environment): + msg += ' %s=%s\n' % (key, value) + return msg + + def notesReport(self): + """ + @rtype: str + @return: All notes, merged and formatted for a report. + """ + msg = '' + if self.notes: + for n in self.notes: + n = n.strip('\n') + if '\n' in n: + n = n.strip('\n') + msg += ' * %s\n' % n.pop(0) + for x in n: + msg += ' %s\n' % x + else: + msg += ' * %s\n' % n + return msg + + def addNote(self, msg): + """ + Add a note to the crash event. + + @type msg: str + @param msg: Note text. + """ + self.notes.append(msg) + + def clearNotes(self): + """ + Clear the notes of this crash event. + """ + self.notes = list() + + def getNotes(self): + """ + Get the list of notes of this crash event. + + @rtype: list( str ) + @return: List of notes. + """ + return self.notes + + def iterNotes(self): + """ + Iterate the notes of this crash event. + + @rtype: listiterator + @return: Iterator of the list of notes. + """ + return self.notes.__iter__() + + def hasNotes(self): + """ + @rtype: bool + @return: C{True} if there are notes for this crash event. + """ + return bool( self.notes ) + +#============================================================================== + +class CrashContainer (object): + """ + Old crash dump persistencer using a DBM database. + Doesn't support duplicate crashes. + + @warning: + DBM database support is provided for backwards compatibility with older + versions of WinAppDbg. New applications should not use this class. + Also, DBM databases in Python suffer from multiple problems that can + easily be avoided by switching to a SQL database. + + @see: If you really must use a DBM database, try the standard C{shelve} + module instead: U{http://docs.python.org/library/shelve.html} + + @group Marshalling configuration: + optimizeKeys, optimizeValues, compressKeys, compressValues, escapeKeys, + escapeValues, binaryKeys, binaryValues + + @type optimizeKeys: bool + @cvar optimizeKeys: Ignored by the current implementation. + + Up to WinAppDbg 1.4 this setting caused the database keys to be + optimized when pickled with the standard C{pickle} module. + + But with a DBM database backend that causes inconsistencies, since the + same key can be serialized into multiple optimized pickles, thus losing + uniqueness. + + @type optimizeValues: bool + @cvar optimizeValues: C{True} to optimize the marshalling of keys, C{False} + otherwise. Only used with the C{pickle} module, ignored when using the + more secure C{cerealizer} module. + + @type compressKeys: bool + @cvar compressKeys: C{True} to compress keys when marshalling, C{False} + to leave them uncompressed. + + @type compressValues: bool + @cvar compressValues: C{True} to compress values when marshalling, C{False} + to leave them uncompressed. + + @type escapeKeys: bool + @cvar escapeKeys: C{True} to escape keys when marshalling, C{False} + to leave them uncompressed. + + @type escapeValues: bool + @cvar escapeValues: C{True} to escape values when marshalling, C{False} + to leave them uncompressed. + + @type binaryKeys: bool + @cvar binaryKeys: C{True} to marshall keys to binary format (the Python + C{buffer} type), C{False} to use text marshalled keys (C{str} type). + + @type binaryValues: bool + @cvar binaryValues: C{True} to marshall values to binary format (the Python + C{buffer} type), C{False} to use text marshalled values (C{str} type). + """ + + optimizeKeys = False + optimizeValues = True + compressKeys = False + compressValues = True + escapeKeys = False + escapeValues = False + binaryKeys = False + binaryValues = False + + def __init__(self, filename = None, allowRepeatedKeys = False): + """ + @type filename: str + @param filename: (Optional) File name for crash database. + If no filename is specified, the container is volatile. + + Volatile containers are stored only in memory and + destroyed when they go out of scope. + + @type allowRepeatedKeys: bool + @param allowRepeatedKeys: + Currently not supported, always use C{False}. + """ + if allowRepeatedKeys: + raise NotImplementedError() + self.__filename = filename + if filename: + global anydbm + if not anydbm: + import anydbm + self.__db = anydbm.open(filename, 'c') + self.__keys = dict([ (self.unmarshall_key(mk), mk) + for mk in self.__db.keys() ]) + else: + self.__db = dict() + self.__keys = dict() + + def remove_key(self, key): + """ + Removes the given key from the set of known keys. + + @type key: L{Crash} key. + @param key: Key to remove. + """ + del self.__keys[key] + + def marshall_key(self, key): + """ + Marshalls a Crash key to be used in the database. + + @see: L{__init__} + + @type key: L{Crash} key. + @param key: Key to convert. + + @rtype: str or buffer + @return: Converted key. + """ + if key in self.__keys: + return self.__keys[key] + skey = pickle.dumps(key, protocol = 0) + if self.compressKeys: + skey = zlib.compress(skey, zlib.Z_BEST_COMPRESSION) + if self.escapeKeys: + skey = skey.encode('hex') + if self.binaryKeys: + skey = buffer(skey) + self.__keys[key] = skey + return skey + + def unmarshall_key(self, key): + """ + Unmarshalls a Crash key read from the database. + + @type key: str or buffer + @param key: Key to convert. + + @rtype: L{Crash} key. + @return: Converted key. + """ + key = str(key) + if self.escapeKeys: + key = key.decode('hex') + if self.compressKeys: + key = zlib.decompress(key) + key = pickle.loads(key) + return key + + def marshall_value(self, value, storeMemoryMap = False): + """ + Marshalls a Crash object to be used in the database. + By default the C{memoryMap} member is B{NOT} stored here. + + @warning: Setting the C{storeMemoryMap} argument to C{True} can lead to + a severe performance penalty! + + @type value: L{Crash} + @param value: Object to convert. + + @type storeMemoryMap: bool + @param storeMemoryMap: C{True} to store the memory map, C{False} + otherwise. + + @rtype: str + @return: Converted object. + """ + if hasattr(value, 'memoryMap'): + crash = value + memoryMap = crash.memoryMap + try: + crash.memoryMap = None + if storeMemoryMap and memoryMap is not None: + # convert the generator to a list + crash.memoryMap = list(memoryMap) + if self.optimizeValues: + value = pickle.dumps(crash, protocol = HIGHEST_PROTOCOL) + value = optimize(value) + else: + value = pickle.dumps(crash, protocol = 0) + finally: + crash.memoryMap = memoryMap + del memoryMap + del crash + if self.compressValues: + value = zlib.compress(value, zlib.Z_BEST_COMPRESSION) + if self.escapeValues: + value = value.encode('hex') + if self.binaryValues: + value = buffer(value) + return value + + def unmarshall_value(self, value): + """ + Unmarshalls a Crash object read from the database. + + @type value: str + @param value: Object to convert. + + @rtype: L{Crash} + @return: Converted object. + """ + value = str(value) + if self.escapeValues: + value = value.decode('hex') + if self.compressValues: + value = zlib.decompress(value) + value = pickle.loads(value) + return value + + # The interface is meant to be similar to a Python set. + # However it may not be necessary to implement all of the set methods. + # Other methods like get, has_key, iterkeys and itervalues + # are dictionary-like. + + def __len__(self): + """ + @rtype: int + @return: Count of known keys. + """ + return len(self.__keys) + + def __bool__(self): + """ + @rtype: bool + @return: C{False} if there are no known keys. + """ + return bool(self.__keys) + + def __contains__(self, crash): + """ + @type crash: L{Crash} + @param crash: Crash object. + + @rtype: bool + @return: + C{True} if a Crash object with the same key is in the container. + """ + return self.has_key( crash.key() ) + + def has_key(self, key): + """ + @type key: L{Crash} key. + @param key: Key to find. + + @rtype: bool + @return: C{True} if the key is present in the set of known keys. + """ + return key in self.__keys + + def iterkeys(self): + """ + @rtype: iterator + @return: Iterator of known L{Crash} keys. + """ + return compat.iterkeys(self.__keys) + + class __CrashContainerIterator (object): + """ + Iterator of Crash objects. Returned by L{CrashContainer.__iter__}. + """ + + def __init__(self, container): + """ + @type container: L{CrashContainer} + @param container: Crash set to iterate. + """ + # It's important to keep a reference to the CrashContainer, + # rather than it's underlying database. + # Otherwise the destructor of CrashContainer may close the + # database while we're still iterating it. + # + # TODO: lock the database when iterating it. + # + self.__container = container + self.__keys_iter = compat.iterkeys(container) + + def next(self): + """ + @rtype: L{Crash} + @return: A B{copy} of a Crash object in the L{CrashContainer}. + @raise StopIteration: No more items left. + """ + key = self.__keys_iter.next() + return self.__container.get(key) + + def __del__(self): + "Class destructor. Closes the database when this object is destroyed." + try: + if self.__filename: + self.__db.close() + except: + pass + + def __iter__(self): + """ + @see: L{itervalues} + @rtype: iterator + @return: Iterator of the contained L{Crash} objects. + """ + return self.itervalues() + + def itervalues(self): + """ + @rtype: iterator + @return: Iterator of the contained L{Crash} objects. + + @warning: A B{copy} of each object is returned, + so any changes made to them will be lost. + + To preserve changes do the following: + 1. Keep a reference to the object. + 2. Delete the object from the set. + 3. Modify the object and add it again. + """ + return self.__CrashContainerIterator(self) + + def add(self, crash): + """ + Adds a new crash to the container. + If the crash appears to be already known, it's ignored. + + @see: L{Crash.key} + + @type crash: L{Crash} + @param crash: Crash object to add. + """ + if crash not in self: + key = crash.key() + skey = self.marshall_key(key) + data = self.marshall_value(crash, storeMemoryMap = True) + self.__db[skey] = data + + def __delitem__(self, key): + """ + Removes a crash from the container. + + @type key: L{Crash} unique key. + @param key: Key of the crash to get. + """ + skey = self.marshall_key(key) + del self.__db[skey] + self.remove_key(key) + + def remove(self, crash): + """ + Removes a crash from the container. + + @type crash: L{Crash} + @param crash: Crash object to remove. + """ + del self[ crash.key() ] + + def get(self, key): + """ + Retrieves a crash from the container. + + @type key: L{Crash} unique key. + @param key: Key of the crash to get. + + @rtype: L{Crash} object. + @return: Crash matching the given key. + + @see: L{iterkeys} + @warning: A B{copy} of each object is returned, + so any changes made to them will be lost. + + To preserve changes do the following: + 1. Keep a reference to the object. + 2. Delete the object from the set. + 3. Modify the object and add it again. + """ + skey = self.marshall_key(key) + data = self.__db[skey] + crash = self.unmarshall_value(data) + return crash + + def __getitem__(self, key): + """ + Retrieves a crash from the container. + + @type key: L{Crash} unique key. + @param key: Key of the crash to get. + + @rtype: L{Crash} object. + @return: Crash matching the given key. + + @see: L{iterkeys} + @warning: A B{copy} of each object is returned, + so any changes made to them will be lost. + + To preserve changes do the following: + 1. Keep a reference to the object. + 2. Delete the object from the set. + 3. Modify the object and add it again. + """ + return self.get(key) + +#============================================================================== + +class CrashDictionary(object): + """ + Dictionary-like persistence interface for L{Crash} objects. + + Currently the only implementation is through L{sql.CrashDAO}. + """ + + def __init__(self, url, creator = None, allowRepeatedKeys = True): + """ + @type url: str + @param url: Connection URL of the crash database. + See L{sql.CrashDAO.__init__} for more details. + + @type creator: callable + @param creator: (Optional) Callback function that creates the SQL + database connection. + + Normally it's not necessary to use this argument. However in some + odd cases you may need to customize the database connection, for + example when using the integrated authentication in MSSQL. + + @type allowRepeatedKeys: bool + @param allowRepeatedKeys: + If C{True} all L{Crash} objects are stored. + + If C{False} any L{Crash} object with the same signature as a + previously existing object will be ignored. + """ + global sql + if sql is None: + from winappdbg import sql + self._allowRepeatedKeys = allowRepeatedKeys + self._dao = sql.CrashDAO(url, creator) + + def add(self, crash): + """ + Adds a new crash to the container. + + @note: + When the C{allowRepeatedKeys} parameter of the constructor + is set to C{False}, duplicated crashes are ignored. + + @see: L{Crash.key} + + @type crash: L{Crash} + @param crash: Crash object to add. + """ + self._dao.add(crash, self._allowRepeatedKeys) + + def get(self, key): + """ + Retrieves a crash from the container. + + @type key: L{Crash} signature. + @param key: Heuristic signature of the crash to get. + + @rtype: L{Crash} object. + @return: Crash matching the given signature. If more than one is found, + retrieve the newest one. + + @see: L{iterkeys} + @warning: A B{copy} of each object is returned, + so any changes made to them will be lost. + + To preserve changes do the following: + 1. Keep a reference to the object. + 2. Delete the object from the set. + 3. Modify the object and add it again. + """ + found = self._dao.find(signature=key, limit=1, order=-1) + if not found: + raise KeyError(key) + return found[0] + + def __iter__(self): + """ + @rtype: iterator + @return: Iterator of the contained L{Crash} objects. + """ + offset = 0 + limit = 10 + while 1: + found = self._dao.find(offset=offset, limit=limit) + if not found: + break + offset += len(found) + for crash in found: + yield crash + + def itervalues(self): + """ + @rtype: iterator + @return: Iterator of the contained L{Crash} objects. + """ + return self.__iter__() + + def iterkeys(self): + """ + @rtype: iterator + @return: Iterator of the contained L{Crash} heuristic signatures. + """ + for crash in self: + yield crash.signature # FIXME this gives repeated results! + + def __contains__(self, crash): + """ + @type crash: L{Crash} + @param crash: Crash object. + + @rtype: bool + @return: C{True} if the Crash object is in the container. + """ + return self._dao.count(signature=crash.signature) > 0 + + def has_key(self, key): + """ + @type key: L{Crash} signature. + @param key: Heuristic signature of the crash to get. + + @rtype: bool + @return: C{True} if a matching L{Crash} object is in the container. + """ + return self._dao.count(signature=key) > 0 + + def __len__(self): + """ + @rtype: int + @return: Count of L{Crash} elements in the container. + """ + return self._dao.count() + + def __bool__(self): + """ + @rtype: bool + @return: C{False} if the container is empty. + """ + return bool( len(self) ) + +class CrashTable(CrashDictionary): + """ + Old crash dump persistencer using a SQLite database. + + @warning: + Superceded by L{CrashDictionary} since WinAppDbg 1.5. + New applications should not use this class. + """ + + def __init__(self, location = None, allowRepeatedKeys = True): + """ + @type location: str + @param location: (Optional) Location of the crash database. + If the location is a filename, it's an SQLite database file. + + If no location is specified, the container is volatile. + Volatile containers are stored only in memory and + destroyed when they go out of scope. + + @type allowRepeatedKeys: bool + @param allowRepeatedKeys: + If C{True} all L{Crash} objects are stored. + + If C{False} any L{Crash} object with the same signature as a + previously existing object will be ignored. + """ + warnings.warn( + "The %s class is deprecated since WinAppDbg 1.5." % self.__class__, + DeprecationWarning) + if location: + url = "sqlite:///%s" % location + else: + url = "sqlite://" + super(CrashTable, self).__init__(url, allowRepeatedKeys) + +class CrashTableMSSQL (CrashDictionary): + """ + Old crash dump persistencer using a Microsoft SQL Server database. + + @warning: + Superceded by L{CrashDictionary} since WinAppDbg 1.5. + New applications should not use this class. + """ + + def __init__(self, location = None, allowRepeatedKeys = True): + """ + @type location: str + @param location: Location of the crash database. + It must be an ODBC connection string. + + @type allowRepeatedKeys: bool + @param allowRepeatedKeys: + If C{True} all L{Crash} objects are stored. + + If C{False} any L{Crash} object with the same signature as a + previously existing object will be ignored. + """ + warnings.warn( + "The %s class is deprecated since WinAppDbg 1.5." % self.__class__, + DeprecationWarning) + import urllib + url = "mssql+pyodbc:///?odbc_connect=" + urllib.quote_plus(location) + super(CrashTableMSSQL, self).__init__(url, allowRepeatedKeys) + +class VolatileCrashContainer (CrashTable): + """ + Old in-memory crash dump storage. + + @warning: + Superceded by L{CrashDictionary} since WinAppDbg 1.5. + New applications should not use this class. + """ + + def __init__(self, allowRepeatedKeys = True): + """ + Volatile containers are stored only in memory and + destroyed when they go out of scope. + + @type allowRepeatedKeys: bool + @param allowRepeatedKeys: + If C{True} all L{Crash} objects are stored. + + If C{False} any L{Crash} object with the same key as a + previously existing object will be ignored. + """ + super(VolatileCrashContainer, self).__init__( + allowRepeatedKeys=allowRepeatedKeys) + +class DummyCrashContainer(object): + """ + Fakes a database of volatile Crash objects, + trying to mimic part of it's interface, but + doesn't actually store anything. + + Normally applications don't need to use this. + + @see: L{CrashDictionary} + """ + + def __init__(self, allowRepeatedKeys = True): + """ + Fake containers don't store L{Crash} objects, but they implement the + interface properly. + + @type allowRepeatedKeys: bool + @param allowRepeatedKeys: + Mimics the duplicate filter behavior found in real containers. + """ + self.__keys = set() + self.__count = 0 + self.__allowRepeatedKeys = allowRepeatedKeys + + def __contains__(self, crash): + """ + @type crash: L{Crash} + @param crash: Crash object. + + @rtype: bool + @return: C{True} if the Crash object is in the container. + """ + return crash.signature in self.__keys + + def __len__(self): + """ + @rtype: int + @return: Count of L{Crash} elements in the container. + """ + if self.__allowRepeatedKeys: + return self.__count + return len( self.__keys ) + + def __bool__(self): + """ + @rtype: bool + @return: C{False} if the container is empty. + """ + return bool( len(self) ) + + def add(self, crash): + """ + Adds a new crash to the container. + + @note: + When the C{allowRepeatedKeys} parameter of the constructor + is set to C{False}, duplicated crashes are ignored. + + @see: L{Crash.key} + + @type crash: L{Crash} + @param crash: Crash object to add. + """ + self.__keys.add( crash.signature ) + self.__count += 1 + + def get(self, key): + """ + This method is not supported. + """ + raise NotImplementedError() + + def has_key(self, key): + """ + @type key: L{Crash} signature. + @param key: Heuristic signature of the crash to get. + + @rtype: bool + @return: C{True} if a matching L{Crash} object is in the container. + """ + return self.__keys.has_key( key ) + + def iterkeys(self): + """ + @rtype: iterator + @return: Iterator of the contained L{Crash} object keys. + + @see: L{get} + @warning: A B{copy} of each object is returned, + so any changes made to them will be lost. + + To preserve changes do the following: + 1. Keep a reference to the object. + 2. Delete the object from the set. + 3. Modify the object and add it again. + """ + return iter(self.__keys) + +#============================================================================== +# Register the Crash class with the secure serializer. + +try: + cerealizer.register(Crash) + cerealizer.register(win32.MemoryBasicInformation) +except NameError: + pass diff --git a/pydevd_attach_to_process/winappdbg/debug.py b/pydevd_attach_to_process/winappdbg/debug.py new file mode 100644 index 0000000..8364a5b --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/debug.py @@ -0,0 +1,1543 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Debugging. + +@group Debugging: + Debug + +@group Warnings: + MixedBitsWarning +""" + +__revision__ = "$Id$" + +__all__ = [ 'Debug', 'MixedBitsWarning' ] + +import sys +from winappdbg import win32 +from winappdbg.system import System +from winappdbg.process import Process +from winappdbg.thread import Thread +from winappdbg.module import Module +from winappdbg.window import Window +from winappdbg.breakpoint import _BreakpointContainer, CodeBreakpoint +from winappdbg.event import Event, EventHandler, EventDispatcher, EventFactory +from winappdbg.interactive import ConsoleDebugger + +import warnings +##import traceback + +#============================================================================== + +# If you set this warning to be considered as an error, you can stop the +# debugger from attaching to 64-bit processes from a 32-bit Python VM and +# visceversa. +class MixedBitsWarning (RuntimeWarning): + """ + This warning is issued when mixing 32 and 64 bit processes. + """ + +#============================================================================== + +# TODO +# * Add memory read and write operations, similar to those in the Process +# class, but hiding the presence of the code breakpoints. +# * Add a method to get the memory map of a process, but hiding the presence +# of the page breakpoints. +# * Maybe the previous two features should be implemented at the Process class +# instead, but how to communicate with the Debug object without creating +# circular references? Perhaps the "overrides" could be set using private +# members (so users won't see them), but then there's the problem of the +# users being able to access the snapshot (i.e. clear it), which is why it's +# not such a great idea to use the snapshot to store data that really belongs +# to the Debug class. + +class Debug (EventDispatcher, _BreakpointContainer): + """ + The main debugger class. + + @group Debugging: + interactive, attach, detach, detach_from_all, execv, execl, + kill, kill_all, + get_debugee_count, get_debugee_pids, + is_debugee, is_debugee_attached, is_debugee_started, + in_hostile_mode, + add_existing_session + + @group Debugging loop: + loop, stop, next, wait, dispatch, cont + + @undocumented: force_garbage_collection + + @type system: L{System} + @ivar system: A System snapshot that is automatically updated for + processes being debugged. Processes not being debugged in this snapshot + may be outdated. + """ + + # Automatically set to True the first time a Debug object is instanced. + _debug_static_init = False + + def __init__(self, eventHandler = None, bKillOnExit = False, + bHostileCode = False): + """ + Debugger object. + + @type eventHandler: L{EventHandler} + @param eventHandler: + (Optional, recommended) Custom event handler object. + + @type bKillOnExit: bool + @param bKillOnExit: (Optional) Kill on exit mode. + If C{True} debugged processes are killed when the debugger is + stopped. If C{False} when the debugger stops it detaches from all + debugged processes and leaves them running (default). + + @type bHostileCode: bool + @param bHostileCode: (Optional) Hostile code mode. + Set to C{True} to take some basic precautions against anti-debug + tricks. Disabled by default. + + @warn: When hostile mode is enabled, some things may not work as + expected! This is because the anti-anti debug tricks may disrupt + the behavior of the Win32 debugging APIs or WinAppDbg itself. + + @note: The L{eventHandler} parameter may be any callable Python object + (for example a function, or an instance method). + However you'll probably find it more convenient to use an instance + of a subclass of L{EventHandler} here. + + @raise WindowsError: Raises an exception on error. + """ + EventDispatcher.__init__(self, eventHandler) + _BreakpointContainer.__init__(self) + + self.system = System() + self.lastEvent = None + self.__firstDebugee = True + self.__bKillOnExit = bKillOnExit + self.__bHostileCode = bHostileCode + self.__breakOnEP = set() # set of pids + self.__attachedDebugees = set() # set of pids + self.__startedDebugees = set() # set of pids + + if not self._debug_static_init: + self._debug_static_init = True + + # Request debug privileges for the current process. + # Only do this once, and only after instancing a Debug object, + # so passive debuggers don't get detected because of this. + self.system.request_debug_privileges(bIgnoreExceptions = False) + + # Try to fix the symbol store path if it wasn't set. + # But don't enable symbol downloading by default, since it may + # degrade performance severely. + self.system.fix_symbol_store_path(remote = False, force = False) + +## # It's hard not to create circular references, +## # and if we have a destructor, we can end up leaking everything. +## # It's best to code the debugging loop properly to always +## # stop the debugger before going out of scope. +## def __del__(self): +## self.stop() + + def __enter__(self): + """ + Compatibility with the "C{with}" Python statement. + """ + return self + + def __exit__(self, type, value, traceback): + """ + Compatibility with the "C{with}" Python statement. + """ + self.stop() + + def __len__(self): + """ + @rtype: int + @return: Number of processes being debugged. + """ + return self.get_debugee_count() + + # TODO: maybe custom __bool__ to break out of loop() ? + # it already does work (because of __len__) but it'd be + # useful to do it from the event handler anyway + +#------------------------------------------------------------------------------ + + def __setSystemKillOnExitMode(self): + # Make sure the default system behavior on detaching from processes + # versus killing them matches our preferences. This only affects the + # scenario where the Python VM dies unexpectedly without running all + # the finally clauses, or the user failed to either instance the Debug + # object inside a with block or call the stop() method before quitting. + if self.__firstDebugee: + try: + System.set_kill_on_exit_mode(self.__bKillOnExit) + self.__firstDebugee = False + except Exception: + pass + + def attach(self, dwProcessId): + """ + Attaches to an existing process for debugging. + + @see: L{detach}, L{execv}, L{execl} + + @type dwProcessId: int + @param dwProcessId: Global ID of a process to attach to. + + @rtype: L{Process} + @return: A new Process object. Normally you don't need to use it now, + it's best to interact with the process from the event handler. + + @raise WindowsError: Raises an exception on error. + Depending on the circumstances, the debugger may or may not have + attached to the target process. + """ + + # Get the Process object from the snapshot, + # if missing create a new one. + try: + aProcess = self.system.get_process(dwProcessId) + except KeyError: + aProcess = Process(dwProcessId) + + # Warn when mixing 32 and 64 bits. + # This also allows the user to stop attaching altogether, + # depending on how the warnings are configured. + if System.bits != aProcess.get_bits(): + msg = "Mixture of 32 and 64 bits is considered experimental." \ + " Use at your own risk!" + warnings.warn(msg, MixedBitsWarning) + + # Attach to the process. + win32.DebugActiveProcess(dwProcessId) + + # Add the new PID to the set of debugees. + self.__attachedDebugees.add(dwProcessId) + + # Match the system kill-on-exit flag to our own. + self.__setSystemKillOnExitMode() + + # If the Process object was not in the snapshot, add it now. + if not self.system.has_process(dwProcessId): + self.system._add_process(aProcess) + + # Scan the process threads and loaded modules. + # This is prefered because the thread and library events do not + # properly give some information, like the filename for each module. + aProcess.scan_threads() + aProcess.scan_modules() + + # Return the Process object, like the execv() and execl() methods. + return aProcess + + def execv(self, argv, **kwargs): + """ + Starts a new process for debugging. + + This method uses a list of arguments. To use a command line string + instead, use L{execl}. + + @see: L{attach}, L{detach} + + @type argv: list( str... ) + @param argv: List of command line arguments to pass to the debugee. + The first element must be the debugee executable filename. + + @type bBreakOnEntryPoint: bool + @keyword bBreakOnEntryPoint: C{True} to automatically set a breakpoint + at the program entry point. + + @type bConsole: bool + @keyword bConsole: True to inherit the console of the debugger. + Defaults to C{False}. + + @type bFollow: bool + @keyword bFollow: C{True} to automatically attach to child processes. + Defaults to C{False}. + + @type bInheritHandles: bool + @keyword bInheritHandles: C{True} if the new process should inherit + it's parent process' handles. Defaults to C{False}. + + @type bSuspended: bool + @keyword bSuspended: C{True} to suspend the main thread before any code + is executed in the debugee. Defaults to C{False}. + + @keyword dwParentProcessId: C{None} or C{0} if the debugger process + should be the parent process (default), or a process ID to + forcefully set as the debugee's parent (only available for Windows + Vista and above). + + In hostile mode, the default is not the debugger process but the + process ID for "explorer.exe". + + @type iTrustLevel: int or None + @keyword iTrustLevel: Trust level. + Must be one of the following values: + - 0: B{No trust}. May not access certain resources, such as + cryptographic keys and credentials. Only available since + Windows XP and 2003, desktop editions. This is the default + in hostile mode. + - 1: B{Normal trust}. Run with the same privileges as a normal + user, that is, one that doesn't have the I{Administrator} or + I{Power User} user rights. Only available since Windows XP + and 2003, desktop editions. + - 2: B{Full trust}. Run with the exact same privileges as the + current user. This is the default in normal mode. + + @type bAllowElevation: bool + @keyword bAllowElevation: C{True} to allow the child process to keep + UAC elevation, if the debugger itself is running elevated. C{False} + to ensure the child process doesn't run with elevation. Defaults to + C{True}. + + This flag is only meaningful on Windows Vista and above, and if the + debugger itself is running with elevation. It can be used to make + sure the child processes don't run elevated as well. + + This flag DOES NOT force an elevation prompt when the debugger is + not running with elevation. + + Note that running the debugger with elevation (or the Python + interpreter at all for that matter) is not normally required. + You should only need to if the target program requires elevation + to work properly (for example if you try to debug an installer). + + @rtype: L{Process} + @return: A new Process object. Normally you don't need to use it now, + it's best to interact with the process from the event handler. + + @raise WindowsError: Raises an exception on error. + """ + if type(argv) in (str, compat.unicode): + raise TypeError("Debug.execv expects a list, not a string") + lpCmdLine = self.system.argv_to_cmdline(argv) + return self.execl(lpCmdLine, **kwargs) + + def execl(self, lpCmdLine, **kwargs): + """ + Starts a new process for debugging. + + This method uses a command line string. To use a list of arguments + instead, use L{execv}. + + @see: L{attach}, L{detach} + + @type lpCmdLine: str + @param lpCmdLine: Command line string to execute. + The first token must be the debugee executable filename. + Tokens with spaces must be enclosed in double quotes. + Tokens including double quote characters must be escaped with a + backslash. + + @type bBreakOnEntryPoint: bool + @keyword bBreakOnEntryPoint: C{True} to automatically set a breakpoint + at the program entry point. Defaults to C{False}. + + @type bConsole: bool + @keyword bConsole: True to inherit the console of the debugger. + Defaults to C{False}. + + @type bFollow: bool + @keyword bFollow: C{True} to automatically attach to child processes. + Defaults to C{False}. + + @type bInheritHandles: bool + @keyword bInheritHandles: C{True} if the new process should inherit + it's parent process' handles. Defaults to C{False}. + + @type bSuspended: bool + @keyword bSuspended: C{True} to suspend the main thread before any code + is executed in the debugee. Defaults to C{False}. + + @type dwParentProcessId: int or None + @keyword dwParentProcessId: C{None} or C{0} if the debugger process + should be the parent process (default), or a process ID to + forcefully set as the debugee's parent (only available for Windows + Vista and above). + + In hostile mode, the default is not the debugger process but the + process ID for "explorer.exe". + + @type iTrustLevel: int + @keyword iTrustLevel: Trust level. + Must be one of the following values: + - 0: B{No trust}. May not access certain resources, such as + cryptographic keys and credentials. Only available since + Windows XP and 2003, desktop editions. This is the default + in hostile mode. + - 1: B{Normal trust}. Run with the same privileges as a normal + user, that is, one that doesn't have the I{Administrator} or + I{Power User} user rights. Only available since Windows XP + and 2003, desktop editions. + - 2: B{Full trust}. Run with the exact same privileges as the + current user. This is the default in normal mode. + + @type bAllowElevation: bool + @keyword bAllowElevation: C{True} to allow the child process to keep + UAC elevation, if the debugger itself is running elevated. C{False} + to ensure the child process doesn't run with elevation. Defaults to + C{True} in normal mode and C{False} in hostile mode. + + This flag is only meaningful on Windows Vista and above, and if the + debugger itself is running with elevation. It can be used to make + sure the child processes don't run elevated as well. + + This flag DOES NOT force an elevation prompt when the debugger is + not running with elevation. + + Note that running the debugger with elevation (or the Python + interpreter at all for that matter) is not normally required. + You should only need to if the target program requires elevation + to work properly (for example if you try to debug an installer). + + @rtype: L{Process} + @return: A new Process object. Normally you don't need to use it now, + it's best to interact with the process from the event handler. + + @raise WindowsError: Raises an exception on error. + """ + if type(lpCmdLine) not in (str, compat.unicode): + warnings.warn("Debug.execl expects a string") + + # Set the "debug" flag to True. + kwargs['bDebug'] = True + + # Pop the "break on entry point" flag. + bBreakOnEntryPoint = kwargs.pop('bBreakOnEntryPoint', False) + + # Set the default trust level if requested. + if 'iTrustLevel' not in kwargs: + if self.__bHostileCode: + kwargs['iTrustLevel'] = 0 + else: + kwargs['iTrustLevel'] = 2 + + # Set the default UAC elevation flag if requested. + if 'bAllowElevation' not in kwargs: + kwargs['bAllowElevation'] = not self.__bHostileCode + + # In hostile mode the default parent process is explorer.exe. + # Only supported for Windows Vista and above. + if self.__bHostileCode and not kwargs.get('dwParentProcessId', None): + try: + vista_and_above = self.__vista_and_above + except AttributeError: + osi = win32.OSVERSIONINFOEXW() + osi.dwMajorVersion = 6 + osi.dwMinorVersion = 0 + osi.dwPlatformId = win32.VER_PLATFORM_WIN32_NT + mask = 0 + mask = win32.VerSetConditionMask(mask, + win32.VER_MAJORVERSION, + win32.VER_GREATER_EQUAL) + mask = win32.VerSetConditionMask(mask, + win32.VER_MAJORVERSION, + win32.VER_GREATER_EQUAL) + mask = win32.VerSetConditionMask(mask, + win32.VER_PLATFORMID, + win32.VER_EQUAL) + vista_and_above = win32.VerifyVersionInfoW(osi, + win32.VER_MAJORVERSION | \ + win32.VER_MINORVERSION | \ + win32.VER_PLATFORMID, + mask) + self.__vista_and_above = vista_and_above + if vista_and_above: + dwParentProcessId = self.system.get_explorer_pid() + if dwParentProcessId: + kwargs['dwParentProcessId'] = dwParentProcessId + else: + msg = ("Failed to find \"explorer.exe\"!" + " Using the debugger as parent process.") + warnings.warn(msg, RuntimeWarning) + + # Start the new process. + aProcess = None + try: + aProcess = self.system.start_process(lpCmdLine, **kwargs) + dwProcessId = aProcess.get_pid() + + # Match the system kill-on-exit flag to our own. + self.__setSystemKillOnExitMode() + + # Warn when mixing 32 and 64 bits. + # This also allows the user to stop attaching altogether, + # depending on how the warnings are configured. + if System.bits != aProcess.get_bits(): + msg = "Mixture of 32 and 64 bits is considered experimental." \ + " Use at your own risk!" + warnings.warn(msg, MixedBitsWarning) + + # Add the new PID to the set of debugees. + self.__startedDebugees.add(dwProcessId) + + # Add the new PID to the set of "break on EP" debugees if needed. + if bBreakOnEntryPoint: + self.__breakOnEP.add(dwProcessId) + + # Return the Process object. + return aProcess + + # On error kill the new process and raise an exception. + except: + if aProcess is not None: + try: + try: + self.__startedDebugees.remove(aProcess.get_pid()) + except KeyError: + pass + finally: + try: + try: + self.__breakOnEP.remove(aProcess.get_pid()) + except KeyError: + pass + finally: + try: + aProcess.kill() + except Exception: + pass + raise + + def add_existing_session(self, dwProcessId, bStarted = False): + """ + Use this method only when for some reason the debugger's been attached + to the target outside of WinAppDbg (for example when integrating with + other tools). + + You don't normally need to call this method. Most users should call + L{attach}, L{execv} or L{execl} instead. + + @type dwProcessId: int + @param dwProcessId: Global process ID. + + @type bStarted: bool + @param bStarted: C{True} if the process was started by the debugger, + or C{False} if the process was attached to instead. + + @raise WindowsError: The target process does not exist, is not attached + to the debugger anymore. + """ + + # Register the process object with the snapshot. + if not self.system.has_process(dwProcessId): + aProcess = Process(dwProcessId) + self.system._add_process(aProcess) + else: + aProcess = self.system.get_process(dwProcessId) + + # Test for debug privileges on the target process. + # Raises WindowsException on error. + aProcess.get_handle() + + # Register the process ID with the debugger. + if bStarted: + self.__attachedDebugees.add(dwProcessId) + else: + self.__startedDebugees.add(dwProcessId) + + # Match the system kill-on-exit flag to our own. + self.__setSystemKillOnExitMode() + + # Scan the process threads and loaded modules. + # This is prefered because the thread and library events do not + # properly give some information, like the filename for each module. + aProcess.scan_threads() + aProcess.scan_modules() + + def __cleanup_process(self, dwProcessId, bIgnoreExceptions = False): + """ + Perform the necessary cleanup of a process about to be killed or + detached from. + + This private method is called by L{kill} and L{detach}. + + @type dwProcessId: int + @param dwProcessId: Global ID of a process to kill. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when killing the process. + + @raise WindowsError: Raises an exception on error, unless + C{bIgnoreExceptions} is C{True}. + """ + # If the process is being debugged... + if self.is_debugee(dwProcessId): + + # Make sure a Process object exists or the following calls fail. + if not self.system.has_process(dwProcessId): + aProcess = Process(dwProcessId) + try: + aProcess.get_handle() + except WindowsError: + pass # fails later on with more specific reason + self.system._add_process(aProcess) + + # Erase all breakpoints in the process. + try: + self.erase_process_breakpoints(dwProcessId) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Stop tracing all threads in the process. + try: + self.stop_tracing_process(dwProcessId) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # The process is no longer a debugee. + try: + if dwProcessId in self.__attachedDebugees: + self.__attachedDebugees.remove(dwProcessId) + if dwProcessId in self.__startedDebugees: + self.__startedDebugees.remove(dwProcessId) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Clear and remove the process from the snapshot. + # If the user wants to do something with it after detaching + # a new Process instance should be created. + try: + if self.system.has_process(dwProcessId): + try: + self.system.get_process(dwProcessId).clear() + finally: + self.system._del_process(dwProcessId) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # If the last debugging event is related to this process, forget it. + try: + if self.lastEvent and self.lastEvent.get_pid() == dwProcessId: + self.lastEvent = None + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + def kill(self, dwProcessId, bIgnoreExceptions = False): + """ + Kills a process currently being debugged. + + @see: L{detach} + + @type dwProcessId: int + @param dwProcessId: Global ID of a process to kill. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when killing the process. + + @raise WindowsError: Raises an exception on error, unless + C{bIgnoreExceptions} is C{True}. + """ + + # Keep a reference to the process. We'll need it later. + try: + aProcess = self.system.get_process(dwProcessId) + except KeyError: + aProcess = Process(dwProcessId) + + # Cleanup all data referring to the process. + self.__cleanup_process(dwProcessId, + bIgnoreExceptions = bIgnoreExceptions) + + # Kill the process. + try: + try: + if self.is_debugee(dwProcessId): + try: + if aProcess.is_alive(): + aProcess.suspend() + finally: + self.detach(dwProcessId, + bIgnoreExceptions = bIgnoreExceptions) + finally: + aProcess.kill() + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Cleanup what remains of the process data. + try: + aProcess.clear() + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + def kill_all(self, bIgnoreExceptions = False): + """ + Kills from all processes currently being debugged. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when killing each process. C{False} to stop and raise an + exception when encountering an error. + + @raise WindowsError: Raises an exception on error, unless + C{bIgnoreExceptions} is C{True}. + """ + for pid in self.get_debugee_pids(): + self.kill(pid, bIgnoreExceptions = bIgnoreExceptions) + + def detach(self, dwProcessId, bIgnoreExceptions = False): + """ + Detaches from a process currently being debugged. + + @note: On Windows 2000 and below the process is killed. + + @see: L{attach}, L{detach_from_all} + + @type dwProcessId: int + @param dwProcessId: Global ID of a process to detach from. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when detaching. C{False} to stop and raise an exception when + encountering an error. + + @raise WindowsError: Raises an exception on error, unless + C{bIgnoreExceptions} is C{True}. + """ + + # Keep a reference to the process. We'll need it later. + try: + aProcess = self.system.get_process(dwProcessId) + except KeyError: + aProcess = Process(dwProcessId) + + # Determine if there is support for detaching. + # This check should only fail on Windows 2000 and older. + try: + win32.DebugActiveProcessStop + can_detach = True + except AttributeError: + can_detach = False + + # Continue the last event before detaching. + # XXX not sure about this... + try: + if can_detach and self.lastEvent and \ + self.lastEvent.get_pid() == dwProcessId: + self.cont(self.lastEvent) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Cleanup all data referring to the process. + self.__cleanup_process(dwProcessId, + bIgnoreExceptions = bIgnoreExceptions) + + try: + # Detach from the process. + # On Windows 2000 and before, kill the process. + if can_detach: + try: + win32.DebugActiveProcessStop(dwProcessId) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + else: + try: + aProcess.kill() + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + finally: + + # Cleanup what remains of the process data. + aProcess.clear() + + def detach_from_all(self, bIgnoreExceptions = False): + """ + Detaches from all processes currently being debugged. + + @note: To better handle last debugging event, call L{stop} instead. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when detaching. + + @raise WindowsError: Raises an exception on error, unless + C{bIgnoreExceptions} is C{True}. + """ + for pid in self.get_debugee_pids(): + self.detach(pid, bIgnoreExceptions = bIgnoreExceptions) + +#------------------------------------------------------------------------------ + + def wait(self, dwMilliseconds = None): + """ + Waits for the next debug event. + + @see: L{cont}, L{dispatch}, L{loop} + + @type dwMilliseconds: int + @param dwMilliseconds: (Optional) Timeout in milliseconds. + Use C{INFINITE} or C{None} for no timeout. + + @rtype: L{Event} + @return: An event that occured in one of the debugees. + + @raise WindowsError: Raises an exception on error. + If no target processes are left to debug, + the error code is L{win32.ERROR_INVALID_HANDLE}. + """ + + # Wait for the next debug event. + raw = win32.WaitForDebugEvent(dwMilliseconds) + event = EventFactory.get(self, raw) + + # Remember it. + self.lastEvent = event + + # Return it. + return event + + def dispatch(self, event = None): + """ + Calls the debug event notify callbacks. + + @see: L{cont}, L{loop}, L{wait} + + @type event: L{Event} + @param event: (Optional) Event object returned by L{wait}. + + @raise WindowsError: Raises an exception on error. + """ + + # If no event object was given, use the last event. + if event is None: + event = self.lastEvent + + # Ignore dummy events. + if not event: + return + + # Determine the default behaviour for this event. + # XXX HACK + # Some undocumented flags are used, but as far as I know in those + # versions of Windows that don't support them they should behave + # like DGB_CONTINUE. + + code = event.get_event_code() + if code == win32.EXCEPTION_DEBUG_EVENT: + + # At this point, by default some exception types are swallowed by + # the debugger, because we don't know yet if it was caused by the + # debugger itself or the debugged process. + # + # Later on (see breakpoint.py) if we determined the exception was + # not caused directly by the debugger itself, we set the default + # back to passing the exception to the debugee. + # + # The "invalid handle" exception is also swallowed by the debugger + # because it's not normally generated by the debugee. But in + # hostile mode we want to pass it to the debugee, as it may be the + # result of an anti-debug trick. In that case it's best to disable + # bad handles detection with Microsoft's gflags.exe utility. See: + # http://msdn.microsoft.com/en-us/library/windows/hardware/ff549557(v=vs.85).aspx + + exc_code = event.get_exception_code() + if exc_code in ( + win32.EXCEPTION_BREAKPOINT, + win32.EXCEPTION_WX86_BREAKPOINT, + win32.EXCEPTION_SINGLE_STEP, + win32.EXCEPTION_GUARD_PAGE, + ): + event.continueStatus = win32.DBG_CONTINUE + elif exc_code == win32.EXCEPTION_INVALID_HANDLE: + if self.__bHostileCode: + event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED + else: + event.continueStatus = win32.DBG_CONTINUE + else: + event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED + + elif code == win32.RIP_EVENT and \ + event.get_rip_type() == win32.SLE_ERROR: + + # RIP events that signal fatal events should kill the process. + event.continueStatus = win32.DBG_TERMINATE_PROCESS + + else: + + # Other events need this continue code. + # Sometimes other codes can be used and are ignored, sometimes not. + # For example, when using the DBG_EXCEPTION_NOT_HANDLED code, + # debug strings are sent twice (!) + event.continueStatus = win32.DBG_CONTINUE + + # Dispatch the debug event. + return EventDispatcher.dispatch(self, event) + + def cont(self, event = None): + """ + Resumes execution after processing a debug event. + + @see: dispatch(), loop(), wait() + + @type event: L{Event} + @param event: (Optional) Event object returned by L{wait}. + + @raise WindowsError: Raises an exception on error. + """ + + # If no event object was given, use the last event. + if event is None: + event = self.lastEvent + + # Ignore dummy events. + if not event: + return + + # Get the event continue status information. + dwProcessId = event.get_pid() + dwThreadId = event.get_tid() + dwContinueStatus = event.continueStatus + + # Check if the process is still being debugged. + if self.is_debugee(dwProcessId): + + # Try to flush the instruction cache. + try: + if self.system.has_process(dwProcessId): + aProcess = self.system.get_process(dwProcessId) + else: + aProcess = Process(dwProcessId) + aProcess.flush_instruction_cache() + except WindowsError: + pass + + # XXX TODO + # + # Try to execute the UnhandledExceptionFilter for second chance + # exceptions, at least when in hostile mode (in normal mode it + # would be breaking compatibility, as users may actually expect + # second chance exceptions to be raised again). + # + # Reportedly in Windows 7 (maybe in Vista too) this seems to be + # happening already. In XP and below the UnhandledExceptionFilter + # was never called for processes being debugged. + + # Continue execution of the debugee. + win32.ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus) + + # If the event is the last event, forget it. + if event == self.lastEvent: + self.lastEvent = None + + def stop(self, bIgnoreExceptions = True): + """ + Stops debugging all processes. + + If the kill on exit mode is on, debugged processes are killed when the + debugger is stopped. Otherwise when the debugger stops it detaches from + all debugged processes and leaves them running (default). For more + details see: L{__init__} + + @note: This method is better than L{detach_from_all} because it can + gracefully handle the last debugging event before detaching. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when detaching. + """ + + # Determine if we have a last debug event that we need to continue. + try: + event = self.lastEvent + has_event = bool(event) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + has_event = False + + # If we do... + if has_event: + + # Disable all breakpoints in the process before resuming execution. + try: + pid = event.get_pid() + self.disable_process_breakpoints(pid) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Disable all breakpoints in the thread before resuming execution. + try: + tid = event.get_tid() + self.disable_thread_breakpoints(tid) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Resume execution. + try: + event.continueDebugEvent = win32.DBG_CONTINUE + self.cont(event) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Detach from or kill all debuggees. + try: + if self.__bKillOnExit: + self.kill_all(bIgnoreExceptions) + else: + self.detach_from_all(bIgnoreExceptions) + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Cleanup the process snapshots. + try: + self.system.clear() + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + + # Close all Win32 handles the Python garbage collector failed to close. + self.force_garbage_collection(bIgnoreExceptions) + + def next(self): + """ + Handles the next debug event. + + @see: L{cont}, L{dispatch}, L{wait}, L{stop} + + @raise WindowsError: Raises an exception on error. + + If the wait operation causes an error, debugging is stopped + (meaning all debugees are either killed or detached from). + + If the event dispatching causes an error, the event is still + continued before returning. This may happen, for example, if the + event handler raises an exception nobody catches. + """ + try: + event = self.wait() + except Exception: + self.stop() + raise + try: + self.dispatch() + finally: + self.cont() + + def loop(self): + """ + Simple debugging loop. + + This debugging loop is meant to be useful for most simple scripts. + It iterates as long as there is at least one debugee, or an exception + is raised. Multiple calls are allowed. + + This is a trivial example script:: + import sys + debug = Debug() + try: + debug.execv( sys.argv [ 1 : ] ) + debug.loop() + finally: + debug.stop() + + @see: L{next}, L{stop} + + U{http://msdn.microsoft.com/en-us/library/ms681675(VS.85).aspx} + + @raise WindowsError: Raises an exception on error. + + If the wait operation causes an error, debugging is stopped + (meaning all debugees are either killed or detached from). + + If the event dispatching causes an error, the event is still + continued before returning. This may happen, for example, if the + event handler raises an exception nobody catches. + """ + while self: + self.next() + + def get_debugee_count(self): + """ + @rtype: int + @return: Number of processes being debugged. + """ + return len(self.__attachedDebugees) + len(self.__startedDebugees) + + def get_debugee_pids(self): + """ + @rtype: list( int... ) + @return: Global IDs of processes being debugged. + """ + return list(self.__attachedDebugees) + list(self.__startedDebugees) + + def is_debugee(self, dwProcessId): + """ + Determine if the debugger is debugging the given process. + + @see: L{is_debugee_attached}, L{is_debugee_started} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @rtype: bool + @return: C{True} if the given process is being debugged + by this L{Debug} instance. + """ + return self.is_debugee_attached(dwProcessId) or \ + self.is_debugee_started(dwProcessId) + + def is_debugee_started(self, dwProcessId): + """ + Determine if the given process was started by the debugger. + + @see: L{is_debugee}, L{is_debugee_attached} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @rtype: bool + @return: C{True} if the given process was started for debugging by this + L{Debug} instance. + """ + return dwProcessId in self.__startedDebugees + + def is_debugee_attached(self, dwProcessId): + """ + Determine if the debugger is attached to the given process. + + @see: L{is_debugee}, L{is_debugee_started} + + @type dwProcessId: int + @param dwProcessId: Process global ID. + + @rtype: bool + @return: C{True} if the given process is attached to this + L{Debug} instance. + """ + return dwProcessId in self.__attachedDebugees + + def in_hostile_mode(self): + """ + Determine if we're in hostile mode (anti-anti-debug). + + @rtype: bool + @return: C{True} if this C{Debug} instance was started in hostile mode, + C{False} otherwise. + """ + return self.__bHostileCode + +#------------------------------------------------------------------------------ + + def interactive(self, bConfirmQuit = True, bShowBanner = True): + """ + Start an interactive debugging session. + + @type bConfirmQuit: bool + @param bConfirmQuit: Set to C{True} to ask the user for confirmation + before closing the session, C{False} otherwise. + + @type bShowBanner: bool + @param bShowBanner: Set to C{True} to show a banner before entering + the session and after leaving it, C{False} otherwise. + + @warn: This will temporarily disable the user-defined event handler! + + This method returns when the user closes the session. + """ + print('') + print("-" * 79) + print("Interactive debugging session started.") + print("Use the \"help\" command to list all available commands.") + print("Use the \"quit\" command to close this session.") + print("-" * 79) + if self.lastEvent is None: + print('') + console = ConsoleDebugger() + console.confirm_quit = bConfirmQuit + console.load_history() + try: + console.start_using_debugger(self) + console.loop() + finally: + console.stop_using_debugger() + console.save_history() + print('') + print("-" * 79) + print("Interactive debugging session closed.") + print("-" * 79) + print('') + +#------------------------------------------------------------------------------ + + @staticmethod + def force_garbage_collection(bIgnoreExceptions = True): + """ + Close all Win32 handles the Python garbage collector failed to close. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when detaching. + """ + try: + import gc + gc.collect() + bRecollect = False + for obj in list(gc.garbage): + try: + if isinstance(obj, win32.Handle): + obj.close() + elif isinstance(obj, Event): + obj.debug = None + elif isinstance(obj, Process): + obj.clear() + elif isinstance(obj, Thread): + obj.set_process(None) + obj.clear() + elif isinstance(obj, Module): + obj.set_process(None) + elif isinstance(obj, Window): + obj.set_process(None) + else: + continue + gc.garbage.remove(obj) + del obj + bRecollect = True + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + if bRecollect: + gc.collect() + except Exception: + if not bIgnoreExceptions: + raise + e = sys.exc_info()[1] + warnings.warn(str(e), RuntimeWarning) + +#------------------------------------------------------------------------------ + + def _notify_create_process(self, event): + """ + Notify the creation of a new process. + + @warning: This method is meant to be used internally by the debugger. + + @type event: L{CreateProcessEvent} + @param event: Create process event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + dwProcessId = event.get_pid() + if dwProcessId not in self.__attachedDebugees: + if dwProcessId not in self.__startedDebugees: + self.__startedDebugees.add(dwProcessId) + + retval = self.system._notify_create_process(event) + + # Set a breakpoint on the program's entry point if requested. + # Try not to use the Event object's entry point value, as in some cases + # it may be wrong. See: http://pferrie.host22.com/misc/lowlevel3.htm + if dwProcessId in self.__breakOnEP: + try: + lpEntryPoint = event.get_process().get_entry_point() + except Exception: + lpEntryPoint = event.get_start_address() + + # It'd be best to use a hardware breakpoint instead, at least in + # hostile mode. But since the main thread's context gets smashed + # by the loader, I haven't found a way to make it work yet. + self.break_at(dwProcessId, lpEntryPoint) + + # Defeat isDebuggerPresent by patching PEB->BeingDebugged. + # When we do this, some debugging APIs cease to work as expected. + # For example, the system breakpoint isn't hit when we attach. + # For that reason we need to define a code breakpoint at the + # code location where a new thread is spawned by the debugging + # APIs, ntdll!DbgUiRemoteBreakin. + if self.__bHostileCode: + aProcess = event.get_process() + try: + hProcess = aProcess.get_handle(win32.PROCESS_QUERY_INFORMATION) + pbi = win32.NtQueryInformationProcess( + hProcess, win32.ProcessBasicInformation) + ptr = pbi.PebBaseAddress + 2 + if aProcess.peek(ptr, 1) == '\x01': + aProcess.poke(ptr, '\x00') + except WindowsError: + e = sys.exc_info()[1] + warnings.warn( + "Cannot patch PEB->BeingDebugged, reason: %s" % e.strerror) + + return retval + + def _notify_create_thread(self, event): + """ + Notify the creation of a new thread. + + @warning: This method is meant to be used internally by the debugger. + + @type event: L{CreateThreadEvent} + @param event: Create thread event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + return event.get_process()._notify_create_thread(event) + + def _notify_load_dll(self, event): + """ + Notify the load of a new module. + + @warning: This method is meant to be used internally by the debugger. + + @type event: L{LoadDLLEvent} + @param event: Load DLL event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + + # Pass the event to the breakpoint container. + bCallHandler = _BreakpointContainer._notify_load_dll(self, event) + + # Get the process where the DLL was loaded. + aProcess = event.get_process() + + # Pass the event to the process. + bCallHandler = aProcess._notify_load_dll(event) and bCallHandler + + # Anti-anti-debugging tricks on ntdll.dll. + if self.__bHostileCode: + aModule = event.get_module() + if aModule.match_name('ntdll.dll'): + + # Since we've overwritten the PEB to hide + # ourselves, we no longer have the system + # breakpoint when attaching to the process. + # Set a breakpoint at ntdll!DbgUiRemoteBreakin + # instead (that's where the debug API spawns + # it's auxiliary threads). This also defeats + # a simple anti-debugging trick: the hostile + # process could have overwritten the int3 + # instruction at the system breakpoint. + self.break_at(aProcess.get_pid(), + aProcess.resolve_label('ntdll!DbgUiRemoteBreakin')) + + return bCallHandler + + def _notify_exit_process(self, event): + """ + Notify the termination of a process. + + @warning: This method is meant to be used internally by the debugger. + + @type event: L{ExitProcessEvent} + @param event: Exit process event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + bCallHandler1 = _BreakpointContainer._notify_exit_process(self, event) + bCallHandler2 = self.system._notify_exit_process(event) + + try: + self.detach( event.get_pid() ) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror != win32.ERROR_INVALID_PARAMETER: + warnings.warn( + "Failed to detach from dead process, reason: %s" % str(e), + RuntimeWarning) + except Exception: + e = sys.exc_info()[1] + warnings.warn( + "Failed to detach from dead process, reason: %s" % str(e), + RuntimeWarning) + + return bCallHandler1 and bCallHandler2 + + def _notify_exit_thread(self, event): + """ + Notify the termination of a thread. + + @warning: This method is meant to be used internally by the debugger. + + @type event: L{ExitThreadEvent} + @param event: Exit thread event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + bCallHandler1 = _BreakpointContainer._notify_exit_thread(self, event) + bCallHandler2 = event.get_process()._notify_exit_thread(event) + return bCallHandler1 and bCallHandler2 + + def _notify_unload_dll(self, event): + """ + Notify the unload of a module. + + @warning: This method is meant to be used internally by the debugger. + + @type event: L{UnloadDLLEvent} + @param event: Unload DLL event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + bCallHandler1 = _BreakpointContainer._notify_unload_dll(self, event) + bCallHandler2 = event.get_process()._notify_unload_dll(event) + return bCallHandler1 and bCallHandler2 + + def _notify_rip(self, event): + """ + Notify of a RIP event. + + @warning: This method is meant to be used internally by the debugger. + + @type event: L{RIPEvent} + @param event: RIP event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + event.debug.detach( event.get_pid() ) + return True + + def _notify_debug_control_c(self, event): + """ + Notify of a Debug Ctrl-C exception. + + @warning: This method is meant to be used internally by the debugger. + + @note: This exception is only raised when a debugger is attached, and + applications are not supposed to handle it, so we need to handle it + ourselves or the application may crash. + + @see: U{http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx} + + @type event: L{ExceptionEvent} + @param event: Debug Ctrl-C exception event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + if event.is_first_chance(): + event.continueStatus = win32.DBG_EXCEPTION_HANDLED + return True + + def _notify_ms_vc_exception(self, event): + """ + Notify of a Microsoft Visual C exception. + + @warning: This method is meant to be used internally by the debugger. + + @note: This allows the debugger to understand the + Microsoft Visual C thread naming convention. + + @see: U{http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx} + + @type event: L{ExceptionEvent} + @param event: Microsoft Visual C exception event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + dwType = event.get_exception_information(0) + if dwType == 0x1000: + pszName = event.get_exception_information(1) + dwThreadId = event.get_exception_information(2) + dwFlags = event.get_exception_information(3) + + aProcess = event.get_process() + szName = aProcess.peek_string(pszName, fUnicode = False) + if szName: + + if dwThreadId == -1: + dwThreadId = event.get_tid() + + if aProcess.has_thread(dwThreadId): + aThread = aProcess.get_thread(dwThreadId) + else: + aThread = Thread(dwThreadId) + aProcess._add_thread(aThread) + +## if aThread.get_name() is None: +## aThread.set_name(szName) + aThread.set_name(szName) + + return True diff --git a/pydevd_attach_to_process/winappdbg/disasm.py b/pydevd_attach_to_process/winappdbg/disasm.py new file mode 100644 index 0000000..230e331 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/disasm.py @@ -0,0 +1,722 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Binary code disassembly. + +@group Disassembler loader: + Disassembler, Engine + +@group Disassembler engines: + BeaEngine, CapstoneEngine, DistormEngine, + LibdisassembleEngine, PyDasmEngine +""" + +from __future__ import with_statement + +__revision__ = "$Id$" + +__all__ = [ + 'Disassembler', + 'Engine', + 'BeaEngine', + 'CapstoneEngine', + 'DistormEngine', + 'LibdisassembleEngine', + 'PyDasmEngine', +] + +from winappdbg.textio import HexDump +from winappdbg import win32 + +import ctypes +import warnings + +# lazy imports +BeaEnginePython = None +distorm3 = None +pydasm = None +libdisassemble = None +capstone = None + +#============================================================================== + +class Engine (object): + """ + Base class for disassembly engine adaptors. + + @type name: str + @cvar name: Engine name to use with the L{Disassembler} class. + + @type desc: str + @cvar desc: User friendly name of the disassembler engine. + + @type url: str + @cvar url: Download URL. + + @type supported: set(str) + @cvar supported: Set of supported processor architectures. + For more details see L{win32.version._get_arch}. + + @type arch: str + @ivar arch: Name of the processor architecture. + """ + + name = "" + desc = "" + url = "" + supported = set() + + def __init__(self, arch = None): + """ + @type arch: str + @param arch: Name of the processor architecture. + If not provided the current processor architecture is assumed. + For more details see L{win32.version._get_arch}. + + @raise NotImplementedError: This disassembler doesn't support the + requested processor architecture. + """ + self.arch = self._validate_arch(arch) + try: + self._import_dependencies() + except ImportError: + msg = "%s is not installed or can't be found. Download it from: %s" + msg = msg % (self.name, self.url) + raise NotImplementedError(msg) + + def _validate_arch(self, arch = None): + """ + @type arch: str + @param arch: Name of the processor architecture. + If not provided the current processor architecture is assumed. + For more details see L{win32.version._get_arch}. + + @rtype: str + @return: Name of the processor architecture. + If not provided the current processor architecture is assumed. + For more details see L{win32.version._get_arch}. + + @raise NotImplementedError: This disassembler doesn't support the + requested processor architecture. + """ + + # Use the default architecture if none specified. + if not arch: + arch = win32.arch + + # Validate the architecture. + if arch not in self.supported: + msg = "The %s engine cannot decode %s code." + msg = msg % (self.name, arch) + raise NotImplementedError(msg) + + # Return the architecture. + return arch + + def _import_dependencies(self): + """ + Loads the dependencies for this disassembler. + + @raise ImportError: This disassembler cannot find or load the + necessary dependencies to make it work. + """ + raise SyntaxError("Subclasses MUST implement this method!") + + def decode(self, address, code): + """ + @type address: int + @param address: Memory address where the code was read from. + + @type code: str + @param code: Machine code to disassemble. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + + @raise NotImplementedError: This disassembler could not be loaded. + This may be due to missing dependencies. + """ + raise NotImplementedError() + +#============================================================================== + +class BeaEngine (Engine): + """ + Integration with the BeaEngine disassembler by Beatrix. + + @see: U{https://sourceforge.net/projects/winappdbg/files/additional%20packages/BeaEngine/} + """ + + name = "BeaEngine" + desc = "BeaEngine disassembler by Beatrix" + url = "https://sourceforge.net/projects/winappdbg/files/additional%20packages/BeaEngine/" + + supported = set(( + win32.ARCH_I386, + win32.ARCH_AMD64, + )) + + def _import_dependencies(self): + + # Load the BeaEngine ctypes wrapper. + global BeaEnginePython + if BeaEnginePython is None: + import BeaEnginePython + + def decode(self, address, code): + addressof = ctypes.addressof + + # Instance the code buffer. + buffer = ctypes.create_string_buffer(code) + buffer_ptr = addressof(buffer) + + # Instance the disassembler structure. + Instruction = BeaEnginePython.DISASM() + Instruction.VirtualAddr = address + Instruction.EIP = buffer_ptr + Instruction.SecurityBlock = buffer_ptr + len(code) + if self.arch == win32.ARCH_I386: + Instruction.Archi = 0 + else: + Instruction.Archi = 0x40 + Instruction.Options = ( BeaEnginePython.Tabulation + + BeaEnginePython.NasmSyntax + + BeaEnginePython.SuffixedNumeral + + BeaEnginePython.ShowSegmentRegs ) + + # Prepare for looping over each instruction. + result = [] + Disasm = BeaEnginePython.Disasm + InstructionPtr = addressof(Instruction) + hexdump = HexDump.hexadecimal + append = result.append + OUT_OF_BLOCK = BeaEnginePython.OUT_OF_BLOCK + UNKNOWN_OPCODE = BeaEnginePython.UNKNOWN_OPCODE + + # For each decoded instruction... + while True: + + # Calculate the current offset into the buffer. + offset = Instruction.EIP - buffer_ptr + + # If we've gone past the buffer, break the loop. + if offset >= len(code): + break + + # Decode the current instruction. + InstrLength = Disasm(InstructionPtr) + + # If BeaEngine detects we've gone past the buffer, break the loop. + if InstrLength == OUT_OF_BLOCK: + break + + # The instruction could not be decoded. + if InstrLength == UNKNOWN_OPCODE: + + # Output a single byte as a "db" instruction. + char = "%.2X" % ord(buffer[offset]) + result.append(( + Instruction.VirtualAddr, + 1, + "db %sh" % char, + char, + )) + Instruction.VirtualAddr += 1 + Instruction.EIP += 1 + + # The instruction was decoded but reading past the buffer's end. + # This can happen when the last instruction is a prefix without an + # opcode. For example: decode(0, '\x66') + elif offset + InstrLength > len(code): + + # Output each byte as a "db" instruction. + for char in buffer[ offset : offset + len(code) ]: + char = "%.2X" % ord(char) + result.append(( + Instruction.VirtualAddr, + 1, + "db %sh" % char, + char, + )) + Instruction.VirtualAddr += 1 + Instruction.EIP += 1 + + # The instruction was decoded correctly. + else: + + # Output the decoded instruction. + append(( + Instruction.VirtualAddr, + InstrLength, + Instruction.CompleteInstr.strip(), + hexdump(buffer.raw[offset:offset+InstrLength]), + )) + Instruction.VirtualAddr += InstrLength + Instruction.EIP += InstrLength + + # Return the list of decoded instructions. + return result + +#============================================================================== + +class DistormEngine (Engine): + """ + Integration with the diStorm disassembler by Gil Dabah. + + @see: U{https://code.google.com/p/distorm3} + """ + + name = "diStorm" + desc = "diStorm disassembler by Gil Dabah" + url = "https://code.google.com/p/distorm3" + + supported = set(( + win32.ARCH_I386, + win32.ARCH_AMD64, + )) + + def _import_dependencies(self): + + # Load the distorm bindings. + global distorm3 + if distorm3 is None: + try: + import distorm3 + except ImportError: + import distorm as distorm3 + + # Load the decoder function. + self.__decode = distorm3.Decode + + # Load the bits flag. + self.__flag = { + win32.ARCH_I386: distorm3.Decode32Bits, + win32.ARCH_AMD64: distorm3.Decode64Bits, + }[self.arch] + + def decode(self, address, code): + return self.__decode(address, code, self.__flag) + +#============================================================================== + +class PyDasmEngine (Engine): + """ + Integration with PyDasm: Python bindings to libdasm. + + @see: U{https://code.google.com/p/libdasm/} + """ + + name = "PyDasm" + desc = "PyDasm: Python bindings to libdasm" + url = "https://code.google.com/p/libdasm/" + + supported = set(( + win32.ARCH_I386, + )) + + def _import_dependencies(self): + + # Load the libdasm bindings. + global pydasm + if pydasm is None: + import pydasm + + def decode(self, address, code): + + # Decode each instruction in the buffer. + result = [] + offset = 0 + while offset < len(code): + + # Try to decode the current instruction. + instruction = pydasm.get_instruction(code[offset:offset+32], + pydasm.MODE_32) + + # Get the memory address of the current instruction. + current = address + offset + + # Illegal opcode or opcode longer than remaining buffer. + if not instruction or instruction.length + offset > len(code): + hexdump = '%.2X' % ord(code[offset]) + disasm = 'db 0x%s' % hexdump + ilen = 1 + + # Correctly decoded instruction. + else: + disasm = pydasm.get_instruction_string(instruction, + pydasm.FORMAT_INTEL, + current) + ilen = instruction.length + hexdump = HexDump.hexadecimal(code[offset:offset+ilen]) + + # Add the decoded instruction to the list. + result.append(( + current, + ilen, + disasm, + hexdump, + )) + + # Move to the next instruction. + offset += ilen + + # Return the list of decoded instructions. + return result + +#============================================================================== + +class LibdisassembleEngine (Engine): + """ + Integration with Immunity libdisassemble. + + @see: U{http://www.immunitysec.com/resources-freesoftware.shtml} + """ + + name = "Libdisassemble" + desc = "Immunity libdisassemble" + url = "http://www.immunitysec.com/resources-freesoftware.shtml" + + supported = set(( + win32.ARCH_I386, + )) + + def _import_dependencies(self): + + # Load the libdisassemble module. + # Since it doesn't come with an installer or an __init__.py file + # users can only install it manually however they feel like it, + # so we'll have to do a bit of guessing to find it. + + global libdisassemble + if libdisassemble is None: + try: + + # If installed properly with __init__.py + import libdisassemble.disassemble as libdisassemble + + except ImportError: + + # If installed by just copying and pasting the files + import disassemble as libdisassemble + + def decode(self, address, code): + + # Decode each instruction in the buffer. + result = [] + offset = 0 + while offset < len(code): + + # Decode the current instruction. + opcode = libdisassemble.Opcode( code[offset:offset+32] ) + length = opcode.getSize() + disasm = opcode.printOpcode('INTEL') + hexdump = HexDump.hexadecimal( code[offset:offset+length] ) + + # Add the decoded instruction to the list. + result.append(( + address + offset, + length, + disasm, + hexdump, + )) + + # Move to the next instruction. + offset += length + + # Return the list of decoded instructions. + return result + +#============================================================================== + +class CapstoneEngine (Engine): + """ + Integration with the Capstone disassembler by Nguyen Anh Quynh. + + @see: U{http://www.capstone-engine.org/} + """ + + name = "Capstone" + desc = "Capstone disassembler by Nguyen Anh Quynh" + url = "http://www.capstone-engine.org/" + + supported = set(( + win32.ARCH_I386, + win32.ARCH_AMD64, + win32.ARCH_THUMB, + win32.ARCH_ARM, + win32.ARCH_ARM64, + )) + + def _import_dependencies(self): + + # Load the Capstone bindings. + global capstone + if capstone is None: + import capstone + + # Load the constants for the requested architecture. + self.__constants = { + win32.ARCH_I386: + (capstone.CS_ARCH_X86, capstone.CS_MODE_32), + win32.ARCH_AMD64: + (capstone.CS_ARCH_X86, capstone.CS_MODE_64), + win32.ARCH_THUMB: + (capstone.CS_ARCH_ARM, capstone.CS_MODE_THUMB), + win32.ARCH_ARM: + (capstone.CS_ARCH_ARM, capstone.CS_MODE_ARM), + win32.ARCH_ARM64: + (capstone.CS_ARCH_ARM64, capstone.CS_MODE_ARM), + } + + # Test for the bug in early versions of Capstone. + # If found, warn the user about it. + try: + self.__bug = not isinstance( + capstone.cs_disasm_quick( + capstone.CS_ARCH_X86, capstone.CS_MODE_32, "\x90", 1)[0], + capstone.capstone.CsInsn) + except AttributeError: + self.__bug = False + if self.__bug: + warnings.warn( + "This version of the Capstone bindings is unstable," + " please upgrade to a newer one!", + RuntimeWarning, stacklevel=4) + + + def decode(self, address, code): + + # Get the constants for the requested architecture. + arch, mode = self.__constants[self.arch] + + # Get the decoder function outside the loop. + decoder = capstone.cs_disasm_quick + + # If the buggy version of the bindings are being used, we need to catch + # all exceptions broadly. If not, we only need to catch CsError. + if self.__bug: + CsError = Exception + else: + CsError = capstone.CsError + + # Create the variables for the instruction length, mnemonic and + # operands. That way they won't be created within the loop, + # minimizing the chances data might be overwritten. + # This only makes sense for the buggy vesion of the bindings, normally + # memory accesses are safe). + length = mnemonic = op_str = None + + # For each instruction... + result = [] + offset = 0 + while offset < len(code): + + # Disassemble a single instruction, because disassembling multiple + # instructions may cause excessive memory usage (Capstone allocates + # approximately 1K of metadata per each decoded instruction). + instr = None + try: + instr = decoder( + arch, mode, code[offset:offset+16], address+offset, 1)[0] + except IndexError: + pass # No instructions decoded. + except CsError: + pass # Any other error. + + # On success add the decoded instruction. + if instr is not None: + + # Get the instruction length, mnemonic and operands. + # Copy the values quickly before someone overwrites them, + # if using the buggy version of the bindings (otherwise it's + # irrelevant in which order we access the properties). + length = instr.size + mnemonic = instr.mnemonic + op_str = instr.op_str + + # Concatenate the mnemonic and the operands. + if op_str: + disasm = "%s %s" % (mnemonic, op_str) + else: + disasm = mnemonic + + # Get the instruction bytes as a hexadecimal dump. + hexdump = HexDump.hexadecimal( code[offset:offset+length] ) + + # On error add a "define constant" instruction. + # The exact instruction depends on the architecture. + else: + + # The number of bytes to skip depends on the architecture. + # On Intel processors we'll skip one byte, since we can't + # really know the instruction length. On the rest of the + # architectures we always know the instruction length. + if self.arch in (win32.ARCH_I386, win32.ARCH_AMD64): + length = 1 + else: + length = 4 + + # Get the skipped bytes as a hexadecimal dump. + skipped = code[offset:offset+length] + hexdump = HexDump.hexadecimal(skipped) + + # Build the "define constant" instruction. + # On Intel processors it's "db". + # On ARM processors it's "dcb". + if self.arch in (win32.ARCH_I386, win32.ARCH_AMD64): + mnemonic = "db " + else: + mnemonic = "dcb " + bytes = [] + for b in skipped: + if b.isalpha(): + bytes.append("'%s'" % b) + else: + bytes.append("0x%x" % ord(b)) + op_str = ", ".join(bytes) + disasm = mnemonic + op_str + + # Add the decoded instruction to the list. + result.append(( + address + offset, + length, + disasm, + hexdump, + )) + + # Update the offset. + offset += length + + # Return the list of decoded instructions. + return result + +#============================================================================== + +# TODO: use a lock to access __decoder +# TODO: look in sys.modules for whichever disassembler is already loaded + +class Disassembler (object): + """ + Generic disassembler. Uses a set of adapters to decide which library to + load for which supported platform. + + @type engines: tuple( L{Engine} ) + @cvar engines: Set of supported engines. If you implement your own adapter + you can add its class here to make it available to L{Disassembler}. + Supported disassemblers are: + """ + + engines = ( + DistormEngine, # diStorm engine goes first for backwards compatibility + BeaEngine, + CapstoneEngine, + LibdisassembleEngine, + PyDasmEngine, + ) + + # Add the list of supported disassemblers to the docstring. + __doc__ += "\n" + for e in engines: + __doc__ += " - %s - %s (U{%s})\n" % (e.name, e.desc, e.url) + del e + + # Cache of already loaded disassemblers. + __decoder = {} + + def __new__(cls, arch = None, engine = None): + """ + Factory class. You can't really instance a L{Disassembler} object, + instead one of the adapter L{Engine} subclasses is returned. + + @type arch: str + @param arch: (Optional) Name of the processor architecture. + If not provided the current processor architecture is assumed. + For more details see L{win32.version._get_arch}. + + @type engine: str + @param engine: (Optional) Name of the disassembler engine. + If not provided a compatible one is loaded automatically. + See: L{Engine.name} + + @raise NotImplementedError: No compatible disassembler was found that + could decode machine code for the requested architecture. This may + be due to missing dependencies. + + @raise ValueError: An unknown engine name was supplied. + """ + + # Use the default architecture if none specified. + if not arch: + arch = win32.arch + + # Return a compatible engine if none specified. + if not engine: + found = False + for clazz in cls.engines: + try: + if arch in clazz.supported: + selected = (clazz.name, arch) + try: + decoder = cls.__decoder[selected] + except KeyError: + decoder = clazz(arch) + cls.__decoder[selected] = decoder + return decoder + except NotImplementedError: + pass + msg = "No disassembler engine available for %s code." % arch + raise NotImplementedError(msg) + + # Return the specified engine. + selected = (engine, arch) + try: + decoder = cls.__decoder[selected] + except KeyError: + found = False + engineLower = engine.lower() + for clazz in cls.engines: + if clazz.name.lower() == engineLower: + found = True + break + if not found: + msg = "Unsupported disassembler engine: %s" % engine + raise ValueError(msg) + if arch not in clazz.supported: + msg = "The %s engine cannot decode %s code." % selected + raise NotImplementedError(msg) + decoder = clazz(arch) + cls.__decoder[selected] = decoder + return decoder diff --git a/pydevd_attach_to_process/winappdbg/event.py b/pydevd_attach_to_process/winappdbg/event.py new file mode 100644 index 0000000..af64727 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/event.py @@ -0,0 +1,1869 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Event handling module. + +@see: U{http://apps.sourceforge.net/trac/winappdbg/wiki/Debugging} + +@group Debugging: + EventHandler, EventSift + +@group Debug events: + EventFactory, + EventDispatcher, + Event, + NoEvent, + CreateProcessEvent, + CreateThreadEvent, + ExitProcessEvent, + ExitThreadEvent, + LoadDLLEvent, + UnloadDLLEvent, + OutputDebugStringEvent, + RIPEvent, + ExceptionEvent + +@group Warnings: + EventCallbackWarning +""" + +__revision__ = "$Id$" + +__all__ = [ + # Factory of Event objects and all of it's subclasses. + # Users should not need to instance Event objects directly. + 'EventFactory', + + # Event dispatcher used internally by the Debug class. + 'EventDispatcher', + + # Base classes for user-defined event handlers. + 'EventHandler', + 'EventSift', + + # Warning for uncaught exceptions on event callbacks. + 'EventCallbackWarning', + + # Dummy event object that can be used as a placeholder. + # It's never returned by the EventFactory. + 'NoEvent', + + # Base class for event objects. + 'Event', + + # Event objects. + 'CreateProcessEvent', + 'CreateThreadEvent', + 'ExitProcessEvent', + 'ExitThreadEvent', + 'LoadDLLEvent', + 'UnloadDLLEvent', + 'OutputDebugStringEvent', + 'RIPEvent', + 'ExceptionEvent' + ] + +from winappdbg import win32 +from winappdbg import compat +from winappdbg.win32 import FileHandle, ProcessHandle, ThreadHandle +from winappdbg.breakpoint import ApiHook +from winappdbg.module import Module +from winappdbg.thread import Thread +from winappdbg.process import Process +from winappdbg.textio import HexDump +from winappdbg.util import StaticClass, PathOperations + +import sys +import ctypes +import warnings +import traceback + +#============================================================================== + +class EventCallbackWarning (RuntimeWarning): + """ + This warning is issued when an uncaught exception was raised by a + user-defined event handler. + """ + +#============================================================================== + +class Event (object): + """ + Event object. + + @type eventMethod: str + @cvar eventMethod: + Method name to call when using L{EventHandler} subclasses. + Used internally. + + @type eventName: str + @cvar eventName: + User-friendly name of the event. + + @type eventDescription: str + @cvar eventDescription: + User-friendly description of the event. + + @type debug: L{Debug} + @ivar debug: + Debug object that received the event. + + @type raw: L{DEBUG_EVENT} + @ivar raw: + Raw DEBUG_EVENT structure as used by the Win32 API. + + @type continueStatus: int + @ivar continueStatus: + Continue status to pass to L{win32.ContinueDebugEvent}. + """ + + eventMethod = 'unknown_event' + eventName = 'Unknown event' + eventDescription = 'A debug event of an unknown type has occured.' + + def __init__(self, debug, raw): + """ + @type debug: L{Debug} + @param debug: Debug object that received the event. + + @type raw: L{DEBUG_EVENT} + @param raw: Raw DEBUG_EVENT structure as used by the Win32 API. + """ + self.debug = debug + self.raw = raw + self.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED + +## @property +## def debug(self): +## """ +## @rtype debug: L{Debug} +## @return debug: +## Debug object that received the event. +## """ +## return self.__debug() + + def get_event_name(self): + """ + @rtype: str + @return: User-friendly name of the event. + """ + return self.eventName + + def get_event_description(self): + """ + @rtype: str + @return: User-friendly description of the event. + """ + return self.eventDescription + + def get_event_code(self): + """ + @rtype: int + @return: Debug event code as defined in the Win32 API. + """ + return self.raw.dwDebugEventCode + +## # Compatibility with version 1.0 +## # XXX to be removed in version 1.4 +## def get_code(self): +## """ +## Alias of L{get_event_code} for backwards compatibility +## with WinAppDbg version 1.0. +## Will be phased out in the next version. +## +## @rtype: int +## @return: Debug event code as defined in the Win32 API. +## """ +## return self.get_event_code() + + def get_pid(self): + """ + @see: L{get_process} + + @rtype: int + @return: Process global ID where the event occured. + """ + return self.raw.dwProcessId + + def get_tid(self): + """ + @see: L{get_thread} + + @rtype: int + @return: Thread global ID where the event occured. + """ + return self.raw.dwThreadId + + def get_process(self): + """ + @see: L{get_pid} + + @rtype: L{Process} + @return: Process where the event occured. + """ + pid = self.get_pid() + system = self.debug.system + if system.has_process(pid): + process = system.get_process(pid) + else: + # XXX HACK + # The process object was missing for some reason, so make a new one. + process = Process(pid) + system._add_process(process) +## process.scan_threads() # not needed + process.scan_modules() + return process + + def get_thread(self): + """ + @see: L{get_tid} + + @rtype: L{Thread} + @return: Thread where the event occured. + """ + tid = self.get_tid() + process = self.get_process() + if process.has_thread(tid): + thread = process.get_thread(tid) + else: + # XXX HACK + # The thread object was missing for some reason, so make a new one. + thread = Thread(tid) + process._add_thread(thread) + return thread + +#============================================================================== + +class NoEvent (Event): + """ + No event. + + Dummy L{Event} object that can be used as a placeholder when no debug + event has occured yet. It's never returned by the L{EventFactory}. + """ + + eventMethod = 'no_event' + eventName = 'No event' + eventDescription = 'No debug event has occured.' + + def __init__(self, debug, raw = None): + Event.__init__(self, debug, raw) + + def __len__(self): + """ + Always returns C{0}, so when evaluating the object as a boolean it's + always C{False}. This prevents L{Debug.cont} from trying to continue + a dummy event. + """ + return 0 + + def get_event_code(self): + return -1 + + def get_pid(self): + return -1 + + def get_tid(self): + return -1 + + def get_process(self): + return Process(self.get_pid()) + + def get_thread(self): + return Thread(self.get_tid()) + +#============================================================================== + +class ExceptionEvent (Event): + """ + Exception event. + + @type exceptionName: dict( int S{->} str ) + @cvar exceptionName: + Mapping of exception constants to their names. + + @type exceptionDescription: dict( int S{->} str ) + @cvar exceptionDescription: + Mapping of exception constants to user-friendly strings. + + @type breakpoint: L{Breakpoint} + @ivar breakpoint: + If the exception was caused by one of our breakpoints, this member + contains a reference to the breakpoint object. Otherwise it's not + defined. It should only be used from the condition or action callback + routines, instead of the event handler. + + @type hook: L{Hook} + @ivar hook: + If the exception was caused by a function hook, this member contains a + reference to the hook object. Otherwise it's not defined. It should + only be used from the hook callback routines, instead of the event + handler. + """ + + eventName = 'Exception event' + eventDescription = 'An exception was raised by the debugee.' + + __exceptionMethod = { + win32.EXCEPTION_ACCESS_VIOLATION : 'access_violation', + win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'array_bounds_exceeded', + win32.EXCEPTION_BREAKPOINT : 'breakpoint', + win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'datatype_misalignment', + win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'float_denormal_operand', + win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'float_divide_by_zero', + win32.EXCEPTION_FLT_INEXACT_RESULT : 'float_inexact_result', + win32.EXCEPTION_FLT_INVALID_OPERATION : 'float_invalid_operation', + win32.EXCEPTION_FLT_OVERFLOW : 'float_overflow', + win32.EXCEPTION_FLT_STACK_CHECK : 'float_stack_check', + win32.EXCEPTION_FLT_UNDERFLOW : 'float_underflow', + win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'illegal_instruction', + win32.EXCEPTION_IN_PAGE_ERROR : 'in_page_error', + win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'integer_divide_by_zero', + win32.EXCEPTION_INT_OVERFLOW : 'integer_overflow', + win32.EXCEPTION_INVALID_DISPOSITION : 'invalid_disposition', + win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'noncontinuable_exception', + win32.EXCEPTION_PRIV_INSTRUCTION : 'privileged_instruction', + win32.EXCEPTION_SINGLE_STEP : 'single_step', + win32.EXCEPTION_STACK_OVERFLOW : 'stack_overflow', + win32.EXCEPTION_GUARD_PAGE : 'guard_page', + win32.EXCEPTION_INVALID_HANDLE : 'invalid_handle', + win32.EXCEPTION_POSSIBLE_DEADLOCK : 'possible_deadlock', + win32.EXCEPTION_WX86_BREAKPOINT : 'wow64_breakpoint', + win32.CONTROL_C_EXIT : 'control_c_exit', + win32.DBG_CONTROL_C : 'debug_control_c', + win32.MS_VC_EXCEPTION : 'ms_vc_exception', + } + + __exceptionName = { + win32.EXCEPTION_ACCESS_VIOLATION : 'EXCEPTION_ACCESS_VIOLATION', + win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'EXCEPTION_ARRAY_BOUNDS_EXCEEDED', + win32.EXCEPTION_BREAKPOINT : 'EXCEPTION_BREAKPOINT', + win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'EXCEPTION_DATATYPE_MISALIGNMENT', + win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'EXCEPTION_FLT_DENORMAL_OPERAND', + win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'EXCEPTION_FLT_DIVIDE_BY_ZERO', + win32.EXCEPTION_FLT_INEXACT_RESULT : 'EXCEPTION_FLT_INEXACT_RESULT', + win32.EXCEPTION_FLT_INVALID_OPERATION : 'EXCEPTION_FLT_INVALID_OPERATION', + win32.EXCEPTION_FLT_OVERFLOW : 'EXCEPTION_FLT_OVERFLOW', + win32.EXCEPTION_FLT_STACK_CHECK : 'EXCEPTION_FLT_STACK_CHECK', + win32.EXCEPTION_FLT_UNDERFLOW : 'EXCEPTION_FLT_UNDERFLOW', + win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'EXCEPTION_ILLEGAL_INSTRUCTION', + win32.EXCEPTION_IN_PAGE_ERROR : 'EXCEPTION_IN_PAGE_ERROR', + win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'EXCEPTION_INT_DIVIDE_BY_ZERO', + win32.EXCEPTION_INT_OVERFLOW : 'EXCEPTION_INT_OVERFLOW', + win32.EXCEPTION_INVALID_DISPOSITION : 'EXCEPTION_INVALID_DISPOSITION', + win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'EXCEPTION_NONCONTINUABLE_EXCEPTION', + win32.EXCEPTION_PRIV_INSTRUCTION : 'EXCEPTION_PRIV_INSTRUCTION', + win32.EXCEPTION_SINGLE_STEP : 'EXCEPTION_SINGLE_STEP', + win32.EXCEPTION_STACK_OVERFLOW : 'EXCEPTION_STACK_OVERFLOW', + win32.EXCEPTION_GUARD_PAGE : 'EXCEPTION_GUARD_PAGE', + win32.EXCEPTION_INVALID_HANDLE : 'EXCEPTION_INVALID_HANDLE', + win32.EXCEPTION_POSSIBLE_DEADLOCK : 'EXCEPTION_POSSIBLE_DEADLOCK', + win32.EXCEPTION_WX86_BREAKPOINT : 'EXCEPTION_WX86_BREAKPOINT', + win32.CONTROL_C_EXIT : 'CONTROL_C_EXIT', + win32.DBG_CONTROL_C : 'DBG_CONTROL_C', + win32.MS_VC_EXCEPTION : 'MS_VC_EXCEPTION', + } + + __exceptionDescription = { + win32.EXCEPTION_ACCESS_VIOLATION : 'Access violation', + win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'Array bounds exceeded', + win32.EXCEPTION_BREAKPOINT : 'Breakpoint', + win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'Datatype misalignment', + win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'Float denormal operand', + win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'Float divide by zero', + win32.EXCEPTION_FLT_INEXACT_RESULT : 'Float inexact result', + win32.EXCEPTION_FLT_INVALID_OPERATION : 'Float invalid operation', + win32.EXCEPTION_FLT_OVERFLOW : 'Float overflow', + win32.EXCEPTION_FLT_STACK_CHECK : 'Float stack check', + win32.EXCEPTION_FLT_UNDERFLOW : 'Float underflow', + win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'Illegal instruction', + win32.EXCEPTION_IN_PAGE_ERROR : 'In-page error', + win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'Integer divide by zero', + win32.EXCEPTION_INT_OVERFLOW : 'Integer overflow', + win32.EXCEPTION_INVALID_DISPOSITION : 'Invalid disposition', + win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'Noncontinuable exception', + win32.EXCEPTION_PRIV_INSTRUCTION : 'Privileged instruction', + win32.EXCEPTION_SINGLE_STEP : 'Single step event', + win32.EXCEPTION_STACK_OVERFLOW : 'Stack limits overflow', + win32.EXCEPTION_GUARD_PAGE : 'Guard page hit', + win32.EXCEPTION_INVALID_HANDLE : 'Invalid handle', + win32.EXCEPTION_POSSIBLE_DEADLOCK : 'Possible deadlock', + win32.EXCEPTION_WX86_BREAKPOINT : 'WOW64 breakpoint', + win32.CONTROL_C_EXIT : 'Control-C exit', + win32.DBG_CONTROL_C : 'Debug Control-C', + win32.MS_VC_EXCEPTION : 'Microsoft Visual C++ exception', + } + + @property + def eventMethod(self): + return self.__exceptionMethod.get( + self.get_exception_code(), 'unknown_exception') + + def get_exception_name(self): + """ + @rtype: str + @return: Name of the exception as defined by the Win32 API. + """ + code = self.get_exception_code() + unk = HexDump.integer(code) + return self.__exceptionName.get(code, unk) + + def get_exception_description(self): + """ + @rtype: str + @return: User-friendly name of the exception. + """ + code = self.get_exception_code() + description = self.__exceptionDescription.get(code, None) + if description is None: + try: + description = 'Exception code %s (%s)' + description = description % (HexDump.integer(code), + ctypes.FormatError(code)) + except OverflowError: + description = 'Exception code %s' % HexDump.integer(code) + return description + + def is_first_chance(self): + """ + @rtype: bool + @return: C{True} for first chance exceptions, C{False} for last chance. + """ + return self.raw.u.Exception.dwFirstChance != 0 + + def is_last_chance(self): + """ + @rtype: bool + @return: The opposite of L{is_first_chance}. + """ + return not self.is_first_chance() + + def is_noncontinuable(self): + """ + @see: U{http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx} + + @rtype: bool + @return: C{True} if the exception is noncontinuable, + C{False} otherwise. + + Attempting to continue a noncontinuable exception results in an + EXCEPTION_NONCONTINUABLE_EXCEPTION exception to be raised. + """ + return bool( self.raw.u.Exception.ExceptionRecord.ExceptionFlags & \ + win32.EXCEPTION_NONCONTINUABLE ) + + def is_continuable(self): + """ + @rtype: bool + @return: The opposite of L{is_noncontinuable}. + """ + return not self.is_noncontinuable() + + def is_user_defined_exception(self): + """ + Determines if this is an user-defined exception. User-defined + exceptions may contain any exception code that is not system reserved. + + Often the exception code is also a valid Win32 error code, but that's + up to the debugged application. + + @rtype: bool + @return: C{True} if the exception is user-defined, C{False} otherwise. + """ + return self.get_exception_code() & 0x10000000 == 0 + + def is_system_defined_exception(self): + """ + @rtype: bool + @return: The opposite of L{is_user_defined_exception}. + """ + return not self.is_user_defined_exception() + + def get_exception_code(self): + """ + @rtype: int + @return: Exception code as defined by the Win32 API. + """ + return self.raw.u.Exception.ExceptionRecord.ExceptionCode + + def get_exception_address(self): + """ + @rtype: int + @return: Memory address where the exception occured. + """ + address = self.raw.u.Exception.ExceptionRecord.ExceptionAddress + if address is None: + address = 0 + return address + + def get_exception_information(self, index): + """ + @type index: int + @param index: Index into the exception information block. + + @rtype: int + @return: Exception information DWORD. + """ + if index < 0 or index > win32.EXCEPTION_MAXIMUM_PARAMETERS: + raise IndexError("Array index out of range: %s" % repr(index)) + info = self.raw.u.Exception.ExceptionRecord.ExceptionInformation + value = info[index] + if value is None: + value = 0 + return value + + def get_exception_information_as_list(self): + """ + @rtype: list( int ) + @return: Exception information block. + """ + info = self.raw.u.Exception.ExceptionRecord.ExceptionInformation + data = list() + for index in compat.xrange(0, win32.EXCEPTION_MAXIMUM_PARAMETERS): + value = info[index] + if value is None: + value = 0 + data.append(value) + return data + + def get_fault_type(self): + """ + @rtype: int + @return: Access violation type. + Should be one of the following constants: + + - L{win32.EXCEPTION_READ_FAULT} + - L{win32.EXCEPTION_WRITE_FAULT} + - L{win32.EXCEPTION_EXECUTE_FAULT} + + @note: This method is only meaningful for access violation exceptions, + in-page memory error exceptions and guard page exceptions. + + @raise NotImplementedError: Wrong kind of exception. + """ + if self.get_exception_code() not in (win32.EXCEPTION_ACCESS_VIOLATION, + win32.EXCEPTION_IN_PAGE_ERROR, win32.EXCEPTION_GUARD_PAGE): + msg = "This method is not meaningful for %s." + raise NotImplementedError(msg % self.get_exception_name()) + return self.get_exception_information(0) + + def get_fault_address(self): + """ + @rtype: int + @return: Access violation memory address. + + @note: This method is only meaningful for access violation exceptions, + in-page memory error exceptions and guard page exceptions. + + @raise NotImplementedError: Wrong kind of exception. + """ + if self.get_exception_code() not in (win32.EXCEPTION_ACCESS_VIOLATION, + win32.EXCEPTION_IN_PAGE_ERROR, win32.EXCEPTION_GUARD_PAGE): + msg = "This method is not meaningful for %s." + raise NotImplementedError(msg % self.get_exception_name()) + return self.get_exception_information(1) + + def get_ntstatus_code(self): + """ + @rtype: int + @return: NTSTATUS status code that caused the exception. + + @note: This method is only meaningful for in-page memory error + exceptions. + + @raise NotImplementedError: Not an in-page memory error. + """ + if self.get_exception_code() != win32.EXCEPTION_IN_PAGE_ERROR: + msg = "This method is only meaningful "\ + "for in-page memory error exceptions." + raise NotImplementedError(msg) + return self.get_exception_information(2) + + def is_nested(self): + """ + @rtype: bool + @return: Returns C{True} if there are additional exception records + associated with this exception. This would mean the exception + is nested, that is, it was triggered while trying to handle + at least one previous exception. + """ + return bool(self.raw.u.Exception.ExceptionRecord.ExceptionRecord) + + def get_raw_exception_record_list(self): + """ + Traverses the exception record linked list and builds a Python list. + + Nested exception records are received for nested exceptions. This + happens when an exception is raised in the debugee while trying to + handle a previous exception. + + @rtype: list( L{win32.EXCEPTION_RECORD} ) + @return: + List of raw exception record structures as used by the Win32 API. + + There is always at least one exception record, so the list is + never empty. All other methods of this class read from the first + exception record only, that is, the most recent exception. + """ + # The first EXCEPTION_RECORD is contained in EXCEPTION_DEBUG_INFO. + # The remaining EXCEPTION_RECORD structures are linked by pointers. + nested = list() + record = self.raw.u.Exception + while True: + record = record.ExceptionRecord + if not record: + break + nested.append(record) + return nested + + def get_nested_exceptions(self): + """ + Traverses the exception record linked list and builds a Python list. + + Nested exception records are received for nested exceptions. This + happens when an exception is raised in the debugee while trying to + handle a previous exception. + + @rtype: list( L{ExceptionEvent} ) + @return: + List of ExceptionEvent objects representing each exception record + found in this event. + + There is always at least one exception record, so the list is + never empty. All other methods of this class read from the first + exception record only, that is, the most recent exception. + """ + # The list always begins with ourselves. + # Just put a reference to "self" as the first element, + # and start looping from the second exception record. + nested = [ self ] + raw = self.raw + dwDebugEventCode = raw.dwDebugEventCode + dwProcessId = raw.dwProcessId + dwThreadId = raw.dwThreadId + dwFirstChance = raw.u.Exception.dwFirstChance + record = raw.u.Exception.ExceptionRecord + while True: + record = record.ExceptionRecord + if not record: + break + raw = win32.DEBUG_EVENT() + raw.dwDebugEventCode = dwDebugEventCode + raw.dwProcessId = dwProcessId + raw.dwThreadId = dwThreadId + raw.u.Exception.ExceptionRecord = record + raw.u.Exception.dwFirstChance = dwFirstChance + event = EventFactory.get(self.debug, raw) + nested.append(event) + return nested + +#============================================================================== + +class CreateThreadEvent (Event): + """ + Thread creation event. + """ + + eventMethod = 'create_thread' + eventName = 'Thread creation event' + eventDescription = 'A new thread has started.' + + def get_thread_handle(self): + """ + @rtype: L{ThreadHandle} + @return: Thread handle received from the system. + Returns C{None} if the handle is not available. + """ + # The handle doesn't need to be closed. + # See http://msdn.microsoft.com/en-us/library/ms681423(VS.85).aspx + hThread = self.raw.u.CreateThread.hThread + if hThread in (0, win32.NULL, win32.INVALID_HANDLE_VALUE): + hThread = None + else: + hThread = ThreadHandle(hThread, False, win32.THREAD_ALL_ACCESS) + return hThread + + def get_teb(self): + """ + @rtype: int + @return: Pointer to the TEB. + """ + return self.raw.u.CreateThread.lpThreadLocalBase + + def get_start_address(self): + """ + @rtype: int + @return: Pointer to the first instruction to execute in this thread. + + Returns C{NULL} when the debugger attached to a process + and the thread already existed. + + See U{http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx} + """ + return self.raw.u.CreateThread.lpStartAddress + +#============================================================================== + +class CreateProcessEvent (Event): + """ + Process creation event. + """ + + eventMethod = 'create_process' + eventName = 'Process creation event' + eventDescription = 'A new process has started.' + + def get_file_handle(self): + """ + @rtype: L{FileHandle} or None + @return: File handle to the main module, received from the system. + Returns C{None} if the handle is not available. + """ + # This handle DOES need to be closed. + # Therefore we must cache it so it doesn't + # get closed after the first call. + try: + hFile = self.__hFile + except AttributeError: + hFile = self.raw.u.CreateProcessInfo.hFile + if hFile in (0, win32.NULL, win32.INVALID_HANDLE_VALUE): + hFile = None + else: + hFile = FileHandle(hFile, True) + self.__hFile = hFile + return hFile + + def get_process_handle(self): + """ + @rtype: L{ProcessHandle} + @return: Process handle received from the system. + Returns C{None} if the handle is not available. + """ + # The handle doesn't need to be closed. + # See http://msdn.microsoft.com/en-us/library/ms681423(VS.85).aspx + hProcess = self.raw.u.CreateProcessInfo.hProcess + if hProcess in (0, win32.NULL, win32.INVALID_HANDLE_VALUE): + hProcess = None + else: + hProcess = ProcessHandle(hProcess, False, win32.PROCESS_ALL_ACCESS) + return hProcess + + def get_thread_handle(self): + """ + @rtype: L{ThreadHandle} + @return: Thread handle received from the system. + Returns C{None} if the handle is not available. + """ + # The handle doesn't need to be closed. + # See http://msdn.microsoft.com/en-us/library/ms681423(VS.85).aspx + hThread = self.raw.u.CreateProcessInfo.hThread + if hThread in (0, win32.NULL, win32.INVALID_HANDLE_VALUE): + hThread = None + else: + hThread = ThreadHandle(hThread, False, win32.THREAD_ALL_ACCESS) + return hThread + + def get_start_address(self): + """ + @rtype: int + @return: Pointer to the first instruction to execute in this process. + + Returns C{NULL} when the debugger attaches to a process. + + See U{http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx} + """ + return self.raw.u.CreateProcessInfo.lpStartAddress + + def get_image_base(self): + """ + @rtype: int + @return: Base address of the main module. + @warn: This value is taken from the PE file + and may be incorrect because of ASLR! + """ + # TODO try to calculate the real value when ASLR is active. + return self.raw.u.CreateProcessInfo.lpBaseOfImage + + def get_teb(self): + """ + @rtype: int + @return: Pointer to the TEB. + """ + return self.raw.u.CreateProcessInfo.lpThreadLocalBase + + def get_debug_info(self): + """ + @rtype: str + @return: Debugging information. + """ + raw = self.raw.u.CreateProcessInfo + ptr = raw.lpBaseOfImage + raw.dwDebugInfoFileOffset + size = raw.nDebugInfoSize + data = self.get_process().peek(ptr, size) + if len(data) == size: + return data + return None + + def get_filename(self): + """ + @rtype: str, None + @return: This method does it's best to retrieve the filename to + the main module of the process. However, sometimes that's not + possible, and C{None} is returned instead. + """ + + # Try to get the filename from the file handle. + szFilename = None + hFile = self.get_file_handle() + if hFile: + szFilename = hFile.get_filename() + if not szFilename: + + # Try to get it from CREATE_PROCESS_DEBUG_INFO.lpImageName + # It's NULL or *NULL most of the times, see MSDN: + # http://msdn.microsoft.com/en-us/library/ms679286(VS.85).aspx + aProcess = self.get_process() + lpRemoteFilenamePtr = self.raw.u.CreateProcessInfo.lpImageName + if lpRemoteFilenamePtr: + lpFilename = aProcess.peek_uint(lpRemoteFilenamePtr) + fUnicode = bool( self.raw.u.CreateProcessInfo.fUnicode ) + szFilename = aProcess.peek_string(lpFilename, fUnicode) + + # XXX TODO + # Sometimes the filename is relative (ntdll.dll, kernel32.dll). + # It could be converted to an absolute pathname (SearchPath). + + # Try to get it from Process.get_image_name(). + if not szFilename: + szFilename = aProcess.get_image_name() + + # Return the filename, or None on error. + return szFilename + + def get_module_base(self): + """ + @rtype: int + @return: Base address of the main module. + """ + return self.get_image_base() + + def get_module(self): + """ + @rtype: L{Module} + @return: Main module of the process. + """ + return self.get_process().get_module( self.get_module_base() ) + +#============================================================================== + +class ExitThreadEvent (Event): + """ + Thread termination event. + """ + + eventMethod = 'exit_thread' + eventName = 'Thread termination event' + eventDescription = 'A thread has finished executing.' + + def get_exit_code(self): + """ + @rtype: int + @return: Exit code of the thread. + """ + return self.raw.u.ExitThread.dwExitCode + +#============================================================================== + +class ExitProcessEvent (Event): + """ + Process termination event. + """ + + eventMethod = 'exit_process' + eventName = 'Process termination event' + eventDescription = 'A process has finished executing.' + + def get_exit_code(self): + """ + @rtype: int + @return: Exit code of the process. + """ + return self.raw.u.ExitProcess.dwExitCode + + def get_filename(self): + """ + @rtype: None or str + @return: Filename of the main module. + C{None} if the filename is unknown. + """ + return self.get_module().get_filename() + + def get_image_base(self): + """ + @rtype: int + @return: Base address of the main module. + """ + return self.get_module_base() + + def get_module_base(self): + """ + @rtype: int + @return: Base address of the main module. + """ + return self.get_module().get_base() + + def get_module(self): + """ + @rtype: L{Module} + @return: Main module of the process. + """ + return self.get_process().get_main_module() + +#============================================================================== + +class LoadDLLEvent (Event): + """ + Module load event. + """ + + eventMethod = 'load_dll' + eventName = 'Module load event' + eventDescription = 'A new DLL library was loaded by the debugee.' + + def get_module_base(self): + """ + @rtype: int + @return: Base address for the newly loaded DLL. + """ + return self.raw.u.LoadDll.lpBaseOfDll + + def get_module(self): + """ + @rtype: L{Module} + @return: Module object for the newly loaded DLL. + """ + lpBaseOfDll = self.get_module_base() + aProcess = self.get_process() + if aProcess.has_module(lpBaseOfDll): + aModule = aProcess.get_module(lpBaseOfDll) + else: + # XXX HACK + # For some reason the module object is missing, so make a new one. + aModule = Module(lpBaseOfDll, + hFile = self.get_file_handle(), + fileName = self.get_filename(), + process = aProcess) + aProcess._add_module(aModule) + return aModule + + def get_file_handle(self): + """ + @rtype: L{FileHandle} or None + @return: File handle to the newly loaded DLL received from the system. + Returns C{None} if the handle is not available. + """ + # This handle DOES need to be closed. + # Therefore we must cache it so it doesn't + # get closed after the first call. + try: + hFile = self.__hFile + except AttributeError: + hFile = self.raw.u.LoadDll.hFile + if hFile in (0, win32.NULL, win32.INVALID_HANDLE_VALUE): + hFile = None + else: + hFile = FileHandle(hFile, True) + self.__hFile = hFile + return hFile + + def get_filename(self): + """ + @rtype: str, None + @return: This method does it's best to retrieve the filename to + the newly loaded module. However, sometimes that's not + possible, and C{None} is returned instead. + """ + szFilename = None + + # Try to get it from LOAD_DLL_DEBUG_INFO.lpImageName + # It's NULL or *NULL most of the times, see MSDN: + # http://msdn.microsoft.com/en-us/library/ms679286(VS.85).aspx + aProcess = self.get_process() + lpRemoteFilenamePtr = self.raw.u.LoadDll.lpImageName + if lpRemoteFilenamePtr: + lpFilename = aProcess.peek_uint(lpRemoteFilenamePtr) + fUnicode = bool( self.raw.u.LoadDll.fUnicode ) + szFilename = aProcess.peek_string(lpFilename, fUnicode) + if not szFilename: + szFilename = None + + # Try to get the filename from the file handle. + if not szFilename: + hFile = self.get_file_handle() + if hFile: + szFilename = hFile.get_filename() + + # Return the filename, or None on error. + return szFilename + +#============================================================================== + +class UnloadDLLEvent (Event): + """ + Module unload event. + """ + + eventMethod = 'unload_dll' + eventName = 'Module unload event' + eventDescription = 'A DLL library was unloaded by the debugee.' + + def get_module_base(self): + """ + @rtype: int + @return: Base address for the recently unloaded DLL. + """ + return self.raw.u.UnloadDll.lpBaseOfDll + + def get_module(self): + """ + @rtype: L{Module} + @return: Module object for the recently unloaded DLL. + """ + lpBaseOfDll = self.get_module_base() + aProcess = self.get_process() + if aProcess.has_module(lpBaseOfDll): + aModule = aProcess.get_module(lpBaseOfDll) + else: + aModule = Module(lpBaseOfDll, process = aProcess) + aProcess._add_module(aModule) + return aModule + + def get_file_handle(self): + """ + @rtype: None or L{FileHandle} + @return: File handle to the recently unloaded DLL. + Returns C{None} if the handle is not available. + """ + hFile = self.get_module().hFile + if hFile in (0, win32.NULL, win32.INVALID_HANDLE_VALUE): + hFile = None + return hFile + + def get_filename(self): + """ + @rtype: None or str + @return: Filename of the recently unloaded DLL. + C{None} if the filename is unknown. + """ + return self.get_module().get_filename() + +#============================================================================== + +class OutputDebugStringEvent (Event): + """ + Debug string output event. + """ + + eventMethod = 'output_string' + eventName = 'Debug string output event' + eventDescription = 'The debugee sent a message to the debugger.' + + def get_debug_string(self): + """ + @rtype: str, compat.unicode + @return: String sent by the debugee. + It may be ANSI or Unicode and may end with a null character. + """ + return self.get_process().peek_string( + self.raw.u.DebugString.lpDebugStringData, + bool( self.raw.u.DebugString.fUnicode ), + self.raw.u.DebugString.nDebugStringLength) + +#============================================================================== + +class RIPEvent (Event): + """ + RIP event. + """ + + eventMethod = 'rip' + eventName = 'RIP event' + eventDescription = 'An error has occured and the process ' \ + 'can no longer be debugged.' + + def get_rip_error(self): + """ + @rtype: int + @return: RIP error code as defined by the Win32 API. + """ + return self.raw.u.RipInfo.dwError + + def get_rip_type(self): + """ + @rtype: int + @return: RIP type code as defined by the Win32 API. + May be C{0} or one of the following: + - L{win32.SLE_ERROR} + - L{win32.SLE_MINORERROR} + - L{win32.SLE_WARNING} + """ + return self.raw.u.RipInfo.dwType + +#============================================================================== + +class EventFactory (StaticClass): + """ + Factory of L{Event} objects. + + @type baseEvent: L{Event} + @cvar baseEvent: + Base class for Event objects. + It's used for unknown event codes. + + @type eventClasses: dict( int S{->} L{Event} ) + @cvar eventClasses: + Dictionary that maps event codes to L{Event} subclasses. + """ + + baseEvent = Event + eventClasses = { + win32.EXCEPTION_DEBUG_EVENT : ExceptionEvent, # 1 + win32.CREATE_THREAD_DEBUG_EVENT : CreateThreadEvent, # 2 + win32.CREATE_PROCESS_DEBUG_EVENT : CreateProcessEvent, # 3 + win32.EXIT_THREAD_DEBUG_EVENT : ExitThreadEvent, # 4 + win32.EXIT_PROCESS_DEBUG_EVENT : ExitProcessEvent, # 5 + win32.LOAD_DLL_DEBUG_EVENT : LoadDLLEvent, # 6 + win32.UNLOAD_DLL_DEBUG_EVENT : UnloadDLLEvent, # 7 + win32.OUTPUT_DEBUG_STRING_EVENT : OutputDebugStringEvent, # 8 + win32.RIP_EVENT : RIPEvent, # 9 + } + + @classmethod + def get(cls, debug, raw): + """ + @type debug: L{Debug} + @param debug: Debug object that received the event. + + @type raw: L{DEBUG_EVENT} + @param raw: Raw DEBUG_EVENT structure as used by the Win32 API. + + @rtype: L{Event} + @returns: An Event object or one of it's subclasses, + depending on the event type. + """ + eventClass = cls.eventClasses.get(raw.dwDebugEventCode, cls.baseEvent) + return eventClass(debug, raw) + +#============================================================================== + +class EventHandler (object): + """ + Base class for debug event handlers. + + Your program should subclass it to implement it's own event handling. + + The constructor can be overriden as long as you call the superclass + constructor. The special method L{__call__} B{MUST NOT} be overriden. + + The signature for event handlers is the following:: + + def event_handler(self, event): + + Where B{event} is an L{Event} object. + + Each event handler is named after the event they handle. + This is the list of all valid event handler names: + + - I{event} + + Receives an L{Event} object or an object of any of it's subclasses, + and handles any event for which no handler was defined. + + - I{unknown_event} + + Receives an L{Event} object or an object of any of it's subclasses, + and handles any event unknown to the debugging engine. (This is not + likely to happen unless the Win32 debugging API is changed in future + versions of Windows). + + - I{exception} + + Receives an L{ExceptionEvent} object and handles any exception for + which no handler was defined. See above for exception handlers. + + - I{unknown_exception} + + Receives an L{ExceptionEvent} object and handles any exception unknown + to the debugging engine. This usually happens for C++ exceptions, which + are not standardized and may change from one compiler to the next. + + Currently we have partial support for C++ exceptions thrown by Microsoft + compilers. + + Also see: U{RaiseException() + } + + - I{create_thread} + + Receives a L{CreateThreadEvent} object. + + - I{create_process} + + Receives a L{CreateProcessEvent} object. + + - I{exit_thread} + + Receives a L{ExitThreadEvent} object. + + - I{exit_process} + + Receives a L{ExitProcessEvent} object. + + - I{load_dll} + + Receives a L{LoadDLLEvent} object. + + - I{unload_dll} + + Receives an L{UnloadDLLEvent} object. + + - I{output_string} + + Receives an L{OutputDebugStringEvent} object. + + - I{rip} + + Receives a L{RIPEvent} object. + + This is the list of all valid exception handler names + (they all receive an L{ExceptionEvent} object): + + - I{access_violation} + - I{array_bounds_exceeded} + - I{breakpoint} + - I{control_c_exit} + - I{datatype_misalignment} + - I{debug_control_c} + - I{float_denormal_operand} + - I{float_divide_by_zero} + - I{float_inexact_result} + - I{float_invalid_operation} + - I{float_overflow} + - I{float_stack_check} + - I{float_underflow} + - I{guard_page} + - I{illegal_instruction} + - I{in_page_error} + - I{integer_divide_by_zero} + - I{integer_overflow} + - I{invalid_disposition} + - I{invalid_handle} + - I{ms_vc_exception} + - I{noncontinuable_exception} + - I{possible_deadlock} + - I{privileged_instruction} + - I{single_step} + - I{stack_overflow} + - I{wow64_breakpoint} + + + + @type apiHooks: dict( str S{->} list( tuple( str, int ) ) ) + @cvar apiHooks: + Dictionary that maps module names to lists of + tuples of ( procedure name, parameter count ). + + All procedures listed here will be hooked for calls from the debugee. + When this happens, the corresponding event handler can be notified both + when the procedure is entered and when it's left by the debugee. + + For example, let's hook the LoadLibraryEx() API call. + This would be the declaration of apiHooks:: + + from winappdbg import EventHandler + from winappdbg.win32 import * + + # (...) + + class MyEventHandler (EventHandler): + + apiHook = { + + "kernel32.dll" : ( + + # Procedure name Signature + ( "LoadLibraryEx", (PVOID, HANDLE, DWORD) ), + + # (more procedures can go here...) + ), + + # (more libraries can go here...) + } + + # (your method definitions go here...) + + Note that all pointer types are treated like void pointers, so your + callback won't get the string or structure pointed to by it, but the + remote memory address instead. This is so to prevent the ctypes library + from being "too helpful" and trying to dereference the pointer. To get + the actual data being pointed to, use one of the L{Process.read} + methods. + + Now, to intercept calls to LoadLibraryEx define a method like this in + your event handler class:: + + def pre_LoadLibraryEx(self, event, ra, lpFilename, hFile, dwFlags): + szFilename = event.get_process().peek_string(lpFilename) + + # (...) + + Note that the first parameter is always the L{Event} object, and the + second parameter is the return address. The third parameter and above + are the values passed to the hooked function. + + Finally, to intercept returns from calls to LoadLibraryEx define a + method like this:: + + def post_LoadLibraryEx(self, event, retval): + # (...) + + The first parameter is the L{Event} object and the second is the + return value from the hooked function. + """ + +#------------------------------------------------------------------------------ + + # Default (empty) API hooks dictionary. + apiHooks = {} + + def __init__(self): + """ + Class constructor. Don't forget to call it when subclassing! + + Forgetting to call the superclass constructor is a common mistake when + you're new to Python. :) + + Example:: + class MyEventHandler (EventHandler): + + # Override the constructor to use an extra argument. + def __init__(self, myArgument): + + # Do something with the argument, like keeping it + # as an instance variable. + self.myVariable = myArgument + + # Call the superclass constructor. + super(MyEventHandler, self).__init__() + + # The rest of your code below... + """ + + # TODO + # All this does is set up the hooks. + # This code should be moved to the EventDispatcher class. + # Then the hooks can be set up at set_event_handler() instead, making + # this class even simpler. The downside here is deciding where to store + # the ApiHook objects. + + # Convert the tuples into instances of the ApiHook class. + # A new dictionary must be instanced, otherwise we could also be + # affecting all other instances of the EventHandler. + apiHooks = dict() + for lib, hooks in compat.iteritems(self.apiHooks): + hook_objs = [] + for proc, args in hooks: + if type(args) in (int, long): + h = ApiHook(self, lib, proc, paramCount = args) + else: + h = ApiHook(self, lib, proc, signature = args) + hook_objs.append(h) + apiHooks[lib] = hook_objs + self.__apiHooks = apiHooks + + def __get_hooks_for_dll(self, event): + """ + Get the requested API hooks for the current DLL. + + Used by L{__hook_dll} and L{__unhook_dll}. + """ + result = [] + if self.__apiHooks: + path = event.get_module().get_filename() + if path: + lib_name = PathOperations.pathname_to_filename(path).lower() + for hook_lib, hook_api_list in compat.iteritems(self.__apiHooks): + if hook_lib == lib_name: + result.extend(hook_api_list) + return result + + def __hook_dll(self, event): + """ + Hook the requested API calls (in self.apiHooks). + + This method is called automatically whenever a DLL is loaded. + """ + debug = event.debug + pid = event.get_pid() + for hook_api_stub in self.__get_hooks_for_dll(event): + hook_api_stub.hook(debug, pid) + + def __unhook_dll(self, event): + """ + Unhook the requested API calls (in self.apiHooks). + + This method is called automatically whenever a DLL is unloaded. + """ + debug = event.debug + pid = event.get_pid() + for hook_api_stub in self.__get_hooks_for_dll(event): + hook_api_stub.unhook(debug, pid) + + def __call__(self, event): + """ + Dispatch debug events. + + @warn: B{Don't override this method!} + + @type event: L{Event} + @param event: Event object. + """ + try: + code = event.get_event_code() + if code == win32.LOAD_DLL_DEBUG_EVENT: + self.__hook_dll(event) + elif code == win32.UNLOAD_DLL_DEBUG_EVENT: + self.__unhook_dll(event) + finally: + method = EventDispatcher.get_handler_method(self, event) + if method is not None: + return method(event) + +#============================================================================== + +# TODO +# * Make it more generic by adding a few more callbacks. +# That way it will be possible to make a thread sifter too. +# * This interface feels too much like an antipattern. +# When apiHooks is deprecated this will have to be reviewed. + +class EventSift(EventHandler): + """ + Event handler that allows you to use customized event handlers for each + process you're attached to. + + This makes coding the event handlers much easier, because each instance + will only "know" about one process. So you can code your event handler as + if only one process was being debugged, but your debugger can attach to + multiple processes. + + Example:: + from winappdbg import Debug, EventHandler, EventSift + + # This class was written assuming only one process is attached. + # If you used it directly it would break when attaching to another + # process, or when a child process is spawned. + class MyEventHandler (EventHandler): + + def create_process(self, event): + self.first = True + self.name = event.get_process().get_filename() + print "Attached to %s" % self.name + + def breakpoint(self, event): + if self.first: + self.first = False + print "First breakpoint reached at %s" % self.name + + def exit_process(self, event): + print "Detached from %s" % self.name + + # Now when debugging we use the EventSift to be able to work with + # multiple processes while keeping our code simple. :) + if __name__ == "__main__": + handler = EventSift(MyEventHandler) + #handler = MyEventHandler() # try uncommenting this line... + with Debug(handler) as debug: + debug.execl("calc.exe") + debug.execl("notepad.exe") + debug.execl("charmap.exe") + debug.loop() + + Subclasses of C{EventSift} can prevent specific event types from + being forwarded by simply defining a method for it. That means your + subclass can handle some event types globally while letting other types + be handled on per-process basis. To forward events manually you can + call C{self.event(event)}. + + Example:: + class MySift (EventSift): + + # Don't forward this event. + def debug_control_c(self, event): + pass + + # Handle this event globally without forwarding it. + def output_string(self, event): + print "Debug string: %s" % event.get_debug_string() + + # Handle this event globally and then forward it. + def create_process(self, event): + print "New process created, PID: %d" % event.get_pid() + return self.event(event) + + # All other events will be forwarded. + + Note that overriding the C{event} method would cause no events to be + forwarded at all. To prevent this, call the superclass implementation. + + Example:: + + def we_want_to_forward_this_event(event): + "Use whatever logic you want here..." + # (...return True or False...) + + class MySift (EventSift): + + def event(self, event): + + # If the event matches some custom criteria... + if we_want_to_forward_this_event(event): + + # Forward it. + return super(MySift, self).event(event) + + # Otherwise, don't. + + @type cls: class + @ivar cls: + Event handler class. There will be one instance of this class + per debugged process in the L{forward} dictionary. + + @type argv: list + @ivar argv: + Positional arguments to pass to the constructor of L{cls}. + + @type argd: list + @ivar argd: + Keyword arguments to pass to the constructor of L{cls}. + + @type forward: dict + @ivar forward: + Dictionary that maps each debugged process ID to an instance of L{cls}. + """ + + def __init__(self, cls, *argv, **argd): + """ + Maintains an instance of your event handler for each process being + debugged, and forwards the events of each process to each corresponding + instance. + + @warn: If you subclass L{EventSift} and reimplement this method, + don't forget to call the superclass constructor! + + @see: L{event} + + @type cls: class + @param cls: Event handler class. This must be the class itself, not an + instance! All additional arguments passed to the constructor of + the event forwarder will be passed on to the constructor of this + class as well. + """ + self.cls = cls + self.argv = argv + self.argd = argd + self.forward = dict() + super(EventSift, self).__init__() + + # XXX HORRIBLE HACK + # This makes apiHooks work in the inner handlers. + def __call__(self, event): + try: + eventCode = event.get_event_code() + if eventCode in (win32.LOAD_DLL_DEBUG_EVENT, + win32.LOAD_DLL_DEBUG_EVENT): + pid = event.get_pid() + handler = self.forward.get(pid, None) + if handler is None: + handler = self.cls(*self.argv, **self.argd) + self.forward[pid] = handler + if isinstance(handler, EventHandler): + if eventCode == win32.LOAD_DLL_DEBUG_EVENT: + handler.__EventHandler_hook_dll(event) + else: + handler.__EventHandler_unhook_dll(event) + finally: + return super(EventSift, self).__call__(event) + + def event(self, event): + """ + Forwards events to the corresponding instance of your event handler + for this process. + + If you subclass L{EventSift} and reimplement this method, no event + will be forwarded at all unless you call the superclass implementation. + + If your filtering is based on the event type, there's a much easier way + to do it: just implement a handler for it. + """ + eventCode = event.get_event_code() + pid = event.get_pid() + handler = self.forward.get(pid, None) + if handler is None: + handler = self.cls(*self.argv, **self.argd) + if eventCode != win32.EXIT_PROCESS_DEBUG_EVENT: + self.forward[pid] = handler + elif eventCode == win32.EXIT_PROCESS_DEBUG_EVENT: + del self.forward[pid] + return handler(event) + +#============================================================================== + +class EventDispatcher (object): + """ + Implements debug event dispatching capabilities. + + @group Debugging events: + get_event_handler, set_event_handler, get_handler_method + """ + + # Maps event code constants to the names of the pre-notify routines. + # These routines are called BEFORE the user-defined handlers. + # Unknown codes are ignored. + __preEventNotifyCallbackName = { + win32.CREATE_THREAD_DEBUG_EVENT : '_notify_create_thread', + win32.CREATE_PROCESS_DEBUG_EVENT : '_notify_create_process', + win32.LOAD_DLL_DEBUG_EVENT : '_notify_load_dll', + } + + # Maps event code constants to the names of the post-notify routines. + # These routines are called AFTER the user-defined handlers. + # Unknown codes are ignored. + __postEventNotifyCallbackName = { + win32.EXIT_THREAD_DEBUG_EVENT : '_notify_exit_thread', + win32.EXIT_PROCESS_DEBUG_EVENT : '_notify_exit_process', + win32.UNLOAD_DLL_DEBUG_EVENT : '_notify_unload_dll', + win32.RIP_EVENT : '_notify_rip', + } + + # Maps exception code constants to the names of the pre-notify routines. + # These routines are called BEFORE the user-defined handlers. + # Unknown codes are ignored. + __preExceptionNotifyCallbackName = { + win32.EXCEPTION_BREAKPOINT : '_notify_breakpoint', + win32.EXCEPTION_WX86_BREAKPOINT : '_notify_breakpoint', + win32.EXCEPTION_SINGLE_STEP : '_notify_single_step', + win32.EXCEPTION_GUARD_PAGE : '_notify_guard_page', + win32.DBG_CONTROL_C : '_notify_debug_control_c', + win32.MS_VC_EXCEPTION : '_notify_ms_vc_exception', + } + + # Maps exception code constants to the names of the post-notify routines. + # These routines are called AFTER the user-defined handlers. + # Unknown codes are ignored. + __postExceptionNotifyCallbackName = { + } + + def __init__(self, eventHandler = None): + """ + Event dispatcher. + + @type eventHandler: L{EventHandler} + @param eventHandler: (Optional) User-defined event handler. + + @raise TypeError: The event handler is of an incorrect type. + + @note: The L{eventHandler} parameter may be any callable Python object + (for example a function, or an instance method). + However you'll probably find it more convenient to use an instance + of a subclass of L{EventHandler} here. + """ + self.set_event_handler(eventHandler) + + def get_event_handler(self): + """ + Get the event handler. + + @see: L{set_event_handler} + + @rtype: L{EventHandler} + @return: Current event handler object, or C{None}. + """ + return self.__eventHandler + + def set_event_handler(self, eventHandler): + """ + Set the event handler. + + @warn: This is normally not needed. Use with care! + + @type eventHandler: L{EventHandler} + @param eventHandler: New event handler object, or C{None}. + + @rtype: L{EventHandler} + @return: Previous event handler object, or C{None}. + + @raise TypeError: The event handler is of an incorrect type. + + @note: The L{eventHandler} parameter may be any callable Python object + (for example a function, or an instance method). + However you'll probably find it more convenient to use an instance + of a subclass of L{EventHandler} here. + """ + if eventHandler is not None and not callable(eventHandler): + raise TypeError("Event handler must be a callable object") + try: + wrong_type = issubclass(eventHandler, EventHandler) + except TypeError: + wrong_type = False + if wrong_type: + classname = str(eventHandler) + msg = "Event handler must be an instance of class %s" + msg += "rather than the %s class itself. (Missing parens?)" + msg = msg % (classname, classname) + raise TypeError(msg) + try: + previous = self.__eventHandler + except AttributeError: + previous = None + self.__eventHandler = eventHandler + return previous + + @staticmethod + def get_handler_method(eventHandler, event, fallback=None): + """ + Retrieves the appropriate callback method from an L{EventHandler} + instance for the given L{Event} object. + + @type eventHandler: L{EventHandler} + @param eventHandler: + Event handler object whose methods we are examining. + + @type event: L{Event} + @param event: Debugging event to be handled. + + @type fallback: callable + @param fallback: (Optional) If no suitable method is found in the + L{EventHandler} instance, return this value. + + @rtype: callable + @return: Bound method that will handle the debugging event. + Returns C{None} if no such method is defined. + """ + eventCode = event.get_event_code() + method = getattr(eventHandler, 'event', fallback) + if eventCode == win32.EXCEPTION_DEBUG_EVENT: + method = getattr(eventHandler, 'exception', method) + method = getattr(eventHandler, event.eventMethod, method) + return method + + def dispatch(self, event): + """ + Sends event notifications to the L{Debug} object and + the L{EventHandler} object provided by the user. + + The L{Debug} object will forward the notifications to it's contained + snapshot objects (L{System}, L{Process}, L{Thread} and L{Module}) when + appropriate. + + @warning: This method is called automatically from L{Debug.dispatch}. + + @see: L{Debug.cont}, L{Debug.loop}, L{Debug.wait} + + @type event: L{Event} + @param event: Event object passed to L{Debug.dispatch}. + + @raise WindowsError: Raises an exception on error. + """ + returnValue = None + bCallHandler = True + pre_handler = None + post_handler = None + eventCode = event.get_event_code() + + # Get the pre and post notification methods for exceptions. + # If not found, the following steps take care of that. + if eventCode == win32.EXCEPTION_DEBUG_EVENT: + exceptionCode = event.get_exception_code() + pre_name = self.__preExceptionNotifyCallbackName.get( + exceptionCode, None) + post_name = self.__postExceptionNotifyCallbackName.get( + exceptionCode, None) + if pre_name is not None: + pre_handler = getattr(self, pre_name, None) + if post_name is not None: + post_handler = getattr(self, post_name, None) + + # Get the pre notification method for all other events. + # This includes the exception event if no notify method was found + # for this exception code. + if pre_handler is None: + pre_name = self.__preEventNotifyCallbackName.get(eventCode, None) + if pre_name is not None: + pre_handler = getattr(self, pre_name, pre_handler) + + # Get the post notification method for all other events. + # This includes the exception event if no notify method was found + # for this exception code. + if post_handler is None: + post_name = self.__postEventNotifyCallbackName.get(eventCode, None) + if post_name is not None: + post_handler = getattr(self, post_name, post_handler) + + # Call the pre-notify method only if it was defined. + # If an exception is raised don't call the other methods. + if pre_handler is not None: + bCallHandler = pre_handler(event) + + # Call the user-defined event handler only if the pre-notify + # method was not defined, or was and it returned True. + try: + if bCallHandler and self.__eventHandler is not None: + try: + returnValue = self.__eventHandler(event) + except Exception: + e = sys.exc_info()[1] + msg = ("Event handler pre-callback %r" + " raised an exception: %s") + msg = msg % (self.__eventHandler, traceback.format_exc(e)) + warnings.warn(msg, EventCallbackWarning) + returnValue = None + + # Call the post-notify method if defined, even if an exception is + # raised by the user-defined event handler. + finally: + if post_handler is not None: + post_handler(event) + + # Return the value from the call to the user-defined event handler. + # If not defined return None. + return returnValue diff --git a/pydevd_attach_to_process/winappdbg/interactive.py b/pydevd_attach_to_process/winappdbg/interactive.py new file mode 100644 index 0000000..b9d842f --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/interactive.py @@ -0,0 +1,2242 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Acknowledgements: +# Nicolas Economou, for his command line debugger on which this is inspired. +# http://tinyurl.com/nicolaseconomou + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Interactive debugging console. + +@group Debugging: + ConsoleDebugger + +@group Exceptions: + CmdError +""" + +from __future__ import with_statement + +__revision__ = "$Id$" + +__all__ = [ 'ConsoleDebugger', 'CmdError' ] + +# TODO document this module with docstrings. +# TODO command to set a last error breakpoint. +# TODO command to show available plugins. + +from winappdbg import win32 +from winappdbg import compat +from winappdbg.system import System +from winappdbg.util import PathOperations +from winappdbg.event import EventHandler, NoEvent +from winappdbg.textio import HexInput, HexOutput, HexDump, CrashDump, DebugLog + +import os +import sys +import code +import time +import warnings +import traceback + +# too many variables named "cmd" to have a module by the same name :P +from cmd import Cmd + +# lazy imports +readline = None + +#============================================================================== + + +class DummyEvent (NoEvent): + "Dummy event object used internally by L{ConsoleDebugger}." + + def get_pid(self): + return self._pid + + def get_tid(self): + return self._tid + + def get_process(self): + return self._process + + def get_thread(self): + return self._thread + +#============================================================================== + + +class CmdError (Exception): + """ + Exception raised when a command parsing error occurs. + Used internally by L{ConsoleDebugger}. + """ + +#============================================================================== + + +class ConsoleDebugger (Cmd, EventHandler): + """ + Interactive console debugger. + + @see: L{Debug.interactive} + """ + +#------------------------------------------------------------------------------ +# Class variables + + # Exception to raise when an error occurs executing a command. + command_error_exception = CmdError + + # Milliseconds to wait for debug events in the main loop. + dwMilliseconds = 100 + + # History file name. + history_file = '.winappdbg_history' + + # Confirm before quitting? + confirm_quit = True + + # Valid plugin name characters. + valid_plugin_name_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXY' \ + 'abcdefghijklmnopqrstuvwxy' \ + '012345678' \ + '_' + + # Names of the registers. + segment_names = ('cs', 'ds', 'es', 'fs', 'gs') + + register_alias_64_to_32 = { + 'eax':'Rax', 'ebx':'Rbx', 'ecx':'Rcx', 'edx':'Rdx', + 'eip':'Rip', 'ebp':'Rbp', 'esp':'Rsp', 'esi':'Rsi', 'edi':'Rdi' + } + register_alias_64_to_16 = { 'ax':'Rax', 'bx':'Rbx', 'cx':'Rcx', 'dx':'Rdx' } + register_alias_64_to_8_low = { 'al':'Rax', 'bl':'Rbx', 'cl':'Rcx', 'dl':'Rdx' } + register_alias_64_to_8_high = { 'ah':'Rax', 'bh':'Rbx', 'ch':'Rcx', 'dh':'Rdx' } + register_alias_32_to_16 = { 'ax':'Eax', 'bx':'Ebx', 'cx':'Ecx', 'dx':'Edx' } + register_alias_32_to_8_low = { 'al':'Eax', 'bl':'Ebx', 'cl':'Ecx', 'dl':'Edx' } + register_alias_32_to_8_high = { 'ah':'Eax', 'bh':'Ebx', 'ch':'Ecx', 'dh':'Edx' } + + register_aliases_full_32 = list(segment_names) + register_aliases_full_32.extend(compat.iterkeys(register_alias_32_to_16)) + register_aliases_full_32.extend(compat.iterkeys(register_alias_32_to_8_low)) + register_aliases_full_32.extend(compat.iterkeys(register_alias_32_to_8_high)) + register_aliases_full_32 = tuple(register_aliases_full_32) + + register_aliases_full_64 = list(segment_names) + register_aliases_full_64.extend(compat.iterkeys(register_alias_64_to_32)) + register_aliases_full_64.extend(compat.iterkeys(register_alias_64_to_16)) + register_aliases_full_64.extend(compat.iterkeys(register_alias_64_to_8_low)) + register_aliases_full_64.extend(compat.iterkeys(register_alias_64_to_8_high)) + register_aliases_full_64 = tuple(register_aliases_full_64) + + # Names of the control flow instructions. + jump_instructions = ( + 'jmp', 'jecxz', 'jcxz', + 'ja', 'jnbe', 'jae', 'jnb', 'jb', 'jnae', 'jbe', 'jna', 'jc', 'je', + 'jz', 'jnc', 'jne', 'jnz', 'jnp', 'jpo', 'jp', 'jpe', 'jg', 'jnle', + 'jge', 'jnl', 'jl', 'jnge', 'jle', 'jng', 'jno', 'jns', 'jo', 'js' + ) + call_instructions = ('call', 'ret', 'retn') + loop_instructions = ('loop', 'loopz', 'loopnz', 'loope', 'loopne') + control_flow_instructions = call_instructions + loop_instructions + \ + jump_instructions + +#------------------------------------------------------------------------------ +# Instance variables + + def __init__(self): + """ + Interactive console debugger. + + @see: L{Debug.interactive} + """ + Cmd.__init__(self) + EventHandler.__init__(self) + + # Quit the debugger when True. + self.debuggerExit = False + + # Full path to the history file. + self.history_file_full_path = None + + # Last executed command. + self.__lastcmd = "" + +#------------------------------------------------------------------------------ +# Debugger + + # Use this Debug object. + def start_using_debugger(self, debug): + + # Clear the previous Debug object. + self.stop_using_debugger() + + # Keep the Debug object. + self.debug = debug + + # Set ourselves as the event handler for the debugger. + self.prevHandler = debug.set_event_handler(self) + + # Stop using the Debug object given by start_using_debugger(). + # Circular references must be removed, or the destructors never get called. + def stop_using_debugger(self): + if hasattr(self, 'debug'): + debug = self.debug + debug.set_event_handler(self.prevHandler) + del self.prevHandler + del self.debug + return debug + return None + + # Destroy the Debug object. + def destroy_debugger(self, autodetach=True): + debug = self.stop_using_debugger() + if debug is not None: + if not autodetach: + debug.kill_all(bIgnoreExceptions=True) + debug.lastEvent = None + debug.stop() + del debug + + @property + def lastEvent(self): + return self.debug.lastEvent + + def set_fake_last_event(self, process): + if self.lastEvent is None: + self.debug.lastEvent = DummyEvent(self.debug) + self.debug.lastEvent._process = process + self.debug.lastEvent._thread = process.get_thread( + process.get_thread_ids()[0]) + self.debug.lastEvent._pid = process.get_pid() + self.debug.lastEvent._tid = self.lastEvent._thread.get_tid() + +#------------------------------------------------------------------------------ +# Input + +# TODO +# * try to guess breakpoints when insufficient data is given +# * child Cmd instances will have to be used for other prompts, for example +# when assembling or editing memory - it may also be a good idea to think +# if it's possible to make the main Cmd instance also a child, instead of +# the debugger itself - probably the same goes for the EventHandler, maybe +# it can be used as a contained object rather than a parent class. + + # Join a token list into an argument string. + def join_tokens(self, token_list): + return self.debug.system.argv_to_cmdline(token_list) + + # Split an argument string into a token list. + def split_tokens(self, arg, min_count=0, max_count=None): + token_list = self.debug.system.cmdline_to_argv(arg) + if len(token_list) < min_count: + raise CmdError("missing parameters.") + if max_count and len(token_list) > max_count: + raise CmdError("too many parameters.") + return token_list + + # Token is a thread ID or name. + def input_thread(self, token): + targets = self.input_thread_list([token]) + if len(targets) == 0: + raise CmdError("missing thread name or ID") + if len(targets) > 1: + msg = "more than one thread with that name:\n" + for tid in targets: + msg += "\t%d\n" % tid + msg = msg[:-len("\n")] + raise CmdError(msg) + return targets[0] + + # Token list is a list of thread IDs or names. + def input_thread_list(self, token_list): + targets = set() + system = self.debug.system + for token in token_list: + try: + tid = self.input_integer(token) + if not system.has_thread(tid): + raise CmdError("thread not found (%d)" % tid) + targets.add(tid) + except ValueError: + found = set() + for process in system.iter_processes(): + found.update(system.find_threads_by_name(token)) + if not found: + raise CmdError("thread not found (%s)" % token) + for thread in found: + targets.add(thread.get_tid()) + targets = list(targets) + targets.sort() + return targets + + # Token is a process ID or name. + def input_process(self, token): + targets = self.input_process_list([token]) + if len(targets) == 0: + raise CmdError("missing process name or ID") + if len(targets) > 1: + msg = "more than one process with that name:\n" + for pid in targets: + msg += "\t%d\n" % pid + msg = msg[:-len("\n")] + raise CmdError(msg) + return targets[0] + + # Token list is a list of process IDs or names. + def input_process_list(self, token_list): + targets = set() + system = self.debug.system + for token in token_list: + try: + pid = self.input_integer(token) + if not system.has_process(pid): + raise CmdError("process not found (%d)" % pid) + targets.add(pid) + except ValueError: + found = system.find_processes_by_filename(token) + if not found: + raise CmdError("process not found (%s)" % token) + for (process, _) in found: + targets.add(process.get_pid()) + targets = list(targets) + targets.sort() + return targets + + # Token is a command line to execute. + def input_command_line(self, command_line): + argv = self.debug.system.cmdline_to_argv(command_line) + if not argv: + raise CmdError("missing command line to execute") + fname = argv[0] + if not os.path.exists(fname): + try: + fname, _ = win32.SearchPath(None, fname, '.exe') + except WindowsError: + raise CmdError("file not found: %s" % fname) + argv[0] = fname + command_line = self.debug.system.argv_to_cmdline(argv) + return command_line + + # Token is an integer. + # Only hexadecimal format is supported. + def input_hexadecimal_integer(self, token): + return int(token, 0x10) + + # Token is an integer. + # It can be in any supported format. + def input_integer(self, token): + return HexInput.integer(token) +# # input_integer = input_hexadecimal_integer + + # Token is an address. + # The address can be a integer, a label or a register. + def input_address(self, token, pid=None, tid=None): + address = None + if self.is_register(token): + if tid is None: + if self.lastEvent is None or pid != self.lastEvent.get_pid(): + msg = "can't resolve register (%s) for unknown thread" + raise CmdError(msg % token) + tid = self.lastEvent.get_tid() + address = self.input_register(token, tid) + if address is None: + try: + address = self.input_hexadecimal_integer(token) + except ValueError: + if pid is None: + if self.lastEvent is None: + raise CmdError("no current process set") + process = self.lastEvent.get_process() + elif self.lastEvent is not None and pid == self.lastEvent.get_pid(): + process = self.lastEvent.get_process() + else: + try: + process = self.debug.system.get_process(pid) + except KeyError: + raise CmdError("process not found (%d)" % pid) + try: + address = process.resolve_label(token) + except Exception: + raise CmdError("unknown address (%s)" % token) + return address + + # Token is an address range, or a single address. + # The addresses can be integers, labels or registers. + def input_address_range(self, token_list, pid=None, tid=None): + if len(token_list) == 2: + token_1, token_2 = token_list + address = self.input_address(token_1, pid, tid) + try: + size = self.input_integer(token_2) + except ValueError: + raise CmdError("bad address range: %s %s" % (token_1, token_2)) + elif len(token_list) == 1: + token = token_list[0] + if '-' in token: + try: + token_1, token_2 = token.split('-') + except Exception: + raise CmdError("bad address range: %s" % token) + address = self.input_address(token_1, pid, tid) + size = self.input_address(token_2, pid, tid) - address + else: + address = self.input_address(token, pid, tid) + size = None + return address, size + + # XXX TODO + # Support non-integer registers here. + def is_register(self, token): + if win32.arch == 'i386': + if token in self.register_aliases_full_32: + return True + token = token.title() + for (name, typ) in win32.CONTEXT._fields_: + if name == token: + return win32.sizeof(typ) == win32.sizeof(win32.DWORD) + elif win32.arch == 'amd64': + if token in self.register_aliases_full_64: + return True + token = token.title() + for (name, typ) in win32.CONTEXT._fields_: + if name == token: + return win32.sizeof(typ) == win32.sizeof(win32.DWORD64) + return False + + # The token is a register name. + # Returns None if no register name is matched. + def input_register(self, token, tid=None): + if tid is None: + if self.lastEvent is None: + raise CmdError("no current process set") + thread = self.lastEvent.get_thread() + else: + thread = self.debug.system.get_thread(tid) + ctx = thread.get_context() + + token = token.lower() + title = token.title() + + if title in ctx: + return ctx.get(title) # eax -> Eax + + if ctx.arch == 'i386': + + if token in self.segment_names: + return ctx.get('Seg%s' % title) # cs -> SegCs + + if token in self.register_alias_32_to_16: + return ctx.get(self.register_alias_32_to_16[token]) & 0xFFFF + + if token in self.register_alias_32_to_8_low: + return ctx.get(self.register_alias_32_to_8_low[token]) & 0xFF + + if token in self.register_alias_32_to_8_high: + return (ctx.get(self.register_alias_32_to_8_high[token]) & 0xFF00) >> 8 + + elif ctx.arch == 'amd64': + + if token in self.segment_names: + return ctx.get('Seg%s' % title) # cs -> SegCs + + if token in self.register_alias_64_to_32: + return ctx.get(self.register_alias_64_to_32[token]) & 0xFFFFFFFF + + if token in self.register_alias_64_to_16: + return ctx.get(self.register_alias_64_to_16[token]) & 0xFFFF + + if token in self.register_alias_64_to_8_low: + return ctx.get(self.register_alias_64_to_8_low[token]) & 0xFF + + if token in self.register_alias_64_to_8_high: + return (ctx.get(self.register_alias_64_to_8_high[token]) & 0xFF00) >> 8 + + return None + + # Token list contains an address or address range. + # The prefix is also parsed looking for process and thread IDs. + def input_full_address_range(self, token_list): + pid, tid = self.get_process_and_thread_ids_from_prefix() + address, size = self.input_address_range(token_list, pid, tid) + return pid, tid, address, size + + # Token list contains a breakpoint. + def input_breakpoint(self, token_list): + pid, tid, address, size = self.input_full_address_range(token_list) + if not self.debug.is_debugee(pid): + raise CmdError("target process is not being debugged") + return pid, tid, address, size + + # Token list contains a memory address, and optional size and process. + # Sets the results as the default for the next display command. + def input_display(self, token_list, default_size=64): + pid, tid, address, size = self.input_full_address_range(token_list) + if not size: + size = default_size + next_address = HexOutput.integer(address + size) + self.default_display_target = next_address + return pid, tid, address, size + +#------------------------------------------------------------------------------ +# Output + + # Tell the user a module was loaded. + def print_module_load(self, event): + mod = event.get_module() + base = mod.get_base() + name = mod.get_filename() + if not name: + name = '' + msg = "Loaded module (%s) %s" + msg = msg % (HexDump.address(base), name) + print(msg) + + # Tell the user a module was unloaded. + def print_module_unload(self, event): + mod = event.get_module() + base = mod.get_base() + name = mod.get_filename() + if not name: + name = '' + msg = "Unloaded module (%s) %s" + msg = msg % (HexDump.address(base), name) + print(msg) + + # Tell the user a process was started. + def print_process_start(self, event): + pid = event.get_pid() + start = event.get_start_address() + if start: + start = HexOutput.address(start) + print("Started process %d at %s" % (pid, start)) + else: + print("Attached to process %d" % pid) + + # Tell the user a thread was started. + def print_thread_start(self, event): + tid = event.get_tid() + start = event.get_start_address() + if start: + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + start = event.get_process().get_label_at_address(start) + print("Started thread %d at %s" % (tid, start)) + else: + print("Attached to thread %d" % tid) + + # Tell the user a process has finished. + def print_process_end(self, event): + pid = event.get_pid() + code = event.get_exit_code() + print("Process %d terminated, exit code %d" % (pid, code)) + + # Tell the user a thread has finished. + def print_thread_end(self, event): + tid = event.get_tid() + code = event.get_exit_code() + print("Thread %d terminated, exit code %d" % (tid, code)) + + # Print(debug strings. + def print_debug_string(self, event): + tid = event.get_tid() + string = event.get_debug_string() + print("Thread %d says: %r" % (tid, string)) + + # Inform the user of any other debugging event. + def print_event(self, event): + code = HexDump.integer(event.get_event_code()) + name = event.get_event_name() + desc = event.get_event_description() + if code in desc: + print('') + print("%s: %s" % (name, desc)) + else: + print('') + print("%s (%s): %s" % (name, code, desc)) + self.print_event_location(event) + + # Stop on exceptions and prompt for commands. + def print_exception(self, event): + address = HexDump.address(event.get_exception_address()) + code = HexDump.integer(event.get_exception_code()) + desc = event.get_exception_description() + if event.is_first_chance(): + chance = 'first' + else: + chance = 'second' + if code in desc: + msg = "%s at address %s (%s chance)" % (desc, address, chance) + else: + msg = "%s (%s) at address %s (%s chance)" % (desc, code, address, chance) + print('') + print(msg) + self.print_event_location(event) + + # Show the current location in the code. + def print_event_location(self, event): + process = event.get_process() + thread = event.get_thread() + self.print_current_location(process, thread) + + # Show the current location in the code. + def print_breakpoint_location(self, event): + process = event.get_process() + thread = event.get_thread() + pc = event.get_exception_address() + self.print_current_location(process, thread, pc) + + # Show the current location in any process and thread. + def print_current_location(self, process=None, thread=None, pc=None): + if not process: + if self.lastEvent is None: + raise CmdError("no current process set") + process = self.lastEvent.get_process() + if not thread: + if self.lastEvent is None: + raise CmdError("no current process set") + thread = self.lastEvent.get_thread() + thread.suspend() + try: + if pc is None: + pc = thread.get_pc() + ctx = thread.get_context() + finally: + thread.resume() + label = process.get_label_at_address(pc) + try: + disasm = process.disassemble(pc, 15) + except WindowsError: + disasm = None + except NotImplementedError: + disasm = None + print('') + print(CrashDump.dump_registers(ctx),) + print("%s:" % label) + if disasm: + print(CrashDump.dump_code_line(disasm[0], pc, bShowDump=True)) + else: + try: + data = process.peek(pc, 15) + except Exception: + data = None + if data: + print('%s: %s' % (HexDump.address(pc), HexDump.hexblock_byte(data))) + else: + print('%s: ???' % HexDump.address(pc)) + + # Display memory contents using a given method. + def print_memory_display(self, arg, method): + if not arg: + arg = self.default_display_target + token_list = self.split_tokens(arg, 1, 2) + pid, tid, address, size = self.input_display(token_list) + label = self.get_process(pid).get_label_at_address(address) + data = self.read_memory(address, size, pid) + if data: + print("%s:" % label) + print(method(data, address),) + +#------------------------------------------------------------------------------ +# Debugging + + # Get the process ID from the prefix or the last event. + def get_process_id_from_prefix(self): + if self.cmdprefix: + pid = self.input_process(self.cmdprefix) + else: + if self.lastEvent is None: + raise CmdError("no current process set") + pid = self.lastEvent.get_pid() + return pid + + # Get the thread ID from the prefix or the last event. + def get_thread_id_from_prefix(self): + if self.cmdprefix: + tid = self.input_thread(self.cmdprefix) + else: + if self.lastEvent is None: + raise CmdError("no current process set") + tid = self.lastEvent.get_tid() + return tid + + # Get the process from the prefix or the last event. + def get_process_from_prefix(self): + pid = self.get_process_id_from_prefix() + return self.get_process(pid) + + # Get the thread from the prefix or the last event. + def get_thread_from_prefix(self): + tid = self.get_thread_id_from_prefix() + return self.get_thread(tid) + + # Get the process and thread IDs from the prefix or the last event. + def get_process_and_thread_ids_from_prefix(self): + if self.cmdprefix: + try: + pid = self.input_process(self.cmdprefix) + tid = None + except CmdError: + try: + tid = self.input_thread(self.cmdprefix) + pid = self.debug.system.get_thread(tid).get_pid() + except CmdError: + msg = "unknown process or thread (%s)" % self.cmdprefix + raise CmdError(msg) + else: + if self.lastEvent is None: + raise CmdError("no current process set") + pid = self.lastEvent.get_pid() + tid = self.lastEvent.get_tid() + return pid, tid + + # Get the process and thread from the prefix or the last event. + def get_process_and_thread_from_prefix(self): + pid, tid = self.get_process_and_thread_ids_from_prefix() + process = self.get_process(pid) + thread = self.get_thread(tid) + return process, thread + + # Get the process object. + def get_process(self, pid=None): + if pid is None: + if self.lastEvent is None: + raise CmdError("no current process set") + process = self.lastEvent.get_process() + elif self.lastEvent is not None and pid == self.lastEvent.get_pid(): + process = self.lastEvent.get_process() + else: + try: + process = self.debug.system.get_process(pid) + except KeyError: + raise CmdError("process not found (%d)" % pid) + return process + + # Get the thread object. + def get_thread(self, tid=None): + if tid is None: + if self.lastEvent is None: + raise CmdError("no current process set") + thread = self.lastEvent.get_thread() + elif self.lastEvent is not None and tid == self.lastEvent.get_tid(): + thread = self.lastEvent.get_thread() + else: + try: + thread = self.debug.system.get_thread(tid) + except KeyError: + raise CmdError("thread not found (%d)" % tid) + return thread + + # Read the process memory. + def read_memory(self, address, size, pid=None): + process = self.get_process(pid) + try: + data = process.peek(address, size) + except WindowsError: + orig_address = HexOutput.integer(address) + next_address = HexOutput.integer(address + size) + msg = "error reading process %d, from %s to %s (%d bytes)" + msg = msg % (pid, orig_address, next_address, size) + raise CmdError(msg) + return data + + # Write the process memory. + def write_memory(self, address, data, pid=None): + process = self.get_process(pid) + try: + process.write(address, data) + except WindowsError: + size = len(data) + orig_address = HexOutput.integer(address) + next_address = HexOutput.integer(address + size) + msg = "error reading process %d, from %s to %s (%d bytes)" + msg = msg % (pid, orig_address, next_address, size) + raise CmdError(msg) + + # Change a register value. + def change_register(self, register, value, tid=None): + + # Get the thread. + if tid is None: + if self.lastEvent is None: + raise CmdError("no current process set") + thread = self.lastEvent.get_thread() + else: + try: + thread = self.debug.system.get_thread(tid) + except KeyError: + raise CmdError("thread not found (%d)" % tid) + + # Convert the value to integer type. + try: + value = self.input_integer(value) + except ValueError: + pid = thread.get_pid() + value = self.input_address(value, pid, tid) + + # Suspend the thread. + # The finally clause ensures the thread is resumed before returning. + thread.suspend() + try: + + # Get the current context. + ctx = thread.get_context() + + # Register name matching is case insensitive. + register = register.lower() + + # Integer 32 bits registers. + if register in self.register_names: + register = register.title() # eax -> Eax + + # Segment (16 bit) registers. + if register in self.segment_names: + register = 'Seg%s' % register.title() # cs -> SegCs + value = value & 0x0000FFFF + + # Integer 16 bits registers. + if register in self.register_alias_16: + register = self.register_alias_16[register] + previous = ctx.get(register) & 0xFFFF0000 + value = (value & 0x0000FFFF) | previous + + # Integer 8 bits registers (low part). + if register in self.register_alias_8_low: + register = self.register_alias_8_low[register] + previous = ctx.get(register) % 0xFFFFFF00 + value = (value & 0x000000FF) | previous + + # Integer 8 bits registers (high part). + if register in self.register_alias_8_high: + register = self.register_alias_8_high[register] + previous = ctx.get(register) % 0xFFFF00FF + value = ((value & 0x000000FF) << 8) | previous + + # Set the new context. + ctx.__setitem__(register, value) + thread.set_context(ctx) + + # Resume the thread. + finally: + thread.resume() + + # Very crude way to find data within the process memory. + # TODO: Perhaps pfind.py can be integrated here instead. + def find_in_memory(self, query, process): + for mbi in process.get_memory_map(): + if mbi.State != win32.MEM_COMMIT or mbi.Protect & win32.PAGE_GUARD: + continue + address = mbi.BaseAddress + size = mbi.RegionSize + try: + data = process.read(address, size) + except WindowsError: + msg = "*** Warning: read error at address %s" + msg = msg % HexDump.address(address) + print(msg) + width = min(len(query), 16) + p = data.find(query) + while p >= 0: + q = p + len(query) + d = data[ p: min(q, p + width) ] + h = HexDump.hexline(d, width=width) + a = HexDump.address(address + p) + print("%s: %s" % (a, h)) + p = data.find(query, q) + + # Kill a process. + def kill_process(self, pid): + process = self.debug.system.get_process(pid) + try: + process.kill() + if self.debug.is_debugee(pid): + self.debug.detach(pid) + print("Killed process (%d)" % pid) + except Exception: + print("Error trying to kill process (%d)" % pid) + + # Kill a thread. + def kill_thread(self, tid): + thread = self.debug.system.get_thread(tid) + try: + thread.kill() + process = thread.get_process() + pid = process.get_pid() + if self.debug.is_debugee(pid) and not process.is_alive(): + self.debug.detach(pid) + print("Killed thread (%d)" % tid) + except Exception: + print("Error trying to kill thread (%d)" % tid) + +#------------------------------------------------------------------------------ +# Command prompt input + + # Prompt the user for commands. + def prompt_user(self): + while not self.debuggerExit: + try: + self.cmdloop() + break + except CmdError: + e = sys.exc_info()[1] + print("*** Error: %s" % str(e)) + except Exception: + traceback.print_exc() +# # self.debuggerExit = True + + # Prompt the user for a YES/NO kind of question. + def ask_user(self, msg, prompt="Are you sure? (y/N): "): + print(msg) + answer = raw_input(prompt) + answer = answer.strip()[:1].lower() + return answer == 'y' + + # Autocomplete the given command when not ambiguous. + # Convert it to lowercase (so commands are seen as case insensitive). + def autocomplete(self, cmd): + cmd = cmd.lower() + completed = self.completenames(cmd) + if len(completed) == 1: + cmd = completed[0] + return cmd + + # Get the help text for the given list of command methods. + # Note it's NOT a list of commands, but a list of actual method names. + # Each line of text is stripped and all lines are sorted. + # Repeated text lines are removed. + # Returns a single, possibly multiline, string. + def get_help(self, commands): + msg = set() + for name in commands: + if name != 'do_help': + try: + doc = getattr(self, name).__doc__.split('\n') + except Exception: + return ("No help available when Python" + " is run with the -OO switch.") + for x in doc: + x = x.strip() + if x: + msg.add(' %s' % x) + msg = list(msg) + msg.sort() + msg = '\n'.join(msg) + return msg + + # Parse the prefix and remove it from the command line. + def split_prefix(self, line): + prefix = None + if line.startswith('~'): + pos = line.find(' ') + if pos == 1: + pos = line.find(' ', pos + 1) + if not pos < 0: + prefix = line[ 1: pos ].strip() + line = line[ pos: ].strip() + return prefix, line + +#------------------------------------------------------------------------------ +# Cmd() hacks + + # Header for help page. + doc_header = 'Available commands (type help * or help )' + +# # # Read and write directly to stdin and stdout. +# # # This prevents the use of raw_input and print. +# # use_rawinput = False + + @property + def prompt(self): + if self.lastEvent: + pid = self.lastEvent.get_pid() + tid = self.lastEvent.get_tid() + if self.debug.is_debugee(pid): +# # return '~%d(%d)> ' % (tid, pid) + return '%d:%d> ' % (pid, tid) + return '> ' + + # Return a sorted list of method names. + # Only returns the methods that implement commands. + def get_names(self): + names = Cmd.get_names(self) + names = [ x for x in set(names) if x.startswith('do_') ] + names.sort() + return names + + # Automatically autocomplete commands, even if Tab wasn't pressed. + # The prefix is removed from the line and stored in self.cmdprefix. + # Also implement the commands that consist of a symbol character. + def parseline(self, line): + self.cmdprefix, line = self.split_prefix(line) + line = line.strip() + if line: + if line[0] == '.': + line = 'plugin ' + line[1:] + elif line[0] == '#': + line = 'python ' + line[1:] + cmd, arg, line = Cmd.parseline(self, line) + if cmd: + cmd = self.autocomplete(cmd) + return cmd, arg, line + +# # # Don't repeat the last executed command. +# # def emptyline(self): +# # pass + + # Reset the defaults for some commands. + def preloop(self): + self.default_disasm_target = 'eip' + self.default_display_target = 'eip' + self.last_display_command = self.do_db + + # Put the prefix back in the command line. + def get_lastcmd(self): + return self.__lastcmd + + def set_lastcmd(self, lastcmd): + if self.cmdprefix: + lastcmd = '~%s %s' % (self.cmdprefix, lastcmd) + self.__lastcmd = lastcmd + + lastcmd = property(get_lastcmd, set_lastcmd) + + # Quit the command prompt if the debuggerExit flag is on. + def postcmd(self, stop, line): + return stop or self.debuggerExit + +#------------------------------------------------------------------------------ +# Commands + + # Each command contains a docstring with it's help text. + # The help text consist of independent text lines, + # where each line shows a command and it's parameters. + # Each command method has the help message for itself and all it's aliases. + # Only the docstring for the "help" command is shown as-is. + + # NOTE: Command methods MUST be all lowercase! + + # Extended help command. + def do_help(self, arg): + """ + ? - show the list of available commands + ? * - show help for all commands + ? [command...] - show help for the given command(s) + help - show the list of available commands + help * - show help for all commands + help [command...] - show help for the given command(s) + """ + if not arg: + Cmd.do_help(self, arg) + elif arg in ('?', 'help'): + # An easter egg :) + print(" Help! I need somebody...") + print(" Help! Not just anybody...") + print(" Help! You know, I need someone...") + print(" Heeelp!") + else: + if arg == '*': + commands = self.get_names() + commands = [ x for x in commands if x.startswith('do_') ] + else: + commands = set() + for x in arg.split(' '): + x = x.strip() + if x: + for n in self.completenames(x): + commands.add('do_%s' % n) + commands = list(commands) + commands.sort() + print(self.get_help(commands)) + + def do_shell(self, arg): + """ + ! - spawn a system shell + shell - spawn a system shell + ! [arguments...] - execute a single shell command + shell [arguments...] - execute a single shell command + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + + # Try to use the environment to locate cmd.exe. + # If not found, it's usually OK to just use the filename, + # since cmd.exe is one of those "magic" programs that + # can be automatically found by CreateProcess. + shell = os.getenv('ComSpec', 'cmd.exe') + + # When given a command, run it and return. + # When no command is given, spawn a shell. + if arg: + arg = '%s /c %s' % (shell, arg) + else: + arg = shell + process = self.debug.system.start_process(arg, bConsole=True) + process.wait() + + # This hack fixes a bug in Python, the interpreter console is closing the + # stdin pipe when calling the exit() function (Ctrl+Z seems to work fine). + class _PythonExit(object): + + def __repr__(self): + return "Use exit() or Ctrl-Z plus Return to exit" + + def __call__(self): + raise SystemExit() + + _python_exit = _PythonExit() + + # Spawns a Python shell with some handy local variables and the winappdbg + # module already imported. Also the console banner is improved. + def _spawn_python_shell(self, arg): + import winappdbg + banner = ('Python %s on %s\nType "help", "copyright", ' + '"credits" or "license" for more information.\n') + platform = winappdbg.version.lower() + platform = 'WinAppDbg %s' % platform + banner = banner % (sys.version, platform) + local = {} + local.update(__builtins__) + local.update({ + '__name__': '__console__', + '__doc__': None, + 'exit': self._python_exit, + 'self': self, + 'arg': arg, + 'winappdbg': winappdbg, + }) + try: + code.interact(banner=banner, local=local) + except SystemExit: + # We need to catch it so it doesn't kill our program. + pass + + def do_python(self, arg): + """ + # - spawn a python interpreter + python - spawn a python interpreter + # - execute a single python statement + python - execute a single python statement + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + + # When given a Python statement, execute it directly. + if arg: + try: + compat.exec_(arg, globals(), locals()) + except Exception: + traceback.print_exc() + + # When no statement is given, spawn a Python interpreter. + else: + try: + self._spawn_python_shell(arg) + except Exception: + e = sys.exc_info()[1] + raise CmdError( + "unhandled exception when running Python console: %s" % e) + + def do_quit(self, arg): + """ + quit - close the debugging session + q - close the debugging session + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + if arg: + raise CmdError("too many arguments") + if self.confirm_quit: + count = self.debug.get_debugee_count() + if count > 0: + if count == 1: + msg = "There's a program still running." + else: + msg = "There are %s programs still running." % count + if not self.ask_user(msg): + return False + self.debuggerExit = True + return True + + do_q = do_quit + + def do_attach(self, arg): + """ + attach [target...] - attach to the given process(es) + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + targets = self.input_process_list(self.split_tokens(arg, 1)) + if not targets: + print("Error: missing parameters") + else: + debug = self.debug + for pid in targets: + try: + debug.attach(pid) + print("Attached to process (%d)" % pid) + except Exception: + print("Error: can't attach to process (%d)" % pid) + + def do_detach(self, arg): + """ + [~process] detach - detach from the current process + detach - detach from the current process + detach [target...] - detach from the given process(es) + """ + debug = self.debug + token_list = self.split_tokens(arg) + if self.cmdprefix: + token_list.insert(0, self.cmdprefix) + targets = self.input_process_list(token_list) + if not targets: + if self.lastEvent is None: + raise CmdError("no current process set") + targets = [ self.lastEvent.get_pid() ] + for pid in targets: + try: + debug.detach(pid) + print("Detached from process (%d)" % pid) + except Exception: + print("Error: can't detach from process (%d)" % pid) + + def do_windowed(self, arg): + """ + windowed [arguments...] - run a windowed program for debugging + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + cmdline = self.input_command_line(arg) + try: + process = self.debug.execl(arg, + bConsole=False, + bFollow=self.options.follow) + print("Spawned process (%d)" % process.get_pid()) + except Exception: + raise CmdError("can't execute") + self.set_fake_last_event(process) + + def do_console(self, arg): + """ + console [arguments...] - run a console program for debugging + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + cmdline = self.input_command_line(arg) + try: + process = self.debug.execl(arg, + bConsole=True, + bFollow=self.options.follow) + print("Spawned process (%d)" % process.get_pid()) + except Exception: + raise CmdError("can't execute") + self.set_fake_last_event(process) + + def do_continue(self, arg): + """ + continue - continue execution + g - continue execution + go - continue execution + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + if arg: + raise CmdError("too many arguments") + if self.debug.get_debugee_count() > 0: + return True + + do_g = do_continue + do_go = do_continue + + def do_gh(self, arg): + """ + gh - go with exception handled + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + if arg: + raise CmdError("too many arguments") + if self.lastEvent: + self.lastEvent.continueStatus = win32.DBG_EXCEPTION_HANDLED + return self.do_go(arg) + + def do_gn(self, arg): + """ + gn - go with exception not handled + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + if arg: + raise CmdError("too many arguments") + if self.lastEvent: + self.lastEvent.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED + return self.do_go(arg) + + def do_refresh(self, arg): + """ + refresh - refresh the list of running processes and threads + [~process] refresh - refresh the list of running threads + """ + if arg: + raise CmdError("too many arguments") + if self.cmdprefix: + process = self.get_process_from_prefix() + process.scan() + else: + self.debug.system.scan() + + def do_processlist(self, arg): + """ + pl - show the processes being debugged + processlist - show the processes being debugged + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + if arg: + raise CmdError("too many arguments") + system = self.debug.system + pid_list = self.debug.get_debugee_pids() + if pid_list: + print("Process ID File name") + for pid in pid_list: + if pid == 0: + filename = "System Idle Process" + elif pid == 4: + filename = "System" + else: + filename = system.get_process(pid).get_filename() + filename = PathOperations.pathname_to_filename(filename) + print("%-12d %s" % (pid, filename)) + + do_pl = do_processlist + + def do_threadlist(self, arg): + """ + tl - show the threads being debugged + threadlist - show the threads being debugged + """ + if arg: + raise CmdError("too many arguments") + if self.cmdprefix: + process = self.get_process_from_prefix() + for thread in process.iter_threads(): + tid = thread.get_tid() + name = thread.get_name() + print("%-12d %s" % (tid, name)) + else: + system = self.debug.system + pid_list = self.debug.get_debugee_pids() + if pid_list: + print("Thread ID Thread name") + for pid in pid_list: + process = system.get_process(pid) + for thread in process.iter_threads(): + tid = thread.get_tid() + name = thread.get_name() + print("%-12d %s" % (tid, name)) + + do_tl = do_threadlist + + def do_kill(self, arg): + """ + [~process] kill - kill a process + [~thread] kill - kill a thread + kill - kill the current process + kill * - kill all debugged processes + kill - kill the given processes and threads + """ + if arg: + if arg == '*': + target_pids = self.debug.get_debugee_pids() + target_tids = list() + else: + target_pids = set() + target_tids = set() + if self.cmdprefix: + pid, tid = self.get_process_and_thread_ids_from_prefix() + if tid is None: + target_tids.add(tid) + else: + target_pids.add(pid) + for token in self.split_tokens(arg): + try: + pid = self.input_process(token) + target_pids.add(pid) + except CmdError: + try: + tid = self.input_process(token) + target_pids.add(pid) + except CmdError: + msg = "unknown process or thread (%s)" % token + raise CmdError(msg) + target_pids = list(target_pids) + target_tids = list(target_tids) + target_pids.sort() + target_tids.sort() + msg = "You are about to kill %d processes and %d threads." + msg = msg % (len(target_pids), len(target_tids)) + if self.ask_user(msg): + for pid in target_pids: + self.kill_process(pid) + for tid in target_tids: + self.kill_thread(tid) + else: + if self.cmdprefix: + pid, tid = self.get_process_and_thread_ids_from_prefix() + if tid is None: + if self.lastEvent is not None and pid == self.lastEvent.get_pid(): + msg = "You are about to kill the current process." + else: + msg = "You are about to kill process %d." % pid + if self.ask_user(msg): + self.kill_process(pid) + else: + if self.lastEvent is not None and tid == self.lastEvent.get_tid(): + msg = "You are about to kill the current thread." + else: + msg = "You are about to kill thread %d." % tid + if self.ask_user(msg): + self.kill_thread(tid) + else: + if self.lastEvent is None: + raise CmdError("no current process set") + pid = self.lastEvent.get_pid() + if self.ask_user("You are about to kill the current process."): + self.kill_process(pid) + + # TODO: create hidden threads using undocumented API calls. + def do_modload(self, arg): + """ + [~process] modload - load a DLL module + """ + filename = self.split_tokens(arg, 1, 1)[0] + process = self.get_process_from_prefix() + try: + process.inject_dll(filename, bWait=False) + except RuntimeError: + print("Can't inject module: %r" % filename) + + # TODO: modunload + + def do_stack(self, arg): + """ + [~thread] k - show the stack trace + [~thread] stack - show the stack trace + """ + if arg: # XXX TODO add depth parameter + raise CmdError("too many arguments") + pid, tid = self.get_process_and_thread_ids_from_prefix() + process = self.get_process(pid) + thread = process.get_thread(tid) + try: + stack_trace = thread.get_stack_trace_with_labels() + if stack_trace: + print(CrashDump.dump_stack_trace_with_labels(stack_trace),) + else: + print("No stack trace available for thread (%d)" % tid) + except WindowsError: + print("Can't get stack trace for thread (%d)" % tid) + + do_k = do_stack + + def do_break(self, arg): + """ + break - force a debug break in all debugees + break [process...] - force a debug break + """ + debug = self.debug + system = debug.system + targets = self.input_process_list(self.split_tokens(arg)) + if not targets: + targets = debug.get_debugee_pids() + targets.sort() + if self.lastEvent: + current = self.lastEvent.get_pid() + else: + current = None + for pid in targets: + if pid != current and debug.is_debugee(pid): + process = system.get_process(pid) + try: + process.debug_break() + except WindowsError: + print("Can't force a debug break on process (%d)") + + def do_step(self, arg): + """ + p - step on the current assembly instruction + next - step on the current assembly instruction + step - step on the current assembly instruction + """ + if self.cmdprefix: + raise CmdError("prefix not allowed") + if self.lastEvent is None: + raise CmdError("no current process set") + if arg: # XXX this check is to be removed + raise CmdError("too many arguments") + pid = self.lastEvent.get_pid() + thread = self.lastEvent.get_thread() + pc = thread.get_pc() + code = thread.disassemble(pc, 16)[0] + size = code[1] + opcode = code[2].lower() + if ' ' in opcode: + opcode = opcode[: opcode.find(' ') ] + if opcode in self.jump_instructions or opcode in ('int', 'ret', 'retn'): + return self.do_trace(arg) + address = pc + size +# # print(hex(pc), hex(address), size # XXX DEBUG + self.debug.stalk_at(pid, address) + return True + + do_p = do_step + do_next = do_step + + def do_trace(self, arg): + """ + t - trace at the current assembly instruction + trace - trace at the current assembly instruction + """ + if arg: # XXX this check is to be removed + raise CmdError("too many arguments") + if self.lastEvent is None: + raise CmdError("no current thread set") + self.lastEvent.get_thread().set_tf() + return True + + do_t = do_trace + + def do_bp(self, arg): + """ + [~process] bp
- set a code breakpoint + """ + pid = self.get_process_id_from_prefix() + if not self.debug.is_debugee(pid): + raise CmdError("target process is not being debugged") + process = self.get_process(pid) + token_list = self.split_tokens(arg, 1, 1) + try: + address = self.input_address(token_list[0], pid) + deferred = False + except Exception: + address = token_list[0] + deferred = True + if not address: + address = token_list[0] + deferred = True + self.debug.break_at(pid, address) + if deferred: + print("Deferred breakpoint set at %s" % address) + else: + print("Breakpoint set at %s" % address) + + def do_ba(self, arg): + """ + [~thread] ba <1|2|4|8>
- set hardware breakpoint + """ + debug = self.debug + thread = self.get_thread_from_prefix() + pid = thread.get_pid() + tid = thread.get_tid() + if not debug.is_debugee(pid): + raise CmdError("target thread is not being debugged") + token_list = self.split_tokens(arg, 3, 3) + access = token_list[0].lower() + size = token_list[1] + address = token_list[2] + if access == 'a': + access = debug.BP_BREAK_ON_ACCESS + elif access == 'w': + access = debug.BP_BREAK_ON_WRITE + elif access == 'e': + access = debug.BP_BREAK_ON_EXECUTION + else: + raise CmdError("bad access type: %s" % token_list[0]) + if size == '1': + size = debug.BP_WATCH_BYTE + elif size == '2': + size = debug.BP_WATCH_WORD + elif size == '4': + size = debug.BP_WATCH_DWORD + elif size == '8': + size = debug.BP_WATCH_QWORD + else: + raise CmdError("bad breakpoint size: %s" % size) + thread = self.get_thread_from_prefix() + tid = thread.get_tid() + pid = thread.get_pid() + if not debug.is_debugee(pid): + raise CmdError("target process is not being debugged") + address = self.input_address(address, pid) + if debug.has_hardware_breakpoint(tid, address): + debug.erase_hardware_breakpoint(tid, address) + debug.define_hardware_breakpoint(tid, address, access, size) + debug.enable_hardware_breakpoint(tid, address) + + def do_bm(self, arg): + """ + [~process] bm - set memory breakpoint + """ + pid = self.get_process_id_from_prefix() + if not self.debug.is_debugee(pid): + raise CmdError("target process is not being debugged") + process = self.get_process(pid) + token_list = self.split_tokens(arg, 1, 2) + address, size = self.input_address_range(token_list[0], pid) + self.debug.watch_buffer(pid, address, size) + + def do_bl(self, arg): + """ + bl - list the breakpoints for the current process + bl * - list the breakpoints for all processes + [~process] bl - list the breakpoints for the given process + bl [process...] - list the breakpoints for each given process + """ + debug = self.debug + if arg == '*': + if self.cmdprefix: + raise CmdError("prefix not supported") + breakpoints = debug.get_debugee_pids() + else: + targets = self.input_process_list(self.split_tokens(arg)) + if self.cmdprefix: + targets.insert(0, self.input_process(self.cmdprefix)) + if not targets: + if self.lastEvent is None: + raise CmdError("no current process is set") + targets = [ self.lastEvent.get_pid() ] + for pid in targets: + bplist = debug.get_process_code_breakpoints(pid) + printed_process_banner = False + if bplist: + if not printed_process_banner: + print("Process %d:" % pid) + printed_process_banner = True + for bp in bplist: + address = repr(bp)[1:-1].replace('remote address ', '') + print(" %s" % address) + dbplist = debug.get_process_deferred_code_breakpoints(pid) + if dbplist: + if not printed_process_banner: + print("Process %d:" % pid) + printed_process_banner = True + for (label, action, oneshot) in dbplist: + if oneshot: + address = " Deferred unconditional one-shot" \ + " code breakpoint at %s" + else: + address = " Deferred unconditional" \ + " code breakpoint at %s" + address = address % label + print(" %s" % address) + bplist = debug.get_process_page_breakpoints(pid) + if bplist: + if not printed_process_banner: + print("Process %d:" % pid) + printed_process_banner = True + for bp in bplist: + address = repr(bp)[1:-1].replace('remote address ', '') + print(" %s" % address) + for tid in debug.system.get_process(pid).iter_thread_ids(): + bplist = debug.get_thread_hardware_breakpoints(tid) + if bplist: + print("Thread %d:" % tid) + for bp in bplist: + address = repr(bp)[1:-1].replace('remote address ', '') + print(" %s" % address) + + def do_bo(self, arg): + """ + [~process] bo
- make a code breakpoint one-shot + [~thread] bo
- make a hardware breakpoint one-shot + [~process] bo - make a memory breakpoint one-shot + [~process] bo
- make a memory breakpoint one-shot + """ + token_list = self.split_tokens(arg, 1, 2) + pid, tid, address, size = self.input_breakpoint(token_list) + debug = self.debug + found = False + if size is None: + if tid is not None: + if debug.has_hardware_breakpoint(tid, address): + debug.enable_one_shot_hardware_breakpoint(tid, address) + found = True + if pid is not None: + if debug.has_code_breakpoint(pid, address): + debug.enable_one_shot_code_breakpoint(pid, address) + found = True + else: + if debug.has_page_breakpoint(pid, address): + debug.enable_one_shot_page_breakpoint(pid, address) + found = True + if not found: + print("Error: breakpoint not found.") + + def do_be(self, arg): + """ + [~process] be
- enable a code breakpoint + [~thread] be
- enable a hardware breakpoint + [~process] be - enable a memory breakpoint + [~process] be
- enable a memory breakpoint + """ + token_list = self.split_tokens(arg, 1, 2) + pid, tid, address, size = self.input_breakpoint(token_list) + debug = self.debug + found = False + if size is None: + if tid is not None: + if debug.has_hardware_breakpoint(tid, address): + debug.enable_hardware_breakpoint(tid, address) + found = True + if pid is not None: + if debug.has_code_breakpoint(pid, address): + debug.enable_code_breakpoint(pid, address) + found = True + else: + if debug.has_page_breakpoint(pid, address): + debug.enable_page_breakpoint(pid, address) + found = True + if not found: + print("Error: breakpoint not found.") + + def do_bd(self, arg): + """ + [~process] bd
- disable a code breakpoint + [~thread] bd
- disable a hardware breakpoint + [~process] bd - disable a memory breakpoint + [~process] bd
- disable a memory breakpoint + """ + token_list = self.split_tokens(arg, 1, 2) + pid, tid, address, size = self.input_breakpoint(token_list) + debug = self.debug + found = False + if size is None: + if tid is not None: + if debug.has_hardware_breakpoint(tid, address): + debug.disable_hardware_breakpoint(tid, address) + found = True + if pid is not None: + if debug.has_code_breakpoint(pid, address): + debug.disable_code_breakpoint(pid, address) + found = True + else: + if debug.has_page_breakpoint(pid, address): + debug.disable_page_breakpoint(pid, address) + found = True + if not found: + print("Error: breakpoint not found.") + + def do_bc(self, arg): + """ + [~process] bc
- clear a code breakpoint + [~thread] bc
- clear a hardware breakpoint + [~process] bc - clear a memory breakpoint + [~process] bc
- clear a memory breakpoint + """ + token_list = self.split_tokens(arg, 1, 2) + pid, tid, address, size = self.input_breakpoint(token_list) + debug = self.debug + found = False + if size is None: + if tid is not None: + if debug.has_hardware_breakpoint(tid, address): + debug.dont_watch_variable(tid, address) + found = True + if pid is not None: + if debug.has_code_breakpoint(pid, address): + debug.dont_break_at(pid, address) + found = True + else: + if debug.has_page_breakpoint(pid, address): + debug.dont_watch_buffer(pid, address, size) + found = True + if not found: + print("Error: breakpoint not found.") + + def do_disassemble(self, arg): + """ + [~thread] u [register] - show code disassembly + [~process] u [address] - show code disassembly + [~thread] disassemble [register] - show code disassembly + [~process] disassemble [address] - show code disassembly + """ + if not arg: + arg = self.default_disasm_target + token_list = self.split_tokens(arg, 1, 1) + pid, tid = self.get_process_and_thread_ids_from_prefix() + process = self.get_process(pid) + address = self.input_address(token_list[0], pid, tid) + try: + code = process.disassemble(address, 15 * 8)[:8] + except Exception: + msg = "can't disassemble address %s" + msg = msg % HexDump.address(address) + raise CmdError(msg) + if code: + label = process.get_label_at_address(address) + last_code = code[-1] + next_address = last_code[0] + last_code[1] + next_address = HexOutput.integer(next_address) + self.default_disasm_target = next_address + print("%s:" % label) +# # print(CrashDump.dump_code(code)) + for line in code: + print(CrashDump.dump_code_line(line, bShowDump=False)) + + do_u = do_disassemble + + def do_search(self, arg): + """ + [~process] s [address-address] + [~process] search [address-address] + """ + token_list = self.split_tokens(arg, 1, 3) + pid, tid = self.get_process_and_thread_ids_from_prefix() + process = self.get_process(pid) + if len(token_list) == 1: + pattern = token_list[0] + minAddr = None + maxAddr = None + else: + pattern = token_list[-1] + addr, size = self.input_address_range(token_list[:-1], pid, tid) + minAddr = addr + maxAddr = addr + size + iter = process.search_bytes(pattern) + if process.get_bits() == 32: + addr_width = 8 + else: + addr_width = 16 + # TODO: need a prettier output here! + for addr in iter: + print(HexDump.address(addr, addr_width)) + + do_s = do_search + + def do_searchhex(self, arg): + """ + [~process] sh [address-address] + [~process] searchhex [address-address] + """ + token_list = self.split_tokens(arg, 1, 3) + pid, tid = self.get_process_and_thread_ids_from_prefix() + process = self.get_process(pid) + if len(token_list) == 1: + pattern = token_list[0] + minAddr = None + maxAddr = None + else: + pattern = token_list[-1] + addr, size = self.input_address_range(token_list[:-1], pid, tid) + minAddr = addr + maxAddr = addr + size + iter = process.search_hexa(pattern) + if process.get_bits() == 32: + addr_width = 8 + else: + addr_width = 16 + for addr, bytes in iter: + print(HexDump.hexblock(bytes, addr, addr_width),) + + do_sh = do_searchhex + +# # def do_strings(self, arg): +# # """ +# # [~process] strings - extract ASCII strings from memory +# # """ +# # if arg: +# # raise CmdError("too many arguments") +# # pid, tid = self.get_process_and_thread_ids_from_prefix() +# # process = self.get_process(pid) +# # for addr, size, data in process.strings(): +# # print("%s: %r" % (HexDump.address(addr), data) + + def do_d(self, arg): + """ + [~thread] d - show memory contents + [~thread] d - show memory contents + [~thread] d - show memory contents + [~process] d
- show memory contents + [~process] d - show memory contents + [~process] d
- show memory contents + """ + return self.last_display_command(arg) + + def do_db(self, arg): + """ + [~thread] db - show memory contents as bytes + [~thread] db - show memory contents as bytes + [~thread] db - show memory contents as bytes + [~process] db
- show memory contents as bytes + [~process] db - show memory contents as bytes + [~process] db
- show memory contents as bytes + """ + self.print_memory_display(arg, HexDump.hexblock) + self.last_display_command = self.do_db + + def do_dw(self, arg): + """ + [~thread] dw - show memory contents as words + [~thread] dw - show memory contents as words + [~thread] dw - show memory contents as words + [~process] dw
- show memory contents as words + [~process] dw - show memory contents as words + [~process] dw
- show memory contents as words + """ + self.print_memory_display(arg, HexDump.hexblock_word) + self.last_display_command = self.do_dw + + def do_dd(self, arg): + """ + [~thread] dd - show memory contents as dwords + [~thread] dd - show memory contents as dwords + [~thread] dd - show memory contents as dwords + [~process] dd
- show memory contents as dwords + [~process] dd - show memory contents as dwords + [~process] dd
- show memory contents as dwords + """ + self.print_memory_display(arg, HexDump.hexblock_dword) + self.last_display_command = self.do_dd + + def do_dq(self, arg): + """ + [~thread] dq - show memory contents as qwords + [~thread] dq - show memory contents as qwords + [~thread] dq - show memory contents as qwords + [~process] dq
- show memory contents as qwords + [~process] dq - show memory contents as qwords + [~process] dq
- show memory contents as qwords + """ + self.print_memory_display(arg, HexDump.hexblock_qword) + self.last_display_command = self.do_dq + + # XXX TODO + # Change the way the default is used with ds and du + + def do_ds(self, arg): + """ + [~thread] ds - show memory contents as ANSI string + [~process] ds
- show memory contents as ANSI string + """ + if not arg: + arg = self.default_display_target + token_list = self.split_tokens(arg, 1, 1) + pid, tid, address, size = self.input_display(token_list, 256) + process = self.get_process(pid) + data = process.peek_string(address, False, size) + if data: + print(repr(data)) + self.last_display_command = self.do_ds + + def do_du(self, arg): + """ + [~thread] du - show memory contents as Unicode string + [~process] du
- show memory contents as Unicode string + """ + if not arg: + arg = self.default_display_target + token_list = self.split_tokens(arg, 1, 2) + pid, tid, address, size = self.input_display(token_list, 256) + process = self.get_process(pid) + data = process.peek_string(address, True, size) + if data: + print(repr(data)) + self.last_display_command = self.do_du + + def do_register(self, arg): + """ + [~thread] r - print(the value of all registers + [~thread] r - print(the value of a register + [~thread] r = - change the value of a register + [~thread] register - print(the value of all registers + [~thread] register - print(the value of a register + [~thread] register = - change the value of a register + """ + arg = arg.strip() + if not arg: + self.print_current_location() + else: + equ = arg.find('=') + if equ >= 0: + register = arg[:equ].strip() + value = arg[equ + 1:].strip() + if not value: + value = '0' + self.change_register(register, value) + else: + value = self.input_register(arg) + if value is None: + raise CmdError("unknown register: %s" % arg) + try: + label = None + thread = self.get_thread_from_prefix() + process = thread.get_process() + module = process.get_module_at_address(value) + if module: + label = module.get_label_at_address(value) + except RuntimeError: + label = None + reg = arg.upper() + val = HexDump.address(value) + if label: + print("%s: %s (%s)" % (reg, val, label)) + else: + print("%s: %s" % (reg, val)) + + do_r = do_register + + def do_eb(self, arg): + """ + [~process] eb
- write the data to the specified address + """ + # TODO + # data parameter should be optional, use a child Cmd here + pid = self.get_process_id_from_prefix() + token_list = self.split_tokens(arg, 2) + address = self.input_address(token_list[0], pid) + data = HexInput.hexadecimal(' '.join(token_list[1:])) + self.write_memory(address, data, pid) + + # XXX TODO + # add ew, ed and eq here + + def do_find(self, arg): + """ + [~process] f - find the string in the process memory + [~process] find - find the string in the process memory + """ + if not arg: + raise CmdError("missing parameter: string") + process = self.get_process_from_prefix() + self.find_in_memory(arg, process) + + do_f = do_find + + def do_memory(self, arg): + """ + [~process] m - show the process memory map + [~process] memory - show the process memory map + """ + if arg: # TODO: take min and max addresses + raise CmdError("too many arguments") + process = self.get_process_from_prefix() + try: + memoryMap = process.get_memory_map() + mappedFilenames = process.get_mapped_filenames() + print('') + print(CrashDump.dump_memory_map(memoryMap, mappedFilenames)) + except WindowsError: + msg = "can't get memory information for process (%d)" + raise CmdError(msg % process.get_pid()) + + do_m = do_memory + +#------------------------------------------------------------------------------ +# Event handling + +# TODO +# * add configurable stop/don't stop behavior on events and exceptions + + # Stop for all events, unless stated otherwise. + def event(self, event): + self.print_event(event) + self.prompt_user() + + # Stop for all exceptions, unless stated otherwise. + def exception(self, event): + self.print_exception(event) + self.prompt_user() + + # Stop for breakpoint exceptions. + def breakpoint(self, event): + if hasattr(event, 'breakpoint') and event.breakpoint: + self.print_breakpoint_location(event) + else: + self.print_exception(event) + self.prompt_user() + + # Stop for WOW64 breakpoint exceptions. + def wow64_breakpoint(self, event): + self.print_exception(event) + self.prompt_user() + + # Stop for single step exceptions. + def single_step(self, event): + if event.debug.is_tracing(event.get_tid()): + self.print_breakpoint_location(event) + else: + self.print_exception(event) + self.prompt_user() + + # Don't stop for C++ exceptions. + def ms_vc_exception(self, event): + self.print_exception(event) + event.continueStatus = win32.DBG_CONTINUE + + # Don't stop for process start. + def create_process(self, event): + self.print_process_start(event) + self.print_thread_start(event) + self.print_module_load(event) + + # Don't stop for process exit. + def exit_process(self, event): + self.print_process_end(event) + + # Don't stop for thread creation. + def create_thread(self, event): + self.print_thread_start(event) + + # Don't stop for thread exit. + def exit_thread(self, event): + self.print_thread_end(event) + + # Don't stop for DLL load. + def load_dll(self, event): + self.print_module_load(event) + + # Don't stop for DLL unload. + def unload_dll(self, event): + self.print_module_unload(event) + + # Don't stop for debug strings. + def output_string(self, event): + self.print_debug_string(event) + +#------------------------------------------------------------------------------ +# History file + + def load_history(self): + global readline + if readline is None: + try: + import readline + except ImportError: + return + if self.history_file_full_path is None: + folder = os.environ.get('USERPROFILE', '') + if not folder: + folder = os.environ.get('HOME', '') + if not folder: + folder = os.path.split(sys.argv[0])[1] + if not folder: + folder = os.path.curdir + self.history_file_full_path = os.path.join(folder, + self.history_file) + try: + if os.path.exists(self.history_file_full_path): + readline.read_history_file(self.history_file_full_path) + except IOError: + e = sys.exc_info()[1] + warnings.warn("Cannot load history file, reason: %s" % str(e)) + + def save_history(self): + if self.history_file_full_path is not None: + global readline + if readline is None: + try: + import readline + except ImportError: + return + try: + readline.write_history_file(self.history_file_full_path) + except IOError: + e = sys.exc_info()[1] + warnings.warn("Cannot save history file, reason: %s" % str(e)) + +#------------------------------------------------------------------------------ +# Main loop + + # Debugging loop. + def loop(self): + self.debuggerExit = False + debug = self.debug + + # Stop on the initial event, if any. + if self.lastEvent is not None: + self.cmdqueue.append('r') + self.prompt_user() + + # Loop until the debugger is told to quit. + while not self.debuggerExit: + + try: + + # If for some reason the last event wasn't continued, + # continue it here. This won't be done more than once + # for a given Event instance, though. + try: + debug.cont() + # On error, show the command prompt. + except Exception: + traceback.print_exc() + self.prompt_user() + + # While debugees are attached, handle debug events. + # Some debug events may cause the command prompt to be shown. + if self.debug.get_debugee_count() > 0: + try: + + # Get the next debug event. + debug.wait() + + # Dispatch the debug event. + try: + debug.dispatch() + + # Continue the debug event. + finally: + debug.cont() + + # On error, show the command prompt. + except Exception: + traceback.print_exc() + self.prompt_user() + + # While no debugees are attached, show the command prompt. + else: + self.prompt_user() + + # When the user presses Ctrl-C send a debug break to all debugees. + except KeyboardInterrupt: + success = False + try: + print("*** User requested debug break") + system = debug.system + for pid in debug.get_debugee_pids(): + try: + system.get_process(pid).debug_break() + success = True + except: + traceback.print_exc() + except: + traceback.print_exc() + if not success: + raise # This should never happen! diff --git a/pydevd_attach_to_process/winappdbg/module.py b/pydevd_attach_to_process/winappdbg/module.py new file mode 100644 index 0000000..6ae0183 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/module.py @@ -0,0 +1,2016 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Module instrumentation. + +@group Instrumentation: + Module + +@group Warnings: + DebugSymbolsWarning +""" + +from __future__ import with_statement + +__revision__ = "$Id$" + +__all__ = ['Module', 'DebugSymbolsWarning'] + +import sys +from winappdbg import win32 +from winappdbg import compat +from winappdbg.textio import HexInput, HexDump +from winappdbg.util import PathOperations + +# delayed imports +Process = None + +import os +import warnings +import traceback + +#============================================================================== + +class DebugSymbolsWarning (UserWarning): + """ + This warning is issued if the support for debug symbols + isn't working properly. + """ + +#============================================================================== + +class Module (object): + """ + Interface to a DLL library loaded in the context of another process. + + @group Properties: + get_base, get_filename, get_name, get_size, get_entry_point, + get_process, set_process, get_pid, + get_handle, set_handle, open_handle, close_handle + + @group Labels: + get_label, get_label_at_address, is_address_here, + resolve, resolve_label, match_name + + @group Symbols: + load_symbols, unload_symbols, get_symbols, iter_symbols, + resolve_symbol, get_symbol_at_address + + @group Modules snapshot: + clear + + @type unknown: str + @cvar unknown: Suggested tag for unknown modules. + + @type lpBaseOfDll: int + @ivar lpBaseOfDll: Base of DLL module. + Use L{get_base} instead. + + @type hFile: L{FileHandle} + @ivar hFile: Handle to the module file. + Use L{get_handle} instead. + + @type fileName: str + @ivar fileName: Module filename. + Use L{get_filename} instead. + + @type SizeOfImage: int + @ivar SizeOfImage: Size of the module. + Use L{get_size} instead. + + @type EntryPoint: int + @ivar EntryPoint: Entry point of the module. + Use L{get_entry_point} instead. + + @type process: L{Process} + @ivar process: Process where the module is loaded. + Use the L{get_process} method instead. + """ + + unknown = '' + + class _SymbolEnumerator (object): + """ + Internally used by L{Module} to enumerate symbols in a module. + """ + + def __init__(self, undecorate = False): + self.symbols = list() + self.undecorate = undecorate + + def __call__(self, SymbolName, SymbolAddress, SymbolSize, UserContext): + """ + Callback that receives symbols and stores them in a Python list. + """ + if self.undecorate: + try: + SymbolName = win32.UnDecorateSymbolName(SymbolName) + except Exception: + pass # not all symbols are decorated! + self.symbols.append( (SymbolName, SymbolAddress, SymbolSize) ) + return win32.TRUE + + def __init__(self, lpBaseOfDll, hFile = None, fileName = None, + SizeOfImage = None, + EntryPoint = None, + process = None): + """ + @type lpBaseOfDll: str + @param lpBaseOfDll: Base address of the module. + + @type hFile: L{FileHandle} + @param hFile: (Optional) Handle to the module file. + + @type fileName: str + @param fileName: (Optional) Module filename. + + @type SizeOfImage: int + @param SizeOfImage: (Optional) Size of the module. + + @type EntryPoint: int + @param EntryPoint: (Optional) Entry point of the module. + + @type process: L{Process} + @param process: (Optional) Process where the module is loaded. + """ + self.lpBaseOfDll = lpBaseOfDll + self.fileName = fileName + self.SizeOfImage = SizeOfImage + self.EntryPoint = EntryPoint + + self.__symbols = list() + + self.set_handle(hFile) + self.set_process(process) + + # Not really sure if it's a good idea... +## def __eq__(self, aModule): +## """ +## Compare two Module objects. The comparison is made using the process +## IDs and the module bases. +## +## @type aModule: L{Module} +## @param aModule: Another Module object. +## +## @rtype: bool +## @return: C{True} if the two process IDs and module bases are equal, +## C{False} otherwise. +## """ +## return isinstance(aModule, Module) and \ +## self.get_pid() == aModule.get_pid() and \ +## self.get_base() == aModule.get_base() + + def get_handle(self): + """ + @rtype: L{Handle} + @return: File handle. + Returns C{None} if unknown. + """ + # no way to guess! + return self.__hFile + + def set_handle(self, hFile): + """ + @type hFile: L{Handle} + @param hFile: File handle. Use C{None} to clear. + """ + if hFile == win32.INVALID_HANDLE_VALUE: + hFile = None + self.__hFile = hFile + + hFile = property(get_handle, set_handle, doc="") + + def get_process(self): + """ + @rtype: L{Process} + @return: Parent Process object. + Returns C{None} if unknown. + """ + # no way to guess! + return self.__process + + def set_process(self, process = None): + """ + Manually set the parent process. Use with care! + + @type process: L{Process} + @param process: (Optional) Process object. Use C{None} for no process. + """ + if process is None: + self.__process = None + else: + global Process # delayed import + if Process is None: + from winappdbg.process import Process + if not isinstance(process, Process): + msg = "Parent process must be a Process instance, " + msg += "got %s instead" % type(process) + raise TypeError(msg) + self.__process = process + + process = property(get_process, set_process, doc="") + + def get_pid(self): + """ + @rtype: int or None + @return: Parent process global ID. + Returns C{None} on error. + """ + process = self.get_process() + if process is not None: + return process.get_pid() + + def get_base(self): + """ + @rtype: int or None + @return: Base address of the module. + Returns C{None} if unknown. + """ + return self.lpBaseOfDll + + def get_size(self): + """ + @rtype: int or None + @return: Base size of the module. + Returns C{None} if unknown. + """ + if not self.SizeOfImage: + self.__get_size_and_entry_point() + return self.SizeOfImage + + def get_entry_point(self): + """ + @rtype: int or None + @return: Entry point of the module. + Returns C{None} if unknown. + """ + if not self.EntryPoint: + self.__get_size_and_entry_point() + return self.EntryPoint + + def __get_size_and_entry_point(self): + "Get the size and entry point of the module using the Win32 API." + process = self.get_process() + if process: + try: + handle = process.get_handle( win32.PROCESS_VM_READ | + win32.PROCESS_QUERY_INFORMATION ) + base = self.get_base() + mi = win32.GetModuleInformation(handle, base) + self.SizeOfImage = mi.SizeOfImage + self.EntryPoint = mi.EntryPoint + except WindowsError: + e = sys.exc_info()[1] + warnings.warn( + "Cannot get size and entry point of module %s, reason: %s"\ + % (self.get_name(), e.strerror), RuntimeWarning) + + def get_filename(self): + """ + @rtype: str or None + @return: Module filename. + Returns C{None} if unknown. + """ + if self.fileName is None: + if self.hFile not in (None, win32.INVALID_HANDLE_VALUE): + fileName = self.hFile.get_filename() + if fileName: + fileName = PathOperations.native_to_win32_pathname(fileName) + self.fileName = fileName + return self.fileName + + def __filename_to_modname(self, pathname): + """ + @type pathname: str + @param pathname: Pathname to a module. + + @rtype: str + @return: Module name. + """ + filename = PathOperations.pathname_to_filename(pathname) + if filename: + filename = filename.lower() + filepart, extpart = PathOperations.split_extension(filename) + if filepart and extpart: + modName = filepart + else: + modName = filename + else: + modName = pathname + return modName + + def get_name(self): + """ + @rtype: str + @return: Module name, as used in labels. + + @warning: Names are B{NOT} guaranteed to be unique. + + If you need unique identification for a loaded module, + use the base address instead. + + @see: L{get_label} + """ + pathname = self.get_filename() + if pathname: + modName = self.__filename_to_modname(pathname) + if isinstance(modName, compat.unicode): + try: + modName = modName.encode('cp1252') + except UnicodeEncodeError: + e = sys.exc_info()[1] + warnings.warn(str(e)) + else: + modName = "0x%x" % self.get_base() + return modName + + def match_name(self, name): + """ + @rtype: bool + @return: + C{True} if the given name could refer to this module. + It may not be exactly the same returned by L{get_name}. + """ + + # If the given name is exactly our name, return True. + # Comparison is case insensitive. + my_name = self.get_name().lower() + if name.lower() == my_name: + return True + + # If the given name is a base address, compare it with ours. + try: + base = HexInput.integer(name) + except ValueError: + base = None + if base is not None and base == self.get_base(): + return True + + # If the given name is a filename, convert it to a module name. + # Then compare it with ours, case insensitive. + modName = self.__filename_to_modname(name) + if modName.lower() == my_name: + return True + + # No match. + return False + +#------------------------------------------------------------------------------ + + def open_handle(self): + """ + Opens a new handle to the module. + + The new handle is stored in the L{hFile} property. + """ + + if not self.get_filename(): + msg = "Cannot retrieve filename for module at %s" + msg = msg % HexDump.address( self.get_base() ) + raise Exception(msg) + + hFile = win32.CreateFile(self.get_filename(), + dwShareMode = win32.FILE_SHARE_READ, + dwCreationDisposition = win32.OPEN_EXISTING) + + # In case hFile was set to an actual handle value instead of a Handle + # object. This shouldn't happen unless the user tinkered with hFile. + if not hasattr(self.hFile, '__del__'): + self.close_handle() + + self.hFile = hFile + + def close_handle(self): + """ + Closes the handle to the module. + + @note: Normally you don't need to call this method. All handles + created by I{WinAppDbg} are automatically closed when the garbage + collector claims them. So unless you've been tinkering with it, + setting L{hFile} to C{None} should be enough. + """ + try: + if hasattr(self.hFile, 'close'): + self.hFile.close() + elif self.hFile not in (None, win32.INVALID_HANDLE_VALUE): + win32.CloseHandle(self.hFile) + finally: + self.hFile = None + + def get_handle(self): + """ + @rtype: L{FileHandle} + @return: Handle to the module file. + """ + if self.hFile in (None, win32.INVALID_HANDLE_VALUE): + self.open_handle() + return self.hFile + + def clear(self): + """ + Clears the resources held by this object. + """ + try: + self.set_process(None) + finally: + self.close_handle() + +#------------------------------------------------------------------------------ + + # XXX FIXME + # I've been told sometimes the debugging symbols APIs don't correctly + # handle redirected exports (for example ws2_32!recv). + # I haven't been able to reproduce the bug yet. + def load_symbols(self): + """ + Loads the debugging symbols for a module. + Automatically called by L{get_symbols}. + """ + if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA: + dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION + else: + dwAccess = win32.PROCESS_QUERY_INFORMATION + hProcess = self.get_process().get_handle(dwAccess) + hFile = self.hFile + BaseOfDll = self.get_base() + SizeOfDll = self.get_size() + Enumerator = self._SymbolEnumerator() + try: + win32.SymInitialize(hProcess) + SymOptions = win32.SymGetOptions() + SymOptions |= ( + win32.SYMOPT_ALLOW_ZERO_ADDRESS | + win32.SYMOPT_CASE_INSENSITIVE | + win32.SYMOPT_FAVOR_COMPRESSED | + win32.SYMOPT_INCLUDE_32BIT_MODULES | + win32.SYMOPT_UNDNAME + ) + SymOptions &= ~( + win32.SYMOPT_LOAD_LINES | + win32.SYMOPT_NO_IMAGE_SEARCH | + win32.SYMOPT_NO_CPP | + win32.SYMOPT_IGNORE_NT_SYMPATH + ) + win32.SymSetOptions(SymOptions) + try: + win32.SymSetOptions( + SymOptions | win32.SYMOPT_ALLOW_ABSOLUTE_SYMBOLS) + except WindowsError: + pass + try: + try: + success = win32.SymLoadModule64( + hProcess, hFile, None, None, BaseOfDll, SizeOfDll) + except WindowsError: + success = 0 + if not success: + ImageName = self.get_filename() + success = win32.SymLoadModule64( + hProcess, None, ImageName, None, BaseOfDll, SizeOfDll) + if success: + try: + win32.SymEnumerateSymbols64( + hProcess, BaseOfDll, Enumerator) + finally: + win32.SymUnloadModule64(hProcess, BaseOfDll) + finally: + win32.SymCleanup(hProcess) + except WindowsError: + e = sys.exc_info()[1] + msg = "Cannot load debug symbols for process ID %d, reason:\n%s" + msg = msg % (self.get_pid(), traceback.format_exc(e)) + warnings.warn(msg, DebugSymbolsWarning) + self.__symbols = Enumerator.symbols + + def unload_symbols(self): + """ + Unloads the debugging symbols for a module. + """ + self.__symbols = list() + + def get_symbols(self): + """ + Returns the debugging symbols for a module. + The symbols are automatically loaded when needed. + + @rtype: list of tuple( str, int, int ) + @return: List of symbols. + Each symbol is represented by a tuple that contains: + - Symbol name + - Symbol memory address + - Symbol size in bytes + """ + if not self.__symbols: + self.load_symbols() + return list(self.__symbols) + + def iter_symbols(self): + """ + Returns an iterator for the debugging symbols in a module, + in no particular order. + The symbols are automatically loaded when needed. + + @rtype: iterator of tuple( str, int, int ) + @return: Iterator of symbols. + Each symbol is represented by a tuple that contains: + - Symbol name + - Symbol memory address + - Symbol size in bytes + """ + if not self.__symbols: + self.load_symbols() + return self.__symbols.__iter__() + + def resolve_symbol(self, symbol, bCaseSensitive = False): + """ + Resolves a debugging symbol's address. + + @type symbol: str + @param symbol: Name of the symbol to resolve. + + @type bCaseSensitive: bool + @param bCaseSensitive: C{True} for case sensitive matches, + C{False} for case insensitive. + + @rtype: int or None + @return: Memory address of symbol. C{None} if not found. + """ + if bCaseSensitive: + for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols(): + if symbol == SymbolName: + return SymbolAddress + for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols(): + try: + SymbolName = win32.UnDecorateSymbolName(SymbolName) + except Exception: + continue + if symbol == SymbolName: + return SymbolAddress + else: + symbol = symbol.lower() + for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols(): + if symbol == SymbolName.lower(): + return SymbolAddress + for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols(): + try: + SymbolName = win32.UnDecorateSymbolName(SymbolName) + except Exception: + continue + if symbol == SymbolName.lower(): + return SymbolAddress + + def get_symbol_at_address(self, address): + """ + Tries to find the closest matching symbol for the given address. + + @type address: int + @param address: Memory address to query. + + @rtype: None or tuple( str, int, int ) + @return: Returns a tuple consisting of: + - Name + - Address + - Size (in bytes) + Returns C{None} if no symbol could be matched. + """ + found = None + for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols(): + if SymbolAddress > address: + continue + if SymbolAddress + SymbolSize > address: + if not found or found[1] < SymbolAddress: + found = (SymbolName, SymbolAddress, SymbolSize) + return found + +#------------------------------------------------------------------------------ + + def get_label(self, function = None, offset = None): + """ + Retrieves the label for the given function of this module or the module + base address if no function name is given. + + @type function: str + @param function: (Optional) Exported function name. + + @type offset: int + @param offset: (Optional) Offset from the module base address. + + @rtype: str + @return: Label for the module base address, plus the offset if given. + """ + return _ModuleContainer.parse_label(self.get_name(), function, offset) + + def get_label_at_address(self, address, offset = None): + """ + Creates a label from the given memory address. + + If the address belongs to the module, the label is made relative to + it's base address. + + @type address: int + @param address: Memory address. + + @type offset: None or int + @param offset: (Optional) Offset value. + + @rtype: str + @return: Label pointing to the given address. + """ + + # Add the offset to the address. + if offset: + address = address + offset + + # Make the label relative to the base address if no match is found. + module = self.get_name() + function = None + offset = address - self.get_base() + + # Make the label relative to the entrypoint if no other match is found. + # Skip if the entry point is unknown. + start = self.get_entry_point() + if start and start <= address: + function = "start" + offset = address - start + + # Enumerate exported functions and debug symbols, + # then find the closest match, if possible. + try: + symbol = self.get_symbol_at_address(address) + if symbol: + (SymbolName, SymbolAddress, SymbolSize) = symbol + new_offset = address - SymbolAddress + if new_offset <= offset: + function = SymbolName + offset = new_offset + except WindowsError: + pass + + # Parse the label and return it. + return _ModuleContainer.parse_label(module, function, offset) + + def is_address_here(self, address): + """ + Tries to determine if the given address belongs to this module. + + @type address: int + @param address: Memory address. + + @rtype: bool or None + @return: C{True} if the address belongs to the module, + C{False} if it doesn't, + and C{None} if it can't be determined. + """ + base = self.get_base() + size = self.get_size() + if base and size: + return base <= address < (base + size) + return None + + def resolve(self, function): + """ + Resolves a function exported by this module. + + @type function: str or int + @param function: + str: Name of the function. + int: Ordinal of the function. + + @rtype: int + @return: Memory address of the exported function in the process. + Returns None on error. + """ + + # Unknown DLL filename, there's nothing we can do. + filename = self.get_filename() + if not filename: + return None + + # If the DLL is already mapped locally, resolve the function. + try: + hlib = win32.GetModuleHandle(filename) + address = win32.GetProcAddress(hlib, function) + except WindowsError: + + # Load the DLL locally, resolve the function and unload it. + try: + hlib = win32.LoadLibraryEx(filename, + win32.DONT_RESOLVE_DLL_REFERENCES) + try: + address = win32.GetProcAddress(hlib, function) + finally: + win32.FreeLibrary(hlib) + except WindowsError: + return None + + # A NULL pointer means the function was not found. + if address in (None, 0): + return None + + # Compensate for DLL base relocations locally and remotely. + return address - hlib + self.lpBaseOfDll + + def resolve_label(self, label): + """ + Resolves a label for this module only. If the label refers to another + module, an exception is raised. + + @type label: str + @param label: Label to resolve. + + @rtype: int + @return: Memory address pointed to by the label. + + @raise ValueError: The label is malformed or impossible to resolve. + @raise RuntimeError: Cannot resolve the module or function. + """ + + # Split the label into it's components. + # Use the fuzzy mode whenever possible. + aProcess = self.get_process() + if aProcess is not None: + (module, procedure, offset) = aProcess.split_label(label) + else: + (module, procedure, offset) = _ModuleContainer.split_label(label) + + # If a module name is given that doesn't match ours, + # raise an exception. + if module and not self.match_name(module): + raise RuntimeError("Label does not belong to this module") + + # Resolve the procedure if given. + if procedure: + address = self.resolve(procedure) + if address is None: + + # If it's a debug symbol, use the symbol. + address = self.resolve_symbol(procedure) + + # If it's the keyword "start" use the entry point. + if address is None and procedure == "start": + address = self.get_entry_point() + + # The procedure was not found. + if address is None: + if not module: + module = self.get_name() + msg = "Can't find procedure %s in module %s" + raise RuntimeError(msg % (procedure, module)) + + # If no procedure is given use the base address of the module. + else: + address = self.get_base() + + # Add the offset if given and return the resolved address. + if offset: + address = address + offset + return address + +#============================================================================== + +# TODO +# An alternative approach to the toolhelp32 snapshots: parsing the PEB and +# fetching the list of loaded modules from there. That would solve the problem +# of toolhelp32 not working when the process hasn't finished initializing. +# See: http://pferrie.host22.com/misc/lowlevel3.htm + +class _ModuleContainer (object): + """ + Encapsulates the capability to contain Module objects. + + @note: Labels are an approximated way of referencing memory locations + across different executions of the same process, or different processes + with common modules. They are not meant to be perfectly unique, and + some errors may occur when multiple modules with the same name are + loaded, or when module filenames can't be retrieved. + + @group Modules snapshot: + scan_modules, + get_module, get_module_bases, get_module_count, + get_module_at_address, get_module_by_name, + has_module, iter_modules, iter_module_addresses, + clear_modules + + @group Labels: + parse_label, split_label, sanitize_label, resolve_label, + resolve_label_components, get_label_at_address, split_label_strict, + split_label_fuzzy + + @group Symbols: + load_symbols, unload_symbols, get_symbols, iter_symbols, + resolve_symbol, get_symbol_at_address + + @group Debugging: + is_system_defined_breakpoint, get_system_breakpoint, + get_user_breakpoint, get_breakin_breakpoint, + get_wow64_system_breakpoint, get_wow64_user_breakpoint, + get_wow64_breakin_breakpoint, get_break_on_error_ptr + """ + + def __init__(self): + self.__moduleDict = dict() + self.__system_breakpoints = dict() + + # Replace split_label with the fuzzy version on object instances. + self.split_label = self.__use_fuzzy_mode + + def __initialize_snapshot(self): + """ + Private method to automatically initialize the snapshot + when you try to use it without calling any of the scan_* + methods first. You don't need to call this yourself. + """ + if not self.__moduleDict: + try: + self.scan_modules() + except WindowsError: + pass + + def __contains__(self, anObject): + """ + @type anObject: L{Module}, int + @param anObject: + - C{Module}: Module object to look for. + - C{int}: Base address of the DLL to look for. + + @rtype: bool + @return: C{True} if the snapshot contains + a L{Module} object with the same base address. + """ + if isinstance(anObject, Module): + anObject = anObject.lpBaseOfDll + return self.has_module(anObject) + + def __iter__(self): + """ + @see: L{iter_modules} + @rtype: dictionary-valueiterator + @return: Iterator of L{Module} objects in this snapshot. + """ + return self.iter_modules() + + def __len__(self): + """ + @see: L{get_module_count} + @rtype: int + @return: Count of L{Module} objects in this snapshot. + """ + return self.get_module_count() + + def has_module(self, lpBaseOfDll): + """ + @type lpBaseOfDll: int + @param lpBaseOfDll: Base address of the DLL to look for. + + @rtype: bool + @return: C{True} if the snapshot contains a + L{Module} object with the given base address. + """ + self.__initialize_snapshot() + return lpBaseOfDll in self.__moduleDict + + def get_module(self, lpBaseOfDll): + """ + @type lpBaseOfDll: int + @param lpBaseOfDll: Base address of the DLL to look for. + + @rtype: L{Module} + @return: Module object with the given base address. + """ + self.__initialize_snapshot() + if lpBaseOfDll not in self.__moduleDict: + msg = "Unknown DLL base address %s" + msg = msg % HexDump.address(lpBaseOfDll) + raise KeyError(msg) + return self.__moduleDict[lpBaseOfDll] + + def iter_module_addresses(self): + """ + @see: L{iter_modules} + @rtype: dictionary-keyiterator + @return: Iterator of DLL base addresses in this snapshot. + """ + self.__initialize_snapshot() + return compat.iterkeys(self.__moduleDict) + + def iter_modules(self): + """ + @see: L{iter_module_addresses} + @rtype: dictionary-valueiterator + @return: Iterator of L{Module} objects in this snapshot. + """ + self.__initialize_snapshot() + return compat.itervalues(self.__moduleDict) + + def get_module_bases(self): + """ + @see: L{iter_module_addresses} + @rtype: list( int... ) + @return: List of DLL base addresses in this snapshot. + """ + self.__initialize_snapshot() + return compat.keys(self.__moduleDict) + + def get_module_count(self): + """ + @rtype: int + @return: Count of L{Module} objects in this snapshot. + """ + self.__initialize_snapshot() + return len(self.__moduleDict) + +#------------------------------------------------------------------------------ + + def get_module_by_name(self, modName): + """ + @type modName: int + @param modName: + Name of the module to look for, as returned by L{Module.get_name}. + If two or more modules with the same name are loaded, only one + of the matching modules is returned. + + You can also pass a full pathname to the DLL file. + This works correctly even if two modules with the same name + are loaded from different paths. + + @rtype: L{Module} + @return: C{Module} object that best matches the given name. + Returns C{None} if no C{Module} can be found. + """ + + # Convert modName to lowercase. + # This helps make case insensitive string comparisons. + modName = modName.lower() + + # modName is an absolute pathname. + if PathOperations.path_is_absolute(modName): + for lib in self.iter_modules(): + if modName == lib.get_filename().lower(): + return lib + return None # Stop trying to match the name. + + # Get all the module names. + # This prevents having to iterate through the module list + # more than once. + modDict = [ ( lib.get_name(), lib ) for lib in self.iter_modules() ] + modDict = dict(modDict) + + # modName is a base filename. + if modName in modDict: + return modDict[modName] + + # modName is a base filename without extension. + filepart, extpart = PathOperations.split_extension(modName) + if filepart and extpart: + if filepart in modDict: + return modDict[filepart] + + # modName is a base address. + try: + baseAddress = HexInput.integer(modName) + except ValueError: + return None + if self.has_module(baseAddress): + return self.get_module(baseAddress) + + # Module not found. + return None + + def get_module_at_address(self, address): + """ + @type address: int + @param address: Memory address to query. + + @rtype: L{Module} + @return: C{Module} object that best matches the given address. + Returns C{None} if no C{Module} can be found. + """ + bases = self.get_module_bases() + bases.sort() + bases.append(long(0x10000000000000000)) # max. 64 bit address + 1 + if address >= bases[0]: + i = 0 + max_i = len(bases) - 1 + while i < max_i: + begin, end = bases[i:i+2] + if begin <= address < end: + module = self.get_module(begin) + here = module.is_address_here(address) + if here is False: + break + else: # True or None + return module + i = i + 1 + return None + + # XXX this method musn't end up calling __initialize_snapshot by accident! + def scan_modules(self): + """ + Populates the snapshot with loaded modules. + """ + + # The module filenames may be spoofed by malware, + # since this information resides in usermode space. + # See: http://www.ragestorm.net/blogs/?p=163 + + # Ignore special process IDs. + # PID 0: System Idle Process. Also has a special meaning to the + # toolhelp APIs (current process). + # PID 4: System Integrity Group. See this forum post for more info: + # http://tinyurl.com/ycza8jo + # (points to social.technet.microsoft.com) + # Only on XP and above + # PID 8: System (?) only in Windows 2000 and below AFAIK. + # It's probably the same as PID 4 in XP and above. + dwProcessId = self.get_pid() + if dwProcessId in (0, 4, 8): + return + + # It would seem easier to clear the snapshot first. + # But then all open handles would be closed. + found_bases = set() + with win32.CreateToolhelp32Snapshot(win32.TH32CS_SNAPMODULE, + dwProcessId) as hSnapshot: + me = win32.Module32First(hSnapshot) + while me is not None: + lpBaseAddress = me.modBaseAddr + fileName = me.szExePath # full pathname + if not fileName: + fileName = me.szModule # filename only + if not fileName: + fileName = None + else: + fileName = PathOperations.native_to_win32_pathname(fileName) + found_bases.add(lpBaseAddress) +## if not self.has_module(lpBaseAddress): # XXX triggers a scan + if lpBaseAddress not in self.__moduleDict: + aModule = Module(lpBaseAddress, fileName = fileName, + SizeOfImage = me.modBaseSize, + process = self) + self._add_module(aModule) + else: + aModule = self.get_module(lpBaseAddress) + if not aModule.fileName: + aModule.fileName = fileName + if not aModule.SizeOfImage: + aModule.SizeOfImage = me.modBaseSize + if not aModule.process: + aModule.process = self + me = win32.Module32Next(hSnapshot) +## for base in self.get_module_bases(): # XXX triggers a scan + for base in compat.keys(self.__moduleDict): + if base not in found_bases: + self._del_module(base) + + def clear_modules(self): + """ + Clears the modules snapshot. + """ + for aModule in compat.itervalues(self.__moduleDict): + aModule.clear() + self.__moduleDict = dict() + +#------------------------------------------------------------------------------ + + @staticmethod + def parse_label(module = None, function = None, offset = None): + """ + Creates a label from a module and a function name, plus an offset. + + @warning: This method only creates the label, it doesn't make sure the + label actually points to a valid memory location. + + @type module: None or str + @param module: (Optional) Module name. + + @type function: None, str or int + @param function: (Optional) Function name or ordinal. + + @type offset: None or int + @param offset: (Optional) Offset value. + + If C{function} is specified, offset from the function. + + If C{function} is C{None}, offset from the module. + + @rtype: str + @return: + Label representing the given function in the given module. + + @raise ValueError: + The module or function name contain invalid characters. + """ + + # TODO + # Invalid characters should be escaped or filtered. + + # Convert ordinals to strings. + try: + function = "#0x%x" % function + except TypeError: + pass + + # Validate the parameters. + if module is not None and ('!' in module or '+' in module): + raise ValueError("Invalid module name: %s" % module) + if function is not None and ('!' in function or '+' in function): + raise ValueError("Invalid function name: %s" % function) + + # Parse the label. + if module: + if function: + if offset: + label = "%s!%s+0x%x" % (module, function, offset) + else: + label = "%s!%s" % (module, function) + else: + if offset: +## label = "%s+0x%x!" % (module, offset) + label = "%s!0x%x" % (module, offset) + else: + label = "%s!" % module + else: + if function: + if offset: + label = "!%s+0x%x" % (function, offset) + else: + label = "!%s" % function + else: + if offset: + label = "0x%x" % offset + else: + label = "0x0" + + return label + + @staticmethod + def split_label_strict(label): + """ + Splits a label created with L{parse_label}. + + To parse labels with a less strict syntax, use the L{split_label_fuzzy} + method instead. + + @warning: This method only parses the label, it doesn't make sure the + label actually points to a valid memory location. + + @type label: str + @param label: Label to split. + + @rtype: tuple( str or None, str or int or None, int or None ) + @return: Tuple containing the C{module} name, + the C{function} name or ordinal, and the C{offset} value. + + If the label doesn't specify a module, + then C{module} is C{None}. + + If the label doesn't specify a function, + then C{function} is C{None}. + + If the label doesn't specify an offset, + then C{offset} is C{0}. + + @raise ValueError: The label is malformed. + """ + module = function = None + offset = 0 + + # Special case: None + if not label: + label = "0x0" + else: + + # Remove all blanks. + label = label.replace(' ', '') + label = label.replace('\t', '') + label = label.replace('\r', '') + label = label.replace('\n', '') + + # Special case: empty label. + if not label: + label = "0x0" + + # * ! * + if '!' in label: + try: + module, function = label.split('!') + except ValueError: + raise ValueError("Malformed label: %s" % label) + + # module ! function + if function: + if '+' in module: + raise ValueError("Malformed label: %s" % label) + + # module ! function + offset + if '+' in function: + try: + function, offset = function.split('+') + except ValueError: + raise ValueError("Malformed label: %s" % label) + try: + offset = HexInput.integer(offset) + except ValueError: + raise ValueError("Malformed label: %s" % label) + else: + + # module ! offset + try: + offset = HexInput.integer(function) + function = None + except ValueError: + pass + else: + + # module + offset ! + if '+' in module: + try: + module, offset = module.split('+') + except ValueError: + raise ValueError("Malformed label: %s" % label) + try: + offset = HexInput.integer(offset) + except ValueError: + raise ValueError("Malformed label: %s" % label) + + else: + + # module ! + try: + offset = HexInput.integer(module) + module = None + + # offset ! + except ValueError: + pass + + if not module: + module = None + if not function: + function = None + + # * + else: + + # offset + try: + offset = HexInput.integer(label) + + # # ordinal + except ValueError: + if label.startswith('#'): + function = label + try: + HexInput.integer(function[1:]) + + # module? + # function? + except ValueError: + raise ValueError("Ambiguous label: %s" % label) + + # module? + # function? + else: + raise ValueError("Ambiguous label: %s" % label) + + # Convert function ordinal strings into integers. + if function and function.startswith('#'): + try: + function = HexInput.integer(function[1:]) + except ValueError: + pass + + # Convert null offsets to None. + if not offset: + offset = None + + return (module, function, offset) + + def split_label_fuzzy(self, label): + """ + Splits a label entered as user input. + + It's more flexible in it's syntax parsing than the L{split_label_strict} + method, as it allows the exclamation mark (B{C{!}}) to be omitted. The + ambiguity is resolved by searching the modules in the snapshot to guess + if a label refers to a module or a function. It also tries to rebuild + labels when they contain hardcoded addresses. + + @warning: This method only parses the label, it doesn't make sure the + label actually points to a valid memory location. + + @type label: str + @param label: Label to split. + + @rtype: tuple( str or None, str or int or None, int or None ) + @return: Tuple containing the C{module} name, + the C{function} name or ordinal, and the C{offset} value. + + If the label doesn't specify a module, + then C{module} is C{None}. + + If the label doesn't specify a function, + then C{function} is C{None}. + + If the label doesn't specify an offset, + then C{offset} is C{0}. + + @raise ValueError: The label is malformed. + """ + module = function = None + offset = 0 + + # Special case: None + if not label: + label = compat.b("0x0") + else: + + # Remove all blanks. + label = label.replace(compat.b(' '), compat.b('')) + label = label.replace(compat.b('\t'), compat.b('')) + label = label.replace(compat.b('\r'), compat.b('')) + label = label.replace(compat.b('\n'), compat.b('')) + + # Special case: empty label. + if not label: + label = compat.b("0x0") + + # If an exclamation sign is present, we know we can parse it strictly. + if compat.b('!') in label: + return self.split_label_strict(label) + +## # Try to parse it strictly, on error do it the fuzzy way. +## try: +## return self.split_label(label) +## except ValueError: +## pass + + # * + offset + if compat.b('+') in label: + try: + prefix, offset = label.split(compat.b('+')) + except ValueError: + raise ValueError("Malformed label: %s" % label) + try: + offset = HexInput.integer(offset) + except ValueError: + raise ValueError("Malformed label: %s" % label) + label = prefix + + # This parses both filenames and base addresses. + modobj = self.get_module_by_name(label) + if modobj: + + # module + # module + offset + module = modobj.get_name() + + else: + + # TODO + # If 0xAAAAAAAA + 0xBBBBBBBB is given, + # A is interpreted as a module base address, + # and B as an offset. + # If that fails, it'd be good to add A+B and try to + # use the nearest loaded module. + + # offset + # base address + offset (when no module has that base address) + try: + address = HexInput.integer(label) + + if offset: + # If 0xAAAAAAAA + 0xBBBBBBBB is given, + # A is interpreted as a module base address, + # and B as an offset. + # If that fails, we get here, meaning no module was found + # at A. Then add up A+B and work with that as a hardcoded + # address. + offset = address + offset + else: + # If the label is a hardcoded address, we get here. + offset = address + + # If only a hardcoded address is given, + # rebuild the label using get_label_at_address. + # Then parse it again, but this time strictly, + # both because there is no need for fuzzy syntax and + # to prevent an infinite recursion if there's a bug here. + try: + new_label = self.get_label_at_address(offset) + module, function, offset = \ + self.split_label_strict(new_label) + except ValueError: + pass + + # function + # function + offset + except ValueError: + function = label + + # Convert function ordinal strings into integers. + if function and function.startswith(compat.b('#')): + try: + function = HexInput.integer(function[1:]) + except ValueError: + pass + + # Convert null offsets to None. + if not offset: + offset = None + + return (module, function, offset) + + @classmethod + def split_label(cls, label): + """ +Splits a label into it's C{module}, C{function} and C{offset} +components, as used in L{parse_label}. + +When called as a static method, the strict syntax mode is used:: + + winappdbg.Process.split_label( "kernel32!CreateFileA" ) + +When called as an instance method, the fuzzy syntax mode is used:: + + aProcessInstance.split_label( "CreateFileA" ) + +@see: L{split_label_strict}, L{split_label_fuzzy} + +@type label: str +@param label: Label to split. + +@rtype: tuple( str or None, str or int or None, int or None ) +@return: + Tuple containing the C{module} name, + the C{function} name or ordinal, and the C{offset} value. + + If the label doesn't specify a module, + then C{module} is C{None}. + + If the label doesn't specify a function, + then C{function} is C{None}. + + If the label doesn't specify an offset, + then C{offset} is C{0}. + +@raise ValueError: The label is malformed. + """ + + # XXX + # Docstring indentation was removed so epydoc doesn't complain + # when parsing the docs for __use_fuzzy_mode(). + + # This function is overwritten by __init__ + # so here is the static implementation only. + return cls.split_label_strict(label) + + # The split_label method is replaced with this function by __init__. + def __use_fuzzy_mode(self, label): + "@see: L{split_label}" + return self.split_label_fuzzy(label) +## __use_fuzzy_mode.__doc__ = split_label.__doc__ + + def sanitize_label(self, label): + """ + Converts a label taken from user input into a well-formed label. + + @type label: str + @param label: Label taken from user input. + + @rtype: str + @return: Sanitized label. + """ + (module, function, offset) = self.split_label_fuzzy(label) + label = self.parse_label(module, function, offset) + return label + + def resolve_label(self, label): + """ + Resolve the memory address of the given label. + + @note: + If multiple modules with the same name are loaded, + the label may be resolved at any of them. For a more precise + way to resolve functions use the base address to get the L{Module} + object (see L{Process.get_module}) and then call L{Module.resolve}. + + If no module name is specified in the label, the function may be + resolved in any loaded module. If you want to resolve all functions + with that name in all processes, call L{Process.iter_modules} to + iterate through all loaded modules, and then try to resolve the + function in each one of them using L{Module.resolve}. + + @type label: str + @param label: Label to resolve. + + @rtype: int + @return: Memory address pointed to by the label. + + @raise ValueError: The label is malformed or impossible to resolve. + @raise RuntimeError: Cannot resolve the module or function. + """ + + # Split the label into module, function and offset components. + module, function, offset = self.split_label_fuzzy(label) + + # Resolve the components into a memory address. + address = self.resolve_label_components(module, function, offset) + + # Return the memory address. + return address + + def resolve_label_components(self, module = None, + function = None, + offset = None): + """ + Resolve the memory address of the given module, function and/or offset. + + @note: + If multiple modules with the same name are loaded, + the label may be resolved at any of them. For a more precise + way to resolve functions use the base address to get the L{Module} + object (see L{Process.get_module}) and then call L{Module.resolve}. + + If no module name is specified in the label, the function may be + resolved in any loaded module. If you want to resolve all functions + with that name in all processes, call L{Process.iter_modules} to + iterate through all loaded modules, and then try to resolve the + function in each one of them using L{Module.resolve}. + + @type module: None or str + @param module: (Optional) Module name. + + @type function: None, str or int + @param function: (Optional) Function name or ordinal. + + @type offset: None or int + @param offset: (Optional) Offset value. + + If C{function} is specified, offset from the function. + + If C{function} is C{None}, offset from the module. + + @rtype: int + @return: Memory address pointed to by the label. + + @raise ValueError: The label is malformed or impossible to resolve. + @raise RuntimeError: Cannot resolve the module or function. + """ + # Default address if no module or function are given. + # An offset may be added later. + address = 0 + + # Resolve the module. + # If the module is not found, check for the special symbol "main". + if module: + modobj = self.get_module_by_name(module) + if not modobj: + if module == "main": + modobj = self.get_main_module() + else: + raise RuntimeError("Module %r not found" % module) + + # Resolve the exported function or debugging symbol. + # If all else fails, check for the special symbol "start". + if function: + address = modobj.resolve(function) + if address is None: + address = modobj.resolve_symbol(function) + if address is None: + if function == "start": + address = modobj.get_entry_point() + if address is None: + msg = "Symbol %r not found in module %s" + raise RuntimeError(msg % (function, module)) + + # No function, use the base address. + else: + address = modobj.get_base() + + # Resolve the function in any module. + # If all else fails, check for the special symbols "main" and "start". + elif function: + for modobj in self.iter_modules(): + address = modobj.resolve(function) + if address is not None: + break + if address is None: + if function == "start": + modobj = self.get_main_module() + address = modobj.get_entry_point() + elif function == "main": + modobj = self.get_main_module() + address = modobj.get_base() + else: + msg = "Function %r not found in any module" % function + raise RuntimeError(msg) + + # Return the address plus the offset. + if offset: + address = address + offset + return address + + def get_label_at_address(self, address, offset = None): + """ + Creates a label from the given memory address. + + @warning: This method uses the name of the nearest currently loaded + module. If that module is unloaded later, the label becomes + impossible to resolve. + + @type address: int + @param address: Memory address. + + @type offset: None or int + @param offset: (Optional) Offset value. + + @rtype: str + @return: Label pointing to the given address. + """ + if offset: + address = address + offset + modobj = self.get_module_at_address(address) + if modobj: + label = modobj.get_label_at_address(address) + else: + label = self.parse_label(None, None, address) + return label + +#------------------------------------------------------------------------------ + + # The memory addresses of system breakpoints are be cached, since they're + # all in system libraries it's not likely they'll ever change their address + # during the lifetime of the process... I don't suppose a program could + # happily unload ntdll.dll and survive. + def __get_system_breakpoint(self, label): + try: + return self.__system_breakpoints[label] + except KeyError: + try: + address = self.resolve_label(label) + except Exception: + return None + self.__system_breakpoints[label] = address + return address + + # It's in kernel32 in Windows Server 2003, in ntdll since Windows Vista. + # It can only be resolved if we have the debug symbols. + def get_break_on_error_ptr(self): + """ + @rtype: int + @return: + If present, returns the address of the C{g_dwLastErrorToBreakOn} + global variable for this process. If not, returns C{None}. + """ + address = self.__get_system_breakpoint("ntdll!g_dwLastErrorToBreakOn") + if not address: + address = self.__get_system_breakpoint( + "kernel32!g_dwLastErrorToBreakOn") + # cheat a little :) + self.__system_breakpoints["ntdll!g_dwLastErrorToBreakOn"] = address + return address + + def is_system_defined_breakpoint(self, address): + """ + @type address: int + @param address: Memory address. + + @rtype: bool + @return: C{True} if the given address points to a system defined + breakpoint. System defined breakpoints are hardcoded into + system libraries. + """ + if address: + module = self.get_module_at_address(address) + if module: + return module.match_name("ntdll") or \ + module.match_name("kernel32") + return False + + # FIXME + # In Wine, the system breakpoint seems to be somewhere in kernel32. + def get_system_breakpoint(self): + """ + @rtype: int or None + @return: Memory address of the system breakpoint + within the process address space. + Returns C{None} on error. + """ + return self.__get_system_breakpoint("ntdll!DbgBreakPoint") + + # I don't know when this breakpoint is actually used... + def get_user_breakpoint(self): + """ + @rtype: int or None + @return: Memory address of the user breakpoint + within the process address space. + Returns C{None} on error. + """ + return self.__get_system_breakpoint("ntdll!DbgUserBreakPoint") + + # On some platforms, this breakpoint can only be resolved + # when the debugging symbols for ntdll.dll are loaded. + def get_breakin_breakpoint(self): + """ + @rtype: int or None + @return: Memory address of the remote breakin breakpoint + within the process address space. + Returns C{None} on error. + """ + return self.__get_system_breakpoint("ntdll!DbgUiRemoteBreakin") + + # Equivalent of ntdll!DbgBreakPoint in Wow64. + def get_wow64_system_breakpoint(self): + """ + @rtype: int or None + @return: Memory address of the Wow64 system breakpoint + within the process address space. + Returns C{None} on error. + """ + return self.__get_system_breakpoint("ntdll32!DbgBreakPoint") + + # Equivalent of ntdll!DbgUserBreakPoint in Wow64. + def get_wow64_user_breakpoint(self): + """ + @rtype: int or None + @return: Memory address of the Wow64 user breakpoint + within the process address space. + Returns C{None} on error. + """ + return self.__get_system_breakpoint("ntdll32!DbgUserBreakPoint") + + # Equivalent of ntdll!DbgUiRemoteBreakin in Wow64. + def get_wow64_breakin_breakpoint(self): + """ + @rtype: int or None + @return: Memory address of the Wow64 remote breakin breakpoint + within the process address space. + Returns C{None} on error. + """ + return self.__get_system_breakpoint("ntdll32!DbgUiRemoteBreakin") + +#------------------------------------------------------------------------------ + + def load_symbols(self): + """ + Loads the debugging symbols for all modules in this snapshot. + Automatically called by L{get_symbols}. + """ + for aModule in self.iter_modules(): + aModule.load_symbols() + + def unload_symbols(self): + """ + Unloads the debugging symbols for all modules in this snapshot. + """ + for aModule in self.iter_modules(): + aModule.unload_symbols() + + def get_symbols(self): + """ + Returns the debugging symbols for all modules in this snapshot. + The symbols are automatically loaded when needed. + + @rtype: list of tuple( str, int, int ) + @return: List of symbols. + Each symbol is represented by a tuple that contains: + - Symbol name + - Symbol memory address + - Symbol size in bytes + """ + symbols = list() + for aModule in self.iter_modules(): + for symbol in aModule.iter_symbols(): + symbols.append(symbol) + return symbols + + def iter_symbols(self): + """ + Returns an iterator for the debugging symbols in all modules in this + snapshot, in no particular order. + The symbols are automatically loaded when needed. + + @rtype: iterator of tuple( str, int, int ) + @return: Iterator of symbols. + Each symbol is represented by a tuple that contains: + - Symbol name + - Symbol memory address + - Symbol size in bytes + """ + for aModule in self.iter_modules(): + for symbol in aModule.iter_symbols(): + yield symbol + + def resolve_symbol(self, symbol, bCaseSensitive = False): + """ + Resolves a debugging symbol's address. + + @type symbol: str + @param symbol: Name of the symbol to resolve. + + @type bCaseSensitive: bool + @param bCaseSensitive: C{True} for case sensitive matches, + C{False} for case insensitive. + + @rtype: int or None + @return: Memory address of symbol. C{None} if not found. + """ + if bCaseSensitive: + for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols(): + if symbol == SymbolName: + return SymbolAddress + else: + symbol = symbol.lower() + for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols(): + if symbol == SymbolName.lower(): + return SymbolAddress + + def get_symbol_at_address(self, address): + """ + Tries to find the closest matching symbol for the given address. + + @type address: int + @param address: Memory address to query. + + @rtype: None or tuple( str, int, int ) + @return: Returns a tuple consisting of: + - Name + - Address + - Size (in bytes) + Returns C{None} if no symbol could be matched. + """ + # Any module may have symbols pointing anywhere in memory, so there's + # no easy way to optimize this. I guess we're stuck with brute force. + found = None + for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols(): + if SymbolAddress > address: + continue + + if SymbolAddress == address: + found = (SymbolName, SymbolAddress, SymbolSize) + break + + if SymbolAddress < address: + if found and (address - found[1]) < (address - SymbolAddress): + continue + else: + found = (SymbolName, SymbolAddress, SymbolSize) + return found +#------------------------------------------------------------------------------ + + # XXX _notify_* methods should not trigger a scan + + def _add_module(self, aModule): + """ + Private method to add a module object to the snapshot. + + @type aModule: L{Module} + @param aModule: Module object. + """ +## if not isinstance(aModule, Module): +## if hasattr(aModule, '__class__'): +## typename = aModule.__class__.__name__ +## else: +## typename = str(type(aModule)) +## msg = "Expected Module, got %s instead" % typename +## raise TypeError(msg) + lpBaseOfDll = aModule.get_base() +## if lpBaseOfDll in self.__moduleDict: +## msg = "Module already exists: %d" % lpBaseOfDll +## raise KeyError(msg) + aModule.set_process(self) + self.__moduleDict[lpBaseOfDll] = aModule + + def _del_module(self, lpBaseOfDll): + """ + Private method to remove a module object from the snapshot. + + @type lpBaseOfDll: int + @param lpBaseOfDll: Module base address. + """ + try: + aModule = self.__moduleDict[lpBaseOfDll] + del self.__moduleDict[lpBaseOfDll] + except KeyError: + aModule = None + msg = "Unknown base address %d" % HexDump.address(lpBaseOfDll) + warnings.warn(msg, RuntimeWarning) + if aModule: + aModule.clear() # remove circular references + + def __add_loaded_module(self, event): + """ + Private method to automatically add new module objects from debug events. + + @type event: L{Event} + @param event: Event object. + """ + lpBaseOfDll = event.get_module_base() + hFile = event.get_file_handle() +## if not self.has_module(lpBaseOfDll): # XXX this would trigger a scan + if lpBaseOfDll not in self.__moduleDict: + fileName = event.get_filename() + if not fileName: + fileName = None + if hasattr(event, 'get_start_address'): + EntryPoint = event.get_start_address() + else: + EntryPoint = None + aModule = Module(lpBaseOfDll, hFile, fileName = fileName, + EntryPoint = EntryPoint, + process = self) + self._add_module(aModule) + else: + aModule = self.get_module(lpBaseOfDll) + if not aModule.hFile and hFile not in (None, 0, + win32.INVALID_HANDLE_VALUE): + aModule.hFile = hFile + if not aModule.process: + aModule.process = self + if aModule.EntryPoint is None and \ + hasattr(event, 'get_start_address'): + aModule.EntryPoint = event.get_start_address() + if not aModule.fileName: + fileName = event.get_filename() + if fileName: + aModule.fileName = fileName + + def _notify_create_process(self, event): + """ + Notify the load of the main module. + + This is done automatically by the L{Debug} class, you shouldn't need + to call it yourself. + + @type event: L{CreateProcessEvent} + @param event: Create process event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + self.__add_loaded_module(event) + return True + + def _notify_load_dll(self, event): + """ + Notify the load of a new module. + + This is done automatically by the L{Debug} class, you shouldn't need + to call it yourself. + + @type event: L{LoadDLLEvent} + @param event: Load DLL event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + self.__add_loaded_module(event) + return True + + def _notify_unload_dll(self, event): + """ + Notify the release of a loaded module. + + This is done automatically by the L{Debug} class, you shouldn't need + to call it yourself. + + @type event: L{UnloadDLLEvent} + @param event: Unload DLL event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + lpBaseOfDll = event.get_module_base() +## if self.has_module(lpBaseOfDll): # XXX this would trigger a scan + if lpBaseOfDll in self.__moduleDict: + self._del_module(lpBaseOfDll) + return True diff --git a/pydevd_attach_to_process/winappdbg/process.py b/pydevd_attach_to_process/winappdbg/process.py new file mode 100644 index 0000000..5d2ae3c --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/process.py @@ -0,0 +1,5021 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Process instrumentation. + +@group Instrumentation: + Process +""" + +from __future__ import with_statement + +# FIXME +# I've been told the host process for the latest versions of VMWare +# can't be instrumented, because they try to stop code injection into the VMs. +# The solution appears to be to run the debugger from a user account that +# belongs to the VMware group. I haven't confirmed this yet. + +__revision__ = "$Id$" + +__all__ = ['Process'] + +import sys +from winappdbg import win32 +from winappdbg import compat +from winappdbg.textio import HexDump, HexInput +from winappdbg.util import Regenerator, PathOperations, MemoryAddresses +from winappdbg.module import Module, _ModuleContainer +from winappdbg.thread import Thread, _ThreadContainer +from winappdbg.window import Window +from winappdbg.search import Search, \ + Pattern, BytePattern, TextPattern, RegExpPattern, HexPattern +from winappdbg.disasm import Disassembler + +import re +import os +import os.path +import ctypes +import struct +import warnings +import traceback + +# delayed import +System = None + +#============================================================================== + +# TODO +# * Remote GetLastError() +# * The memory operation methods do not take into account that code breakpoints +# change the memory. This object should talk to BreakpointContainer to +# retrieve the original memory contents where code breakpoints are enabled. +# * A memory cache could be implemented here. + +class Process (_ThreadContainer, _ModuleContainer): + """ + Interface to a process. Contains threads and modules snapshots. + + @group Properties: + get_pid, is_alive, is_debugged, is_wow64, get_arch, get_bits, + get_filename, get_exit_code, + get_start_time, get_exit_time, get_running_time, + get_services, get_dep_policy, get_peb, get_peb_address, + get_entry_point, get_main_module, get_image_base, get_image_name, + get_command_line, get_environment, + get_command_line_block, + get_environment_block, get_environment_variables, + get_handle, open_handle, close_handle + + @group Instrumentation: + kill, wait, suspend, resume, inject_code, inject_dll, clean_exit + + @group Disassembly: + disassemble, disassemble_around, disassemble_around_pc, + disassemble_string, disassemble_instruction, disassemble_current + + @group Debugging: + flush_instruction_cache, debug_break, peek_pointers_in_data + + @group Memory mapping: + take_memory_snapshot, generate_memory_snapshot, iter_memory_snapshot, + restore_memory_snapshot, get_memory_map, get_mapped_filenames, + generate_memory_map, iter_memory_map, + is_pointer, is_address_valid, is_address_free, is_address_reserved, + is_address_commited, is_address_guard, is_address_readable, + is_address_writeable, is_address_copy_on_write, is_address_executable, + is_address_executable_and_writeable, + is_buffer, + is_buffer_readable, is_buffer_writeable, is_buffer_executable, + is_buffer_executable_and_writeable, is_buffer_copy_on_write + + @group Memory allocation: + malloc, free, mprotect, mquery + + @group Memory read: + read, read_char, read_int, read_uint, read_float, read_double, + read_dword, read_qword, read_pointer, read_string, read_structure, + peek, peek_char, peek_int, peek_uint, peek_float, peek_double, + peek_dword, peek_qword, peek_pointer, peek_string + + @group Memory write: + write, write_char, write_int, write_uint, write_float, write_double, + write_dword, write_qword, write_pointer, + poke, poke_char, poke_int, poke_uint, poke_float, poke_double, + poke_dword, poke_qword, poke_pointer + + @group Memory search: + search, search_bytes, search_hexa, search_text, search_regexp, strings + + @group Processes snapshot: + scan, clear, __contains__, __iter__, __len__ + + @group Deprecated: + get_environment_data, parse_environment_data + + @type dwProcessId: int + @ivar dwProcessId: Global process ID. Use L{get_pid} instead. + + @type hProcess: L{ProcessHandle} + @ivar hProcess: Handle to the process. Use L{get_handle} instead. + + @type fileName: str + @ivar fileName: Filename of the main module. Use L{get_filename} instead. + """ + + def __init__(self, dwProcessId, hProcess = None, fileName = None): + """ + @type dwProcessId: int + @param dwProcessId: Global process ID. + + @type hProcess: L{ProcessHandle} + @param hProcess: Handle to the process. + + @type fileName: str + @param fileName: (Optional) Filename of the main module. + """ + _ThreadContainer.__init__(self) + _ModuleContainer.__init__(self) + + self.dwProcessId = dwProcessId + self.hProcess = hProcess + self.fileName = fileName + + def get_pid(self): + """ + @rtype: int + @return: Process global ID. + """ + return self.dwProcessId + + def get_filename(self): + """ + @rtype: str + @return: Filename of the main module of the process. + """ + if not self.fileName: + self.fileName = self.get_image_name() + return self.fileName + + def open_handle(self, dwDesiredAccess = win32.PROCESS_ALL_ACCESS): + """ + Opens a new handle to the process. + + The new handle is stored in the L{hProcess} property. + + @warn: Normally you should call L{get_handle} instead, since it's much + "smarter" and tries to reuse handles and merge access rights. + + @type dwDesiredAccess: int + @param dwDesiredAccess: Desired access rights. + Defaults to L{win32.PROCESS_ALL_ACCESS}. + See: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx} + + @raise WindowsError: It's not possible to open a handle to the process + with the requested access rights. This tipically happens because + the target process is a system process and the debugger is not + runnning with administrative rights. + """ + hProcess = win32.OpenProcess(dwDesiredAccess, win32.FALSE, self.dwProcessId) + + try: + self.close_handle() + except Exception: + warnings.warn( + "Failed to close process handle: %s" % traceback.format_exc()) + + self.hProcess = hProcess + + def close_handle(self): + """ + Closes the handle to the process. + + @note: Normally you don't need to call this method. All handles + created by I{WinAppDbg} are automatically closed when the garbage + collector claims them. So unless you've been tinkering with it, + setting L{hProcess} to C{None} should be enough. + """ + try: + if hasattr(self.hProcess, 'close'): + self.hProcess.close() + elif self.hProcess not in (None, win32.INVALID_HANDLE_VALUE): + win32.CloseHandle(self.hProcess) + finally: + self.hProcess = None + + def get_handle(self, dwDesiredAccess = win32.PROCESS_ALL_ACCESS): + """ + Returns a handle to the process with I{at least} the access rights + requested. + + @note: + If a handle was previously opened and has the required access + rights, it's reused. If not, a new handle is opened with the + combination of the old and new access rights. + + @type dwDesiredAccess: int + @param dwDesiredAccess: Desired access rights. + Defaults to L{win32.PROCESS_ALL_ACCESS}. + See: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx} + + @rtype: L{ProcessHandle} + @return: Handle to the process. + + @raise WindowsError: It's not possible to open a handle to the process + with the requested access rights. This tipically happens because + the target process is a system process and the debugger is not + runnning with administrative rights. + """ + if self.hProcess in (None, win32.INVALID_HANDLE_VALUE): + self.open_handle(dwDesiredAccess) + else: + dwAccess = self.hProcess.dwAccess + if (dwAccess | dwDesiredAccess) != dwAccess: + self.open_handle(dwAccess | dwDesiredAccess) + return self.hProcess + +#------------------------------------------------------------------------------ + + # Not really sure if it's a good idea... +## def __eq__(self, aProcess): +## """ +## Compare two Process objects. The comparison is made using the IDs. +## +## @warning: +## If you have two Process instances with different handles the +## equality operator still returns C{True}, so be careful! +## +## @type aProcess: L{Process} +## @param aProcess: Another Process object. +## +## @rtype: bool +## @return: C{True} if the two process IDs are equal, +## C{False} otherwise. +## """ +## return isinstance(aProcess, Process) and \ +## self.get_pid() == aProcess.get_pid() + + def __contains__(self, anObject): + """ + The same as: C{self.has_thread(anObject) or self.has_module(anObject)} + + @type anObject: L{Thread}, L{Module} or int + @param anObject: Object to look for. + Can be a Thread, Module, thread global ID or module base address. + + @rtype: bool + @return: C{True} if the requested object was found in the snapshot. + """ + return _ThreadContainer.__contains__(self, anObject) or \ + _ModuleContainer.__contains__(self, anObject) + + def __len__(self): + """ + @see: L{get_thread_count}, L{get_module_count} + @rtype: int + @return: Count of L{Thread} and L{Module} objects in this snapshot. + """ + return _ThreadContainer.__len__(self) + \ + _ModuleContainer.__len__(self) + + class __ThreadsAndModulesIterator (object): + """ + Iterator object for L{Process} objects. + Iterates through L{Thread} objects first, L{Module} objects next. + """ + + def __init__(self, container): + """ + @type container: L{Process} + @param container: L{Thread} and L{Module} container. + """ + self.__container = container + self.__iterator = None + self.__state = 0 + + def __iter__(self): + 'x.__iter__() <==> iter(x)' + return self + + def next(self): + 'x.next() -> the next value, or raise StopIteration' + if self.__state == 0: + self.__iterator = self.__container.iter_threads() + self.__state = 1 + if self.__state == 1: + try: + return self.__iterator.next() + except StopIteration: + self.__iterator = self.__container.iter_modules() + self.__state = 2 + if self.__state == 2: + try: + return self.__iterator.next() + except StopIteration: + self.__iterator = None + self.__state = 3 + raise StopIteration + + def __iter__(self): + """ + @see: L{iter_threads}, L{iter_modules} + @rtype: iterator + @return: Iterator of L{Thread} and L{Module} objects in this snapshot. + All threads are iterated first, then all modules. + """ + return self.__ThreadsAndModulesIterator(self) + +#------------------------------------------------------------------------------ + + def wait(self, dwTimeout = None): + """ + Waits for the process to finish executing. + + @raise WindowsError: On error an exception is raised. + """ + self.get_handle(win32.SYNCHRONIZE).wait(dwTimeout) + + def kill(self, dwExitCode = 0): + """ + Terminates the execution of the process. + + @raise WindowsError: On error an exception is raised. + """ + hProcess = self.get_handle(win32.PROCESS_TERMINATE) + win32.TerminateProcess(hProcess, dwExitCode) + + def suspend(self): + """ + Suspends execution on all threads of the process. + + @raise WindowsError: On error an exception is raised. + """ + self.scan_threads() # force refresh the snapshot + suspended = list() + try: + for aThread in self.iter_threads(): + aThread.suspend() + suspended.append(aThread) + except Exception: + for aThread in suspended: + try: + aThread.resume() + except Exception: + pass + raise + + def resume(self): + """ + Resumes execution on all threads of the process. + + @raise WindowsError: On error an exception is raised. + """ + if self.get_thread_count() == 0: + self.scan_threads() # only refresh the snapshot if empty + resumed = list() + try: + for aThread in self.iter_threads(): + aThread.resume() + resumed.append(aThread) + except Exception: + for aThread in resumed: + try: + aThread.suspend() + except Exception: + pass + raise + + def is_debugged(self): + """ + Tries to determine if the process is being debugged by another process. + It may detect other debuggers besides WinAppDbg. + + @rtype: bool + @return: C{True} if the process has a debugger attached. + + @warning: + May return inaccurate results when some anti-debug techniques are + used by the target process. + + @note: To know if a process currently being debugged by a L{Debug} + object, call L{Debug.is_debugee} instead. + """ + # FIXME the MSDN docs don't say what access rights are needed here! + hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION) + return win32.CheckRemoteDebuggerPresent(hProcess) + + def is_alive(self): + """ + @rtype: bool + @return: C{True} if the process is currently running. + """ + try: + self.wait(0) + except WindowsError: + e = sys.exc_info()[1] + return e.winerror == win32.WAIT_TIMEOUT + return False + + def get_exit_code(self): + """ + @rtype: int + @return: Process exit code, or C{STILL_ACTIVE} if it's still alive. + + @warning: If a process returns C{STILL_ACTIVE} as it's exit code, + you may not be able to determine if it's active or not with this + method. Use L{is_alive} to check if the process is still active. + Alternatively you can call L{get_handle} to get the handle object + and then L{ProcessHandle.wait} on it to wait until the process + finishes running. + """ + if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA: + dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION + else: + dwAccess = win32.PROCESS_QUERY_INFORMATION + return win32.GetExitCodeProcess( self.get_handle(dwAccess) ) + +#------------------------------------------------------------------------------ + + def scan(self): + """ + Populates the snapshot of threads and modules. + """ + self.scan_threads() + self.scan_modules() + + def clear(self): + """ + Clears the snapshot of threads and modules. + """ + try: + try: + self.clear_threads() + finally: + self.clear_modules() + finally: + self.close_handle() + +#------------------------------------------------------------------------------ + + # Regular expression to find hexadecimal values of any size. + __hexa_parameter = re.compile('0x[0-9A-Fa-f]+') + + def __fixup_labels(self, disasm): + """ + Private method used when disassembling from process memory. + + It has no return value because the list is modified in place. On return + all raw memory addresses are replaced by labels when possible. + + @type disasm: list of tuple(int, int, str, str) + @param disasm: Output of one of the dissassembly functions. + """ + for index in compat.xrange(len(disasm)): + (address, size, text, dump) = disasm[index] + m = self.__hexa_parameter.search(text) + while m: + s, e = m.span() + value = text[s:e] + try: + label = self.get_label_at_address( int(value, 0x10) ) + except Exception: + label = None + if label: + text = text[:s] + label + text[e:] + e = s + len(value) + m = self.__hexa_parameter.search(text, e) + disasm[index] = (address, size, text, dump) + + def disassemble_string(self, lpAddress, code): + """ + Disassemble instructions from a block of binary code. + + @type lpAddress: int + @param lpAddress: Memory address where the code was read from. + + @type code: str + @param code: Binary code to disassemble. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + + @raise NotImplementedError: + No compatible disassembler was found for the current platform. + """ + try: + disasm = self.__disasm + except AttributeError: + disasm = self.__disasm = Disassembler( self.get_arch() ) + return disasm.decode(lpAddress, code) + + def disassemble(self, lpAddress, dwSize): + """ + Disassemble instructions from the address space of the process. + + @type lpAddress: int + @param lpAddress: Memory address where to read the code from. + + @type dwSize: int + @param dwSize: Size of binary code to disassemble. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + data = self.read(lpAddress, dwSize) + disasm = self.disassemble_string(lpAddress, data) + self.__fixup_labels(disasm) + return disasm + + # FIXME + # This algorithm really bad, I've got to write a better one :P + def disassemble_around(self, lpAddress, dwSize = 64): + """ + Disassemble around the given address. + + @type lpAddress: int + @param lpAddress: Memory address where to read the code from. + + @type dwSize: int + @param dwSize: Delta offset. + Code will be read from lpAddress - dwSize to lpAddress + dwSize. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + dwDelta = int(float(dwSize) / 2.0) + addr_1 = lpAddress - dwDelta + addr_2 = lpAddress + size_1 = dwDelta + size_2 = dwSize - dwDelta + data = self.read(addr_1, dwSize) + data_1 = data[:size_1] + data_2 = data[size_1:] + disasm_1 = self.disassemble_string(addr_1, data_1) + disasm_2 = self.disassemble_string(addr_2, data_2) + disasm = disasm_1 + disasm_2 + self.__fixup_labels(disasm) + return disasm + + def disassemble_around_pc(self, dwThreadId, dwSize = 64): + """ + Disassemble around the program counter of the given thread. + + @type dwThreadId: int + @param dwThreadId: Global thread ID. + The program counter for this thread will be used as the disassembly + address. + + @type dwSize: int + @param dwSize: Delta offset. + Code will be read from pc - dwSize to pc + dwSize. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + aThread = self.get_thread(dwThreadId) + return self.disassemble_around(aThread.get_pc(), dwSize) + + def disassemble_instruction(self, lpAddress): + """ + Disassemble the instruction at the given memory address. + + @type lpAddress: int + @param lpAddress: Memory address where to read the code from. + + @rtype: tuple( long, int, str, str ) + @return: The tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + return self.disassemble(lpAddress, 15)[0] + + def disassemble_current(self, dwThreadId): + """ + Disassemble the instruction at the program counter of the given thread. + + @type dwThreadId: int + @param dwThreadId: Global thread ID. + The program counter for this thread will be used as the disassembly + address. + + @rtype: tuple( long, int, str, str ) + @return: The tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + aThread = self.get_thread(dwThreadId) + return self.disassemble_instruction(aThread.get_pc()) + +#------------------------------------------------------------------------------ + + def flush_instruction_cache(self): + """ + Flush the instruction cache. This is required if the process memory is + modified and one or more threads are executing nearby the modified + memory region. + + @see: U{http://blogs.msdn.com/oldnewthing/archive/2003/12/08/55954.aspx#55958} + + @raise WindowsError: Raises exception on error. + """ + # FIXME + # No idea what access rights are required here! + # Maybe PROCESS_VM_OPERATION ??? + # In any case we're only calling this from the debugger, + # so it should be fine (we already have PROCESS_ALL_ACCESS). + win32.FlushInstructionCache( self.get_handle() ) + + def debug_break(self): + """ + Triggers the system breakpoint in the process. + + @raise WindowsError: On error an exception is raised. + """ + # The exception is raised by a new thread. + # When continuing the exception, the thread dies by itself. + # This thread is hidden from the debugger. + win32.DebugBreakProcess( self.get_handle() ) + + def is_wow64(self): + """ + Determines if the process is running under WOW64. + + @rtype: bool + @return: + C{True} if the process is running under WOW64. That is, a 32-bit + application running in a 64-bit Windows. + + C{False} if the process is either a 32-bit application running in + a 32-bit Windows, or a 64-bit application running in a 64-bit + Windows. + + @raise WindowsError: On error an exception is raised. + + @see: U{http://msdn.microsoft.com/en-us/library/aa384249(VS.85).aspx} + """ + try: + wow64 = self.__wow64 + except AttributeError: + if (win32.bits == 32 and not win32.wow64): + wow64 = False + else: + if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA: + dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION + else: + dwAccess = win32.PROCESS_QUERY_INFORMATION + hProcess = self.get_handle(dwAccess) + try: + wow64 = win32.IsWow64Process(hProcess) + except AttributeError: + wow64 = False + self.__wow64 = wow64 + return wow64 + + def get_arch(self): + """ + @rtype: str + @return: The architecture in which this process believes to be running. + For example, if running a 32 bit binary in a 64 bit machine, the + architecture returned by this method will be L{win32.ARCH_I386}, + but the value of L{System.arch} will be L{win32.ARCH_AMD64}. + """ + + # Are we in a 32 bit machine? + if win32.bits == 32 and not win32.wow64: + return win32.arch + + # Is the process outside of WOW64? + if not self.is_wow64(): + return win32.arch + + # In WOW64, "amd64" becomes "i386". + if win32.arch == win32.ARCH_AMD64: + return win32.ARCH_I386 + + # We don't know the translation for other architectures. + raise NotImplementedError() + + def get_bits(self): + """ + @rtype: str + @return: The number of bits in which this process believes to be + running. For example, if running a 32 bit binary in a 64 bit + machine, the number of bits returned by this method will be C{32}, + but the value of L{System.arch} will be C{64}. + """ + + # Are we in a 32 bit machine? + if win32.bits == 32 and not win32.wow64: + + # All processes are 32 bits. + return 32 + + # Is the process inside WOW64? + if self.is_wow64(): + + # The process is 32 bits. + return 32 + + # The process is 64 bits. + return 64 + + # TODO: get_os, to test compatibility run + # See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683224(v=vs.85).aspx + +#------------------------------------------------------------------------------ + + def get_start_time(self): + """ + Determines when has this process started running. + + @rtype: win32.SYSTEMTIME + @return: Process start time. + """ + if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA: + dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION + else: + dwAccess = win32.PROCESS_QUERY_INFORMATION + hProcess = self.get_handle(dwAccess) + CreationTime = win32.GetProcessTimes(hProcess)[0] + return win32.FileTimeToSystemTime(CreationTime) + + def get_exit_time(self): + """ + Determines when has this process finished running. + If the process is still alive, the current time is returned instead. + + @rtype: win32.SYSTEMTIME + @return: Process exit time. + """ + if self.is_alive(): + ExitTime = win32.GetSystemTimeAsFileTime() + else: + if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA: + dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION + else: + dwAccess = win32.PROCESS_QUERY_INFORMATION + hProcess = self.get_handle(dwAccess) + ExitTime = win32.GetProcessTimes(hProcess)[1] + return win32.FileTimeToSystemTime(ExitTime) + + def get_running_time(self): + """ + Determines how long has this process been running. + + @rtype: long + @return: Process running time in milliseconds. + """ + if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA: + dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION + else: + dwAccess = win32.PROCESS_QUERY_INFORMATION + hProcess = self.get_handle(dwAccess) + (CreationTime, ExitTime, _, _) = win32.GetProcessTimes(hProcess) + if self.is_alive(): + ExitTime = win32.GetSystemTimeAsFileTime() + CreationTime = CreationTime.dwLowDateTime + (CreationTime.dwHighDateTime << 32) + ExitTime = ExitTime.dwLowDateTime + ( ExitTime.dwHighDateTime << 32) + RunningTime = ExitTime - CreationTime + return RunningTime / 10000 # 100 nanoseconds steps => milliseconds + +#------------------------------------------------------------------------------ + + def __load_System_class(self): + global System # delayed import + if System is None: + from system import System + + def get_services(self): + """ + Retrieves the list of system services that are currently running in + this process. + + @see: L{System.get_services} + + @rtype: list( L{win32.ServiceStatusProcessEntry} ) + @return: List of service status descriptors. + """ + self.__load_System_class() + pid = self.get_pid() + return [d for d in System.get_active_services() if d.ProcessId == pid] + +#------------------------------------------------------------------------------ + + def get_dep_policy(self): + """ + Retrieves the DEP (Data Execution Prevention) policy for this process. + + @note: This method is only available in Windows XP SP3 and above, and + only for 32 bit processes. It will fail in any other circumstance. + + @see: U{http://msdn.microsoft.com/en-us/library/bb736297(v=vs.85).aspx} + + @rtype: tuple(int, int) + @return: + The first member of the tuple is the DEP flags. It can be a + combination of the following values: + - 0: DEP is disabled for this process. + - 1: DEP is enabled for this process. (C{PROCESS_DEP_ENABLE}) + - 2: DEP-ATL thunk emulation is disabled for this process. + (C{PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION}) + + The second member of the tuple is the permanent flag. If C{TRUE} + the DEP settings cannot be changed in runtime for this process. + + @raise WindowsError: On error an exception is raised. + """ + hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION) + try: + return win32.kernel32.GetProcessDEPPolicy(hProcess) + except AttributeError: + msg = "This method is only available in Windows XP SP3 and above." + raise NotImplementedError(msg) + +#------------------------------------------------------------------------------ + + def get_peb(self): + """ + Returns a copy of the PEB. + To dereference pointers in it call L{Process.read_structure}. + + @rtype: L{win32.PEB} + @return: PEB structure. + @raise WindowsError: An exception is raised on error. + """ + self.get_handle( win32.PROCESS_VM_READ | + win32.PROCESS_QUERY_INFORMATION ) + return self.read_structure(self.get_peb_address(), win32.PEB) + + def get_peb_address(self): + """ + Returns a remote pointer to the PEB. + + @rtype: int + @return: Remote pointer to the L{win32.PEB} structure. + Returns C{None} on error. + """ + try: + return self._peb_ptr + except AttributeError: + hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION) + pbi = win32.NtQueryInformationProcess(hProcess, + win32.ProcessBasicInformation) + address = pbi.PebBaseAddress + self._peb_ptr = address + return address + + def get_entry_point(self): + """ + Alias to C{process.get_main_module().get_entry_point()}. + + @rtype: int + @return: Address of the entry point of the main module. + """ + return self.get_main_module().get_entry_point() + + def get_main_module(self): + """ + @rtype: L{Module} + @return: Module object for the process main module. + """ + return self.get_module(self.get_image_base()) + + def get_image_base(self): + """ + @rtype: int + @return: Image base address for the process main module. + """ + return self.get_peb().ImageBaseAddress + + def get_image_name(self): + """ + @rtype: int + @return: Filename of the process main module. + + This method does it's best to retrieve the filename. + However sometimes this is not possible, so C{None} may + be returned instead. + """ + + # Method 1: Module.fileName + # It's cached if the filename was already found by the other methods, + # if it came with the corresponding debug event, or it was found by the + # toolhelp API. + mainModule = None + try: + mainModule = self.get_main_module() + name = mainModule.fileName + if not name: + name = None + except (KeyError, AttributeError, WindowsError): +## traceback.print_exc() # XXX DEBUG + name = None + + # Method 2: QueryFullProcessImageName() + # Not implemented until Windows Vista. + if not name: + try: + hProcess = self.get_handle( + win32.PROCESS_QUERY_LIMITED_INFORMATION) + name = win32.QueryFullProcessImageName(hProcess) + except (AttributeError, WindowsError): +## traceback.print_exc() # XXX DEBUG + name = None + + # Method 3: GetProcessImageFileName() + # + # Not implemented until Windows XP. + # For more info see: + # https://voidnish.wordpress.com/2005/06/20/getprocessimagefilenamequerydosdevice-trivia/ + if not name: + try: + hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION) + name = win32.GetProcessImageFileName(hProcess) + if name: + name = PathOperations.native_to_win32_pathname(name) + else: + name = None + except (AttributeError, WindowsError): +## traceback.print_exc() # XXX DEBUG + if not name: + name = None + + # Method 4: GetModuleFileNameEx() + # Not implemented until Windows 2000. + # + # May be spoofed by malware, since this information resides + # in usermode space (see http://www.ragestorm.net/blogs/?p=163). + if not name: + try: + hProcess = self.get_handle( win32.PROCESS_VM_READ | + win32.PROCESS_QUERY_INFORMATION ) + try: + name = win32.GetModuleFileNameEx(hProcess) + except WindowsError: +## traceback.print_exc() # XXX DEBUG + name = win32.GetModuleFileNameEx( + hProcess, self.get_image_base()) + if name: + name = PathOperations.native_to_win32_pathname(name) + else: + name = None + except (AttributeError, WindowsError): +## traceback.print_exc() # XXX DEBUG + if not name: + name = None + + # Method 5: PEB.ProcessParameters->ImagePathName + # + # May fail since it's using an undocumented internal structure. + # + # May be spoofed by malware, since this information resides + # in usermode space (see http://www.ragestorm.net/blogs/?p=163). + if not name: + try: + peb = self.get_peb() + pp = self.read_structure(peb.ProcessParameters, + win32.RTL_USER_PROCESS_PARAMETERS) + s = pp.ImagePathName + name = self.peek_string(s.Buffer, + dwMaxSize=s.MaximumLength, fUnicode=True) + if name: + name = PathOperations.native_to_win32_pathname(name) + else: + name = None + except (AttributeError, WindowsError): +## traceback.print_exc() # XXX DEBUG + name = None + + # Method 6: Module.get_filename() + # It tries to get the filename from the file handle. + # + # There are currently some problems due to the strange way the API + # works - it returns the pathname without the drive letter, and I + # couldn't figure out a way to fix it. + if not name and mainModule is not None: + try: + name = mainModule.get_filename() + if not name: + name = None + except (AttributeError, WindowsError): +## traceback.print_exc() # XXX DEBUG + name = None + + # Remember the filename. + if name and mainModule is not None: + mainModule.fileName = name + + # Return the image filename, or None on error. + return name + + def get_command_line_block(self): + """ + Retrieves the command line block memory address and size. + + @rtype: tuple(int, int) + @return: Tuple with the memory address of the command line block + and it's maximum size in Unicode characters. + + @raise WindowsError: On error an exception is raised. + """ + peb = self.get_peb() + pp = self.read_structure(peb.ProcessParameters, + win32.RTL_USER_PROCESS_PARAMETERS) + s = pp.CommandLine + return (s.Buffer, s.MaximumLength) + + def get_environment_block(self): + """ + Retrieves the environment block memory address for the process. + + @note: The size is always enough to contain the environment data, but + it may not be an exact size. It's best to read the memory and + scan for two null wide chars to find the actual size. + + @rtype: tuple(int, int) + @return: Tuple with the memory address of the environment block + and it's size. + + @raise WindowsError: On error an exception is raised. + """ + peb = self.get_peb() + pp = self.read_structure(peb.ProcessParameters, + win32.RTL_USER_PROCESS_PARAMETERS) + Environment = pp.Environment + try: + EnvironmentSize = pp.EnvironmentSize + except AttributeError: + mbi = self.mquery(Environment) + EnvironmentSize = mbi.RegionSize + mbi.BaseAddress - Environment + return (Environment, EnvironmentSize) + + def get_command_line(self): + """ + Retrieves the command line with wich the program was started. + + @rtype: str + @return: Command line string. + + @raise WindowsError: On error an exception is raised. + """ + (Buffer, MaximumLength) = self.get_command_line_block() + CommandLine = self.peek_string(Buffer, dwMaxSize=MaximumLength, + fUnicode=True) + gst = win32.GuessStringType + if gst.t_default == gst.t_ansi: + CommandLine = CommandLine.encode('cp1252') + return CommandLine + + def get_environment_variables(self): + """ + Retrieves the environment variables with wich the program is running. + + @rtype: list of tuple(compat.unicode, compat.unicode) + @return: Environment keys and values as found in the process memory. + + @raise WindowsError: On error an exception is raised. + """ + + # Note: the first bytes are garbage and must be skipped. Then the first + # two environment entries are the current drive and directory as key + # and value pairs, followed by the ExitCode variable (it's what batch + # files know as "errorlevel"). After that, the real environment vars + # are there in alphabetical order. In theory that's where it stops, + # but I've always seen one more "variable" tucked at the end which + # may be another environment block but in ANSI. I haven't examined it + # yet, I'm just skipping it because if it's parsed as Unicode it just + # renders garbage. + + # Read the environment block contents. + data = self.peek( *self.get_environment_block() ) + + # Put them into a Unicode buffer. + tmp = ctypes.create_string_buffer(data) + buffer = ctypes.create_unicode_buffer(len(data)) + ctypes.memmove(buffer, tmp, len(data)) + del tmp + + # Skip until the first Unicode null char is found. + pos = 0 + while buffer[pos] != u'\0': + pos += 1 + pos += 1 + + # Loop for each environment variable... + environment = [] + while buffer[pos] != u'\0': + + # Until we find a null char... + env_name_pos = pos + env_name = u'' + found_name = False + while buffer[pos] != u'\0': + + # Get the current char. + char = buffer[pos] + + # Is it an equal sign? + if char == u'=': + + # Skip leading equal signs. + if env_name_pos == pos: + env_name_pos += 1 + pos += 1 + continue + + # Otherwise we found the separator equal sign. + pos += 1 + found_name = True + break + + # Add the char to the variable name. + env_name += char + + # Next char. + pos += 1 + + # If the name was not parsed properly, stop. + if not found_name: + break + + # Read the variable value until we find a null char. + env_value = u'' + while buffer[pos] != u'\0': + env_value += buffer[pos] + pos += 1 + + # Skip the null char. + pos += 1 + + # Add to the list of environment variables found. + environment.append( (env_name, env_value) ) + + # Remove the last entry, it's garbage. + if environment: + environment.pop() + + # Return the environment variables. + return environment + + def get_environment_data(self, fUnicode = None): + """ + Retrieves the environment block data with wich the program is running. + + @warn: Deprecated since WinAppDbg 1.5. + + @see: L{win32.GuessStringType} + + @type fUnicode: bool or None + @param fUnicode: C{True} to return a list of Unicode strings, C{False} + to return a list of ANSI strings, or C{None} to return whatever + the default is for string types. + + @rtype: list of str + @return: Environment keys and values separated by a (C{=}) character, + as found in the process memory. + + @raise WindowsError: On error an exception is raised. + """ + + # Issue a deprecation warning. + warnings.warn( + "Process.get_environment_data() is deprecated" \ + " since WinAppDbg 1.5.", + DeprecationWarning) + + # Get the environment variables. + block = [ key + u'=' + value for (key, value) \ + in self.get_environment_variables() ] + + # Convert the data to ANSI if requested. + if fUnicode is None: + gst = win32.GuessStringType + fUnicode = gst.t_default == gst.t_unicode + if not fUnicode: + block = [x.encode('cp1252') for x in block] + + # Return the environment data. + return block + + @staticmethod + def parse_environment_data(block): + """ + Parse the environment block into a Python dictionary. + + @warn: Deprecated since WinAppDbg 1.5. + + @note: Values of duplicated keys are joined using null characters. + + @type block: list of str + @param block: List of strings as returned by L{get_environment_data}. + + @rtype: dict(str S{->} str) + @return: Dictionary of environment keys and values. + """ + + # Issue a deprecation warning. + warnings.warn( + "Process.parse_environment_data() is deprecated" \ + " since WinAppDbg 1.5.", + DeprecationWarning) + + # Create an empty environment dictionary. + environment = dict() + + # End here if the environment block is empty. + if not block: + return environment + + # Prepare the tokens (ANSI or Unicode). + gst = win32.GuessStringType + if type(block[0]) == gst.t_ansi: + equals = '=' + terminator = '\0' + else: + equals = u'=' + terminator = u'\0' + + # Split the blocks into key/value pairs. + for chunk in block: + sep = chunk.find(equals, 1) + if sep < 0: +## raise Exception() + continue # corrupted environment block? + key, value = chunk[:sep], chunk[sep+1:] + + # For duplicated keys, append the value. + # Values are separated using null terminators. + if key not in environment: + environment[key] = value + else: + environment[key] += terminator + value + + # Return the environment dictionary. + return environment + + def get_environment(self, fUnicode = None): + """ + Retrieves the environment with wich the program is running. + + @note: Duplicated keys are joined using null characters. + To avoid this behavior, call L{get_environment_variables} instead + and convert the results to a dictionary directly, like this: + C{dict(process.get_environment_variables())} + + @see: L{win32.GuessStringType} + + @type fUnicode: bool or None + @param fUnicode: C{True} to return a list of Unicode strings, C{False} + to return a list of ANSI strings, or C{None} to return whatever + the default is for string types. + + @rtype: dict(str S{->} str) + @return: Dictionary of environment keys and values. + + @raise WindowsError: On error an exception is raised. + """ + + # Get the environment variables. + variables = self.get_environment_variables() + + # Convert the strings to ANSI if requested. + if fUnicode is None: + gst = win32.GuessStringType + fUnicode = gst.t_default == gst.t_unicode + if not fUnicode: + variables = [ ( key.encode('cp1252'), value.encode('cp1252') ) \ + for (key, value) in variables ] + + # Add the variables to a dictionary, concatenating duplicates. + environment = dict() + for key, value in variables: + if key in environment: + environment[key] = environment[key] + u'\0' + value + else: + environment[key] = value + + # Return the dictionary. + return environment + +#------------------------------------------------------------------------------ + + def search(self, pattern, minAddr = None, maxAddr = None): + """ + Search for the given pattern within the process memory. + + @type pattern: str, compat.unicode or L{Pattern} + @param pattern: Pattern to search for. + It may be a byte string, a Unicode string, or an instance of + L{Pattern}. + + The following L{Pattern} subclasses are provided by WinAppDbg: + - L{BytePattern} + - L{TextPattern} + - L{RegExpPattern} + - L{HexPattern} + + You can also write your own subclass of L{Pattern} for customized + searches. + + @type minAddr: int + @param minAddr: (Optional) Start the search at this memory address. + + @type maxAddr: int + @param maxAddr: (Optional) Stop the search at this memory address. + + @rtype: iterator of tuple( int, int, str ) + @return: An iterator of tuples. Each tuple contains the following: + - The memory address where the pattern was found. + - The size of the data that matches the pattern. + - The data that matches the pattern. + + @raise WindowsError: An error occurred when querying or reading the + process memory. + """ + if isinstance(pattern, str): + return self.search_bytes(pattern, minAddr, maxAddr) + if isinstance(pattern, compat.unicode): + return self.search_bytes(pattern.encode("utf-16le"), + minAddr, maxAddr) + if isinstance(pattern, Pattern): + return Search.search_process(self, pattern, minAddr, maxAddr) + raise TypeError("Unknown pattern type: %r" % type(pattern)) + + def search_bytes(self, bytes, minAddr = None, maxAddr = None): + """ + Search for the given byte pattern within the process memory. + + @type bytes: str + @param bytes: Bytes to search for. + + @type minAddr: int + @param minAddr: (Optional) Start the search at this memory address. + + @type maxAddr: int + @param maxAddr: (Optional) Stop the search at this memory address. + + @rtype: iterator of int + @return: An iterator of memory addresses where the pattern was found. + + @raise WindowsError: An error occurred when querying or reading the + process memory. + """ + pattern = BytePattern(bytes) + matches = Search.search_process(self, pattern, minAddr, maxAddr) + for addr, size, data in matches: + yield addr + + def search_text(self, text, encoding = "utf-16le", + caseSensitive = False, + minAddr = None, + maxAddr = None): + """ + Search for the given text within the process memory. + + @type text: str or compat.unicode + @param text: Text to search for. + + @type encoding: str + @param encoding: (Optional) Encoding for the text parameter. + Only used when the text to search for is a Unicode string. + Don't change unless you know what you're doing! + + @type caseSensitive: bool + @param caseSensitive: C{True} of the search is case sensitive, + C{False} otherwise. + + @type minAddr: int + @param minAddr: (Optional) Start the search at this memory address. + + @type maxAddr: int + @param maxAddr: (Optional) Stop the search at this memory address. + + @rtype: iterator of tuple( int, str ) + @return: An iterator of tuples. Each tuple contains the following: + - The memory address where the pattern was found. + - The text that matches the pattern. + + @raise WindowsError: An error occurred when querying or reading the + process memory. + """ + pattern = TextPattern(text, encoding, caseSensitive) + matches = Search.search_process(self, pattern, minAddr, maxAddr) + for addr, size, data in matches: + yield addr, data + + def search_regexp(self, regexp, flags = 0, + minAddr = None, + maxAddr = None, + bufferPages = -1): + """ + Search for the given regular expression within the process memory. + + @type regexp: str + @param regexp: Regular expression string. + + @type flags: int + @param flags: Regular expression flags. + + @type minAddr: int + @param minAddr: (Optional) Start the search at this memory address. + + @type maxAddr: int + @param maxAddr: (Optional) Stop the search at this memory address. + + @type bufferPages: int + @param bufferPages: (Optional) Number of memory pages to buffer when + performing the search. Valid values are: + - C{0} or C{None}: + Automatically determine the required buffer size. May not give + complete results for regular expressions that match variable + sized strings. + - C{> 0}: Set the buffer size, in memory pages. + - C{< 0}: Disable buffering entirely. This may give you a little + speed gain at the cost of an increased memory usage. If the + target process has very large contiguous memory regions it may + actually be slower or even fail. It's also the only way to + guarantee complete results for regular expressions that match + variable sized strings. + + @rtype: iterator of tuple( int, int, str ) + @return: An iterator of tuples. Each tuple contains the following: + - The memory address where the pattern was found. + - The size of the data that matches the pattern. + - The data that matches the pattern. + + @raise WindowsError: An error occurred when querying or reading the + process memory. + """ + pattern = RegExpPattern(regexp, flags) + return Search.search_process(self, pattern, + minAddr, maxAddr, + bufferPages) + + def search_hexa(self, hexa, minAddr = None, maxAddr = None): + """ + Search for the given hexadecimal pattern within the process memory. + + Hex patterns must be in this form:: + "68 65 6c 6c 6f 20 77 6f 72 6c 64" # "hello world" + + Spaces are optional. Capitalization of hex digits doesn't matter. + This is exactly equivalent to the previous example:: + "68656C6C6F20776F726C64" # "hello world" + + Wildcards are allowed, in the form of a C{?} sign in any hex digit:: + "5? 5? c3" # pop register / pop register / ret + "b8 ?? ?? ?? ??" # mov eax, immediate value + + @type hexa: str + @param hexa: Pattern to search for. + + @type minAddr: int + @param minAddr: (Optional) Start the search at this memory address. + + @type maxAddr: int + @param maxAddr: (Optional) Stop the search at this memory address. + + @rtype: iterator of tuple( int, str ) + @return: An iterator of tuples. Each tuple contains the following: + - The memory address where the pattern was found. + - The bytes that match the pattern. + + @raise WindowsError: An error occurred when querying or reading the + process memory. + """ + pattern = HexPattern(hexa) + matches = Search.search_process(self, pattern, minAddr, maxAddr) + for addr, size, data in matches: + yield addr, data + + def strings(self, minSize = 4, maxSize = 1024): + """ + Extract ASCII strings from the process memory. + + @type minSize: int + @param minSize: (Optional) Minimum size of the strings to search for. + + @type maxSize: int + @param maxSize: (Optional) Maximum size of the strings to search for. + + @rtype: iterator of tuple(int, int, str) + @return: Iterator of strings extracted from the process memory. + Each tuple contains the following: + - The memory address where the string was found. + - The size of the string. + - The string. + """ + return Search.extract_ascii_strings(self, minSize = minSize, + maxSize = maxSize) + +#------------------------------------------------------------------------------ + + def __read_c_type(self, address, format, c_type): + size = ctypes.sizeof(c_type) + packed = self.read(address, size) + if len(packed) != size: + raise ctypes.WinError() + return struct.unpack(format, packed)[0] + + def __write_c_type(self, address, format, unpacked): + packed = struct.pack('@L', unpacked) + self.write(address, packed) + + # XXX TODO + # + Maybe change page permissions before trying to read? + def read(self, lpBaseAddress, nSize): + """ + Reads from the memory of the process. + + @see: L{peek} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @type nSize: int + @param nSize: Number of bytes to read. + + @rtype: str + @return: Bytes read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + hProcess = self.get_handle( win32.PROCESS_VM_READ | + win32.PROCESS_QUERY_INFORMATION ) + if not self.is_buffer(lpBaseAddress, nSize): + raise ctypes.WinError(win32.ERROR_INVALID_ADDRESS) + data = win32.ReadProcessMemory(hProcess, lpBaseAddress, nSize) + if len(data) != nSize: + raise ctypes.WinError() + return data + + def write(self, lpBaseAddress, lpBuffer): + """ + Writes to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type lpBuffer: str + @param lpBuffer: Bytes to write. + + @raise WindowsError: On error an exception is raised. + """ + r = self.poke(lpBaseAddress, lpBuffer) + if r != len(lpBuffer): + raise ctypes.WinError() + + def read_char(self, lpBaseAddress): + """ + Reads a single character to the memory of the process. + + @see: L{peek_char} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @rtype: int + @return: Character value read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + return ord( self.read(lpBaseAddress, 1) ) + + def write_char(self, lpBaseAddress, char): + """ + Writes a single character to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke_char} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type char: int + @param char: Character to write. + + @raise WindowsError: On error an exception is raised. + """ + self.write(lpBaseAddress, chr(char)) + + def read_int(self, lpBaseAddress): + """ + Reads a signed integer from the memory of the process. + + @see: L{peek_int} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + return self.__read_c_type(lpBaseAddress, compat.b('@l'), ctypes.c_int) + + def write_int(self, lpBaseAddress, unpackedValue): + """ + Writes a signed integer to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke_int} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @raise WindowsError: On error an exception is raised. + """ + self.__write_c_type(lpBaseAddress, '@l', unpackedValue) + + def read_uint(self, lpBaseAddress): + """ + Reads an unsigned integer from the memory of the process. + + @see: L{peek_uint} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + return self.__read_c_type(lpBaseAddress, '@L', ctypes.c_uint) + + def write_uint(self, lpBaseAddress, unpackedValue): + """ + Writes an unsigned integer to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke_uint} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @raise WindowsError: On error an exception is raised. + """ + self.__write_c_type(lpBaseAddress, '@L', unpackedValue) + + def read_float(self, lpBaseAddress): + """ + Reads a float from the memory of the process. + + @see: L{peek_float} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Floating point value read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + return self.__read_c_type(lpBaseAddress, '@f', ctypes.c_float) + + def write_float(self, lpBaseAddress, unpackedValue): + """ + Writes a float to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke_float} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Floating point value to write. + + @raise WindowsError: On error an exception is raised. + """ + self.__write_c_type(lpBaseAddress, '@f', unpackedValue) + + def read_double(self, lpBaseAddress): + """ + Reads a double from the memory of the process. + + @see: L{peek_double} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Floating point value read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + return self.__read_c_type(lpBaseAddress, '@d', ctypes.c_double) + + def write_double(self, lpBaseAddress, unpackedValue): + """ + Writes a double to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke_double} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Floating point value to write. + + @raise WindowsError: On error an exception is raised. + """ + self.__write_c_type(lpBaseAddress, '@d', unpackedValue) + + def read_pointer(self, lpBaseAddress): + """ + Reads a pointer value from the memory of the process. + + @see: L{peek_pointer} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Pointer value read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + return self.__read_c_type(lpBaseAddress, '@P', ctypes.c_void_p) + + def write_pointer(self, lpBaseAddress, unpackedValue): + """ + Writes a pointer value to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke_pointer} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @raise WindowsError: On error an exception is raised. + """ + self.__write_c_type(lpBaseAddress, '@P', unpackedValue) + + def read_dword(self, lpBaseAddress): + """ + Reads a DWORD from the memory of the process. + + @see: L{peek_dword} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + return self.__read_c_type(lpBaseAddress, '=L', win32.DWORD) + + def write_dword(self, lpBaseAddress, unpackedValue): + """ + Writes a DWORD to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke_dword} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @raise WindowsError: On error an exception is raised. + """ + self.__write_c_type(lpBaseAddress, '=L', unpackedValue) + + def read_qword(self, lpBaseAddress): + """ + Reads a QWORD from the memory of the process. + + @see: L{peek_qword} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + return self.__read_c_type(lpBaseAddress, '=Q', win32.QWORD) + + def write_qword(self, lpBaseAddress, unpackedValue): + """ + Writes a QWORD to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{poke_qword} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @raise WindowsError: On error an exception is raised. + """ + self.__write_c_type(lpBaseAddress, '=Q', unpackedValue) + + def read_structure(self, lpBaseAddress, stype): + """ + Reads a ctypes structure from the memory of the process. + + @see: L{read} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @type stype: class ctypes.Structure or a subclass. + @param stype: Structure definition. + + @rtype: int + @return: Structure instance filled in with data + read from the process memory. + + @raise WindowsError: On error an exception is raised. + """ + if type(lpBaseAddress) not in (type(0), type(long(0))): + lpBaseAddress = ctypes.cast(lpBaseAddress, ctypes.c_void_p) + data = self.read(lpBaseAddress, ctypes.sizeof(stype)) + buff = ctypes.create_string_buffer(data) + ptr = ctypes.cast(ctypes.pointer(buff), ctypes.POINTER(stype)) + return ptr.contents + +# XXX TODO +## def write_structure(self, lpBaseAddress, sStructure): +## """ +## Writes a ctypes structure into the memory of the process. +## +## @note: Page permissions may be changed temporarily while writing. +## +## @see: L{write} +## +## @type lpBaseAddress: int +## @param lpBaseAddress: Memory address to begin writing. +## +## @type sStructure: ctypes.Structure or a subclass' instance. +## @param sStructure: Structure definition. +## +## @rtype: int +## @return: Structure instance filled in with data +## read from the process memory. +## +## @raise WindowsError: On error an exception is raised. +## """ +## size = ctypes.sizeof(sStructure) +## data = ctypes.create_string_buffer("", size = size) +## win32.CopyMemory(ctypes.byref(data), ctypes.byref(sStructure), size) +## self.write(lpBaseAddress, data.raw) + + def read_string(self, lpBaseAddress, nChars, fUnicode = False): + """ + Reads an ASCII or Unicode string + from the address space of the process. + + @see: L{peek_string} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @type nChars: int + @param nChars: String length to read, in characters. + Remember that Unicode strings have two byte characters. + + @type fUnicode: bool + @param fUnicode: C{True} is the string is expected to be Unicode, + C{False} if it's expected to be ANSI. + + @rtype: str, compat.unicode + @return: String read from the process memory space. + + @raise WindowsError: On error an exception is raised. + """ + if fUnicode: + nChars = nChars * 2 + szString = self.read(lpBaseAddress, nChars) + if fUnicode: + szString = compat.unicode(szString, 'U16', 'ignore') + return szString + +#------------------------------------------------------------------------------ + + # FIXME this won't work properly with a different endianness! + def __peek_c_type(self, address, format, c_type): + size = ctypes.sizeof(c_type) + packed = self.peek(address, size) + if len(packed) < size: + packed = '\0' * (size - len(packed)) + packed + elif len(packed) > size: + packed = packed[:size] + return struct.unpack(format, packed)[0] + + def __poke_c_type(self, address, format, unpacked): + packed = struct.pack('@L', unpacked) + return self.poke(address, packed) + + def peek(self, lpBaseAddress, nSize): + """ + Reads the memory of the process. + + @see: L{read} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @type nSize: int + @param nSize: Number of bytes to read. + + @rtype: str + @return: Bytes read from the process memory. + Returns an empty string on error. + """ + # XXX TODO + # + Maybe change page permissions before trying to read? + # + Maybe use mquery instead of get_memory_map? + # (less syscalls if we break out of the loop earlier) + data = '' + if nSize > 0: + try: + hProcess = self.get_handle( win32.PROCESS_VM_READ | + win32.PROCESS_QUERY_INFORMATION ) + for mbi in self.get_memory_map(lpBaseAddress, + lpBaseAddress + nSize): + if not mbi.is_readable(): + nSize = mbi.BaseAddress - lpBaseAddress + break + if nSize > 0: + data = win32.ReadProcessMemory( + hProcess, lpBaseAddress, nSize) + except WindowsError: + e = sys.exc_info()[1] + msg = "Error reading process %d address %s: %s" + msg %= (self.get_pid(), + HexDump.address(lpBaseAddress), + e.strerror) + warnings.warn(msg) + return data + + def poke(self, lpBaseAddress, lpBuffer): + """ + Writes to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type lpBuffer: str + @param lpBuffer: Bytes to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + assert isinstance(lpBuffer, compat.bytes) + hProcess = self.get_handle( win32.PROCESS_VM_WRITE | + win32.PROCESS_VM_OPERATION | + win32.PROCESS_QUERY_INFORMATION ) + mbi = self.mquery(lpBaseAddress) + if not mbi.has_content(): + raise ctypes.WinError(win32.ERROR_INVALID_ADDRESS) + if mbi.is_image() or mbi.is_mapped(): + prot = win32.PAGE_WRITECOPY + elif mbi.is_writeable(): + prot = None + elif mbi.is_executable(): + prot = win32.PAGE_EXECUTE_READWRITE + else: + prot = win32.PAGE_READWRITE + if prot is not None: + try: + self.mprotect(lpBaseAddress, len(lpBuffer), prot) + except Exception: + prot = None + msg = ("Failed to adjust page permissions" + " for process %s at address %s: %s") + msg = msg % (self.get_pid(), + HexDump.address(lpBaseAddress, self.get_bits()), + traceback.format_exc()) + warnings.warn(msg, RuntimeWarning) + try: + r = win32.WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer) + finally: + if prot is not None: + self.mprotect(lpBaseAddress, len(lpBuffer), mbi.Protect) + return r + + def peek_char(self, lpBaseAddress): + """ + Reads a single character from the memory of the process. + + @see: L{read_char} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Character read from the process memory. + Returns zero on error. + """ + char = self.peek(lpBaseAddress, 1) + if char: + return ord(char) + return 0 + + def poke_char(self, lpBaseAddress, char): + """ + Writes a single character to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write_char} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type char: str + @param char: Character to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + return self.poke(lpBaseAddress, chr(char)) + + def peek_int(self, lpBaseAddress): + """ + Reads a signed integer from the memory of the process. + + @see: L{read_int} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + Returns zero on error. + """ + return self.__peek_c_type(lpBaseAddress, '@l', ctypes.c_int) + + def poke_int(self, lpBaseAddress, unpackedValue): + """ + Writes a signed integer to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write_int} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + return self.__poke_c_type(lpBaseAddress, '@l', unpackedValue) + + def peek_uint(self, lpBaseAddress): + """ + Reads an unsigned integer from the memory of the process. + + @see: L{read_uint} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + Returns zero on error. + """ + return self.__peek_c_type(lpBaseAddress, '@L', ctypes.c_uint) + + def poke_uint(self, lpBaseAddress, unpackedValue): + """ + Writes an unsigned integer to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write_uint} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + return self.__poke_c_type(lpBaseAddress, '@L', unpackedValue) + + def peek_float(self, lpBaseAddress): + """ + Reads a float from the memory of the process. + + @see: L{read_float} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + Returns zero on error. + """ + return self.__peek_c_type(lpBaseAddress, '@f', ctypes.c_float) + + def poke_float(self, lpBaseAddress, unpackedValue): + """ + Writes a float to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write_float} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + return self.__poke_c_type(lpBaseAddress, '@f', unpackedValue) + + def peek_double(self, lpBaseAddress): + """ + Reads a double from the memory of the process. + + @see: L{read_double} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + Returns zero on error. + """ + return self.__peek_c_type(lpBaseAddress, '@d', ctypes.c_double) + + def poke_double(self, lpBaseAddress, unpackedValue): + """ + Writes a double to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write_double} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + return self.__poke_c_type(lpBaseAddress, '@d', unpackedValue) + + def peek_dword(self, lpBaseAddress): + """ + Reads a DWORD from the memory of the process. + + @see: L{read_dword} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + Returns zero on error. + """ + return self.__peek_c_type(lpBaseAddress, '=L', win32.DWORD) + + def poke_dword(self, lpBaseAddress, unpackedValue): + """ + Writes a DWORD to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write_dword} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + return self.__poke_c_type(lpBaseAddress, '=L', unpackedValue) + + def peek_qword(self, lpBaseAddress): + """ + Reads a QWORD from the memory of the process. + + @see: L{read_qword} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Integer value read from the process memory. + Returns zero on error. + """ + return self.__peek_c_type(lpBaseAddress, '=Q', win32.QWORD) + + def poke_qword(self, lpBaseAddress, unpackedValue): + """ + Writes a QWORD to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write_qword} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + return self.__poke_c_type(lpBaseAddress, '=Q', unpackedValue) + + def peek_pointer(self, lpBaseAddress): + """ + Reads a pointer value from the memory of the process. + + @see: L{read_pointer} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @rtype: int + @return: Pointer value read from the process memory. + Returns zero on error. + """ + return self.__peek_c_type(lpBaseAddress, '@P', ctypes.c_void_p) + + def poke_pointer(self, lpBaseAddress, unpackedValue): + """ + Writes a pointer value to the memory of the process. + + @note: Page permissions may be changed temporarily while writing. + + @see: L{write_pointer} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin writing. + + @type unpackedValue: int, long + @param unpackedValue: Value to write. + + @rtype: int + @return: Number of bytes written. + May be less than the number of bytes to write. + """ + return self.__poke_c_type(lpBaseAddress, '@P', unpackedValue) + + def peek_string(self, lpBaseAddress, fUnicode = False, dwMaxSize = 0x1000): + """ + Tries to read an ASCII or Unicode string + from the address space of the process. + + @see: L{read_string} + + @type lpBaseAddress: int + @param lpBaseAddress: Memory address to begin reading. + + @type fUnicode: bool + @param fUnicode: C{True} is the string is expected to be Unicode, + C{False} if it's expected to be ANSI. + + @type dwMaxSize: int + @param dwMaxSize: Maximum allowed string length to read, in bytes. + + @rtype: str, compat.unicode + @return: String read from the process memory space. + It B{doesn't} include the terminating null character. + Returns an empty string on failure. + """ + + # Validate the parameters. + if not lpBaseAddress or dwMaxSize == 0: + if fUnicode: + return u'' + return '' + if not dwMaxSize: + dwMaxSize = 0x1000 + + # Read the string. + szString = self.peek(lpBaseAddress, dwMaxSize) + + # If the string is Unicode... + if fUnicode: + + # Decode the string. + szString = compat.unicode(szString, 'U16', 'replace') +## try: +## szString = compat.unicode(szString, 'U16') +## except UnicodeDecodeError: +## szString = struct.unpack('H' * (len(szString) / 2), szString) +## szString = [ unichr(c) for c in szString ] +## szString = u''.join(szString) + + # Truncate the string when the first null char is found. + szString = szString[ : szString.find(u'\0') ] + + # If the string is ANSI... + else: + + # Truncate the string when the first null char is found. + szString = szString[ : szString.find('\0') ] + + # Return the decoded string. + return szString + + # TODO + # try to avoid reading the same page twice by caching it + def peek_pointers_in_data(self, data, peekSize = 16, peekStep = 1): + """ + Tries to guess which values in the given data are valid pointers, + and reads some data from them. + + @see: L{peek} + + @type data: str + @param data: Binary data to find pointers in. + + @type peekSize: int + @param peekSize: Number of bytes to read from each pointer found. + + @type peekStep: int + @param peekStep: Expected data alignment. + Tipically you specify 1 when data alignment is unknown, + or 4 when you expect data to be DWORD aligned. + Any other value may be specified. + + @rtype: dict( str S{->} str ) + @return: Dictionary mapping stack offsets to the data they point to. + """ + result = dict() + ptrSize = win32.sizeof(win32.LPVOID) + if ptrSize == 4: + ptrFmt = ' 0: + for i in compat.xrange(0, len(data), peekStep): + packed = data[i:i+ptrSize] + if len(packed) == ptrSize: + address = struct.unpack(ptrFmt, packed)[0] +## if not address & (~0xFFFF): continue + peek_data = self.peek(address, peekSize) + if peek_data: + result[i] = peek_data + return result + +#------------------------------------------------------------------------------ + + def malloc(self, dwSize, lpAddress = None): + """ + Allocates memory into the address space of the process. + + @see: L{free} + + @type dwSize: int + @param dwSize: Number of bytes to allocate. + + @type lpAddress: int + @param lpAddress: (Optional) + Desired address for the newly allocated memory. + This is only a hint, the memory could still be allocated somewhere + else. + + @rtype: int + @return: Address of the newly allocated memory. + + @raise WindowsError: On error an exception is raised. + """ + hProcess = self.get_handle(win32.PROCESS_VM_OPERATION) + return win32.VirtualAllocEx(hProcess, lpAddress, dwSize) + + def mprotect(self, lpAddress, dwSize, flNewProtect): + """ + Set memory protection in the address space of the process. + + @see: U{http://msdn.microsoft.com/en-us/library/aa366899.aspx} + + @type lpAddress: int + @param lpAddress: Address of memory to protect. + + @type dwSize: int + @param dwSize: Number of bytes to protect. + + @type flNewProtect: int + @param flNewProtect: New protect flags. + + @rtype: int + @return: Old protect flags. + + @raise WindowsError: On error an exception is raised. + """ + hProcess = self.get_handle(win32.PROCESS_VM_OPERATION) + return win32.VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect) + + def mquery(self, lpAddress): + """ + Query memory information from the address space of the process. + Returns a L{win32.MemoryBasicInformation} object. + + @see: U{http://msdn.microsoft.com/en-us/library/aa366907(VS.85).aspx} + + @type lpAddress: int + @param lpAddress: Address of memory to query. + + @rtype: L{win32.MemoryBasicInformation} + @return: Memory region information. + + @raise WindowsError: On error an exception is raised. + """ + hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION) + return win32.VirtualQueryEx(hProcess, lpAddress) + + def free(self, lpAddress): + """ + Frees memory from the address space of the process. + + @see: U{http://msdn.microsoft.com/en-us/library/aa366894(v=vs.85).aspx} + + @type lpAddress: int + @param lpAddress: Address of memory to free. + Must be the base address returned by L{malloc}. + + @raise WindowsError: On error an exception is raised. + """ + hProcess = self.get_handle(win32.PROCESS_VM_OPERATION) + win32.VirtualFreeEx(hProcess, lpAddress) + +#------------------------------------------------------------------------------ + + def is_pointer(self, address): + """ + Determines if an address is a valid code or data pointer. + + That is, the address must be valid and must point to code or data in + the target process. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: C{True} if the address is a valid code or data pointer. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.has_content() + + def is_address_valid(self, address): + """ + Determines if an address is a valid user mode address. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: C{True} if the address is a valid user mode address. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return True + + def is_address_free(self, address): + """ + Determines if an address belongs to a free page. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: C{True} if the address belongs to a free page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_free() + + def is_address_reserved(self, address): + """ + Determines if an address belongs to a reserved page. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: C{True} if the address belongs to a reserved page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_reserved() + + def is_address_commited(self, address): + """ + Determines if an address belongs to a commited page. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: C{True} if the address belongs to a commited page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_commited() + + def is_address_guard(self, address): + """ + Determines if an address belongs to a guard page. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: C{True} if the address belongs to a guard page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_guard() + + def is_address_readable(self, address): + """ + Determines if an address belongs to a commited and readable page. + The page may or may not have additional permissions. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: + C{True} if the address belongs to a commited and readable page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_readable() + + def is_address_writeable(self, address): + """ + Determines if an address belongs to a commited and writeable page. + The page may or may not have additional permissions. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: + C{True} if the address belongs to a commited and writeable page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_writeable() + + def is_address_copy_on_write(self, address): + """ + Determines if an address belongs to a commited, copy-on-write page. + The page may or may not have additional permissions. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: + C{True} if the address belongs to a commited, copy-on-write page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_copy_on_write() + + def is_address_executable(self, address): + """ + Determines if an address belongs to a commited and executable page. + The page may or may not have additional permissions. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: + C{True} if the address belongs to a commited and executable page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_executable() + + def is_address_executable_and_writeable(self, address): + """ + Determines if an address belongs to a commited, writeable and + executable page. The page may or may not have additional permissions. + + Looking for writeable and executable pages is important when + exploiting a software vulnerability. + + @note: Returns always C{False} for kernel mode addresses. + + @type address: int + @param address: Memory address to query. + + @rtype: bool + @return: + C{True} if the address belongs to a commited, writeable and + executable page. + + @raise WindowsError: An exception is raised on error. + """ + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + return mbi.is_executable_and_writeable() + + def is_buffer(self, address, size): + """ + Determines if the given memory area is a valid code or data buffer. + + @note: Returns always C{False} for kernel mode addresses. + + @see: L{mquery} + + @type address: int + @param address: Memory address. + + @type size: int + @param size: Number of bytes. Must be greater than zero. + + @rtype: bool + @return: C{True} if the memory area is a valid code or data buffer, + C{False} otherwise. + + @raise ValueError: The size argument must be greater than zero. + @raise WindowsError: On error an exception is raised. + """ + if size <= 0: + raise ValueError("The size argument must be greater than zero") + while size > 0: + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + if not mbi.has_content(): + return False + size = size - mbi.RegionSize + return True + + def is_buffer_readable(self, address, size): + """ + Determines if the given memory area is readable. + + @note: Returns always C{False} for kernel mode addresses. + + @see: L{mquery} + + @type address: int + @param address: Memory address. + + @type size: int + @param size: Number of bytes. Must be greater than zero. + + @rtype: bool + @return: C{True} if the memory area is readable, C{False} otherwise. + + @raise ValueError: The size argument must be greater than zero. + @raise WindowsError: On error an exception is raised. + """ + if size <= 0: + raise ValueError("The size argument must be greater than zero") + while size > 0: + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + if not mbi.is_readable(): + return False + size = size - mbi.RegionSize + return True + + def is_buffer_writeable(self, address, size): + """ + Determines if the given memory area is writeable. + + @note: Returns always C{False} for kernel mode addresses. + + @see: L{mquery} + + @type address: int + @param address: Memory address. + + @type size: int + @param size: Number of bytes. Must be greater than zero. + + @rtype: bool + @return: C{True} if the memory area is writeable, C{False} otherwise. + + @raise ValueError: The size argument must be greater than zero. + @raise WindowsError: On error an exception is raised. + """ + if size <= 0: + raise ValueError("The size argument must be greater than zero") + while size > 0: + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + if not mbi.is_writeable(): + return False + size = size - mbi.RegionSize + return True + + def is_buffer_copy_on_write(self, address, size): + """ + Determines if the given memory area is marked as copy-on-write. + + @note: Returns always C{False} for kernel mode addresses. + + @see: L{mquery} + + @type address: int + @param address: Memory address. + + @type size: int + @param size: Number of bytes. Must be greater than zero. + + @rtype: bool + @return: C{True} if the memory area is marked as copy-on-write, + C{False} otherwise. + + @raise ValueError: The size argument must be greater than zero. + @raise WindowsError: On error an exception is raised. + """ + if size <= 0: + raise ValueError("The size argument must be greater than zero") + while size > 0: + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + if not mbi.is_copy_on_write(): + return False + size = size - mbi.RegionSize + return True + + def is_buffer_executable(self, address, size): + """ + Determines if the given memory area is executable. + + @note: Returns always C{False} for kernel mode addresses. + + @see: L{mquery} + + @type address: int + @param address: Memory address. + + @type size: int + @param size: Number of bytes. Must be greater than zero. + + @rtype: bool + @return: C{True} if the memory area is executable, C{False} otherwise. + + @raise ValueError: The size argument must be greater than zero. + @raise WindowsError: On error an exception is raised. + """ + if size <= 0: + raise ValueError("The size argument must be greater than zero") + while size > 0: + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + if not mbi.is_executable(): + return False + size = size - mbi.RegionSize + return True + + def is_buffer_executable_and_writeable(self, address, size): + """ + Determines if the given memory area is writeable and executable. + + Looking for writeable and executable pages is important when + exploiting a software vulnerability. + + @note: Returns always C{False} for kernel mode addresses. + + @see: L{mquery} + + @type address: int + @param address: Memory address. + + @type size: int + @param size: Number of bytes. Must be greater than zero. + + @rtype: bool + @return: C{True} if the memory area is writeable and executable, + C{False} otherwise. + + @raise ValueError: The size argument must be greater than zero. + @raise WindowsError: On error an exception is raised. + """ + if size <= 0: + raise ValueError("The size argument must be greater than zero") + while size > 0: + try: + mbi = self.mquery(address) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + return False + raise + if not mbi.is_executable(): + return False + size = size - mbi.RegionSize + return True + + def get_memory_map(self, minAddr = None, maxAddr = None): + """ + Produces a memory map to the process address space. + + Optionally restrict the map to the given address range. + + @see: L{mquery} + + @type minAddr: int + @param minAddr: (Optional) Starting address in address range to query. + + @type maxAddr: int + @param maxAddr: (Optional) Ending address in address range to query. + + @rtype: list( L{win32.MemoryBasicInformation} ) + @return: List of memory region information objects. + """ + return list(self.iter_memory_map(minAddr, maxAddr)) + + def generate_memory_map(self, minAddr = None, maxAddr = None): + """ + Returns a L{Regenerator} that can iterate indefinitely over the memory + map to the process address space. + + Optionally restrict the map to the given address range. + + @see: L{mquery} + + @type minAddr: int + @param minAddr: (Optional) Starting address in address range to query. + + @type maxAddr: int + @param maxAddr: (Optional) Ending address in address range to query. + + @rtype: L{Regenerator} of L{win32.MemoryBasicInformation} + @return: List of memory region information objects. + """ + return Regenerator(self.iter_memory_map, minAddr, maxAddr) + + def iter_memory_map(self, minAddr = None, maxAddr = None): + """ + Produces an iterator over the memory map to the process address space. + + Optionally restrict the map to the given address range. + + @see: L{mquery} + + @type minAddr: int + @param minAddr: (Optional) Starting address in address range to query. + + @type maxAddr: int + @param maxAddr: (Optional) Ending address in address range to query. + + @rtype: iterator of L{win32.MemoryBasicInformation} + @return: List of memory region information objects. + """ + minAddr, maxAddr = MemoryAddresses.align_address_range(minAddr,maxAddr) + prevAddr = minAddr - 1 + currentAddr = minAddr + while prevAddr < currentAddr < maxAddr: + try: + mbi = self.mquery(currentAddr) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_INVALID_PARAMETER: + break + raise + yield mbi + prevAddr = currentAddr + currentAddr = mbi.BaseAddress + mbi.RegionSize + + def get_mapped_filenames(self, memoryMap = None): + """ + Retrieves the filenames for memory mapped files in the debugee. + + @type memoryMap: list( L{win32.MemoryBasicInformation} ) + @param memoryMap: (Optional) Memory map returned by L{get_memory_map}. + If not given, the current memory map is used. + + @rtype: dict( int S{->} str ) + @return: Dictionary mapping memory addresses to file names. + Native filenames are converted to Win32 filenames when possible. + """ + hProcess = self.get_handle( win32.PROCESS_VM_READ | + win32.PROCESS_QUERY_INFORMATION ) + if not memoryMap: + memoryMap = self.get_memory_map() + mappedFilenames = dict() + for mbi in memoryMap: + if mbi.Type not in (win32.MEM_IMAGE, win32.MEM_MAPPED): + continue + baseAddress = mbi.BaseAddress + fileName = "" + try: + fileName = win32.GetMappedFileName(hProcess, baseAddress) + fileName = PathOperations.native_to_win32_pathname(fileName) + except WindowsError: + #e = sys.exc_info()[1] + #try: + # msg = "Can't get mapped file name at address %s in process " \ + # "%d, reason: %s" % (HexDump.address(baseAddress), + # self.get_pid(), + # e.strerror) + # warnings.warn(msg, Warning) + #except Exception: + pass + mappedFilenames[baseAddress] = fileName + return mappedFilenames + + def generate_memory_snapshot(self, minAddr = None, maxAddr = None): + """ + Returns a L{Regenerator} that allows you to iterate through the memory + contents of a process indefinitely. + + It's basically the same as the L{take_memory_snapshot} method, but it + takes the snapshot of each memory region as it goes, as opposed to + taking the whole snapshot at once. This allows you to work with very + large snapshots without a significant performance penalty. + + Example:: + # Print the memory contents of a process. + process.suspend() + try: + snapshot = process.generate_memory_snapshot() + for mbi in snapshot: + print HexDump.hexblock(mbi.content, mbi.BaseAddress) + finally: + process.resume() + + The downside of this is the process must remain suspended while + iterating the snapshot, otherwise strange things may happen. + + The snapshot can be iterated more than once. Each time it's iterated + the memory contents of the process will be fetched again. + + You can also iterate the memory of a dead process, just as long as the + last open handle to it hasn't been closed. + + @see: L{take_memory_snapshot} + + @type minAddr: int + @param minAddr: (Optional) Starting address in address range to query. + + @type maxAddr: int + @param maxAddr: (Optional) Ending address in address range to query. + + @rtype: L{Regenerator} of L{win32.MemoryBasicInformation} + @return: Generator that when iterated returns memory region information + objects. Two extra properties are added to these objects: + - C{filename}: Mapped filename, or C{None}. + - C{content}: Memory contents, or C{None}. + """ + return Regenerator(self.iter_memory_snapshot, minAddr, maxAddr) + + def iter_memory_snapshot(self, minAddr = None, maxAddr = None): + """ + Returns an iterator that allows you to go through the memory contents + of a process. + + It's basically the same as the L{take_memory_snapshot} method, but it + takes the snapshot of each memory region as it goes, as opposed to + taking the whole snapshot at once. This allows you to work with very + large snapshots without a significant performance penalty. + + Example:: + # Print the memory contents of a process. + process.suspend() + try: + snapshot = process.generate_memory_snapshot() + for mbi in snapshot: + print HexDump.hexblock(mbi.content, mbi.BaseAddress) + finally: + process.resume() + + The downside of this is the process must remain suspended while + iterating the snapshot, otherwise strange things may happen. + + The snapshot can only iterated once. To be able to iterate indefinitely + call the L{generate_memory_snapshot} method instead. + + You can also iterate the memory of a dead process, just as long as the + last open handle to it hasn't been closed. + + @see: L{take_memory_snapshot} + + @type minAddr: int + @param minAddr: (Optional) Starting address in address range to query. + + @type maxAddr: int + @param maxAddr: (Optional) Ending address in address range to query. + + @rtype: iterator of L{win32.MemoryBasicInformation} + @return: Iterator of memory region information objects. + Two extra properties are added to these objects: + - C{filename}: Mapped filename, or C{None}. + - C{content}: Memory contents, or C{None}. + """ + + # One may feel tempted to include calls to self.suspend() and + # self.resume() here, but that wouldn't work on a dead process. + # It also wouldn't be needed when debugging since the process is + # already suspended when the debug event arrives. So it's up to + # the user to suspend the process if needed. + + # Get the memory map. + memory = self.get_memory_map(minAddr, maxAddr) + + # Abort if the map couldn't be retrieved. + if not memory: + return + + # Get the mapped filenames. + # Don't fail on access denied errors. + try: + filenames = self.get_mapped_filenames(memory) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror != win32.ERROR_ACCESS_DENIED: + raise + filenames = dict() + + # Trim the first memory information block if needed. + if minAddr is not None: + minAddr = MemoryAddresses.align_address_to_page_start(minAddr) + mbi = memory[0] + if mbi.BaseAddress < minAddr: + mbi.RegionSize = mbi.BaseAddress + mbi.RegionSize - minAddr + mbi.BaseAddress = minAddr + + # Trim the last memory information block if needed. + if maxAddr is not None: + if maxAddr != MemoryAddresses.align_address_to_page_start(maxAddr): + maxAddr = MemoryAddresses.align_address_to_page_end(maxAddr) + mbi = memory[-1] + if mbi.BaseAddress + mbi.RegionSize > maxAddr: + mbi.RegionSize = maxAddr - mbi.BaseAddress + + # Read the contents of each block and yield it. + while memory: + mbi = memory.pop(0) # so the garbage collector can take it + mbi.filename = filenames.get(mbi.BaseAddress, None) + if mbi.has_content(): + mbi.content = self.read(mbi.BaseAddress, mbi.RegionSize) + else: + mbi.content = None + yield mbi + + def take_memory_snapshot(self, minAddr = None, maxAddr = None): + """ + Takes a snapshot of the memory contents of the process. + + It's best if the process is suspended (if alive) when taking the + snapshot. Execution can be resumed afterwards. + + Example:: + # Print the memory contents of a process. + process.suspend() + try: + snapshot = process.take_memory_snapshot() + for mbi in snapshot: + print HexDump.hexblock(mbi.content, mbi.BaseAddress) + finally: + process.resume() + + You can also iterate the memory of a dead process, just as long as the + last open handle to it hasn't been closed. + + @warning: If the target process has a very big memory footprint, the + resulting snapshot will be equally big. This may result in a severe + performance penalty. + + @see: L{generate_memory_snapshot} + + @type minAddr: int + @param minAddr: (Optional) Starting address in address range to query. + + @type maxAddr: int + @param maxAddr: (Optional) Ending address in address range to query. + + @rtype: list( L{win32.MemoryBasicInformation} ) + @return: List of memory region information objects. + Two extra properties are added to these objects: + - C{filename}: Mapped filename, or C{None}. + - C{content}: Memory contents, or C{None}. + """ + return list( self.iter_memory_snapshot(minAddr, maxAddr) ) + + def restore_memory_snapshot(self, snapshot, + bSkipMappedFiles = True, + bSkipOnError = False): + """ + Attempts to restore the memory state as it was when the given snapshot + was taken. + + @warning: Currently only the memory contents, state and protect bits + are restored. Under some circumstances this method may fail (for + example if memory was freed and then reused by a mapped file). + + @type snapshot: list( L{win32.MemoryBasicInformation} ) + @param snapshot: Memory snapshot returned by L{take_memory_snapshot}. + Snapshots returned by L{generate_memory_snapshot} don't work here. + + @type bSkipMappedFiles: bool + @param bSkipMappedFiles: C{True} to avoid restoring the contents of + memory mapped files, C{False} otherwise. Use with care! Setting + this to C{False} can cause undesired side effects - changes to + memory mapped files may be written to disk by the OS. Also note + that most mapped files are typically executables and don't change, + so trying to restore their contents is usually a waste of time. + + @type bSkipOnError: bool + @param bSkipOnError: C{True} to issue a warning when an error occurs + during the restoration of the snapshot, C{False} to stop and raise + an exception instead. Use with care! Setting this to C{True} will + cause the debugger to falsely believe the memory snapshot has been + correctly restored. + + @raise WindowsError: An error occured while restoring the snapshot. + @raise RuntimeError: An error occured while restoring the snapshot. + @raise TypeError: A snapshot of the wrong type was passed. + """ + if not snapshot or not isinstance(snapshot, list) \ + or not isinstance(snapshot[0], win32.MemoryBasicInformation): + raise TypeError( "Only snapshots returned by " \ + "take_memory_snapshot() can be used here." ) + + # Get the process handle. + hProcess = self.get_handle( win32.PROCESS_VM_WRITE | + win32.PROCESS_VM_OPERATION | + win32.PROCESS_SUSPEND_RESUME | + win32.PROCESS_QUERY_INFORMATION ) + + # Freeze the process. + self.suspend() + try: + + # For each memory region in the snapshot... + for old_mbi in snapshot: + + # If the region matches, restore it directly. + new_mbi = self.mquery(old_mbi.BaseAddress) + if new_mbi.BaseAddress == old_mbi.BaseAddress and \ + new_mbi.RegionSize == old_mbi.RegionSize: + self.__restore_mbi(hProcess, new_mbi, old_mbi, + bSkipMappedFiles) + + # If the region doesn't match, restore it page by page. + else: + + # We need a copy so we don't corrupt the snapshot. + old_mbi = win32.MemoryBasicInformation(old_mbi) + + # Get the overlapping range of pages. + old_start = old_mbi.BaseAddress + old_end = old_start + old_mbi.RegionSize + new_start = new_mbi.BaseAddress + new_end = new_start + new_mbi.RegionSize + if old_start > new_start: + start = old_start + else: + start = new_start + if old_end < new_end: + end = old_end + else: + end = new_end + + # Restore each page in the overlapping range. + step = MemoryAddresses.pageSize + old_mbi.RegionSize = step + new_mbi.RegionSize = step + address = start + while address < end: + old_mbi.BaseAddress = address + new_mbi.BaseAddress = address + self.__restore_mbi(hProcess, new_mbi, old_mbi, + bSkipMappedFiles, bSkipOnError) + address = address + step + + # Resume execution. + finally: + self.resume() + + def __restore_mbi(self, hProcess, new_mbi, old_mbi, bSkipMappedFiles, + bSkipOnError): + """ + Used internally by L{restore_memory_snapshot}. + """ + +## print "Restoring %s-%s" % ( +## HexDump.address(old_mbi.BaseAddress, self.get_bits()), +## HexDump.address(old_mbi.BaseAddress + old_mbi.RegionSize, +## self.get_bits())) + + try: + + # Restore the region state. + if new_mbi.State != old_mbi.State: + if new_mbi.is_free(): + if old_mbi.is_reserved(): + + # Free -> Reserved + address = win32.VirtualAllocEx(hProcess, + old_mbi.BaseAddress, + old_mbi.RegionSize, + win32.MEM_RESERVE, + old_mbi.Protect) + if address != old_mbi.BaseAddress: + self.free(address) + msg = "Error restoring region at address %s" + msg = msg % HexDump(old_mbi.BaseAddress, + self.get_bits()) + raise RuntimeError(msg) + # permissions already restored + new_mbi.Protect = old_mbi.Protect + + else: # elif old_mbi.is_commited(): + + # Free -> Commited + address = win32.VirtualAllocEx(hProcess, + old_mbi.BaseAddress, + old_mbi.RegionSize, + win32.MEM_RESERVE | \ + win32.MEM_COMMIT, + old_mbi.Protect) + if address != old_mbi.BaseAddress: + self.free(address) + msg = "Error restoring region at address %s" + msg = msg % HexDump(old_mbi.BaseAddress, + self.get_bits()) + raise RuntimeError(msg) + # permissions already restored + new_mbi.Protect = old_mbi.Protect + + elif new_mbi.is_reserved(): + if old_mbi.is_commited(): + + # Reserved -> Commited + address = win32.VirtualAllocEx(hProcess, + old_mbi.BaseAddress, + old_mbi.RegionSize, + win32.MEM_COMMIT, + old_mbi.Protect) + if address != old_mbi.BaseAddress: + self.free(address) + msg = "Error restoring region at address %s" + msg = msg % HexDump(old_mbi.BaseAddress, + self.get_bits()) + raise RuntimeError(msg) + # permissions already restored + new_mbi.Protect = old_mbi.Protect + + else: # elif old_mbi.is_free(): + + # Reserved -> Free + win32.VirtualFreeEx(hProcess, + old_mbi.BaseAddress, + old_mbi.RegionSize, + win32.MEM_RELEASE) + + else: # elif new_mbi.is_commited(): + if old_mbi.is_reserved(): + + # Commited -> Reserved + win32.VirtualFreeEx(hProcess, + old_mbi.BaseAddress, + old_mbi.RegionSize, + win32.MEM_DECOMMIT) + + else: # elif old_mbi.is_free(): + + # Commited -> Free + win32.VirtualFreeEx(hProcess, + old_mbi.BaseAddress, + old_mbi.RegionSize, + win32.MEM_DECOMMIT | win32.MEM_RELEASE) + + new_mbi.State = old_mbi.State + + # Restore the region permissions. + if old_mbi.is_commited() and old_mbi.Protect != new_mbi.Protect: + win32.VirtualProtectEx(hProcess, old_mbi.BaseAddress, + old_mbi.RegionSize, old_mbi.Protect) + new_mbi.Protect = old_mbi.Protect + + # Restore the region data. + # Ignore write errors when the region belongs to a mapped file. + if old_mbi.has_content(): + if old_mbi.Type != 0: + if not bSkipMappedFiles: + self.poke(old_mbi.BaseAddress, old_mbi.content) + else: + self.write(old_mbi.BaseAddress, old_mbi.content) + new_mbi.content = old_mbi.content + + # On error, skip this region or raise an exception. + except Exception: + if not bSkipOnError: + raise + msg = "Error restoring region at address %s: %s" + msg = msg % ( + HexDump(old_mbi.BaseAddress, self.get_bits()), + traceback.format_exc()) + warnings.warn(msg, RuntimeWarning) + +#------------------------------------------------------------------------------ + + def inject_code(self, payload, lpParameter = 0): + """ + Injects relocatable code into the process memory and executes it. + + @warning: Don't forget to free the memory when you're done with it! + Otherwise you'll be leaking memory in the target process. + + @see: L{inject_dll} + + @type payload: str + @param payload: Relocatable code to run in a new thread. + + @type lpParameter: int + @param lpParameter: (Optional) Parameter to be pushed in the stack. + + @rtype: tuple( L{Thread}, int ) + @return: The injected Thread object + and the memory address where the code was written. + + @raise WindowsError: An exception is raised on error. + """ + + # Uncomment for debugging... +## payload = '\xCC' + payload + + # Allocate the memory for the shellcode. + lpStartAddress = self.malloc(len(payload)) + + # Catch exceptions so we can free the memory on error. + try: + + # Write the shellcode to our memory location. + self.write(lpStartAddress, payload) + + # Start a new thread for the shellcode to run. + aThread = self.start_thread(lpStartAddress, lpParameter, + bSuspended = False) + + # Remember the shellcode address. + # It will be freed ONLY by the Thread.kill() method + # and the EventHandler class, otherwise you'll have to + # free it in your code, or have your shellcode clean up + # after itself (recommended). + aThread.pInjectedMemory = lpStartAddress + + # Free the memory on error. + except Exception: + self.free(lpStartAddress) + raise + + # Return the Thread object and the shellcode address. + return aThread, lpStartAddress + + # TODO + # The shellcode should check for errors, otherwise it just crashes + # when the DLL can't be loaded or the procedure can't be found. + # On error the shellcode should execute an int3 instruction. + def inject_dll(self, dllname, procname = None, lpParameter = 0, + bWait = True, dwTimeout = None): + """ + Injects a DLL into the process memory. + + @warning: Setting C{bWait} to C{True} when the process is frozen by a + debug event will cause a deadlock in your debugger. + + @warning: This involves allocating memory in the target process. + This is how the freeing of this memory is handled: + + - If the C{bWait} flag is set to C{True} the memory will be freed + automatically before returning from this method. + - If the C{bWait} flag is set to C{False}, the memory address is + set as the L{Thread.pInjectedMemory} property of the returned + thread object. + - L{Debug} objects free L{Thread.pInjectedMemory} automatically + both when it detaches from a process and when the injected + thread finishes its execution. + - The {Thread.kill} method also frees L{Thread.pInjectedMemory} + automatically, even if you're not attached to the process. + + You could still be leaking memory if not careful. For example, if + you inject a dll into a process you're not attached to, you don't + wait for the thread's completion and you don't kill it either, the + memory would be leaked. + + @see: L{inject_code} + + @type dllname: str + @param dllname: Name of the DLL module to load. + + @type procname: str + @param procname: (Optional) Procedure to call when the DLL is loaded. + + @type lpParameter: int + @param lpParameter: (Optional) Parameter to the C{procname} procedure. + + @type bWait: bool + @param bWait: C{True} to wait for the process to finish. + C{False} to return immediately. + + @type dwTimeout: int + @param dwTimeout: (Optional) Timeout value in milliseconds. + Ignored if C{bWait} is C{False}. + + @rtype: L{Thread} + @return: Newly created thread object. If C{bWait} is set to C{True} the + thread will be dead, otherwise it will be alive. + + @raise NotImplementedError: The target platform is not supported. + Currently calling a procedure in the library is only supported in + the I{i386} architecture. + + @raise WindowsError: An exception is raised on error. + """ + + # Resolve kernel32.dll + aModule = self.get_module_by_name(compat.b('kernel32.dll')) + if aModule is None: + self.scan_modules() + aModule = self.get_module_by_name(compat.b('kernel32.dll')) + if aModule is None: + raise RuntimeError( + "Cannot resolve kernel32.dll in the remote process") + + # Old method, using shellcode. + if procname: + if self.get_arch() != win32.ARCH_I386: + raise NotImplementedError() + dllname = compat.b(dllname) + + # Resolve kernel32.dll!LoadLibraryA + pllib = aModule.resolve(compat.b('LoadLibraryA')) + if not pllib: + raise RuntimeError( + "Cannot resolve kernel32.dll!LoadLibraryA" + " in the remote process") + + # Resolve kernel32.dll!GetProcAddress + pgpad = aModule.resolve(compat.b('GetProcAddress')) + if not pgpad: + raise RuntimeError( + "Cannot resolve kernel32.dll!GetProcAddress" + " in the remote process") + + # Resolve kernel32.dll!VirtualFree + pvf = aModule.resolve(compat.b('VirtualFree')) + if not pvf: + raise RuntimeError( + "Cannot resolve kernel32.dll!VirtualFree" + " in the remote process") + + # Shellcode follows... + code = compat.b('') + + # push dllname + code += compat.b('\xe8') + struct.pack('= 2 and bAllowElevation: + pi = win32.CreateProcess(None, lpCmdLine, + bInheritHandles = bInheritHandles, + dwCreationFlags = dwCreationFlags, + lpStartupInfo = lpStartupInfo) + + # Create the process the hard way... + else: + + # If we allow elevation, use the current process token. + # If not, get the token from the current shell process. + hToken = None + try: + if not bAllowElevation: + if bFollow: + msg = ( + "Child processes can't be autofollowed" + " when dropping UAC elevation.") + raise NotImplementedError(msg) + if bConsole: + msg = ( + "Child processes can't inherit the debugger's" + " console when dropping UAC elevation.") + raise NotImplementedError(msg) + if bInheritHandles: + msg = ( + "Child processes can't inherit the debugger's" + " handles when dropping UAC elevation.") + raise NotImplementedError(msg) + try: + hWnd = self.get_shell_window() + except WindowsError: + hWnd = self.get_desktop_window() + shell = hWnd.get_process() + try: + hShell = shell.get_handle( + win32.PROCESS_QUERY_INFORMATION) + with win32.OpenProcessToken(hShell) as hShellToken: + hToken = win32.DuplicateTokenEx(hShellToken) + finally: + shell.close_handle() + + # Lower trust level if requested. + if iTrustLevel < 2: + if iTrustLevel > 0: + dwLevelId = win32.SAFER_LEVELID_NORMALUSER + else: + dwLevelId = win32.SAFER_LEVELID_UNTRUSTED + with win32.SaferCreateLevel(dwLevelId = dwLevelId) as hSafer: + hSaferToken = win32.SaferComputeTokenFromLevel( + hSafer, hToken)[0] + try: + if hToken is not None: + hToken.close() + except: + hSaferToken.close() + raise + hToken = hSaferToken + + # If we have a computed token, call CreateProcessAsUser(). + if bAllowElevation: + pi = win32.CreateProcessAsUser( + hToken = hToken, + lpCommandLine = lpCmdLine, + bInheritHandles = bInheritHandles, + dwCreationFlags = dwCreationFlags, + lpStartupInfo = lpStartupInfo) + + # If we have a primary token call CreateProcessWithToken(). + # The problem is, there are many flags CreateProcess() and + # CreateProcessAsUser() accept but CreateProcessWithToken() + # and CreateProcessWithLogonW() don't, so we need to work + # around them. + else: + + # Remove the debug flags. + dwCreationFlags &= ~win32.DEBUG_PROCESS + dwCreationFlags &= ~win32.DEBUG_ONLY_THIS_PROCESS + + # Remove the console flags. + dwCreationFlags &= ~win32.DETACHED_PROCESS + + # The process will be created suspended. + dwCreationFlags |= win32.CREATE_SUSPENDED + + # Create the process using the new primary token. + pi = win32.CreateProcessWithToken( + hToken = hToken, + dwLogonFlags = win32.LOGON_WITH_PROFILE, + lpCommandLine = lpCmdLine, + dwCreationFlags = dwCreationFlags, + lpStartupInfo = lpStartupInfo) + + # Attach as a debugger, if requested. + if bDebug: + win32.DebugActiveProcess(pi.dwProcessId) + + # Resume execution, if requested. + if not bSuspended: + win32.ResumeThread(pi.hThread) + + # Close the token when we're done with it. + finally: + if hToken is not None: + hToken.close() + + # Wrap the new process and thread in Process and Thread objects, + # and add them to the corresponding snapshots. + aProcess = Process(pi.dwProcessId, pi.hProcess) + aThread = Thread (pi.dwThreadId, pi.hThread) + aProcess._add_thread(aThread) + self._add_process(aProcess) + + # Clean up on error. + except: + if pi is not None: + try: + win32.TerminateProcess(pi.hProcess) + except WindowsError: + pass + pi.hThread.close() + pi.hProcess.close() + raise + + # Return the new Process object. + return aProcess + + def get_explorer_pid(self): + """ + Tries to find the process ID for "explorer.exe". + + @rtype: int or None + @return: Returns the process ID, or C{None} on error. + """ + try: + exp = win32.SHGetFolderPath(win32.CSIDL_WINDOWS) + except Exception: + exp = None + if not exp: + exp = os.getenv('SystemRoot') + if exp: + exp = os.path.join(exp, 'explorer.exe') + exp_list = self.find_processes_by_filename(exp) + if exp_list: + return exp_list[0][0].get_pid() + return None + +#------------------------------------------------------------------------------ + + # XXX this methods musn't end up calling __initialize_snapshot by accident! + + def scan(self): + """ + Populates the snapshot with running processes and threads, + and loaded modules. + + Tipically this is the first method called after instantiating a + L{System} object, as it makes a best effort approach to gathering + information on running processes. + + @rtype: bool + @return: C{True} if the snapshot is complete, C{False} if the debugger + doesn't have permission to scan some processes. In either case, the + snapshot is complete for all processes the debugger has access to. + """ + has_threads = True + try: + try: + + # Try using the Toolhelp API + # to scan for processes and threads. + self.scan_processes_and_threads() + + except Exception: + + # On error, try using the PSAPI to scan for process IDs only. + self.scan_processes_fast() + + # Now try using the Toolhelp again to get the threads. + for aProcess in self.__processDict.values(): + if aProcess._get_thread_ids(): + try: + aProcess.scan_threads() + except WindowsError: + has_threads = False + + finally: + + # Try using the Remote Desktop API to scan for processes only. + # This will update the filenames when it's not possible + # to obtain them from the Toolhelp API. + self.scan_processes() + + # When finished scanning for processes, try modules too. + has_modules = self.scan_modules() + + # Try updating the process filenames when possible. + has_full_names = self.scan_process_filenames() + + # Return the completion status. + return has_threads and has_modules and has_full_names + + def scan_processes_and_threads(self): + """ + Populates the snapshot with running processes and threads. + + Tipically you don't need to call this method directly, if unsure use + L{scan} instead. + + @note: This method uses the Toolhelp API. + + @see: L{scan_modules} + + @raise WindowsError: An error occured while updating the snapshot. + The snapshot was not modified. + """ + + # The main module filename may be spoofed by malware, + # since this information resides in usermode space. + # See: http://www.ragestorm.net/blogs/?p=163 + + our_pid = win32.GetCurrentProcessId() + dead_pids = set( compat.iterkeys(self.__processDict) ) + found_tids = set() + + # Ignore our own process if it's in the snapshot for some reason + if our_pid in dead_pids: + dead_pids.remove(our_pid) + + # Take a snapshot of all processes and threads + dwFlags = win32.TH32CS_SNAPPROCESS | win32.TH32CS_SNAPTHREAD + with win32.CreateToolhelp32Snapshot(dwFlags) as hSnapshot: + + # Add all the processes (excluding our own) + pe = win32.Process32First(hSnapshot) + while pe is not None: + dwProcessId = pe.th32ProcessID + if dwProcessId != our_pid: + if dwProcessId in dead_pids: + dead_pids.remove(dwProcessId) + if dwProcessId not in self.__processDict: + aProcess = Process(dwProcessId, fileName=pe.szExeFile) + self._add_process(aProcess) + elif pe.szExeFile: + aProcess = self.get_process(dwProcessId) + if not aProcess.fileName: + aProcess.fileName = pe.szExeFile + pe = win32.Process32Next(hSnapshot) + + # Add all the threads + te = win32.Thread32First(hSnapshot) + while te is not None: + dwProcessId = te.th32OwnerProcessID + if dwProcessId != our_pid: + if dwProcessId in dead_pids: + dead_pids.remove(dwProcessId) + if dwProcessId in self.__processDict: + aProcess = self.get_process(dwProcessId) + else: + aProcess = Process(dwProcessId) + self._add_process(aProcess) + dwThreadId = te.th32ThreadID + found_tids.add(dwThreadId) + if not aProcess._has_thread_id(dwThreadId): + aThread = Thread(dwThreadId, process = aProcess) + aProcess._add_thread(aThread) + te = win32.Thread32Next(hSnapshot) + + # Remove dead processes + for pid in dead_pids: + self._del_process(pid) + + # Remove dead threads + for aProcess in compat.itervalues(self.__processDict): + dead_tids = set( aProcess._get_thread_ids() ) + dead_tids.difference_update(found_tids) + for tid in dead_tids: + aProcess._del_thread(tid) + + def scan_modules(self): + """ + Populates the snapshot with loaded modules. + + Tipically you don't need to call this method directly, if unsure use + L{scan} instead. + + @note: This method uses the Toolhelp API. + + @see: L{scan_processes_and_threads} + + @rtype: bool + @return: C{True} if the snapshot is complete, C{False} if the debugger + doesn't have permission to scan some processes. In either case, the + snapshot is complete for all processes the debugger has access to. + """ + complete = True + for aProcess in compat.itervalues(self.__processDict): + try: + aProcess.scan_modules() + except WindowsError: + complete = False + return complete + + def scan_processes(self): + """ + Populates the snapshot with running processes. + + Tipically you don't need to call this method directly, if unsure use + L{scan} instead. + + @note: This method uses the Remote Desktop API instead of the Toolhelp + API. It might give slightly different results, especially if the + current process does not have full privileges. + + @note: This method will only retrieve process filenames. To get the + process pathnames instead, B{after} this method call + L{scan_process_filenames}. + + @raise WindowsError: An error occured while updating the snapshot. + The snapshot was not modified. + """ + + # Get the previous list of PIDs. + # We'll be removing live PIDs from it as we find them. + our_pid = win32.GetCurrentProcessId() + dead_pids = set( compat.iterkeys(self.__processDict) ) + + # Ignore our own PID. + if our_pid in dead_pids: + dead_pids.remove(our_pid) + + # Get the list of processes from the Remote Desktop API. + pProcessInfo = None + try: + pProcessInfo, dwCount = win32.WTSEnumerateProcesses( + win32.WTS_CURRENT_SERVER_HANDLE) + + # For each process found... + for index in compat.xrange(dwCount): + sProcessInfo = pProcessInfo[index] + +## # Ignore processes belonging to other sessions. +## if sProcessInfo.SessionId != win32.WTS_CURRENT_SESSION: +## continue + + # Ignore our own PID. + pid = sProcessInfo.ProcessId + if pid == our_pid: + continue + + # Remove the PID from the dead PIDs list. + if pid in dead_pids: + dead_pids.remove(pid) + + # Get the "process name". + # Empirically, this seems to be the filename without the path. + # (The MSDN docs aren't very clear about this API call). + fileName = sProcessInfo.pProcessName + + # If the process is new, add a new Process object. + if pid not in self.__processDict: + aProcess = Process(pid, fileName = fileName) + self._add_process(aProcess) + + # If the process was already in the snapshot, and the + # filename is missing, update the Process object. + elif fileName: + aProcess = self.__processDict.get(pid) + if not aProcess.fileName: + aProcess.fileName = fileName + + # Free the memory allocated by the Remote Desktop API. + finally: + if pProcessInfo is not None: + try: + win32.WTSFreeMemory(pProcessInfo) + except WindowsError: + pass + + # At this point the only remaining PIDs from the old list are dead. + # Remove them from the snapshot. + for pid in dead_pids: + self._del_process(pid) + + def scan_processes_fast(self): + """ + Populates the snapshot with running processes. + Only the PID is retrieved for each process. + + Dead processes are removed. + Threads and modules of living processes are ignored. + + Tipically you don't need to call this method directly, if unsure use + L{scan} instead. + + @note: This method uses the PSAPI. It may be faster for scanning, + but some information may be missing, outdated or slower to obtain. + This could be a good tradeoff under some circumstances. + """ + + # Get the new and old list of pids + new_pids = set( win32.EnumProcesses() ) + old_pids = set( compat.iterkeys(self.__processDict) ) + + # Ignore our own pid + our_pid = win32.GetCurrentProcessId() + if our_pid in new_pids: + new_pids.remove(our_pid) + if our_pid in old_pids: + old_pids.remove(our_pid) + + # Add newly found pids + for pid in new_pids.difference(old_pids): + self._add_process( Process(pid) ) + + # Remove missing pids + for pid in old_pids.difference(new_pids): + self._del_process(pid) + + def scan_process_filenames(self): + """ + Update the filename for each process in the snapshot when possible. + + @note: Tipically you don't need to call this method. It's called + automatically by L{scan} to get the full pathname for each process + when possible, since some scan methods only get filenames without + the path component. + + If unsure, use L{scan} instead. + + @see: L{scan}, L{Process.get_filename} + + @rtype: bool + @return: C{True} if all the pathnames were retrieved, C{False} if the + debugger doesn't have permission to scan some processes. In either + case, all processes the debugger has access to have a full pathname + instead of just a filename. + """ + complete = True + for aProcess in self.__processDict.values(): + try: + new_name = None + old_name = aProcess.fileName + try: + aProcess.fileName = None + new_name = aProcess.get_filename() + finally: + if not new_name: + aProcess.fileName = old_name + complete = False + except Exception: + complete = False + return complete + +#------------------------------------------------------------------------------ + + def clear_dead_processes(self): + """ + Removes Process objects from the snapshot + referring to processes no longer running. + """ + for pid in self.get_process_ids(): + aProcess = self.get_process(pid) + if not aProcess.is_alive(): + self._del_process(aProcess) + + def clear_unattached_processes(self): + """ + Removes Process objects from the snapshot + referring to processes not being debugged. + """ + for pid in self.get_process_ids(): + aProcess = self.get_process(pid) + if not aProcess.is_being_debugged(): + self._del_process(aProcess) + + def close_process_handles(self): + """ + Closes all open handles to processes in this snapshot. + """ + for pid in self.get_process_ids(): + aProcess = self.get_process(pid) + try: + aProcess.close_handle() + except Exception: + e = sys.exc_info()[1] + try: + msg = "Cannot close process handle %s, reason: %s" + msg %= (aProcess.hProcess.value, str(e)) + warnings.warn(msg) + except Exception: + pass + + def close_process_and_thread_handles(self): + """ + Closes all open handles to processes and threads in this snapshot. + """ + for aProcess in self.iter_processes(): + aProcess.close_thread_handles() + try: + aProcess.close_handle() + except Exception: + e = sys.exc_info()[1] + try: + msg = "Cannot close process handle %s, reason: %s" + msg %= (aProcess.hProcess.value, str(e)) + warnings.warn(msg) + except Exception: + pass + + def clear_processes(self): + """ + Removes all L{Process}, L{Thread} and L{Module} objects in this snapshot. + """ + #self.close_process_and_thread_handles() + for aProcess in self.iter_processes(): + aProcess.clear() + self.__processDict = dict() + + def clear(self): + """ + Clears this snapshot. + + @see: L{clear_processes} + """ + self.clear_processes() + +#------------------------------------------------------------------------------ + + # Docs for these methods are taken from the _ThreadContainer class. + + def has_thread(self, dwThreadId): + dwProcessId = self.get_pid_from_tid(dwThreadId) + if dwProcessId is None: + return False + return self.has_process(dwProcessId) + + def get_thread(self, dwThreadId): + dwProcessId = self.get_pid_from_tid(dwThreadId) + if dwProcessId is None: + msg = "Unknown thread ID %d" % dwThreadId + raise KeyError(msg) + return self.get_process(dwProcessId).get_thread(dwThreadId) + + def get_thread_ids(self): + ids = list() + for aProcess in self.iter_processes(): + ids += aProcess.get_thread_ids() + return ids + + def get_thread_count(self): + count = 0 + for aProcess in self.iter_processes(): + count += aProcess.get_thread_count() + return count + + has_thread.__doc__ = _ThreadContainer.has_thread.__doc__ + get_thread.__doc__ = _ThreadContainer.get_thread.__doc__ + get_thread_ids.__doc__ = _ThreadContainer.get_thread_ids.__doc__ + get_thread_count.__doc__ = _ThreadContainer.get_thread_count.__doc__ + +#------------------------------------------------------------------------------ + + # Docs for these methods are taken from the _ModuleContainer class. + + def get_module_count(self): + count = 0 + for aProcess in self.iter_processes(): + count += aProcess.get_module_count() + return count + + get_module_count.__doc__ = _ModuleContainer.get_module_count.__doc__ + +#------------------------------------------------------------------------------ + + def find_modules_by_base(self, lpBaseOfDll): + """ + @rtype: list( L{Module}... ) + @return: List of Module objects with the given base address. + """ + found = list() + for aProcess in self.iter_processes(): + if aProcess.has_module(lpBaseOfDll): + aModule = aProcess.get_module(lpBaseOfDll) + found.append( (aProcess, aModule) ) + return found + + def find_modules_by_name(self, fileName): + """ + @rtype: list( L{Module}... ) + @return: List of Module objects found. + """ + found = list() + for aProcess in self.iter_processes(): + aModule = aProcess.get_module_by_name(fileName) + if aModule is not None: + found.append( (aProcess, aModule) ) + return found + + def find_modules_by_address(self, address): + """ + @rtype: list( L{Module}... ) + @return: List of Module objects that best match the given address. + """ + found = list() + for aProcess in self.iter_processes(): + aModule = aProcess.get_module_at_address(address) + if aModule is not None: + found.append( (aProcess, aModule) ) + return found + + def __find_processes_by_filename(self, filename): + """ + Internally used by L{find_processes_by_filename}. + """ + found = list() + filename = filename.lower() + if PathOperations.path_is_absolute(filename): + for aProcess in self.iter_processes(): + imagename = aProcess.get_filename() + if imagename and imagename.lower() == filename: + found.append( (aProcess, imagename) ) + else: + for aProcess in self.iter_processes(): + imagename = aProcess.get_filename() + if imagename: + imagename = PathOperations.pathname_to_filename(imagename) + if imagename.lower() == filename: + found.append( (aProcess, imagename) ) + return found + + def find_processes_by_filename(self, fileName): + """ + @type fileName: str + @param fileName: Filename to search for. + If it's a full pathname, the match must be exact. + If it's a base filename only, the file part is matched, + regardless of the directory where it's located. + + @note: If the process is not found and the file extension is not + given, this method will search again assuming a default + extension (.exe). + + @rtype: list of tuple( L{Process}, str ) + @return: List of processes matching the given main module filename. + Each tuple contains a Process object and it's filename. + """ + found = self.__find_processes_by_filename(fileName) + if not found: + fn, ext = PathOperations.split_extension(fileName) + if not ext: + fileName = '%s.exe' % fn + found = self.__find_processes_by_filename(fileName) + return found + +#------------------------------------------------------------------------------ + + # XXX _notify_* methods should not trigger a scan + + def _add_process(self, aProcess): + """ + Private method to add a process object to the snapshot. + + @type aProcess: L{Process} + @param aProcess: Process object. + """ +## if not isinstance(aProcess, Process): +## if hasattr(aProcess, '__class__'): +## typename = aProcess.__class__.__name__ +## else: +## typename = str(type(aProcess)) +## msg = "Expected Process, got %s instead" % typename +## raise TypeError(msg) + dwProcessId = aProcess.dwProcessId +## if dwProcessId in self.__processDict: +## msg = "Process already exists: %d" % dwProcessId +## raise KeyError(msg) + self.__processDict[dwProcessId] = aProcess + + def _del_process(self, dwProcessId): + """ + Private method to remove a process object from the snapshot. + + @type dwProcessId: int + @param dwProcessId: Global process ID. + """ + try: + aProcess = self.__processDict[dwProcessId] + del self.__processDict[dwProcessId] + except KeyError: + aProcess = None + msg = "Unknown process ID %d" % dwProcessId + warnings.warn(msg, RuntimeWarning) + if aProcess: + aProcess.clear() # remove circular references + + # Notify the creation of a new process. + def _notify_create_process(self, event): + """ + Notify the creation of a new process. + + This is done automatically by the L{Debug} class, you shouldn't need + to call it yourself. + + @type event: L{CreateProcessEvent} + @param event: Create process event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + dwProcessId = event.get_pid() + dwThreadId = event.get_tid() + hProcess = event.get_process_handle() +## if not self.has_process(dwProcessId): # XXX this would trigger a scan + if dwProcessId not in self.__processDict: + aProcess = Process(dwProcessId, hProcess) + self._add_process(aProcess) + aProcess.fileName = event.get_filename() + else: + aProcess = self.get_process(dwProcessId) + #if hProcess != win32.INVALID_HANDLE_VALUE: + # aProcess.hProcess = hProcess # may have more privileges + if not aProcess.fileName: + fileName = event.get_filename() + if fileName: + aProcess.fileName = fileName + return aProcess._notify_create_process(event) # pass it to the process + + def _notify_exit_process(self, event): + """ + Notify the termination of a process. + + This is done automatically by the L{Debug} class, you shouldn't need + to call it yourself. + + @type event: L{ExitProcessEvent} + @param event: Exit process event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + dwProcessId = event.get_pid() +## if self.has_process(dwProcessId): # XXX this would trigger a scan + if dwProcessId in self.__processDict: + self._del_process(dwProcessId) + return True diff --git a/pydevd_attach_to_process/winappdbg/registry.py b/pydevd_attach_to_process/winappdbg/registry.py new file mode 100644 index 0000000..5623b80 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/registry.py @@ -0,0 +1,695 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Registry access. + +@group Instrumentation: + Registry, RegistryKey +""" + +from __future__ import with_statement + +__revision__ = "$Id$" + +__all__ = ['Registry'] + +import sys +from winappdbg import win32 +from winappdbg import compat +import collections +import warnings + +#============================================================================== + +class _RegistryContainer (object): + """ + Base class for L{Registry} and L{RegistryKey}. + """ + + # Dummy object to detect empty arguments. + class __EmptyArgument: + pass + __emptyArgument = __EmptyArgument() + + def __init__(self): + self.__default = None + + def has_key(self, name): + return name in self + + def get(self, name, default=__emptyArgument): + try: + return self[name] + except KeyError: + if default is RegistryKey.__emptyArgument: + return self.__default + return default + + def setdefault(self, default): + self.__default = default + + def __iter__(self): + return compat.iterkeys(self) + +#============================================================================== + +class RegistryKey (_RegistryContainer): + """ + Exposes a single Windows Registry key as a dictionary-like object. + + @see: L{Registry} + + @type path: str + @ivar path: Registry key path. + + @type handle: L{win32.RegistryKeyHandle} + @ivar handle: Registry key handle. + """ + + def __init__(self, path, handle): + """ + @type path: str + @param path: Registry key path. + + @type handle: L{win32.RegistryKeyHandle} + @param handle: Registry key handle. + """ + super(RegistryKey, self).__init__() + if path.endswith('\\'): + path = path[:-1] + self._path = path + self._handle = handle + + @property + def path(self): + return self._path + + @property + def handle(self): + #if not self._handle: + # msg = "This Registry key handle has already been closed." + # raise RuntimeError(msg) + return self._handle + + #def close(self): + # """ + # Close the Registry key handle, freeing its resources. It cannot be + # used again after calling this method. + # + # @note: This method will be called automatically by the garbage + # collector, and upon exiting a "with" block. + # + # @raise RuntimeError: This Registry key handle has already been closed. + # """ + # self.handle.close() + # + #def __enter__(self): + # """ + # Compatibility with the "C{with}" Python statement. + # """ + # return self + # + #def __exit__(self, type, value, traceback): + # """ + # Compatibility with the "C{with}" Python statement. + # """ + # try: + # self.close() + # except Exception: + # pass + + def __contains__(self, name): + try: + win32.RegQueryValueEx(self.handle, name, False) + return True + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_FILE_NOT_FOUND: + return False + raise + + def __getitem__(self, name): + try: + return win32.RegQueryValueEx(self.handle, name)[0] + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_FILE_NOT_FOUND: + raise KeyError(name) + raise + + def __setitem__(self, name, value): + win32.RegSetValueEx(self.handle, name, value) + + def __delitem__(self, name): + win32.RegDeleteValue(self.handle, name) + + def iterkeys(self): + handle = self.handle + index = 0 + while 1: + resp = win32.RegEnumValue(handle, index, False) + if resp is None: + break + yield resp[0] + index += 1 + + def itervalues(self): + handle = self.handle + index = 0 + while 1: + resp = win32.RegEnumValue(handle, index) + if resp is None: + break + yield resp[2] + index += 1 + + def iteritems(self): + handle = self.handle + index = 0 + while 1: + resp = win32.RegEnumValue(handle, index) + if resp is None: + break + yield resp[0], resp[2] + index += 1 + + def keys(self): + # return list(self.iterkeys()) # that can't be optimized by psyco + handle = self.handle + keys = list() + index = 0 + while 1: + resp = win32.RegEnumValue(handle, index, False) + if resp is None: + break + keys.append(resp[0]) + index += 1 + return keys + + def values(self): + # return list(self.itervalues()) # that can't be optimized by psyco + handle = self.handle + values = list() + index = 0 + while 1: + resp = win32.RegEnumValue(handle, index) + if resp is None: + break + values.append(resp[2]) + index += 1 + return values + + def items(self): + # return list(self.iteritems()) # that can't be optimized by psyco + handle = self.handle + items = list() + index = 0 + while 1: + resp = win32.RegEnumValue(handle, index) + if resp is None: + break + items.append( (resp[0], resp[2]) ) + index += 1 + return items + + def get_value_type(self, name): + """ + Retrieves the low-level data type for the given value. + + @type name: str + @param name: Registry value name. + + @rtype: int + @return: One of the following constants: + - L{win32.REG_NONE} (0) + - L{win32.REG_SZ} (1) + - L{win32.REG_EXPAND_SZ} (2) + - L{win32.REG_BINARY} (3) + - L{win32.REG_DWORD} (4) + - L{win32.REG_DWORD_BIG_ENDIAN} (5) + - L{win32.REG_LINK} (6) + - L{win32.REG_MULTI_SZ} (7) + - L{win32.REG_RESOURCE_LIST} (8) + - L{win32.REG_FULL_RESOURCE_DESCRIPTOR} (9) + - L{win32.REG_RESOURCE_REQUIREMENTS_LIST} (10) + - L{win32.REG_QWORD} (11) + + @raise KeyError: The specified value could not be found. + """ + try: + return win32.RegQueryValueEx(self.handle, name)[1] + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_FILE_NOT_FOUND: + raise KeyError(name) + raise + + def clear(self): + handle = self.handle + while 1: + resp = win32.RegEnumValue(handle, 0, False) + if resp is None: + break + win32.RegDeleteValue(handle, resp[0]) + + def __str__(self): + default = self[''] + return str(default) + + def __unicode__(self): + default = self[u''] + return compat.unicode(default) + + def __repr__(self): + return '' % self._path + + def iterchildren(self): + """ + Iterates the subkeys for this Registry key. + + @rtype: iter of L{RegistryKey} + @return: Iterator of subkeys. + """ + handle = self.handle + index = 0 + while 1: + subkey = win32.RegEnumKey(handle, index) + if subkey is None: + break + yield self.child(subkey) + index += 1 + + def children(self): + """ + Returns a list of subkeys for this Registry key. + + @rtype: list(L{RegistryKey}) + @return: List of subkeys. + """ + # return list(self.iterchildren()) # that can't be optimized by psyco + handle = self.handle + result = [] + index = 0 + while 1: + subkey = win32.RegEnumKey(handle, index) + if subkey is None: + break + result.append( self.child(subkey) ) + index += 1 + return result + + def child(self, subkey): + """ + Retrieves a subkey for this Registry key, given its name. + + @type subkey: str + @param subkey: Name of the subkey. + + @rtype: L{RegistryKey} + @return: Subkey. + """ + path = self._path + '\\' + subkey + handle = win32.RegOpenKey(self.handle, subkey) + return RegistryKey(path, handle) + + def flush(self): + """ + Flushes changes immediately to disk. + + This method is normally not needed, as the Registry writes changes + to disk by itself. This mechanism is provided to ensure the write + happens immediately, as opposed to whenever the OS wants to. + + @warn: Calling this method too often may degrade performance. + """ + win32.RegFlushKey(self.handle) + +#============================================================================== + +# TODO: possibly cache the RegistryKey objects +# to avoid opening and closing handles many times on code sequences like this: +# +# r = Registry() +# r['HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Run']['Example 1'] = 'example1.exe' +# r['HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Run']['Example 2'] = 'example2.exe' +# r['HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Run']['Example 3'] = 'example3.exe' + +# TODO: support for access flags? +# TODO: should be possible to disable the safety checks (see __delitem__) + +# TODO: workaround for an API bug described by a user in MSDN +# +# http://msdn.microsoft.com/en-us/library/windows/desktop/aa379776(v=vs.85).aspx +# +# Apparently RegDeleteTree won't work remotely from Win7 to WinXP, and the only +# solution is to recursively call RegDeleteKey. + +class Registry (_RegistryContainer): + """ + Exposes the Windows Registry as a Python container. + + @type machine: str or None + @ivar machine: For a remote Registry, the machine name. + For a local Registry, the value is C{None}. + """ + + _hives_by_name = { + + # Short names + 'HKCR' : win32.HKEY_CLASSES_ROOT, + 'HKCU' : win32.HKEY_CURRENT_USER, + 'HKLM' : win32.HKEY_LOCAL_MACHINE, + 'HKU' : win32.HKEY_USERS, + 'HKPD' : win32.HKEY_PERFORMANCE_DATA, + 'HKCC' : win32.HKEY_CURRENT_CONFIG, + + # Long names + 'HKEY_CLASSES_ROOT' : win32.HKEY_CLASSES_ROOT, + 'HKEY_CURRENT_USER' : win32.HKEY_CURRENT_USER, + 'HKEY_LOCAL_MACHINE' : win32.HKEY_LOCAL_MACHINE, + 'HKEY_USERS' : win32.HKEY_USERS, + 'HKEY_PERFORMANCE_DATA' : win32.HKEY_PERFORMANCE_DATA, + 'HKEY_CURRENT_CONFIG' : win32.HKEY_CURRENT_CONFIG, + } + + _hives_by_value = { + win32.HKEY_CLASSES_ROOT : 'HKEY_CLASSES_ROOT', + win32.HKEY_CURRENT_USER : 'HKEY_CURRENT_USER', + win32.HKEY_LOCAL_MACHINE : 'HKEY_LOCAL_MACHINE', + win32.HKEY_USERS : 'HKEY_USERS', + win32.HKEY_PERFORMANCE_DATA : 'HKEY_PERFORMANCE_DATA', + win32.HKEY_CURRENT_CONFIG : 'HKEY_CURRENT_CONFIG', + } + + _hives = sorted(compat.itervalues(_hives_by_value)) + + def __init__(self, machine = None): + """ + Opens a local or remote registry. + + @type machine: str + @param machine: Optional machine name. If C{None} it opens the local + registry. + """ + self._machine = machine + self._remote_hives = {} + + @property + def machine(self): + return self._machine + + def _split_path(self, path): + """ + Splits a Registry path and returns the hive and key. + + @type path: str + @param path: Registry path. + + @rtype: tuple( int, str ) + @return: Tuple containing the hive handle and the subkey path. + The hive handle is always one of the following integer constants: + - L{win32.HKEY_CLASSES_ROOT} + - L{win32.HKEY_CURRENT_USER} + - L{win32.HKEY_LOCAL_MACHINE} + - L{win32.HKEY_USERS} + - L{win32.HKEY_PERFORMANCE_DATA} + - L{win32.HKEY_CURRENT_CONFIG} + """ + if '\\' in path: + p = path.find('\\') + hive = path[:p] + path = path[p+1:] + else: + hive = path + path = None + handle = self._hives_by_name[ hive.upper() ] + return handle, path + + def _parse_path(self, path): + """ + Parses a Registry path and returns the hive and key. + + @type path: str + @param path: Registry path. + + @rtype: tuple( int, str ) + @return: Tuple containing the hive handle and the subkey path. + For a local Registry, the hive handle is an integer. + For a remote Registry, the hive handle is a L{RegistryKeyHandle}. + """ + handle, path = self._split_path(path) + if self._machine is not None: + handle = self._connect_hive(handle) + return handle, path + + def _join_path(self, hive, subkey): + """ + Joins the hive and key to make a Registry path. + + @type hive: int + @param hive: Registry hive handle. + The hive handle must be one of the following integer constants: + - L{win32.HKEY_CLASSES_ROOT} + - L{win32.HKEY_CURRENT_USER} + - L{win32.HKEY_LOCAL_MACHINE} + - L{win32.HKEY_USERS} + - L{win32.HKEY_PERFORMANCE_DATA} + - L{win32.HKEY_CURRENT_CONFIG} + + @type subkey: str + @param subkey: Subkey path. + + @rtype: str + @return: Registry path. + """ + path = self._hives_by_value[hive] + if subkey: + path = path + '\\' + subkey + return path + + def _sanitize_path(self, path): + """ + Sanitizes the given Registry path. + + @type path: str + @param path: Registry path. + + @rtype: str + @return: Registry path. + """ + return self._join_path( *self._split_path(path) ) + + def _connect_hive(self, hive): + """ + Connect to the specified hive of a remote Registry. + + @note: The connection will be cached, to close all connections and + erase this cache call the L{close} method. + + @type hive: int + @param hive: Hive to connect to. + + @rtype: L{win32.RegistryKeyHandle} + @return: Open handle to the remote Registry hive. + """ + try: + handle = self._remote_hives[hive] + except KeyError: + handle = win32.RegConnectRegistry(self._machine, hive) + self._remote_hives[hive] = handle + return handle + + def close(self): + """ + Closes all open connections to the remote Registry. + + No exceptions are raised, even if an error occurs. + + This method has no effect when opening the local Registry. + + The remote Registry will still be accessible after calling this method + (new connections will be opened automatically on access). + """ + while self._remote_hives: + hive = self._remote_hives.popitem()[1] + try: + hive.close() + except Exception: + try: + e = sys.exc_info()[1] + msg = "Cannot close registry hive handle %s, reason: %s" + msg %= (hive.value, str(e)) + warnings.warn(msg) + except Exception: + pass + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + def __repr__(self): + if self._machine: + return '' % self._machine + return '' + + def __contains__(self, path): + hive, subpath = self._parse_path(path) + try: + with win32.RegOpenKey(hive, subpath): + return True + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_FILE_NOT_FOUND: + return False + raise + + def __getitem__(self, path): + path = self._sanitize_path(path) + hive, subpath = self._parse_path(path) + try: + handle = win32.RegOpenKey(hive, subpath) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_FILE_NOT_FOUND: + raise KeyError(path) + raise + return RegistryKey(path, handle) + + def __setitem__(self, path, value): + do_copy = isinstance(value, RegistryKey) + if not do_copy and not isinstance(value, str) \ + and not isinstance(value, compat.unicode): + if isinstance(value, object): + t = value.__class__.__name__ + else: + t = type(value) + raise TypeError("Expected string or RegistryKey, got %s" % t) + hive, subpath = self._parse_path(path) + with win32.RegCreateKey(hive, subpath) as handle: + if do_copy: + win32.RegCopyTree(value.handle, None, handle) + else: + win32.RegSetValueEx(handle, None, value) + + # XXX FIXME currently not working! + # It's probably best to call RegDeleteKey recursively, even if slower. + def __delitem__(self, path): + hive, subpath = self._parse_path(path) + if not subpath: + raise TypeError( + "Are you SURE you want to wipe out an entire hive?!" + " Call win32.RegDeleteTree() directly if you must...") + try: + win32.RegDeleteTree(hive, subpath) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror == win32.ERROR_FILE_NOT_FOUND: + raise KeyError(path) + raise + + def create(self, path): + """ + Creates a new Registry key. + + @type path: str + @param path: Registry key path. + + @rtype: L{RegistryKey} + @return: The newly created Registry key. + """ + path = self._sanitize_path(path) + hive, subpath = self._parse_path(path) + handle = win32.RegCreateKey(hive, subpath) + return RegistryKey(path, handle) + + def subkeys(self, path): + """ + Returns a list of subkeys for the given Registry key. + + @type path: str + @param path: Registry key path. + + @rtype: list(str) + @return: List of subkey names. + """ + result = list() + hive, subpath = self._parse_path(path) + with win32.RegOpenKey(hive, subpath) as handle: + index = 0 + while 1: + name = win32.RegEnumKey(handle, index) + if name is None: + break + result.append(name) + index += 1 + return result + + def iterate(self, path): + """ + Returns a recursive iterator on the specified key and its subkeys. + + @type path: str + @param path: Registry key path. + + @rtype: iterator + @return: Recursive iterator that returns Registry key paths. + + @raise KeyError: The specified path does not exist. + """ + if path.endswith('\\'): + path = path[:-1] + if not self.has_key(path): + raise KeyError(path) + stack = collections.deque() + stack.appendleft(path) + return self.__iterate(stack) + + def iterkeys(self): + """ + Returns an iterator that crawls the entire Windows Registry. + """ + stack = collections.deque(self._hives) + stack.reverse() + return self.__iterate(stack) + + def __iterate(self, stack): + while stack: + path = stack.popleft() + yield path + try: + subkeys = self.subkeys(path) + except WindowsError: + continue + prefix = path + '\\' + subkeys = [prefix + name for name in subkeys] + stack.extendleft(subkeys) diff --git a/pydevd_attach_to_process/winappdbg/search.py b/pydevd_attach_to_process/winappdbg/search.py new file mode 100644 index 0000000..6efaea6 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/search.py @@ -0,0 +1,665 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Process memory finder +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Process memory search. + +@group Memory search: + Search, + Pattern, + BytePattern, + TextPattern, + RegExpPattern, + HexPattern +""" + +__revision__ = "$Id$" + +__all__ = [ + 'Search', + 'Pattern', + 'BytePattern', + 'TextPattern', + 'RegExpPattern', + 'HexPattern', + ] + +from winappdbg.textio import HexInput +from winappdbg.util import StaticClass, MemoryAddresses +from winappdbg import win32 + +import warnings + +try: + # http://pypi.python.org/pypi/regex + import regex as re +except ImportError: + import re + +#============================================================================== + +class Pattern (object): + """ + Base class for search patterns. + + The following L{Pattern} subclasses are provided by WinAppDbg: + - L{BytePattern} + - L{TextPattern} + - L{RegExpPattern} + - L{HexPattern} + + @see: L{Search.search_process} + """ + + def __init__(self, pattern): + """ + Class constructor. + + The only mandatory argument should be the pattern string. + + This method B{MUST} be reimplemented by subclasses of L{Pattern}. + """ + raise NotImplementedError() + + def __len__(self): + """ + Returns the maximum expected length of the strings matched by this + pattern. Exact behavior is implementation dependent. + + Ideally it should be an exact value, but in some cases it's not + possible to calculate so an upper limit should be returned instead. + + If that's not possible either an exception must be raised. + + This value will be used to calculate the required buffer size when + doing buffered searches. + + This method B{MUST} be reimplemented by subclasses of L{Pattern}. + """ + raise NotImplementedError() + + def read(self, process, address, size): + """ + Reads the requested number of bytes from the process memory at the + given address. + + Subclasses of L{Pattern} tipically don't need to reimplement this + method. + """ + return process.read(address, size) + + def find(self, buffer, pos = None): + """ + Searches for the pattern in the given buffer, optionally starting at + the given position within the buffer. + + This method B{MUST} be reimplemented by subclasses of L{Pattern}. + + @type buffer: str + @param buffer: Buffer to search on. + + @type pos: int + @param pos: + (Optional) Position within the buffer to start searching from. + + @rtype: tuple( int, int ) + @return: Tuple containing the following: + - Position within the buffer where a match is found, or C{-1} if + no match was found. + - Length of the matched data if a match is found, or undefined if + no match was found. + """ + raise NotImplementedError() + + def found(self, address, size, data): + """ + This method gets called when a match is found. + + This allows subclasses of L{Pattern} to filter out unwanted results, + or modify the results before giving them to the caller of + L{Search.search_process}. + + If the return value is C{None} the result is skipped. + + Subclasses of L{Pattern} don't need to reimplement this method unless + filtering is needed. + + @type address: int + @param address: The memory address where the pattern was found. + + @type size: int + @param size: The size of the data that matches the pattern. + + @type data: str + @param data: The data that matches the pattern. + + @rtype: tuple( int, int, str ) + @return: Tuple containing the following: + * The memory address where the pattern was found. + * The size of the data that matches the pattern. + * The data that matches the pattern. + """ + return (address, size, data) + +#------------------------------------------------------------------------------ + +class BytePattern (Pattern): + """ + Fixed byte pattern. + + @type pattern: str + @ivar pattern: Byte string to search for. + + @type length: int + @ivar length: Length of the byte pattern. + """ + + def __init__(self, pattern): + """ + @type pattern: str + @param pattern: Byte string to search for. + """ + self.pattern = str(pattern) + self.length = len(pattern) + + def __len__(self): + """ + Returns the exact length of the pattern. + + @see: L{Pattern.__len__} + """ + return self.length + + def find(self, buffer, pos = None): + return buffer.find(self.pattern, pos), self.length + +#------------------------------------------------------------------------------ + +# FIXME: case insensitive compat.unicode searches are probably buggy! + +class TextPattern (BytePattern): + """ + Text pattern. + + @type isUnicode: bool + @ivar isUnicode: C{True} if the text to search for is a compat.unicode string, + C{False} otherwise. + + @type encoding: str + @ivar encoding: Encoding for the text parameter. + Only used when the text to search for is a Unicode string. + Don't change unless you know what you're doing! + + @type caseSensitive: bool + @ivar caseSensitive: C{True} of the search is case sensitive, + C{False} otherwise. + """ + + def __init__(self, text, encoding = "utf-16le", caseSensitive = False): + """ + @type text: str or compat.unicode + @param text: Text to search for. + + @type encoding: str + @param encoding: (Optional) Encoding for the text parameter. + Only used when the text to search for is a Unicode string. + Don't change unless you know what you're doing! + + @type caseSensitive: bool + @param caseSensitive: C{True} of the search is case sensitive, + C{False} otherwise. + """ + self.isUnicode = isinstance(text, compat.unicode) + self.encoding = encoding + self.caseSensitive = caseSensitive + if not self.caseSensitive: + pattern = text.lower() + if self.isUnicode: + pattern = text.encode(encoding) + super(TextPattern, self).__init__(pattern) + + def read(self, process, address, size): + data = super(TextPattern, self).read(address, size) + if not self.caseSensitive: + if self.isUnicode: + try: + encoding = self.encoding + text = data.decode(encoding, "replace") + text = text.lower() + new_data = text.encode(encoding, "replace") + if len(data) == len(new_data): + data = new_data + else: + data = data.lower() + except Exception: + data = data.lower() + else: + data = data.lower() + return data + + def found(self, address, size, data): + if self.isUnicode: + try: + data = compat.unicode(data, self.encoding) + except Exception: +## traceback.print_exc() # XXX DEBUG + return None + return (address, size, data) + +#------------------------------------------------------------------------------ + +class RegExpPattern (Pattern): + """ + Regular expression pattern. + + @type pattern: str + @ivar pattern: Regular expression in text form. + + @type flags: int + @ivar flags: Regular expression flags. + + @type regexp: re.compile + @ivar regexp: Regular expression in compiled form. + + @type maxLength: int + @ivar maxLength: + Maximum expected length of the strings matched by this regular + expression. + + This value will be used to calculate the required buffer size when + doing buffered searches. + + Ideally it should be an exact value, but in some cases it's not + possible to calculate so an upper limit should be given instead. + + If that's not possible either, C{None} should be used. That will + cause an exception to be raised if this pattern is used in a + buffered search. + """ + + def __init__(self, regexp, flags = 0, maxLength = None): + """ + @type regexp: str + @param regexp: Regular expression string. + + @type flags: int + @param flags: Regular expression flags. + + @type maxLength: int + @param maxLength: Maximum expected length of the strings matched by + this regular expression. + + This value will be used to calculate the required buffer size when + doing buffered searches. + + Ideally it should be an exact value, but in some cases it's not + possible to calculate so an upper limit should be given instead. + + If that's not possible either, C{None} should be used. That will + cause an exception to be raised if this pattern is used in a + buffered search. + """ + self.pattern = regexp + self.flags = flags + self.regexp = re.compile(regexp, flags) + self.maxLength = maxLength + + def __len__(self): + """ + Returns the maximum expected length of the strings matched by this + pattern. This value is taken from the C{maxLength} argument of the + constructor if this class. + + Ideally it should be an exact value, but in some cases it's not + possible to calculate so an upper limit should be returned instead. + + If that's not possible either an exception must be raised. + + This value will be used to calculate the required buffer size when + doing buffered searches. + """ + if self.maxLength is None: + raise NotImplementedError() + return self.maxLength + + def find(self, buffer, pos = None): + if not pos: # make sure pos is an int + pos = 0 + match = self.regexp.search(buffer, pos) + if match: + start, end = match.span() + return start, end - start + return -1, 0 + +#------------------------------------------------------------------------------ + +class HexPattern (RegExpPattern): + """ + Hexadecimal pattern. + + Hex patterns must be in this form:: + "68 65 6c 6c 6f 20 77 6f 72 6c 64" # "hello world" + + Spaces are optional. Capitalization of hex digits doesn't matter. + This is exactly equivalent to the previous example:: + "68656C6C6F20776F726C64" # "hello world" + + Wildcards are allowed, in the form of a C{?} sign in any hex digit:: + "5? 5? c3" # pop register / pop register / ret + "b8 ?? ?? ?? ??" # mov eax, immediate value + + @type pattern: str + @ivar pattern: Hexadecimal pattern. + """ + + def __new__(cls, pattern): + """ + If the pattern is completely static (no wildcards are present) a + L{BytePattern} is created instead. That's because searching for a + fixed byte pattern is faster than searching for a regular expression. + """ + if '?' not in pattern: + return BytePattern( HexInput.hexadecimal(pattern) ) + return object.__new__(cls, pattern) + + def __init__(self, hexa): + """ + Hex patterns must be in this form:: + "68 65 6c 6c 6f 20 77 6f 72 6c 64" # "hello world" + + Spaces are optional. Capitalization of hex digits doesn't matter. + This is exactly equivalent to the previous example:: + "68656C6C6F20776F726C64" # "hello world" + + Wildcards are allowed, in the form of a C{?} sign in any hex digit:: + "5? 5? c3" # pop register / pop register / ret + "b8 ?? ?? ?? ??" # mov eax, immediate value + + @type hexa: str + @param hexa: Pattern to search for. + """ + maxLength = len([x for x in hexa + if x in "?0123456789ABCDEFabcdef"]) / 2 + super(HexPattern, self).__init__(HexInput.pattern(hexa), + maxLength = maxLength) + +#============================================================================== + +class Search (StaticClass): + """ + Static class to group the search functionality. + + Do not instance this class! Use its static methods instead. + """ + + # TODO: aligned searches + # TODO: method to coalesce search results + # TODO: search memory dumps + # TODO: search non-ascii C strings + + @staticmethod + def search_process(process, pattern, minAddr = None, + maxAddr = None, + bufferPages = None, + overlapping = False): + """ + Search for the given pattern within the process memory. + + @type process: L{Process} + @param process: Process to search. + + @type pattern: L{Pattern} + @param pattern: Pattern to search for. + It must be an instance of a subclass of L{Pattern}. + + The following L{Pattern} subclasses are provided by WinAppDbg: + - L{BytePattern} + - L{TextPattern} + - L{RegExpPattern} + - L{HexPattern} + + You can also write your own subclass of L{Pattern} for customized + searches. + + @type minAddr: int + @param minAddr: (Optional) Start the search at this memory address. + + @type maxAddr: int + @param maxAddr: (Optional) Stop the search at this memory address. + + @type bufferPages: int + @param bufferPages: (Optional) Number of memory pages to buffer when + performing the search. Valid values are: + - C{0} or C{None}: + Automatically determine the required buffer size. May not give + complete results for regular expressions that match variable + sized strings. + - C{> 0}: Set the buffer size, in memory pages. + - C{< 0}: Disable buffering entirely. This may give you a little + speed gain at the cost of an increased memory usage. If the + target process has very large contiguous memory regions it may + actually be slower or even fail. It's also the only way to + guarantee complete results for regular expressions that match + variable sized strings. + + @type overlapping: bool + @param overlapping: C{True} to allow overlapping results, C{False} + otherwise. + + Overlapping results yield the maximum possible number of results. + + For example, if searching for "AAAA" within "AAAAAAAA" at address + C{0x10000}, when overlapping is turned off the following matches + are yielded:: + (0x10000, 4, "AAAA") + (0x10004, 4, "AAAA") + + If overlapping is turned on, the following matches are yielded:: + (0x10000, 4, "AAAA") + (0x10001, 4, "AAAA") + (0x10002, 4, "AAAA") + (0x10003, 4, "AAAA") + (0x10004, 4, "AAAA") + + As you can see, the middle results are overlapping the last two. + + @rtype: iterator of tuple( int, int, str ) + @return: An iterator of tuples. Each tuple contains the following: + - The memory address where the pattern was found. + - The size of the data that matches the pattern. + - The data that matches the pattern. + + @raise WindowsError: An error occurred when querying or reading the + process memory. + """ + + # Do some namespace lookups of symbols we'll be using frequently. + MEM_COMMIT = win32.MEM_COMMIT + PAGE_GUARD = win32.PAGE_GUARD + page = MemoryAddresses.pageSize + read = pattern.read + find = pattern.find + + # Calculate the address range. + if minAddr is None: + minAddr = 0 + if maxAddr is None: + maxAddr = win32.LPVOID(-1).value # XXX HACK + + # Calculate the buffer size from the number of pages. + if bufferPages is None: + try: + size = MemoryAddresses.\ + align_address_to_page_end(len(pattern)) + page + except NotImplementedError: + size = None + elif bufferPages > 0: + size = page * (bufferPages + 1) + else: + size = None + + # Get the memory map of the process. + memory_map = process.iter_memory_map(minAddr, maxAddr) + + # Perform search with buffering enabled. + if size: + + # Loop through all memory blocks containing data. + buffer = "" # buffer to hold the memory data + prev_addr = 0 # previous memory block address + last = 0 # position of the last match + delta = 0 # delta of last read address and start of buffer + for mbi in memory_map: + + # Skip blocks with no data to search on. + if not mbi.has_content(): + continue + + # Get the address and size of this block. + address = mbi.BaseAddress # current address to search on + block_size = mbi.RegionSize # total size of the block + if address >= maxAddr: + break + end = address + block_size # end address of the block + + # If the block is contiguous to the previous block, + # coalesce the new data in the buffer. + if delta and address == prev_addr: + buffer += read(process, address, page) + + # If not, clear the buffer and read new data. + else: + buffer = read(process, address, min(size, block_size)) + last = 0 + delta = 0 + + # Search for the pattern in this block. + while 1: + + # Yield each match of the pattern in the buffer. + pos, length = find(buffer, last) + while pos >= last: + match_addr = address + pos - delta + if minAddr <= match_addr < maxAddr: + result = pattern.found( + match_addr, length, + buffer [ pos : pos + length ] ) + if result is not None: + yield result + if overlapping: + last = pos + 1 + else: + last = pos + length + pos, length = find(buffer, last) + + # Advance to the next page. + address = address + page + block_size = block_size - page + prev_addr = address + + # Fix the position of the last match. + last = last - page + if last < 0: + last = 0 + + # Remove the first page in the buffer. + buffer = buffer[ page : ] + delta = page + + # If we haven't reached the end of the block yet, + # read the next page in the block and keep seaching. + if address < end: + buffer = buffer + read(process, address, page) + + # Otherwise, we're done searching this block. + else: + break + + # Perform search with buffering disabled. + else: + + # Loop through all memory blocks containing data. + for mbi in memory_map: + + # Skip blocks with no data to search on. + if not mbi.has_content(): + continue + + # Get the address and size of this block. + address = mbi.BaseAddress + block_size = mbi.RegionSize + if address >= maxAddr: + break; + + # Read the whole memory region. + buffer = process.read(address, block_size) + + # Search for the pattern in this region. + pos, length = find(buffer) + last = 0 + while pos >= last: + match_addr = address + pos + if minAddr <= match_addr < maxAddr: + result = pattern.found( + match_addr, length, + buffer [ pos : pos + length ] ) + if result is not None: + yield result + if overlapping: + last = pos + 1 + else: + last = pos + length + pos, length = find(buffer, last) + + @classmethod + def extract_ascii_strings(cls, process, minSize = 4, maxSize = 1024): + """ + Extract ASCII strings from the process memory. + + @type process: L{Process} + @param process: Process to search. + + @type minSize: int + @param minSize: (Optional) Minimum size of the strings to search for. + + @type maxSize: int + @param maxSize: (Optional) Maximum size of the strings to search for. + + @rtype: iterator of tuple(int, int, str) + @return: Iterator of strings extracted from the process memory. + Each tuple contains the following: + - The memory address where the string was found. + - The size of the string. + - The string. + """ + regexp = r"[\s\w\!\@\#\$\%%\^\&\*\(\)\{\}\[\]\~\`\'\"\:\;\.\,\\\/\-\+\=\_\<\>]{%d,%d}\0" % (minSize, maxSize) + pattern = RegExpPattern(regexp, 0, maxSize) + return cls.search_process(process, pattern, overlapping = False) diff --git a/pydevd_attach_to_process/winappdbg/sql.py b/pydevd_attach_to_process/winappdbg/sql.py new file mode 100644 index 0000000..d974110 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/sql.py @@ -0,0 +1,993 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +SQL database storage support. + +@group Crash reporting: + CrashDAO +""" + +__revision__ = "$Id$" + +__all__ = ['CrashDAO'] + +import sqlite3 +import datetime +import warnings + +from sqlalchemy import create_engine, Column, ForeignKey, Sequence +from sqlalchemy.engine.url import URL +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.interfaces import PoolListener +from sqlalchemy.orm import sessionmaker, deferred +from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound +from sqlalchemy.types import Integer, BigInteger, Boolean, DateTime, String, \ + LargeBinary, Enum, VARCHAR +from sqlalchemy.sql.expression import asc, desc + +from crash import Crash, Marshaller, pickle, HIGHEST_PROTOCOL +from textio import CrashDump +import win32 + +#------------------------------------------------------------------------------ + +try: + from decorator import decorator +except ImportError: + import functools + def decorator(w): + """ + The C{decorator} module was not found. You can install it from: + U{http://pypi.python.org/pypi/decorator/} + """ + def d(fn): + @functools.wraps(fn) + def x(*argv, **argd): + return w(fn, *argv, **argd) + return x + return d + +#------------------------------------------------------------------------------ + +@compiles(String, 'mysql') +@compiles(VARCHAR, 'mysql') +def _compile_varchar_mysql(element, compiler, **kw): + """MySQL hack to avoid the "VARCHAR requires a length" error.""" + if not element.length or element.length == 'max': + return "TEXT" + else: + return compiler.visit_VARCHAR(element, **kw) + +#------------------------------------------------------------------------------ + +class _SQLitePatch (PoolListener): + """ + Used internally by L{BaseDAO}. + + After connecting to an SQLite database, ensure that the foreign keys + support is enabled. If not, abort the connection. + + @see: U{http://sqlite.org/foreignkeys.html} + """ + def connect(dbapi_connection, connection_record): + """ + Called once by SQLAlchemy for each new SQLite DB-API connection. + + Here is where we issue some PRAGMA statements to configure how we're + going to access the SQLite database. + + @param dbapi_connection: + A newly connected raw SQLite DB-API connection. + + @param connection_record: + Unused by this method. + """ + try: + cursor = dbapi_connection.cursor() + try: + cursor.execute("PRAGMA foreign_keys = ON;") + cursor.execute("PRAGMA foreign_keys;") + if cursor.fetchone()[0] != 1: + raise Exception() + finally: + cursor.close() + except Exception: + dbapi_connection.close() + raise sqlite3.Error() + +#------------------------------------------------------------------------------ + +class BaseDTO (object): + """ + Customized declarative base for SQLAlchemy. + """ + + __table_args__ = { + + # Don't use MyISAM in MySQL. It doesn't support ON DELETE CASCADE. + 'mysql_engine': 'InnoDB', + + # Don't use BlitzDB in Drizzle. It doesn't support foreign keys. + 'drizzle_engine': 'InnoDB', + + # Collate to UTF-8. + 'mysql_charset': 'utf8', + + } + +BaseDTO = declarative_base(cls = BaseDTO) + +#------------------------------------------------------------------------------ + +# TODO: if using mssql, check it's at least SQL Server 2005 +# (LIMIT and OFFSET support is required). +# TODO: if using mysql, check it's at least MySQL 5.0.3 +# (nested transactions are required). +# TODO: maybe in mysql check the tables are not myisam? +# TODO: maybe create the database if it doesn't exist? +# TODO: maybe add a method to compact the database? +# http://stackoverflow.com/questions/1875885 +# http://www.sqlite.org/lang_vacuum.html +# http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html +# http://msdn.microsoft.com/en-us/library/ms174459(v=sql.90).aspx + +class BaseDAO (object): + """ + Data Access Object base class. + + @type _url: sqlalchemy.url.URL + @ivar _url: Database connection URL. + + @type _dialect: str + @ivar _dialect: SQL dialect currently being used. + + @type _driver: str + @ivar _driver: Name of the database driver currently being used. + To get the actual Python module use L{_url}.get_driver() instead. + + @type _session: sqlalchemy.orm.Session + @ivar _session: Database session object. + + @type _new_session: class + @cvar _new_session: Custom configured Session class used to create the + L{_session} instance variable. + + @type _echo: bool + @cvar _echo: Set to C{True} to print all SQL queries to standard output. + """ + + _echo = False + + _new_session = sessionmaker(autoflush = True, + autocommit = True, + expire_on_commit = True, + weak_identity_map = True) + + def __init__(self, url, creator = None): + """ + Connect to the database using the given connection URL. + + The current implementation uses SQLAlchemy and so it will support + whatever database said module supports. + + @type url: str + @param url: + URL that specifies the database to connect to. + + Some examples: + - Opening an SQLite file: + C{dao = CrashDAO("sqlite:///C:\\some\\path\\database.sqlite")} + - Connecting to a locally installed SQL Express database: + C{dao = CrashDAO("mssql://.\\SQLEXPRESS/Crashes?trusted_connection=yes")} + - Connecting to a MySQL database running locally, using the + C{oursql} library, authenticating as the "winappdbg" user with + no password: + C{dao = CrashDAO("mysql+oursql://winappdbg@localhost/Crashes")} + - Connecting to a Postgres database running locally, + authenticating with user and password: + C{dao = CrashDAO("postgresql://winappdbg:winappdbg@localhost/Crashes")} + + For more information see the C{SQLAlchemy} documentation online: + U{http://docs.sqlalchemy.org/en/latest/core/engines.html} + + Note that in all dialects except for SQLite the database + must already exist. The tables schema, however, is created + automatically when connecting for the first time. + + To create the database in MSSQL, you can use the + U{SQLCMD} + command:: + sqlcmd -Q "CREATE DATABASE Crashes" + + In MySQL you can use something like the following:: + mysql -u root -e "CREATE DATABASE Crashes;" + + And in Postgres:: + createdb Crashes -h localhost -U winappdbg -p winappdbg -O winappdbg + + Some small changes to the schema may be tolerated (for example, + increasing the maximum length of string columns, or adding new + columns with default values). Of course, it's best to test it + first before making changes in a live database. This all depends + very much on the SQLAlchemy version you're using, but it's best + to use the latest version always. + + @type creator: callable + @param creator: (Optional) Callback function that creates the SQL + database connection. + + Normally it's not necessary to use this argument. However in some + odd cases you may need to customize the database connection. + """ + + # Parse the connection URL. + parsed_url = URL(url) + schema = parsed_url.drivername + if '+' in schema: + dialect, driver = schema.split('+') + else: + dialect, driver = schema, 'base' + dialect = dialect.strip().lower() + driver = driver.strip() + + # Prepare the database engine arguments. + arguments = {'echo' : self._echo} + if dialect == 'sqlite': + arguments['module'] = sqlite3.dbapi2 + arguments['listeners'] = [_SQLitePatch()] + if creator is not None: + arguments['creator'] = creator + + # Load the database engine. + engine = create_engine(url, **arguments) + + # Create a new session. + session = self._new_session(bind = engine) + + # Create the required tables if they don't exist. + BaseDTO.metadata.create_all(engine) + # TODO: create a dialect specific index on the "signature" column. + + # Set the instance properties. + self._url = parsed_url + self._driver = driver + self._dialect = dialect + self._session = session + + def _transactional(self, method, *argv, **argd): + """ + Begins a transaction and calls the given DAO method. + + If the method executes successfully the transaction is commited. + + If the method fails, the transaction is rolled back. + + @type method: callable + @param method: Bound method of this class or one of its subclasses. + The first argument will always be C{self}. + + @return: The return value of the method call. + + @raise Exception: Any exception raised by the method. + """ + self._session.begin(subtransactions = True) + try: + result = method(self, *argv, **argd) + self._session.commit() + return result + except: + self._session.rollback() + raise + +#------------------------------------------------------------------------------ + +@decorator +def Transactional(fn, self, *argv, **argd): + """ + Decorator that wraps DAO methods to handle transactions automatically. + + It may only work with subclasses of L{BaseDAO}. + """ + return self._transactional(fn, *argv, **argd) + +#============================================================================== + +# Generates all possible memory access flags. +def _gen_valid_access_flags(): + f = [] + for a1 in ("---", "R--", "RW-", "RC-", "--X", "R-X", "RWX", "RCX", "???"): + for a2 in ("G", "-"): + for a3 in ("N", "-"): + for a4 in ("W", "-"): + f.append("%s %s%s%s" % (a1, a2, a3, a4)) + return tuple(f) +_valid_access_flags = _gen_valid_access_flags() + +# Enumerated types for the memory table. +n_MEM_ACCESS_ENUM = {"name" : "MEM_ACCESS_ENUM"} +n_MEM_ALLOC_ACCESS_ENUM = {"name" : "MEM_ALLOC_ACCESS_ENUM"} +MEM_ACCESS_ENUM = Enum(*_valid_access_flags, + **n_MEM_ACCESS_ENUM) +MEM_ALLOC_ACCESS_ENUM = Enum(*_valid_access_flags, + **n_MEM_ALLOC_ACCESS_ENUM) +MEM_STATE_ENUM = Enum("Reserved", "Commited", "Free", "Unknown", + name = "MEM_STATE_ENUM") +MEM_TYPE_ENUM = Enum("Image", "Mapped", "Private", "Unknown", + name = "MEM_TYPE_ENUM") + +# Cleanup the namespace. +del _gen_valid_access_flags +del _valid_access_flags +del n_MEM_ACCESS_ENUM +del n_MEM_ALLOC_ACCESS_ENUM + +#------------------------------------------------------------------------------ + +class MemoryDTO (BaseDTO): + """ + Database mapping for memory dumps. + """ + + # Declare the table mapping. + __tablename__ = 'memory' + id = Column(Integer, Sequence(__tablename__ + '_seq'), + primary_key = True, autoincrement = True) + crash_id = Column(Integer, ForeignKey('crashes.id', + ondelete = 'CASCADE', + onupdate = 'CASCADE'), + nullable = False) + address = Column(BigInteger, nullable = False, index = True) + size = Column(BigInteger, nullable = False) + state = Column(MEM_STATE_ENUM, nullable = False) + access = Column(MEM_ACCESS_ENUM) + type = Column(MEM_TYPE_ENUM) + alloc_base = Column(BigInteger) + alloc_access = Column(MEM_ALLOC_ACCESS_ENUM) + filename = Column(String) + content = deferred(Column(LargeBinary)) + + def __init__(self, crash_id, mbi): + """ + Process a L{win32.MemoryBasicInformation} object for database storage. + """ + + # Crash ID. + self.crash_id = crash_id + + # Address. + self.address = mbi.BaseAddress + + # Size. + self.size = mbi.RegionSize + + # State (free or allocated). + if mbi.State == win32.MEM_RESERVE: + self.state = "Reserved" + elif mbi.State == win32.MEM_COMMIT: + self.state = "Commited" + elif mbi.State == win32.MEM_FREE: + self.state = "Free" + else: + self.state = "Unknown" + + # Page protection bits (R/W/X/G). + if mbi.State != win32.MEM_COMMIT: + self.access = None + else: + self.access = self._to_access(mbi.Protect) + + # Type (file mapping, executable image, or private memory). + if mbi.Type == win32.MEM_IMAGE: + self.type = "Image" + elif mbi.Type == win32.MEM_MAPPED: + self.type = "Mapped" + elif mbi.Type == win32.MEM_PRIVATE: + self.type = "Private" + elif mbi.Type == 0: + self.type = None + else: + self.type = "Unknown" + + # Allocation info. + self.alloc_base = mbi.AllocationBase + if not mbi.AllocationProtect: + self.alloc_access = None + else: + self.alloc_access = self._to_access(mbi.AllocationProtect) + + # Filename (for memory mappings). + try: + self.filename = mbi.filename + except AttributeError: + self.filename = None + + # Memory contents. + try: + self.content = mbi.content + except AttributeError: + self.content = None + + def _to_access(self, protect): + if protect & win32.PAGE_NOACCESS: + access = "--- " + elif protect & win32.PAGE_READONLY: + access = "R-- " + elif protect & win32.PAGE_READWRITE: + access = "RW- " + elif protect & win32.PAGE_WRITECOPY: + access = "RC- " + elif protect & win32.PAGE_EXECUTE: + access = "--X " + elif protect & win32.PAGE_EXECUTE_READ: + access = "R-X " + elif protect & win32.PAGE_EXECUTE_READWRITE: + access = "RWX " + elif protect & win32.PAGE_EXECUTE_WRITECOPY: + access = "RCX " + else: + access = "??? " + if protect & win32.PAGE_GUARD: + access += "G" + else: + access += "-" + if protect & win32.PAGE_NOCACHE: + access += "N" + else: + access += "-" + if protect & win32.PAGE_WRITECOMBINE: + access += "W" + else: + access += "-" + return access + + def toMBI(self, getMemoryDump = False): + """ + Returns a L{win32.MemoryBasicInformation} object using the data + retrieved from the database. + + @type getMemoryDump: bool + @param getMemoryDump: (Optional) If C{True} retrieve the memory dump. + Defaults to C{False} since this may be a costly operation. + + @rtype: L{win32.MemoryBasicInformation} + @return: Memory block information. + """ + mbi = win32.MemoryBasicInformation() + mbi.BaseAddress = self.address + mbi.RegionSize = self.size + mbi.State = self._parse_state(self.state) + mbi.Protect = self._parse_access(self.access) + mbi.Type = self._parse_type(self.type) + if self.alloc_base is not None: + mbi.AllocationBase = self.alloc_base + else: + mbi.AllocationBase = mbi.BaseAddress + if self.alloc_access is not None: + mbi.AllocationProtect = self._parse_access(self.alloc_access) + else: + mbi.AllocationProtect = mbi.Protect + if self.filename is not None: + mbi.filename = self.filename + if getMemoryDump and self.content is not None: + mbi.content = self.content + return mbi + + @staticmethod + def _parse_state(state): + if state: + if state == "Reserved": + return win32.MEM_RESERVE + if state == "Commited": + return win32.MEM_COMMIT + if state == "Free": + return win32.MEM_FREE + return 0 + + @staticmethod + def _parse_type(type): + if type: + if type == "Image": + return win32.MEM_IMAGE + if type == "Mapped": + return win32.MEM_MAPPED + if type == "Private": + return win32.MEM_PRIVATE + return -1 + return 0 + + @staticmethod + def _parse_access(access): + if not access: + return 0 + perm = access[:3] + if perm == "R--": + protect = win32.PAGE_READONLY + elif perm == "RW-": + protect = win32.PAGE_READWRITE + elif perm == "RC-": + protect = win32.PAGE_WRITECOPY + elif perm == "--X": + protect = win32.PAGE_EXECUTE + elif perm == "R-X": + protect = win32.PAGE_EXECUTE_READ + elif perm == "RWX": + protect = win32.PAGE_EXECUTE_READWRITE + elif perm == "RCX": + protect = win32.PAGE_EXECUTE_WRITECOPY + else: + protect = win32.PAGE_NOACCESS + if access[5] == "G": + protect = protect | win32.PAGE_GUARD + if access[6] == "N": + protect = protect | win32.PAGE_NOCACHE + if access[7] == "W": + protect = protect | win32.PAGE_WRITECOMBINE + return protect + +#------------------------------------------------------------------------------ + +class CrashDTO (BaseDTO): + """ + Database mapping for crash dumps. + """ + + # Table name. + __tablename__ = "crashes" + + # Primary key. + id = Column(Integer, Sequence(__tablename__ + '_seq'), + primary_key = True, autoincrement = True) + + # Timestamp. + timestamp = Column(DateTime, nullable = False, index = True) + + # Exploitability test. + exploitable = Column(Integer, nullable = False) + exploitability_rule = Column(String(32), nullable = False) + exploitability_rating = Column(String(32), nullable = False) + exploitability_desc = Column(String, nullable = False) + + # Platform description. + os = Column(String(32), nullable = False) + arch = Column(String(16), nullable = False) + bits = Column(Integer, nullable = False) # Integer(4) is deprecated :( + + # Event description. + event = Column(String, nullable = False) + pid = Column(Integer, nullable = False) + tid = Column(Integer, nullable = False) + pc = Column(BigInteger, nullable = False) + sp = Column(BigInteger, nullable = False) + fp = Column(BigInteger, nullable = False) + pc_label = Column(String, nullable = False) + + # Exception description. + exception = Column(String(64)) + exception_text = Column(String(64)) + exception_address = Column(BigInteger) + exception_label = Column(String) + first_chance = Column(Boolean) + fault_type = Column(Integer) + fault_address = Column(BigInteger) + fault_label = Column(String) + fault_disasm = Column(String) + stack_trace = Column(String) + + # Environment description. + command_line = Column(String) + environment = Column(String) + + # Debug strings. + debug_string = Column(String) + + # Notes. + notes = Column(String) + + # Heuristic signature. + signature = Column(String, nullable = False) + + # Pickled Crash object, minus the memory dump. + data = deferred(Column(LargeBinary, nullable = False)) + + def __init__(self, crash): + """ + @type crash: Crash + @param crash: L{Crash} object to store into the database. + """ + + # Timestamp and signature. + self.timestamp = datetime.datetime.fromtimestamp( crash.timeStamp ) + self.signature = pickle.dumps(crash.signature, protocol = 0) + + # Marshalled Crash object, minus the memory dump. + # This code is *not* thread safe! + memoryMap = crash.memoryMap + try: + crash.memoryMap = None + self.data = buffer( Marshaller.dumps(crash) ) + finally: + crash.memoryMap = memoryMap + + # Exploitability test. + self.exploitability_rating, \ + self.exploitability_rule, \ + self.exploitability_desc = crash.isExploitable() + + # Exploitability test as an integer result (for sorting). + self.exploitable = [ + "Not an exception", + "Not exploitable", + "Not likely exploitable", + "Unknown", + "Probably exploitable", + "Exploitable", + ].index(self.exploitability_rating) + + # Platform description. + self.os = crash.os + self.arch = crash.arch + self.bits = crash.bits + + # Event description. + self.event = crash.eventName + self.pid = crash.pid + self.tid = crash.tid + self.pc = crash.pc + self.sp = crash.sp + self.fp = crash.fp + self.pc_label = crash.labelPC + + # Exception description. + self.exception = crash.exceptionName + self.exception_text = crash.exceptionDescription + self.exception_address = crash.exceptionAddress + self.exception_label = crash.exceptionLabel + self.first_chance = crash.firstChance + self.fault_type = crash.faultType + self.fault_address = crash.faultAddress + self.fault_label = crash.faultLabel + self.fault_disasm = CrashDump.dump_code( crash.faultDisasm, + crash.pc ) + self.stack_trace = CrashDump.dump_stack_trace_with_labels( + crash.stackTracePretty ) + + # Command line. + self.command_line = crash.commandLine + + # Environment. + if crash.environment: + envList = crash.environment.items() + envList.sort() + environment = '' + for envKey, envVal in envList: + # Must concatenate here instead of using a substitution, + # so strings can be automatically promoted to Unicode. + environment += envKey + '=' + envVal + '\n' + if environment: + self.environment = environment + + # Debug string. + self.debug_string = crash.debugString + + # Notes. + self.notes = crash.notesReport() + + def toCrash(self, getMemoryDump = False): + """ + Returns a L{Crash} object using the data retrieved from the database. + + @type getMemoryDump: bool + @param getMemoryDump: If C{True} retrieve the memory dump. + Defaults to C{False} since this may be a costly operation. + + @rtype: L{Crash} + @return: Crash object. + """ + crash = Marshaller.loads(str(self.data)) + if not isinstance(crash, Crash): + raise TypeError( + "Expected Crash instance, got %s instead" % type(crash)) + crash._rowid = self.id + if not crash.memoryMap: + memory = getattr(self, "memory", []) + if memory: + crash.memoryMap = [dto.toMBI(getMemoryDump) for dto in memory] + return crash + +#============================================================================== + +# TODO: add a method to modify already stored crash dumps. + +class CrashDAO (BaseDAO): + """ + Data Access Object to read, write and search for L{Crash} objects in a + database. + """ + + @Transactional + def add(self, crash, allow_duplicates = True): + """ + Add a new crash dump to the database, optionally filtering them by + signature to avoid duplicates. + + @type crash: L{Crash} + @param crash: Crash object. + + @type allow_duplicates: bool + @param allow_duplicates: (Optional) + C{True} to always add the new crash dump. + C{False} to only add the crash dump if no other crash with the + same signature is found in the database. + + Sometimes, your fuzzer turns out to be I{too} good. Then you find + youself browsing through gigabytes of crash dumps, only to find + a handful of actual bugs in them. This simple heuristic filter + saves you the trouble by discarding crashes that seem to be similar + to another one you've already found. + """ + + # Filter out duplicated crashes, if requested. + if not allow_duplicates: + signature = pickle.dumps(crash.signature, protocol = 0) + if self._session.query(CrashDTO.id) \ + .filter_by(signature = signature) \ + .count() > 0: + return + + # Fill out a new row for the crashes table. + crash_id = self.__add_crash(crash) + + # Fill out new rows for the memory dump. + self.__add_memory(crash_id, crash.memoryMap) + + # On success set the row ID for the Crash object. + # WARNING: In nested calls, make sure to delete + # this property before a session rollback! + crash._rowid = crash_id + + # Store the Crash object into the crashes table. + def __add_crash(self, crash): + session = self._session + r_crash = None + try: + + # Fill out a new row for the crashes table. + r_crash = CrashDTO(crash) + session.add(r_crash) + + # Flush and get the new row ID. + session.flush() + crash_id = r_crash.id + + finally: + try: + + # Make the ORM forget the CrashDTO object. + if r_crash is not None: + session.expire(r_crash) + + finally: + + # Delete the last reference to the CrashDTO + # object, so the Python garbage collector claims it. + del r_crash + + # Return the row ID. + return crash_id + + # Store the memory dump into the memory table. + def __add_memory(self, crash_id, memoryMap): + session = self._session + if memoryMap: + for mbi in memoryMap: + r_mem = MemoryDTO(crash_id, mbi) + session.add(r_mem) + session.flush() + + @Transactional + def find(self, + signature = None, order = 0, + since = None, until = None, + offset = None, limit = None): + """ + Retrieve all crash dumps in the database, optionally filtering them by + signature and timestamp, and/or sorting them by timestamp. + + Results can be paged to avoid consuming too much memory if the database + is large. + + @see: L{find_by_example} + + @type signature: object + @param signature: (Optional) Return only through crashes matching + this signature. See L{Crash.signature} for more details. + + @type order: int + @param order: (Optional) Sort by timestamp. + If C{== 0}, results are not sorted. + If C{> 0}, results are sorted from older to newer. + If C{< 0}, results are sorted from newer to older. + + @type since: datetime + @param since: (Optional) Return only the crashes after and + including this date and time. + + @type until: datetime + @param until: (Optional) Return only the crashes before this date + and time, not including it. + + @type offset: int + @param offset: (Optional) Skip the first I{offset} results. + + @type limit: int + @param limit: (Optional) Return at most I{limit} results. + + @rtype: list(L{Crash}) + @return: List of Crash objects. + """ + + # Validate the parameters. + if since and until and since > until: + warnings.warn("CrashDAO.find() got the 'since' and 'until'" + " arguments reversed, corrected automatically.") + since, until = until, since + if limit is not None and not limit: + warnings.warn("CrashDAO.find() was set a limit of 0 results," + " returning without executing a query.") + return [] + + # Build the SQL query. + query = self._session.query(CrashDTO) + if signature is not None: + sig_pickled = pickle.dumps(signature, protocol = 0) + query = query.filter(CrashDTO.signature == sig_pickled) + if since: + query = query.filter(CrashDTO.timestamp >= since) + if until: + query = query.filter(CrashDTO.timestamp < until) + if order: + if order > 0: + query = query.order_by(asc(CrashDTO.timestamp)) + else: + query = query.order_by(desc(CrashDTO.timestamp)) + else: + # Default ordering is by row ID, to get consistent results. + # Also some database engines require ordering when using offsets. + query = query.order_by(asc(CrashDTO.id)) + if offset: + query = query.offset(offset) + if limit: + query = query.limit(limit) + + # Execute the SQL query and convert the results. + try: + return [dto.toCrash() for dto in query.all()] + except NoResultFound: + return [] + + @Transactional + def find_by_example(self, crash, offset = None, limit = None): + """ + Find all crash dumps that have common properties with the crash dump + provided. + + Results can be paged to avoid consuming too much memory if the database + is large. + + @see: L{find} + + @type crash: L{Crash} + @param crash: Crash object to compare with. Fields set to C{None} are + ignored, all other fields but the signature are used in the + comparison. + + To search for signature instead use the L{find} method. + + @type offset: int + @param offset: (Optional) Skip the first I{offset} results. + + @type limit: int + @param limit: (Optional) Return at most I{limit} results. + + @rtype: list(L{Crash}) + @return: List of similar crash dumps found. + """ + + # Validate the parameters. + if limit is not None and not limit: + warnings.warn("CrashDAO.find_by_example() was set a limit of 0" + " results, returning without executing a query.") + return [] + + # Build the query. + query = self._session.query(CrashDTO) + + # Order by row ID to get consistent results. + # Also some database engines require ordering when using offsets. + query = query.asc(CrashDTO.id) + + # Build a CrashDTO from the Crash object. + dto = CrashDTO(crash) + + # Filter all the fields in the crashes table that are present in the + # CrashDTO object and not set to None, except for the row ID. + for name, column in compat.iteritems(CrashDTO.__dict__): + if not name.startswith('__') and name not in ('id', + 'signature', + 'data'): + if isinstance(column, Column): + value = getattr(dto, name, None) + if value is not None: + query = query.filter(column == value) + + # Page the query. + if offset: + query = query.offset(offset) + if limit: + query = query.limit(limit) + + # Execute the SQL query and convert the results. + try: + return [dto.toCrash() for dto in query.all()] + except NoResultFound: + return [] + + @Transactional + def count(self, signature = None): + """ + Counts how many crash dumps have been stored in this database. + Optionally filters the count by heuristic signature. + + @type signature: object + @param signature: (Optional) Count only the crashes that match + this signature. See L{Crash.signature} for more details. + + @rtype: int + @return: Count of crash dumps stored in this database. + """ + query = self._session.query(CrashDTO.id) + if signature: + sig_pickled = pickle.dumps(signature, protocol = 0) + query = query.filter_by(signature = sig_pickled) + return query.count() + + @Transactional + def delete(self, crash): + """ + Remove the given crash dump from the database. + + @type crash: L{Crash} + @param crash: Crash dump to remove. + """ + query = self._session.query(CrashDTO).filter_by(id = crash._rowid) + query.delete(synchronize_session = False) + del crash._rowid diff --git a/pydevd_attach_to_process/winappdbg/system.py b/pydevd_attach_to_process/winappdbg/system.py new file mode 100644 index 0000000..9ee3200 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/system.py @@ -0,0 +1,1297 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +System settings. + +@group Instrumentation: + System +""" + +from __future__ import with_statement + +__revision__ = "$Id$" + +__all__ = ['System'] + +from winappdbg import win32 +from winappdbg.registry import Registry +from winappdbg.textio import HexInput, HexDump +from winappdbg.util import Regenerator, PathOperations, MemoryAddresses, DebugRegister, \ + classproperty +from winappdbg.process import _ProcessContainer +from winappdbg.window import Window + +import sys +import os +import ctypes +import warnings + +from os import path, getenv + +#============================================================================== + +class System (_ProcessContainer): + """ + Interface to a batch of processes, plus some system wide settings. + Contains a snapshot of processes. + + @group Platform settings: + arch, bits, os, wow64, pageSize + + @group Instrumentation: + find_window, get_window_at, get_foreground_window, + get_desktop_window, get_shell_window + + @group Debugging: + load_dbghelp, fix_symbol_store_path, + request_debug_privileges, drop_debug_privileges + + @group Postmortem debugging: + get_postmortem_debugger, set_postmortem_debugger, + get_postmortem_exclusion_list, add_to_postmortem_exclusion_list, + remove_from_postmortem_exclusion_list + + @group System services: + get_services, get_active_services, + start_service, stop_service, + pause_service, resume_service, + get_service_display_name, get_service_from_display_name + + @group Permissions and privileges: + request_privileges, drop_privileges, adjust_privileges, is_admin + + @group Miscellaneous global settings: + set_kill_on_exit_mode, read_msr, write_msr, enable_step_on_branch_mode, + get_last_branch_location + + @type arch: str + @cvar arch: Name of the processor architecture we're running on. + For more details see L{win32.version._get_arch}. + + @type bits: int + @cvar bits: Size of the machine word in bits for the current architecture. + For more details see L{win32.version._get_bits}. + + @type os: str + @cvar os: Name of the Windows version we're runing on. + For more details see L{win32.version._get_os}. + + @type wow64: bool + @cvar wow64: C{True} if the debugger is a 32 bits process running in a 64 + bits version of Windows, C{False} otherwise. + + @type pageSize: int + @cvar pageSize: Page size in bytes. Defaults to 0x1000 but it's + automatically updated on runtime when importing the module. + + @type registry: L{Registry} + @cvar registry: Windows Registry for this machine. + """ + + arch = win32.arch + bits = win32.bits + os = win32.os + wow64 = win32.wow64 + + @classproperty + def pageSize(cls): + pageSize = MemoryAddresses.pageSize + cls.pageSize = pageSize + return pageSize + + registry = Registry() + +#------------------------------------------------------------------------------ + + @staticmethod + def find_window(className = None, windowName = None): + """ + Find the first top-level window in the current desktop to match the + given class name and/or window name. If neither are provided any + top-level window will match. + + @see: L{get_window_at} + + @type className: str + @param className: (Optional) Class name of the window to find. + If C{None} or not used any class name will match the search. + + @type windowName: str + @param windowName: (Optional) Caption text of the window to find. + If C{None} or not used any caption text will match the search. + + @rtype: L{Window} or None + @return: A window that matches the request. There may be more matching + windows, but this method only returns one. If no matching window + is found, the return value is C{None}. + + @raise WindowsError: An error occured while processing this request. + """ + # I'd love to reverse the order of the parameters + # but that might create some confusion. :( + hWnd = win32.FindWindow(className, windowName) + if hWnd: + return Window(hWnd) + + @staticmethod + def get_window_at(x, y): + """ + Get the window located at the given coordinates in the desktop. + If no such window exists an exception is raised. + + @see: L{find_window} + + @type x: int + @param x: Horizontal coordinate. + @type y: int + @param y: Vertical coordinate. + + @rtype: L{Window} + @return: Window at the requested position. If no such window + exists a C{WindowsError} exception is raised. + + @raise WindowsError: An error occured while processing this request. + """ + return Window( win32.WindowFromPoint( (x, y) ) ) + + @staticmethod + def get_foreground_window(): + """ + @rtype: L{Window} + @return: Returns the foreground window. + @raise WindowsError: An error occured while processing this request. + """ + return Window( win32.GetForegroundWindow() ) + + @staticmethod + def get_desktop_window(): + """ + @rtype: L{Window} + @return: Returns the desktop window. + @raise WindowsError: An error occured while processing this request. + """ + return Window( win32.GetDesktopWindow() ) + + @staticmethod + def get_shell_window(): + """ + @rtype: L{Window} + @return: Returns the shell window. + @raise WindowsError: An error occured while processing this request. + """ + return Window( win32.GetShellWindow() ) + +#------------------------------------------------------------------------------ + + @classmethod + def request_debug_privileges(cls, bIgnoreExceptions = False): + """ + Requests debug privileges. + + This may be needed to debug processes running as SYSTEM + (such as services) since Windows XP. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when requesting debug privileges. + + @rtype: bool + @return: C{True} on success, C{False} on failure. + + @raise WindowsError: Raises an exception on error, unless + C{bIgnoreExceptions} is C{True}. + """ + try: + cls.request_privileges(win32.SE_DEBUG_NAME) + return True + except Exception: + if not bIgnoreExceptions: + raise + return False + + @classmethod + def drop_debug_privileges(cls, bIgnoreExceptions = False): + """ + Drops debug privileges. + + This may be needed to avoid being detected + by certain anti-debug tricks. + + @type bIgnoreExceptions: bool + @param bIgnoreExceptions: C{True} to ignore any exceptions that may be + raised when dropping debug privileges. + + @rtype: bool + @return: C{True} on success, C{False} on failure. + + @raise WindowsError: Raises an exception on error, unless + C{bIgnoreExceptions} is C{True}. + """ + try: + cls.drop_privileges(win32.SE_DEBUG_NAME) + return True + except Exception: + if not bIgnoreExceptions: + raise + return False + + @classmethod + def request_privileges(cls, *privileges): + """ + Requests privileges. + + @type privileges: int... + @param privileges: Privileges to request. + + @raise WindowsError: Raises an exception on error. + """ + cls.adjust_privileges(True, privileges) + + @classmethod + def drop_privileges(cls, *privileges): + """ + Drops privileges. + + @type privileges: int... + @param privileges: Privileges to drop. + + @raise WindowsError: Raises an exception on error. + """ + cls.adjust_privileges(False, privileges) + + @staticmethod + def adjust_privileges(state, privileges): + """ + Requests or drops privileges. + + @type state: bool + @param state: C{True} to request, C{False} to drop. + + @type privileges: list(int) + @param privileges: Privileges to request or drop. + + @raise WindowsError: Raises an exception on error. + """ + with win32.OpenProcessToken(win32.GetCurrentProcess(), + win32.TOKEN_ADJUST_PRIVILEGES) as hToken: + NewState = ( (priv, state) for priv in privileges ) + win32.AdjustTokenPrivileges(hToken, NewState) + + @staticmethod + def is_admin(): + """ + @rtype: bool + @return: C{True} if the current user as Administrator privileges, + C{False} otherwise. Since Windows Vista and above this means if + the current process is running with UAC elevation or not. + """ + return win32.IsUserAnAdmin() + +#------------------------------------------------------------------------------ + + __binary_types = { + win32.VFT_APP: "application", + win32.VFT_DLL: "dynamic link library", + win32.VFT_STATIC_LIB: "static link library", + win32.VFT_FONT: "font", + win32.VFT_DRV: "driver", + win32.VFT_VXD: "legacy driver", + } + + __driver_types = { + win32.VFT2_DRV_COMM: "communications driver", + win32.VFT2_DRV_DISPLAY: "display driver", + win32.VFT2_DRV_INSTALLABLE: "installable driver", + win32.VFT2_DRV_KEYBOARD: "keyboard driver", + win32.VFT2_DRV_LANGUAGE: "language driver", + win32.VFT2_DRV_MOUSE: "mouse driver", + win32.VFT2_DRV_NETWORK: "network driver", + win32.VFT2_DRV_PRINTER: "printer driver", + win32.VFT2_DRV_SOUND: "sound driver", + win32.VFT2_DRV_SYSTEM: "system driver", + win32.VFT2_DRV_VERSIONED_PRINTER: "versioned printer driver", + } + + __font_types = { + win32.VFT2_FONT_RASTER: "raster font", + win32.VFT2_FONT_TRUETYPE: "TrueType font", + win32.VFT2_FONT_VECTOR: "vector font", + } + + __months = ( + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ) + + __days_of_the_week = ( + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + ) + + @classmethod + def get_file_version_info(cls, filename): + """ + Get the program version from an executable file, if available. + + @type filename: str + @param filename: Pathname to the executable file to query. + + @rtype: tuple(str, str, bool, bool, str, str) + @return: Tuple with version information extracted from the executable + file metadata, containing the following: + - File version number (C{"major.minor"}). + - Product version number (C{"major.minor"}). + - C{True} for debug builds, C{False} for production builds. + - C{True} for legacy OS builds (DOS, OS/2, Win16), + C{False} for modern OS builds. + - Binary file type. + May be one of the following values: + - "application" + - "dynamic link library" + - "static link library" + - "font" + - "raster font" + - "TrueType font" + - "vector font" + - "driver" + - "communications driver" + - "display driver" + - "installable driver" + - "keyboard driver" + - "language driver" + - "legacy driver" + - "mouse driver" + - "network driver" + - "printer driver" + - "sound driver" + - "system driver" + - "versioned printer driver" + - Binary creation timestamp. + Any of the fields may be C{None} if not available. + + @raise WindowsError: Raises an exception on error. + """ + + # Get the file version info structure. + pBlock = win32.GetFileVersionInfo(filename) + pBuffer, dwLen = win32.VerQueryValue(pBlock, "\\") + if dwLen != ctypes.sizeof(win32.VS_FIXEDFILEINFO): + raise ctypes.WinError(win32.ERROR_BAD_LENGTH) + pVersionInfo = ctypes.cast(pBuffer, + ctypes.POINTER(win32.VS_FIXEDFILEINFO)) + VersionInfo = pVersionInfo.contents + if VersionInfo.dwSignature != 0xFEEF04BD: + raise ctypes.WinError(win32.ERROR_BAD_ARGUMENTS) + + # File and product versions. + FileVersion = "%d.%d" % (VersionInfo.dwFileVersionMS, + VersionInfo.dwFileVersionLS) + ProductVersion = "%d.%d" % (VersionInfo.dwProductVersionMS, + VersionInfo.dwProductVersionLS) + + # Debug build? + if VersionInfo.dwFileFlagsMask & win32.VS_FF_DEBUG: + DebugBuild = (VersionInfo.dwFileFlags & win32.VS_FF_DEBUG) != 0 + else: + DebugBuild = None + + # Legacy OS build? + LegacyBuild = (VersionInfo.dwFileOS != win32.VOS_NT_WINDOWS32) + + # File type. + FileType = cls.__binary_types.get(VersionInfo.dwFileType) + if VersionInfo.dwFileType == win32.VFT_DRV: + FileType = cls.__driver_types.get(VersionInfo.dwFileSubtype) + elif VersionInfo.dwFileType == win32.VFT_FONT: + FileType = cls.__font_types.get(VersionInfo.dwFileSubtype) + + # Timestamp, ex: "Monday, July 7, 2013 (12:20:50.126)". + # FIXME: how do we know the time zone? + FileDate = (VersionInfo.dwFileDateMS << 32) + VersionInfo.dwFileDateLS + if FileDate: + CreationTime = win32.FileTimeToSystemTime(FileDate) + CreationTimestamp = "%s, %s %d, %d (%d:%d:%d.%d)" % ( + cls.__days_of_the_week[CreationTime.wDayOfWeek], + cls.__months[CreationTime.wMonth], + CreationTime.wDay, + CreationTime.wYear, + CreationTime.wHour, + CreationTime.wMinute, + CreationTime.wSecond, + CreationTime.wMilliseconds, + ) + else: + CreationTimestamp = None + + # Return the file version info. + return ( + FileVersion, + ProductVersion, + DebugBuild, + LegacyBuild, + FileType, + CreationTimestamp, + ) + +#------------------------------------------------------------------------------ + + # Locations for dbghelp.dll. + # Unfortunately, Microsoft started bundling WinDbg with the + # platform SDK, so the install directories may vary across + # versions and platforms. + __dbghelp_locations = { + + # Intel 64 bits. + win32.ARCH_AMD64: set([ + + # WinDbg bundled with the SDK, version 8.0. + path.join( + getenv("ProgramFiles", "C:\\Program Files"), + "Windows Kits", + "8.0", + "Debuggers", + "x64", + "dbghelp.dll"), + path.join( + getenv("ProgramW6432", getenv("ProgramFiles", + "C:\\Program Files")), + "Windows Kits", + "8.0", + "Debuggers", + "x64", + "dbghelp.dll"), + + # Old standalone versions of WinDbg. + path.join( + getenv("ProgramFiles", "C:\\Program Files"), + "Debugging Tools for Windows (x64)", + "dbghelp.dll"), + ]), + + # Intel 32 bits. + win32.ARCH_I386 : set([ + + # WinDbg bundled with the SDK, version 8.0. + path.join( + getenv("ProgramFiles", "C:\\Program Files"), + "Windows Kits", + "8.0", + "Debuggers", + "x86", + "dbghelp.dll"), + path.join( + getenv("ProgramW6432", getenv("ProgramFiles", + "C:\\Program Files")), + "Windows Kits", + "8.0", + "Debuggers", + "x86", + "dbghelp.dll"), + + # Old standalone versions of WinDbg. + path.join( + getenv("ProgramFiles", "C:\\Program Files"), + "Debugging Tools for Windows (x86)", + "dbghelp.dll"), + + # Version shipped with Windows. + path.join( + getenv("ProgramFiles", "C:\\Program Files"), + "Debugging Tools for Windows (x86)", + "dbghelp.dll"), + ]), + } + + @classmethod + def load_dbghelp(cls, pathname = None): + """ + Load the specified version of the C{dbghelp.dll} library. + + This library is shipped with the Debugging Tools for Windows, and it's + required to load debug symbols. + + Normally you don't need to call this method, as WinAppDbg already tries + to load the latest version automatically - but it may come in handy if + the Debugging Tools are installed in a non standard folder. + + Example:: + from winappdbg import Debug + + def simple_debugger( argv ): + + # Instance a Debug object, passing it the event handler callback + debug = Debug( my_event_handler ) + try: + + # Load a specific dbghelp.dll file + debug.system.load_dbghelp("C:\\Some folder\\dbghelp.dll") + + # Start a new process for debugging + debug.execv( argv ) + + # Wait for the debugee to finish + debug.loop() + + # Stop the debugger + finally: + debug.stop() + + @see: U{http://msdn.microsoft.com/en-us/library/ms679294(VS.85).aspx} + + @type pathname: str + @param pathname: + (Optional) Full pathname to the C{dbghelp.dll} library. + If not provided this method will try to autodetect it. + + @rtype: ctypes.WinDLL + @return: Loaded instance of C{dbghelp.dll}. + + @raise NotImplementedError: This feature was not implemented for the + current architecture. + + @raise WindowsError: An error occured while processing this request. + """ + + # If an explicit pathname was not given, search for the library. + if not pathname: + + # Under WOW64 we'll treat AMD64 as I386. + arch = win32.arch + if arch == win32.ARCH_AMD64 and win32.bits == 32: + arch = win32.ARCH_I386 + + # Check if the architecture is supported. + if not arch in cls.__dbghelp_locations: + msg = "Architecture %s is not currently supported." + raise NotImplementedError(msg % arch) + + # Grab all versions of the library we can find. + found = [] + for pathname in cls.__dbghelp_locations[arch]: + if path.isfile(pathname): + try: + f_ver, p_ver = cls.get_file_version_info(pathname)[:2] + except WindowsError: + msg = "Failed to parse file version metadata for: %s" + warnings.warn(msg % pathname) + if not f_ver: + f_ver = p_ver + elif p_ver and p_ver > f_ver: + f_ver = p_ver + found.append( (f_ver, pathname) ) + + # If we found any, use the newest version. + if found: + found.sort() + pathname = found.pop()[1] + + # If we didn't find any, trust the default DLL search algorithm. + else: + pathname = "dbghelp.dll" + + # Load the library. + dbghelp = ctypes.windll.LoadLibrary(pathname) + + # Set it globally as the library to be used. + ctypes.windll.dbghelp = dbghelp + + # Return the library. + return dbghelp + + @staticmethod + def fix_symbol_store_path(symbol_store_path = None, + remote = True, + force = False): + """ + Fix the symbol store path. Equivalent to the C{.symfix} command in + Microsoft WinDbg. + + If the symbol store path environment variable hasn't been set, this + method will provide a default one. + + @type symbol_store_path: str or None + @param symbol_store_path: (Optional) Symbol store path to set. + + @type remote: bool + @param remote: (Optional) Defines the symbol store path to set when the + C{symbol_store_path} is C{None}. + + If C{True} the default symbol store path is set to the Microsoft + symbol server. Debug symbols will be downloaded through HTTP. + This gives the best results but is also quite slow. + + If C{False} the default symbol store path is set to the local + cache only. This prevents debug symbols from being downloaded and + is faster, but unless you've installed the debug symbols on this + machine or downloaded them in a previous debugging session, some + symbols may be missing. + + If the C{symbol_store_path} argument is not C{None}, this argument + is ignored entirely. + + @type force: bool + @param force: (Optional) If C{True} the new symbol store path is set + always. If C{False} the new symbol store path is only set if + missing. + + This allows you to call this method preventively to ensure the + symbol server is always set up correctly when running your script, + but without messing up whatever configuration the user has. + + Example:: + from winappdbg import Debug, System + + def simple_debugger( argv ): + + # Instance a Debug object + debug = Debug( MyEventHandler() ) + try: + + # Make sure the remote symbol store is set + System.fix_symbol_store_path(remote = True, + force = False) + + # Start a new process for debugging + debug.execv( argv ) + + # Wait for the debugee to finish + debug.loop() + + # Stop the debugger + finally: + debug.stop() + + @rtype: str or None + @return: The previously set symbol store path if any, + otherwise returns C{None}. + """ + try: + if symbol_store_path is None: + local_path = "C:\\SYMBOLS" + if not path.isdir(local_path): + local_path = "C:\\Windows\\Symbols" + if not path.isdir(local_path): + local_path = path.abspath(".") + if remote: + symbol_store_path = ( + "cache*;SRV*" + + local_path + + "*" + "http://msdl.microsoft.com/download/symbols" + ) + else: + symbol_store_path = "cache*;SRV*" + local_path + previous = os.environ.get("_NT_SYMBOL_PATH", None) + if not previous or force: + os.environ["_NT_SYMBOL_PATH"] = symbol_store_path + return previous + except Exception: + e = sys.exc_info()[1] + warnings.warn("Cannot fix symbol path, reason: %s" % str(e), + RuntimeWarning) + +#------------------------------------------------------------------------------ + + @staticmethod + def set_kill_on_exit_mode(bKillOnExit = False): + """ + Defines the behavior of the debugged processes when the debugging + thread dies. This method only affects the calling thread. + + Works on the following platforms: + + - Microsoft Windows XP and above. + - Wine (Windows Emulator). + + Fails on the following platforms: + + - Microsoft Windows 2000 and below. + - ReactOS. + + @type bKillOnExit: bool + @param bKillOnExit: C{True} to automatically kill processes when the + debugger thread dies. C{False} to automatically detach from + processes when the debugger thread dies. + + @rtype: bool + @return: C{True} on success, C{False} on error. + + @note: + This call will fail if a debug port was not created. That is, if + the debugger isn't attached to at least one process. For more info + see: U{http://msdn.microsoft.com/en-us/library/ms679307.aspx} + """ + try: + # won't work before calling CreateProcess or DebugActiveProcess + win32.DebugSetProcessKillOnExit(bKillOnExit) + except (AttributeError, WindowsError): + return False + return True + + @staticmethod + def read_msr(address): + """ + Read the contents of the specified MSR (Machine Specific Register). + + @type address: int + @param address: MSR to read. + + @rtype: int + @return: Value of the specified MSR. + + @raise WindowsError: + Raises an exception on error. + + @raise NotImplementedError: + Current architecture is not C{i386} or C{amd64}. + + @warning: + It could potentially brick your machine. + It works on my machine, but your mileage may vary. + """ + if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64): + raise NotImplementedError( + "MSR reading is only supported on i386 or amd64 processors.") + msr = win32.SYSDBG_MSR() + msr.Address = address + msr.Data = 0 + win32.NtSystemDebugControl(win32.SysDbgReadMsr, + InputBuffer = msr, + OutputBuffer = msr) + return msr.Data + + @staticmethod + def write_msr(address, value): + """ + Set the contents of the specified MSR (Machine Specific Register). + + @type address: int + @param address: MSR to write. + + @type value: int + @param value: Contents to write on the MSR. + + @raise WindowsError: + Raises an exception on error. + + @raise NotImplementedError: + Current architecture is not C{i386} or C{amd64}. + + @warning: + It could potentially brick your machine. + It works on my machine, but your mileage may vary. + """ + if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64): + raise NotImplementedError( + "MSR writing is only supported on i386 or amd64 processors.") + msr = win32.SYSDBG_MSR() + msr.Address = address + msr.Data = value + win32.NtSystemDebugControl(win32.SysDbgWriteMsr, InputBuffer = msr) + + @classmethod + def enable_step_on_branch_mode(cls): + """ + When tracing, call this on every single step event + for step on branch mode. + + @raise WindowsError: + Raises C{ERROR_DEBUGGER_INACTIVE} if the debugger is not attached + to least one process. + + @raise NotImplementedError: + Current architecture is not C{i386} or C{amd64}. + + @warning: + This method uses the processor's machine specific registers (MSR). + It could potentially brick your machine. + It works on my machine, but your mileage may vary. + + @note: + It doesn't seem to work in VMWare or VirtualBox machines. + Maybe it fails in other virtualization/emulation environments, + no extensive testing was made so far. + """ + cls.write_msr(DebugRegister.DebugCtlMSR, + DebugRegister.BranchTrapFlag | DebugRegister.LastBranchRecord) + + @classmethod + def get_last_branch_location(cls): + """ + Returns the source and destination addresses of the last taken branch. + + @rtype: tuple( int, int ) + @return: Source and destination addresses of the last taken branch. + + @raise WindowsError: + Raises an exception on error. + + @raise NotImplementedError: + Current architecture is not C{i386} or C{amd64}. + + @warning: + This method uses the processor's machine specific registers (MSR). + It could potentially brick your machine. + It works on my machine, but your mileage may vary. + + @note: + It doesn't seem to work in VMWare or VirtualBox machines. + Maybe it fails in other virtualization/emulation environments, + no extensive testing was made so far. + """ + LastBranchFromIP = cls.read_msr(DebugRegister.LastBranchFromIP) + LastBranchToIP = cls.read_msr(DebugRegister.LastBranchToIP) + return ( LastBranchFromIP, LastBranchToIP ) + +#------------------------------------------------------------------------------ + + @classmethod + def get_postmortem_debugger(cls, bits = None): + """ + Returns the postmortem debugging settings from the Registry. + + @see: L{set_postmortem_debugger} + + @type bits: int + @param bits: Set to C{32} for the 32 bits debugger, or C{64} for the + 64 bits debugger. Set to {None} for the default (L{System.bits}. + + @rtype: tuple( str, bool, int ) + @return: A tuple containing the command line string to the postmortem + debugger, a boolean specifying if user interaction is allowed + before attaching, and an integer specifying a user defined hotkey. + Any member of the tuple may be C{None}. + See L{set_postmortem_debugger} for more details. + + @raise WindowsError: + Raises an exception on error. + """ + if bits is None: + bits = cls.bits + elif bits not in (32, 64): + raise NotImplementedError("Unknown architecture (%r bits)" % bits) + + if bits == 32 and cls.bits == 64: + keyname = 'HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug' + else: + keyname = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug' + + key = cls.registry[keyname] + + debugger = key.get('Debugger') + auto = key.get('Auto') + hotkey = key.get('UserDebuggerHotkey') + + if auto is not None: + auto = bool(auto) + + return (debugger, auto, hotkey) + + @classmethod + def get_postmortem_exclusion_list(cls, bits = None): + """ + Returns the exclusion list for the postmortem debugger. + + @see: L{get_postmortem_debugger} + + @type bits: int + @param bits: Set to C{32} for the 32 bits debugger, or C{64} for the + 64 bits debugger. Set to {None} for the default (L{System.bits}). + + @rtype: list( str ) + @return: List of excluded application filenames. + + @raise WindowsError: + Raises an exception on error. + """ + if bits is None: + bits = cls.bits + elif bits not in (32, 64): + raise NotImplementedError("Unknown architecture (%r bits)" % bits) + + if bits == 32 and cls.bits == 64: + keyname = 'HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList' + else: + keyname = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList' + + try: + key = cls.registry[keyname] + except KeyError: + return [] + + return [name for (name, enabled) in key.items() if enabled] + + @classmethod + def set_postmortem_debugger(cls, cmdline, + auto = None, hotkey = None, bits = None): + """ + Sets the postmortem debugging settings in the Registry. + + @warning: This method requires administrative rights. + + @see: L{get_postmortem_debugger} + + @type cmdline: str + @param cmdline: Command line to the new postmortem debugger. + When the debugger is invoked, the first "%ld" is replaced with the + process ID and the second "%ld" is replaced with the event handle. + Don't forget to enclose the program filename in double quotes if + the path contains spaces. + + @type auto: bool + @param auto: Set to C{True} if no user interaction is allowed, C{False} + to prompt a confirmation dialog before attaching. + Use C{None} to leave this value unchanged. + + @type hotkey: int + @param hotkey: Virtual key scan code for the user defined hotkey. + Use C{0} to disable the hotkey. + Use C{None} to leave this value unchanged. + + @type bits: int + @param bits: Set to C{32} for the 32 bits debugger, or C{64} for the + 64 bits debugger. Set to {None} for the default (L{System.bits}). + + @rtype: tuple( str, bool, int ) + @return: Previously defined command line and auto flag. + + @raise WindowsError: + Raises an exception on error. + """ + if bits is None: + bits = cls.bits + elif bits not in (32, 64): + raise NotImplementedError("Unknown architecture (%r bits)" % bits) + + if bits == 32 and cls.bits == 64: + keyname = 'HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug' + else: + keyname = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug' + + key = cls.registry[keyname] + + if cmdline is not None: + key['Debugger'] = cmdline + if auto is not None: + key['Auto'] = int(bool(auto)) + if hotkey is not None: + key['UserDebuggerHotkey'] = int(hotkey) + + @classmethod + def add_to_postmortem_exclusion_list(cls, pathname, bits = None): + """ + Adds the given filename to the exclusion list for postmortem debugging. + + @warning: This method requires administrative rights. + + @see: L{get_postmortem_exclusion_list} + + @type pathname: str + @param pathname: + Application pathname to exclude from postmortem debugging. + + @type bits: int + @param bits: Set to C{32} for the 32 bits debugger, or C{64} for the + 64 bits debugger. Set to {None} for the default (L{System.bits}). + + @raise WindowsError: + Raises an exception on error. + """ + if bits is None: + bits = cls.bits + elif bits not in (32, 64): + raise NotImplementedError("Unknown architecture (%r bits)" % bits) + + if bits == 32 and cls.bits == 64: + keyname = 'HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList' + else: + keyname = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList' + + try: + key = cls.registry[keyname] + except KeyError: + key = cls.registry.create(keyname) + + key[pathname] = 1 + + @classmethod + def remove_from_postmortem_exclusion_list(cls, pathname, bits = None): + """ + Removes the given filename to the exclusion list for postmortem + debugging from the Registry. + + @warning: This method requires administrative rights. + + @warning: Don't ever delete entries you haven't created yourself! + Some entries are set by default for your version of Windows. + Deleting them might deadlock your system under some circumstances. + + For more details see: + U{http://msdn.microsoft.com/en-us/library/bb204634(v=vs.85).aspx} + + @see: L{get_postmortem_exclusion_list} + + @type pathname: str + @param pathname: Application pathname to remove from the postmortem + debugging exclusion list. + + @type bits: int + @param bits: Set to C{32} for the 32 bits debugger, or C{64} for the + 64 bits debugger. Set to {None} for the default (L{System.bits}). + + @raise WindowsError: + Raises an exception on error. + """ + if bits is None: + bits = cls.bits + elif bits not in (32, 64): + raise NotImplementedError("Unknown architecture (%r bits)" % bits) + + if bits == 32 and cls.bits == 64: + keyname = 'HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList' + else: + keyname = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList' + + try: + key = cls.registry[keyname] + except KeyError: + return + + try: + del key[pathname] + except KeyError: + return + +#------------------------------------------------------------------------------ + + @staticmethod + def get_services(): + """ + Retrieve a list of all system services. + + @see: L{get_active_services}, + L{start_service}, L{stop_service}, + L{pause_service}, L{resume_service} + + @rtype: list( L{win32.ServiceStatusProcessEntry} ) + @return: List of service status descriptors. + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_ENUMERATE_SERVICE + ) as hSCManager: + try: + return win32.EnumServicesStatusEx(hSCManager) + except AttributeError: + return win32.EnumServicesStatus(hSCManager) + + @staticmethod + def get_active_services(): + """ + Retrieve a list of all active system services. + + @see: L{get_services}, + L{start_service}, L{stop_service}, + L{pause_service}, L{resume_service} + + @rtype: list( L{win32.ServiceStatusProcessEntry} ) + @return: List of service status descriptors. + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_ENUMERATE_SERVICE + ) as hSCManager: + return [ entry for entry in win32.EnumServicesStatusEx(hSCManager, + dwServiceType = win32.SERVICE_WIN32, + dwServiceState = win32.SERVICE_ACTIVE) \ + if entry.ProcessId ] + + @staticmethod + def get_service(name): + """ + Get the service descriptor for the given service name. + + @see: L{start_service}, L{stop_service}, + L{pause_service}, L{resume_service} + + @type name: str + @param name: Service unique name. You can get this value from the + C{ServiceName} member of the service descriptors returned by + L{get_services} or L{get_active_services}. + + @rtype: L{win32.ServiceStatusProcess} + @return: Service status descriptor. + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_ENUMERATE_SERVICE + ) as hSCManager: + with win32.OpenService(hSCManager, name, + dwDesiredAccess = win32.SERVICE_QUERY_STATUS + ) as hService: + try: + return win32.QueryServiceStatusEx(hService) + except AttributeError: + return win32.QueryServiceStatus(hService) + + @staticmethod + def get_service_display_name(name): + """ + Get the service display name for the given service name. + + @see: L{get_service} + + @type name: str + @param name: Service unique name. You can get this value from the + C{ServiceName} member of the service descriptors returned by + L{get_services} or L{get_active_services}. + + @rtype: str + @return: Service display name. + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_ENUMERATE_SERVICE + ) as hSCManager: + return win32.GetServiceDisplayName(hSCManager, name) + + @staticmethod + def get_service_from_display_name(displayName): + """ + Get the service unique name given its display name. + + @see: L{get_service} + + @type displayName: str + @param displayName: Service display name. You can get this value from + the C{DisplayName} member of the service descriptors returned by + L{get_services} or L{get_active_services}. + + @rtype: str + @return: Service unique name. + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_ENUMERATE_SERVICE + ) as hSCManager: + return win32.GetServiceKeyName(hSCManager, displayName) + + @staticmethod + def start_service(name, argv = None): + """ + Start the service given by name. + + @warn: This method requires UAC elevation in Windows Vista and above. + + @see: L{stop_service}, L{pause_service}, L{resume_service} + + @type name: str + @param name: Service unique name. You can get this value from the + C{ServiceName} member of the service descriptors returned by + L{get_services} or L{get_active_services}. + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_CONNECT + ) as hSCManager: + with win32.OpenService(hSCManager, name, + dwDesiredAccess = win32.SERVICE_START + ) as hService: + win32.StartService(hService) + + @staticmethod + def stop_service(name): + """ + Stop the service given by name. + + @warn: This method requires UAC elevation in Windows Vista and above. + + @see: L{get_services}, L{get_active_services}, + L{start_service}, L{pause_service}, L{resume_service} + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_CONNECT + ) as hSCManager: + with win32.OpenService(hSCManager, name, + dwDesiredAccess = win32.SERVICE_STOP + ) as hService: + win32.ControlService(hService, win32.SERVICE_CONTROL_STOP) + + @staticmethod + def pause_service(name): + """ + Pause the service given by name. + + @warn: This method requires UAC elevation in Windows Vista and above. + + @note: Not all services support this. + + @see: L{get_services}, L{get_active_services}, + L{start_service}, L{stop_service}, L{resume_service} + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_CONNECT + ) as hSCManager: + with win32.OpenService(hSCManager, name, + dwDesiredAccess = win32.SERVICE_PAUSE_CONTINUE + ) as hService: + win32.ControlService(hService, win32.SERVICE_CONTROL_PAUSE) + + @staticmethod + def resume_service(name): + """ + Resume the service given by name. + + @warn: This method requires UAC elevation in Windows Vista and above. + + @note: Not all services support this. + + @see: L{get_services}, L{get_active_services}, + L{start_service}, L{stop_service}, L{pause_service} + """ + with win32.OpenSCManager( + dwDesiredAccess = win32.SC_MANAGER_CONNECT + ) as hSCManager: + with win32.OpenService(hSCManager, name, + dwDesiredAccess = win32.SERVICE_PAUSE_CONTINUE + ) as hService: + win32.ControlService(hService, win32.SERVICE_CONTROL_CONTINUE) + + # TODO: create_service, delete_service diff --git a/pydevd_attach_to_process/winappdbg/textio.py b/pydevd_attach_to_process/winappdbg/textio.py new file mode 100644 index 0000000..402f631 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/textio.py @@ -0,0 +1,1879 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Functions for text input, logging or text output. + +@group Helpers: + HexDump, + HexInput, + HexOutput, + Color, + Table, + Logger + DebugLog + CrashDump +""" + +__revision__ = "$Id$" + +__all__ = [ + 'HexDump', + 'HexInput', + 'HexOutput', + 'Color', + 'Table', + 'CrashDump', + 'DebugLog', + 'Logger', + ] + +import sys +from winappdbg import win32 +from winappdbg import compat +from winappdbg.util import StaticClass + +import re +import time +import struct +import traceback + +#------------------------------------------------------------------------------ + +class HexInput (StaticClass): + """ + Static functions for user input parsing. + The counterparts for each method are in the L{HexOutput} class. + """ + + @staticmethod + def integer(token): + """ + Convert numeric strings into integers. + + @type token: str + @param token: String to parse. + + @rtype: int + @return: Parsed integer value. + """ + token = token.strip() + neg = False + if token.startswith(compat.b('-')): + token = token[1:] + neg = True + if token.startswith(compat.b('0x')): + result = int(token, 16) # hexadecimal + elif token.startswith(compat.b('0b')): + result = int(token[2:], 2) # binary + elif token.startswith(compat.b('0o')): + result = int(token, 8) # octal + else: + try: + result = int(token) # decimal + except ValueError: + result = int(token, 16) # hexadecimal (no "0x" prefix) + if neg: + result = -result + return result + + @staticmethod + def address(token): + """ + Convert numeric strings into memory addresses. + + @type token: str + @param token: String to parse. + + @rtype: int + @return: Parsed integer value. + """ + return int(token, 16) + + @staticmethod + def hexadecimal(token): + """ + Convert a strip of hexadecimal numbers into binary data. + + @type token: str + @param token: String to parse. + + @rtype: str + @return: Parsed string value. + """ + token = ''.join([ c for c in token if c.isalnum() ]) + if len(token) % 2 != 0: + raise ValueError("Missing characters in hex data") + data = '' + for i in compat.xrange(0, len(token), 2): + x = token[i:i+2] + d = int(x, 16) + s = struct.pack('= 0: + return ('0x%%.%dx' % (integer_size - 2)) % integer + return ('-0x%%.%dx' % (integer_size - 2)) % -integer + + @classmethod + def address(cls, address, bits = None): + """ + @type address: int + @param address: Memory address. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexOutput.address_size} + + @rtype: str + @return: Text output. + """ + if bits is None: + address_size = cls.address_size + bits = win32.bits + else: + address_size = (bits / 4) + 2 + if address < 0: + address = ((2 ** bits) - 1) ^ ~address + return ('0x%%.%dx' % (address_size - 2)) % address + + @staticmethod + def hexadecimal(data): + """ + Convert binary data to a string of hexadecimal numbers. + + @type data: str + @param data: Binary data. + + @rtype: str + @return: Hexadecimal representation. + """ + return HexDump.hexadecimal(data, separator = '') + + @classmethod + def integer_list_file(cls, filename, values, bits = None): + """ + Write a list of integers to a file. + If a file of the same name exists, it's contents are replaced. + + See L{HexInput.integer_list_file} for a description of the file format. + + @type filename: str + @param filename: Name of the file to write. + + @type values: list( int ) + @param values: List of integers to write to the file. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexOutput.integer_size} + """ + fd = open(filename, 'w') + for integer in values: + print >> fd, cls.integer(integer, bits) + fd.close() + + @classmethod + def string_list_file(cls, filename, values): + """ + Write a list of strings to a file. + If a file of the same name exists, it's contents are replaced. + + See L{HexInput.string_list_file} for a description of the file format. + + @type filename: str + @param filename: Name of the file to write. + + @type values: list( int ) + @param values: List of strings to write to the file. + """ + fd = open(filename, 'w') + for string in values: + print >> fd, string + fd.close() + + @classmethod + def mixed_list_file(cls, filename, values, bits): + """ + Write a list of mixed values to a file. + If a file of the same name exists, it's contents are replaced. + + See L{HexInput.mixed_list_file} for a description of the file format. + + @type filename: str + @param filename: Name of the file to write. + + @type values: list( int ) + @param values: List of mixed values to write to the file. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexOutput.integer_size} + """ + fd = open(filename, 'w') + for original in values: + try: + parsed = cls.integer(original, bits) + except TypeError: + parsed = repr(original) + print >> fd, parsed + fd.close() + +#------------------------------------------------------------------------------ + +class HexDump (StaticClass): + """ + Static functions for hexadecimal dumps. + + @type integer_size: int + @cvar integer_size: Size in characters of an outputted integer. + This value is platform dependent. + + @type address_size: int + @cvar address_size: Size in characters of an outputted address. + This value is platform dependent. + """ + + integer_size = (win32.SIZEOF(win32.DWORD) * 2) + address_size = (win32.SIZEOF(win32.SIZE_T) * 2) + + @classmethod + def integer(cls, integer, bits = None): + """ + @type integer: int + @param integer: Integer. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexDump.integer_size} + + @rtype: str + @return: Text output. + """ + if bits is None: + integer_size = cls.integer_size + else: + integer_size = bits / 4 + return ('%%.%dX' % integer_size) % integer + + @classmethod + def address(cls, address, bits = None): + """ + @type address: int + @param address: Memory address. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexDump.address_size} + + @rtype: str + @return: Text output. + """ + if bits is None: + address_size = cls.address_size + bits = win32.bits + else: + address_size = bits / 4 + if address < 0: + address = ((2 ** bits) - 1) ^ ~address + return ('%%.%dX' % address_size) % address + + @staticmethod + def printable(data): + """ + Replace unprintable characters with dots. + + @type data: str + @param data: Binary data. + + @rtype: str + @return: Printable text. + """ + result = '' + for c in data: + if 32 < ord(c) < 128: + result += c + else: + result += '.' + return result + + @staticmethod + def hexadecimal(data, separator = ''): + """ + Convert binary data to a string of hexadecimal numbers. + + @type data: str + @param data: Binary data. + + @type separator: str + @param separator: + Separator between the hexadecimal representation of each character. + + @rtype: str + @return: Hexadecimal representation. + """ + return separator.join( [ '%.2x' % ord(c) for c in data ] ) + + @staticmethod + def hexa_word(data, separator = ' '): + """ + Convert binary data to a string of hexadecimal WORDs. + + @type data: str + @param data: Binary data. + + @type separator: str + @param separator: + Separator between the hexadecimal representation of each WORD. + + @rtype: str + @return: Hexadecimal representation. + """ + if len(data) & 1 != 0: + data += '\0' + return separator.join( [ '%.4x' % struct.unpack(' 0: + width.extend( len_row[ -missing : ] ) + elif missing < 0: + len_row.extend( [0] * (-missing) ) + self.__width = [ max( width[i], len_row[i] ) for i in compat.xrange(len(len_row)) ] + self.__cols.append(row) + + def justify(self, column, direction): + """ + Make the text in a column left or right justified. + + @type column: int + @param column: Index of the column. + + @type direction: int + @param direction: + C{-1} to justify left, + C{1} to justify right. + + @raise IndexError: Bad column index. + @raise ValueError: Bad direction value. + """ + if direction == -1: + self.__width[column] = abs(self.__width[column]) + elif direction == 1: + self.__width[column] = - abs(self.__width[column]) + else: + raise ValueError("Bad direction value.") + + def getWidth(self): + """ + Get the width of the text output for the table. + + @rtype: int + @return: Width in characters for the text output, + including the newline character. + """ + width = 0 + if self.__width: + width = sum( abs(x) for x in self.__width ) + width = width + len(self.__width) * len(self.__sep) + 1 + return width + + def getOutput(self): + """ + Get the text output for the table. + + @rtype: str + @return: Text output. + """ + return '%s\n' % '\n'.join( self.yieldOutput() ) + + def yieldOutput(self): + """ + Generate the text output for the table. + + @rtype: generator of str + @return: Text output. + """ + width = self.__width + if width: + num_cols = len(width) + fmt = ['%%%ds' % -w for w in width] + if width[-1] > 0: + fmt[-1] = '%s' + fmt = self.__sep.join(fmt) + for row in self.__cols: + row.extend( [''] * (num_cols - len(row)) ) + yield fmt % tuple(row) + + def show(self): + """ + Print the text output for the table. + """ + print(self.getOutput()) + +#------------------------------------------------------------------------------ + +class CrashDump (StaticClass): + """ + Static functions for crash dumps. + + @type reg_template: str + @cvar reg_template: Template for the L{dump_registers} method. + """ + + # Templates for the dump_registers method. + reg_template = { + win32.ARCH_I386 : ( + 'eax=%(Eax).8x ebx=%(Ebx).8x ecx=%(Ecx).8x edx=%(Edx).8x esi=%(Esi).8x edi=%(Edi).8x\n' + 'eip=%(Eip).8x esp=%(Esp).8x ebp=%(Ebp).8x %(efl_dump)s\n' + 'cs=%(SegCs).4x ss=%(SegSs).4x ds=%(SegDs).4x es=%(SegEs).4x fs=%(SegFs).4x gs=%(SegGs).4x efl=%(EFlags).8x\n' + ), + win32.ARCH_AMD64 : ( + 'rax=%(Rax).16x rbx=%(Rbx).16x rcx=%(Rcx).16x\n' + 'rdx=%(Rdx).16x rsi=%(Rsi).16x rdi=%(Rdi).16x\n' + 'rip=%(Rip).16x rsp=%(Rsp).16x rbp=%(Rbp).16x\n' + ' r8=%(R8).16x r9=%(R9).16x r10=%(R10).16x\n' + 'r11=%(R11).16x r12=%(R12).16x r13=%(R13).16x\n' + 'r14=%(R14).16x r15=%(R15).16x\n' + '%(efl_dump)s\n' + 'cs=%(SegCs).4x ss=%(SegSs).4x ds=%(SegDs).4x es=%(SegEs).4x fs=%(SegFs).4x gs=%(SegGs).4x efl=%(EFlags).8x\n' + ), + } + + @staticmethod + def dump_flags(efl): + """ + Dump the x86 processor flags. + The output mimics that of the WinDBG debugger. + Used by L{dump_registers}. + + @type efl: int + @param efl: Value of the eFlags register. + + @rtype: str + @return: Text suitable for logging. + """ + if efl is None: + return '' + efl_dump = 'iopl=%1d' % ((efl & 0x3000) >> 12) + if efl & 0x100000: + efl_dump += ' vip' + else: + efl_dump += ' ' + if efl & 0x80000: + efl_dump += ' vif' + else: + efl_dump += ' ' + # 0x20000 ??? + if efl & 0x800: + efl_dump += ' ov' # Overflow + else: + efl_dump += ' no' # No overflow + if efl & 0x400: + efl_dump += ' dn' # Downwards + else: + efl_dump += ' up' # Upwards + if efl & 0x200: + efl_dump += ' ei' # Enable interrupts + else: + efl_dump += ' di' # Disable interrupts + # 0x100 trap flag + if efl & 0x80: + efl_dump += ' ng' # Negative + else: + efl_dump += ' pl' # Positive + if efl & 0x40: + efl_dump += ' zr' # Zero + else: + efl_dump += ' nz' # Nonzero + if efl & 0x10: + efl_dump += ' ac' # Auxiliary carry + else: + efl_dump += ' na' # No auxiliary carry + # 0x8 ??? + if efl & 0x4: + efl_dump += ' pe' # Parity odd + else: + efl_dump += ' po' # Parity even + # 0x2 ??? + if efl & 0x1: + efl_dump += ' cy' # Carry + else: + efl_dump += ' nc' # No carry + return efl_dump + + @classmethod + def dump_registers(cls, registers, arch = None): + """ + Dump the x86/x64 processor register values. + The output mimics that of the WinDBG debugger. + + @type registers: dict( str S{->} int ) + @param registers: Dictionary mapping register names to their values. + + @type arch: str + @param arch: Architecture of the machine whose registers were dumped. + Defaults to the current architecture. + Currently only the following architectures are supported: + - L{win32.ARCH_I386} + - L{win32.ARCH_AMD64} + + @rtype: str + @return: Text suitable for logging. + """ + if registers is None: + return '' + if arch is None: + if 'Eax' in registers: + arch = win32.ARCH_I386 + elif 'Rax' in registers: + arch = win32.ARCH_AMD64 + else: + arch = 'Unknown' + if arch not in cls.reg_template: + msg = "Don't know how to dump the registers for architecture: %s" + raise NotImplementedError(msg % arch) + registers = registers.copy() + registers['efl_dump'] = cls.dump_flags( registers['EFlags'] ) + return cls.reg_template[arch] % registers + + @staticmethod + def dump_registers_peek(registers, data, separator = ' ', width = 16): + """ + Dump data pointed to by the given registers, if any. + + @type registers: dict( str S{->} int ) + @param registers: Dictionary mapping register names to their values. + This value is returned by L{Thread.get_context}. + + @type data: dict( str S{->} str ) + @param data: Dictionary mapping register names to the data they point to. + This value is returned by L{Thread.peek_pointers_in_registers}. + + @rtype: str + @return: Text suitable for logging. + """ + if None in (registers, data): + return '' + names = compat.keys(data) + names.sort() + result = '' + for reg_name in names: + tag = reg_name.lower() + dumped = HexDump.hexline(data[reg_name], separator, width) + result += '%s -> %s\n' % (tag, dumped) + return result + + @staticmethod + def dump_data_peek(data, base = 0, + separator = ' ', + width = 16, + bits = None): + """ + Dump data from pointers guessed within the given binary data. + + @type data: str + @param data: Dictionary mapping offsets to the data they point to. + + @type base: int + @param base: Base offset. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexDump.address_size} + + @rtype: str + @return: Text suitable for logging. + """ + if data is None: + return '' + pointers = compat.keys(data) + pointers.sort() + result = '' + for offset in pointers: + dumped = HexDump.hexline(data[offset], separator, width) + address = HexDump.address(base + offset, bits) + result += '%s -> %s\n' % (address, dumped) + return result + + @staticmethod + def dump_stack_peek(data, separator = ' ', width = 16, arch = None): + """ + Dump data from pointers guessed within the given stack dump. + + @type data: str + @param data: Dictionary mapping stack offsets to the data they point to. + + @type separator: str + @param separator: + Separator between the hexadecimal representation of each character. + + @type width: int + @param width: + (Optional) Maximum number of characters to convert per text line. + This value is also used for padding. + + @type arch: str + @param arch: Architecture of the machine whose registers were dumped. + Defaults to the current architecture. + + @rtype: str + @return: Text suitable for logging. + """ + if data is None: + return '' + if arch is None: + arch = win32.arch + pointers = compat.keys(data) + pointers.sort() + result = '' + if pointers: + if arch == win32.ARCH_I386: + spreg = 'esp' + elif arch == win32.ARCH_AMD64: + spreg = 'rsp' + else: + spreg = 'STACK' # just a generic tag + tag_fmt = '[%s+0x%%.%dx]' % (spreg, len( '%x' % pointers[-1] ) ) + for offset in pointers: + dumped = HexDump.hexline(data[offset], separator, width) + tag = tag_fmt % offset + result += '%s -> %s\n' % (tag, dumped) + return result + + @staticmethod + def dump_stack_trace(stack_trace, bits = None): + """ + Dump a stack trace, as returned by L{Thread.get_stack_trace} with the + C{bUseLabels} parameter set to C{False}. + + @type stack_trace: list( int, int, str ) + @param stack_trace: Stack trace as a list of tuples of + ( return address, frame pointer, module filename ) + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexDump.address_size} + + @rtype: str + @return: Text suitable for logging. + """ + if not stack_trace: + return '' + table = Table() + table.addRow('Frame', 'Origin', 'Module') + for (fp, ra, mod) in stack_trace: + fp_d = HexDump.address(fp, bits) + ra_d = HexDump.address(ra, bits) + table.addRow(fp_d, ra_d, mod) + return table.getOutput() + + @staticmethod + def dump_stack_trace_with_labels(stack_trace, bits = None): + """ + Dump a stack trace, + as returned by L{Thread.get_stack_trace_with_labels}. + + @type stack_trace: list( int, int, str ) + @param stack_trace: Stack trace as a list of tuples of + ( return address, frame pointer, module filename ) + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexDump.address_size} + + @rtype: str + @return: Text suitable for logging. + """ + if not stack_trace: + return '' + table = Table() + table.addRow('Frame', 'Origin') + for (fp, label) in stack_trace: + table.addRow( HexDump.address(fp, bits), label ) + return table.getOutput() + + # TODO + # + Instead of a star when EIP points to, it would be better to show + # any register value (or other values like the exception address) that + # points to a location in the dissassembled code. + # + It'd be very useful to show some labels here. + # + It'd be very useful to show register contents for code at EIP + @staticmethod + def dump_code(disassembly, pc = None, + bLowercase = True, + bits = None): + """ + Dump a disassembly. Optionally mark where the program counter is. + + @type disassembly: list of tuple( int, int, str, str ) + @param disassembly: Disassembly dump as returned by + L{Process.disassemble} or L{Thread.disassemble_around_pc}. + + @type pc: int + @param pc: (Optional) Program counter. + + @type bLowercase: bool + @param bLowercase: (Optional) If C{True} convert the code to lowercase. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexDump.address_size} + + @rtype: str + @return: Text suitable for logging. + """ + if not disassembly: + return '' + table = Table(sep = ' | ') + for (addr, size, code, dump) in disassembly: + if bLowercase: + code = code.lower() + if addr == pc: + addr = ' * %s' % HexDump.address(addr, bits) + else: + addr = ' %s' % HexDump.address(addr, bits) + table.addRow(addr, dump, code) + table.justify(1, 1) + return table.getOutput() + + @staticmethod + def dump_code_line(disassembly_line, bShowAddress = True, + bShowDump = True, + bLowercase = True, + dwDumpWidth = None, + dwCodeWidth = None, + bits = None): + """ + Dump a single line of code. To dump a block of code use L{dump_code}. + + @type disassembly_line: tuple( int, int, str, str ) + @param disassembly_line: Single item of the list returned by + L{Process.disassemble} or L{Thread.disassemble_around_pc}. + + @type bShowAddress: bool + @param bShowAddress: (Optional) If C{True} show the memory address. + + @type bShowDump: bool + @param bShowDump: (Optional) If C{True} show the hexadecimal dump. + + @type bLowercase: bool + @param bLowercase: (Optional) If C{True} convert the code to lowercase. + + @type dwDumpWidth: int or None + @param dwDumpWidth: (Optional) Width in characters of the hex dump. + + @type dwCodeWidth: int or None + @param dwCodeWidth: (Optional) Width in characters of the code. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexDump.address_size} + + @rtype: str + @return: Text suitable for logging. + """ + if bits is None: + address_size = HexDump.address_size + else: + address_size = bits / 4 + (addr, size, code, dump) = disassembly_line + dump = dump.replace(' ', '') + result = list() + fmt = '' + if bShowAddress: + result.append( HexDump.address(addr, bits) ) + fmt += '%%%ds:' % address_size + if bShowDump: + result.append(dump) + if dwDumpWidth: + fmt += ' %%-%ds' % dwDumpWidth + else: + fmt += ' %s' + if bLowercase: + code = code.lower() + result.append(code) + if dwCodeWidth: + fmt += ' %%-%ds' % dwCodeWidth + else: + fmt += ' %s' + return fmt % tuple(result) + + @staticmethod + def dump_memory_map(memoryMap, mappedFilenames = None, bits = None): + """ + Dump the memory map of a process. Optionally show the filenames for + memory mapped files as well. + + @type memoryMap: list( L{win32.MemoryBasicInformation} ) + @param memoryMap: Memory map returned by L{Process.get_memory_map}. + + @type mappedFilenames: dict( int S{->} str ) + @param mappedFilenames: (Optional) Memory mapped filenames + returned by L{Process.get_mapped_filenames}. + + @type bits: int + @param bits: + (Optional) Number of bits of the target architecture. + The default is platform dependent. See: L{HexDump.address_size} + + @rtype: str + @return: Text suitable for logging. + """ + if not memoryMap: + return '' + + table = Table() + if mappedFilenames: + table.addRow("Address", "Size", "State", "Access", "Type", "File") + else: + table.addRow("Address", "Size", "State", "Access", "Type") + + # For each memory block in the map... + for mbi in memoryMap: + + # Address and size of memory block. + BaseAddress = HexDump.address(mbi.BaseAddress, bits) + RegionSize = HexDump.address(mbi.RegionSize, bits) + + # State (free or allocated). + mbiState = mbi.State + if mbiState == win32.MEM_RESERVE: + State = "Reserved" + elif mbiState == win32.MEM_COMMIT: + State = "Commited" + elif mbiState == win32.MEM_FREE: + State = "Free" + else: + State = "Unknown" + + # Page protection bits (R/W/X/G). + if mbiState != win32.MEM_COMMIT: + Protect = "" + else: + mbiProtect = mbi.Protect + if mbiProtect & win32.PAGE_NOACCESS: + Protect = "--- " + elif mbiProtect & win32.PAGE_READONLY: + Protect = "R-- " + elif mbiProtect & win32.PAGE_READWRITE: + Protect = "RW- " + elif mbiProtect & win32.PAGE_WRITECOPY: + Protect = "RC- " + elif mbiProtect & win32.PAGE_EXECUTE: + Protect = "--X " + elif mbiProtect & win32.PAGE_EXECUTE_READ: + Protect = "R-X " + elif mbiProtect & win32.PAGE_EXECUTE_READWRITE: + Protect = "RWX " + elif mbiProtect & win32.PAGE_EXECUTE_WRITECOPY: + Protect = "RCX " + else: + Protect = "??? " + if mbiProtect & win32.PAGE_GUARD: + Protect += "G" + else: + Protect += "-" + if mbiProtect & win32.PAGE_NOCACHE: + Protect += "N" + else: + Protect += "-" + if mbiProtect & win32.PAGE_WRITECOMBINE: + Protect += "W" + else: + Protect += "-" + + # Type (file mapping, executable image, or private memory). + mbiType = mbi.Type + if mbiType == win32.MEM_IMAGE: + Type = "Image" + elif mbiType == win32.MEM_MAPPED: + Type = "Mapped" + elif mbiType == win32.MEM_PRIVATE: + Type = "Private" + elif mbiType == 0: + Type = "" + else: + Type = "Unknown" + + # Output a row in the table. + if mappedFilenames: + FileName = mappedFilenames.get(mbi.BaseAddress, '') + table.addRow( BaseAddress, RegionSize, State, Protect, Type, FileName ) + else: + table.addRow( BaseAddress, RegionSize, State, Protect, Type ) + + # Return the table output. + return table.getOutput() + +#------------------------------------------------------------------------------ + +class DebugLog (StaticClass): + 'Static functions for debug logging.' + + @staticmethod + def log_text(text): + """ + Log lines of text, inserting a timestamp. + + @type text: str + @param text: Text to log. + + @rtype: str + @return: Log line. + """ + if text.endswith('\n'): + text = text[:-len('\n')] + #text = text.replace('\n', '\n\t\t') # text CSV + ltime = time.strftime("%X") + msecs = (time.time() % 1) * 1000 + return '[%s.%04d] %s' % (ltime, msecs, text) + #return '[%s.%04d]\t%s' % (ltime, msecs, text) # text CSV + + @classmethod + def log_event(cls, event, text = None): + """ + Log lines of text associated with a debug event. + + @type event: L{Event} + @param event: Event object. + + @type text: str + @param text: (Optional) Text to log. If no text is provided the default + is to show a description of the event itself. + + @rtype: str + @return: Log line. + """ + if not text: + if event.get_event_code() == win32.EXCEPTION_DEBUG_EVENT: + what = event.get_exception_description() + if event.is_first_chance(): + what = '%s (first chance)' % what + else: + what = '%s (second chance)' % what + try: + address = event.get_fault_address() + except NotImplementedError: + address = event.get_exception_address() + else: + what = event.get_event_name() + address = event.get_thread().get_pc() + process = event.get_process() + label = process.get_label_at_address(address) + address = HexDump.address(address, process.get_bits()) + if label: + where = '%s (%s)' % (address, label) + else: + where = address + text = '%s at %s' % (what, where) + text = 'pid %d tid %d: %s' % (event.get_pid(), event.get_tid(), text) + #text = 'pid %d tid %d:\t%s' % (event.get_pid(), event.get_tid(), text) # text CSV + return cls.log_text(text) + +#------------------------------------------------------------------------------ + +class Logger(object): + """ + Logs text to standard output and/or a text file. + + @type logfile: str or None + @ivar logfile: Append messages to this text file. + + @type verbose: bool + @ivar verbose: C{True} to print messages to standard output. + + @type fd: file + @ivar fd: File object where log messages are printed to. + C{None} if no log file is used. + """ + + def __init__(self, logfile = None, verbose = True): + """ + @type logfile: str or None + @param logfile: Append messages to this text file. + + @type verbose: bool + @param verbose: C{True} to print messages to standard output. + """ + self.verbose = verbose + self.logfile = logfile + if self.logfile: + self.fd = open(self.logfile, 'a+') + + def __logfile_error(self, e): + """ + Shows an error message to standard error + if the log file can't be written to. + + Used internally. + + @type e: Exception + @param e: Exception raised when trying to write to the log file. + """ + from sys import stderr + msg = "Warning, error writing log file %s: %s\n" + msg = msg % (self.logfile, str(e)) + stderr.write(DebugLog.log_text(msg)) + self.logfile = None + self.fd = None + + def __do_log(self, text): + """ + Writes the given text verbatim into the log file (if any) + and/or standard input (if the verbose flag is turned on). + + Used internally. + + @type text: str + @param text: Text to print. + """ + if isinstance(text, compat.unicode): + text = text.encode('cp1252') + if self.verbose: + print(text) + if self.logfile: + try: + self.fd.writelines('%s\n' % text) + except IOError: + e = sys.exc_info()[1] + self.__logfile_error(e) + + def log_text(self, text): + """ + Log lines of text, inserting a timestamp. + + @type text: str + @param text: Text to log. + """ + self.__do_log( DebugLog.log_text(text) ) + + def log_event(self, event, text = None): + """ + Log lines of text associated with a debug event. + + @type event: L{Event} + @param event: Event object. + + @type text: str + @param text: (Optional) Text to log. If no text is provided the default + is to show a description of the event itself. + """ + self.__do_log( DebugLog.log_event(event, text) ) + + def log_exc(self): + """ + Log lines of text associated with the last Python exception. + """ + self.__do_log( 'Exception raised: %s' % traceback.format_exc() ) + + def is_enabled(self): + """ + Determines if the logger will actually print anything when the log_* + methods are called. + + This may save some processing if the log text requires a lengthy + calculation to prepare. If no log file is set and stdout logging + is disabled, there's no point in preparing a log text that won't + be shown to anyone. + + @rtype: bool + @return: C{True} if a log file was set and/or standard output logging + is enabled, or C{False} otherwise. + """ + return self.verbose or self.logfile diff --git a/pydevd_attach_to_process/winappdbg/thread.py b/pydevd_attach_to_process/winappdbg/thread.py new file mode 100644 index 0000000..07313f2 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/thread.py @@ -0,0 +1,2127 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Thread instrumentation. + +@group Instrumentation: + Thread +""" + +from __future__ import with_statement + +__revision__ = "$Id$" + +__all__ = ['Thread'] + +from winappdbg import win32 +from winappdbg import compat +from winappdbg.textio import HexDump +from winappdbg.util import DebugRegister +from winappdbg.window import Window + +import sys +import struct +import warnings + +# delayed imports +Process = None + +#============================================================================== + +# TODO +# + fetch special registers (MMX, XMM, 3DNow!, etc) + +class Thread (object): + """ + Interface to a thread in another process. + + @group Properties: + get_tid, get_pid, get_process, set_process, get_exit_code, is_alive, + get_name, set_name, get_windows, get_teb, get_teb_address, is_wow64, + get_arch, get_bits, get_handle, open_handle, close_handle + + @group Instrumentation: + suspend, resume, kill, wait + + @group Debugging: + get_seh_chain_pointer, set_seh_chain_pointer, + get_seh_chain, get_wait_chain, is_hidden + + @group Disassembly: + disassemble, disassemble_around, disassemble_around_pc, + disassemble_string, disassemble_instruction, disassemble_current + + @group Stack: + get_stack_frame, get_stack_frame_range, get_stack_range, + get_stack_trace, get_stack_trace_with_labels, + read_stack_data, read_stack_dwords, read_stack_qwords, + peek_stack_data, peek_stack_dwords, peek_stack_qwords, + read_stack_structure, read_stack_frame + + @group Registers: + get_context, + get_register, + get_flags, get_flag_value, + get_pc, get_sp, get_fp, + get_cf, get_df, get_sf, get_tf, get_zf, + set_context, + set_register, + set_flags, set_flag_value, + set_pc, set_sp, set_fp, + set_cf, set_df, set_sf, set_tf, set_zf, + clear_cf, clear_df, clear_sf, clear_tf, clear_zf, + Flags + + @group Threads snapshot: + clear + + @group Miscellaneous: + read_code_bytes, peek_code_bytes, + peek_pointers_in_data, peek_pointers_in_registers, + get_linear_address, get_label_at_pc + + @type dwThreadId: int + @ivar dwThreadId: Global thread ID. Use L{get_tid} instead. + + @type hThread: L{ThreadHandle} + @ivar hThread: Handle to the thread. Use L{get_handle} instead. + + @type process: L{Process} + @ivar process: Parent process object. Use L{get_process} instead. + + @type pInjectedMemory: int + @ivar pInjectedMemory: If the thread was created by L{Process.inject_code}, + this member contains a pointer to the memory buffer for the injected + code. Otherwise it's C{None}. + + The L{kill} method uses this member to free the buffer + when the injected thread is killed. + """ + + def __init__(self, dwThreadId, hThread = None, process = None): + """ + @type dwThreadId: int + @param dwThreadId: Global thread ID. + + @type hThread: L{ThreadHandle} + @param hThread: (Optional) Handle to the thread. + + @type process: L{Process} + @param process: (Optional) Parent Process object. + """ + self.dwProcessId = None + self.dwThreadId = dwThreadId + self.hThread = hThread + self.pInjectedMemory = None + self.set_name(None) + self.set_process(process) + + # Not really sure if it's a good idea... +## def __eq__(self, aThread): +## """ +## Compare two Thread objects. The comparison is made using the IDs. +## +## @warning: +## If you have two Thread instances with different handles the +## equality operator still returns C{True}, so be careful! +## +## @type aThread: L{Thread} +## @param aThread: Another Thread object. +## +## @rtype: bool +## @return: C{True} if the two thread IDs are equal, +## C{False} otherwise. +## """ +## return isinstance(aThread, Thread) and \ +## self.get_tid() == aThread.get_tid() + + def __load_Process_class(self): + global Process # delayed import + if Process is None: + from winappdbg.process import Process + + def get_process(self): + """ + @rtype: L{Process} + @return: Parent Process object. + Returns C{None} if unknown. + """ + if self.__process is not None: + return self.__process + self.__load_Process_class() + self.__process = Process(self.get_pid()) + return self.__process + + def set_process(self, process = None): + """ + Manually set the parent Process object. Use with care! + + @type process: L{Process} + @param process: (Optional) Process object. Use C{None} for no process. + """ + if process is None: + self.dwProcessId = None + self.__process = None + else: + self.__load_Process_class() + if not isinstance(process, Process): + msg = "Parent process must be a Process instance, " + msg += "got %s instead" % type(process) + raise TypeError(msg) + self.dwProcessId = process.get_pid() + self.__process = process + + process = property(get_process, set_process, doc="") + + def get_pid(self): + """ + @rtype: int + @return: Parent process global ID. + + @raise WindowsError: An error occured when calling a Win32 API function. + @raise RuntimeError: The parent process ID can't be found. + """ + if self.dwProcessId is None: + if self.__process is not None: + # Infinite loop if self.__process is None + self.dwProcessId = self.get_process().get_pid() + else: + try: + # I wish this had been implemented before Vista... + # XXX TODO find the real ntdll call under this api + hThread = self.get_handle( + win32.THREAD_QUERY_LIMITED_INFORMATION) + self.dwProcessId = win32.GetProcessIdOfThread(hThread) + except AttributeError: + # This method is really bad :P + self.dwProcessId = self.__get_pid_by_scanning() + return self.dwProcessId + + def __get_pid_by_scanning(self): + 'Internally used by get_pid().' + dwProcessId = None + dwThreadId = self.get_tid() + with win32.CreateToolhelp32Snapshot(win32.TH32CS_SNAPTHREAD) as hSnapshot: + te = win32.Thread32First(hSnapshot) + while te is not None: + if te.th32ThreadID == dwThreadId: + dwProcessId = te.th32OwnerProcessID + break + te = win32.Thread32Next(hSnapshot) + if dwProcessId is None: + msg = "Cannot find thread ID %d in any process" % dwThreadId + raise RuntimeError(msg) + return dwProcessId + + def get_tid(self): + """ + @rtype: int + @return: Thread global ID. + """ + return self.dwThreadId + + def get_name(self): + """ + @rtype: str + @return: Thread name, or C{None} if the thread is nameless. + """ + return self.name + + def set_name(self, name = None): + """ + Sets the thread's name. + + @type name: str + @param name: Thread name, or C{None} if the thread is nameless. + """ + self.name = name + +#------------------------------------------------------------------------------ + + def open_handle(self, dwDesiredAccess = win32.THREAD_ALL_ACCESS): + """ + Opens a new handle to the thread, closing the previous one. + + The new handle is stored in the L{hThread} property. + + @warn: Normally you should call L{get_handle} instead, since it's much + "smarter" and tries to reuse handles and merge access rights. + + @type dwDesiredAccess: int + @param dwDesiredAccess: Desired access rights. + Defaults to L{win32.THREAD_ALL_ACCESS}. + See: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx} + + @raise WindowsError: It's not possible to open a handle to the thread + with the requested access rights. This tipically happens because + the target thread belongs to system process and the debugger is not + runnning with administrative rights. + """ + hThread = win32.OpenThread(dwDesiredAccess, win32.FALSE, self.dwThreadId) + + # In case hThread was set to an actual handle value instead of a Handle + # object. This shouldn't happen unless the user tinkered with it. + if not hasattr(self.hThread, '__del__'): + self.close_handle() + + self.hThread = hThread + + def close_handle(self): + """ + Closes the handle to the thread. + + @note: Normally you don't need to call this method. All handles + created by I{WinAppDbg} are automatically closed when the garbage + collector claims them. + """ + try: + if hasattr(self.hThread, 'close'): + self.hThread.close() + elif self.hThread not in (None, win32.INVALID_HANDLE_VALUE): + win32.CloseHandle(self.hThread) + finally: + self.hThread = None + + def get_handle(self, dwDesiredAccess = win32.THREAD_ALL_ACCESS): + """ + Returns a handle to the thread with I{at least} the access rights + requested. + + @note: + If a handle was previously opened and has the required access + rights, it's reused. If not, a new handle is opened with the + combination of the old and new access rights. + + @type dwDesiredAccess: int + @param dwDesiredAccess: Desired access rights. + See: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx} + + @rtype: ThreadHandle + @return: Handle to the thread. + + @raise WindowsError: It's not possible to open a handle to the thread + with the requested access rights. This tipically happens because + the target thread belongs to system process and the debugger is not + runnning with administrative rights. + """ + if self.hThread in (None, win32.INVALID_HANDLE_VALUE): + self.open_handle(dwDesiredAccess) + else: + dwAccess = self.hThread.dwAccess + if (dwAccess | dwDesiredAccess) != dwAccess: + self.open_handle(dwAccess | dwDesiredAccess) + return self.hThread + + def clear(self): + """ + Clears the resources held by this object. + """ + try: + self.set_process(None) + finally: + self.close_handle() + +#------------------------------------------------------------------------------ + + def wait(self, dwTimeout = None): + """ + Waits for the thread to finish executing. + + @type dwTimeout: int + @param dwTimeout: (Optional) Timeout value in milliseconds. + Use C{INFINITE} or C{None} for no timeout. + """ + self.get_handle(win32.SYNCHRONIZE).wait(dwTimeout) + + def kill(self, dwExitCode = 0): + """ + Terminates the thread execution. + + @note: If the C{lpInjectedMemory} member contains a valid pointer, + the memory is freed. + + @type dwExitCode: int + @param dwExitCode: (Optional) Thread exit code. + """ + hThread = self.get_handle(win32.THREAD_TERMINATE) + win32.TerminateThread(hThread, dwExitCode) + + # Ugliest hack ever, won't work if many pieces of code are injected. + # Seriously, what was I thinking? :( + if self.pInjectedMemory is not None: + try: + self.get_process().free(self.pInjectedMemory) + self.pInjectedMemory = None + except Exception: +## raise # XXX DEBUG + pass + + # XXX TODO + # suspend() and resume() should have a counter of how many times a thread + # was suspended, so on debugger exit they could (optionally!) be restored + + def suspend(self): + """ + Suspends the thread execution. + + @rtype: int + @return: Suspend count. If zero, the thread is running. + """ + hThread = self.get_handle(win32.THREAD_SUSPEND_RESUME) + if self.is_wow64(): + # FIXME this will be horribly slow on XP 64 + # since it'll try to resolve a missing API every time + try: + return win32.Wow64SuspendThread(hThread) + except AttributeError: + pass + return win32.SuspendThread(hThread) + + def resume(self): + """ + Resumes the thread execution. + + @rtype: int + @return: Suspend count. If zero, the thread is running. + """ + hThread = self.get_handle(win32.THREAD_SUSPEND_RESUME) + return win32.ResumeThread(hThread) + + def is_alive(self): + """ + @rtype: bool + @return: C{True} if the thread if currently running. + @raise WindowsError: + The debugger doesn't have enough privileges to perform this action. + """ + try: + self.wait(0) + except WindowsError: + e = sys.exc_info()[1] + error = e.winerror + if error == win32.ERROR_ACCESS_DENIED: + raise + return error == win32.WAIT_TIMEOUT + return True + + def get_exit_code(self): + """ + @rtype: int + @return: Thread exit code, or C{STILL_ACTIVE} if it's still alive. + """ + if win32.THREAD_ALL_ACCESS == win32.THREAD_ALL_ACCESS_VISTA: + dwAccess = win32.THREAD_QUERY_LIMITED_INFORMATION + else: + dwAccess = win32.THREAD_QUERY_INFORMATION + return win32.GetExitCodeThread( self.get_handle(dwAccess) ) + +#------------------------------------------------------------------------------ + + # XXX TODO + # Support for string searches on the window captions. + + def get_windows(self): + """ + @rtype: list of L{Window} + @return: Returns a list of windows handled by this thread. + """ + try: + process = self.get_process() + except Exception: + process = None + return [ + Window( hWnd, process, self ) \ + for hWnd in win32.EnumThreadWindows( self.get_tid() ) + ] + +#------------------------------------------------------------------------------ + + # TODO + # A registers cache could be implemented here. + def get_context(self, ContextFlags = None, bSuspend = False): + """ + Retrieves the execution context (i.e. the registers values) for this + thread. + + @type ContextFlags: int + @param ContextFlags: Optional, specify which registers to retrieve. + Defaults to C{win32.CONTEXT_ALL} which retrieves all registes + for the current platform. + + @type bSuspend: bool + @param bSuspend: C{True} to automatically suspend the thread before + getting its context, C{False} otherwise. + + Defaults to C{False} because suspending the thread during some + debug events (like thread creation or destruction) may lead to + strange errors. + + Note that WinAppDbg 1.4 used to suspend the thread automatically + always. This behavior was changed in version 1.5. + + @rtype: dict( str S{->} int ) + @return: Dictionary mapping register names to their values. + + @see: L{set_context} + """ + + # Some words on the "strange errors" that lead to the bSuspend + # parameter. Peter Van Eeckhoutte and I were working on a fix + # for some bugs he found in the 1.5 betas when we stumbled upon + # what seemed to be a deadlock in the debug API that caused the + # GetThreadContext() call never to return. Since removing the + # call to SuspendThread() solved the problem, and a few Google + # searches showed a handful of problems related to these two + # APIs and Wow64 environments, I decided to break compatibility. + # + # Here are some pages about the weird behavior of SuspendThread: + # http://zachsaw.blogspot.com.es/2010/11/wow64-bug-getthreadcontext-may-return.html + # http://stackoverflow.com/questions/3444190/windows-suspendthread-doesnt-getthreadcontext-fails + + # Get the thread handle. + dwAccess = win32.THREAD_GET_CONTEXT + if bSuspend: + dwAccess = dwAccess | win32.THREAD_SUSPEND_RESUME + hThread = self.get_handle(dwAccess) + + # Suspend the thread if requested. + if bSuspend: + try: + self.suspend() + except WindowsError: + # Threads can't be suspended when the exit process event + # arrives, but you can still get the context. + bSuspend = False + + # If an exception is raised, make sure the thread execution is resumed. + try: + + if win32.bits == self.get_bits(): + + # 64 bit debugger attached to 64 bit process, or + # 32 bit debugger attached to 32 bit process. + ctx = win32.GetThreadContext(hThread, + ContextFlags = ContextFlags) + + else: + if self.is_wow64(): + + # 64 bit debugger attached to 32 bit process. + if ContextFlags is not None: + ContextFlags &= ~win32.ContextArchMask + ContextFlags |= win32.WOW64_CONTEXT_i386 + ctx = win32.Wow64GetThreadContext(hThread, ContextFlags) + + else: + + # 32 bit debugger attached to 64 bit process. + # XXX only i386/AMD64 is supported in this particular case + if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64): + raise NotImplementedError() + if ContextFlags is not None: + ContextFlags &= ~win32.ContextArchMask + ContextFlags |= win32.context_amd64.CONTEXT_AMD64 + ctx = win32.context_amd64.GetThreadContext(hThread, + ContextFlags = ContextFlags) + + finally: + + # Resume the thread if we suspended it. + if bSuspend: + self.resume() + + # Return the context. + return ctx + + def set_context(self, context, bSuspend = False): + """ + Sets the values of the registers. + + @see: L{get_context} + + @type context: dict( str S{->} int ) + @param context: Dictionary mapping register names to their values. + + @type bSuspend: bool + @param bSuspend: C{True} to automatically suspend the thread before + setting its context, C{False} otherwise. + + Defaults to C{False} because suspending the thread during some + debug events (like thread creation or destruction) may lead to + strange errors. + + Note that WinAppDbg 1.4 used to suspend the thread automatically + always. This behavior was changed in version 1.5. + """ + + # Get the thread handle. + dwAccess = win32.THREAD_SET_CONTEXT + if bSuspend: + dwAccess = dwAccess | win32.THREAD_SUSPEND_RESUME + hThread = self.get_handle(dwAccess) + + # Suspend the thread if requested. + if bSuspend: + self.suspend() + # No fix for the exit process event bug. + # Setting the context of a dead thread is pointless anyway. + + # Set the thread context. + try: + if win32.bits == 64 and self.is_wow64(): + win32.Wow64SetThreadContext(hThread, context) + else: + win32.SetThreadContext(hThread, context) + + # Resume the thread if we suspended it. + finally: + if bSuspend: + self.resume() + + def get_register(self, register): + """ + @type register: str + @param register: Register name. + + @rtype: int + @return: Value of the requested register. + """ + 'Returns the value of a specific register.' + context = self.get_context() + return context[register] + + def set_register(self, register, value): + """ + Sets the value of a specific register. + + @type register: str + @param register: Register name. + + @rtype: int + @return: Register value. + """ + context = self.get_context() + context[register] = value + self.set_context(context) + +#------------------------------------------------------------------------------ + + # TODO: a metaclass would do a better job instead of checking the platform + # during module import, also would support mixing 32 and 64 bits + + if win32.arch in (win32.ARCH_I386, win32.ARCH_AMD64): + + def get_pc(self): + """ + @rtype: int + @return: Value of the program counter register. + """ + context = self.get_context(win32.CONTEXT_CONTROL) + return context.pc + + def set_pc(self, pc): + """ + Sets the value of the program counter register. + + @type pc: int + @param pc: Value of the program counter register. + """ + context = self.get_context(win32.CONTEXT_CONTROL) + context.pc = pc + self.set_context(context) + + def get_sp(self): + """ + @rtype: int + @return: Value of the stack pointer register. + """ + context = self.get_context(win32.CONTEXT_CONTROL) + return context.sp + + def set_sp(self, sp): + """ + Sets the value of the stack pointer register. + + @type sp: int + @param sp: Value of the stack pointer register. + """ + context = self.get_context(win32.CONTEXT_CONTROL) + context.sp = sp + self.set_context(context) + + def get_fp(self): + """ + @rtype: int + @return: Value of the frame pointer register. + """ + flags = win32.CONTEXT_CONTROL | win32.CONTEXT_INTEGER + context = self.get_context(flags) + return context.fp + + def set_fp(self, fp): + """ + Sets the value of the frame pointer register. + + @type fp: int + @param fp: Value of the frame pointer register. + """ + flags = win32.CONTEXT_CONTROL | win32.CONTEXT_INTEGER + context = self.get_context(flags) + context.fp = fp + self.set_context(context) + +#------------------------------------------------------------------------------ + + if win32.arch in (win32.ARCH_I386, win32.ARCH_AMD64): + + class Flags (object): + 'Commonly used processor flags' + Overflow = 0x800 + Direction = 0x400 + Interrupts = 0x200 + Trap = 0x100 + Sign = 0x80 + Zero = 0x40 + # 0x20 ??? + Auxiliary = 0x10 + # 0x8 ??? + Parity = 0x4 + # 0x2 ??? + Carry = 0x1 + + def get_flags(self, FlagMask = 0xFFFFFFFF): + """ + @type FlagMask: int + @param FlagMask: (Optional) Bitwise-AND mask. + + @rtype: int + @return: Flags register contents, optionally masking out some bits. + """ + context = self.get_context(win32.CONTEXT_CONTROL) + return context['EFlags'] & FlagMask + + def set_flags(self, eflags, FlagMask = 0xFFFFFFFF): + """ + Sets the flags register, optionally masking some bits. + + @type eflags: int + @param eflags: Flags register contents. + + @type FlagMask: int + @param FlagMask: (Optional) Bitwise-AND mask. + """ + context = self.get_context(win32.CONTEXT_CONTROL) + context['EFlags'] = (context['EFlags'] & FlagMask) | eflags + self.set_context(context) + + def get_flag_value(self, FlagBit): + """ + @type FlagBit: int + @param FlagBit: One of the L{Flags}. + + @rtype: bool + @return: Boolean value of the requested flag. + """ + return bool( self.get_flags(FlagBit) ) + + def set_flag_value(self, FlagBit, FlagValue): + """ + Sets a single flag, leaving the others intact. + + @type FlagBit: int + @param FlagBit: One of the L{Flags}. + + @type FlagValue: bool + @param FlagValue: Boolean value of the flag. + """ + if FlagValue: + eflags = FlagBit + else: + eflags = 0 + FlagMask = 0xFFFFFFFF ^ FlagBit + self.set_flags(eflags, FlagMask) + + def get_zf(self): + """ + @rtype: bool + @return: Boolean value of the Zero flag. + """ + return self.get_flag_value(self.Flags.Zero) + + def get_cf(self): + """ + @rtype: bool + @return: Boolean value of the Carry flag. + """ + return self.get_flag_value(self.Flags.Carry) + + def get_sf(self): + """ + @rtype: bool + @return: Boolean value of the Sign flag. + """ + return self.get_flag_value(self.Flags.Sign) + + def get_df(self): + """ + @rtype: bool + @return: Boolean value of the Direction flag. + """ + return self.get_flag_value(self.Flags.Direction) + + def get_tf(self): + """ + @rtype: bool + @return: Boolean value of the Trap flag. + """ + return self.get_flag_value(self.Flags.Trap) + + def clear_zf(self): + 'Clears the Zero flag.' + self.set_flag_value(self.Flags.Zero, False) + + def clear_cf(self): + 'Clears the Carry flag.' + self.set_flag_value(self.Flags.Carry, False) + + def clear_sf(self): + 'Clears the Sign flag.' + self.set_flag_value(self.Flags.Sign, False) + + def clear_df(self): + 'Clears the Direction flag.' + self.set_flag_value(self.Flags.Direction, False) + + def clear_tf(self): + 'Clears the Trap flag.' + self.set_flag_value(self.Flags.Trap, False) + + def set_zf(self): + 'Sets the Zero flag.' + self.set_flag_value(self.Flags.Zero, True) + + def set_cf(self): + 'Sets the Carry flag.' + self.set_flag_value(self.Flags.Carry, True) + + def set_sf(self): + 'Sets the Sign flag.' + self.set_flag_value(self.Flags.Sign, True) + + def set_df(self): + 'Sets the Direction flag.' + self.set_flag_value(self.Flags.Direction, True) + + def set_tf(self): + 'Sets the Trap flag.' + self.set_flag_value(self.Flags.Trap, True) + +#------------------------------------------------------------------------------ + + def is_wow64(self): + """ + Determines if the thread is running under WOW64. + + @rtype: bool + @return: + C{True} if the thread is running under WOW64. That is, it belongs + to a 32-bit application running in a 64-bit Windows. + + C{False} if the thread belongs to either a 32-bit application + running in a 32-bit Windows, or a 64-bit application running in a + 64-bit Windows. + + @raise WindowsError: On error an exception is raised. + + @see: U{http://msdn.microsoft.com/en-us/library/aa384249(VS.85).aspx} + """ + try: + wow64 = self.__wow64 + except AttributeError: + if (win32.bits == 32 and not win32.wow64): + wow64 = False + else: + wow64 = self.get_process().is_wow64() + self.__wow64 = wow64 + return wow64 + + def get_arch(self): + """ + @rtype: str + @return: The architecture in which this thread believes to be running. + For example, if running a 32 bit binary in a 64 bit machine, the + architecture returned by this method will be L{win32.ARCH_I386}, + but the value of L{System.arch} will be L{win32.ARCH_AMD64}. + """ + if win32.bits == 32 and not win32.wow64: + return win32.arch + return self.get_process().get_arch() + + def get_bits(self): + """ + @rtype: str + @return: The number of bits in which this thread believes to be + running. For example, if running a 32 bit binary in a 64 bit + machine, the number of bits returned by this method will be C{32}, + but the value of L{System.arch} will be C{64}. + """ + if win32.bits == 32 and not win32.wow64: + return 32 + return self.get_process().get_bits() + + def is_hidden(self): + """ + Determines if the thread has been hidden from debuggers. + + Some binary packers hide their own threads to thwart debugging. + + @rtype: bool + @return: C{True} if the thread is hidden from debuggers. + This means the thread's execution won't be stopped for debug + events, and thus said events won't be sent to the debugger. + """ + return win32.NtQueryInformationThread( + self.get_handle(), # XXX what permissions do I need? + win32.ThreadHideFromDebugger) + + def get_teb(self): + """ + Returns a copy of the TEB. + To dereference pointers in it call L{Process.read_structure}. + + @rtype: L{TEB} + @return: TEB structure. + @raise WindowsError: An exception is raised on error. + """ + return self.get_process().read_structure( self.get_teb_address(), + win32.TEB ) + + def get_teb_address(self): + """ + Returns a remote pointer to the TEB. + + @rtype: int + @return: Remote pointer to the L{TEB} structure. + @raise WindowsError: An exception is raised on error. + """ + try: + return self._teb_ptr + except AttributeError: + try: + hThread = self.get_handle(win32.THREAD_QUERY_INFORMATION) + tbi = win32.NtQueryInformationThread( hThread, + win32.ThreadBasicInformation) + address = tbi.TebBaseAddress + except WindowsError: + address = self.get_linear_address('SegFs', 0) # fs:[0] + if not address: + raise + self._teb_ptr = address + return address + + def get_linear_address(self, segment, address): + """ + Translates segment-relative addresses to linear addresses. + + Linear addresses can be used to access a process memory, + calling L{Process.read} and L{Process.write}. + + @type segment: str + @param segment: Segment register name. + + @type address: int + @param address: Segment relative memory address. + + @rtype: int + @return: Linear memory address. + + @raise ValueError: Address is too large for selector. + + @raise WindowsError: + The current architecture does not support selectors. + Selectors only exist in x86-based systems. + """ + hThread = self.get_handle(win32.THREAD_QUERY_INFORMATION) + selector = self.get_register(segment) + ldt = win32.GetThreadSelectorEntry(hThread, selector) + BaseLow = ldt.BaseLow + BaseMid = ldt.HighWord.Bytes.BaseMid << 16 + BaseHi = ldt.HighWord.Bytes.BaseHi << 24 + Base = BaseLow | BaseMid | BaseHi + LimitLow = ldt.LimitLow + LimitHi = ldt.HighWord.Bits.LimitHi << 16 + Limit = LimitLow | LimitHi + if address > Limit: + msg = "Address %s too large for segment %s (selector %d)" + msg = msg % (HexDump.address(address, self.get_bits()), + segment, selector) + raise ValueError(msg) + return Base + address + + def get_label_at_pc(self): + """ + @rtype: str + @return: Label that points to the instruction currently being executed. + """ + return self.get_process().get_label_at_address( self.get_pc() ) + + def get_seh_chain_pointer(self): + """ + Get the pointer to the first structured exception handler block. + + @rtype: int + @return: Remote pointer to the first block of the structured exception + handlers linked list. If the list is empty, the returned value is + C{0xFFFFFFFF}. + + @raise NotImplementedError: + This method is only supported in 32 bits versions of Windows. + """ + if win32.arch != win32.ARCH_I386: + raise NotImplementedError( + "SEH chain parsing is only supported in 32-bit Windows.") + + process = self.get_process() + address = self.get_linear_address( 'SegFs', 0 ) + return process.read_pointer( address ) + + def set_seh_chain_pointer(self, value): + """ + Change the pointer to the first structured exception handler block. + + @type value: int + @param value: Value of the remote pointer to the first block of the + structured exception handlers linked list. To disable SEH set the + value C{0xFFFFFFFF}. + + @raise NotImplementedError: + This method is only supported in 32 bits versions of Windows. + """ + if win32.arch != win32.ARCH_I386: + raise NotImplementedError( + "SEH chain parsing is only supported in 32-bit Windows.") + + process = self.get_process() + address = self.get_linear_address( 'SegFs', 0 ) + process.write_pointer( address, value ) + + def get_seh_chain(self): + """ + @rtype: list of tuple( int, int ) + @return: List of structured exception handlers. + Each SEH is represented as a tuple of two addresses: + - Address of this SEH block + - Address of the SEH callback function + Do not confuse this with the contents of the SEH block itself, + where the first member is a pointer to the B{next} block instead. + + @raise NotImplementedError: + This method is only supported in 32 bits versions of Windows. + """ + seh_chain = list() + try: + process = self.get_process() + seh = self.get_seh_chain_pointer() + while seh != 0xFFFFFFFF: + seh_func = process.read_pointer( seh + 4 ) + seh_chain.append( (seh, seh_func) ) + seh = process.read_pointer( seh ) + except WindowsError: + seh_chain.append( (seh, None) ) + return seh_chain + + def get_wait_chain(self): + """ + @rtype: + tuple of ( + list of L{win32.WaitChainNodeInfo} structures, + bool) + @return: + Wait chain for the thread. + The boolean indicates if there's a cycle in the chain (a deadlock). + @raise AttributeError: + This method is only suppported in Windows Vista and above. + @see: + U{http://msdn.microsoft.com/en-us/library/ms681622%28VS.85%29.aspx} + """ + with win32.OpenThreadWaitChainSession() as hWct: + return win32.GetThreadWaitChain(hWct, ThreadId = self.get_tid()) + + def get_stack_range(self): + """ + @rtype: tuple( int, int ) + @return: Stack beginning and end pointers, in memory addresses order. + That is, the first pointer is the stack top, and the second pointer + is the stack bottom, since the stack grows towards lower memory + addresses. + @raise WindowsError: Raises an exception on error. + """ + # TODO use teb.DeallocationStack too (max. possible stack size) + teb = self.get_teb() + tib = teb.NtTib + return ( tib.StackLimit, tib.StackBase ) # top, bottom + + def __get_stack_trace(self, depth = 16, bUseLabels = True, + bMakePretty = True): + """ + Tries to get a stack trace for the current function using the debug + helper API (dbghelp.dll). + + @type depth: int + @param depth: Maximum depth of stack trace. + + @type bUseLabels: bool + @param bUseLabels: C{True} to use labels, C{False} to use addresses. + + @type bMakePretty: bool + @param bMakePretty: + C{True} for user readable labels, + C{False} for labels that can be passed to L{Process.resolve_label}. + + "Pretty" labels look better when producing output for the user to + read, while pure labels are more useful programatically. + + @rtype: tuple of tuple( int, int, str ) + @return: Stack trace of the thread as a tuple of + ( return address, frame pointer address, module filename ) + when C{bUseLabels} is C{True}, or a tuple of + ( return address, frame pointer label ) + when C{bUseLabels} is C{False}. + + @raise WindowsError: Raises an exception on error. + """ + + aProcess = self.get_process() + arch = aProcess.get_arch() + bits = aProcess.get_bits() + + if arch == win32.ARCH_I386: + MachineType = win32.IMAGE_FILE_MACHINE_I386 + elif arch == win32.ARCH_AMD64: + MachineType = win32.IMAGE_FILE_MACHINE_AMD64 + elif arch == win32.ARCH_IA64: + MachineType = win32.IMAGE_FILE_MACHINE_IA64 + else: + msg = "Stack walking is not available for this architecture: %s" + raise NotImplementedError(msg % arch) + + hProcess = aProcess.get_handle( win32.PROCESS_VM_READ | + win32.PROCESS_QUERY_INFORMATION ) + hThread = self.get_handle( win32.THREAD_GET_CONTEXT | + win32.THREAD_QUERY_INFORMATION ) + + StackFrame = win32.STACKFRAME64() + StackFrame.AddrPC = win32.ADDRESS64( self.get_pc() ) + StackFrame.AddrFrame = win32.ADDRESS64( self.get_fp() ) + StackFrame.AddrStack = win32.ADDRESS64( self.get_sp() ) + + trace = list() + while win32.StackWalk64(MachineType, hProcess, hThread, StackFrame): + if depth <= 0: + break + fp = StackFrame.AddrFrame.Offset + ra = aProcess.peek_pointer(fp + 4) + if ra == 0: + break + lib = aProcess.get_module_at_address(ra) + if lib is None: + lib = "" + else: + if lib.fileName: + lib = lib.fileName + else: + lib = "%s" % HexDump.address(lib.lpBaseOfDll, bits) + if bUseLabels: + label = aProcess.get_label_at_address(ra) + if bMakePretty: + label = '%s (%s)' % (HexDump.address(ra, bits), label) + trace.append( (fp, label) ) + else: + trace.append( (fp, ra, lib) ) + fp = aProcess.peek_pointer(fp) + return tuple(trace) + + def __get_stack_trace_manually(self, depth = 16, bUseLabels = True, + bMakePretty = True): + """ + Tries to get a stack trace for the current function. + Only works for functions with standard prologue and epilogue. + + @type depth: int + @param depth: Maximum depth of stack trace. + + @type bUseLabels: bool + @param bUseLabels: C{True} to use labels, C{False} to use addresses. + + @type bMakePretty: bool + @param bMakePretty: + C{True} for user readable labels, + C{False} for labels that can be passed to L{Process.resolve_label}. + + "Pretty" labels look better when producing output for the user to + read, while pure labels are more useful programatically. + + @rtype: tuple of tuple( int, int, str ) + @return: Stack trace of the thread as a tuple of + ( return address, frame pointer address, module filename ) + when C{bUseLabels} is C{True}, or a tuple of + ( return address, frame pointer label ) + when C{bUseLabels} is C{False}. + + @raise WindowsError: Raises an exception on error. + """ + aProcess = self.get_process() + st, sb = self.get_stack_range() # top, bottom + fp = self.get_fp() + trace = list() + if aProcess.get_module_count() == 0: + aProcess.scan_modules() + bits = aProcess.get_bits() + while depth > 0: + if fp == 0: + break + if not st <= fp < sb: + break + ra = aProcess.peek_pointer(fp + 4) + if ra == 0: + break + lib = aProcess.get_module_at_address(ra) + if lib is None: + lib = "" + else: + if lib.fileName: + lib = lib.fileName + else: + lib = "%s" % HexDump.address(lib.lpBaseOfDll, bits) + if bUseLabels: + label = aProcess.get_label_at_address(ra) + if bMakePretty: + label = '%s (%s)' % (HexDump.address(ra, bits), label) + trace.append( (fp, label) ) + else: + trace.append( (fp, ra, lib) ) + fp = aProcess.peek_pointer(fp) + return tuple(trace) + + def get_stack_trace(self, depth = 16): + """ + Tries to get a stack trace for the current function. + Only works for functions with standard prologue and epilogue. + + @type depth: int + @param depth: Maximum depth of stack trace. + + @rtype: tuple of tuple( int, int, str ) + @return: Stack trace of the thread as a tuple of + ( return address, frame pointer address, module filename ). + + @raise WindowsError: Raises an exception on error. + """ + try: + trace = self.__get_stack_trace(depth, False) + except Exception: + import traceback + traceback.print_exc() + trace = () + if not trace: + trace = self.__get_stack_trace_manually(depth, False) + return trace + + def get_stack_trace_with_labels(self, depth = 16, bMakePretty = True): + """ + Tries to get a stack trace for the current function. + Only works for functions with standard prologue and epilogue. + + @type depth: int + @param depth: Maximum depth of stack trace. + + @type bMakePretty: bool + @param bMakePretty: + C{True} for user readable labels, + C{False} for labels that can be passed to L{Process.resolve_label}. + + "Pretty" labels look better when producing output for the user to + read, while pure labels are more useful programatically. + + @rtype: tuple of tuple( int, int, str ) + @return: Stack trace of the thread as a tuple of + ( return address, frame pointer label ). + + @raise WindowsError: Raises an exception on error. + """ + try: + trace = self.__get_stack_trace(depth, True, bMakePretty) + except Exception: + trace = () + if not trace: + trace = self.__get_stack_trace_manually(depth, True, bMakePretty) + return trace + + def get_stack_frame_range(self): + """ + Returns the starting and ending addresses of the stack frame. + Only works for functions with standard prologue and epilogue. + + @rtype: tuple( int, int ) + @return: Stack frame range. + May not be accurate, depending on the compiler used. + + @raise RuntimeError: The stack frame is invalid, + or the function doesn't have a standard prologue + and epilogue. + + @raise WindowsError: An error occured when getting the thread context. + """ + st, sb = self.get_stack_range() # top, bottom + sp = self.get_sp() + fp = self.get_fp() + size = fp - sp + if not st <= sp < sb: + raise RuntimeError('Stack pointer lies outside the stack') + if not st <= fp < sb: + raise RuntimeError('Frame pointer lies outside the stack') + if sp > fp: + raise RuntimeError('No valid stack frame found') + return (sp, fp) + + def get_stack_frame(self, max_size = None): + """ + Reads the contents of the current stack frame. + Only works for functions with standard prologue and epilogue. + + @type max_size: int + @param max_size: (Optional) Maximum amount of bytes to read. + + @rtype: str + @return: Stack frame data. + May not be accurate, depending on the compiler used. + May return an empty string. + + @raise RuntimeError: The stack frame is invalid, + or the function doesn't have a standard prologue + and epilogue. + + @raise WindowsError: An error occured when getting the thread context + or reading data from the process memory. + """ + sp, fp = self.get_stack_frame_range() + size = fp - sp + if max_size and size > max_size: + size = max_size + return self.get_process().peek(sp, size) + + def read_stack_data(self, size = 128, offset = 0): + """ + Reads the contents of the top of the stack. + + @type size: int + @param size: Number of bytes to read. + + @type offset: int + @param offset: Offset from the stack pointer to begin reading. + + @rtype: str + @return: Stack data. + + @raise WindowsError: Could not read the requested data. + """ + aProcess = self.get_process() + return aProcess.read(self.get_sp() + offset, size) + + def peek_stack_data(self, size = 128, offset = 0): + """ + Tries to read the contents of the top of the stack. + + @type size: int + @param size: Number of bytes to read. + + @type offset: int + @param offset: Offset from the stack pointer to begin reading. + + @rtype: str + @return: Stack data. + Returned data may be less than the requested size. + """ + aProcess = self.get_process() + return aProcess.peek(self.get_sp() + offset, size) + + def read_stack_dwords(self, count, offset = 0): + """ + Reads DWORDs from the top of the stack. + + @type count: int + @param count: Number of DWORDs to read. + + @type offset: int + @param offset: Offset from the stack pointer to begin reading. + + @rtype: tuple( int... ) + @return: Tuple of integers read from the stack. + + @raise WindowsError: Could not read the requested data. + """ + if count > 0: + stackData = self.read_stack_data(count * 4, offset) + return struct.unpack('<'+('L'*count), stackData) + return () + + def peek_stack_dwords(self, count, offset = 0): + """ + Tries to read DWORDs from the top of the stack. + + @type count: int + @param count: Number of DWORDs to read. + + @type offset: int + @param offset: Offset from the stack pointer to begin reading. + + @rtype: tuple( int... ) + @return: Tuple of integers read from the stack. + May be less than the requested number of DWORDs. + """ + stackData = self.peek_stack_data(count * 4, offset) + if len(stackData) & 3: + stackData = stackData[:-len(stackData) & 3] + if not stackData: + return () + return struct.unpack('<'+('L'*count), stackData) + + def read_stack_qwords(self, count, offset = 0): + """ + Reads QWORDs from the top of the stack. + + @type count: int + @param count: Number of QWORDs to read. + + @type offset: int + @param offset: Offset from the stack pointer to begin reading. + + @rtype: tuple( int... ) + @return: Tuple of integers read from the stack. + + @raise WindowsError: Could not read the requested data. + """ + stackData = self.read_stack_data(count * 8, offset) + return struct.unpack('<'+('Q'*count), stackData) + + def peek_stack_qwords(self, count, offset = 0): + """ + Tries to read QWORDs from the top of the stack. + + @type count: int + @param count: Number of QWORDs to read. + + @type offset: int + @param offset: Offset from the stack pointer to begin reading. + + @rtype: tuple( int... ) + @return: Tuple of integers read from the stack. + May be less than the requested number of QWORDs. + """ + stackData = self.peek_stack_data(count * 8, offset) + if len(stackData) & 7: + stackData = stackData[:-len(stackData) & 7] + if not stackData: + return () + return struct.unpack('<'+('Q'*count), stackData) + + def read_stack_structure(self, structure, offset = 0): + """ + Reads the given structure at the top of the stack. + + @type structure: ctypes.Structure + @param structure: Structure of the data to read from the stack. + + @type offset: int + @param offset: Offset from the stack pointer to begin reading. + The stack pointer is the same returned by the L{get_sp} method. + + @rtype: tuple + @return: Tuple of elements read from the stack. The type of each + element matches the types in the stack frame structure. + """ + aProcess = self.get_process() + stackData = aProcess.read_structure(self.get_sp() + offset, structure) + return tuple([ stackData.__getattribute__(name) + for (name, type) in stackData._fields_ ]) + + def read_stack_frame(self, structure, offset = 0): + """ + Reads the stack frame of the thread. + + @type structure: ctypes.Structure + @param structure: Structure of the stack frame. + + @type offset: int + @param offset: Offset from the frame pointer to begin reading. + The frame pointer is the same returned by the L{get_fp} method. + + @rtype: tuple + @return: Tuple of elements read from the stack frame. The type of each + element matches the types in the stack frame structure. + """ + aProcess = self.get_process() + stackData = aProcess.read_structure(self.get_fp() + offset, structure) + return tuple([ stackData.__getattribute__(name) + for (name, type) in stackData._fields_ ]) + + def read_code_bytes(self, size = 128, offset = 0): + """ + Tries to read some bytes of the code currently being executed. + + @type size: int + @param size: Number of bytes to read. + + @type offset: int + @param offset: Offset from the program counter to begin reading. + + @rtype: str + @return: Bytes read from the process memory. + + @raise WindowsError: Could not read the requested data. + """ + return self.get_process().read(self.get_pc() + offset, size) + + def peek_code_bytes(self, size = 128, offset = 0): + """ + Tries to read some bytes of the code currently being executed. + + @type size: int + @param size: Number of bytes to read. + + @type offset: int + @param offset: Offset from the program counter to begin reading. + + @rtype: str + @return: Bytes read from the process memory. + May be less than the requested number of bytes. + """ + return self.get_process().peek(self.get_pc() + offset, size) + + def peek_pointers_in_registers(self, peekSize = 16, context = None): + """ + Tries to guess which values in the registers are valid pointers, + and reads some data from them. + + @type peekSize: int + @param peekSize: Number of bytes to read from each pointer found. + + @type context: dict( str S{->} int ) + @param context: (Optional) + Dictionary mapping register names to their values. + If not given, the current thread context will be used. + + @rtype: dict( str S{->} str ) + @return: Dictionary mapping register names to the data they point to. + """ + peekable_registers = ( + 'Eax', 'Ebx', 'Ecx', 'Edx', 'Esi', 'Edi', 'Ebp' + ) + if not context: + context = self.get_context(win32.CONTEXT_CONTROL | \ + win32.CONTEXT_INTEGER) + aProcess = self.get_process() + data = dict() + for (reg_name, reg_value) in compat.iteritems(context): + if reg_name not in peekable_registers: + continue +## if reg_name == 'Ebp': +## stack_begin, stack_end = self.get_stack_range() +## print hex(stack_end), hex(reg_value), hex(stack_begin) +## if stack_begin and stack_end and stack_end < stack_begin and \ +## stack_begin <= reg_value <= stack_end: +## continue + reg_data = aProcess.peek(reg_value, peekSize) + if reg_data: + data[reg_name] = reg_data + return data + + # TODO + # try to avoid reading the same page twice by caching it + def peek_pointers_in_data(self, data, peekSize = 16, peekStep = 1): + """ + Tries to guess which values in the given data are valid pointers, + and reads some data from them. + + @type data: str + @param data: Binary data to find pointers in. + + @type peekSize: int + @param peekSize: Number of bytes to read from each pointer found. + + @type peekStep: int + @param peekStep: Expected data alignment. + Tipically you specify 1 when data alignment is unknown, + or 4 when you expect data to be DWORD aligned. + Any other value may be specified. + + @rtype: dict( str S{->} str ) + @return: Dictionary mapping stack offsets to the data they point to. + """ + aProcess = self.get_process() + return aProcess.peek_pointers_in_data(data, peekSize, peekStep) + +#------------------------------------------------------------------------------ + + # TODO + # The disassemble_around and disassemble_around_pc methods + # should take as parameter instruction counts rather than sizes + + def disassemble_string(self, lpAddress, code): + """ + Disassemble instructions from a block of binary code. + + @type lpAddress: int + @param lpAddress: Memory address where the code was read from. + + @type code: str + @param code: Binary code to disassemble. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + aProcess = self.get_process() + return aProcess.disassemble_string(lpAddress, code) + + def disassemble(self, lpAddress, dwSize): + """ + Disassemble instructions from the address space of the process. + + @type lpAddress: int + @param lpAddress: Memory address where to read the code from. + + @type dwSize: int + @param dwSize: Size of binary code to disassemble. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + aProcess = self.get_process() + return aProcess.disassemble(lpAddress, dwSize) + + def disassemble_around(self, lpAddress, dwSize = 64): + """ + Disassemble around the given address. + + @type lpAddress: int + @param lpAddress: Memory address where to read the code from. + + @type dwSize: int + @param dwSize: Delta offset. + Code will be read from lpAddress - dwSize to lpAddress + dwSize. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + aProcess = self.get_process() + return aProcess.disassemble_around(lpAddress, dwSize) + + def disassemble_around_pc(self, dwSize = 64): + """ + Disassemble around the program counter of the given thread. + + @type dwSize: int + @param dwSize: Delta offset. + Code will be read from pc - dwSize to pc + dwSize. + + @rtype: list of tuple( long, int, str, str ) + @return: List of tuples. Each tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + aProcess = self.get_process() + return aProcess.disassemble_around(self.get_pc(), dwSize) + + def disassemble_instruction(self, lpAddress): + """ + Disassemble the instruction at the given memory address. + + @type lpAddress: int + @param lpAddress: Memory address where to read the code from. + + @rtype: tuple( long, int, str, str ) + @return: The tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + aProcess = self.get_process() + return aProcess.disassemble(lpAddress, 15)[0] + + def disassemble_current(self): + """ + Disassemble the instruction at the program counter of the given thread. + + @rtype: tuple( long, int, str, str ) + @return: The tuple represents an assembly instruction + and contains: + - Memory address of instruction. + - Size of instruction in bytes. + - Disassembly line of instruction. + - Hexadecimal dump of instruction. + """ + return self.disassemble_instruction( self.get_pc() ) + +#============================================================================== + +class _ThreadContainer (object): + """ + Encapsulates the capability to contain Thread objects. + + @group Instrumentation: + start_thread + + @group Threads snapshot: + scan_threads, + get_thread, get_thread_count, get_thread_ids, + has_thread, iter_threads, iter_thread_ids, + find_threads_by_name, get_windows, + clear_threads, clear_dead_threads, close_thread_handles + """ + + def __init__(self): + self.__threadDict = dict() + + def __initialize_snapshot(self): + """ + Private method to automatically initialize the snapshot + when you try to use it without calling any of the scan_* + methods first. You don't need to call this yourself. + """ + if not self.__threadDict: + self.scan_threads() + + def __contains__(self, anObject): + """ + @type anObject: L{Thread}, int + @param anObject: + - C{int}: Global ID of the thread to look for. + - C{Thread}: Thread object to look for. + + @rtype: bool + @return: C{True} if the snapshot contains + a L{Thread} object with the same ID. + """ + if isinstance(anObject, Thread): + anObject = anObject.dwThreadId + return self.has_thread(anObject) + + def __iter__(self): + """ + @see: L{iter_threads} + @rtype: dictionary-valueiterator + @return: Iterator of L{Thread} objects in this snapshot. + """ + return self.iter_threads() + + def __len__(self): + """ + @see: L{get_thread_count} + @rtype: int + @return: Count of L{Thread} objects in this snapshot. + """ + return self.get_thread_count() + + def has_thread(self, dwThreadId): + """ + @type dwThreadId: int + @param dwThreadId: Global ID of the thread to look for. + + @rtype: bool + @return: C{True} if the snapshot contains a + L{Thread} object with the given global ID. + """ + self.__initialize_snapshot() + return dwThreadId in self.__threadDict + + def get_thread(self, dwThreadId): + """ + @type dwThreadId: int + @param dwThreadId: Global ID of the thread to look for. + + @rtype: L{Thread} + @return: Thread object with the given global ID. + """ + self.__initialize_snapshot() + if dwThreadId not in self.__threadDict: + msg = "Unknown thread ID: %d" % dwThreadId + raise KeyError(msg) + return self.__threadDict[dwThreadId] + + def iter_thread_ids(self): + """ + @see: L{iter_threads} + @rtype: dictionary-keyiterator + @return: Iterator of global thread IDs in this snapshot. + """ + self.__initialize_snapshot() + return compat.iterkeys(self.__threadDict) + + def iter_threads(self): + """ + @see: L{iter_thread_ids} + @rtype: dictionary-valueiterator + @return: Iterator of L{Thread} objects in this snapshot. + """ + self.__initialize_snapshot() + return compat.itervalues(self.__threadDict) + + def get_thread_ids(self): + """ + @rtype: list( int ) + @return: List of global thread IDs in this snapshot. + """ + self.__initialize_snapshot() + return compat.keys(self.__threadDict) + + def get_thread_count(self): + """ + @rtype: int + @return: Count of L{Thread} objects in this snapshot. + """ + self.__initialize_snapshot() + return len(self.__threadDict) + +#------------------------------------------------------------------------------ + + def find_threads_by_name(self, name, bExactMatch = True): + """ + Find threads by name, using different search methods. + + @type name: str, None + @param name: Name to look for. Use C{None} to find nameless threads. + + @type bExactMatch: bool + @param bExactMatch: C{True} if the name must be + B{exactly} as given, C{False} if the name can be + loosely matched. + + This parameter is ignored when C{name} is C{None}. + + @rtype: list( L{Thread} ) + @return: All threads matching the given name. + """ + found_threads = list() + + # Find threads with no name. + if name is None: + for aThread in self.iter_threads(): + if aThread.get_name() is None: + found_threads.append(aThread) + + # Find threads matching the given name exactly. + elif bExactMatch: + for aThread in self.iter_threads(): + if aThread.get_name() == name: + found_threads.append(aThread) + + # Find threads whose names match the given substring. + else: + for aThread in self.iter_threads(): + t_name = aThread.get_name() + if t_name is not None and name in t_name: + found_threads.append(aThread) + + return found_threads + +#------------------------------------------------------------------------------ + + # XXX TODO + # Support for string searches on the window captions. + + def get_windows(self): + """ + @rtype: list of L{Window} + @return: Returns a list of windows handled by this process. + """ + window_list = list() + for thread in self.iter_threads(): + window_list.extend( thread.get_windows() ) + return window_list + +#------------------------------------------------------------------------------ + + def start_thread(self, lpStartAddress, lpParameter=0, bSuspended = False): + """ + Remotely creates a new thread in the process. + + @type lpStartAddress: int + @param lpStartAddress: Start address for the new thread. + + @type lpParameter: int + @param lpParameter: Optional argument for the new thread. + + @type bSuspended: bool + @param bSuspended: C{True} if the new thread should be suspended. + In that case use L{Thread.resume} to start execution. + """ + if bSuspended: + dwCreationFlags = win32.CREATE_SUSPENDED + else: + dwCreationFlags = 0 + hProcess = self.get_handle( win32.PROCESS_CREATE_THREAD | + win32.PROCESS_QUERY_INFORMATION | + win32.PROCESS_VM_OPERATION | + win32.PROCESS_VM_WRITE | + win32.PROCESS_VM_READ ) + hThread, dwThreadId = win32.CreateRemoteThread( + hProcess, 0, 0, lpStartAddress, lpParameter, dwCreationFlags) + aThread = Thread(dwThreadId, hThread, self) + self._add_thread(aThread) + return aThread + +#------------------------------------------------------------------------------ + + # TODO + # maybe put all the toolhelp code into their own set of classes? + # + # XXX this method musn't end up calling __initialize_snapshot by accident! + def scan_threads(self): + """ + Populates the snapshot with running threads. + """ + + # Ignore special process IDs. + # PID 0: System Idle Process. Also has a special meaning to the + # toolhelp APIs (current process). + # PID 4: System Integrity Group. See this forum post for more info: + # http://tinyurl.com/ycza8jo + # (points to social.technet.microsoft.com) + # Only on XP and above + # PID 8: System (?) only in Windows 2000 and below AFAIK. + # It's probably the same as PID 4 in XP and above. + dwProcessId = self.get_pid() + if dwProcessId in (0, 4, 8): + return + +## dead_tids = set( self.get_thread_ids() ) # XXX triggers a scan + dead_tids = self._get_thread_ids() + dwProcessId = self.get_pid() + hSnapshot = win32.CreateToolhelp32Snapshot(win32.TH32CS_SNAPTHREAD, + dwProcessId) + try: + te = win32.Thread32First(hSnapshot) + while te is not None: + if te.th32OwnerProcessID == dwProcessId: + dwThreadId = te.th32ThreadID + if dwThreadId in dead_tids: + dead_tids.remove(dwThreadId) +## if not self.has_thread(dwThreadId): # XXX triggers a scan + if not self._has_thread_id(dwThreadId): + aThread = Thread(dwThreadId, process = self) + self._add_thread(aThread) + te = win32.Thread32Next(hSnapshot) + finally: + win32.CloseHandle(hSnapshot) + for tid in dead_tids: + self._del_thread(tid) + + def clear_dead_threads(self): + """ + Remove Thread objects from the snapshot + referring to threads no longer running. + """ + for tid in self.get_thread_ids(): + aThread = self.get_thread(tid) + if not aThread.is_alive(): + self._del_thread(aThread) + + def clear_threads(self): + """ + Clears the threads snapshot. + """ + for aThread in compat.itervalues(self.__threadDict): + aThread.clear() + self.__threadDict = dict() + + def close_thread_handles(self): + """ + Closes all open handles to threads in the snapshot. + """ + for aThread in self.iter_threads(): + try: + aThread.close_handle() + except Exception: + try: + e = sys.exc_info()[1] + msg = "Cannot close thread handle %s, reason: %s" + msg %= (aThread.hThread.value, str(e)) + warnings.warn(msg) + except Exception: + pass + +#------------------------------------------------------------------------------ + + # XXX _notify_* methods should not trigger a scan + + def _add_thread(self, aThread): + """ + Private method to add a thread object to the snapshot. + + @type aThread: L{Thread} + @param aThread: Thread object. + """ +## if not isinstance(aThread, Thread): +## if hasattr(aThread, '__class__'): +## typename = aThread.__class__.__name__ +## else: +## typename = str(type(aThread)) +## msg = "Expected Thread, got %s instead" % typename +## raise TypeError(msg) + dwThreadId = aThread.dwThreadId +## if dwThreadId in self.__threadDict: +## msg = "Already have a Thread object with ID %d" % dwThreadId +## raise KeyError(msg) + aThread.set_process(self) + self.__threadDict[dwThreadId] = aThread + + def _del_thread(self, dwThreadId): + """ + Private method to remove a thread object from the snapshot. + + @type dwThreadId: int + @param dwThreadId: Global thread ID. + """ + try: + aThread = self.__threadDict[dwThreadId] + del self.__threadDict[dwThreadId] + except KeyError: + aThread = None + msg = "Unknown thread ID %d" % dwThreadId + warnings.warn(msg, RuntimeWarning) + if aThread: + aThread.clear() # remove circular references + + def _has_thread_id(self, dwThreadId): + """ + Private method to test for a thread in the snapshot without triggering + an automatic scan. + """ + return dwThreadId in self.__threadDict + + def _get_thread_ids(self): + """ + Private method to get the list of thread IDs currently in the snapshot + without triggering an automatic scan. + """ + return compat.keys(self.__threadDict) + + def __add_created_thread(self, event): + """ + Private method to automatically add new thread objects from debug events. + + @type event: L{Event} + @param event: Event object. + """ + dwThreadId = event.get_tid() + hThread = event.get_thread_handle() +## if not self.has_thread(dwThreadId): # XXX this would trigger a scan + if not self._has_thread_id(dwThreadId): + aThread = Thread(dwThreadId, hThread, self) + teb_ptr = event.get_teb() # remember the TEB pointer + if teb_ptr: + aThread._teb_ptr = teb_ptr + self._add_thread(aThread) + #else: + # aThread = self.get_thread(dwThreadId) + # if hThread != win32.INVALID_HANDLE_VALUE: + # aThread.hThread = hThread # may have more privileges + + def _notify_create_process(self, event): + """ + Notify the creation of the main thread of this process. + + This is done automatically by the L{Debug} class, you shouldn't need + to call it yourself. + + @type event: L{CreateProcessEvent} + @param event: Create process event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + self.__add_created_thread(event) + return True + + def _notify_create_thread(self, event): + """ + Notify the creation of a new thread in this process. + + This is done automatically by the L{Debug} class, you shouldn't need + to call it yourself. + + @type event: L{CreateThreadEvent} + @param event: Create thread event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + self.__add_created_thread(event) + return True + + def _notify_exit_thread(self, event): + """ + Notify the termination of a thread. + + This is done automatically by the L{Debug} class, you shouldn't need + to call it yourself. + + @type event: L{ExitThreadEvent} + @param event: Exit thread event. + + @rtype: bool + @return: C{True} to call the user-defined handle, C{False} otherwise. + """ + dwThreadId = event.get_tid() +## if self.has_thread(dwThreadId): # XXX this would trigger a scan + if self._has_thread_id(dwThreadId): + self._del_thread(dwThreadId) + return True diff --git a/pydevd_attach_to_process/winappdbg/util.py b/pydevd_attach_to_process/winappdbg/util.py new file mode 100644 index 0000000..4a9a984 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/util.py @@ -0,0 +1,1038 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Miscellaneous utility classes and functions. + +@group Helpers: + PathOperations, + MemoryAddresses, + CustomAddressIterator, + DataAddressIterator, + ImageAddressIterator, + MappedAddressIterator, + ExecutableAddressIterator, + ReadableAddressIterator, + WriteableAddressIterator, + ExecutableAndWriteableAddressIterator, + DebugRegister, + Regenerator, + BannerHelpFormatter, + StaticClass, + classproperty +""" + +__revision__ = "$Id$" + +__all__ = [ + + # Filename and pathname manipulation + 'PathOperations', + + # Memory address operations + 'MemoryAddresses', + 'CustomAddressIterator', + 'DataAddressIterator', + 'ImageAddressIterator', + 'MappedAddressIterator', + 'ExecutableAddressIterator', + 'ReadableAddressIterator', + 'WriteableAddressIterator', + 'ExecutableAndWriteableAddressIterator', + + # Debug registers manipulation + 'DebugRegister', + + # Miscellaneous + 'Regenerator', + ] + +import sys +import os +import ctypes +import optparse + +from winappdbg import win32 +from winappdbg import compat + +#============================================================================== + +class classproperty(property): + """ + Class property method. + + Only works for getting properties, if you set them + the symbol gets overwritten in the class namespace. + + Inspired on: U{http://stackoverflow.com/a/7864317/426293} + """ + def __init__(self, fget=None, fset=None, fdel=None, doc=""): + if fset is not None or fdel is not None: + raise NotImplementedError() + super(classproperty, self).__init__(fget=classmethod(fget), doc=doc) + def __get__(self, cls, owner): + return self.fget.__get__(None, owner)() + +class BannerHelpFormatter(optparse.IndentedHelpFormatter): + "Just a small tweak to optparse to be able to print a banner." + def __init__(self, banner, *argv, **argd): + self.banner = banner + optparse.IndentedHelpFormatter.__init__(self, *argv, **argd) + def format_usage(self, usage): + msg = optparse.IndentedHelpFormatter.format_usage(self, usage) + return '%s\n%s' % (self.banner, msg) + +# See Process.generate_memory_snapshot() +class Regenerator(object): + """ + Calls a generator and iterates it. When it's finished iterating, the + generator is called again. This allows you to iterate a generator more + than once (well, sort of). + """ + + def __init__(self, g_function, *v_args, **d_args): + """ + @type g_function: function + @param g_function: Function that when called returns a generator. + + @type v_args: tuple + @param v_args: Variable arguments to pass to the generator function. + + @type d_args: dict + @param d_args: Variable arguments to pass to the generator function. + """ + self.__g_function = g_function + self.__v_args = v_args + self.__d_args = d_args + self.__g_object = None + + def __iter__(self): + 'x.__iter__() <==> iter(x)' + return self + + def next(self): + 'x.next() -> the next value, or raise StopIteration' + if self.__g_object is None: + self.__g_object = self.__g_function( *self.__v_args, **self.__d_args ) + try: + return self.__g_object.next() + except StopIteration: + self.__g_object = None + raise + +class StaticClass (object): + def __new__(cls, *argv, **argd): + "Don't try to instance this class, just use the static methods." + raise NotImplementedError( + "Cannot instance static class %s" % cls.__name__) + +#============================================================================== + +class PathOperations (StaticClass): + """ + Static methods for filename and pathname manipulation. + """ + + @staticmethod + def path_is_relative(path): + """ + @see: L{path_is_absolute} + + @type path: str + @param path: Absolute or relative path. + + @rtype: bool + @return: C{True} if the path is relative, C{False} if it's absolute. + """ + return win32.PathIsRelative(path) + + @staticmethod + def path_is_absolute(path): + """ + @see: L{path_is_relative} + + @type path: str + @param path: Absolute or relative path. + + @rtype: bool + @return: C{True} if the path is absolute, C{False} if it's relative. + """ + return not win32.PathIsRelative(path) + + @staticmethod + def make_relative(path, current = None): + """ + @type path: str + @param path: Absolute path. + + @type current: str + @param current: (Optional) Path to the current directory. + + @rtype: str + @return: Relative path. + + @raise WindowsError: It's impossible to make the path relative. + This happens when the path and the current path are not on the + same disk drive or network share. + """ + return win32.PathRelativePathTo(pszFrom = current, pszTo = path) + + @staticmethod + def make_absolute(path): + """ + @type path: str + @param path: Relative path. + + @rtype: str + @return: Absolute path. + """ + return win32.GetFullPathName(path)[0] + + @staticmethod + def split_extension(pathname): + """ + @type pathname: str + @param pathname: Absolute path. + + @rtype: tuple( str, str ) + @return: + Tuple containing the file and extension components of the filename. + """ + filepart = win32.PathRemoveExtension(pathname) + extpart = win32.PathFindExtension(pathname) + return (filepart, extpart) + + @staticmethod + def split_filename(pathname): + """ + @type pathname: str + @param pathname: Absolute path. + + @rtype: tuple( str, str ) + @return: Tuple containing the path to the file and the base filename. + """ + filepart = win32.PathFindFileName(pathname) + pathpart = win32.PathRemoveFileSpec(pathname) + return (pathpart, filepart) + + @staticmethod + def split_path(path): + """ + @see: L{join_path} + + @type path: str + @param path: Absolute or relative path. + + @rtype: list( str... ) + @return: List of path components. + """ + components = list() + while path: + next = win32.PathFindNextComponent(path) + if next: + prev = path[ : -len(next) ] + components.append(prev) + path = next + return components + + @staticmethod + def join_path(*components): + """ + @see: L{split_path} + + @type components: tuple( str... ) + @param components: Path components. + + @rtype: str + @return: Absolute or relative path. + """ + if components: + path = components[0] + for next in components[1:]: + path = win32.PathAppend(path, next) + else: + path = "" + return path + + @staticmethod + def native_to_win32_pathname(name): + """ + @type name: str + @param name: Native (NT) absolute pathname. + + @rtype: str + @return: Win32 absolute pathname. + """ + # XXX TODO + # There are probably some native paths that + # won't be converted by this naive approach. + if name.startswith(compat.b("\\")): + if name.startswith(compat.b("\\??\\")): + name = name[4:] + elif name.startswith(compat.b("\\SystemRoot\\")): + system_root_path = os.environ['SYSTEMROOT'] + if system_root_path.endswith('\\'): + system_root_path = system_root_path[:-1] + name = system_root_path + name[11:] + else: + for drive_number in compat.xrange(ord('A'), ord('Z') + 1): + drive_letter = '%c:' % drive_number + try: + device_native_path = win32.QueryDosDevice(drive_letter) + except WindowsError: + e = sys.exc_info()[1] + if e.winerror in (win32.ERROR_FILE_NOT_FOUND, \ + win32.ERROR_PATH_NOT_FOUND): + continue + raise + if not device_native_path.endswith(compat.b('\\')): + device_native_path += compat.b('\\') + if name.startswith(device_native_path): + name = drive_letter + compat.b('\\') + \ + name[ len(device_native_path) : ] + break + return name + + @staticmethod + def pathname_to_filename(pathname): + """ + Equivalent to: C{PathOperations.split_filename(pathname)[0]} + + @note: This function is preserved for backwards compatibility with + WinAppDbg 1.4 and earlier. It may be removed in future versions. + + @type pathname: str + @param pathname: Absolute path to a file. + + @rtype: str + @return: Filename component of the path. + """ + return win32.PathFindFileName(pathname) + +#============================================================================== + +class MemoryAddresses (StaticClass): + """ + Class to manipulate memory addresses. + + @type pageSize: int + @cvar pageSize: Page size in bytes. Defaults to 0x1000 but it's + automatically updated on runtime when importing the module. + """ + + @classproperty + def pageSize(cls): + """ + Try to get the pageSize value on runtime. + """ + try: + try: + pageSize = win32.GetSystemInfo().dwPageSize + except WindowsError: + pageSize = 0x1000 + except NameError: + pageSize = 0x1000 + cls.pageSize = pageSize # now this function won't be called again + return pageSize + + @classmethod + def align_address_to_page_start(cls, address): + """ + Align the given address to the start of the page it occupies. + + @type address: int + @param address: Memory address. + + @rtype: int + @return: Aligned memory address. + """ + return address - ( address % cls.pageSize ) + + @classmethod + def align_address_to_page_end(cls, address): + """ + Align the given address to the end of the page it occupies. + That is, to point to the start of the next page. + + @type address: int + @param address: Memory address. + + @rtype: int + @return: Aligned memory address. + """ + return address + cls.pageSize - ( address % cls.pageSize ) + + @classmethod + def align_address_range(cls, begin, end): + """ + Align the given address range to the start and end of the page(s) it occupies. + + @type begin: int + @param begin: Memory address of the beginning of the buffer. + Use C{None} for the first legal address in the address space. + + @type end: int + @param end: Memory address of the end of the buffer. + Use C{None} for the last legal address in the address space. + + @rtype: tuple( int, int ) + @return: Aligned memory addresses. + """ + if begin is None: + begin = 0 + if end is None: + end = win32.LPVOID(-1).value # XXX HACK + if end < begin: + begin, end = end, begin + begin = cls.align_address_to_page_start(begin) + if end != cls.align_address_to_page_start(end): + end = cls.align_address_to_page_end(end) + return (begin, end) + + @classmethod + def get_buffer_size_in_pages(cls, address, size): + """ + Get the number of pages in use by the given buffer. + + @type address: int + @param address: Aligned memory address. + + @type size: int + @param size: Buffer size. + + @rtype: int + @return: Buffer size in number of pages. + """ + if size < 0: + size = -size + address = address - size + begin, end = cls.align_address_range(address, address + size) + # XXX FIXME + # I think this rounding fails at least for address 0xFFFFFFFF size 1 + return int(float(end - begin) / float(cls.pageSize)) + + @staticmethod + def do_ranges_intersect(begin, end, old_begin, old_end): + """ + Determine if the two given memory address ranges intersect. + + @type begin: int + @param begin: Start address of the first range. + + @type end: int + @param end: End address of the first range. + + @type old_begin: int + @param old_begin: Start address of the second range. + + @type old_end: int + @param old_end: End address of the second range. + + @rtype: bool + @return: C{True} if the two ranges intersect, C{False} otherwise. + """ + return (old_begin <= begin < old_end) or \ + (old_begin < end <= old_end) or \ + (begin <= old_begin < end) or \ + (begin < old_end <= end) + +#============================================================================== + +def CustomAddressIterator(memory_map, condition): + """ + Generator function that iterates through a memory map, filtering memory + region blocks by any given condition. + + @type memory_map: list( L{win32.MemoryBasicInformation} ) + @param memory_map: List of memory region information objects. + Returned by L{Process.get_memory_map}. + + @type condition: function + @param condition: Callback function that returns C{True} if the memory + block should be returned, or C{False} if it should be filtered. + + @rtype: generator of L{win32.MemoryBasicInformation} + @return: Generator object to iterate memory blocks. + """ + for mbi in memory_map: + if condition(mbi): + address = mbi.BaseAddress + max_addr = address + mbi.RegionSize + while address < max_addr: + yield address + address = address + 1 + +def DataAddressIterator(memory_map): + """ + Generator function that iterates through a memory map, returning only those + memory blocks that contain data. + + @type memory_map: list( L{win32.MemoryBasicInformation} ) + @param memory_map: List of memory region information objects. + Returned by L{Process.get_memory_map}. + + @rtype: generator of L{win32.MemoryBasicInformation} + @return: Generator object to iterate memory blocks. + """ + return CustomAddressIterator(memory_map, + win32.MemoryBasicInformation.has_content) + +def ImageAddressIterator(memory_map): + """ + Generator function that iterates through a memory map, returning only those + memory blocks that belong to executable images. + + @type memory_map: list( L{win32.MemoryBasicInformation} ) + @param memory_map: List of memory region information objects. + Returned by L{Process.get_memory_map}. + + @rtype: generator of L{win32.MemoryBasicInformation} + @return: Generator object to iterate memory blocks. + """ + return CustomAddressIterator(memory_map, + win32.MemoryBasicInformation.is_image) + +def MappedAddressIterator(memory_map): + """ + Generator function that iterates through a memory map, returning only those + memory blocks that belong to memory mapped files. + + @type memory_map: list( L{win32.MemoryBasicInformation} ) + @param memory_map: List of memory region information objects. + Returned by L{Process.get_memory_map}. + + @rtype: generator of L{win32.MemoryBasicInformation} + @return: Generator object to iterate memory blocks. + """ + return CustomAddressIterator(memory_map, + win32.MemoryBasicInformation.is_mapped) + +def ReadableAddressIterator(memory_map): + """ + Generator function that iterates through a memory map, returning only those + memory blocks that are readable. + + @type memory_map: list( L{win32.MemoryBasicInformation} ) + @param memory_map: List of memory region information objects. + Returned by L{Process.get_memory_map}. + + @rtype: generator of L{win32.MemoryBasicInformation} + @return: Generator object to iterate memory blocks. + """ + return CustomAddressIterator(memory_map, + win32.MemoryBasicInformation.is_readable) + +def WriteableAddressIterator(memory_map): + """ + Generator function that iterates through a memory map, returning only those + memory blocks that are writeable. + + @note: Writeable memory is always readable too. + + @type memory_map: list( L{win32.MemoryBasicInformation} ) + @param memory_map: List of memory region information objects. + Returned by L{Process.get_memory_map}. + + @rtype: generator of L{win32.MemoryBasicInformation} + @return: Generator object to iterate memory blocks. + """ + return CustomAddressIterator(memory_map, + win32.MemoryBasicInformation.is_writeable) + +def ExecutableAddressIterator(memory_map): + """ + Generator function that iterates through a memory map, returning only those + memory blocks that are executable. + + @note: Executable memory is always readable too. + + @type memory_map: list( L{win32.MemoryBasicInformation} ) + @param memory_map: List of memory region information objects. + Returned by L{Process.get_memory_map}. + + @rtype: generator of L{win32.MemoryBasicInformation} + @return: Generator object to iterate memory blocks. + """ + return CustomAddressIterator(memory_map, + win32.MemoryBasicInformation.is_executable) + +def ExecutableAndWriteableAddressIterator(memory_map): + """ + Generator function that iterates through a memory map, returning only those + memory blocks that are executable and writeable. + + @note: The presence of such pages make memory corruption vulnerabilities + much easier to exploit. + + @type memory_map: list( L{win32.MemoryBasicInformation} ) + @param memory_map: List of memory region information objects. + Returned by L{Process.get_memory_map}. + + @rtype: generator of L{win32.MemoryBasicInformation} + @return: Generator object to iterate memory blocks. + """ + return CustomAddressIterator(memory_map, + win32.MemoryBasicInformation.is_executable_and_writeable) + +#============================================================================== +try: + _registerMask = win32.SIZE_T(-1).value +except TypeError: + if win32.SIZEOF(win32.SIZE_T) == 4: + _registerMask = 0xFFFFFFFF + elif win32.SIZEOF(win32.SIZE_T) == 8: + _registerMask = 0xFFFFFFFFFFFFFFFF + else: + raise + +class DebugRegister (StaticClass): + """ + Class to manipulate debug registers. + Used by L{HardwareBreakpoint}. + + @group Trigger flags used by HardwareBreakpoint: + BREAK_ON_EXECUTION, BREAK_ON_WRITE, BREAK_ON_ACCESS, BREAK_ON_IO_ACCESS + @group Size flags used by HardwareBreakpoint: + WATCH_BYTE, WATCH_WORD, WATCH_DWORD, WATCH_QWORD + @group Bitwise masks for Dr7: + enableMask, disableMask, triggerMask, watchMask, clearMask, + generalDetectMask + @group Bitwise masks for Dr6: + hitMask, hitMaskAll, debugAccessMask, singleStepMask, taskSwitchMask, + clearDr6Mask, clearHitMask + @group Debug control MSR definitions: + DebugCtlMSR, LastBranchRecord, BranchTrapFlag, PinControl, + LastBranchToIP, LastBranchFromIP, + LastExceptionToIP, LastExceptionFromIP + + @type BREAK_ON_EXECUTION: int + @cvar BREAK_ON_EXECUTION: Break on execution. + + @type BREAK_ON_WRITE: int + @cvar BREAK_ON_WRITE: Break on write. + + @type BREAK_ON_ACCESS: int + @cvar BREAK_ON_ACCESS: Break on read or write. + + @type BREAK_ON_IO_ACCESS: int + @cvar BREAK_ON_IO_ACCESS: Break on I/O port access. + Not supported by any hardware. + + @type WATCH_BYTE: int + @cvar WATCH_BYTE: Watch a byte. + + @type WATCH_WORD: int + @cvar WATCH_WORD: Watch a word. + + @type WATCH_DWORD: int + @cvar WATCH_DWORD: Watch a double word. + + @type WATCH_QWORD: int + @cvar WATCH_QWORD: Watch one quad word. + + @type enableMask: 4-tuple of integers + @cvar enableMask: + Enable bit on C{Dr7} for each slot. + Works as a bitwise-OR mask. + + @type disableMask: 4-tuple of integers + @cvar disableMask: + Mask of the enable bit on C{Dr7} for each slot. + Works as a bitwise-AND mask. + + @type triggerMask: 4-tuple of 2-tuples of integers + @cvar triggerMask: + Trigger bits on C{Dr7} for each trigger flag value. + Each 2-tuple has the bitwise-OR mask and the bitwise-AND mask. + + @type watchMask: 4-tuple of 2-tuples of integers + @cvar watchMask: + Watch bits on C{Dr7} for each watch flag value. + Each 2-tuple has the bitwise-OR mask and the bitwise-AND mask. + + @type clearMask: 4-tuple of integers + @cvar clearMask: + Mask of all important bits on C{Dr7} for each slot. + Works as a bitwise-AND mask. + + @type generalDetectMask: integer + @cvar generalDetectMask: + General detect mode bit. It enables the processor to notify the + debugger when the debugee is trying to access one of the debug + registers. + + @type hitMask: 4-tuple of integers + @cvar hitMask: + Hit bit on C{Dr6} for each slot. + Works as a bitwise-AND mask. + + @type hitMaskAll: integer + @cvar hitMaskAll: + Bitmask for all hit bits in C{Dr6}. Useful to know if at least one + hardware breakpoint was hit, or to clear the hit bits only. + + @type clearHitMask: integer + @cvar clearHitMask: + Bitmask to clear all the hit bits in C{Dr6}. + + @type debugAccessMask: integer + @cvar debugAccessMask: + The debugee tried to access a debug register. Needs bit + L{generalDetectMask} enabled in C{Dr7}. + + @type singleStepMask: integer + @cvar singleStepMask: + A single step exception was raised. Needs the trap flag enabled. + + @type taskSwitchMask: integer + @cvar taskSwitchMask: + A task switch has occurred. Needs the TSS T-bit set to 1. + + @type clearDr6Mask: integer + @cvar clearDr6Mask: + Bitmask to clear all meaningful bits in C{Dr6}. + """ + + BREAK_ON_EXECUTION = 0 + BREAK_ON_WRITE = 1 + BREAK_ON_ACCESS = 3 + BREAK_ON_IO_ACCESS = 2 + + WATCH_BYTE = 0 + WATCH_WORD = 1 + WATCH_DWORD = 3 + WATCH_QWORD = 2 + + registerMask = _registerMask + +#------------------------------------------------------------------------------ + + ########################################################################### + # http://en.wikipedia.org/wiki/Debug_register + # + # DR7 - Debug control + # + # The low-order eight bits of DR7 (0,2,4,6 and 1,3,5,7) selectively enable + # the four address breakpoint conditions. There are two levels of enabling: + # the local (0,2,4,6) and global (1,3,5,7) levels. The local enable bits + # are automatically reset by the processor at every task switch to avoid + # unwanted breakpoint conditions in the new task. The global enable bits + # are not reset by a task switch; therefore, they can be used for + # conditions that are global to all tasks. + # + # Bits 16-17 (DR0), 20-21 (DR1), 24-25 (DR2), 28-29 (DR3), define when + # breakpoints trigger. Each breakpoint has a two-bit entry that specifies + # whether they break on execution (00b), data write (01b), data read or + # write (11b). 10b is defined to mean break on IO read or write but no + # hardware supports it. Bits 18-19 (DR0), 22-23 (DR1), 26-27 (DR2), 30-31 + # (DR3), define how large area of memory is watched by breakpoints. Again + # each breakpoint has a two-bit entry that specifies whether they watch + # one (00b), two (01b), eight (10b) or four (11b) bytes. + ########################################################################### + + # Dr7 |= enableMask[register] + enableMask = ( + 1 << 0, # Dr0 (bit 0) + 1 << 2, # Dr1 (bit 2) + 1 << 4, # Dr2 (bit 4) + 1 << 6, # Dr3 (bit 6) + ) + + # Dr7 &= disableMask[register] + disableMask = tuple( [_registerMask ^ x for x in enableMask] ) # The registerMask from the class is not there in py3 + try: + del x # It's not there in py3 + except: + pass + + # orMask, andMask = triggerMask[register][trigger] + # Dr7 = (Dr7 & andMask) | orMask # to set + # Dr7 = Dr7 & andMask # to remove + triggerMask = ( + # Dr0 (bits 16-17) + ( + ((0 << 16), (3 << 16) ^ registerMask), # execute + ((1 << 16), (3 << 16) ^ registerMask), # write + ((2 << 16), (3 << 16) ^ registerMask), # io read + ((3 << 16), (3 << 16) ^ registerMask), # access + ), + # Dr1 (bits 20-21) + ( + ((0 << 20), (3 << 20) ^ registerMask), # execute + ((1 << 20), (3 << 20) ^ registerMask), # write + ((2 << 20), (3 << 20) ^ registerMask), # io read + ((3 << 20), (3 << 20) ^ registerMask), # access + ), + # Dr2 (bits 24-25) + ( + ((0 << 24), (3 << 24) ^ registerMask), # execute + ((1 << 24), (3 << 24) ^ registerMask), # write + ((2 << 24), (3 << 24) ^ registerMask), # io read + ((3 << 24), (3 << 24) ^ registerMask), # access + ), + # Dr3 (bits 28-29) + ( + ((0 << 28), (3 << 28) ^ registerMask), # execute + ((1 << 28), (3 << 28) ^ registerMask), # write + ((2 << 28), (3 << 28) ^ registerMask), # io read + ((3 << 28), (3 << 28) ^ registerMask), # access + ), + ) + + # orMask, andMask = watchMask[register][watch] + # Dr7 = (Dr7 & andMask) | orMask # to set + # Dr7 = Dr7 & andMask # to remove + watchMask = ( + # Dr0 (bits 18-19) + ( + ((0 << 18), (3 << 18) ^ registerMask), # byte + ((1 << 18), (3 << 18) ^ registerMask), # word + ((2 << 18), (3 << 18) ^ registerMask), # qword + ((3 << 18), (3 << 18) ^ registerMask), # dword + ), + # Dr1 (bits 22-23) + ( + ((0 << 23), (3 << 23) ^ registerMask), # byte + ((1 << 23), (3 << 23) ^ registerMask), # word + ((2 << 23), (3 << 23) ^ registerMask), # qword + ((3 << 23), (3 << 23) ^ registerMask), # dword + ), + # Dr2 (bits 26-27) + ( + ((0 << 26), (3 << 26) ^ registerMask), # byte + ((1 << 26), (3 << 26) ^ registerMask), # word + ((2 << 26), (3 << 26) ^ registerMask), # qword + ((3 << 26), (3 << 26) ^ registerMask), # dword + ), + # Dr3 (bits 30-31) + ( + ((0 << 30), (3 << 31) ^ registerMask), # byte + ((1 << 30), (3 << 31) ^ registerMask), # word + ((2 << 30), (3 << 31) ^ registerMask), # qword + ((3 << 30), (3 << 31) ^ registerMask), # dword + ), + ) + + # Dr7 = Dr7 & clearMask[register] + clearMask = ( + registerMask ^ ( (1 << 0) + (3 << 16) + (3 << 18) ), # Dr0 + registerMask ^ ( (1 << 2) + (3 << 20) + (3 << 22) ), # Dr1 + registerMask ^ ( (1 << 4) + (3 << 24) + (3 << 26) ), # Dr2 + registerMask ^ ( (1 << 6) + (3 << 28) + (3 << 30) ), # Dr3 + ) + + # Dr7 = Dr7 | generalDetectMask + generalDetectMask = (1 << 13) + + ########################################################################### + # http://en.wikipedia.org/wiki/Debug_register + # + # DR6 - Debug status + # + # The debug status register permits the debugger to determine which debug + # conditions have occurred. When the processor detects an enabled debug + # exception, it sets the low-order bits of this register (0,1,2,3) before + # entering the debug exception handler. + # + # Note that the bits of DR6 are never cleared by the processor. To avoid + # any confusion in identifying the next debug exception, the debug handler + # should move zeros to DR6 immediately before returning. + ########################################################################### + + # bool(Dr6 & hitMask[register]) + hitMask = ( + (1 << 0), # Dr0 + (1 << 1), # Dr1 + (1 << 2), # Dr2 + (1 << 3), # Dr3 + ) + + # bool(Dr6 & anyHitMask) + hitMaskAll = hitMask[0] | hitMask[1] | hitMask[2] | hitMask[3] + + # Dr6 = Dr6 & clearHitMask + clearHitMask = registerMask ^ hitMaskAll + + # bool(Dr6 & debugAccessMask) + debugAccessMask = (1 << 13) + + # bool(Dr6 & singleStepMask) + singleStepMask = (1 << 14) + + # bool(Dr6 & taskSwitchMask) + taskSwitchMask = (1 << 15) + + # Dr6 = Dr6 & clearDr6Mask + clearDr6Mask = registerMask ^ (hitMaskAll | \ + debugAccessMask | singleStepMask | taskSwitchMask) + +#------------------------------------------------------------------------------ + +############################################################################### +# +# (from the AMD64 manuals) +# +# The fields within the DebugCtlMSR register are: +# +# Last-Branch Record (LBR) - Bit 0, read/write. Software sets this bit to 1 +# to cause the processor to record the source and target addresses of the +# last control transfer taken before a debug exception occurs. The recorded +# control transfers include branch instructions, interrupts, and exceptions. +# +# Branch Single Step (BTF) - Bit 1, read/write. Software uses this bit to +# change the behavior of the rFLAGS.TF bit. When this bit is cleared to 0, +# the rFLAGS.TF bit controls instruction single stepping, (normal behavior). +# When this bit is set to 1, the rFLAGS.TF bit controls single stepping on +# control transfers. The single-stepped control transfers include branch +# instructions, interrupts, and exceptions. Control-transfer single stepping +# requires both BTF=1 and rFLAGS.TF=1. +# +# Performance-Monitoring/Breakpoint Pin-Control (PBi) - Bits 5-2, read/write. +# Software uses these bits to control the type of information reported by +# the four external performance-monitoring/breakpoint pins on the processor. +# When a PBi bit is cleared to 0, the corresponding external pin (BPi) +# reports performance-monitor information. When a PBi bit is set to 1, the +# corresponding external pin (BPi) reports breakpoint information. +# +# All remaining bits in the DebugCtlMSR register are reserved. +# +# Software can enable control-transfer single stepping by setting +# DebugCtlMSR.BTF to 1 and rFLAGS.TF to 1. The processor automatically +# disables control-transfer single stepping when a debug exception (#DB) +# occurs by clearing DebugCtlMSR.BTF to 0. rFLAGS.TF is also cleared when a +# #DB exception occurs. Before exiting the debug-exception handler, software +# must set both DebugCtlMSR.BTF and rFLAGS.TF to 1 to restart single +# stepping. +# +############################################################################### + + DebugCtlMSR = 0x1D9 + LastBranchRecord = (1 << 0) + BranchTrapFlag = (1 << 1) + PinControl = ( + (1 << 2), # PB1 + (1 << 3), # PB2 + (1 << 4), # PB3 + (1 << 5), # PB4 + ) + +############################################################################### +# +# (from the AMD64 manuals) +# +# Control-transfer recording MSRs: LastBranchToIP, LastBranchFromIP, +# LastExceptionToIP, and LastExceptionFromIP. These registers are loaded +# automatically by the processor when the DebugCtlMSR.LBR bit is set to 1. +# These MSRs are read-only. +# +# The processor automatically disables control-transfer recording when a +# debug exception (#DB) occurs by clearing DebugCtlMSR.LBR to 0. The +# contents of the control-transfer recording MSRs are not altered by the +# processor when the #DB occurs. Before exiting the debug-exception handler, +# software can set DebugCtlMSR.LBR to 1 to re-enable the recording mechanism. +# +############################################################################### + + LastBranchToIP = 0x1DC + LastBranchFromIP = 0x1DB + LastExceptionToIP = 0x1DE + LastExceptionFromIP = 0x1DD + +#------------------------------------------------------------------------------ + + @classmethod + def clear_bp(cls, ctx, register): + """ + Clears a hardware breakpoint. + + @see: find_slot, set_bp + + @type ctx: dict( str S{->} int ) + @param ctx: Thread context dictionary. + + @type register: int + @param register: Slot (debug register) for hardware breakpoint. + """ + ctx['Dr7'] &= cls.clearMask[register] + ctx['Dr%d' % register] = 0 + + @classmethod + def set_bp(cls, ctx, register, address, trigger, watch): + """ + Sets a hardware breakpoint. + + @see: clear_bp, find_slot + + @type ctx: dict( str S{->} int ) + @param ctx: Thread context dictionary. + + @type register: int + @param register: Slot (debug register). + + @type address: int + @param address: Memory address. + + @type trigger: int + @param trigger: Trigger flag. See L{HardwareBreakpoint.validTriggers}. + + @type watch: int + @param watch: Watch flag. See L{HardwareBreakpoint.validWatchSizes}. + """ + Dr7 = ctx['Dr7'] + Dr7 |= cls.enableMask[register] + orMask, andMask = cls.triggerMask[register][trigger] + Dr7 &= andMask + Dr7 |= orMask + orMask, andMask = cls.watchMask[register][watch] + Dr7 &= andMask + Dr7 |= orMask + ctx['Dr7'] = Dr7 + ctx['Dr%d' % register] = address + + @classmethod + def find_slot(cls, ctx): + """ + Finds an empty slot to set a hardware breakpoint. + + @see: clear_bp, set_bp + + @type ctx: dict( str S{->} int ) + @param ctx: Thread context dictionary. + + @rtype: int + @return: Slot (debug register) for hardware breakpoint. + """ + Dr7 = ctx['Dr7'] + slot = 0 + for m in cls.enableMask: + if (Dr7 & m) == 0: + return slot + slot += 1 + return None diff --git a/pydevd_attach_to_process/winappdbg/win32/__init__.py b/pydevd_attach_to_process/winappdbg/win32/__init__.py new file mode 100644 index 0000000..b5536c1 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/__init__.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Debugging API wrappers in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32 import defines +from winappdbg.win32 import kernel32 +from winappdbg.win32 import user32 +from winappdbg.win32 import advapi32 +from winappdbg.win32 import wtsapi32 +from winappdbg.win32 import shell32 +from winappdbg.win32 import shlwapi +from winappdbg.win32 import psapi +from winappdbg.win32 import dbghelp +from winappdbg.win32 import ntdll + +from winappdbg.win32.defines import * +from winappdbg.win32.kernel32 import * +from winappdbg.win32.user32 import * +from winappdbg.win32.advapi32 import * +from winappdbg.win32.wtsapi32 import * +from winappdbg.win32.shell32 import * +from winappdbg.win32.shlwapi import * +from winappdbg.win32.psapi import * +from winappdbg.win32.dbghelp import * +from winappdbg.win32.ntdll import * + +# This calculates the list of exported symbols. +_all = set() +_all.update(defines._all) +_all.update(kernel32._all) +_all.update(user32._all) +_all.update(advapi32._all) +_all.update(wtsapi32._all) +_all.update(shell32._all) +_all.update(shlwapi._all) +_all.update(psapi._all) +_all.update(dbghelp._all) +_all.update(ntdll._all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() diff --git a/pydevd_attach_to_process/winappdbg/win32/advapi32.py b/pydevd_attach_to_process/winappdbg/win32/advapi32.py new file mode 100644 index 0000000..4e49889 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/advapi32.py @@ -0,0 +1,3209 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for advapi32.dll in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.kernel32 import * + +# XXX TODO +# + add transacted registry operations + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- Constants ---------------------------------------------------------------- + +# Privilege constants +SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" +SE_AUDIT_NAME = "SeAuditPrivilege" +SE_BACKUP_NAME = "SeBackupPrivilege" +SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" +SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege" +SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" +SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" +SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege" +SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" +SE_DEBUG_NAME = "SeDebugPrivilege" +SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege" +SE_IMPERSONATE_NAME = "SeImpersonatePrivilege" +SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" +SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" +SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege" +SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" +SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" +SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" +SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege" +SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" +SE_RELABEL_NAME = "SeRelabelPrivilege" +SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege" +SE_RESTORE_NAME = "SeRestorePrivilege" +SE_SECURITY_NAME = "SeSecurityPrivilege" +SE_SHUTDOWN_NAME = "SeShutdownPrivilege" +SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege" +SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege" +SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege" +SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege" +SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege" +SE_TCB_NAME = "SeTcbPrivilege" +SE_TIME_ZONE_NAME = "SeTimeZonePrivilege" +SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege" +SE_UNDOCK_NAME = "SeUndockPrivilege" +SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege" + +SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001 +SE_PRIVILEGE_ENABLED = 0x00000002 +SE_PRIVILEGE_REMOVED = 0x00000004 +SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000 + +TOKEN_ADJUST_PRIVILEGES = 0x00000020 + +LOGON_WITH_PROFILE = 0x00000001 +LOGON_NETCREDENTIALS_ONLY = 0x00000002 + +# Token access rights +TOKEN_ASSIGN_PRIMARY = 0x0001 +TOKEN_DUPLICATE = 0x0002 +TOKEN_IMPERSONATE = 0x0004 +TOKEN_QUERY = 0x0008 +TOKEN_QUERY_SOURCE = 0x0010 +TOKEN_ADJUST_PRIVILEGES = 0x0020 +TOKEN_ADJUST_GROUPS = 0x0040 +TOKEN_ADJUST_DEFAULT = 0x0080 +TOKEN_ADJUST_SESSIONID = 0x0100 +TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY) +TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | + TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | + TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | + TOKEN_ADJUST_SESSIONID) + +# Predefined HKEY values +HKEY_CLASSES_ROOT = 0x80000000 +HKEY_CURRENT_USER = 0x80000001 +HKEY_LOCAL_MACHINE = 0x80000002 +HKEY_USERS = 0x80000003 +HKEY_PERFORMANCE_DATA = 0x80000004 +HKEY_CURRENT_CONFIG = 0x80000005 + +# Registry access rights +KEY_ALL_ACCESS = 0xF003F +KEY_CREATE_LINK = 0x0020 +KEY_CREATE_SUB_KEY = 0x0004 +KEY_ENUMERATE_SUB_KEYS = 0x0008 +KEY_EXECUTE = 0x20019 +KEY_NOTIFY = 0x0010 +KEY_QUERY_VALUE = 0x0001 +KEY_READ = 0x20019 +KEY_SET_VALUE = 0x0002 +KEY_WOW64_32KEY = 0x0200 +KEY_WOW64_64KEY = 0x0100 +KEY_WRITE = 0x20006 + +# Registry value types +REG_NONE = 0 +REG_SZ = 1 +REG_EXPAND_SZ = 2 +REG_BINARY = 3 +REG_DWORD = 4 +REG_DWORD_LITTLE_ENDIAN = REG_DWORD +REG_DWORD_BIG_ENDIAN = 5 +REG_LINK = 6 +REG_MULTI_SZ = 7 +REG_RESOURCE_LIST = 8 +REG_FULL_RESOURCE_DESCRIPTOR = 9 +REG_RESOURCE_REQUIREMENTS_LIST = 10 +REG_QWORD = 11 +REG_QWORD_LITTLE_ENDIAN = REG_QWORD + +#--- TOKEN_PRIVILEGE structure ------------------------------------------------ + +# typedef struct _LUID { +# DWORD LowPart; +# LONG HighPart; +# } LUID, +# *PLUID; +class LUID(Structure): + _fields_ = [ + ("LowPart", DWORD), + ("HighPart", LONG), + ] + +PLUID = POINTER(LUID) + +# typedef struct _LUID_AND_ATTRIBUTES { +# LUID Luid; +# DWORD Attributes; +# } LUID_AND_ATTRIBUTES, +# *PLUID_AND_ATTRIBUTES; +class LUID_AND_ATTRIBUTES(Structure): + _fields_ = [ + ("Luid", LUID), + ("Attributes", DWORD), + ] + +# typedef struct _TOKEN_PRIVILEGES { +# DWORD PrivilegeCount; +# LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; +# } TOKEN_PRIVILEGES, +# *PTOKEN_PRIVILEGES; +class TOKEN_PRIVILEGES(Structure): + _fields_ = [ + ("PrivilegeCount", DWORD), +## ("Privileges", LUID_AND_ATTRIBUTES * ANYSIZE_ARRAY), + ("Privileges", LUID_AND_ATTRIBUTES), + ] + # See comments on AdjustTokenPrivileges about this structure + +PTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES) + +#--- GetTokenInformation enums and structures --------------------------------- + +# typedef enum _TOKEN_INFORMATION_CLASS { +# TokenUser = 1, +# TokenGroups, +# TokenPrivileges, +# TokenOwner, +# TokenPrimaryGroup, +# TokenDefaultDacl, +# TokenSource, +# TokenType, +# TokenImpersonationLevel, +# TokenStatistics, +# TokenRestrictedSids, +# TokenSessionId, +# TokenGroupsAndPrivileges, +# TokenSessionReference, +# TokenSandBoxInert, +# TokenAuditPolicy, +# TokenOrigin, +# TokenElevationType, +# TokenLinkedToken, +# TokenElevation, +# TokenHasRestrictions, +# TokenAccessInformation, +# TokenVirtualizationAllowed, +# TokenVirtualizationEnabled, +# TokenIntegrityLevel, +# TokenUIAccess, +# TokenMandatoryPolicy, +# TokenLogonSid, +# TokenIsAppContainer, +# TokenCapabilities, +# TokenAppContainerSid, +# TokenAppContainerNumber, +# TokenUserClaimAttributes, +# TokenDeviceClaimAttributes, +# TokenRestrictedUserClaimAttributes, +# TokenRestrictedDeviceClaimAttributes, +# TokenDeviceGroups, +# TokenRestrictedDeviceGroups, +# TokenSecurityAttributes, +# TokenIsRestricted, +# MaxTokenInfoClass +# } TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS; + +TOKEN_INFORMATION_CLASS = ctypes.c_int + +TokenUser = 1 +TokenGroups = 2 +TokenPrivileges = 3 +TokenOwner = 4 +TokenPrimaryGroup = 5 +TokenDefaultDacl = 6 +TokenSource = 7 +TokenType = 8 +TokenImpersonationLevel = 9 +TokenStatistics = 10 +TokenRestrictedSids = 11 +TokenSessionId = 12 +TokenGroupsAndPrivileges = 13 +TokenSessionReference = 14 +TokenSandBoxInert = 15 +TokenAuditPolicy = 16 +TokenOrigin = 17 +TokenElevationType = 18 +TokenLinkedToken = 19 +TokenElevation = 20 +TokenHasRestrictions = 21 +TokenAccessInformation = 22 +TokenVirtualizationAllowed = 23 +TokenVirtualizationEnabled = 24 +TokenIntegrityLevel = 25 +TokenUIAccess = 26 +TokenMandatoryPolicy = 27 +TokenLogonSid = 28 +TokenIsAppContainer = 29 +TokenCapabilities = 30 +TokenAppContainerSid = 31 +TokenAppContainerNumber = 32 +TokenUserClaimAttributes = 33 +TokenDeviceClaimAttributes = 34 +TokenRestrictedUserClaimAttributes = 35 +TokenRestrictedDeviceClaimAttributes = 36 +TokenDeviceGroups = 37 +TokenRestrictedDeviceGroups = 38 +TokenSecurityAttributes = 39 +TokenIsRestricted = 40 +MaxTokenInfoClass = 41 + +# typedef enum tagTOKEN_TYPE { +# TokenPrimary = 1, +# TokenImpersonation +# } TOKEN_TYPE, *PTOKEN_TYPE; + +TOKEN_TYPE = ctypes.c_int +PTOKEN_TYPE = POINTER(TOKEN_TYPE) + +TokenPrimary = 1 +TokenImpersonation = 2 + +# typedef enum { +# TokenElevationTypeDefault = 1, +# TokenElevationTypeFull, +# TokenElevationTypeLimited +# } TOKEN_ELEVATION_TYPE , *PTOKEN_ELEVATION_TYPE; + +TokenElevationTypeDefault = 1 +TokenElevationTypeFull = 2 +TokenElevationTypeLimited = 3 + +TOKEN_ELEVATION_TYPE = ctypes.c_int +PTOKEN_ELEVATION_TYPE = POINTER(TOKEN_ELEVATION_TYPE) + +# typedef enum _SECURITY_IMPERSONATION_LEVEL { +# SecurityAnonymous, +# SecurityIdentification, +# SecurityImpersonation, +# SecurityDelegation +# } SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL; + +SecurityAnonymous = 0 +SecurityIdentification = 1 +SecurityImpersonation = 2 +SecurityDelegation = 3 + +SECURITY_IMPERSONATION_LEVEL = ctypes.c_int +PSECURITY_IMPERSONATION_LEVEL = POINTER(SECURITY_IMPERSONATION_LEVEL) + +# typedef struct _SID_AND_ATTRIBUTES { +# PSID Sid; +# DWORD Attributes; +# } SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES; +class SID_AND_ATTRIBUTES(Structure): + _fields_ = [ + ("Sid", PSID), + ("Attributes", DWORD), + ] +PSID_AND_ATTRIBUTES = POINTER(SID_AND_ATTRIBUTES) + +# typedef struct _TOKEN_USER { +# SID_AND_ATTRIBUTES User; +# } TOKEN_USER, *PTOKEN_USER; +class TOKEN_USER(Structure): + _fields_ = [ + ("User", SID_AND_ATTRIBUTES), + ] +PTOKEN_USER = POINTER(TOKEN_USER) + +# typedef struct _TOKEN_MANDATORY_LABEL { +# SID_AND_ATTRIBUTES Label; +# } TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL; +class TOKEN_MANDATORY_LABEL(Structure): + _fields_ = [ + ("Label", SID_AND_ATTRIBUTES), + ] +PTOKEN_MANDATORY_LABEL = POINTER(TOKEN_MANDATORY_LABEL) + +# typedef struct _TOKEN_OWNER { +# PSID Owner; +# } TOKEN_OWNER, *PTOKEN_OWNER; +class TOKEN_OWNER(Structure): + _fields_ = [ + ("Owner", PSID), + ] +PTOKEN_OWNER = POINTER(TOKEN_OWNER) + +# typedef struct _TOKEN_PRIMARY_GROUP { +# PSID PrimaryGroup; +# } TOKEN_PRIMARY_GROUP, *PTOKEN_PRIMARY_GROUP; +class TOKEN_PRIMARY_GROUP(Structure): + _fields_ = [ + ("PrimaryGroup", PSID), + ] +PTOKEN_PRIMARY_GROUP = POINTER(TOKEN_PRIMARY_GROUP) + +# typedef struct _TOKEN_APPCONTAINER_INFORMATION { +# PSID TokenAppContainer; +# } TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION; +class TOKEN_APPCONTAINER_INFORMATION(Structure): + _fields_ = [ + ("TokenAppContainer", PSID), + ] +PTOKEN_APPCONTAINER_INFORMATION = POINTER(TOKEN_APPCONTAINER_INFORMATION) + +# typedef struct _TOKEN_ORIGIN { +# LUID OriginatingLogonSession; +# } TOKEN_ORIGIN, *PTOKEN_ORIGIN; +class TOKEN_ORIGIN(Structure): + _fields_ = [ + ("OriginatingLogonSession", LUID), + ] +PTOKEN_ORIGIN = POINTER(TOKEN_ORIGIN) + +# typedef struct _TOKEN_LINKED_TOKEN { +# HANDLE LinkedToken; +# } TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN; +class TOKEN_LINKED_TOKEN(Structure): + _fields_ = [ + ("LinkedToken", HANDLE), + ] +PTOKEN_LINKED_TOKEN = POINTER(TOKEN_LINKED_TOKEN) + +# typedef struct _TOKEN_STATISTICS { +# LUID TokenId; +# LUID AuthenticationId; +# LARGE_INTEGER ExpirationTime; +# TOKEN_TYPE TokenType; +# SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; +# DWORD DynamicCharged; +# DWORD DynamicAvailable; +# DWORD GroupCount; +# DWORD PrivilegeCount; +# LUID ModifiedId; +# } TOKEN_STATISTICS, *PTOKEN_STATISTICS; +class TOKEN_STATISTICS(Structure): + _fields_ = [ + ("TokenId", LUID), + ("AuthenticationId", LUID), + ("ExpirationTime", LONGLONG), # LARGE_INTEGER + ("TokenType", TOKEN_TYPE), + ("ImpersonationLevel", SECURITY_IMPERSONATION_LEVEL), + ("DynamicCharged", DWORD), + ("DynamicAvailable", DWORD), + ("GroupCount", DWORD), + ("PrivilegeCount", DWORD), + ("ModifiedId", LUID), + ] +PTOKEN_STATISTICS = POINTER(TOKEN_STATISTICS) + +#--- SID_NAME_USE enum -------------------------------------------------------- + +# typedef enum _SID_NAME_USE { +# SidTypeUser = 1, +# SidTypeGroup, +# SidTypeDomain, +# SidTypeAlias, +# SidTypeWellKnownGroup, +# SidTypeDeletedAccount, +# SidTypeInvalid, +# SidTypeUnknown, +# SidTypeComputer, +# SidTypeLabel +# } SID_NAME_USE, *PSID_NAME_USE; + +SidTypeUser = 1 +SidTypeGroup = 2 +SidTypeDomain = 3 +SidTypeAlias = 4 +SidTypeWellKnownGroup = 5 +SidTypeDeletedAccount = 6 +SidTypeInvalid = 7 +SidTypeUnknown = 8 +SidTypeComputer = 9 +SidTypeLabel = 10 + +#--- WAITCHAIN_NODE_INFO structure and types ---------------------------------- + +WCT_MAX_NODE_COUNT = 16 +WCT_OBJNAME_LENGTH = 128 +WCT_ASYNC_OPEN_FLAG = 1 +WCTP_OPEN_ALL_FLAGS = WCT_ASYNC_OPEN_FLAG +WCT_OUT_OF_PROC_FLAG = 1 +WCT_OUT_OF_PROC_COM_FLAG = 2 +WCT_OUT_OF_PROC_CS_FLAG = 4 +WCTP_GETINFO_ALL_FLAGS = WCT_OUT_OF_PROC_FLAG | WCT_OUT_OF_PROC_COM_FLAG | WCT_OUT_OF_PROC_CS_FLAG + +HWCT = LPVOID + +# typedef enum _WCT_OBJECT_TYPE +# { +# WctCriticalSectionType = 1, +# WctSendMessageType, +# WctMutexType, +# WctAlpcType, +# WctComType, +# WctThreadWaitType, +# WctProcessWaitType, +# WctThreadType, +# WctComActivationType, +# WctUnknownType, +# WctMaxType +# } WCT_OBJECT_TYPE; + +WCT_OBJECT_TYPE = DWORD + +WctCriticalSectionType = 1 +WctSendMessageType = 2 +WctMutexType = 3 +WctAlpcType = 4 +WctComType = 5 +WctThreadWaitType = 6 +WctProcessWaitType = 7 +WctThreadType = 8 +WctComActivationType = 9 +WctUnknownType = 10 +WctMaxType = 11 + +# typedef enum _WCT_OBJECT_STATUS +# { +# WctStatusNoAccess = 1, // ACCESS_DENIED for this object +# WctStatusRunning, // Thread status +# WctStatusBlocked, // Thread status +# WctStatusPidOnly, // Thread status +# WctStatusPidOnlyRpcss, // Thread status +# WctStatusOwned, // Dispatcher object status +# WctStatusNotOwned, // Dispatcher object status +# WctStatusAbandoned, // Dispatcher object status +# WctStatusUnknown, // All objects +# WctStatusError, // All objects +# WctStatusMax +# } WCT_OBJECT_STATUS; + +WCT_OBJECT_STATUS = DWORD + +WctStatusNoAccess = 1 # ACCESS_DENIED for this object +WctStatusRunning = 2 # Thread status +WctStatusBlocked = 3 # Thread status +WctStatusPidOnly = 4 # Thread status +WctStatusPidOnlyRpcss = 5 # Thread status +WctStatusOwned = 6 # Dispatcher object status +WctStatusNotOwned = 7 # Dispatcher object status +WctStatusAbandoned = 8 # Dispatcher object status +WctStatusUnknown = 9 # All objects +WctStatusError = 10 # All objects +WctStatusMax = 11 + +# typedef struct _WAITCHAIN_NODE_INFO { +# WCT_OBJECT_TYPE ObjectType; +# WCT_OBJECT_STATUS ObjectStatus; +# union { +# struct { +# WCHAR ObjectName[WCT_OBJNAME_LENGTH]; +# LARGE_INTEGER Timeout; +# BOOL Alertable; +# } LockObject; +# struct { +# DWORD ProcessId; +# DWORD ThreadId; +# DWORD WaitTime; +# DWORD ContextSwitches; +# } ThreadObject; +# } ; +# }WAITCHAIN_NODE_INFO, *PWAITCHAIN_NODE_INFO; + +class _WAITCHAIN_NODE_INFO_STRUCT_1(Structure): + _fields_ = [ + ("ObjectName", WCHAR * WCT_OBJNAME_LENGTH), + ("Timeout", LONGLONG), # LARGE_INTEGER + ("Alertable", BOOL), + ] + +class _WAITCHAIN_NODE_INFO_STRUCT_2(Structure): + _fields_ = [ + ("ProcessId", DWORD), + ("ThreadId", DWORD), + ("WaitTime", DWORD), + ("ContextSwitches", DWORD), + ] + +class _WAITCHAIN_NODE_INFO_UNION(Union): + _fields_ = [ + ("LockObject", _WAITCHAIN_NODE_INFO_STRUCT_1), + ("ThreadObject", _WAITCHAIN_NODE_INFO_STRUCT_2), + ] + +class WAITCHAIN_NODE_INFO(Structure): + _fields_ = [ + ("ObjectType", WCT_OBJECT_TYPE), + ("ObjectStatus", WCT_OBJECT_STATUS), + ("u", _WAITCHAIN_NODE_INFO_UNION), + ] + +PWAITCHAIN_NODE_INFO = POINTER(WAITCHAIN_NODE_INFO) + +class WaitChainNodeInfo (object): + """ + Represents a node in the wait chain. + + It's a wrapper on the L{WAITCHAIN_NODE_INFO} structure. + + The following members are defined only + if the node is of L{WctThreadType} type: + - C{ProcessId} + - C{ThreadId} + - C{WaitTime} + - C{ContextSwitches} + + @see: L{GetThreadWaitChain} + + @type ObjectName: unicode + @ivar ObjectName: Object name. May be an empty string. + + @type ObjectType: int + @ivar ObjectType: Object type. + Should be one of the following values: + - L{WctCriticalSectionType} + - L{WctSendMessageType} + - L{WctMutexType} + - L{WctAlpcType} + - L{WctComType} + - L{WctThreadWaitType} + - L{WctProcessWaitType} + - L{WctThreadType} + - L{WctComActivationType} + - L{WctUnknownType} + + @type ObjectStatus: int + @ivar ObjectStatus: Wait status. + Should be one of the following values: + - L{WctStatusNoAccess} I{(ACCESS_DENIED for this object)} + - L{WctStatusRunning} I{(Thread status)} + - L{WctStatusBlocked} I{(Thread status)} + - L{WctStatusPidOnly} I{(Thread status)} + - L{WctStatusPidOnlyRpcss} I{(Thread status)} + - L{WctStatusOwned} I{(Dispatcher object status)} + - L{WctStatusNotOwned} I{(Dispatcher object status)} + - L{WctStatusAbandoned} I{(Dispatcher object status)} + - L{WctStatusUnknown} I{(All objects)} + - L{WctStatusError} I{(All objects)} + + @type ProcessId: int + @ivar ProcessId: Process global ID. + + @type ThreadId: int + @ivar ThreadId: Thread global ID. + + @type WaitTime: int + @ivar WaitTime: Wait time. + + @type ContextSwitches: int + @ivar ContextSwitches: Number of context switches. + """ + + #@type Timeout: int + #@ivar Timeout: Currently not documented in MSDN. + # + #@type Alertable: bool + #@ivar Alertable: Currently not documented in MSDN. + + # TODO: __repr__ + + def __init__(self, aStructure): + self.ObjectType = aStructure.ObjectType + self.ObjectStatus = aStructure.ObjectStatus + if self.ObjectType == WctThreadType: + self.ProcessId = aStructure.u.ThreadObject.ProcessId + self.ThreadId = aStructure.u.ThreadObject.ThreadId + self.WaitTime = aStructure.u.ThreadObject.WaitTime + self.ContextSwitches = aStructure.u.ThreadObject.ContextSwitches + self.ObjectName = u'' + else: + self.ObjectName = aStructure.u.LockObject.ObjectName.value + #self.Timeout = aStructure.u.LockObject.Timeout + #self.Alertable = bool(aStructure.u.LockObject.Alertable) + +class ThreadWaitChainSessionHandle (Handle): + """ + Thread wait chain session handle. + + Returned by L{OpenThreadWaitChainSession}. + + @see: L{Handle} + """ + + def __init__(self, aHandle = None): + """ + @type aHandle: int + @param aHandle: Win32 handle value. + """ + super(ThreadWaitChainSessionHandle, self).__init__(aHandle, + bOwnership = True) + + def _close(self): + if self.value is None: + raise ValueError("Handle was already closed!") + CloseThreadWaitChainSession(self.value) + + def dup(self): + raise NotImplementedError() + + def wait(self, dwMilliseconds = None): + raise NotImplementedError() + + @property + def inherit(self): + return False + + @property + def protectFromClose(self): + return False + +#--- Privilege dropping ------------------------------------------------------- + +SAFER_LEVEL_HANDLE = HANDLE + +SAFER_SCOPEID_MACHINE = 1 +SAFER_SCOPEID_USER = 2 + +SAFER_LEVEL_OPEN = 1 + +SAFER_LEVELID_DISALLOWED = 0x00000 +SAFER_LEVELID_UNTRUSTED = 0x01000 +SAFER_LEVELID_CONSTRAINED = 0x10000 +SAFER_LEVELID_NORMALUSER = 0x20000 +SAFER_LEVELID_FULLYTRUSTED = 0x40000 + +SAFER_POLICY_INFO_CLASS = DWORD +SaferPolicyLevelList = 1 +SaferPolicyEnableTransparentEnforcement = 2 +SaferPolicyDefaultLevel = 3 +SaferPolicyEvaluateUserScope = 4 +SaferPolicyScopeFlags = 5 + +SAFER_TOKEN_NULL_IF_EQUAL = 1 +SAFER_TOKEN_COMPARE_ONLY = 2 +SAFER_TOKEN_MAKE_INERT = 4 +SAFER_TOKEN_WANT_FLAGS = 8 +SAFER_TOKEN_MASK = 15 + +#--- Service Control Manager types, constants and structures ------------------ + +SC_HANDLE = HANDLE + +SERVICES_ACTIVE_DATABASEW = u"ServicesActive" +SERVICES_FAILED_DATABASEW = u"ServicesFailed" + +SERVICES_ACTIVE_DATABASEA = "ServicesActive" +SERVICES_FAILED_DATABASEA = "ServicesFailed" + +SC_GROUP_IDENTIFIERW = u'+' +SC_GROUP_IDENTIFIERA = '+' + +SERVICE_NO_CHANGE = 0xffffffff + +# enum SC_STATUS_TYPE +SC_STATUS_TYPE = ctypes.c_int +SC_STATUS_PROCESS_INFO = 0 + +# enum SC_ENUM_TYPE +SC_ENUM_TYPE = ctypes.c_int +SC_ENUM_PROCESS_INFO = 0 + +# Access rights +# http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx + +SERVICE_ALL_ACCESS = 0xF01FF +SERVICE_QUERY_CONFIG = 0x0001 +SERVICE_CHANGE_CONFIG = 0x0002 +SERVICE_QUERY_STATUS = 0x0004 +SERVICE_ENUMERATE_DEPENDENTS = 0x0008 +SERVICE_START = 0x0010 +SERVICE_STOP = 0x0020 +SERVICE_PAUSE_CONTINUE = 0x0040 +SERVICE_INTERROGATE = 0x0080 +SERVICE_USER_DEFINED_CONTROL = 0x0100 + +SC_MANAGER_ALL_ACCESS = 0xF003F +SC_MANAGER_CONNECT = 0x0001 +SC_MANAGER_CREATE_SERVICE = 0x0002 +SC_MANAGER_ENUMERATE_SERVICE = 0x0004 +SC_MANAGER_LOCK = 0x0008 +SC_MANAGER_QUERY_LOCK_STATUS = 0x0010 +SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020 + +# CreateService() service start type +SERVICE_BOOT_START = 0x00000000 +SERVICE_SYSTEM_START = 0x00000001 +SERVICE_AUTO_START = 0x00000002 +SERVICE_DEMAND_START = 0x00000003 +SERVICE_DISABLED = 0x00000004 + +# CreateService() error control flags +SERVICE_ERROR_IGNORE = 0x00000000 +SERVICE_ERROR_NORMAL = 0x00000001 +SERVICE_ERROR_SEVERE = 0x00000002 +SERVICE_ERROR_CRITICAL = 0x00000003 + +# EnumServicesStatusEx() service state filters +SERVICE_ACTIVE = 1 +SERVICE_INACTIVE = 2 +SERVICE_STATE_ALL = 3 + +# SERVICE_STATUS_PROCESS.dwServiceType +SERVICE_KERNEL_DRIVER = 0x00000001 +SERVICE_FILE_SYSTEM_DRIVER = 0x00000002 +SERVICE_ADAPTER = 0x00000004 +SERVICE_RECOGNIZER_DRIVER = 0x00000008 +SERVICE_WIN32_OWN_PROCESS = 0x00000010 +SERVICE_WIN32_SHARE_PROCESS = 0x00000020 +SERVICE_INTERACTIVE_PROCESS = 0x00000100 + +# EnumServicesStatusEx() service type filters (in addition to actual types) +SERVICE_DRIVER = 0x0000000B # SERVICE_KERNEL_DRIVER and SERVICE_FILE_SYSTEM_DRIVER +SERVICE_WIN32 = 0x00000030 # SERVICE_WIN32_OWN_PROCESS and SERVICE_WIN32_SHARE_PROCESS + +# SERVICE_STATUS_PROCESS.dwCurrentState +SERVICE_STOPPED = 0x00000001 +SERVICE_START_PENDING = 0x00000002 +SERVICE_STOP_PENDING = 0x00000003 +SERVICE_RUNNING = 0x00000004 +SERVICE_CONTINUE_PENDING = 0x00000005 +SERVICE_PAUSE_PENDING = 0x00000006 +SERVICE_PAUSED = 0x00000007 + +# SERVICE_STATUS_PROCESS.dwControlsAccepted +SERVICE_ACCEPT_STOP = 0x00000001 +SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002 +SERVICE_ACCEPT_SHUTDOWN = 0x00000004 +SERVICE_ACCEPT_PARAMCHANGE = 0x00000008 +SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010 +SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020 +SERVICE_ACCEPT_POWEREVENT = 0x00000040 +SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080 +SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100 + +# SERVICE_STATUS_PROCESS.dwServiceFlags +SERVICE_RUNS_IN_SYSTEM_PROCESS = 0x00000001 + +# Service control flags +SERVICE_CONTROL_STOP = 0x00000001 +SERVICE_CONTROL_PAUSE = 0x00000002 +SERVICE_CONTROL_CONTINUE = 0x00000003 +SERVICE_CONTROL_INTERROGATE = 0x00000004 +SERVICE_CONTROL_SHUTDOWN = 0x00000005 +SERVICE_CONTROL_PARAMCHANGE = 0x00000006 +SERVICE_CONTROL_NETBINDADD = 0x00000007 +SERVICE_CONTROL_NETBINDREMOVE = 0x00000008 +SERVICE_CONTROL_NETBINDENABLE = 0x00000009 +SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A +SERVICE_CONTROL_DEVICEEVENT = 0x0000000B +SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0x0000000C +SERVICE_CONTROL_POWEREVENT = 0x0000000D +SERVICE_CONTROL_SESSIONCHANGE = 0x0000000E + +# Service control accepted bitmasks +SERVICE_ACCEPT_STOP = 0x00000001 +SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002 +SERVICE_ACCEPT_SHUTDOWN = 0x00000004 +SERVICE_ACCEPT_PARAMCHANGE = 0x00000008 +SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010 +SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020 +SERVICE_ACCEPT_POWEREVENT = 0x00000040 +SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080 +SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100 +SERVICE_ACCEPT_TIMECHANGE = 0x00000200 +SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400 +SERVICE_ACCEPT_USERMODEREBOOT = 0x00000800 + +# enum SC_ACTION_TYPE +SC_ACTION_NONE = 0 +SC_ACTION_RESTART = 1 +SC_ACTION_REBOOT = 2 +SC_ACTION_RUN_COMMAND = 3 + +# QueryServiceConfig2 +SERVICE_CONFIG_DESCRIPTION = 1 +SERVICE_CONFIG_FAILURE_ACTIONS = 2 + +# typedef struct _SERVICE_STATUS { +# DWORD dwServiceType; +# DWORD dwCurrentState; +# DWORD dwControlsAccepted; +# DWORD dwWin32ExitCode; +# DWORD dwServiceSpecificExitCode; +# DWORD dwCheckPoint; +# DWORD dwWaitHint; +# } SERVICE_STATUS, *LPSERVICE_STATUS; +class SERVICE_STATUS(Structure): + _fields_ = [ + ("dwServiceType", DWORD), + ("dwCurrentState", DWORD), + ("dwControlsAccepted", DWORD), + ("dwWin32ExitCode", DWORD), + ("dwServiceSpecificExitCode", DWORD), + ("dwCheckPoint", DWORD), + ("dwWaitHint", DWORD), + ] +LPSERVICE_STATUS = POINTER(SERVICE_STATUS) + +# typedef struct _SERVICE_STATUS_PROCESS { +# DWORD dwServiceType; +# DWORD dwCurrentState; +# DWORD dwControlsAccepted; +# DWORD dwWin32ExitCode; +# DWORD dwServiceSpecificExitCode; +# DWORD dwCheckPoint; +# DWORD dwWaitHint; +# DWORD dwProcessId; +# DWORD dwServiceFlags; +# } SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS; +class SERVICE_STATUS_PROCESS(Structure): + _fields_ = SERVICE_STATUS._fields_ + [ + ("dwProcessId", DWORD), + ("dwServiceFlags", DWORD), + ] +LPSERVICE_STATUS_PROCESS = POINTER(SERVICE_STATUS_PROCESS) + +# typedef struct _ENUM_SERVICE_STATUS { +# LPTSTR lpServiceName; +# LPTSTR lpDisplayName; +# SERVICE_STATUS ServiceStatus; +# } ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS; +class ENUM_SERVICE_STATUSA(Structure): + _fields_ = [ + ("lpServiceName", LPSTR), + ("lpDisplayName", LPSTR), + ("ServiceStatus", SERVICE_STATUS), + ] +class ENUM_SERVICE_STATUSW(Structure): + _fields_ = [ + ("lpServiceName", LPWSTR), + ("lpDisplayName", LPWSTR), + ("ServiceStatus", SERVICE_STATUS), + ] +LPENUM_SERVICE_STATUSA = POINTER(ENUM_SERVICE_STATUSA) +LPENUM_SERVICE_STATUSW = POINTER(ENUM_SERVICE_STATUSW) + +# typedef struct _ENUM_SERVICE_STATUS_PROCESS { +# LPTSTR lpServiceName; +# LPTSTR lpDisplayName; +# SERVICE_STATUS_PROCESS ServiceStatusProcess; +# } ENUM_SERVICE_STATUS_PROCESS, *LPENUM_SERVICE_STATUS_PROCESS; +class ENUM_SERVICE_STATUS_PROCESSA(Structure): + _fields_ = [ + ("lpServiceName", LPSTR), + ("lpDisplayName", LPSTR), + ("ServiceStatusProcess", SERVICE_STATUS_PROCESS), + ] +class ENUM_SERVICE_STATUS_PROCESSW(Structure): + _fields_ = [ + ("lpServiceName", LPWSTR), + ("lpDisplayName", LPWSTR), + ("ServiceStatusProcess", SERVICE_STATUS_PROCESS), + ] +LPENUM_SERVICE_STATUS_PROCESSA = POINTER(ENUM_SERVICE_STATUS_PROCESSA) +LPENUM_SERVICE_STATUS_PROCESSW = POINTER(ENUM_SERVICE_STATUS_PROCESSW) + +class ServiceStatus(object): + """ + Wrapper for the L{SERVICE_STATUS} structure. + """ + + def __init__(self, raw): + """ + @type raw: L{SERVICE_STATUS} + @param raw: Raw structure for this service status data. + """ + self.ServiceType = raw.dwServiceType + self.CurrentState = raw.dwCurrentState + self.ControlsAccepted = raw.dwControlsAccepted + self.Win32ExitCode = raw.dwWin32ExitCode + self.ServiceSpecificExitCode = raw.dwServiceSpecificExitCode + self.CheckPoint = raw.dwCheckPoint + self.WaitHint = raw.dwWaitHint + +class ServiceStatusProcess(object): + """ + Wrapper for the L{SERVICE_STATUS_PROCESS} structure. + """ + + def __init__(self, raw): + """ + @type raw: L{SERVICE_STATUS_PROCESS} + @param raw: Raw structure for this service status data. + """ + self.ServiceType = raw.dwServiceType + self.CurrentState = raw.dwCurrentState + self.ControlsAccepted = raw.dwControlsAccepted + self.Win32ExitCode = raw.dwWin32ExitCode + self.ServiceSpecificExitCode = raw.dwServiceSpecificExitCode + self.CheckPoint = raw.dwCheckPoint + self.WaitHint = raw.dwWaitHint + self.ProcessId = raw.dwProcessId + self.ServiceFlags = raw.dwServiceFlags + +class ServiceStatusEntry(object): + """ + Service status entry returned by L{EnumServicesStatus}. + """ + + def __init__(self, raw): + """ + @type raw: L{ENUM_SERVICE_STATUSA} or L{ENUM_SERVICE_STATUSW} + @param raw: Raw structure for this service status entry. + """ + self.ServiceName = raw.lpServiceName + self.DisplayName = raw.lpDisplayName + self.ServiceType = raw.ServiceStatus.dwServiceType + self.CurrentState = raw.ServiceStatus.dwCurrentState + self.ControlsAccepted = raw.ServiceStatus.dwControlsAccepted + self.Win32ExitCode = raw.ServiceStatus.dwWin32ExitCode + self.ServiceSpecificExitCode = raw.ServiceStatus.dwServiceSpecificExitCode + self.CheckPoint = raw.ServiceStatus.dwCheckPoint + self.WaitHint = raw.ServiceStatus.dwWaitHint + + def __str__(self): + output = [] + if self.ServiceType & SERVICE_INTERACTIVE_PROCESS: + output.append("Interactive service") + else: + output.append("Service") + if self.DisplayName: + output.append("\"%s\" (%s)" % (self.DisplayName, self.ServiceName)) + else: + output.append("\"%s\"" % self.ServiceName) + if self.CurrentState == SERVICE_CONTINUE_PENDING: + output.append("is about to continue.") + elif self.CurrentState == SERVICE_PAUSE_PENDING: + output.append("is pausing.") + elif self.CurrentState == SERVICE_PAUSED: + output.append("is paused.") + elif self.CurrentState == SERVICE_RUNNING: + output.append("is running.") + elif self.CurrentState == SERVICE_START_PENDING: + output.append("is starting.") + elif self.CurrentState == SERVICE_STOP_PENDING: + output.append("is stopping.") + elif self.CurrentState == SERVICE_STOPPED: + output.append("is stopped.") + return " ".join(output) + +class ServiceStatusProcessEntry(object): + """ + Service status entry returned by L{EnumServicesStatusEx}. + """ + + def __init__(self, raw): + """ + @type raw: L{ENUM_SERVICE_STATUS_PROCESSA} or L{ENUM_SERVICE_STATUS_PROCESSW} + @param raw: Raw structure for this service status entry. + """ + self.ServiceName = raw.lpServiceName + self.DisplayName = raw.lpDisplayName + self.ServiceType = raw.ServiceStatusProcess.dwServiceType + self.CurrentState = raw.ServiceStatusProcess.dwCurrentState + self.ControlsAccepted = raw.ServiceStatusProcess.dwControlsAccepted + self.Win32ExitCode = raw.ServiceStatusProcess.dwWin32ExitCode + self.ServiceSpecificExitCode = raw.ServiceStatusProcess.dwServiceSpecificExitCode + self.CheckPoint = raw.ServiceStatusProcess.dwCheckPoint + self.WaitHint = raw.ServiceStatusProcess.dwWaitHint + self.ProcessId = raw.ServiceStatusProcess.dwProcessId + self.ServiceFlags = raw.ServiceStatusProcess.dwServiceFlags + + def __str__(self): + output = [] + if self.ServiceType & SERVICE_INTERACTIVE_PROCESS: + output.append("Interactive service ") + else: + output.append("Service ") + if self.DisplayName: + output.append("\"%s\" (%s)" % (self.DisplayName, self.ServiceName)) + else: + output.append("\"%s\"" % self.ServiceName) + if self.CurrentState == SERVICE_CONTINUE_PENDING: + output.append(" is about to continue") + elif self.CurrentState == SERVICE_PAUSE_PENDING: + output.append(" is pausing") + elif self.CurrentState == SERVICE_PAUSED: + output.append(" is paused") + elif self.CurrentState == SERVICE_RUNNING: + output.append(" is running") + elif self.CurrentState == SERVICE_START_PENDING: + output.append(" is starting") + elif self.CurrentState == SERVICE_STOP_PENDING: + output.append(" is stopping") + elif self.CurrentState == SERVICE_STOPPED: + output.append(" is stopped") + if self.ProcessId: + output.append(" at process %d" % self.ProcessId) + output.append(".") + return "".join(output) + +#--- Handle wrappers ---------------------------------------------------------- + +# XXX maybe add functions related to the tokens here? +class TokenHandle (Handle): + """ + Access token handle. + + @see: L{Handle} + """ + pass + +class RegistryKeyHandle (UserModeHandle): + """ + Registry key handle. + """ + + _TYPE = HKEY + + def _close(self): + RegCloseKey(self.value) + +class SaferLevelHandle (UserModeHandle): + """ + Safer level handle. + + @see: U{http://msdn.microsoft.com/en-us/library/ms722425(VS.85).aspx} + """ + + _TYPE = SAFER_LEVEL_HANDLE + + def _close(self): + SaferCloseLevel(self.value) + +class ServiceHandle (UserModeHandle): + """ + Service handle. + + @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684330(v=vs.85).aspx} + """ + + _TYPE = SC_HANDLE + + def _close(self): + CloseServiceHandle(self.value) + +class ServiceControlManagerHandle (UserModeHandle): + """ + Service Control Manager (SCM) handle. + + @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684323(v=vs.85).aspx} + """ + + _TYPE = SC_HANDLE + + def _close(self): + CloseServiceHandle(self.value) + +#--- advapi32.dll ------------------------------------------------------------- + +# BOOL WINAPI GetUserName( +# __out LPTSTR lpBuffer, +# __inout LPDWORD lpnSize +# ); +def GetUserNameA(): + _GetUserNameA = windll.advapi32.GetUserNameA + _GetUserNameA.argtypes = [LPSTR, LPDWORD] + _GetUserNameA.restype = bool + + nSize = DWORD(0) + _GetUserNameA(None, byref(nSize)) + error = GetLastError() + if error != ERROR_INSUFFICIENT_BUFFER: + raise ctypes.WinError(error) + lpBuffer = ctypes.create_string_buffer('', nSize.value + 1) + success = _GetUserNameA(lpBuffer, byref(nSize)) + if not success: + raise ctypes.WinError() + return lpBuffer.value + +def GetUserNameW(): + _GetUserNameW = windll.advapi32.GetUserNameW + _GetUserNameW.argtypes = [LPWSTR, LPDWORD] + _GetUserNameW.restype = bool + + nSize = DWORD(0) + _GetUserNameW(None, byref(nSize)) + error = GetLastError() + if error != ERROR_INSUFFICIENT_BUFFER: + raise ctypes.WinError(error) + lpBuffer = ctypes.create_unicode_buffer(u'', nSize.value + 1) + success = _GetUserNameW(lpBuffer, byref(nSize)) + if not success: + raise ctypes.WinError() + return lpBuffer.value + +GetUserName = DefaultStringType(GetUserNameA, GetUserNameW) + +# BOOL WINAPI LookupAccountName( +# __in_opt LPCTSTR lpSystemName, +# __in LPCTSTR lpAccountName, +# __out_opt PSID Sid, +# __inout LPDWORD cbSid, +# __out_opt LPTSTR ReferencedDomainName, +# __inout LPDWORD cchReferencedDomainName, +# __out PSID_NAME_USE peUse +# ); + +# XXX TO DO + +# BOOL WINAPI LookupAccountSid( +# __in_opt LPCTSTR lpSystemName, +# __in PSID lpSid, +# __out_opt LPTSTR lpName, +# __inout LPDWORD cchName, +# __out_opt LPTSTR lpReferencedDomainName, +# __inout LPDWORD cchReferencedDomainName, +# __out PSID_NAME_USE peUse +# ); +def LookupAccountSidA(lpSystemName, lpSid): + _LookupAccountSidA = windll.advapi32.LookupAccountSidA + _LookupAccountSidA.argtypes = [LPSTR, PSID, LPSTR, LPDWORD, LPSTR, LPDWORD, LPDWORD] + _LookupAccountSidA.restype = bool + + cchName = DWORD(0) + cchReferencedDomainName = DWORD(0) + peUse = DWORD(0) + _LookupAccountSidA(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName), byref(peUse)) + error = GetLastError() + if error != ERROR_INSUFFICIENT_BUFFER: + raise ctypes.WinError(error) + lpName = ctypes.create_string_buffer('', cchName + 1) + lpReferencedDomainName = ctypes.create_string_buffer('', cchReferencedDomainName + 1) + success = _LookupAccountSidA(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse)) + if not success: + raise ctypes.WinError() + return lpName.value, lpReferencedDomainName.value, peUse.value + +def LookupAccountSidW(lpSystemName, lpSid): + _LookupAccountSidW = windll.advapi32.LookupAccountSidA + _LookupAccountSidW.argtypes = [LPSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPDWORD] + _LookupAccountSidW.restype = bool + + cchName = DWORD(0) + cchReferencedDomainName = DWORD(0) + peUse = DWORD(0) + _LookupAccountSidW(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName), byref(peUse)) + error = GetLastError() + if error != ERROR_INSUFFICIENT_BUFFER: + raise ctypes.WinError(error) + lpName = ctypes.create_unicode_buffer(u'', cchName + 1) + lpReferencedDomainName = ctypes.create_unicode_buffer(u'', cchReferencedDomainName + 1) + success = _LookupAccountSidW(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse)) + if not success: + raise ctypes.WinError() + return lpName.value, lpReferencedDomainName.value, peUse.value + +LookupAccountSid = GuessStringType(LookupAccountSidA, LookupAccountSidW) + +# BOOL ConvertSidToStringSid( +# __in PSID Sid, +# __out LPTSTR *StringSid +# ); +def ConvertSidToStringSidA(Sid): + _ConvertSidToStringSidA = windll.advapi32.ConvertSidToStringSidA + _ConvertSidToStringSidA.argtypes = [PSID, LPSTR] + _ConvertSidToStringSidA.restype = bool + _ConvertSidToStringSidA.errcheck = RaiseIfZero + + pStringSid = LPSTR() + _ConvertSidToStringSidA(Sid, byref(pStringSid)) + try: + StringSid = pStringSid.value + finally: + LocalFree(pStringSid) + return StringSid + +def ConvertSidToStringSidW(Sid): + _ConvertSidToStringSidW = windll.advapi32.ConvertSidToStringSidW + _ConvertSidToStringSidW.argtypes = [PSID, LPWSTR] + _ConvertSidToStringSidW.restype = bool + _ConvertSidToStringSidW.errcheck = RaiseIfZero + + pStringSid = LPWSTR() + _ConvertSidToStringSidW(Sid, byref(pStringSid)) + try: + StringSid = pStringSid.value + finally: + LocalFree(pStringSid) + return StringSid + +ConvertSidToStringSid = DefaultStringType(ConvertSidToStringSidA, ConvertSidToStringSidW) + +# BOOL WINAPI ConvertStringSidToSid( +# __in LPCTSTR StringSid, +# __out PSID *Sid +# ); +def ConvertStringSidToSidA(StringSid): + _ConvertStringSidToSidA = windll.advapi32.ConvertStringSidToSidA + _ConvertStringSidToSidA.argtypes = [LPSTR, PVOID] + _ConvertStringSidToSidA.restype = bool + _ConvertStringSidToSidA.errcheck = RaiseIfZero + + Sid = PVOID() + _ConvertStringSidToSidA(StringSid, ctypes.pointer(Sid)) + return Sid.value + +def ConvertStringSidToSidW(StringSid): + _ConvertStringSidToSidW = windll.advapi32.ConvertStringSidToSidW + _ConvertStringSidToSidW.argtypes = [LPWSTR, PVOID] + _ConvertStringSidToSidW.restype = bool + _ConvertStringSidToSidW.errcheck = RaiseIfZero + + Sid = PVOID() + _ConvertStringSidToSidW(StringSid, ctypes.pointer(Sid)) + return Sid.value + +ConvertStringSidToSid = GuessStringType(ConvertStringSidToSidA, ConvertStringSidToSidW) + +# BOOL WINAPI IsValidSid( +# __in PSID pSid +# ); +def IsValidSid(pSid): + _IsValidSid = windll.advapi32.IsValidSid + _IsValidSid.argtypes = [PSID] + _IsValidSid.restype = bool + return _IsValidSid(pSid) + +# BOOL WINAPI EqualSid( +# __in PSID pSid1, +# __in PSID pSid2 +# ); +def EqualSid(pSid1, pSid2): + _EqualSid = windll.advapi32.EqualSid + _EqualSid.argtypes = [PSID, PSID] + _EqualSid.restype = bool + return _EqualSid(pSid1, pSid2) + +# DWORD WINAPI GetLengthSid( +# __in PSID pSid +# ); +def GetLengthSid(pSid): + _GetLengthSid = windll.advapi32.GetLengthSid + _GetLengthSid.argtypes = [PSID] + _GetLengthSid.restype = DWORD + return _GetLengthSid(pSid) + +# BOOL WINAPI CopySid( +# __in DWORD nDestinationSidLength, +# __out PSID pDestinationSid, +# __in PSID pSourceSid +# ); +def CopySid(pSourceSid): + _CopySid = windll.advapi32.CopySid + _CopySid.argtypes = [DWORD, PVOID, PSID] + _CopySid.restype = bool + _CopySid.errcheck = RaiseIfZero + + nDestinationSidLength = GetLengthSid(pSourceSid) + DestinationSid = ctypes.create_string_buffer('', nDestinationSidLength) + pDestinationSid = ctypes.cast(ctypes.pointer(DestinationSid), PVOID) + _CopySid(nDestinationSidLength, pDestinationSid, pSourceSid) + return ctypes.cast(pDestinationSid, PSID) + +# PVOID WINAPI FreeSid( +# __in PSID pSid +# ); +def FreeSid(pSid): + _FreeSid = windll.advapi32.FreeSid + _FreeSid.argtypes = [PSID] + _FreeSid.restype = PSID + _FreeSid.errcheck = RaiseIfNotZero + _FreeSid(pSid) + +# BOOL WINAPI OpenProcessToken( +# __in HANDLE ProcessHandle, +# __in DWORD DesiredAccess, +# __out PHANDLE TokenHandle +# ); +def OpenProcessToken(ProcessHandle, DesiredAccess = TOKEN_ALL_ACCESS): + _OpenProcessToken = windll.advapi32.OpenProcessToken + _OpenProcessToken.argtypes = [HANDLE, DWORD, PHANDLE] + _OpenProcessToken.restype = bool + _OpenProcessToken.errcheck = RaiseIfZero + + NewTokenHandle = HANDLE(INVALID_HANDLE_VALUE) + _OpenProcessToken(ProcessHandle, DesiredAccess, byref(NewTokenHandle)) + return TokenHandle(NewTokenHandle.value) + +# BOOL WINAPI OpenThreadToken( +# __in HANDLE ThreadHandle, +# __in DWORD DesiredAccess, +# __in BOOL OpenAsSelf, +# __out PHANDLE TokenHandle +# ); +def OpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf = True): + _OpenThreadToken = windll.advapi32.OpenThreadToken + _OpenThreadToken.argtypes = [HANDLE, DWORD, BOOL, PHANDLE] + _OpenThreadToken.restype = bool + _OpenThreadToken.errcheck = RaiseIfZero + + NewTokenHandle = HANDLE(INVALID_HANDLE_VALUE) + _OpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, byref(NewTokenHandle)) + return TokenHandle(NewTokenHandle.value) + +# BOOL WINAPI DuplicateToken( +# _In_ HANDLE ExistingTokenHandle, +# _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, +# _Out_ PHANDLE DuplicateTokenHandle +# ); +def DuplicateToken(ExistingTokenHandle, ImpersonationLevel = SecurityImpersonation): + _DuplicateToken = windll.advapi32.DuplicateToken + _DuplicateToken.argtypes = [HANDLE, SECURITY_IMPERSONATION_LEVEL, PHANDLE] + _DuplicateToken.restype = bool + _DuplicateToken.errcheck = RaiseIfZero + + DuplicateTokenHandle = HANDLE(INVALID_HANDLE_VALUE) + _DuplicateToken(ExistingTokenHandle, ImpersonationLevel, byref(DuplicateTokenHandle)) + return TokenHandle(DuplicateTokenHandle.value) + +# BOOL WINAPI DuplicateTokenEx( +# _In_ HANDLE hExistingToken, +# _In_ DWORD dwDesiredAccess, +# _In_opt_ LPSECURITY_ATTRIBUTES lpTokenAttributes, +# _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, +# _In_ TOKEN_TYPE TokenType, +# _Out_ PHANDLE phNewToken +# ); +def DuplicateTokenEx(hExistingToken, dwDesiredAccess = TOKEN_ALL_ACCESS, lpTokenAttributes = None, ImpersonationLevel = SecurityImpersonation, TokenType = TokenPrimary): + _DuplicateTokenEx = windll.advapi32.DuplicateTokenEx + _DuplicateTokenEx.argtypes = [HANDLE, DWORD, LPSECURITY_ATTRIBUTES, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, PHANDLE] + _DuplicateTokenEx.restype = bool + _DuplicateTokenEx.errcheck = RaiseIfZero + + DuplicateTokenHandle = HANDLE(INVALID_HANDLE_VALUE) + _DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, byref(DuplicateTokenHandle)) + return TokenHandle(DuplicateTokenHandle.value) + +# BOOL WINAPI IsTokenRestricted( +# __in HANDLE TokenHandle +# ); +def IsTokenRestricted(hTokenHandle): + _IsTokenRestricted = windll.advapi32.IsTokenRestricted + _IsTokenRestricted.argtypes = [HANDLE] + _IsTokenRestricted.restype = bool + _IsTokenRestricted.errcheck = RaiseIfNotErrorSuccess + + SetLastError(ERROR_SUCCESS) + return _IsTokenRestricted(hTokenHandle) + +# BOOL WINAPI LookupPrivilegeValue( +# __in_opt LPCTSTR lpSystemName, +# __in LPCTSTR lpName, +# __out PLUID lpLuid +# ); +def LookupPrivilegeValueA(lpSystemName, lpName): + _LookupPrivilegeValueA = windll.advapi32.LookupPrivilegeValueA + _LookupPrivilegeValueA.argtypes = [LPSTR, LPSTR, PLUID] + _LookupPrivilegeValueA.restype = bool + _LookupPrivilegeValueA.errcheck = RaiseIfZero + + lpLuid = LUID() + if not lpSystemName: + lpSystemName = None + _LookupPrivilegeValueA(lpSystemName, lpName, byref(lpLuid)) + return lpLuid + +def LookupPrivilegeValueW(lpSystemName, lpName): + _LookupPrivilegeValueW = windll.advapi32.LookupPrivilegeValueW + _LookupPrivilegeValueW.argtypes = [LPWSTR, LPWSTR, PLUID] + _LookupPrivilegeValueW.restype = bool + _LookupPrivilegeValueW.errcheck = RaiseIfZero + + lpLuid = LUID() + if not lpSystemName: + lpSystemName = None + _LookupPrivilegeValueW(lpSystemName, lpName, byref(lpLuid)) + return lpLuid + +LookupPrivilegeValue = GuessStringType(LookupPrivilegeValueA, LookupPrivilegeValueW) + +# BOOL WINAPI LookupPrivilegeName( +# __in_opt LPCTSTR lpSystemName, +# __in PLUID lpLuid, +# __out_opt LPTSTR lpName, +# __inout LPDWORD cchName +# ); + +def LookupPrivilegeNameA(lpSystemName, lpLuid): + _LookupPrivilegeNameA = windll.advapi32.LookupPrivilegeNameA + _LookupPrivilegeNameA.argtypes = [LPSTR, PLUID, LPSTR, LPDWORD] + _LookupPrivilegeNameA.restype = bool + _LookupPrivilegeNameA.errcheck = RaiseIfZero + + cchName = DWORD(0) + _LookupPrivilegeNameA(lpSystemName, byref(lpLuid), NULL, byref(cchName)) + lpName = ctypes.create_string_buffer("", cchName.value) + _LookupPrivilegeNameA(lpSystemName, byref(lpLuid), byref(lpName), byref(cchName)) + return lpName.value + +def LookupPrivilegeNameW(lpSystemName, lpLuid): + _LookupPrivilegeNameW = windll.advapi32.LookupPrivilegeNameW + _LookupPrivilegeNameW.argtypes = [LPWSTR, PLUID, LPWSTR, LPDWORD] + _LookupPrivilegeNameW.restype = bool + _LookupPrivilegeNameW.errcheck = RaiseIfZero + + cchName = DWORD(0) + _LookupPrivilegeNameW(lpSystemName, byref(lpLuid), NULL, byref(cchName)) + lpName = ctypes.create_unicode_buffer(u"", cchName.value) + _LookupPrivilegeNameW(lpSystemName, byref(lpLuid), byref(lpName), byref(cchName)) + return lpName.value + +LookupPrivilegeName = GuessStringType(LookupPrivilegeNameA, LookupPrivilegeNameW) + +# BOOL WINAPI AdjustTokenPrivileges( +# __in HANDLE TokenHandle, +# __in BOOL DisableAllPrivileges, +# __in_opt PTOKEN_PRIVILEGES NewState, +# __in DWORD BufferLength, +# __out_opt PTOKEN_PRIVILEGES PreviousState, +# __out_opt PDWORD ReturnLength +# ); +def AdjustTokenPrivileges(TokenHandle, NewState = ()): + _AdjustTokenPrivileges = windll.advapi32.AdjustTokenPrivileges + _AdjustTokenPrivileges.argtypes = [HANDLE, BOOL, LPVOID, DWORD, LPVOID, LPVOID] + _AdjustTokenPrivileges.restype = bool + _AdjustTokenPrivileges.errcheck = RaiseIfZero + # + # I don't know how to allocate variable sized structures in ctypes :( + # so this hack will work by using always TOKEN_PRIVILEGES of one element + # and calling the API many times. This also means the PreviousState + # parameter won't be supported yet as it's too much hassle. In a future + # version I look forward to implementing this function correctly. + # + if not NewState: + _AdjustTokenPrivileges(TokenHandle, TRUE, NULL, 0, NULL, NULL) + else: + success = True + for (privilege, enabled) in NewState: + if not isinstance(privilege, LUID): + privilege = LookupPrivilegeValue(NULL, privilege) + if enabled == True: + flags = SE_PRIVILEGE_ENABLED + elif enabled == False: + flags = SE_PRIVILEGE_REMOVED + elif enabled == None: + flags = 0 + else: + flags = enabled + laa = LUID_AND_ATTRIBUTES(privilege, flags) + tp = TOKEN_PRIVILEGES(1, laa) + _AdjustTokenPrivileges(TokenHandle, FALSE, byref(tp), sizeof(tp), NULL, NULL) + +# BOOL WINAPI GetTokenInformation( +# __in HANDLE TokenHandle, +# __in TOKEN_INFORMATION_CLASS TokenInformationClass, +# __out_opt LPVOID TokenInformation, +# __in DWORD TokenInformationLength, +# __out PDWORD ReturnLength +# ); +def GetTokenInformation(hTokenHandle, TokenInformationClass): + if TokenInformationClass <= 0 or TokenInformationClass > MaxTokenInfoClass: + raise ValueError("Invalid value for TokenInformationClass (%i)" % TokenInformationClass) + + # User SID. + if TokenInformationClass == TokenUser: + TokenInformation = TOKEN_USER() + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.User.Sid.value + + # Owner SID. + if TokenInformationClass == TokenOwner: + TokenInformation = TOKEN_OWNER() + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.Owner.value + + # Primary group SID. + if TokenInformationClass == TokenOwner: + TokenInformation = TOKEN_PRIMARY_GROUP() + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.PrimaryGroup.value + + # App container SID. + if TokenInformationClass == TokenAppContainerSid: + TokenInformation = TOKEN_APPCONTAINER_INFORMATION() + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.TokenAppContainer.value + + # Integrity level SID. + if TokenInformationClass == TokenIntegrityLevel: + TokenInformation = TOKEN_MANDATORY_LABEL() + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.Label.Sid.value, TokenInformation.Label.Attributes + + # Logon session LUID. + if TokenInformationClass == TokenOrigin: + TokenInformation = TOKEN_ORIGIN() + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.OriginatingLogonSession + + # Primary or impersonation token. + if TokenInformationClass == TokenType: + TokenInformation = TOKEN_TYPE(0) + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.value + + # Elevated token. + if TokenInformationClass == TokenElevation: + TokenInformation = TOKEN_ELEVATION(0) + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.value + + # Security impersonation level. + if TokenInformationClass == TokenElevation: + TokenInformation = SECURITY_IMPERSONATION_LEVEL(0) + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.value + + # Session ID and other DWORD values. + if TokenInformationClass in (TokenSessionId, TokenAppContainerNumber): + TokenInformation = DWORD(0) + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation.value + + # Various boolean flags. + if TokenInformationClass in (TokenSandBoxInert, TokenHasRestrictions, TokenUIAccess, + TokenVirtualizationAllowed, TokenVirtualizationEnabled): + TokenInformation = DWORD(0) + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return bool(TokenInformation.value) + + # Linked token. + if TokenInformationClass == TokenLinkedToken: + TokenInformation = TOKEN_LINKED_TOKEN(0) + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenHandle(TokenInformation.LinkedToken.value, bOwnership = True) + + # Token statistics. + if TokenInformationClass == TokenStatistics: + TokenInformation = TOKEN_STATISTICS() + _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation) + return TokenInformation # TODO add a class wrapper? + + # Currently unsupported flags. + raise NotImplementedError("TokenInformationClass(%i) not yet supported!" % TokenInformationClass) + +def _internal_GetTokenInformation(hTokenHandle, TokenInformationClass, TokenInformation): + _GetTokenInformation = windll.advapi32.GetTokenInformation + _GetTokenInformation.argtypes = [HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD] + _GetTokenInformation.restype = bool + _GetTokenInformation.errcheck = RaiseIfZero + + ReturnLength = DWORD(0) + TokenInformationLength = SIZEOF(TokenInformation) + _GetTokenInformation(hTokenHandle, TokenInformationClass, byref(TokenInformation), TokenInformationLength, byref(ReturnLength)) + if ReturnLength.value != TokenInformationLength: + raise ctypes.WinError(ERROR_INSUFFICIENT_BUFFER) + return TokenInformation + +# BOOL WINAPI SetTokenInformation( +# __in HANDLE TokenHandle, +# __in TOKEN_INFORMATION_CLASS TokenInformationClass, +# __in LPVOID TokenInformation, +# __in DWORD TokenInformationLength +# ); + +# XXX TODO + +# BOOL WINAPI CreateProcessWithLogonW( +# __in LPCWSTR lpUsername, +# __in_opt LPCWSTR lpDomain, +# __in LPCWSTR lpPassword, +# __in DWORD dwLogonFlags, +# __in_opt LPCWSTR lpApplicationName, +# __inout_opt LPWSTR lpCommandLine, +# __in DWORD dwCreationFlags, +# __in_opt LPVOID lpEnvironment, +# __in_opt LPCWSTR lpCurrentDirectory, +# __in LPSTARTUPINFOW lpStartupInfo, +# __out LPPROCESS_INFORMATION lpProcessInfo +# ); +def CreateProcessWithLogonW(lpUsername = None, lpDomain = None, lpPassword = None, dwLogonFlags = 0, lpApplicationName = None, lpCommandLine = None, dwCreationFlags = 0, lpEnvironment = None, lpCurrentDirectory = None, lpStartupInfo = None): + _CreateProcessWithLogonW = windll.advapi32.CreateProcessWithLogonW + _CreateProcessWithLogonW.argtypes = [LPWSTR, LPWSTR, LPWSTR, DWORD, LPWSTR, LPWSTR, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION] + _CreateProcessWithLogonW.restype = bool + _CreateProcessWithLogonW.errcheck = RaiseIfZero + + if not lpUsername: + lpUsername = None + if not lpDomain: + lpDomain = None + if not lpPassword: + lpPassword = None + if not lpApplicationName: + lpApplicationName = None + if not lpCommandLine: + lpCommandLine = None + else: + lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine))) + if not lpEnvironment: + lpEnvironment = None + else: + lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment) + if not lpCurrentDirectory: + lpCurrentDirectory = None + if not lpStartupInfo: + lpStartupInfo = STARTUPINFOW() + lpStartupInfo.cb = sizeof(STARTUPINFOW) + lpStartupInfo.lpReserved = 0 + lpStartupInfo.lpDesktop = 0 + lpStartupInfo.lpTitle = 0 + lpStartupInfo.dwFlags = 0 + lpStartupInfo.cbReserved2 = 0 + lpStartupInfo.lpReserved2 = 0 + lpProcessInformation = PROCESS_INFORMATION() + lpProcessInformation.hProcess = INVALID_HANDLE_VALUE + lpProcessInformation.hThread = INVALID_HANDLE_VALUE + lpProcessInformation.dwProcessId = 0 + lpProcessInformation.dwThreadId = 0 + _CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation)) + return ProcessInformation(lpProcessInformation) + +CreateProcessWithLogonA = MakeANSIVersion(CreateProcessWithLogonW) +CreateProcessWithLogon = DefaultStringType(CreateProcessWithLogonA, CreateProcessWithLogonW) + +# BOOL WINAPI CreateProcessWithTokenW( +# __in HANDLE hToken, +# __in DWORD dwLogonFlags, +# __in_opt LPCWSTR lpApplicationName, +# __inout_opt LPWSTR lpCommandLine, +# __in DWORD dwCreationFlags, +# __in_opt LPVOID lpEnvironment, +# __in_opt LPCWSTR lpCurrentDirectory, +# __in LPSTARTUPINFOW lpStartupInfo, +# __out LPPROCESS_INFORMATION lpProcessInfo +# ); +def CreateProcessWithTokenW(hToken = None, dwLogonFlags = 0, lpApplicationName = None, lpCommandLine = None, dwCreationFlags = 0, lpEnvironment = None, lpCurrentDirectory = None, lpStartupInfo = None): + _CreateProcessWithTokenW = windll.advapi32.CreateProcessWithTokenW + _CreateProcessWithTokenW.argtypes = [HANDLE, DWORD, LPWSTR, LPWSTR, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION] + _CreateProcessWithTokenW.restype = bool + _CreateProcessWithTokenW.errcheck = RaiseIfZero + + if not hToken: + hToken = None + if not lpApplicationName: + lpApplicationName = None + if not lpCommandLine: + lpCommandLine = None + else: + lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine))) + if not lpEnvironment: + lpEnvironment = None + else: + lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment) + if not lpCurrentDirectory: + lpCurrentDirectory = None + if not lpStartupInfo: + lpStartupInfo = STARTUPINFOW() + lpStartupInfo.cb = sizeof(STARTUPINFOW) + lpStartupInfo.lpReserved = 0 + lpStartupInfo.lpDesktop = 0 + lpStartupInfo.lpTitle = 0 + lpStartupInfo.dwFlags = 0 + lpStartupInfo.cbReserved2 = 0 + lpStartupInfo.lpReserved2 = 0 + lpProcessInformation = PROCESS_INFORMATION() + lpProcessInformation.hProcess = INVALID_HANDLE_VALUE + lpProcessInformation.hThread = INVALID_HANDLE_VALUE + lpProcessInformation.dwProcessId = 0 + lpProcessInformation.dwThreadId = 0 + _CreateProcessWithTokenW(hToken, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation)) + return ProcessInformation(lpProcessInformation) + +CreateProcessWithTokenA = MakeANSIVersion(CreateProcessWithTokenW) +CreateProcessWithToken = DefaultStringType(CreateProcessWithTokenA, CreateProcessWithTokenW) + +# BOOL WINAPI CreateProcessAsUser( +# __in_opt HANDLE hToken, +# __in_opt LPCTSTR lpApplicationName, +# __inout_opt LPTSTR lpCommandLine, +# __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, +# __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, +# __in BOOL bInheritHandles, +# __in DWORD dwCreationFlags, +# __in_opt LPVOID lpEnvironment, +# __in_opt LPCTSTR lpCurrentDirectory, +# __in LPSTARTUPINFO lpStartupInfo, +# __out LPPROCESS_INFORMATION lpProcessInformation +# ); +def CreateProcessAsUserA(hToken = None, lpApplicationName = None, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None): + _CreateProcessAsUserA = windll.advapi32.CreateProcessAsUserA + _CreateProcessAsUserA.argtypes = [HANDLE, LPSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPSTR, LPVOID, LPPROCESS_INFORMATION] + _CreateProcessAsUserA.restype = bool + _CreateProcessAsUserA.errcheck = RaiseIfZero + + if not lpApplicationName: + lpApplicationName = None + if not lpCommandLine: + lpCommandLine = None + else: + lpCommandLine = ctypes.create_string_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine))) + if not lpEnvironment: + lpEnvironment = None + else: + lpEnvironment = ctypes.create_string_buffer(lpEnvironment) + if not lpCurrentDirectory: + lpCurrentDirectory = None + if not lpProcessAttributes: + lpProcessAttributes = None + else: + lpProcessAttributes = byref(lpProcessAttributes) + if not lpThreadAttributes: + lpThreadAttributes = None + else: + lpThreadAttributes = byref(lpThreadAttributes) + if not lpStartupInfo: + lpStartupInfo = STARTUPINFO() + lpStartupInfo.cb = sizeof(STARTUPINFO) + lpStartupInfo.lpReserved = 0 + lpStartupInfo.lpDesktop = 0 + lpStartupInfo.lpTitle = 0 + lpStartupInfo.dwFlags = 0 + lpStartupInfo.cbReserved2 = 0 + lpStartupInfo.lpReserved2 = 0 + lpProcessInformation = PROCESS_INFORMATION() + lpProcessInformation.hProcess = INVALID_HANDLE_VALUE + lpProcessInformation.hThread = INVALID_HANDLE_VALUE + lpProcessInformation.dwProcessId = 0 + lpProcessInformation.dwThreadId = 0 + _CreateProcessAsUserA(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHandles), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation)) + return ProcessInformation(lpProcessInformation) + +def CreateProcessAsUserW(hToken = None, lpApplicationName = None, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None): + _CreateProcessAsUserW = windll.advapi32.CreateProcessAsUserW + _CreateProcessAsUserW.argtypes = [HANDLE, LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION] + _CreateProcessAsUserW.restype = bool + _CreateProcessAsUserW.errcheck = RaiseIfZero + + if not lpApplicationName: + lpApplicationName = None + if not lpCommandLine: + lpCommandLine = None + else: + lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine))) + if not lpEnvironment: + lpEnvironment = None + else: + lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment) + if not lpCurrentDirectory: + lpCurrentDirectory = None + if not lpProcessAttributes: + lpProcessAttributes = None + else: + lpProcessAttributes = byref(lpProcessAttributes) + if not lpThreadAttributes: + lpThreadAttributes = None + else: + lpThreadAttributes = byref(lpThreadAttributes) + if not lpStartupInfo: + lpStartupInfo = STARTUPINFO() + lpStartupInfo.cb = sizeof(STARTUPINFO) + lpStartupInfo.lpReserved = 0 + lpStartupInfo.lpDesktop = 0 + lpStartupInfo.lpTitle = 0 + lpStartupInfo.dwFlags = 0 + lpStartupInfo.cbReserved2 = 0 + lpStartupInfo.lpReserved2 = 0 + lpProcessInformation = PROCESS_INFORMATION() + lpProcessInformation.hProcess = INVALID_HANDLE_VALUE + lpProcessInformation.hThread = INVALID_HANDLE_VALUE + lpProcessInformation.dwProcessId = 0 + lpProcessInformation.dwThreadId = 0 + _CreateProcessAsUserW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHandles), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation)) + return ProcessInformation(lpProcessInformation) + +CreateProcessAsUser = GuessStringType(CreateProcessAsUserA, CreateProcessAsUserW) + +# VOID CALLBACK WaitChainCallback( +# HWCT WctHandle, +# DWORD_PTR Context, +# DWORD CallbackStatus, +# LPDWORD NodeCount, +# PWAITCHAIN_NODE_INFO NodeInfoArray, +# LPBOOL IsCycle +# ); +PWAITCHAINCALLBACK = WINFUNCTYPE(HWCT, DWORD_PTR, DWORD, LPDWORD, PWAITCHAIN_NODE_INFO, LPBOOL) + +# HWCT WINAPI OpenThreadWaitChainSession( +# __in DWORD Flags, +# __in_opt PWAITCHAINCALLBACK callback +# ); +def OpenThreadWaitChainSession(Flags = 0, callback = None): + _OpenThreadWaitChainSession = windll.advapi32.OpenThreadWaitChainSession + _OpenThreadWaitChainSession.argtypes = [DWORD, PVOID] + _OpenThreadWaitChainSession.restype = HWCT + _OpenThreadWaitChainSession.errcheck = RaiseIfZero + + if callback is not None: + callback = PWAITCHAINCALLBACK(callback) + aHandle = _OpenThreadWaitChainSession(Flags, callback) + return ThreadWaitChainSessionHandle(aHandle) + +# BOOL WINAPI GetThreadWaitChain( +# _In_ HWCT WctHandle, +# _In_opt_ DWORD_PTR Context, +# _In_ DWORD Flags, +# _In_ DWORD ThreadId, +# _Inout_ LPDWORD NodeCount, +# _Out_ PWAITCHAIN_NODE_INFO NodeInfoArray, +# _Out_ LPBOOL IsCycle +# ); +def GetThreadWaitChain(WctHandle, Context = None, Flags = WCTP_GETINFO_ALL_FLAGS, ThreadId = -1, NodeCount = WCT_MAX_NODE_COUNT): + _GetThreadWaitChain = windll.advapi32.GetThreadWaitChain + _GetThreadWaitChain.argtypes = [HWCT, LPDWORD, DWORD, DWORD, LPDWORD, PWAITCHAIN_NODE_INFO, LPBOOL] + _GetThreadWaitChain.restype = bool + _GetThreadWaitChain.errcheck = RaiseIfZero + + dwNodeCount = DWORD(NodeCount) + NodeInfoArray = (WAITCHAIN_NODE_INFO * NodeCount)() + IsCycle = BOOL(0) + _GetThreadWaitChain(WctHandle, Context, Flags, ThreadId, byref(dwNodeCount), ctypes.cast(ctypes.pointer(NodeInfoArray), PWAITCHAIN_NODE_INFO), byref(IsCycle)) + while dwNodeCount.value > NodeCount: + NodeCount = dwNodeCount.value + NodeInfoArray = (WAITCHAIN_NODE_INFO * NodeCount)() + _GetThreadWaitChain(WctHandle, Context, Flags, ThreadId, byref(dwNodeCount), ctypes.cast(ctypes.pointer(NodeInfoArray), PWAITCHAIN_NODE_INFO), byref(IsCycle)) + return ( + [ WaitChainNodeInfo(NodeInfoArray[index]) for index in compat.xrange(dwNodeCount.value) ], + bool(IsCycle.value) + ) + +# VOID WINAPI CloseThreadWaitChainSession( +# __in HWCT WctHandle +# ); +def CloseThreadWaitChainSession(WctHandle): + _CloseThreadWaitChainSession = windll.advapi32.CloseThreadWaitChainSession + _CloseThreadWaitChainSession.argtypes = [HWCT] + _CloseThreadWaitChainSession(WctHandle) + +# BOOL WINAPI SaferCreateLevel( +# __in DWORD dwScopeId, +# __in DWORD dwLevelId, +# __in DWORD OpenFlags, +# __out SAFER_LEVEL_HANDLE *pLevelHandle, +# __reserved LPVOID lpReserved +# ); +def SaferCreateLevel(dwScopeId=SAFER_SCOPEID_USER, dwLevelId=SAFER_LEVELID_NORMALUSER, OpenFlags=0): + _SaferCreateLevel = windll.advapi32.SaferCreateLevel + _SaferCreateLevel.argtypes = [DWORD, DWORD, DWORD, POINTER(SAFER_LEVEL_HANDLE), LPVOID] + _SaferCreateLevel.restype = BOOL + _SaferCreateLevel.errcheck = RaiseIfZero + + hLevelHandle = SAFER_LEVEL_HANDLE(INVALID_HANDLE_VALUE) + _SaferCreateLevel(dwScopeId, dwLevelId, OpenFlags, byref(hLevelHandle), None) + return SaferLevelHandle(hLevelHandle.value) + +# BOOL WINAPI SaferIdentifyLevel( +# __in DWORD dwNumProperties, +# __in_opt PSAFER_CODE_PROPERTIES pCodeProperties, +# __out SAFER_LEVEL_HANDLE *pLevelHandle, +# __reserved LPVOID lpReserved +# ); + +# XXX TODO + +# BOOL WINAPI SaferComputeTokenFromLevel( +# __in SAFER_LEVEL_HANDLE LevelHandle, +# __in_opt HANDLE InAccessToken, +# __out PHANDLE OutAccessToken, +# __in DWORD dwFlags, +# __inout_opt LPVOID lpReserved +# ); +def SaferComputeTokenFromLevel(LevelHandle, InAccessToken=None, dwFlags=0): + _SaferComputeTokenFromLevel = windll.advapi32.SaferComputeTokenFromLevel + _SaferComputeTokenFromLevel.argtypes = [SAFER_LEVEL_HANDLE, HANDLE, PHANDLE, DWORD, LPDWORD] + _SaferComputeTokenFromLevel.restype = BOOL + _SaferComputeTokenFromLevel.errcheck = RaiseIfZero + + OutAccessToken = HANDLE(INVALID_HANDLE_VALUE) + lpReserved = DWORD(0) + _SaferComputeTokenFromLevel(LevelHandle, InAccessToken, byref(OutAccessToken), dwFlags, byref(lpReserved)) + return TokenHandle(OutAccessToken.value), lpReserved.value + +# BOOL WINAPI SaferCloseLevel( +# __in SAFER_LEVEL_HANDLE hLevelHandle +# ); +def SaferCloseLevel(hLevelHandle): + _SaferCloseLevel = windll.advapi32.SaferCloseLevel + _SaferCloseLevel.argtypes = [SAFER_LEVEL_HANDLE] + _SaferCloseLevel.restype = BOOL + _SaferCloseLevel.errcheck = RaiseIfZero + + if hasattr(hLevelHandle, 'value'): + _SaferCloseLevel(hLevelHandle.value) + else: + _SaferCloseLevel(hLevelHandle) + +# BOOL SaferiIsExecutableFileType( +# __in LPCWSTR szFullPath, +# __in BOOLEAN bFromShellExecute +# ); +def SaferiIsExecutableFileType(szFullPath, bFromShellExecute = False): + _SaferiIsExecutableFileType = windll.advapi32.SaferiIsExecutableFileType + _SaferiIsExecutableFileType.argtypes = [LPWSTR, BOOLEAN] + _SaferiIsExecutableFileType.restype = BOOL + _SaferiIsExecutableFileType.errcheck = RaiseIfLastError + + SetLastError(ERROR_SUCCESS) + return bool(_SaferiIsExecutableFileType(compat.unicode(szFullPath), bFromShellExecute)) + +# useful alias since I'm likely to misspell it :P +SaferIsExecutableFileType = SaferiIsExecutableFileType + +#------------------------------------------------------------------------------ + +# LONG WINAPI RegCloseKey( +# __in HKEY hKey +# ); +def RegCloseKey(hKey): + if hasattr(hKey, 'value'): + value = hKey.value + else: + value = hKey + + if value in ( + HKEY_CLASSES_ROOT, + HKEY_CURRENT_USER, + HKEY_LOCAL_MACHINE, + HKEY_USERS, + HKEY_PERFORMANCE_DATA, + HKEY_CURRENT_CONFIG + ): + return + + _RegCloseKey = windll.advapi32.RegCloseKey + _RegCloseKey.argtypes = [HKEY] + _RegCloseKey.restype = LONG + _RegCloseKey.errcheck = RaiseIfNotErrorSuccess + _RegCloseKey(hKey) + +# LONG WINAPI RegConnectRegistry( +# __in_opt LPCTSTR lpMachineName, +# __in HKEY hKey, +# __out PHKEY phkResult +# ); +def RegConnectRegistryA(lpMachineName = None, hKey = HKEY_LOCAL_MACHINE): + _RegConnectRegistryA = windll.advapi32.RegConnectRegistryA + _RegConnectRegistryA.argtypes = [LPSTR, HKEY, PHKEY] + _RegConnectRegistryA.restype = LONG + _RegConnectRegistryA.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegConnectRegistryA(lpMachineName, hKey, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +def RegConnectRegistryW(lpMachineName = None, hKey = HKEY_LOCAL_MACHINE): + _RegConnectRegistryW = windll.advapi32.RegConnectRegistryW + _RegConnectRegistryW.argtypes = [LPWSTR, HKEY, PHKEY] + _RegConnectRegistryW.restype = LONG + _RegConnectRegistryW.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegConnectRegistryW(lpMachineName, hKey, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +RegConnectRegistry = GuessStringType(RegConnectRegistryA, RegConnectRegistryW) + +# LONG WINAPI RegCreateKey( +# __in HKEY hKey, +# __in_opt LPCTSTR lpSubKey, +# __out PHKEY phkResult +# ); +def RegCreateKeyA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None): + _RegCreateKeyA = windll.advapi32.RegCreateKeyA + _RegCreateKeyA.argtypes = [HKEY, LPSTR, PHKEY] + _RegCreateKeyA.restype = LONG + _RegCreateKeyA.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegCreateKeyA(hKey, lpSubKey, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +def RegCreateKeyW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None): + _RegCreateKeyW = windll.advapi32.RegCreateKeyW + _RegCreateKeyW.argtypes = [HKEY, LPWSTR, PHKEY] + _RegCreateKeyW.restype = LONG + _RegCreateKeyW.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegCreateKeyW(hKey, lpSubKey, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +RegCreateKey = GuessStringType(RegCreateKeyA, RegCreateKeyW) + +# LONG WINAPI RegCreateKeyEx( +# __in HKEY hKey, +# __in LPCTSTR lpSubKey, +# __reserved DWORD Reserved, +# __in_opt LPTSTR lpClass, +# __in DWORD dwOptions, +# __in REGSAM samDesired, +# __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, +# __out PHKEY phkResult, +# __out_opt LPDWORD lpdwDisposition +# ); + +# XXX TODO + +# LONG WINAPI RegOpenKey( +# __in HKEY hKey, +# __in_opt LPCTSTR lpSubKey, +# __out PHKEY phkResult +# ); +def RegOpenKeyA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None): + _RegOpenKeyA = windll.advapi32.RegOpenKeyA + _RegOpenKeyA.argtypes = [HKEY, LPSTR, PHKEY] + _RegOpenKeyA.restype = LONG + _RegOpenKeyA.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegOpenKeyA(hKey, lpSubKey, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +def RegOpenKeyW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None): + _RegOpenKeyW = windll.advapi32.RegOpenKeyW + _RegOpenKeyW.argtypes = [HKEY, LPWSTR, PHKEY] + _RegOpenKeyW.restype = LONG + _RegOpenKeyW.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegOpenKeyW(hKey, lpSubKey, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +RegOpenKey = GuessStringType(RegOpenKeyA, RegOpenKeyW) + +# LONG WINAPI RegOpenKeyEx( +# __in HKEY hKey, +# __in_opt LPCTSTR lpSubKey, +# __reserved DWORD ulOptions, +# __in REGSAM samDesired, +# __out PHKEY phkResult +# ); +def RegOpenKeyExA(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None, samDesired = KEY_ALL_ACCESS): + _RegOpenKeyExA = windll.advapi32.RegOpenKeyExA + _RegOpenKeyExA.argtypes = [HKEY, LPSTR, DWORD, REGSAM, PHKEY] + _RegOpenKeyExA.restype = LONG + _RegOpenKeyExA.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegOpenKeyExA(hKey, lpSubKey, 0, samDesired, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +def RegOpenKeyExW(hKey = HKEY_LOCAL_MACHINE, lpSubKey = None, samDesired = KEY_ALL_ACCESS): + _RegOpenKeyExW = windll.advapi32.RegOpenKeyExW + _RegOpenKeyExW.argtypes = [HKEY, LPWSTR, DWORD, REGSAM, PHKEY] + _RegOpenKeyExW.restype = LONG + _RegOpenKeyExW.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegOpenKeyExW(hKey, lpSubKey, 0, samDesired, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +RegOpenKeyEx = GuessStringType(RegOpenKeyExA, RegOpenKeyExW) + +# LONG WINAPI RegOpenCurrentUser( +# __in REGSAM samDesired, +# __out PHKEY phkResult +# ); +def RegOpenCurrentUser(samDesired = KEY_ALL_ACCESS): + _RegOpenCurrentUser = windll.advapi32.RegOpenCurrentUser + _RegOpenCurrentUser.argtypes = [REGSAM, PHKEY] + _RegOpenCurrentUser.restype = LONG + _RegOpenCurrentUser.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegOpenCurrentUser(samDesired, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +# LONG WINAPI RegOpenUserClassesRoot( +# __in HANDLE hToken, +# __reserved DWORD dwOptions, +# __in REGSAM samDesired, +# __out PHKEY phkResult +# ); +def RegOpenUserClassesRoot(hToken, samDesired = KEY_ALL_ACCESS): + _RegOpenUserClassesRoot = windll.advapi32.RegOpenUserClassesRoot + _RegOpenUserClassesRoot.argtypes = [HANDLE, DWORD, REGSAM, PHKEY] + _RegOpenUserClassesRoot.restype = LONG + _RegOpenUserClassesRoot.errcheck = RaiseIfNotErrorSuccess + + hkResult = HKEY(INVALID_HANDLE_VALUE) + _RegOpenUserClassesRoot(hToken, 0, samDesired, byref(hkResult)) + return RegistryKeyHandle(hkResult.value) + +# LONG WINAPI RegQueryValue( +# __in HKEY hKey, +# __in_opt LPCTSTR lpSubKey, +# __out_opt LPTSTR lpValue, +# __inout_opt PLONG lpcbValue +# ); +def RegQueryValueA(hKey, lpSubKey = None): + _RegQueryValueA = windll.advapi32.RegQueryValueA + _RegQueryValueA.argtypes = [HKEY, LPSTR, LPVOID, PLONG] + _RegQueryValueA.restype = LONG + _RegQueryValueA.errcheck = RaiseIfNotErrorSuccess + + cbValue = LONG(0) + _RegQueryValueA(hKey, lpSubKey, None, byref(cbValue)) + lpValue = ctypes.create_string_buffer(cbValue.value) + _RegQueryValueA(hKey, lpSubKey, lpValue, byref(cbValue)) + return lpValue.value + +def RegQueryValueW(hKey, lpSubKey = None): + _RegQueryValueW = windll.advapi32.RegQueryValueW + _RegQueryValueW.argtypes = [HKEY, LPWSTR, LPVOID, PLONG] + _RegQueryValueW.restype = LONG + _RegQueryValueW.errcheck = RaiseIfNotErrorSuccess + + cbValue = LONG(0) + _RegQueryValueW(hKey, lpSubKey, None, byref(cbValue)) + lpValue = ctypes.create_unicode_buffer(cbValue.value * sizeof(WCHAR)) + _RegQueryValueW(hKey, lpSubKey, lpValue, byref(cbValue)) + return lpValue.value + +RegQueryValue = GuessStringType(RegQueryValueA, RegQueryValueW) + +# LONG WINAPI RegQueryValueEx( +# __in HKEY hKey, +# __in_opt LPCTSTR lpValueName, +# __reserved LPDWORD lpReserved, +# __out_opt LPDWORD lpType, +# __out_opt LPBYTE lpData, +# __inout_opt LPDWORD lpcbData +# ); +def _internal_RegQueryValueEx(ansi, hKey, lpValueName = None, bGetData = True): + _RegQueryValueEx = _caller_RegQueryValueEx(ansi) + + cbData = DWORD(0) + dwType = DWORD(-1) + _RegQueryValueEx(hKey, lpValueName, None, byref(dwType), None, byref(cbData)) + Type = dwType.value + + if not bGetData: + return cbData.value, Type + + if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN + if cbData.value != 4: + raise ValueError("REG_DWORD value of size %d" % cbData.value) + dwData = DWORD(0) + _RegQueryValueEx(hKey, lpValueName, None, None, byref(dwData), byref(cbData)) + return dwData.value, Type + + if Type == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN + if cbData.value != 8: + raise ValueError("REG_QWORD value of size %d" % cbData.value) + qwData = QWORD(long(0)) + _RegQueryValueEx(hKey, lpValueName, None, None, byref(qwData), byref(cbData)) + return qwData.value, Type + + if Type in (REG_SZ, REG_EXPAND_SZ): + if ansi: + szData = ctypes.create_string_buffer(cbData.value) + else: + szData = ctypes.create_unicode_buffer(cbData.value) + _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData)) + return szData.value, Type + + if Type == REG_MULTI_SZ: + if ansi: + szData = ctypes.create_string_buffer(cbData.value) + else: + szData = ctypes.create_unicode_buffer(cbData.value) + _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData)) + Data = szData[:] + if ansi: + aData = Data.split('\0') + else: + aData = Data.split(u'\0') + aData = [token for token in aData if token] + return aData, Type + + if Type == REG_LINK: + szData = ctypes.create_unicode_buffer(cbData.value) + _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData)) + return szData.value, Type + + # REG_BINARY, REG_NONE, and any future types + szData = ctypes.create_string_buffer(cbData.value) + _RegQueryValueEx(hKey, lpValueName, None, None, byref(szData), byref(cbData)) + return szData.raw, Type + +def _caller_RegQueryValueEx(ansi): + if ansi: + _RegQueryValueEx = windll.advapi32.RegQueryValueExA + _RegQueryValueEx.argtypes = [HKEY, LPSTR, LPVOID, PDWORD, LPVOID, PDWORD] + else: + _RegQueryValueEx = windll.advapi32.RegQueryValueExW + _RegQueryValueEx.argtypes = [HKEY, LPWSTR, LPVOID, PDWORD, LPVOID, PDWORD] + _RegQueryValueEx.restype = LONG + _RegQueryValueEx.errcheck = RaiseIfNotErrorSuccess + return _RegQueryValueEx + +# see _internal_RegQueryValueEx +def RegQueryValueExA(hKey, lpValueName = None, bGetData = True): + return _internal_RegQueryValueEx(True, hKey, lpValueName, bGetData) + +# see _internal_RegQueryValueEx +def RegQueryValueExW(hKey, lpValueName = None, bGetData = True): + return _internal_RegQueryValueEx(False, hKey, lpValueName, bGetData) + +RegQueryValueEx = GuessStringType(RegQueryValueExA, RegQueryValueExW) + +# LONG WINAPI RegSetValueEx( +# __in HKEY hKey, +# __in_opt LPCTSTR lpValueName, +# __reserved DWORD Reserved, +# __in DWORD dwType, +# __in_opt const BYTE *lpData, +# __in DWORD cbData +# ); +def RegSetValueEx(hKey, lpValueName = None, lpData = None, dwType = None): + + # Determine which version of the API to use, ANSI or Widechar. + if lpValueName is None: + if isinstance(lpData, GuessStringType.t_ansi): + ansi = True + elif isinstance(lpData, GuessStringType.t_unicode): + ansi = False + else: + ansi = (GuessStringType.t_ansi == GuessStringType.t_default) + elif isinstance(lpValueName, GuessStringType.t_ansi): + ansi = True + elif isinstance(lpValueName, GuessStringType.t_unicode): + ansi = False + else: + raise TypeError("String expected, got %s instead" % type(lpValueName)) + + # Autodetect the type when not given. + # TODO: improve detection of DWORD and QWORD by seeing if the value "fits". + if dwType is None: + if lpValueName is None: + dwType = REG_SZ + elif lpData is None: + dwType = REG_NONE + elif isinstance(lpData, GuessStringType.t_ansi): + dwType = REG_SZ + elif isinstance(lpData, GuessStringType.t_unicode): + dwType = REG_SZ + elif isinstance(lpData, int): + dwType = REG_DWORD + elif isinstance(lpData, long): + dwType = REG_QWORD + else: + dwType = REG_BINARY + + # Load the ctypes caller. + if ansi: + _RegSetValueEx = windll.advapi32.RegSetValueExA + _RegSetValueEx.argtypes = [HKEY, LPSTR, DWORD, DWORD, LPVOID, DWORD] + else: + _RegSetValueEx = windll.advapi32.RegSetValueExW + _RegSetValueEx.argtypes = [HKEY, LPWSTR, DWORD, DWORD, LPVOID, DWORD] + _RegSetValueEx.restype = LONG + _RegSetValueEx.errcheck = RaiseIfNotErrorSuccess + + # Convert the arguments so ctypes can understand them. + if lpData is None: + DataRef = None + DataSize = 0 + else: + if dwType in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN + Data = DWORD(lpData) + elif dwType == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN + Data = QWORD(lpData) + elif dwType in (REG_SZ, REG_EXPAND_SZ): + if ansi: + Data = ctypes.create_string_buffer(lpData) + else: + Data = ctypes.create_unicode_buffer(lpData) + elif dwType == REG_MULTI_SZ: + if ansi: + Data = ctypes.create_string_buffer('\0'.join(lpData) + '\0\0') + else: + Data = ctypes.create_unicode_buffer(u'\0'.join(lpData) + u'\0\0') + elif dwType == REG_LINK: + Data = ctypes.create_unicode_buffer(lpData) + else: + Data = ctypes.create_string_buffer(lpData) + DataRef = byref(Data) + DataSize = sizeof(Data) + + # Call the API with the converted arguments. + _RegSetValueEx(hKey, lpValueName, 0, dwType, DataRef, DataSize) + +# No "GuessStringType" here since detection is done inside. +RegSetValueExA = RegSetValueExW = RegSetValueEx + +# LONG WINAPI RegEnumKey( +# __in HKEY hKey, +# __in DWORD dwIndex, +# __out LPTSTR lpName, +# __in DWORD cchName +# ); +def RegEnumKeyA(hKey, dwIndex): + _RegEnumKeyA = windll.advapi32.RegEnumKeyA + _RegEnumKeyA.argtypes = [HKEY, DWORD, LPSTR, DWORD] + _RegEnumKeyA.restype = LONG + + cchName = 1024 + while True: + lpName = ctypes.create_string_buffer(cchName) + errcode = _RegEnumKeyA(hKey, dwIndex, lpName, cchName) + if errcode != ERROR_MORE_DATA: + break + cchName = cchName + 1024 + if cchName > 65536: + raise ctypes.WinError(errcode) + if errcode == ERROR_NO_MORE_ITEMS: + return None + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return lpName.value + +def RegEnumKeyW(hKey, dwIndex): + _RegEnumKeyW = windll.advapi32.RegEnumKeyW + _RegEnumKeyW.argtypes = [HKEY, DWORD, LPWSTR, DWORD] + _RegEnumKeyW.restype = LONG + + cchName = 512 + while True: + lpName = ctypes.create_unicode_buffer(cchName) + errcode = _RegEnumKeyW(hKey, dwIndex, lpName, cchName * 2) + if errcode != ERROR_MORE_DATA: + break + cchName = cchName + 512 + if cchName > 32768: + raise ctypes.WinError(errcode) + if errcode == ERROR_NO_MORE_ITEMS: + return None + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return lpName.value + +RegEnumKey = DefaultStringType(RegEnumKeyA, RegEnumKeyW) + +# LONG WINAPI RegEnumKeyEx( +# __in HKEY hKey, +# __in DWORD dwIndex, +# __out LPTSTR lpName, +# __inout LPDWORD lpcName, +# __reserved LPDWORD lpReserved, +# __inout LPTSTR lpClass, +# __inout_opt LPDWORD lpcClass, +# __out_opt PFILETIME lpftLastWriteTime +# ); + +# XXX TODO + +# LONG WINAPI RegEnumValue( +# __in HKEY hKey, +# __in DWORD dwIndex, +# __out LPTSTR lpValueName, +# __inout LPDWORD lpcchValueName, +# __reserved LPDWORD lpReserved, +# __out_opt LPDWORD lpType, +# __out_opt LPBYTE lpData, +# __inout_opt LPDWORD lpcbData +# ); +def _internal_RegEnumValue(ansi, hKey, dwIndex, bGetData = True): + if ansi: + _RegEnumValue = windll.advapi32.RegEnumValueA + _RegEnumValue.argtypes = [HKEY, DWORD, LPSTR, LPDWORD, LPVOID, LPDWORD, LPVOID, LPDWORD] + else: + _RegEnumValue = windll.advapi32.RegEnumValueW + _RegEnumValue.argtypes = [HKEY, DWORD, LPWSTR, LPDWORD, LPVOID, LPDWORD, LPVOID, LPDWORD] + _RegEnumValue.restype = LONG + + cchValueName = DWORD(1024) + dwType = DWORD(-1) + lpcchValueName = byref(cchValueName) + lpType = byref(dwType) + if ansi: + lpValueName = ctypes.create_string_buffer(cchValueName.value) + else: + lpValueName = ctypes.create_unicode_buffer(cchValueName.value) + if bGetData: + cbData = DWORD(0) + lpcbData = byref(cbData) + else: + lpcbData = None + lpData = None + errcode = _RegEnumValue(hKey, dwIndex, lpValueName, lpcchValueName, None, lpType, lpData, lpcbData) + + if errcode == ERROR_MORE_DATA or (bGetData and errcode == ERROR_SUCCESS): + if ansi: + cchValueName.value = cchValueName.value + sizeof(CHAR) + lpValueName = ctypes.create_string_buffer(cchValueName.value) + else: + cchValueName.value = cchValueName.value + sizeof(WCHAR) + lpValueName = ctypes.create_unicode_buffer(cchValueName.value) + + if bGetData: + Type = dwType.value + + if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN): # REG_DWORD_LITTLE_ENDIAN + if cbData.value != sizeof(DWORD): + raise ValueError("REG_DWORD value of size %d" % cbData.value) + Data = DWORD(0) + + elif Type == REG_QWORD: # REG_QWORD_LITTLE_ENDIAN + if cbData.value != sizeof(QWORD): + raise ValueError("REG_QWORD value of size %d" % cbData.value) + Data = QWORD(long(0)) + + elif Type in (REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ): + if ansi: + Data = ctypes.create_string_buffer(cbData.value) + else: + Data = ctypes.create_unicode_buffer(cbData.value) + + elif Type == REG_LINK: + Data = ctypes.create_unicode_buffer(cbData.value) + + else: # REG_BINARY, REG_NONE, and any future types + Data = ctypes.create_string_buffer(cbData.value) + + lpData = byref(Data) + + errcode = _RegEnumValue(hKey, dwIndex, lpValueName, lpcchValueName, None, lpType, lpData, lpcbData) + + if errcode == ERROR_NO_MORE_ITEMS: + return None + #if errcode != ERROR_SUCCESS: + # raise ctypes.WinError(errcode) + + if not bGetData: + return lpValueName.value, dwType.value + + if Type in (REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD, REG_SZ, REG_EXPAND_SZ, REG_LINK): # REG_DWORD_LITTLE_ENDIAN, REG_QWORD_LITTLE_ENDIAN + return lpValueName.value, dwType.value, Data.value + + if Type == REG_MULTI_SZ: + sData = Data[:] + del Data + if ansi: + aData = sData.split('\0') + else: + aData = sData.split(u'\0') + aData = [token for token in aData if token] + return lpValueName.value, dwType.value, aData + + # REG_BINARY, REG_NONE, and any future types + return lpValueName.value, dwType.value, Data.raw + +def RegEnumValueA(hKey, dwIndex, bGetData = True): + return _internal_RegEnumValue(True, hKey, dwIndex, bGetData) + +def RegEnumValueW(hKey, dwIndex, bGetData = True): + return _internal_RegEnumValue(False, hKey, dwIndex, bGetData) + +RegEnumValue = DefaultStringType(RegEnumValueA, RegEnumValueW) + +# XXX TODO + +# LONG WINAPI RegSetKeyValue( +# __in HKEY hKey, +# __in_opt LPCTSTR lpSubKey, +# __in_opt LPCTSTR lpValueName, +# __in DWORD dwType, +# __in_opt LPCVOID lpData, +# __in DWORD cbData +# ); + +# XXX TODO + +# LONG WINAPI RegQueryMultipleValues( +# __in HKEY hKey, +# __out PVALENT val_list, +# __in DWORD num_vals, +# __out_opt LPTSTR lpValueBuf, +# __inout_opt LPDWORD ldwTotsize +# ); + +# XXX TODO + +# LONG WINAPI RegDeleteValue( +# __in HKEY hKey, +# __in_opt LPCTSTR lpValueName +# ); +def RegDeleteValueA(hKeySrc, lpValueName = None): + _RegDeleteValueA = windll.advapi32.RegDeleteValueA + _RegDeleteValueA.argtypes = [HKEY, LPSTR] + _RegDeleteValueA.restype = LONG + _RegDeleteValueA.errcheck = RaiseIfNotErrorSuccess + _RegDeleteValueA(hKeySrc, lpValueName) +def RegDeleteValueW(hKeySrc, lpValueName = None): + _RegDeleteValueW = windll.advapi32.RegDeleteValueW + _RegDeleteValueW.argtypes = [HKEY, LPWSTR] + _RegDeleteValueW.restype = LONG + _RegDeleteValueW.errcheck = RaiseIfNotErrorSuccess + _RegDeleteValueW(hKeySrc, lpValueName) +RegDeleteValue = GuessStringType(RegDeleteValueA, RegDeleteValueW) + +# LONG WINAPI RegDeleteKeyValue( +# __in HKEY hKey, +# __in_opt LPCTSTR lpSubKey, +# __in_opt LPCTSTR lpValueName +# ); +def RegDeleteKeyValueA(hKeySrc, lpSubKey = None, lpValueName = None): + _RegDeleteKeyValueA = windll.advapi32.RegDeleteKeyValueA + _RegDeleteKeyValueA.argtypes = [HKEY, LPSTR, LPSTR] + _RegDeleteKeyValueA.restype = LONG + _RegDeleteKeyValueA.errcheck = RaiseIfNotErrorSuccess + _RegDeleteKeyValueA(hKeySrc, lpSubKey, lpValueName) +def RegDeleteKeyValueW(hKeySrc, lpSubKey = None, lpValueName = None): + _RegDeleteKeyValueW = windll.advapi32.RegDeleteKeyValueW + _RegDeleteKeyValueW.argtypes = [HKEY, LPWSTR, LPWSTR] + _RegDeleteKeyValueW.restype = LONG + _RegDeleteKeyValueW.errcheck = RaiseIfNotErrorSuccess + _RegDeleteKeyValueW(hKeySrc, lpSubKey, lpValueName) +RegDeleteKeyValue = GuessStringType(RegDeleteKeyValueA, RegDeleteKeyValueW) + +# LONG WINAPI RegDeleteKey( +# __in HKEY hKey, +# __in LPCTSTR lpSubKey +# ); +def RegDeleteKeyA(hKeySrc, lpSubKey = None): + _RegDeleteKeyA = windll.advapi32.RegDeleteKeyA + _RegDeleteKeyA.argtypes = [HKEY, LPSTR] + _RegDeleteKeyA.restype = LONG + _RegDeleteKeyA.errcheck = RaiseIfNotErrorSuccess + _RegDeleteKeyA(hKeySrc, lpSubKey) +def RegDeleteKeyW(hKeySrc, lpSubKey = None): + _RegDeleteKeyW = windll.advapi32.RegDeleteKeyW + _RegDeleteKeyW.argtypes = [HKEY, LPWSTR] + _RegDeleteKeyW.restype = LONG + _RegDeleteKeyW.errcheck = RaiseIfNotErrorSuccess + _RegDeleteKeyW(hKeySrc, lpSubKey) +RegDeleteKey = GuessStringType(RegDeleteKeyA, RegDeleteKeyW) + +# LONG WINAPI RegDeleteKeyEx( +# __in HKEY hKey, +# __in LPCTSTR lpSubKey, +# __in REGSAM samDesired, +# __reserved DWORD Reserved +# ); + +def RegDeleteKeyExA(hKeySrc, lpSubKey = None, samDesired = KEY_WOW64_32KEY): + _RegDeleteKeyExA = windll.advapi32.RegDeleteKeyExA + _RegDeleteKeyExA.argtypes = [HKEY, LPSTR, REGSAM, DWORD] + _RegDeleteKeyExA.restype = LONG + _RegDeleteKeyExA.errcheck = RaiseIfNotErrorSuccess + _RegDeleteKeyExA(hKeySrc, lpSubKey, samDesired, 0) +def RegDeleteKeyExW(hKeySrc, lpSubKey = None, samDesired = KEY_WOW64_32KEY): + _RegDeleteKeyExW = windll.advapi32.RegDeleteKeyExW + _RegDeleteKeyExW.argtypes = [HKEY, LPWSTR, REGSAM, DWORD] + _RegDeleteKeyExW.restype = LONG + _RegDeleteKeyExW.errcheck = RaiseIfNotErrorSuccess + _RegDeleteKeyExW(hKeySrc, lpSubKey, samDesired, 0) +RegDeleteKeyEx = GuessStringType(RegDeleteKeyExA, RegDeleteKeyExW) + +# LONG WINAPI RegCopyTree( +# __in HKEY hKeySrc, +# __in_opt LPCTSTR lpSubKey, +# __in HKEY hKeyDest +# ); +def RegCopyTreeA(hKeySrc, lpSubKey, hKeyDest): + _RegCopyTreeA = windll.advapi32.RegCopyTreeA + _RegCopyTreeA.argtypes = [HKEY, LPSTR, HKEY] + _RegCopyTreeA.restype = LONG + _RegCopyTreeA.errcheck = RaiseIfNotErrorSuccess + _RegCopyTreeA(hKeySrc, lpSubKey, hKeyDest) +def RegCopyTreeW(hKeySrc, lpSubKey, hKeyDest): + _RegCopyTreeW = windll.advapi32.RegCopyTreeW + _RegCopyTreeW.argtypes = [HKEY, LPWSTR, HKEY] + _RegCopyTreeW.restype = LONG + _RegCopyTreeW.errcheck = RaiseIfNotErrorSuccess + _RegCopyTreeW(hKeySrc, lpSubKey, hKeyDest) +RegCopyTree = GuessStringType(RegCopyTreeA, RegCopyTreeW) + +# LONG WINAPI RegDeleteTree( +# __in HKEY hKey, +# __in_opt LPCTSTR lpSubKey +# ); +def RegDeleteTreeA(hKey, lpSubKey = None): + _RegDeleteTreeA = windll.advapi32.RegDeleteTreeA + _RegDeleteTreeA.argtypes = [HKEY, LPWSTR] + _RegDeleteTreeA.restype = LONG + _RegDeleteTreeA.errcheck = RaiseIfNotErrorSuccess + _RegDeleteTreeA(hKey, lpSubKey) +def RegDeleteTreeW(hKey, lpSubKey = None): + _RegDeleteTreeW = windll.advapi32.RegDeleteTreeW + _RegDeleteTreeW.argtypes = [HKEY, LPWSTR] + _RegDeleteTreeW.restype = LONG + _RegDeleteTreeW.errcheck = RaiseIfNotErrorSuccess + _RegDeleteTreeW(hKey, lpSubKey) +RegDeleteTree = GuessStringType(RegDeleteTreeA, RegDeleteTreeW) + +# LONG WINAPI RegFlushKey( +# __in HKEY hKey +# ); +def RegFlushKey(hKey): + _RegFlushKey = windll.advapi32.RegFlushKey + _RegFlushKey.argtypes = [HKEY] + _RegFlushKey.restype = LONG + _RegFlushKey.errcheck = RaiseIfNotErrorSuccess + _RegFlushKey(hKey) + +# LONG WINAPI RegLoadMUIString( +# _In_ HKEY hKey, +# _In_opt_ LPCTSTR pszValue, +# _Out_opt_ LPTSTR pszOutBuf, +# _In_ DWORD cbOutBuf, +# _Out_opt_ LPDWORD pcbData, +# _In_ DWORD Flags, +# _In_opt_ LPCTSTR pszDirectory +# ); + +# TO DO + +#------------------------------------------------------------------------------ + +# BOOL WINAPI CloseServiceHandle( +# _In_ SC_HANDLE hSCObject +# ); +def CloseServiceHandle(hSCObject): + _CloseServiceHandle = windll.advapi32.CloseServiceHandle + _CloseServiceHandle.argtypes = [SC_HANDLE] + _CloseServiceHandle.restype = bool + _CloseServiceHandle.errcheck = RaiseIfZero + + if isinstance(hSCObject, Handle): + # Prevents the handle from being closed without notifying the Handle object. + hSCObject.close() + else: + _CloseServiceHandle(hSCObject) + +# SC_HANDLE WINAPI OpenSCManager( +# _In_opt_ LPCTSTR lpMachineName, +# _In_opt_ LPCTSTR lpDatabaseName, +# _In_ DWORD dwDesiredAccess +# ); +def OpenSCManagerA(lpMachineName = None, lpDatabaseName = None, dwDesiredAccess = SC_MANAGER_ALL_ACCESS): + _OpenSCManagerA = windll.advapi32.OpenSCManagerA + _OpenSCManagerA.argtypes = [LPSTR, LPSTR, DWORD] + _OpenSCManagerA.restype = SC_HANDLE + _OpenSCManagerA.errcheck = RaiseIfZero + + hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess) + return ServiceControlManagerHandle(hSCObject) + +def OpenSCManagerW(lpMachineName = None, lpDatabaseName = None, dwDesiredAccess = SC_MANAGER_ALL_ACCESS): + _OpenSCManagerW = windll.advapi32.OpenSCManagerW + _OpenSCManagerW.argtypes = [LPWSTR, LPWSTR, DWORD] + _OpenSCManagerW.restype = SC_HANDLE + _OpenSCManagerW.errcheck = RaiseIfZero + + hSCObject = _OpenSCManagerA(lpMachineName, lpDatabaseName, dwDesiredAccess) + return ServiceControlManagerHandle(hSCObject) + +OpenSCManager = GuessStringType(OpenSCManagerA, OpenSCManagerW) + +# SC_HANDLE WINAPI OpenService( +# _In_ SC_HANDLE hSCManager, +# _In_ LPCTSTR lpServiceName, +# _In_ DWORD dwDesiredAccess +# ); +def OpenServiceA(hSCManager, lpServiceName, dwDesiredAccess = SERVICE_ALL_ACCESS): + _OpenServiceA = windll.advapi32.OpenServiceA + _OpenServiceA.argtypes = [SC_HANDLE, LPSTR, DWORD] + _OpenServiceA.restype = SC_HANDLE + _OpenServiceA.errcheck = RaiseIfZero + return ServiceHandle( _OpenServiceA(hSCManager, lpServiceName, dwDesiredAccess) ) + +def OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess = SERVICE_ALL_ACCESS): + _OpenServiceW = windll.advapi32.OpenServiceW + _OpenServiceW.argtypes = [SC_HANDLE, LPWSTR, DWORD] + _OpenServiceW.restype = SC_HANDLE + _OpenServiceW.errcheck = RaiseIfZero + return ServiceHandle( _OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess) ) + +OpenService = GuessStringType(OpenServiceA, OpenServiceW) + +# SC_HANDLE WINAPI CreateService( +# _In_ SC_HANDLE hSCManager, +# _In_ LPCTSTR lpServiceName, +# _In_opt_ LPCTSTR lpDisplayName, +# _In_ DWORD dwDesiredAccess, +# _In_ DWORD dwServiceType, +# _In_ DWORD dwStartType, +# _In_ DWORD dwErrorControl, +# _In_opt_ LPCTSTR lpBinaryPathName, +# _In_opt_ LPCTSTR lpLoadOrderGroup, +# _Out_opt_ LPDWORD lpdwTagId, +# _In_opt_ LPCTSTR lpDependencies, +# _In_opt_ LPCTSTR lpServiceStartName, +# _In_opt_ LPCTSTR lpPassword +# ); +def CreateServiceA(hSCManager, lpServiceName, + lpDisplayName = None, + dwDesiredAccess = SERVICE_ALL_ACCESS, + dwServiceType = SERVICE_WIN32_OWN_PROCESS, + dwStartType = SERVICE_DEMAND_START, + dwErrorControl = SERVICE_ERROR_NORMAL, + lpBinaryPathName = None, + lpLoadOrderGroup = None, + lpDependencies = None, + lpServiceStartName = None, + lpPassword = None): + + _CreateServiceA = windll.advapi32.CreateServiceA + _CreateServiceA.argtypes = [SC_HANDLE, LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD, LPSTR, LPSTR, LPDWORD, LPSTR, LPSTR, LPSTR] + _CreateServiceA.restype = SC_HANDLE + _CreateServiceA.errcheck = RaiseIfZero + + dwTagId = DWORD(0) + hService = _CreateServiceA(hSCManager, lpServiceName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, byref(dwTagId), lpDependencies, lpServiceStartName, lpPassword) + return ServiceHandle(hService), dwTagId.value + +def CreateServiceW(hSCManager, lpServiceName, + lpDisplayName = None, + dwDesiredAccess = SERVICE_ALL_ACCESS, + dwServiceType = SERVICE_WIN32_OWN_PROCESS, + dwStartType = SERVICE_DEMAND_START, + dwErrorControl = SERVICE_ERROR_NORMAL, + lpBinaryPathName = None, + lpLoadOrderGroup = None, + lpDependencies = None, + lpServiceStartName = None, + lpPassword = None): + + _CreateServiceW = windll.advapi32.CreateServiceW + _CreateServiceW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, DWORD, DWORD, DWORD, DWORD, LPWSTR, LPWSTR, LPDWORD, LPWSTR, LPWSTR, LPWSTR] + _CreateServiceW.restype = SC_HANDLE + _CreateServiceW.errcheck = RaiseIfZero + + dwTagId = DWORD(0) + hService = _CreateServiceW(hSCManager, lpServiceName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, byref(dwTagId), lpDependencies, lpServiceStartName, lpPassword) + return ServiceHandle(hService), dwTagId.value + +CreateService = GuessStringType(CreateServiceA, CreateServiceW) + +# BOOL WINAPI DeleteService( +# _In_ SC_HANDLE hService +# ); +def DeleteService(hService): + _DeleteService = windll.advapi32.DeleteService + _DeleteService.argtypes = [SC_HANDLE] + _DeleteService.restype = bool + _DeleteService.errcheck = RaiseIfZero + _DeleteService(hService) + +# BOOL WINAPI GetServiceKeyName( +# _In_ SC_HANDLE hSCManager, +# _In_ LPCTSTR lpDisplayName, +# _Out_opt_ LPTSTR lpServiceName, +# _Inout_ LPDWORD lpcchBuffer +# ); +def GetServiceKeyNameA(hSCManager, lpDisplayName): + _GetServiceKeyNameA = windll.advapi32.GetServiceKeyNameA + _GetServiceKeyNameA.argtypes = [SC_HANDLE, LPSTR, LPSTR, LPDWORD] + _GetServiceKeyNameA.restype = bool + + cchBuffer = DWORD(0) + _GetServiceKeyNameA(hSCManager, lpDisplayName, None, byref(cchBuffer)) + if cchBuffer.value == 0: + raise ctypes.WinError() + lpServiceName = ctypes.create_string_buffer(cchBuffer.value + 1) + cchBuffer.value = sizeof(lpServiceName) + success = _GetServiceKeyNameA(hSCManager, lpDisplayName, lpServiceName, byref(cchBuffer)) + if not success: + raise ctypes.WinError() + return lpServiceName.value + +def GetServiceKeyNameW(hSCManager, lpDisplayName): + _GetServiceKeyNameW = windll.advapi32.GetServiceKeyNameW + _GetServiceKeyNameW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, LPDWORD] + _GetServiceKeyNameW.restype = bool + + cchBuffer = DWORD(0) + _GetServiceKeyNameW(hSCManager, lpDisplayName, None, byref(cchBuffer)) + if cchBuffer.value == 0: + raise ctypes.WinError() + lpServiceName = ctypes.create_unicode_buffer(cchBuffer.value + 2) + cchBuffer.value = sizeof(lpServiceName) + success = _GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName, byref(cchBuffer)) + if not success: + raise ctypes.WinError() + return lpServiceName.value + +GetServiceKeyName = GuessStringType(GetServiceKeyNameA, GetServiceKeyNameW) + +# BOOL WINAPI GetServiceDisplayName( +# _In_ SC_HANDLE hSCManager, +# _In_ LPCTSTR lpServiceName, +# _Out_opt_ LPTSTR lpDisplayName, +# _Inout_ LPDWORD lpcchBuffer +# ); +def GetServiceDisplayNameA(hSCManager, lpServiceName): + _GetServiceDisplayNameA = windll.advapi32.GetServiceDisplayNameA + _GetServiceDisplayNameA.argtypes = [SC_HANDLE, LPSTR, LPSTR, LPDWORD] + _GetServiceDisplayNameA.restype = bool + + cchBuffer = DWORD(0) + _GetServiceDisplayNameA(hSCManager, lpServiceName, None, byref(cchBuffer)) + if cchBuffer.value == 0: + raise ctypes.WinError() + lpDisplayName = ctypes.create_string_buffer(cchBuffer.value + 1) + cchBuffer.value = sizeof(lpDisplayName) + success = _GetServiceDisplayNameA(hSCManager, lpServiceName, lpDisplayName, byref(cchBuffer)) + if not success: + raise ctypes.WinError() + return lpDisplayName.value + +def GetServiceDisplayNameW(hSCManager, lpServiceName): + _GetServiceDisplayNameW = windll.advapi32.GetServiceDisplayNameW + _GetServiceDisplayNameW.argtypes = [SC_HANDLE, LPWSTR, LPWSTR, LPDWORD] + _GetServiceDisplayNameW.restype = bool + + cchBuffer = DWORD(0) + _GetServiceDisplayNameW(hSCManager, lpServiceName, None, byref(cchBuffer)) + if cchBuffer.value == 0: + raise ctypes.WinError() + lpDisplayName = ctypes.create_unicode_buffer(cchBuffer.value + 2) + cchBuffer.value = sizeof(lpDisplayName) + success = _GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName, byref(cchBuffer)) + if not success: + raise ctypes.WinError() + return lpDisplayName.value + +GetServiceDisplayName = GuessStringType(GetServiceDisplayNameA, GetServiceDisplayNameW) + +# BOOL WINAPI QueryServiceConfig( +# _In_ SC_HANDLE hService, +# _Out_opt_ LPQUERY_SERVICE_CONFIG lpServiceConfig, +# _In_ DWORD cbBufSize, +# _Out_ LPDWORD pcbBytesNeeded +# ); + +# TO DO + +# BOOL WINAPI QueryServiceConfig2( +# _In_ SC_HANDLE hService, +# _In_ DWORD dwInfoLevel, +# _Out_opt_ LPBYTE lpBuffer, +# _In_ DWORD cbBufSize, +# _Out_ LPDWORD pcbBytesNeeded +# ); + +# TO DO + +# BOOL WINAPI ChangeServiceConfig( +# _In_ SC_HANDLE hService, +# _In_ DWORD dwServiceType, +# _In_ DWORD dwStartType, +# _In_ DWORD dwErrorControl, +# _In_opt_ LPCTSTR lpBinaryPathName, +# _In_opt_ LPCTSTR lpLoadOrderGroup, +# _Out_opt_ LPDWORD lpdwTagId, +# _In_opt_ LPCTSTR lpDependencies, +# _In_opt_ LPCTSTR lpServiceStartName, +# _In_opt_ LPCTSTR lpPassword, +# _In_opt_ LPCTSTR lpDisplayName +# ); + +# TO DO + +# BOOL WINAPI ChangeServiceConfig2( +# _In_ SC_HANDLE hService, +# _In_ DWORD dwInfoLevel, +# _In_opt_ LPVOID lpInfo +# ); + +# TO DO + +# BOOL WINAPI StartService( +# _In_ SC_HANDLE hService, +# _In_ DWORD dwNumServiceArgs, +# _In_opt_ LPCTSTR *lpServiceArgVectors +# ); +def StartServiceA(hService, ServiceArgVectors = None): + _StartServiceA = windll.advapi32.StartServiceA + _StartServiceA.argtypes = [SC_HANDLE, DWORD, LPVOID] + _StartServiceA.restype = bool + _StartServiceA.errcheck = RaiseIfZero + + if ServiceArgVectors: + dwNumServiceArgs = len(ServiceArgVectors) + CServiceArgVectors = (LPSTR * dwNumServiceArgs)(*ServiceArgVectors) + lpServiceArgVectors = ctypes.pointer(CServiceArgVectors) + else: + dwNumServiceArgs = 0 + lpServiceArgVectors = None + _StartServiceA(hService, dwNumServiceArgs, lpServiceArgVectors) + +def StartServiceW(hService, ServiceArgVectors = None): + _StartServiceW = windll.advapi32.StartServiceW + _StartServiceW.argtypes = [SC_HANDLE, DWORD, LPVOID] + _StartServiceW.restype = bool + _StartServiceW.errcheck = RaiseIfZero + + if ServiceArgVectors: + dwNumServiceArgs = len(ServiceArgVectors) + CServiceArgVectors = (LPWSTR * dwNumServiceArgs)(*ServiceArgVectors) + lpServiceArgVectors = ctypes.pointer(CServiceArgVectors) + else: + dwNumServiceArgs = 0 + lpServiceArgVectors = None + _StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors) + +StartService = GuessStringType(StartServiceA, StartServiceW) + +# BOOL WINAPI ControlService( +# _In_ SC_HANDLE hService, +# _In_ DWORD dwControl, +# _Out_ LPSERVICE_STATUS lpServiceStatus +# ); +def ControlService(hService, dwControl): + _ControlService = windll.advapi32.ControlService + _ControlService.argtypes = [SC_HANDLE, DWORD, LPSERVICE_STATUS] + _ControlService.restype = bool + _ControlService.errcheck = RaiseIfZero + + rawServiceStatus = SERVICE_STATUS() + _ControlService(hService, dwControl, byref(rawServiceStatus)) + return ServiceStatus(rawServiceStatus) + +# BOOL WINAPI ControlServiceEx( +# _In_ SC_HANDLE hService, +# _In_ DWORD dwControl, +# _In_ DWORD dwInfoLevel, +# _Inout_ PVOID pControlParams +# ); + +# TO DO + +# DWORD WINAPI NotifyServiceStatusChange( +# _In_ SC_HANDLE hService, +# _In_ DWORD dwNotifyMask, +# _In_ PSERVICE_NOTIFY pNotifyBuffer +# ); + +# TO DO + +# BOOL WINAPI QueryServiceStatus( +# _In_ SC_HANDLE hService, +# _Out_ LPSERVICE_STATUS lpServiceStatus +# ); +def QueryServiceStatus(hService): + _QueryServiceStatus = windll.advapi32.QueryServiceStatus + _QueryServiceStatus.argtypes = [SC_HANDLE, LPSERVICE_STATUS] + _QueryServiceStatus.restype = bool + _QueryServiceStatus.errcheck = RaiseIfZero + + rawServiceStatus = SERVICE_STATUS() + _QueryServiceStatus(hService, byref(rawServiceStatus)) + return ServiceStatus(rawServiceStatus) + +# BOOL WINAPI QueryServiceStatusEx( +# _In_ SC_HANDLE hService, +# _In_ SC_STATUS_TYPE InfoLevel, +# _Out_opt_ LPBYTE lpBuffer, +# _In_ DWORD cbBufSize, +# _Out_ LPDWORD pcbBytesNeeded +# ); +def QueryServiceStatusEx(hService, InfoLevel = SC_STATUS_PROCESS_INFO): + + if InfoLevel != SC_STATUS_PROCESS_INFO: + raise NotImplementedError() + + _QueryServiceStatusEx = windll.advapi32.QueryServiceStatusEx + _QueryServiceStatusEx.argtypes = [SC_HANDLE, SC_STATUS_TYPE, LPVOID, DWORD, LPDWORD] + _QueryServiceStatusEx.restype = bool + _QueryServiceStatusEx.errcheck = RaiseIfZero + + lpBuffer = SERVICE_STATUS_PROCESS() + cbBytesNeeded = DWORD(sizeof(lpBuffer)) + _QueryServiceStatusEx(hService, InfoLevel, byref(lpBuffer), sizeof(lpBuffer), byref(cbBytesNeeded)) + return ServiceStatusProcess(lpBuffer) + +# BOOL WINAPI EnumServicesStatus( +# _In_ SC_HANDLE hSCManager, +# _In_ DWORD dwServiceType, +# _In_ DWORD dwServiceState, +# _Out_opt_ LPENUM_SERVICE_STATUS lpServices, +# _In_ DWORD cbBufSize, +# _Out_ LPDWORD pcbBytesNeeded, +# _Out_ LPDWORD lpServicesReturned, +# _Inout_opt_ LPDWORD lpResumeHandle +# ); +def EnumServicesStatusA(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL): + _EnumServicesStatusA = windll.advapi32.EnumServicesStatusA + _EnumServicesStatusA.argtypes = [SC_HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD] + _EnumServicesStatusA.restype = bool + + cbBytesNeeded = DWORD(0) + ServicesReturned = DWORD(0) + ResumeHandle = DWORD(0) + + _EnumServicesStatusA(hSCManager, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle)) + + Services = [] + success = False + while GetLastError() == ERROR_MORE_DATA: + if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSA): + break + ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value) + success = _EnumServicesStatusA(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle)) + if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSA) * ServicesReturned.value): + raise ctypes.WinError() + lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSA) + for index in compat.xrange(0, ServicesReturned.value): + Services.append( ServiceStatusEntry(lpServicesArray[index]) ) + if success: break + if not success: + raise ctypes.WinError() + + return Services + +def EnumServicesStatusW(hSCManager, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL): + _EnumServicesStatusW = windll.advapi32.EnumServicesStatusW + _EnumServicesStatusW.argtypes = [SC_HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD] + _EnumServicesStatusW.restype = bool + + cbBytesNeeded = DWORD(0) + ServicesReturned = DWORD(0) + ResumeHandle = DWORD(0) + + _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle)) + + Services = [] + success = False + while GetLastError() == ERROR_MORE_DATA: + if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUSW): + break + ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value) + success = _EnumServicesStatusW(hSCManager, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle)) + if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUSW) * ServicesReturned.value): + raise ctypes.WinError() + lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUSW) + for index in compat.xrange(0, ServicesReturned.value): + Services.append( ServiceStatusEntry(lpServicesArray[index]) ) + if success: break + if not success: + raise ctypes.WinError() + + return Services + +EnumServicesStatus = DefaultStringType(EnumServicesStatusA, EnumServicesStatusW) + +# BOOL WINAPI EnumServicesStatusEx( +# _In_ SC_HANDLE hSCManager, +# _In_ SC_ENUM_TYPE InfoLevel, +# _In_ DWORD dwServiceType, +# _In_ DWORD dwServiceState, +# _Out_opt_ LPBYTE lpServices, +# _In_ DWORD cbBufSize, +# _Out_ LPDWORD pcbBytesNeeded, +# _Out_ LPDWORD lpServicesReturned, +# _Inout_opt_ LPDWORD lpResumeHandle, +# _In_opt_ LPCTSTR pszGroupName +# ); +def EnumServicesStatusExA(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None): + + if InfoLevel != SC_ENUM_PROCESS_INFO: + raise NotImplementedError() + + _EnumServicesStatusExA = windll.advapi32.EnumServicesStatusExA + _EnumServicesStatusExA.argtypes = [SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR] + _EnumServicesStatusExA.restype = bool + + cbBytesNeeded = DWORD(0) + ServicesReturned = DWORD(0) + ResumeHandle = DWORD(0) + + _EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle), pszGroupName) + + Services = [] + success = False + while GetLastError() == ERROR_MORE_DATA: + if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSA): + break + ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value) + success = _EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle), pszGroupName) + if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSA) * ServicesReturned.value): + raise ctypes.WinError() + lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSA) + for index in compat.xrange(0, ServicesReturned.value): + Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) ) + if success: break + if not success: + raise ctypes.WinError() + + return Services + +def EnumServicesStatusExW(hSCManager, InfoLevel = SC_ENUM_PROCESS_INFO, dwServiceType = SERVICE_DRIVER | SERVICE_WIN32, dwServiceState = SERVICE_STATE_ALL, pszGroupName = None): + _EnumServicesStatusExW = windll.advapi32.EnumServicesStatusExW + _EnumServicesStatusExW.argtypes = [SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD, LPWSTR] + _EnumServicesStatusExW.restype = bool + + if InfoLevel != SC_ENUM_PROCESS_INFO: + raise NotImplementedError() + + cbBytesNeeded = DWORD(0) + ServicesReturned = DWORD(0) + ResumeHandle = DWORD(0) + + _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, None, 0, byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle), pszGroupName) + + Services = [] + success = False + while GetLastError() == ERROR_MORE_DATA: + if cbBytesNeeded.value < sizeof(ENUM_SERVICE_STATUS_PROCESSW): + break + ServicesBuffer = ctypes.create_string_buffer("", cbBytesNeeded.value) + success = _EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, byref(ServicesBuffer), sizeof(ServicesBuffer), byref(cbBytesNeeded), byref(ServicesReturned), byref(ResumeHandle), pszGroupName) + if sizeof(ServicesBuffer) < (sizeof(ENUM_SERVICE_STATUS_PROCESSW) * ServicesReturned.value): + raise ctypes.WinError() + lpServicesArray = ctypes.cast(ctypes.cast(ctypes.pointer(ServicesBuffer), ctypes.c_void_p), LPENUM_SERVICE_STATUS_PROCESSW) + for index in compat.xrange(0, ServicesReturned.value): + Services.append( ServiceStatusProcessEntry(lpServicesArray[index]) ) + if success: break + if not success: + raise ctypes.WinError() + + return Services + +EnumServicesStatusEx = DefaultStringType(EnumServicesStatusExA, EnumServicesStatusExW) + +# BOOL WINAPI EnumDependentServices( +# _In_ SC_HANDLE hService, +# _In_ DWORD dwServiceState, +# _Out_opt_ LPENUM_SERVICE_STATUS lpServices, +# _In_ DWORD cbBufSize, +# _Out_ LPDWORD pcbBytesNeeded, +# _Out_ LPDWORD lpServicesReturned +# ); + +# TO DO + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/context_amd64.py b/pydevd_attach_to_process/winappdbg/win32/context_amd64.py new file mode 100644 index 0000000..eb786b6 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/context_amd64.py @@ -0,0 +1,762 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +CONTEXT structure for amd64. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.version import ARCH_AMD64 +from winappdbg.win32 import context_i386 + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- CONTEXT structures and constants ----------------------------------------- + +# The following values specify the type of access in the first parameter +# of the exception record when the exception code specifies an access +# violation. +EXCEPTION_READ_FAULT = 0 # exception caused by a read +EXCEPTION_WRITE_FAULT = 1 # exception caused by a write +EXCEPTION_EXECUTE_FAULT = 8 # exception caused by an instruction fetch + +CONTEXT_AMD64 = 0x00100000 + +CONTEXT_CONTROL = (CONTEXT_AMD64 | long(0x1)) +CONTEXT_INTEGER = (CONTEXT_AMD64 | long(0x2)) +CONTEXT_SEGMENTS = (CONTEXT_AMD64 | long(0x4)) +CONTEXT_FLOATING_POINT = (CONTEXT_AMD64 | long(0x8)) +CONTEXT_DEBUG_REGISTERS = (CONTEXT_AMD64 | long(0x10)) + +CONTEXT_MMX_REGISTERS = CONTEXT_FLOATING_POINT + +CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \ + CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS) + +CONTEXT_EXCEPTION_ACTIVE = 0x8000000 +CONTEXT_SERVICE_ACTIVE = 0x10000000 +CONTEXT_EXCEPTION_REQUEST = 0x40000000 +CONTEXT_EXCEPTION_REPORTING = 0x80000000 + +INITIAL_MXCSR = 0x1f80 # initial MXCSR value +INITIAL_FPCSR = 0x027f # initial FPCSR value + +# typedef struct _XMM_SAVE_AREA32 { +# WORD ControlWord; +# WORD StatusWord; +# BYTE TagWord; +# BYTE Reserved1; +# WORD ErrorOpcode; +# DWORD ErrorOffset; +# WORD ErrorSelector; +# WORD Reserved2; +# DWORD DataOffset; +# WORD DataSelector; +# WORD Reserved3; +# DWORD MxCsr; +# DWORD MxCsr_Mask; +# M128A FloatRegisters[8]; +# M128A XmmRegisters[16]; +# BYTE Reserved4[96]; +# } XMM_SAVE_AREA32, *PXMM_SAVE_AREA32; +class XMM_SAVE_AREA32(Structure): + _pack_ = 1 + _fields_ = [ + ('ControlWord', WORD), + ('StatusWord', WORD), + ('TagWord', BYTE), + ('Reserved1', BYTE), + ('ErrorOpcode', WORD), + ('ErrorOffset', DWORD), + ('ErrorSelector', WORD), + ('Reserved2', WORD), + ('DataOffset', DWORD), + ('DataSelector', WORD), + ('Reserved3', WORD), + ('MxCsr', DWORD), + ('MxCsr_Mask', DWORD), + ('FloatRegisters', M128A * 8), + ('XmmRegisters', M128A * 16), + ('Reserved4', BYTE * 96), + ] + + def from_dict(self): + raise NotImplementedError() + + def to_dict(self): + d = dict() + for name, type in self._fields_: + if name in ('FloatRegisters', 'XmmRegisters'): + d[name] = tuple([ (x.LowPart + (x.HighPart << 64)) for x in getattr(self, name) ]) + elif name == 'Reserved4': + d[name] = tuple([ chr(x) for x in getattr(self, name) ]) + else: + d[name] = getattr(self, name) + return d + +LEGACY_SAVE_AREA_LENGTH = sizeof(XMM_SAVE_AREA32) + +PXMM_SAVE_AREA32 = ctypes.POINTER(XMM_SAVE_AREA32) +LPXMM_SAVE_AREA32 = PXMM_SAVE_AREA32 + +# // +# // Context Frame +# // +# // This frame has a several purposes: 1) it is used as an argument to +# // NtContinue, 2) is is used to constuct a call frame for APC delivery, +# // and 3) it is used in the user level thread creation routines. +# // +# // +# // The flags field within this record controls the contents of a CONTEXT +# // record. +# // +# // If the context record is used as an input parameter, then for each +# // portion of the context record controlled by a flag whose value is +# // set, it is assumed that that portion of the context record contains +# // valid context. If the context record is being used to modify a threads +# // context, then only that portion of the threads context is modified. +# // +# // If the context record is used as an output parameter to capture the +# // context of a thread, then only those portions of the thread's context +# // corresponding to set flags will be returned. +# // +# // CONTEXT_CONTROL specifies SegSs, Rsp, SegCs, Rip, and EFlags. +# // +# // CONTEXT_INTEGER specifies Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, and R8-R15. +# // +# // CONTEXT_SEGMENTS specifies SegDs, SegEs, SegFs, and SegGs. +# // +# // CONTEXT_DEBUG_REGISTERS specifies Dr0-Dr3 and Dr6-Dr7. +# // +# // CONTEXT_MMX_REGISTERS specifies the floating point and extended registers +# // Mm0/St0-Mm7/St7 and Xmm0-Xmm15). +# // +# +# typedef struct DECLSPEC_ALIGN(16) _CONTEXT { +# +# // +# // Register parameter home addresses. +# // +# // N.B. These fields are for convience - they could be used to extend the +# // context record in the future. +# // +# +# DWORD64 P1Home; +# DWORD64 P2Home; +# DWORD64 P3Home; +# DWORD64 P4Home; +# DWORD64 P5Home; +# DWORD64 P6Home; +# +# // +# // Control flags. +# // +# +# DWORD ContextFlags; +# DWORD MxCsr; +# +# // +# // Segment Registers and processor flags. +# // +# +# WORD SegCs; +# WORD SegDs; +# WORD SegEs; +# WORD SegFs; +# WORD SegGs; +# WORD SegSs; +# DWORD EFlags; +# +# // +# // Debug registers +# // +# +# DWORD64 Dr0; +# DWORD64 Dr1; +# DWORD64 Dr2; +# DWORD64 Dr3; +# DWORD64 Dr6; +# DWORD64 Dr7; +# +# // +# // Integer registers. +# // +# +# DWORD64 Rax; +# DWORD64 Rcx; +# DWORD64 Rdx; +# DWORD64 Rbx; +# DWORD64 Rsp; +# DWORD64 Rbp; +# DWORD64 Rsi; +# DWORD64 Rdi; +# DWORD64 R8; +# DWORD64 R9; +# DWORD64 R10; +# DWORD64 R11; +# DWORD64 R12; +# DWORD64 R13; +# DWORD64 R14; +# DWORD64 R15; +# +# // +# // Program counter. +# // +# +# DWORD64 Rip; +# +# // +# // Floating point state. +# // +# +# union { +# XMM_SAVE_AREA32 FltSave; +# struct { +# M128A Header[2]; +# M128A Legacy[8]; +# M128A Xmm0; +# M128A Xmm1; +# M128A Xmm2; +# M128A Xmm3; +# M128A Xmm4; +# M128A Xmm5; +# M128A Xmm6; +# M128A Xmm7; +# M128A Xmm8; +# M128A Xmm9; +# M128A Xmm10; +# M128A Xmm11; +# M128A Xmm12; +# M128A Xmm13; +# M128A Xmm14; +# M128A Xmm15; +# }; +# }; +# +# // +# // Vector registers. +# // +# +# M128A VectorRegister[26]; +# DWORD64 VectorControl; +# +# // +# // Special debug control registers. +# // +# +# DWORD64 DebugControl; +# DWORD64 LastBranchToRip; +# DWORD64 LastBranchFromRip; +# DWORD64 LastExceptionToRip; +# DWORD64 LastExceptionFromRip; +# } CONTEXT, *PCONTEXT; + +class _CONTEXT_FLTSAVE_STRUCT(Structure): + _fields_ = [ + ('Header', M128A * 2), + ('Legacy', M128A * 8), + ('Xmm0', M128A), + ('Xmm1', M128A), + ('Xmm2', M128A), + ('Xmm3', M128A), + ('Xmm4', M128A), + ('Xmm5', M128A), + ('Xmm6', M128A), + ('Xmm7', M128A), + ('Xmm8', M128A), + ('Xmm9', M128A), + ('Xmm10', M128A), + ('Xmm11', M128A), + ('Xmm12', M128A), + ('Xmm13', M128A), + ('Xmm14', M128A), + ('Xmm15', M128A), + ] + + def from_dict(self): + raise NotImplementedError() + + def to_dict(self): + d = dict() + for name, type in self._fields_: + if name in ('Header', 'Legacy'): + d[name] = tuple([ (x.Low + (x.High << 64)) for x in getattr(self, name) ]) + else: + x = getattr(self, name) + d[name] = x.Low + (x.High << 64) + return d + +class _CONTEXT_FLTSAVE_UNION(Union): + _fields_ = [ + ('flt', XMM_SAVE_AREA32), + ('xmm', _CONTEXT_FLTSAVE_STRUCT), + ] + + def from_dict(self): + raise NotImplementedError() + + def to_dict(self): + d = dict() + d['flt'] = self.flt.to_dict() + d['xmm'] = self.xmm.to_dict() + return d + +class CONTEXT(Structure): + arch = ARCH_AMD64 + + _pack_ = 16 + _fields_ = [ + + # Register parameter home addresses. + ('P1Home', DWORD64), + ('P2Home', DWORD64), + ('P3Home', DWORD64), + ('P4Home', DWORD64), + ('P5Home', DWORD64), + ('P6Home', DWORD64), + + # Control flags. + ('ContextFlags', DWORD), + ('MxCsr', DWORD), + + # Segment Registers and processor flags. + ('SegCs', WORD), + ('SegDs', WORD), + ('SegEs', WORD), + ('SegFs', WORD), + ('SegGs', WORD), + ('SegSs', WORD), + ('EFlags', DWORD), + + # Debug registers. + ('Dr0', DWORD64), + ('Dr1', DWORD64), + ('Dr2', DWORD64), + ('Dr3', DWORD64), + ('Dr6', DWORD64), + ('Dr7', DWORD64), + + # Integer registers. + ('Rax', DWORD64), + ('Rcx', DWORD64), + ('Rdx', DWORD64), + ('Rbx', DWORD64), + ('Rsp', DWORD64), + ('Rbp', DWORD64), + ('Rsi', DWORD64), + ('Rdi', DWORD64), + ('R8', DWORD64), + ('R9', DWORD64), + ('R10', DWORD64), + ('R11', DWORD64), + ('R12', DWORD64), + ('R13', DWORD64), + ('R14', DWORD64), + ('R15', DWORD64), + + # Program counter. + ('Rip', DWORD64), + + # Floating point state. + ('FltSave', _CONTEXT_FLTSAVE_UNION), + + # Vector registers. + ('VectorRegister', M128A * 26), + ('VectorControl', DWORD64), + + # Special debug control registers. + ('DebugControl', DWORD64), + ('LastBranchToRip', DWORD64), + ('LastBranchFromRip', DWORD64), + ('LastExceptionToRip', DWORD64), + ('LastExceptionFromRip', DWORD64), + ] + + _others = ('P1Home', 'P2Home', 'P3Home', 'P4Home', 'P5Home', 'P6Home', \ + 'MxCsr', 'VectorRegister', 'VectorControl') + _control = ('SegSs', 'Rsp', 'SegCs', 'Rip', 'EFlags') + _integer = ('Rax', 'Rcx', 'Rdx', 'Rbx', 'Rsp', 'Rbp', 'Rsi', 'Rdi', \ + 'R8', 'R9', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15') + _segments = ('SegDs', 'SegEs', 'SegFs', 'SegGs') + _debug = ('Dr0', 'Dr1', 'Dr2', 'Dr3', 'Dr6', 'Dr7', \ + 'DebugControl', 'LastBranchToRip', 'LastBranchFromRip', \ + 'LastExceptionToRip', 'LastExceptionFromRip') + _mmx = ('Xmm0', 'Xmm1', 'Xmm2', 'Xmm3', 'Xmm4', 'Xmm5', 'Xmm6', 'Xmm7', \ + 'Xmm8', 'Xmm9', 'Xmm10', 'Xmm11', 'Xmm12', 'Xmm13', 'Xmm14', 'Xmm15') + + # XXX TODO + # Convert VectorRegister and Xmm0-Xmm15 to pure Python types! + + @classmethod + def from_dict(cls, ctx): + 'Instance a new structure from a Python native type.' + ctx = Context(ctx) + s = cls() + ContextFlags = ctx['ContextFlags'] + s.ContextFlags = ContextFlags + for key in cls._others: + if key != 'VectorRegister': + setattr(s, key, ctx[key]) + else: + w = ctx[key] + v = (M128A * len(w))() + i = 0 + for x in w: + y = M128A() + y.High = x >> 64 + y.Low = x - (x >> 64) + v[i] = y + i += 1 + setattr(s, key, v) + if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL: + for key in cls._control: + setattr(s, key, ctx[key]) + if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER: + for key in cls._integer: + setattr(s, key, ctx[key]) + if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS: + for key in cls._segments: + setattr(s, key, ctx[key]) + if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS: + for key in cls._debug: + setattr(s, key, ctx[key]) + if (ContextFlags & CONTEXT_MMX_REGISTERS) == CONTEXT_MMX_REGISTERS: + xmm = s.FltSave.xmm + for key in cls._mmx: + y = M128A() + y.High = x >> 64 + y.Low = x - (x >> 64) + setattr(xmm, key, y) + return s + + def to_dict(self): + 'Convert a structure into a Python dictionary.' + ctx = Context() + ContextFlags = self.ContextFlags + ctx['ContextFlags'] = ContextFlags + for key in self._others: + if key != 'VectorRegister': + ctx[key] = getattr(self, key) + else: + ctx[key] = tuple([ (x.Low + (x.High << 64)) for x in getattr(self, key) ]) + if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL: + for key in self._control: + ctx[key] = getattr(self, key) + if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER: + for key in self._integer: + ctx[key] = getattr(self, key) + if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS: + for key in self._segments: + ctx[key] = getattr(self, key) + if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS: + for key in self._debug: + ctx[key] = getattr(self, key) + if (ContextFlags & CONTEXT_MMX_REGISTERS) == CONTEXT_MMX_REGISTERS: + xmm = self.FltSave.xmm.to_dict() + for key in self._mmx: + ctx[key] = xmm.get(key) + return ctx + +PCONTEXT = ctypes.POINTER(CONTEXT) +LPCONTEXT = PCONTEXT + +class Context(dict): + """ + Register context dictionary for the amd64 architecture. + """ + + arch = CONTEXT.arch + + def __get_pc(self): + return self['Rip'] + def __set_pc(self, value): + self['Rip'] = value + pc = property(__get_pc, __set_pc) + + def __get_sp(self): + return self['Rsp'] + def __set_sp(self, value): + self['Rsp'] = value + sp = property(__get_sp, __set_sp) + + def __get_fp(self): + return self['Rbp'] + def __set_fp(self, value): + self['Rbp'] = value + fp = property(__get_fp, __set_fp) + +#--- LDT_ENTRY structure ------------------------------------------------------ + +# typedef struct _LDT_ENTRY { +# WORD LimitLow; +# WORD BaseLow; +# union { +# struct { +# BYTE BaseMid; +# BYTE Flags1; +# BYTE Flags2; +# BYTE BaseHi; +# } Bytes; +# struct { +# DWORD BaseMid :8; +# DWORD Type :5; +# DWORD Dpl :2; +# DWORD Pres :1; +# DWORD LimitHi :4; +# DWORD Sys :1; +# DWORD Reserved_0 :1; +# DWORD Default_Big :1; +# DWORD Granularity :1; +# DWORD BaseHi :8; +# } Bits; +# } HighWord; +# } LDT_ENTRY, +# *PLDT_ENTRY; + +class _LDT_ENTRY_BYTES_(Structure): + _pack_ = 1 + _fields_ = [ + ('BaseMid', BYTE), + ('Flags1', BYTE), + ('Flags2', BYTE), + ('BaseHi', BYTE), + ] + +class _LDT_ENTRY_BITS_(Structure): + _pack_ = 1 + _fields_ = [ + ('BaseMid', DWORD, 8), + ('Type', DWORD, 5), + ('Dpl', DWORD, 2), + ('Pres', DWORD, 1), + ('LimitHi', DWORD, 4), + ('Sys', DWORD, 1), + ('Reserved_0', DWORD, 1), + ('Default_Big', DWORD, 1), + ('Granularity', DWORD, 1), + ('BaseHi', DWORD, 8), + ] + +class _LDT_ENTRY_HIGHWORD_(Union): + _pack_ = 1 + _fields_ = [ + ('Bytes', _LDT_ENTRY_BYTES_), + ('Bits', _LDT_ENTRY_BITS_), + ] + +class LDT_ENTRY(Structure): + _pack_ = 1 + _fields_ = [ + ('LimitLow', WORD), + ('BaseLow', WORD), + ('HighWord', _LDT_ENTRY_HIGHWORD_), + ] + +PLDT_ENTRY = POINTER(LDT_ENTRY) +LPLDT_ENTRY = PLDT_ENTRY + +#--- WOW64 CONTEXT structure and constants ------------------------------------ + +# Value of SegCs in a Wow64 thread when running in 32 bits mode +WOW64_CS32 = 0x23 + +WOW64_CONTEXT_i386 = long(0x00010000) +WOW64_CONTEXT_i486 = long(0x00010000) + +WOW64_CONTEXT_CONTROL = (WOW64_CONTEXT_i386 | long(0x00000001)) +WOW64_CONTEXT_INTEGER = (WOW64_CONTEXT_i386 | long(0x00000002)) +WOW64_CONTEXT_SEGMENTS = (WOW64_CONTEXT_i386 | long(0x00000004)) +WOW64_CONTEXT_FLOATING_POINT = (WOW64_CONTEXT_i386 | long(0x00000008)) +WOW64_CONTEXT_DEBUG_REGISTERS = (WOW64_CONTEXT_i386 | long(0x00000010)) +WOW64_CONTEXT_EXTENDED_REGISTERS = (WOW64_CONTEXT_i386 | long(0x00000020)) + +WOW64_CONTEXT_FULL = (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS) +WOW64_CONTEXT_ALL = (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS | WOW64_CONTEXT_FLOATING_POINT | WOW64_CONTEXT_DEBUG_REGISTERS | WOW64_CONTEXT_EXTENDED_REGISTERS) + +WOW64_SIZE_OF_80387_REGISTERS = 80 +WOW64_MAXIMUM_SUPPORTED_EXTENSION = 512 + +class WOW64_FLOATING_SAVE_AREA (context_i386.FLOATING_SAVE_AREA): + pass + +class WOW64_CONTEXT (context_i386.CONTEXT): + pass + +class WOW64_LDT_ENTRY (context_i386.LDT_ENTRY): + pass + +PWOW64_FLOATING_SAVE_AREA = POINTER(WOW64_FLOATING_SAVE_AREA) +PWOW64_CONTEXT = POINTER(WOW64_CONTEXT) +PWOW64_LDT_ENTRY = POINTER(WOW64_LDT_ENTRY) + +############################################################################### + +# BOOL WINAPI GetThreadSelectorEntry( +# __in HANDLE hThread, +# __in DWORD dwSelector, +# __out LPLDT_ENTRY lpSelectorEntry +# ); +def GetThreadSelectorEntry(hThread, dwSelector): + _GetThreadSelectorEntry = windll.kernel32.GetThreadSelectorEntry + _GetThreadSelectorEntry.argtypes = [HANDLE, DWORD, LPLDT_ENTRY] + _GetThreadSelectorEntry.restype = bool + _GetThreadSelectorEntry.errcheck = RaiseIfZero + + ldt = LDT_ENTRY() + _GetThreadSelectorEntry(hThread, dwSelector, byref(ldt)) + return ldt + +# BOOL WINAPI GetThreadContext( +# __in HANDLE hThread, +# __inout LPCONTEXT lpContext +# ); +def GetThreadContext(hThread, ContextFlags = None, raw = False): + _GetThreadContext = windll.kernel32.GetThreadContext + _GetThreadContext.argtypes = [HANDLE, LPCONTEXT] + _GetThreadContext.restype = bool + _GetThreadContext.errcheck = RaiseIfZero + + if ContextFlags is None: + ContextFlags = CONTEXT_ALL | CONTEXT_AMD64 + Context = CONTEXT() + Context.ContextFlags = ContextFlags + _GetThreadContext(hThread, byref(Context)) + if raw: + return Context + return Context.to_dict() + +# BOOL WINAPI SetThreadContext( +# __in HANDLE hThread, +# __in const CONTEXT* lpContext +# ); +def SetThreadContext(hThread, lpContext): + _SetThreadContext = windll.kernel32.SetThreadContext + _SetThreadContext.argtypes = [HANDLE, LPCONTEXT] + _SetThreadContext.restype = bool + _SetThreadContext.errcheck = RaiseIfZero + + if isinstance(lpContext, dict): + lpContext = CONTEXT.from_dict(lpContext) + _SetThreadContext(hThread, byref(lpContext)) + +# BOOL Wow64GetThreadSelectorEntry( +# __in HANDLE hThread, +# __in DWORD dwSelector, +# __out PWOW64_LDT_ENTRY lpSelectorEntry +# ); +def Wow64GetThreadSelectorEntry(hThread, dwSelector): + _Wow64GetThreadSelectorEntry = windll.kernel32.Wow64GetThreadSelectorEntry + _Wow64GetThreadSelectorEntry.argtypes = [HANDLE, DWORD, PWOW64_LDT_ENTRY] + _Wow64GetThreadSelectorEntry.restype = bool + _Wow64GetThreadSelectorEntry.errcheck = RaiseIfZero + + lpSelectorEntry = WOW64_LDT_ENTRY() + _Wow64GetThreadSelectorEntry(hThread, dwSelector, byref(lpSelectorEntry)) + return lpSelectorEntry + +# DWORD WINAPI Wow64ResumeThread( +# __in HANDLE hThread +# ); +def Wow64ResumeThread(hThread): + _Wow64ResumeThread = windll.kernel32.Wow64ResumeThread + _Wow64ResumeThread.argtypes = [HANDLE] + _Wow64ResumeThread.restype = DWORD + + previousCount = _Wow64ResumeThread(hThread) + if previousCount == DWORD(-1).value: + raise ctypes.WinError() + return previousCount + +# DWORD WINAPI Wow64SuspendThread( +# __in HANDLE hThread +# ); +def Wow64SuspendThread(hThread): + _Wow64SuspendThread = windll.kernel32.Wow64SuspendThread + _Wow64SuspendThread.argtypes = [HANDLE] + _Wow64SuspendThread.restype = DWORD + + previousCount = _Wow64SuspendThread(hThread) + if previousCount == DWORD(-1).value: + raise ctypes.WinError() + return previousCount + +# XXX TODO Use this http://www.nynaeve.net/Code/GetThreadWow64Context.cpp +# Also see http://www.woodmann.com/forum/archive/index.php/t-11162.html + +# BOOL WINAPI Wow64GetThreadContext( +# __in HANDLE hThread, +# __inout PWOW64_CONTEXT lpContext +# ); +def Wow64GetThreadContext(hThread, ContextFlags = None): + _Wow64GetThreadContext = windll.kernel32.Wow64GetThreadContext + _Wow64GetThreadContext.argtypes = [HANDLE, PWOW64_CONTEXT] + _Wow64GetThreadContext.restype = bool + _Wow64GetThreadContext.errcheck = RaiseIfZero + + # XXX doesn't exist in XP 64 bits + + Context = WOW64_CONTEXT() + if ContextFlags is None: + Context.ContextFlags = WOW64_CONTEXT_ALL | WOW64_CONTEXT_i386 + else: + Context.ContextFlags = ContextFlags + _Wow64GetThreadContext(hThread, byref(Context)) + return Context.to_dict() + +# BOOL WINAPI Wow64SetThreadContext( +# __in HANDLE hThread, +# __in const WOW64_CONTEXT *lpContext +# ); +def Wow64SetThreadContext(hThread, lpContext): + _Wow64SetThreadContext = windll.kernel32.Wow64SetThreadContext + _Wow64SetThreadContext.argtypes = [HANDLE, PWOW64_CONTEXT] + _Wow64SetThreadContext.restype = bool + _Wow64SetThreadContext.errcheck = RaiseIfZero + + # XXX doesn't exist in XP 64 bits + + if isinstance(lpContext, dict): + lpContext = WOW64_CONTEXT.from_dict(lpContext) + _Wow64SetThreadContext(hThread, byref(lpContext)) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/context_i386.py b/pydevd_attach_to_process/winappdbg/win32/context_i386.py new file mode 100644 index 0000000..91ff2d9 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/context_i386.py @@ -0,0 +1,449 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +CONTEXT structure for i386. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.version import ARCH_I386 + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- CONTEXT structures and constants ----------------------------------------- + +# The following values specify the type of access in the first parameter +# of the exception record when the exception code specifies an access +# violation. +EXCEPTION_READ_FAULT = 0 # exception caused by a read +EXCEPTION_WRITE_FAULT = 1 # exception caused by a write +EXCEPTION_EXECUTE_FAULT = 8 # exception caused by an instruction fetch + +CONTEXT_i386 = 0x00010000 # this assumes that i386 and +CONTEXT_i486 = 0x00010000 # i486 have identical context records + +CONTEXT_CONTROL = (CONTEXT_i386 | long(0x00000001)) # SS:SP, CS:IP, FLAGS, BP +CONTEXT_INTEGER = (CONTEXT_i386 | long(0x00000002)) # AX, BX, CX, DX, SI, DI +CONTEXT_SEGMENTS = (CONTEXT_i386 | long(0x00000004)) # DS, ES, FS, GS +CONTEXT_FLOATING_POINT = (CONTEXT_i386 | long(0x00000008)) # 387 state +CONTEXT_DEBUG_REGISTERS = (CONTEXT_i386 | long(0x00000010)) # DB 0-3,6,7 +CONTEXT_EXTENDED_REGISTERS = (CONTEXT_i386 | long(0x00000020)) # cpu specific extensions + +CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) + +CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \ + CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | \ + CONTEXT_EXTENDED_REGISTERS) + +SIZE_OF_80387_REGISTERS = 80 +MAXIMUM_SUPPORTED_EXTENSION = 512 + +# typedef struct _FLOATING_SAVE_AREA { +# DWORD ControlWord; +# DWORD StatusWord; +# DWORD TagWord; +# DWORD ErrorOffset; +# DWORD ErrorSelector; +# DWORD DataOffset; +# DWORD DataSelector; +# BYTE RegisterArea[SIZE_OF_80387_REGISTERS]; +# DWORD Cr0NpxState; +# } FLOATING_SAVE_AREA; +class FLOATING_SAVE_AREA(Structure): + _pack_ = 1 + _fields_ = [ + ('ControlWord', DWORD), + ('StatusWord', DWORD), + ('TagWord', DWORD), + ('ErrorOffset', DWORD), + ('ErrorSelector', DWORD), + ('DataOffset', DWORD), + ('DataSelector', DWORD), + ('RegisterArea', BYTE * SIZE_OF_80387_REGISTERS), + ('Cr0NpxState', DWORD), + ] + + _integer_members = ('ControlWord', 'StatusWord', 'TagWord', 'ErrorOffset', 'ErrorSelector', 'DataOffset', 'DataSelector', 'Cr0NpxState') + + @classmethod + def from_dict(cls, fsa): + 'Instance a new structure from a Python dictionary.' + fsa = dict(fsa) + s = cls() + for key in cls._integer_members: + setattr(s, key, fsa.get(key)) + ra = fsa.get('RegisterArea', None) + if ra is not None: + for index in compat.xrange(0, SIZE_OF_80387_REGISTERS): + s.RegisterArea[index] = ra[index] + return s + + def to_dict(self): + 'Convert a structure into a Python dictionary.' + fsa = dict() + for key in self._integer_members: + fsa[key] = getattr(self, key) + ra = [ self.RegisterArea[index] for index in compat.xrange(0, SIZE_OF_80387_REGISTERS) ] + ra = tuple(ra) + fsa['RegisterArea'] = ra + return fsa + +PFLOATING_SAVE_AREA = POINTER(FLOATING_SAVE_AREA) +LPFLOATING_SAVE_AREA = PFLOATING_SAVE_AREA + +# typedef struct _CONTEXT { +# DWORD ContextFlags; +# DWORD Dr0; +# DWORD Dr1; +# DWORD Dr2; +# DWORD Dr3; +# DWORD Dr6; +# DWORD Dr7; +# FLOATING_SAVE_AREA FloatSave; +# DWORD SegGs; +# DWORD SegFs; +# DWORD SegEs; +# DWORD SegDs; +# DWORD Edi; +# DWORD Esi; +# DWORD Ebx; +# DWORD Edx; +# DWORD Ecx; +# DWORD Eax; +# DWORD Ebp; +# DWORD Eip; +# DWORD SegCs; +# DWORD EFlags; +# DWORD Esp; +# DWORD SegSs; +# BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; +# } CONTEXT; +class CONTEXT(Structure): + arch = ARCH_I386 + + _pack_ = 1 + + # Context Frame + # + # This frame has a several purposes: 1) it is used as an argument to + # NtContinue, 2) is is used to constuct a call frame for APC delivery, + # and 3) it is used in the user level thread creation routines. + # + # The layout of the record conforms to a standard call frame. + + _fields_ = [ + + # The flags values within this flag control the contents of + # a CONTEXT record. + # + # If the context record is used as an input parameter, then + # for each portion of the context record controlled by a flag + # whose value is set, it is assumed that that portion of the + # context record contains valid context. If the context record + # is being used to modify a threads context, then only that + # portion of the threads context will be modified. + # + # If the context record is used as an IN OUT parameter to capture + # the context of a thread, then only those portions of the thread's + # context corresponding to set flags will be returned. + # + # The context record is never used as an OUT only parameter. + + ('ContextFlags', DWORD), + + # This section is specified/returned if CONTEXT_DEBUG_REGISTERS is + # set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT + # included in CONTEXT_FULL. + + ('Dr0', DWORD), + ('Dr1', DWORD), + ('Dr2', DWORD), + ('Dr3', DWORD), + ('Dr6', DWORD), + ('Dr7', DWORD), + + # This section is specified/returned if the + # ContextFlags word contains the flag CONTEXT_FLOATING_POINT. + + ('FloatSave', FLOATING_SAVE_AREA), + + # This section is specified/returned if the + # ContextFlags word contains the flag CONTEXT_SEGMENTS. + + ('SegGs', DWORD), + ('SegFs', DWORD), + ('SegEs', DWORD), + ('SegDs', DWORD), + + # This section is specified/returned if the + # ContextFlags word contains the flag CONTEXT_INTEGER. + + ('Edi', DWORD), + ('Esi', DWORD), + ('Ebx', DWORD), + ('Edx', DWORD), + ('Ecx', DWORD), + ('Eax', DWORD), + + # This section is specified/returned if the + # ContextFlags word contains the flag CONTEXT_CONTROL. + + ('Ebp', DWORD), + ('Eip', DWORD), + ('SegCs', DWORD), # MUST BE SANITIZED + ('EFlags', DWORD), # MUST BE SANITIZED + ('Esp', DWORD), + ('SegSs', DWORD), + + # This section is specified/returned if the ContextFlags word + # contains the flag CONTEXT_EXTENDED_REGISTERS. + # The format and contexts are processor specific. + + ('ExtendedRegisters', BYTE * MAXIMUM_SUPPORTED_EXTENSION), + ] + + _ctx_debug = ('Dr0', 'Dr1', 'Dr2', 'Dr3', 'Dr6', 'Dr7') + _ctx_segs = ('SegGs', 'SegFs', 'SegEs', 'SegDs', ) + _ctx_int = ('Edi', 'Esi', 'Ebx', 'Edx', 'Ecx', 'Eax') + _ctx_ctrl = ('Ebp', 'Eip', 'SegCs', 'EFlags', 'Esp', 'SegSs') + + @classmethod + def from_dict(cls, ctx): + 'Instance a new structure from a Python dictionary.' + ctx = Context(ctx) + s = cls() + ContextFlags = ctx['ContextFlags'] + setattr(s, 'ContextFlags', ContextFlags) + if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS: + for key in s._ctx_debug: + setattr(s, key, ctx[key]) + if (ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT: + fsa = ctx['FloatSave'] + s.FloatSave = FLOATING_SAVE_AREA.from_dict(fsa) + if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS: + for key in s._ctx_segs: + setattr(s, key, ctx[key]) + if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER: + for key in s._ctx_int: + setattr(s, key, ctx[key]) + if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL: + for key in s._ctx_ctrl: + setattr(s, key, ctx[key]) + if (ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS: + er = ctx['ExtendedRegisters'] + for index in compat.xrange(0, MAXIMUM_SUPPORTED_EXTENSION): + s.ExtendedRegisters[index] = er[index] + return s + + def to_dict(self): + 'Convert a structure into a Python native type.' + ctx = Context() + ContextFlags = self.ContextFlags + ctx['ContextFlags'] = ContextFlags + if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS: + for key in self._ctx_debug: + ctx[key] = getattr(self, key) + if (ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT: + ctx['FloatSave'] = self.FloatSave.to_dict() + if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS: + for key in self._ctx_segs: + ctx[key] = getattr(self, key) + if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER: + for key in self._ctx_int: + ctx[key] = getattr(self, key) + if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL: + for key in self._ctx_ctrl: + ctx[key] = getattr(self, key) + if (ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS: + er = [ self.ExtendedRegisters[index] for index in compat.xrange(0, MAXIMUM_SUPPORTED_EXTENSION) ] + er = tuple(er) + ctx['ExtendedRegisters'] = er + return ctx + +PCONTEXT = POINTER(CONTEXT) +LPCONTEXT = PCONTEXT + +class Context(dict): + """ + Register context dictionary for the i386 architecture. + """ + + arch = CONTEXT.arch + + def __get_pc(self): + return self['Eip'] + def __set_pc(self, value): + self['Eip'] = value + pc = property(__get_pc, __set_pc) + + def __get_sp(self): + return self['Esp'] + def __set_sp(self, value): + self['Esp'] = value + sp = property(__get_sp, __set_sp) + + def __get_fp(self): + return self['Ebp'] + def __set_fp(self, value): + self['Ebp'] = value + fp = property(__get_fp, __set_fp) + +#--- LDT_ENTRY structure ------------------------------------------------------ + +# typedef struct _LDT_ENTRY { +# WORD LimitLow; +# WORD BaseLow; +# union { +# struct { +# BYTE BaseMid; +# BYTE Flags1; +# BYTE Flags2; +# BYTE BaseHi; +# } Bytes; +# struct { +# DWORD BaseMid :8; +# DWORD Type :5; +# DWORD Dpl :2; +# DWORD Pres :1; +# DWORD LimitHi :4; +# DWORD Sys :1; +# DWORD Reserved_0 :1; +# DWORD Default_Big :1; +# DWORD Granularity :1; +# DWORD BaseHi :8; +# } Bits; +# } HighWord; +# } LDT_ENTRY, +# *PLDT_ENTRY; + +class _LDT_ENTRY_BYTES_(Structure): + _pack_ = 1 + _fields_ = [ + ('BaseMid', BYTE), + ('Flags1', BYTE), + ('Flags2', BYTE), + ('BaseHi', BYTE), + ] + +class _LDT_ENTRY_BITS_(Structure): + _pack_ = 1 + _fields_ = [ + ('BaseMid', DWORD, 8), + ('Type', DWORD, 5), + ('Dpl', DWORD, 2), + ('Pres', DWORD, 1), + ('LimitHi', DWORD, 4), + ('Sys', DWORD, 1), + ('Reserved_0', DWORD, 1), + ('Default_Big', DWORD, 1), + ('Granularity', DWORD, 1), + ('BaseHi', DWORD, 8), + ] + +class _LDT_ENTRY_HIGHWORD_(Union): + _pack_ = 1 + _fields_ = [ + ('Bytes', _LDT_ENTRY_BYTES_), + ('Bits', _LDT_ENTRY_BITS_), + ] + +class LDT_ENTRY(Structure): + _pack_ = 1 + _fields_ = [ + ('LimitLow', WORD), + ('BaseLow', WORD), + ('HighWord', _LDT_ENTRY_HIGHWORD_), + ] + +PLDT_ENTRY = POINTER(LDT_ENTRY) +LPLDT_ENTRY = PLDT_ENTRY + +############################################################################### + +# BOOL WINAPI GetThreadSelectorEntry( +# __in HANDLE hThread, +# __in DWORD dwSelector, +# __out LPLDT_ENTRY lpSelectorEntry +# ); +def GetThreadSelectorEntry(hThread, dwSelector): + _GetThreadSelectorEntry = windll.kernel32.GetThreadSelectorEntry + _GetThreadSelectorEntry.argtypes = [HANDLE, DWORD, LPLDT_ENTRY] + _GetThreadSelectorEntry.restype = bool + _GetThreadSelectorEntry.errcheck = RaiseIfZero + + ldt = LDT_ENTRY() + _GetThreadSelectorEntry(hThread, dwSelector, byref(ldt)) + return ldt + +# BOOL WINAPI GetThreadContext( +# __in HANDLE hThread, +# __inout LPCONTEXT lpContext +# ); +def GetThreadContext(hThread, ContextFlags = None, raw = False): + _GetThreadContext = windll.kernel32.GetThreadContext + _GetThreadContext.argtypes = [HANDLE, LPCONTEXT] + _GetThreadContext.restype = bool + _GetThreadContext.errcheck = RaiseIfZero + + if ContextFlags is None: + ContextFlags = CONTEXT_ALL | CONTEXT_i386 + Context = CONTEXT() + Context.ContextFlags = ContextFlags + _GetThreadContext(hThread, byref(Context)) + if raw: + return Context + return Context.to_dict() + +# BOOL WINAPI SetThreadContext( +# __in HANDLE hThread, +# __in const CONTEXT* lpContext +# ); +def SetThreadContext(hThread, lpContext): + _SetThreadContext = windll.kernel32.SetThreadContext + _SetThreadContext.argtypes = [HANDLE, LPCONTEXT] + _SetThreadContext.restype = bool + _SetThreadContext.errcheck = RaiseIfZero + + if isinstance(lpContext, dict): + lpContext = CONTEXT.from_dict(lpContext) + _SetThreadContext(hThread, byref(lpContext)) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/dbghelp.py b/pydevd_attach_to_process/winappdbg/win32/dbghelp.py new file mode 100644 index 0000000..17c843e --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/dbghelp.py @@ -0,0 +1,1277 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for dbghelp.dll in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.version import * +from winappdbg.win32.kernel32 import * + +# DbgHelp versions and features list: +# http://msdn.microsoft.com/en-us/library/windows/desktop/ms679294(v=vs.85).aspx + +#------------------------------------------------------------------------------ +# Tries to load the newest version of dbghelp.dll if available. + +def _load_latest_dbghelp_dll(): + + from os import getenv + from os.path import join, exists + + program_files_location = getenv("ProgramFiles") + if not program_files_location: + program_files_location = "C:\\Program Files" + + program_files_x86_location = getenv("ProgramFiles(x86)") + + if arch == ARCH_AMD64: + if wow64: + pathname = join( + program_files_x86_location or program_files_location, + "Debugging Tools for Windows (x86)", + "dbghelp.dll") + else: + pathname = join( + program_files_location, + "Debugging Tools for Windows (x64)", + "dbghelp.dll") + elif arch == ARCH_I386: + pathname = join( + program_files_location, + "Debugging Tools for Windows (x86)", + "dbghelp.dll") + else: + pathname = None + + if pathname and exists(pathname): + try: + _dbghelp = ctypes.windll.LoadLibrary(pathname) + ctypes.windll.dbghelp = _dbghelp + except Exception: + pass + +_load_latest_dbghelp_dll() + +# Recover the old binding of the "os" symbol. +# XXX FIXME not sure if I really need to do this! +##from version import os + +#------------------------------------------------------------------------------ + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +# SymGetHomeDirectory "type" values +hdBase = 0 +hdSym = 1 +hdSrc = 2 + +UNDNAME_32_BIT_DECODE = 0x0800 +UNDNAME_COMPLETE = 0x0000 +UNDNAME_NAME_ONLY = 0x1000 +UNDNAME_NO_ACCESS_SPECIFIERS = 0x0080 +UNDNAME_NO_ALLOCATION_LANGUAGE = 0x0010 +UNDNAME_NO_ALLOCATION_MODEL = 0x0008 +UNDNAME_NO_ARGUMENTS = 0x2000 +UNDNAME_NO_CV_THISTYPE = 0x0040 +UNDNAME_NO_FUNCTION_RETURNS = 0x0004 +UNDNAME_NO_LEADING_UNDERSCORES = 0x0001 +UNDNAME_NO_MEMBER_TYPE = 0x0200 +UNDNAME_NO_MS_KEYWORDS = 0x0002 +UNDNAME_NO_MS_THISTYPE = 0x0020 +UNDNAME_NO_RETURN_UDT_MODEL = 0x0400 +UNDNAME_NO_SPECIAL_SYMS = 0x4000 +UNDNAME_NO_THISTYPE = 0x0060 +UNDNAME_NO_THROW_SIGNATURES = 0x0100 + +#--- IMAGEHLP_MODULE structure and related ------------------------------------ + +SYMOPT_ALLOW_ABSOLUTE_SYMBOLS = 0x00000800 +SYMOPT_ALLOW_ZERO_ADDRESS = 0x01000000 +SYMOPT_AUTO_PUBLICS = 0x00010000 +SYMOPT_CASE_INSENSITIVE = 0x00000001 +SYMOPT_DEBUG = 0x80000000 +SYMOPT_DEFERRED_LOADS = 0x00000004 +SYMOPT_DISABLE_SYMSRV_AUTODETECT = 0x02000000 +SYMOPT_EXACT_SYMBOLS = 0x00000400 +SYMOPT_FAIL_CRITICAL_ERRORS = 0x00000200 +SYMOPT_FAVOR_COMPRESSED = 0x00800000 +SYMOPT_FLAT_DIRECTORY = 0x00400000 +SYMOPT_IGNORE_CVREC = 0x00000080 +SYMOPT_IGNORE_IMAGEDIR = 0x00200000 +SYMOPT_IGNORE_NT_SYMPATH = 0x00001000 +SYMOPT_INCLUDE_32BIT_MODULES = 0x00002000 +SYMOPT_LOAD_ANYTHING = 0x00000040 +SYMOPT_LOAD_LINES = 0x00000010 +SYMOPT_NO_CPP = 0x00000008 +SYMOPT_NO_IMAGE_SEARCH = 0x00020000 +SYMOPT_NO_PROMPTS = 0x00080000 +SYMOPT_NO_PUBLICS = 0x00008000 +SYMOPT_NO_UNQUALIFIED_LOADS = 0x00000100 +SYMOPT_OVERWRITE = 0x00100000 +SYMOPT_PUBLICS_ONLY = 0x00004000 +SYMOPT_SECURE = 0x00040000 +SYMOPT_UNDNAME = 0x00000002 + +##SSRVOPT_DWORD +##SSRVOPT_DWORDPTR +##SSRVOPT_GUIDPTR +## +##SSRVOPT_CALLBACK +##SSRVOPT_DOWNSTREAM_STORE +##SSRVOPT_FLAT_DEFAULT_STORE +##SSRVOPT_FAVOR_COMPRESSED +##SSRVOPT_NOCOPY +##SSRVOPT_OVERWRITE +##SSRVOPT_PARAMTYPE +##SSRVOPT_PARENTWIN +##SSRVOPT_PROXY +##SSRVOPT_RESET +##SSRVOPT_SECURE +##SSRVOPT_SETCONTEXT +##SSRVOPT_TRACE +##SSRVOPT_UNATTENDED + +# typedef enum +# { +# SymNone = 0, +# SymCoff, +# SymCv, +# SymPdb, +# SymExport, +# SymDeferred, +# SymSym, +# SymDia, +# SymVirtual, +# NumSymTypes +# } SYM_TYPE; +SymNone = 0 +SymCoff = 1 +SymCv = 2 +SymPdb = 3 +SymExport = 4 +SymDeferred = 5 +SymSym = 6 +SymDia = 7 +SymVirtual = 8 +NumSymTypes = 9 + +# typedef struct _IMAGEHLP_MODULE64 { +# DWORD SizeOfStruct; +# DWORD64 BaseOfImage; +# DWORD ImageSize; +# DWORD TimeDateStamp; +# DWORD CheckSum; +# DWORD NumSyms; +# SYM_TYPE SymType; +# TCHAR ModuleName[32]; +# TCHAR ImageName[256]; +# TCHAR LoadedImageName[256]; +# TCHAR LoadedPdbName[256]; +# DWORD CVSig; +# TCHAR CVData[MAX_PATH*3]; +# DWORD PdbSig; +# GUID PdbSig70; +# DWORD PdbAge; +# BOOL PdbUnmatched; +# BOOL DbgUnmatched; +# BOOL LineNumbers; +# BOOL GlobalSymbols; +# BOOL TypeInfo; +# BOOL SourceIndexed; +# BOOL Publics; +# } IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64; + +class IMAGEHLP_MODULE (Structure): + _fields_ = [ + ("SizeOfStruct", DWORD), + ("BaseOfImage", DWORD), + ("ImageSize", DWORD), + ("TimeDateStamp", DWORD), + ("CheckSum", DWORD), + ("NumSyms", DWORD), + ("SymType", DWORD), # SYM_TYPE + ("ModuleName", CHAR * 32), + ("ImageName", CHAR * 256), + ("LoadedImageName", CHAR * 256), + ] +PIMAGEHLP_MODULE = POINTER(IMAGEHLP_MODULE) + +class IMAGEHLP_MODULE64 (Structure): + _fields_ = [ + ("SizeOfStruct", DWORD), + ("BaseOfImage", DWORD64), + ("ImageSize", DWORD), + ("TimeDateStamp", DWORD), + ("CheckSum", DWORD), + ("NumSyms", DWORD), + ("SymType", DWORD), # SYM_TYPE + ("ModuleName", CHAR * 32), + ("ImageName", CHAR * 256), + ("LoadedImageName", CHAR * 256), + ("LoadedPdbName", CHAR * 256), + ("CVSig", DWORD), + ("CVData", CHAR * (MAX_PATH * 3)), + ("PdbSig", DWORD), + ("PdbSig70", GUID), + ("PdbAge", DWORD), + ("PdbUnmatched", BOOL), + ("DbgUnmatched", BOOL), + ("LineNumbers", BOOL), + ("GlobalSymbols", BOOL), + ("TypeInfo", BOOL), + ("SourceIndexed", BOOL), + ("Publics", BOOL), + ] +PIMAGEHLP_MODULE64 = POINTER(IMAGEHLP_MODULE64) + +class IMAGEHLP_MODULEW (Structure): + _fields_ = [ + ("SizeOfStruct", DWORD), + ("BaseOfImage", DWORD), + ("ImageSize", DWORD), + ("TimeDateStamp", DWORD), + ("CheckSum", DWORD), + ("NumSyms", DWORD), + ("SymType", DWORD), # SYM_TYPE + ("ModuleName", WCHAR * 32), + ("ImageName", WCHAR * 256), + ("LoadedImageName", WCHAR * 256), + ] +PIMAGEHLP_MODULEW = POINTER(IMAGEHLP_MODULEW) + +class IMAGEHLP_MODULEW64 (Structure): + _fields_ = [ + ("SizeOfStruct", DWORD), + ("BaseOfImage", DWORD64), + ("ImageSize", DWORD), + ("TimeDateStamp", DWORD), + ("CheckSum", DWORD), + ("NumSyms", DWORD), + ("SymType", DWORD), # SYM_TYPE + ("ModuleName", WCHAR * 32), + ("ImageName", WCHAR * 256), + ("LoadedImageName", WCHAR * 256), + ("LoadedPdbName", WCHAR * 256), + ("CVSig", DWORD), + ("CVData", WCHAR * (MAX_PATH * 3)), + ("PdbSig", DWORD), + ("PdbSig70", GUID), + ("PdbAge", DWORD), + ("PdbUnmatched", BOOL), + ("DbgUnmatched", BOOL), + ("LineNumbers", BOOL), + ("GlobalSymbols", BOOL), + ("TypeInfo", BOOL), + ("SourceIndexed", BOOL), + ("Publics", BOOL), + ] +PIMAGEHLP_MODULEW64 = POINTER(IMAGEHLP_MODULEW64) + +#--- dbghelp.dll -------------------------------------------------------------- + +# XXX the ANSI versions of these functions don't end in "A" as expected! + +# BOOL WINAPI MakeSureDirectoryPathExists( +# _In_ PCSTR DirPath +# ); +def MakeSureDirectoryPathExistsA(DirPath): + _MakeSureDirectoryPathExists = windll.dbghelp.MakeSureDirectoryPathExists + _MakeSureDirectoryPathExists.argtypes = [LPSTR] + _MakeSureDirectoryPathExists.restype = bool + _MakeSureDirectoryPathExists.errcheck = RaiseIfZero + return _MakeSureDirectoryPathExists(DirPath) + +MakeSureDirectoryPathExistsW = MakeWideVersion(MakeSureDirectoryPathExistsA) +MakeSureDirectoryPathExists = GuessStringType(MakeSureDirectoryPathExistsA, MakeSureDirectoryPathExistsW) + +# BOOL WINAPI SymInitialize( +# __in HANDLE hProcess, +# __in_opt PCTSTR UserSearchPath, +# __in BOOL fInvadeProcess +# ); +def SymInitializeA(hProcess, UserSearchPath = None, fInvadeProcess = False): + _SymInitialize = windll.dbghelp.SymInitialize + _SymInitialize.argtypes = [HANDLE, LPSTR, BOOL] + _SymInitialize.restype = bool + _SymInitialize.errcheck = RaiseIfZero + if not UserSearchPath: + UserSearchPath = None + _SymInitialize(hProcess, UserSearchPath, fInvadeProcess) + +SymInitializeW = MakeWideVersion(SymInitializeA) +SymInitialize = GuessStringType(SymInitializeA, SymInitializeW) + +# BOOL WINAPI SymCleanup( +# __in HANDLE hProcess +# ); +def SymCleanup(hProcess): + _SymCleanup = windll.dbghelp.SymCleanup + _SymCleanup.argtypes = [HANDLE] + _SymCleanup.restype = bool + _SymCleanup.errcheck = RaiseIfZero + _SymCleanup(hProcess) + +# BOOL WINAPI SymRefreshModuleList( +# __in HANDLE hProcess +# ); +def SymRefreshModuleList(hProcess): + _SymRefreshModuleList = windll.dbghelp.SymRefreshModuleList + _SymRefreshModuleList.argtypes = [HANDLE] + _SymRefreshModuleList.restype = bool + _SymRefreshModuleList.errcheck = RaiseIfZero + _SymRefreshModuleList(hProcess) + +# BOOL WINAPI SymSetParentWindow( +# __in HWND hwnd +# ); +def SymSetParentWindow(hwnd): + _SymSetParentWindow = windll.dbghelp.SymSetParentWindow + _SymSetParentWindow.argtypes = [HWND] + _SymSetParentWindow.restype = bool + _SymSetParentWindow.errcheck = RaiseIfZero + _SymSetParentWindow(hwnd) + +# DWORD WINAPI SymSetOptions( +# __in DWORD SymOptions +# ); +def SymSetOptions(SymOptions): + _SymSetOptions = windll.dbghelp.SymSetOptions + _SymSetOptions.argtypes = [DWORD] + _SymSetOptions.restype = DWORD + _SymSetOptions.errcheck = RaiseIfZero + _SymSetOptions(SymOptions) + +# DWORD WINAPI SymGetOptions(void); +def SymGetOptions(): + _SymGetOptions = windll.dbghelp.SymGetOptions + _SymGetOptions.argtypes = [] + _SymGetOptions.restype = DWORD + return _SymGetOptions() + +# DWORD WINAPI SymLoadModule( +# __in HANDLE hProcess, +# __in_opt HANDLE hFile, +# __in_opt PCSTR ImageName, +# __in_opt PCSTR ModuleName, +# __in DWORD BaseOfDll, +# __in DWORD SizeOfDll +# ); +def SymLoadModuleA(hProcess, hFile = None, ImageName = None, ModuleName = None, BaseOfDll = None, SizeOfDll = None): + _SymLoadModule = windll.dbghelp.SymLoadModule + _SymLoadModule.argtypes = [HANDLE, HANDLE, LPSTR, LPSTR, DWORD, DWORD] + _SymLoadModule.restype = DWORD + + if not ImageName: + ImageName = None + if not ModuleName: + ModuleName = None + if not BaseOfDll: + BaseOfDll = 0 + if not SizeOfDll: + SizeOfDll = 0 + SetLastError(ERROR_SUCCESS) + lpBaseAddress = _SymLoadModule(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll) + if lpBaseAddress == NULL: + dwErrorCode = GetLastError() + if dwErrorCode != ERROR_SUCCESS: + raise ctypes.WinError(dwErrorCode) + return lpBaseAddress + +SymLoadModuleW = MakeWideVersion(SymLoadModuleA) +SymLoadModule = GuessStringType(SymLoadModuleA, SymLoadModuleW) + +# DWORD64 WINAPI SymLoadModule64( +# __in HANDLE hProcess, +# __in_opt HANDLE hFile, +# __in_opt PCSTR ImageName, +# __in_opt PCSTR ModuleName, +# __in DWORD64 BaseOfDll, +# __in DWORD SizeOfDll +# ); +def SymLoadModule64A(hProcess, hFile = None, ImageName = None, ModuleName = None, BaseOfDll = None, SizeOfDll = None): + _SymLoadModule64 = windll.dbghelp.SymLoadModule64 + _SymLoadModule64.argtypes = [HANDLE, HANDLE, LPSTR, LPSTR, DWORD64, DWORD] + _SymLoadModule64.restype = DWORD64 + + if not ImageName: + ImageName = None + if not ModuleName: + ModuleName = None + if not BaseOfDll: + BaseOfDll = 0 + if not SizeOfDll: + SizeOfDll = 0 + SetLastError(ERROR_SUCCESS) + lpBaseAddress = _SymLoadModule64(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll) + if lpBaseAddress == NULL: + dwErrorCode = GetLastError() + if dwErrorCode != ERROR_SUCCESS: + raise ctypes.WinError(dwErrorCode) + return lpBaseAddress + +SymLoadModule64W = MakeWideVersion(SymLoadModule64A) +SymLoadModule64 = GuessStringType(SymLoadModule64A, SymLoadModule64W) + +# BOOL WINAPI SymUnloadModule( +# __in HANDLE hProcess, +# __in DWORD BaseOfDll +# ); +def SymUnloadModule(hProcess, BaseOfDll): + _SymUnloadModule = windll.dbghelp.SymUnloadModule + _SymUnloadModule.argtypes = [HANDLE, DWORD] + _SymUnloadModule.restype = bool + _SymUnloadModule.errcheck = RaiseIfZero + _SymUnloadModule(hProcess, BaseOfDll) + +# BOOL WINAPI SymUnloadModule64( +# __in HANDLE hProcess, +# __in DWORD64 BaseOfDll +# ); +def SymUnloadModule64(hProcess, BaseOfDll): + _SymUnloadModule64 = windll.dbghelp.SymUnloadModule64 + _SymUnloadModule64.argtypes = [HANDLE, DWORD64] + _SymUnloadModule64.restype = bool + _SymUnloadModule64.errcheck = RaiseIfZero + _SymUnloadModule64(hProcess, BaseOfDll) + +# BOOL WINAPI SymGetModuleInfo( +# __in HANDLE hProcess, +# __in DWORD dwAddr, +# __out PIMAGEHLP_MODULE ModuleInfo +# ); +def SymGetModuleInfoA(hProcess, dwAddr): + _SymGetModuleInfo = windll.dbghelp.SymGetModuleInfo + _SymGetModuleInfo.argtypes = [HANDLE, DWORD, PIMAGEHLP_MODULE] + _SymGetModuleInfo.restype = bool + _SymGetModuleInfo.errcheck = RaiseIfZero + + ModuleInfo = IMAGEHLP_MODULE() + ModuleInfo.SizeOfStruct = sizeof(ModuleInfo) + _SymGetModuleInfo(hProcess, dwAddr, byref(ModuleInfo)) + return ModuleInfo + +def SymGetModuleInfoW(hProcess, dwAddr): + _SymGetModuleInfoW = windll.dbghelp.SymGetModuleInfoW + _SymGetModuleInfoW.argtypes = [HANDLE, DWORD, PIMAGEHLP_MODULEW] + _SymGetModuleInfoW.restype = bool + _SymGetModuleInfoW.errcheck = RaiseIfZero + + ModuleInfo = IMAGEHLP_MODULEW() + ModuleInfo.SizeOfStruct = sizeof(ModuleInfo) + _SymGetModuleInfoW(hProcess, dwAddr, byref(ModuleInfo)) + return ModuleInfo + +SymGetModuleInfo = GuessStringType(SymGetModuleInfoA, SymGetModuleInfoW) + +# BOOL WINAPI SymGetModuleInfo64( +# __in HANDLE hProcess, +# __in DWORD64 dwAddr, +# __out PIMAGEHLP_MODULE64 ModuleInfo +# ); +def SymGetModuleInfo64A(hProcess, dwAddr): + _SymGetModuleInfo64 = windll.dbghelp.SymGetModuleInfo64 + _SymGetModuleInfo64.argtypes = [HANDLE, DWORD64, PIMAGEHLP_MODULE64] + _SymGetModuleInfo64.restype = bool + _SymGetModuleInfo64.errcheck = RaiseIfZero + + ModuleInfo = IMAGEHLP_MODULE64() + ModuleInfo.SizeOfStruct = sizeof(ModuleInfo) + _SymGetModuleInfo64(hProcess, dwAddr, byref(ModuleInfo)) + return ModuleInfo + +def SymGetModuleInfo64W(hProcess, dwAddr): + _SymGetModuleInfo64W = windll.dbghelp.SymGetModuleInfo64W + _SymGetModuleInfo64W.argtypes = [HANDLE, DWORD64, PIMAGEHLP_MODULE64W] + _SymGetModuleInfo64W.restype = bool + _SymGetModuleInfo64W.errcheck = RaiseIfZero + + ModuleInfo = IMAGEHLP_MODULE64W() + ModuleInfo.SizeOfStruct = sizeof(ModuleInfo) + _SymGetModuleInfo64W(hProcess, dwAddr, byref(ModuleInfo)) + return ModuleInfo + +SymGetModuleInfo64 = GuessStringType(SymGetModuleInfo64A, SymGetModuleInfo64W) + +# BOOL CALLBACK SymEnumerateModulesProc( +# __in PCTSTR ModuleName, +# __in DWORD BaseOfDll, +# __in_opt PVOID UserContext +# ); +PSYM_ENUMMODULES_CALLBACK = WINFUNCTYPE(BOOL, LPSTR, DWORD, PVOID) +PSYM_ENUMMODULES_CALLBACKW = WINFUNCTYPE(BOOL, LPWSTR, DWORD, PVOID) + +# BOOL CALLBACK SymEnumerateModulesProc64( +# __in PCTSTR ModuleName, +# __in DWORD64 BaseOfDll, +# __in_opt PVOID UserContext +# ); +PSYM_ENUMMODULES_CALLBACK64 = WINFUNCTYPE(BOOL, LPSTR, DWORD64, PVOID) +PSYM_ENUMMODULES_CALLBACKW64 = WINFUNCTYPE(BOOL, LPWSTR, DWORD64, PVOID) + +# BOOL WINAPI SymEnumerateModules( +# __in HANDLE hProcess, +# __in PSYM_ENUMMODULES_CALLBACK EnumModulesCallback, +# __in_opt PVOID UserContext +# ); +def SymEnumerateModulesA(hProcess, EnumModulesCallback, UserContext = None): + _SymEnumerateModules = windll.dbghelp.SymEnumerateModules + _SymEnumerateModules.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK, PVOID] + _SymEnumerateModules.restype = bool + _SymEnumerateModules.errcheck = RaiseIfZero + + EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK(EnumModulesCallback) + if UserContext: + UserContext = ctypes.pointer(UserContext) + else: + UserContext = LPVOID(NULL) + _SymEnumerateModules(hProcess, EnumModulesCallback, UserContext) + +def SymEnumerateModulesW(hProcess, EnumModulesCallback, UserContext = None): + _SymEnumerateModulesW = windll.dbghelp.SymEnumerateModulesW + _SymEnumerateModulesW.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACKW, PVOID] + _SymEnumerateModulesW.restype = bool + _SymEnumerateModulesW.errcheck = RaiseIfZero + + EnumModulesCallback = PSYM_ENUMMODULES_CALLBACKW(EnumModulesCallback) + if UserContext: + UserContext = ctypes.pointer(UserContext) + else: + UserContext = LPVOID(NULL) + _SymEnumerateModulesW(hProcess, EnumModulesCallback, UserContext) + +SymEnumerateModules = GuessStringType(SymEnumerateModulesA, SymEnumerateModulesW) + +# BOOL WINAPI SymEnumerateModules64( +# __in HANDLE hProcess, +# __in PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, +# __in_opt PVOID UserContext +# ); +def SymEnumerateModules64A(hProcess, EnumModulesCallback, UserContext = None): + _SymEnumerateModules64 = windll.dbghelp.SymEnumerateModules64 + _SymEnumerateModules64.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK64, PVOID] + _SymEnumerateModules64.restype = bool + _SymEnumerateModules64.errcheck = RaiseIfZero + + EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK64(EnumModulesCallback) + if UserContext: + UserContext = ctypes.pointer(UserContext) + else: + UserContext = LPVOID(NULL) + _SymEnumerateModules64(hProcess, EnumModulesCallback, UserContext) + +def SymEnumerateModules64W(hProcess, EnumModulesCallback, UserContext = None): + _SymEnumerateModules64W = windll.dbghelp.SymEnumerateModules64W + _SymEnumerateModules64W.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK64W, PVOID] + _SymEnumerateModules64W.restype = bool + _SymEnumerateModules64W.errcheck = RaiseIfZero + + EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK64W(EnumModulesCallback) + if UserContext: + UserContext = ctypes.pointer(UserContext) + else: + UserContext = LPVOID(NULL) + _SymEnumerateModules64W(hProcess, EnumModulesCallback, UserContext) + +SymEnumerateModules64 = GuessStringType(SymEnumerateModules64A, SymEnumerateModules64W) + +# BOOL CALLBACK SymEnumerateSymbolsProc( +# __in PCTSTR SymbolName, +# __in DWORD SymbolAddress, +# __in ULONG SymbolSize, +# __in_opt PVOID UserContext +# ); +PSYM_ENUMSYMBOLS_CALLBACK = WINFUNCTYPE(BOOL, LPSTR, DWORD, ULONG, PVOID) +PSYM_ENUMSYMBOLS_CALLBACKW = WINFUNCTYPE(BOOL, LPWSTR, DWORD, ULONG, PVOID) + +# BOOL CALLBACK SymEnumerateSymbolsProc64( +# __in PCTSTR SymbolName, +# __in DWORD64 SymbolAddress, +# __in ULONG SymbolSize, +# __in_opt PVOID UserContext +# ); +PSYM_ENUMSYMBOLS_CALLBACK64 = WINFUNCTYPE(BOOL, LPSTR, DWORD64, ULONG, PVOID) +PSYM_ENUMSYMBOLS_CALLBACKW64 = WINFUNCTYPE(BOOL, LPWSTR, DWORD64, ULONG, PVOID) + +# BOOL WINAPI SymEnumerateSymbols( +# __in HANDLE hProcess, +# __in ULONG BaseOfDll, +# __in PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, +# __in_opt PVOID UserContext +# ); +def SymEnumerateSymbolsA(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None): + _SymEnumerateSymbols = windll.dbghelp.SymEnumerateSymbols + _SymEnumerateSymbols.argtypes = [HANDLE, ULONG, PSYM_ENUMSYMBOLS_CALLBACK, PVOID] + _SymEnumerateSymbols.restype = bool + _SymEnumerateSymbols.errcheck = RaiseIfZero + + EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK(EnumSymbolsCallback) + if UserContext: + UserContext = ctypes.pointer(UserContext) + else: + UserContext = LPVOID(NULL) + _SymEnumerateSymbols(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext) + +def SymEnumerateSymbolsW(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None): + _SymEnumerateSymbolsW = windll.dbghelp.SymEnumerateSymbolsW + _SymEnumerateSymbolsW.argtypes = [HANDLE, ULONG, PSYM_ENUMSYMBOLS_CALLBACKW, PVOID] + _SymEnumerateSymbolsW.restype = bool + _SymEnumerateSymbolsW.errcheck = RaiseIfZero + + EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACKW(EnumSymbolsCallback) + if UserContext: + UserContext = ctypes.pointer(UserContext) + else: + UserContext = LPVOID(NULL) + _SymEnumerateSymbolsW(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext) + +SymEnumerateSymbols = GuessStringType(SymEnumerateSymbolsA, SymEnumerateSymbolsW) + +# BOOL WINAPI SymEnumerateSymbols64( +# __in HANDLE hProcess, +# __in ULONG64 BaseOfDll, +# __in PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, +# __in_opt PVOID UserContext +# ); +def SymEnumerateSymbols64A(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None): + _SymEnumerateSymbols64 = windll.dbghelp.SymEnumerateSymbols64 + _SymEnumerateSymbols64.argtypes = [HANDLE, ULONG64, PSYM_ENUMSYMBOLS_CALLBACK64, PVOID] + _SymEnumerateSymbols64.restype = bool + _SymEnumerateSymbols64.errcheck = RaiseIfZero + + EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK64(EnumSymbolsCallback) + if UserContext: + UserContext = ctypes.pointer(UserContext) + else: + UserContext = LPVOID(NULL) + _SymEnumerateSymbols64(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext) + +def SymEnumerateSymbols64W(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None): + _SymEnumerateSymbols64W = windll.dbghelp.SymEnumerateSymbols64W + _SymEnumerateSymbols64W.argtypes = [HANDLE, ULONG64, PSYM_ENUMSYMBOLS_CALLBACK64W, PVOID] + _SymEnumerateSymbols64W.restype = bool + _SymEnumerateSymbols64W.errcheck = RaiseIfZero + + EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK64W(EnumSymbolsCallback) + if UserContext: + UserContext = ctypes.pointer(UserContext) + else: + UserContext = LPVOID(NULL) + _SymEnumerateSymbols64W(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext) + +SymEnumerateSymbols64 = GuessStringType(SymEnumerateSymbols64A, SymEnumerateSymbols64W) + +# DWORD WINAPI UnDecorateSymbolName( +# __in PCTSTR DecoratedName, +# __out PTSTR UnDecoratedName, +# __in DWORD UndecoratedLength, +# __in DWORD Flags +# ); +def UnDecorateSymbolNameA(DecoratedName, Flags = UNDNAME_COMPLETE): + _UnDecorateSymbolNameA = windll.dbghelp.UnDecorateSymbolName + _UnDecorateSymbolNameA.argtypes = [LPSTR, LPSTR, DWORD, DWORD] + _UnDecorateSymbolNameA.restype = DWORD + _UnDecorateSymbolNameA.errcheck = RaiseIfZero + + UndecoratedLength = _UnDecorateSymbolNameA(DecoratedName, None, 0, Flags) + UnDecoratedName = ctypes.create_string_buffer('', UndecoratedLength + 1) + _UnDecorateSymbolNameA(DecoratedName, UnDecoratedName, UndecoratedLength, Flags) + return UnDecoratedName.value + +def UnDecorateSymbolNameW(DecoratedName, Flags = UNDNAME_COMPLETE): + _UnDecorateSymbolNameW = windll.dbghelp.UnDecorateSymbolNameW + _UnDecorateSymbolNameW.argtypes = [LPWSTR, LPWSTR, DWORD, DWORD] + _UnDecorateSymbolNameW.restype = DWORD + _UnDecorateSymbolNameW.errcheck = RaiseIfZero + + UndecoratedLength = _UnDecorateSymbolNameW(DecoratedName, None, 0, Flags) + UnDecoratedName = ctypes.create_unicode_buffer(u'', UndecoratedLength + 1) + _UnDecorateSymbolNameW(DecoratedName, UnDecoratedName, UndecoratedLength, Flags) + return UnDecoratedName.value + +UnDecorateSymbolName = GuessStringType(UnDecorateSymbolNameA, UnDecorateSymbolNameW) + +# BOOL WINAPI SymGetSearchPath( +# __in HANDLE hProcess, +# __out PTSTR SearchPath, +# __in DWORD SearchPathLength +# ); +def SymGetSearchPathA(hProcess): + _SymGetSearchPath = windll.dbghelp.SymGetSearchPath + _SymGetSearchPath.argtypes = [HANDLE, LPSTR, DWORD] + _SymGetSearchPath.restype = bool + _SymGetSearchPath.errcheck = RaiseIfZero + + SearchPathLength = MAX_PATH + SearchPath = ctypes.create_string_buffer("", SearchPathLength) + _SymGetSearchPath(hProcess, SearchPath, SearchPathLength) + return SearchPath.value + +def SymGetSearchPathW(hProcess): + _SymGetSearchPathW = windll.dbghelp.SymGetSearchPathW + _SymGetSearchPathW.argtypes = [HANDLE, LPWSTR, DWORD] + _SymGetSearchPathW.restype = bool + _SymGetSearchPathW.errcheck = RaiseIfZero + + SearchPathLength = MAX_PATH + SearchPath = ctypes.create_unicode_buffer(u"", SearchPathLength) + _SymGetSearchPathW(hProcess, SearchPath, SearchPathLength) + return SearchPath.value + +SymGetSearchPath = GuessStringType(SymGetSearchPathA, SymGetSearchPathW) + +# BOOL WINAPI SymSetSearchPath( +# __in HANDLE hProcess, +# __in_opt PCTSTR SearchPath +# ); +def SymSetSearchPathA(hProcess, SearchPath = None): + _SymSetSearchPath = windll.dbghelp.SymSetSearchPath + _SymSetSearchPath.argtypes = [HANDLE, LPSTR] + _SymSetSearchPath.restype = bool + _SymSetSearchPath.errcheck = RaiseIfZero + if not SearchPath: + SearchPath = None + _SymSetSearchPath(hProcess, SearchPath) + +def SymSetSearchPathW(hProcess, SearchPath = None): + _SymSetSearchPathW = windll.dbghelp.SymSetSearchPathW + _SymSetSearchPathW.argtypes = [HANDLE, LPWSTR] + _SymSetSearchPathW.restype = bool + _SymSetSearchPathW.errcheck = RaiseIfZero + if not SearchPath: + SearchPath = None + _SymSetSearchPathW(hProcess, SearchPath) + +SymSetSearchPath = GuessStringType(SymSetSearchPathA, SymSetSearchPathW) + +# PTCHAR WINAPI SymGetHomeDirectory( +# __in DWORD type, +# __out PTSTR dir, +# __in size_t size +# ); +def SymGetHomeDirectoryA(type): + _SymGetHomeDirectoryA = windll.dbghelp.SymGetHomeDirectoryA + _SymGetHomeDirectoryA.argtypes = [DWORD, LPSTR, SIZE_T] + _SymGetHomeDirectoryA.restype = LPSTR + _SymGetHomeDirectoryA.errcheck = RaiseIfZero + + size = MAX_PATH + dir = ctypes.create_string_buffer("", size) + _SymGetHomeDirectoryA(type, dir, size) + return dir.value + +def SymGetHomeDirectoryW(type): + _SymGetHomeDirectoryW = windll.dbghelp.SymGetHomeDirectoryW + _SymGetHomeDirectoryW.argtypes = [DWORD, LPWSTR, SIZE_T] + _SymGetHomeDirectoryW.restype = LPWSTR + _SymGetHomeDirectoryW.errcheck = RaiseIfZero + + size = MAX_PATH + dir = ctypes.create_unicode_buffer(u"", size) + _SymGetHomeDirectoryW(type, dir, size) + return dir.value + +SymGetHomeDirectory = GuessStringType(SymGetHomeDirectoryA, SymGetHomeDirectoryW) + +# PTCHAR WINAPI SymSetHomeDirectory( +# __in HANDLE hProcess, +# __in_opt PCTSTR dir +# ); +def SymSetHomeDirectoryA(hProcess, dir = None): + _SymSetHomeDirectoryA = windll.dbghelp.SymSetHomeDirectoryA + _SymSetHomeDirectoryA.argtypes = [HANDLE, LPSTR] + _SymSetHomeDirectoryA.restype = LPSTR + _SymSetHomeDirectoryA.errcheck = RaiseIfZero + if not dir: + dir = None + _SymSetHomeDirectoryA(hProcess, dir) + return dir + +def SymSetHomeDirectoryW(hProcess, dir = None): + _SymSetHomeDirectoryW = windll.dbghelp.SymSetHomeDirectoryW + _SymSetHomeDirectoryW.argtypes = [HANDLE, LPWSTR] + _SymSetHomeDirectoryW.restype = LPWSTR + _SymSetHomeDirectoryW.errcheck = RaiseIfZero + if not dir: + dir = None + _SymSetHomeDirectoryW(hProcess, dir) + return dir + +SymSetHomeDirectory = GuessStringType(SymSetHomeDirectoryA, SymSetHomeDirectoryW) + +#--- DbgHelp 5+ support, patch by Neitsa -------------------------------------- + +# XXX TODO +# + use the GuessStringType decorator for ANSI/Wide versions +# + replace hardcoded struct sizes with sizeof() calls +# + StackWalk64 should raise on error, but something has to be done about it +# not setting the last error code (maybe we should call SetLastError +# ourselves with a default error code?) +# /Mario + +#maximum length of a symbol name +MAX_SYM_NAME = 2000 + +class SYM_INFO(Structure): + _fields_ = [ + ("SizeOfStruct", ULONG), + ("TypeIndex", ULONG), + ("Reserved", ULONG64 * 2), + ("Index", ULONG), + ("Size", ULONG), + ("ModBase", ULONG64), + ("Flags", ULONG), + ("Value", ULONG64), + ("Address", ULONG64), + ("Register", ULONG), + ("Scope", ULONG), + ("Tag", ULONG), + ("NameLen", ULONG), + ("MaxNameLen", ULONG), + ("Name", CHAR * (MAX_SYM_NAME + 1)), + ] +PSYM_INFO = POINTER(SYM_INFO) + +class SYM_INFOW(Structure): + _fields_ = [ + ("SizeOfStruct", ULONG), + ("TypeIndex", ULONG), + ("Reserved", ULONG64 * 2), + ("Index", ULONG), + ("Size", ULONG), + ("ModBase", ULONG64), + ("Flags", ULONG), + ("Value", ULONG64), + ("Address", ULONG64), + ("Register", ULONG), + ("Scope", ULONG), + ("Tag", ULONG), + ("NameLen", ULONG), + ("MaxNameLen", ULONG), + ("Name", WCHAR * (MAX_SYM_NAME + 1)), + ] +PSYM_INFOW = POINTER(SYM_INFOW) + +#=============================================================================== +# BOOL WINAPI SymFromName( +# __in HANDLE hProcess, +# __in PCTSTR Name, +# __inout PSYMBOL_INFO Symbol +# ); +#=============================================================================== +def SymFromName(hProcess, Name): + _SymFromNameA = windll.dbghelp.SymFromName + _SymFromNameA.argtypes = [HANDLE, LPSTR, PSYM_INFO] + _SymFromNameA.restype = bool + _SymFromNameA.errcheck = RaiseIfZero + + SymInfo = SYM_INFO() + SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFO) in C. + SymInfo.MaxNameLen = MAX_SYM_NAME + + _SymFromNameA(hProcess, Name, byref(SymInfo)) + + return SymInfo + +def SymFromNameW(hProcess, Name): + _SymFromNameW = windll.dbghelp.SymFromNameW + _SymFromNameW.argtypes = [HANDLE, LPWSTR, PSYM_INFOW] + _SymFromNameW.restype = bool + _SymFromNameW.errcheck = RaiseIfZero + + SymInfo = SYM_INFOW() + SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFOW) in C. + SymInfo.MaxNameLen = MAX_SYM_NAME + + _SymFromNameW(hProcess, Name, byref(SymInfo)) + + return SymInfo + +#=============================================================================== +# BOOL WINAPI SymFromAddr( +# __in HANDLE hProcess, +# __in DWORD64 Address, +# __out_opt PDWORD64 Displacement, +# __inout PSYMBOL_INFO Symbol +# ); +#=============================================================================== +def SymFromAddr(hProcess, Address): + _SymFromAddr = windll.dbghelp.SymFromAddr + _SymFromAddr.argtypes = [HANDLE, DWORD64, PDWORD64, PSYM_INFO] + _SymFromAddr.restype = bool + _SymFromAddr.errcheck = RaiseIfZero + + SymInfo = SYM_INFO() + SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFO) in C. + SymInfo.MaxNameLen = MAX_SYM_NAME + + Displacement = DWORD64(0) + _SymFromAddr(hProcess, Address, byref(Displacement), byref(SymInfo)) + + return (Displacement.value, SymInfo) + +def SymFromAddrW(hProcess, Address): + _SymFromAddr = windll.dbghelp.SymFromAddrW + _SymFromAddr.argtypes = [HANDLE, DWORD64, PDWORD64, PSYM_INFOW] + _SymFromAddr.restype = bool + _SymFromAddr.errcheck = RaiseIfZero + + SymInfo = SYM_INFOW() + SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFOW) in C. + SymInfo.MaxNameLen = MAX_SYM_NAME + + Displacement = DWORD64(0) + _SymFromAddr(hProcess, Address, byref(Displacement), byref(SymInfo)) + + return (Displacement.value, SymInfo) + +#=============================================================================== +# typedef struct _IMAGEHLP_SYMBOL64 { +# DWORD SizeOfStruct; +# DWORD64 Address; +# DWORD Size; +# DWORD Flags; +# DWORD MaxNameLength; +# CHAR Name[1]; +# } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; +#=============================================================================== +class IMAGEHLP_SYMBOL64 (Structure): + _fields_ = [ + ("SizeOfStruct", DWORD), + ("Address", DWORD64), + ("Size", DWORD), + ("Flags", DWORD), + ("MaxNameLength", DWORD), + ("Name", CHAR * (MAX_SYM_NAME + 1)), + ] +PIMAGEHLP_SYMBOL64 = POINTER(IMAGEHLP_SYMBOL64) + +#=============================================================================== +# typedef struct _IMAGEHLP_SYMBOLW64 { +# DWORD SizeOfStruct; +# DWORD64 Address; +# DWORD Size; +# DWORD Flags; +# DWORD MaxNameLength; +# WCHAR Name[1]; +# } IMAGEHLP_SYMBOLW64, *PIMAGEHLP_SYMBOLW64; +#=============================================================================== +class IMAGEHLP_SYMBOLW64 (Structure): + _fields_ = [ + ("SizeOfStruct", DWORD), + ("Address", DWORD64), + ("Size", DWORD), + ("Flags", DWORD), + ("MaxNameLength", DWORD), + ("Name", WCHAR * (MAX_SYM_NAME + 1)), + ] +PIMAGEHLP_SYMBOLW64 = POINTER(IMAGEHLP_SYMBOLW64) + +#=============================================================================== +# BOOL WINAPI SymGetSymFromAddr64( +# __in HANDLE hProcess, +# __in DWORD64 Address, +# __out_opt PDWORD64 Displacement, +# __inout PIMAGEHLP_SYMBOL64 Symbol +# ); +#=============================================================================== +def SymGetSymFromAddr64(hProcess, Address): + _SymGetSymFromAddr64 = windll.dbghelp.SymGetSymFromAddr64 + _SymGetSymFromAddr64.argtypes = [HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64] + _SymGetSymFromAddr64.restype = bool + _SymGetSymFromAddr64.errcheck = RaiseIfZero + + imagehlp_symbol64 = IMAGEHLP_SYMBOL64() + imagehlp_symbol64.SizeOfStruct = 32 # *don't modify*: sizeof(IMAGEHLP_SYMBOL64) in C. + imagehlp_symbol64.MaxNameLen = MAX_SYM_NAME + + Displacement = DWORD64(0) + _SymGetSymFromAddr64(hProcess, Address, byref(Displacement), byref(imagehlp_symbol64)) + + return (Displacement.value, imagehlp_symbol64) + +#TODO: check for the 'W' version of SymGetSymFromAddr64() + + +#=============================================================================== +# typedef struct API_VERSION { +# USHORT MajorVersion; +# USHORT MinorVersion; +# USHORT Revision; +# USHORT Reserved; +# } API_VERSION, *LPAPI_VERSION; +#=============================================================================== +class API_VERSION (Structure): + _fields_ = [ + ("MajorVersion", USHORT), + ("MinorVersion", USHORT), + ("Revision", USHORT), + ("Reserved", USHORT), + ] +PAPI_VERSION = POINTER(API_VERSION) +LPAPI_VERSION = PAPI_VERSION + +#=============================================================================== +# LPAPI_VERSION WINAPI ImagehlpApiVersion(void); +#=============================================================================== +def ImagehlpApiVersion(): + _ImagehlpApiVersion = windll.dbghelp.ImagehlpApiVersion + _ImagehlpApiVersion.restype = LPAPI_VERSION + + api_version = _ImagehlpApiVersion() + return api_version.contents + + +#=============================================================================== +# LPAPI_VERSION WINAPI ImagehlpApiVersionEx( +# __in LPAPI_VERSION AppVersion +# ); +#=============================================================================== +def ImagehlpApiVersionEx(MajorVersion, MinorVersion, Revision): + _ImagehlpApiVersionEx = windll.dbghelp.ImagehlpApiVersionEx + _ImagehlpApiVersionEx.argtypes = [LPAPI_VERSION] + _ImagehlpApiVersionEx.restype = LPAPI_VERSION + + api_version = API_VERSION(MajorVersion, MinorVersion, Revision, 0) + + ret_api_version = _ImagehlpApiVersionEx(byref(api_version)) + + return ret_api_version.contents + +#=============================================================================== +# typedef enum { +# AddrMode1616, +# AddrMode1632, +# AddrModeReal, +# AddrModeFlat +# } ADDRESS_MODE; +#=============================================================================== +AddrMode1616 = 0 +AddrMode1632 = 1 +AddrModeReal = 2 +AddrModeFlat = 3 + +ADDRESS_MODE = DWORD #needed for the size of an ADDRESS_MODE (see ADDRESS64) + +#=============================================================================== +# typedef struct _tagADDRESS64 { +# DWORD64 Offset; +# WORD Segment; +# ADDRESS_MODE Mode; +# } ADDRESS64, *LPADDRESS64; +#=============================================================================== +class ADDRESS64 (Structure): + _fields_ = [ + ("Offset", DWORD64), + ("Segment", WORD), + ("Mode", ADDRESS_MODE), #it's a member of the ADDRESS_MODE enum. + ] +LPADDRESS64 = POINTER(ADDRESS64) + +#=============================================================================== +# typedef struct _KDHELP64 { +# DWORD64 Thread; +# DWORD ThCallbackStack; +# DWORD ThCallbackBStore; +# DWORD NextCallback; +# DWORD FramePointer; +# DWORD64 KiCallUserMode; +# DWORD64 KeUserCallbackDispatcher; +# DWORD64 SystemRangeStart; +# DWORD64 KiUserExceptionDispatcher; +# DWORD64 StackBase; +# DWORD64 StackLimit; +# DWORD64 Reserved[5]; +# } KDHELP64, *PKDHELP64; +#=============================================================================== +class KDHELP64 (Structure): + _fields_ = [ + ("Thread", DWORD64), + ("ThCallbackStack", DWORD), + ("ThCallbackBStore", DWORD), + ("NextCallback", DWORD), + ("FramePointer", DWORD), + ("KiCallUserMode", DWORD64), + ("KeUserCallbackDispatcher", DWORD64), + ("SystemRangeStart", DWORD64), + ("KiUserExceptionDispatcher", DWORD64), + ("StackBase", DWORD64), + ("StackLimit", DWORD64), + ("Reserved", DWORD64 * 5), + ] +PKDHELP64 = POINTER(KDHELP64) + +#=============================================================================== +# typedef struct _tagSTACKFRAME64 { +# ADDRESS64 AddrPC; +# ADDRESS64 AddrReturn; +# ADDRESS64 AddrFrame; +# ADDRESS64 AddrStack; +# ADDRESS64 AddrBStore; +# PVOID FuncTableEntry; +# DWORD64 Params[4]; +# BOOL Far; +# BOOL Virtual; +# DWORD64 Reserved[3]; +# KDHELP64 KdHelp; +# } STACKFRAME64, *LPSTACKFRAME64; +#=============================================================================== +class STACKFRAME64(Structure): + _fields_ = [ + ("AddrPC", ADDRESS64), + ("AddrReturn", ADDRESS64), + ("AddrFrame", ADDRESS64), + ("AddrStack", ADDRESS64), + ("AddrBStore", ADDRESS64), + ("FuncTableEntry", PVOID), + ("Params", DWORD64 * 4), + ("Far", BOOL), + ("Virtual", BOOL), + ("Reserved", DWORD64 * 3), + ("KdHelp", KDHELP64), + ] +LPSTACKFRAME64 = POINTER(STACKFRAME64) + +#=============================================================================== +# BOOL CALLBACK ReadProcessMemoryProc64( +# __in HANDLE hProcess, +# __in DWORD64 lpBaseAddress, +# __out PVOID lpBuffer, +# __in DWORD nSize, +# __out LPDWORD lpNumberOfBytesRead +# ); +#=============================================================================== +PREAD_PROCESS_MEMORY_ROUTINE64 = WINFUNCTYPE(BOOL, HANDLE, DWORD64, PVOID, DWORD, LPDWORD) + +#=============================================================================== +# PVOID CALLBACK FunctionTableAccessProc64( +# __in HANDLE hProcess, +# __in DWORD64 AddrBase +# ); +#=============================================================================== +PFUNCTION_TABLE_ACCESS_ROUTINE64 = WINFUNCTYPE(PVOID, HANDLE, DWORD64) + +#=============================================================================== +# DWORD64 CALLBACK GetModuleBaseProc64( +# __in HANDLE hProcess, +# __in DWORD64 Address +# ); +#=============================================================================== +PGET_MODULE_BASE_ROUTINE64 = WINFUNCTYPE(DWORD64, HANDLE, DWORD64) + +#=============================================================================== +# DWORD64 CALLBACK GetModuleBaseProc64( +# __in HANDLE hProcess, +# __in DWORD64 Address +# ); +#=============================================================================== +PTRANSLATE_ADDRESS_ROUTINE64 = WINFUNCTYPE(DWORD64, HANDLE, DWORD64) + +# Valid machine types for StackWalk64 function +IMAGE_FILE_MACHINE_I386 = 0x014c #Intel x86 +IMAGE_FILE_MACHINE_IA64 = 0x0200 #Intel Itanium Processor Family (IPF) +IMAGE_FILE_MACHINE_AMD64 = 0x8664 #x64 (AMD64 or EM64T) + +#=============================================================================== +# BOOL WINAPI StackWalk64( +# __in DWORD MachineType, +# __in HANDLE hProcess, +# __in HANDLE hThread, +# __inout LPSTACKFRAME64 StackFrame, +# __inout PVOID ContextRecord, +# __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, +# __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, +# __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, +# __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress +# ); +#=============================================================================== +def StackWalk64(MachineType, hProcess, hThread, StackFrame, + ContextRecord = None, ReadMemoryRoutine = None, + FunctionTableAccessRoutine = None, GetModuleBaseRoutine = None, + TranslateAddress = None): + + _StackWalk64 = windll.dbghelp.StackWalk64 + _StackWalk64.argtypes = [DWORD, HANDLE, HANDLE, LPSTACKFRAME64, PVOID, + PREAD_PROCESS_MEMORY_ROUTINE64, + PFUNCTION_TABLE_ACCESS_ROUTINE64, + PGET_MODULE_BASE_ROUTINE64, + PTRANSLATE_ADDRESS_ROUTINE64] + _StackWalk64.restype = bool + + pReadMemoryRoutine = None + if ReadMemoryRoutine: + pReadMemoryRoutine = PREAD_PROCESS_MEMORY_ROUTINE64(ReadMemoryRoutine) + else: + pReadMemoryRoutine = ctypes.cast(None, PREAD_PROCESS_MEMORY_ROUTINE64) + + pFunctionTableAccessRoutine = None + if FunctionTableAccessRoutine: + pFunctionTableAccessRoutine = PFUNCTION_TABLE_ACCESS_ROUTINE64(FunctionTableAccessRoutine) + else: + pFunctionTableAccessRoutine = ctypes.cast(None, PFUNCTION_TABLE_ACCESS_ROUTINE64) + + pGetModuleBaseRoutine = None + if GetModuleBaseRoutine: + pGetModuleBaseRoutine = PGET_MODULE_BASE_ROUTINE64(GetModuleBaseRoutine) + else: + pGetModuleBaseRoutine = ctypes.cast(None, PGET_MODULE_BASE_ROUTINE64) + + pTranslateAddress = None + if TranslateAddress: + pTranslateAddress = PTRANSLATE_ADDRESS_ROUTINE64(TranslateAddress) + else: + pTranslateAddress = ctypes.cast(None, PTRANSLATE_ADDRESS_ROUTINE64) + + pContextRecord = None + if ContextRecord is None: + ContextRecord = GetThreadContext(hThread, raw=True) + pContextRecord = PCONTEXT(ContextRecord) + + #this function *DOESN'T* set last error [GetLastError()] properly most of the time. + ret = _StackWalk64(MachineType, hProcess, hThread, byref(StackFrame), + pContextRecord, pReadMemoryRoutine, + pFunctionTableAccessRoutine, pGetModuleBaseRoutine, + pTranslateAddress) + + return ret + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/defines.py b/pydevd_attach_to_process/winappdbg/win32/defines.py new file mode 100644 index 0000000..187e429 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/defines.py @@ -0,0 +1,718 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Common definitions. +""" + +# TODO +# + add TCHAR and related types? + +__revision__ = "$Id$" + +import ctypes +import functools +from winappdbg import compat + +#------------------------------------------------------------------------------ + +# Some stuff from ctypes we'll be using very frequently. +addressof = ctypes.addressof +sizeof = ctypes.sizeof +SIZEOF = ctypes.sizeof +POINTER = ctypes.POINTER +Structure = ctypes.Structure +Union = ctypes.Union +WINFUNCTYPE = ctypes.WINFUNCTYPE +windll = ctypes.windll + +# The IronPython implementation of byref() was giving me problems, +# so I'm replacing it with the slower pointer() function. +try: + ctypes.c_void_p(ctypes.byref(ctypes.c_char())) # this fails in IronPython + byref = ctypes.byref +except TypeError: + byref = ctypes.pointer + +# XXX DEBUG +# The following code can be enabled to make the Win32 API wrappers log to +# standard output the dll and function names, the parameter values and the +# return value for each call. + +##WIN32_VERBOSE_MODE = True +WIN32_VERBOSE_MODE = False + +if WIN32_VERBOSE_MODE: + + class WinDllHook(object): + def __getattr__(self, name): + if name.startswith('_'): + return object.__getattr__(self, name) + return WinFuncHook(name) + + class WinFuncHook(object): + def __init__(self, name): + self.__name = name + + def __getattr__(self, name): + if name.startswith('_'): + return object.__getattr__(self, name) + return WinCallHook(self.__name, name) + + class WinCallHook(object): + def __init__(self, dllname, funcname): + self.__dllname = dllname + self.__funcname = funcname + self.__func = getattr(getattr(ctypes.windll, dllname), funcname) + + def __copy_attribute(self, attribute): + try: + value = getattr(self, attribute) + setattr(self.__func, attribute, value) + except AttributeError: + try: + delattr(self.__func, attribute) + except AttributeError: + pass + + def __call__(self, *argv): + self.__copy_attribute('argtypes') + self.__copy_attribute('restype') + self.__copy_attribute('errcheck') + print("-"*10) + print("%s ! %s %r" % (self.__dllname, self.__funcname, argv)) + retval = self.__func(*argv) + print("== %r" % (retval,)) + return retval + + windll = WinDllHook() + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +def RaiseIfZero(result, func = None, arguments = ()): + """ + Error checking for most Win32 API calls. + + The function is assumed to return an integer, which is C{0} on error. + In that case the C{WindowsError} exception is raised. + """ + if not result: + raise ctypes.WinError() + return result + +def RaiseIfNotZero(result, func = None, arguments = ()): + """ + Error checking for some odd Win32 API calls. + + The function is assumed to return an integer, which is zero on success. + If the return value is nonzero the C{WindowsError} exception is raised. + + This is mostly useful for free() like functions, where the return value is + the pointer to the memory block on failure or a C{NULL} pointer on success. + """ + if result: + raise ctypes.WinError() + return result + +def RaiseIfNotErrorSuccess(result, func = None, arguments = ()): + """ + Error checking for Win32 Registry API calls. + + The function is assumed to return a Win32 error code. If the code is not + C{ERROR_SUCCESS} then a C{WindowsError} exception is raised. + """ + if result != ERROR_SUCCESS: + raise ctypes.WinError(result) + return result + +class GuessStringType(object): + """ + Decorator that guesses the correct version (A or W) to call + based on the types of the strings passed as parameters. + + Calls the B{ANSI} version if the only string types are ANSI. + + Calls the B{Unicode} version if Unicode or mixed string types are passed. + + The default if no string arguments are passed depends on the value of the + L{t_default} class variable. + + @type fn_ansi: function + @ivar fn_ansi: ANSI version of the API function to call. + @type fn_unicode: function + @ivar fn_unicode: Unicode (wide) version of the API function to call. + + @type t_default: type + @cvar t_default: Default string type to use. + Possible values are: + - type('') for ANSI + - type(u'') for Unicode + """ + + # ANSI and Unicode types + t_ansi = type('') + t_unicode = type(u'') + + # Default is ANSI for Python 2.x + t_default = t_ansi + + def __init__(self, fn_ansi, fn_unicode): + """ + @type fn_ansi: function + @param fn_ansi: ANSI version of the API function to call. + @type fn_unicode: function + @param fn_unicode: Unicode (wide) version of the API function to call. + """ + self.fn_ansi = fn_ansi + self.fn_unicode = fn_unicode + + # Copy the wrapped function attributes. + try: + self.__name__ = self.fn_ansi.__name__[:-1] # remove the A or W + except AttributeError: + pass + try: + self.__module__ = self.fn_ansi.__module__ + except AttributeError: + pass + try: + self.__doc__ = self.fn_ansi.__doc__ + except AttributeError: + pass + + def __call__(self, *argv, **argd): + + # Shortcut to self.t_ansi + t_ansi = self.t_ansi + + # Get the types of all arguments for the function + v_types = [ type(item) for item in argv ] + v_types.extend( [ type(value) for (key, value) in compat.iteritems(argd) ] ) + + # Get the appropriate function for the default type + if self.t_default == t_ansi: + fn = self.fn_ansi + else: + fn = self.fn_unicode + + # If at least one argument is a Unicode string... + if self.t_unicode in v_types: + + # If al least one argument is an ANSI string, + # convert all ANSI strings to Unicode + if t_ansi in v_types: + argv = list(argv) + for index in compat.xrange(len(argv)): + if v_types[index] == t_ansi: + argv[index] = compat.unicode(argv[index]) + for (key, value) in argd.items(): + if type(value) == t_ansi: + argd[key] = compat.unicode(value) + + # Use the W version + fn = self.fn_unicode + + # If at least one argument is an ANSI string, + # but there are no Unicode strings... + elif t_ansi in v_types: + + # Use the A version + fn = self.fn_ansi + + # Call the function and return the result + return fn(*argv, **argd) + +class DefaultStringType(object): + """ + Decorator that uses the default version (A or W) to call + based on the configuration of the L{GuessStringType} decorator. + + @see: L{GuessStringType.t_default} + + @type fn_ansi: function + @ivar fn_ansi: ANSI version of the API function to call. + @type fn_unicode: function + @ivar fn_unicode: Unicode (wide) version of the API function to call. + """ + + def __init__(self, fn_ansi, fn_unicode): + """ + @type fn_ansi: function + @param fn_ansi: ANSI version of the API function to call. + @type fn_unicode: function + @param fn_unicode: Unicode (wide) version of the API function to call. + """ + self.fn_ansi = fn_ansi + self.fn_unicode = fn_unicode + + # Copy the wrapped function attributes. + try: + self.__name__ = self.fn_ansi.__name__[:-1] # remove the A or W + except AttributeError: + pass + try: + self.__module__ = self.fn_ansi.__module__ + except AttributeError: + pass + try: + self.__doc__ = self.fn_ansi.__doc__ + except AttributeError: + pass + + def __call__(self, *argv, **argd): + + # Get the appropriate function based on the default. + if GuessStringType.t_default == GuessStringType.t_ansi: + fn = self.fn_ansi + else: + fn = self.fn_unicode + + # Call the function and return the result + return fn(*argv, **argd) + +def MakeANSIVersion(fn): + """ + Decorator that generates an ANSI version of a Unicode (wide) only API call. + + @type fn: callable + @param fn: Unicode (wide) version of the API function to call. + """ + @functools.wraps(fn) + def wrapper(*argv, **argd): + t_ansi = GuessStringType.t_ansi + t_unicode = GuessStringType.t_unicode + v_types = [ type(item) for item in argv ] + v_types.extend( [ type(value) for (key, value) in compat.iteritems(argd) ] ) + if t_ansi in v_types: + argv = list(argv) + for index in compat.xrange(len(argv)): + if v_types[index] == t_ansi: + argv[index] = t_unicode(argv[index]) + for key, value in argd.items(): + if type(value) == t_ansi: + argd[key] = t_unicode(value) + return fn(*argv, **argd) + return wrapper + +def MakeWideVersion(fn): + """ + Decorator that generates a Unicode (wide) version of an ANSI only API call. + + @type fn: callable + @param fn: ANSI version of the API function to call. + """ + @functools.wraps(fn) + def wrapper(*argv, **argd): + t_ansi = GuessStringType.t_ansi + t_unicode = GuessStringType.t_unicode + v_types = [ type(item) for item in argv ] + v_types.extend( [ type(value) for (key, value) in compat.iteritems(argd) ] ) + if t_unicode in v_types: + argv = list(argv) + for index in compat.xrange(len(argv)): + if v_types[index] == t_unicode: + argv[index] = t_ansi(argv[index]) + for key, value in argd.items(): + if type(value) == t_unicode: + argd[key] = t_ansi(value) + return fn(*argv, **argd) + return wrapper + +#--- Types -------------------------------------------------------------------- +# http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx + +# Map of basic C types to Win32 types +LPVOID = ctypes.c_void_p +CHAR = ctypes.c_char +WCHAR = ctypes.c_wchar +BYTE = ctypes.c_ubyte +SBYTE = ctypes.c_byte +WORD = ctypes.c_uint16 +SWORD = ctypes.c_int16 +DWORD = ctypes.c_uint32 +SDWORD = ctypes.c_int32 +QWORD = ctypes.c_uint64 +SQWORD = ctypes.c_int64 +SHORT = ctypes.c_short +USHORT = ctypes.c_ushort +INT = ctypes.c_int +UINT = ctypes.c_uint +LONG = ctypes.c_long +ULONG = ctypes.c_ulong +LONGLONG = ctypes.c_int64 # c_longlong +ULONGLONG = ctypes.c_uint64 # c_ulonglong +LPSTR = ctypes.c_char_p +LPWSTR = ctypes.c_wchar_p +INT8 = ctypes.c_int8 +INT16 = ctypes.c_int16 +INT32 = ctypes.c_int32 +INT64 = ctypes.c_int64 +UINT8 = ctypes.c_uint8 +UINT16 = ctypes.c_uint16 +UINT32 = ctypes.c_uint32 +UINT64 = ctypes.c_uint64 +LONG32 = ctypes.c_int32 +LONG64 = ctypes.c_int64 +ULONG32 = ctypes.c_uint32 +ULONG64 = ctypes.c_uint64 +DWORD32 = ctypes.c_uint32 +DWORD64 = ctypes.c_uint64 +BOOL = ctypes.c_int +FLOAT = ctypes.c_float + +# Map size_t to SIZE_T +try: + SIZE_T = ctypes.c_size_t + SSIZE_T = ctypes.c_ssize_t +except AttributeError: + # Size of a pointer + SIZE_T = {1:BYTE, 2:WORD, 4:DWORD, 8:QWORD}[sizeof(LPVOID)] + SSIZE_T = {1:SBYTE, 2:SWORD, 4:SDWORD, 8:SQWORD}[sizeof(LPVOID)] +PSIZE_T = POINTER(SIZE_T) + +# Not really pointers but pointer-sized integers +DWORD_PTR = SIZE_T +ULONG_PTR = SIZE_T +LONG_PTR = SIZE_T + +# Other Win32 types, more may be added as needed +PVOID = LPVOID +PPVOID = POINTER(PVOID) +PSTR = LPSTR +PWSTR = LPWSTR +PCHAR = LPSTR +PWCHAR = LPWSTR +LPBYTE = POINTER(BYTE) +LPSBYTE = POINTER(SBYTE) +LPWORD = POINTER(WORD) +LPSWORD = POINTER(SWORD) +LPDWORD = POINTER(DWORD) +LPSDWORD = POINTER(SDWORD) +LPULONG = POINTER(ULONG) +LPLONG = POINTER(LONG) +PDWORD = LPDWORD +PDWORD_PTR = POINTER(DWORD_PTR) +PULONG = LPULONG +PLONG = LPLONG +CCHAR = CHAR +BOOLEAN = BYTE +PBOOL = POINTER(BOOL) +LPBOOL = PBOOL +TCHAR = CHAR # XXX ANSI by default? +UCHAR = BYTE +DWORDLONG = ULONGLONG +LPDWORD32 = POINTER(DWORD32) +LPULONG32 = POINTER(ULONG32) +LPDWORD64 = POINTER(DWORD64) +LPULONG64 = POINTER(ULONG64) +PDWORD32 = LPDWORD32 +PULONG32 = LPULONG32 +PDWORD64 = LPDWORD64 +PULONG64 = LPULONG64 +ATOM = WORD +HANDLE = LPVOID +PHANDLE = POINTER(HANDLE) +LPHANDLE = PHANDLE +HMODULE = HANDLE +HINSTANCE = HANDLE +HTASK = HANDLE +HKEY = HANDLE +PHKEY = POINTER(HKEY) +HDESK = HANDLE +HRSRC = HANDLE +HSTR = HANDLE +HWINSTA = HANDLE +HKL = HANDLE +HDWP = HANDLE +HFILE = HANDLE +HRESULT = LONG +HGLOBAL = HANDLE +HLOCAL = HANDLE +HGDIOBJ = HANDLE +HDC = HGDIOBJ +HRGN = HGDIOBJ +HBITMAP = HGDIOBJ +HPALETTE = HGDIOBJ +HPEN = HGDIOBJ +HBRUSH = HGDIOBJ +HMF = HGDIOBJ +HEMF = HGDIOBJ +HENHMETAFILE = HGDIOBJ +HMETAFILE = HGDIOBJ +HMETAFILEPICT = HGDIOBJ +HWND = HANDLE +NTSTATUS = LONG +PNTSTATUS = POINTER(NTSTATUS) +KAFFINITY = ULONG_PTR +RVA = DWORD +RVA64 = QWORD +WPARAM = DWORD +LPARAM = LPVOID +LRESULT = LPVOID +ACCESS_MASK = DWORD +REGSAM = ACCESS_MASK +PACCESS_MASK = POINTER(ACCESS_MASK) +PREGSAM = POINTER(REGSAM) + +# Since the SID is an opaque structure, let's treat its pointers as void* +PSID = PVOID + +# typedef union _LARGE_INTEGER { +# struct { +# DWORD LowPart; +# LONG HighPart; +# } ; +# struct { +# DWORD LowPart; +# LONG HighPart; +# } u; +# LONGLONG QuadPart; +# } LARGE_INTEGER, +# *PLARGE_INTEGER; + +# XXX TODO + +# typedef struct _FLOAT128 { +# __int64 LowPart; +# __int64 HighPart; +# } FLOAT128; +class FLOAT128 (Structure): + _fields_ = [ + ("LowPart", QWORD), + ("HighPart", QWORD), + ] +PFLOAT128 = POINTER(FLOAT128) + +# typedef struct DECLSPEC_ALIGN(16) _M128A { +# ULONGLONG Low; +# LONGLONG High; +# } M128A, *PM128A; +class M128A(Structure): + _fields_ = [ + ("Low", ULONGLONG), + ("High", LONGLONG), + ] +PM128A = POINTER(M128A) + +#--- Constants ---------------------------------------------------------------- + +NULL = None +INFINITE = -1 +TRUE = 1 +FALSE = 0 + +# http://blogs.msdn.com/oldnewthing/archive/2004/08/26/220873.aspx +ANYSIZE_ARRAY = 1 + +# Invalid handle value is -1 casted to void pointer. +try: + INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value #-1 #0xFFFFFFFF +except TypeError: + if sizeof(ctypes.c_void_p) == 4: + INVALID_HANDLE_VALUE = 0xFFFFFFFF + elif sizeof(ctypes.c_void_p) == 8: + INVALID_HANDLE_VALUE = 0xFFFFFFFFFFFFFFFF + else: + raise + +MAX_MODULE_NAME32 = 255 +MAX_PATH = 260 + +# Error codes +# TODO maybe add more error codes? +# if they're too many they could be pickled instead, +# or at the very least put in a new file +ERROR_SUCCESS = 0 +ERROR_INVALID_FUNCTION = 1 +ERROR_FILE_NOT_FOUND = 2 +ERROR_PATH_NOT_FOUND = 3 +ERROR_ACCESS_DENIED = 5 +ERROR_INVALID_HANDLE = 6 +ERROR_NOT_ENOUGH_MEMORY = 8 +ERROR_INVALID_DRIVE = 15 +ERROR_NO_MORE_FILES = 18 +ERROR_BAD_LENGTH = 24 +ERROR_HANDLE_EOF = 38 +ERROR_HANDLE_DISK_FULL = 39 +ERROR_NOT_SUPPORTED = 50 +ERROR_FILE_EXISTS = 80 +ERROR_INVALID_PARAMETER = 87 +ERROR_BUFFER_OVERFLOW = 111 +ERROR_DISK_FULL = 112 +ERROR_CALL_NOT_IMPLEMENTED = 120 +ERROR_SEM_TIMEOUT = 121 +ERROR_INSUFFICIENT_BUFFER = 122 +ERROR_INVALID_NAME = 123 +ERROR_MOD_NOT_FOUND = 126 +ERROR_PROC_NOT_FOUND = 127 +ERROR_DIR_NOT_EMPTY = 145 +ERROR_BAD_THREADID_ADDR = 159 +ERROR_BAD_ARGUMENTS = 160 +ERROR_BAD_PATHNAME = 161 +ERROR_ALREADY_EXISTS = 183 +ERROR_INVALID_FLAG_NUMBER = 186 +ERROR_ENVVAR_NOT_FOUND = 203 +ERROR_FILENAME_EXCED_RANGE = 206 +ERROR_MORE_DATA = 234 + +WAIT_TIMEOUT = 258 + +ERROR_NO_MORE_ITEMS = 259 +ERROR_PARTIAL_COPY = 299 +ERROR_INVALID_ADDRESS = 487 +ERROR_THREAD_NOT_IN_PROCESS = 566 +ERROR_CONTROL_C_EXIT = 572 +ERROR_UNHANDLED_EXCEPTION = 574 +ERROR_ASSERTION_FAILURE = 668 +ERROR_WOW_ASSERTION = 670 + +ERROR_DBG_EXCEPTION_NOT_HANDLED = 688 +ERROR_DBG_REPLY_LATER = 689 +ERROR_DBG_UNABLE_TO_PROVIDE_HANDLE = 690 +ERROR_DBG_TERMINATE_THREAD = 691 +ERROR_DBG_TERMINATE_PROCESS = 692 +ERROR_DBG_CONTROL_C = 693 +ERROR_DBG_PRINTEXCEPTION_C = 694 +ERROR_DBG_RIPEXCEPTION = 695 +ERROR_DBG_CONTROL_BREAK = 696 +ERROR_DBG_COMMAND_EXCEPTION = 697 +ERROR_DBG_EXCEPTION_HANDLED = 766 +ERROR_DBG_CONTINUE = 767 + +ERROR_ELEVATION_REQUIRED = 740 +ERROR_NOACCESS = 998 + +ERROR_CIRCULAR_DEPENDENCY = 1059 +ERROR_SERVICE_DOES_NOT_EXIST = 1060 +ERROR_SERVICE_CANNOT_ACCEPT_CTRL = 1061 +ERROR_SERVICE_NOT_ACTIVE = 1062 +ERROR_FAILED_SERVICE_CONTROLLER_CONNECT = 1063 +ERROR_EXCEPTION_IN_SERVICE = 1064 +ERROR_DATABASE_DOES_NOT_EXIST = 1065 +ERROR_SERVICE_SPECIFIC_ERROR = 1066 +ERROR_PROCESS_ABORTED = 1067 +ERROR_SERVICE_DEPENDENCY_FAIL = 1068 +ERROR_SERVICE_LOGON_FAILED = 1069 +ERROR_SERVICE_START_HANG = 1070 +ERROR_INVALID_SERVICE_LOCK = 1071 +ERROR_SERVICE_MARKED_FOR_DELETE = 1072 +ERROR_SERVICE_EXISTS = 1073 +ERROR_ALREADY_RUNNING_LKG = 1074 +ERROR_SERVICE_DEPENDENCY_DELETED = 1075 +ERROR_BOOT_ALREADY_ACCEPTED = 1076 +ERROR_SERVICE_NEVER_STARTED = 1077 +ERROR_DUPLICATE_SERVICE_NAME = 1078 +ERROR_DIFFERENT_SERVICE_ACCOUNT = 1079 +ERROR_CANNOT_DETECT_DRIVER_FAILURE = 1080 +ERROR_CANNOT_DETECT_PROCESS_ABORT = 1081 +ERROR_NO_RECOVERY_PROGRAM = 1082 +ERROR_SERVICE_NOT_IN_EXE = 1083 +ERROR_NOT_SAFEBOOT_SERVICE = 1084 + +ERROR_DEBUGGER_INACTIVE = 1284 + +ERROR_PRIVILEGE_NOT_HELD = 1314 + +ERROR_NONE_MAPPED = 1332 + +RPC_S_SERVER_UNAVAILABLE = 1722 + +# Standard access rights +import sys +if sys.version_info[0] >= 3: + long = int + +DELETE = long(0x00010000) +READ_CONTROL = long(0x00020000) +WRITE_DAC = long(0x00040000) +WRITE_OWNER = long(0x00080000) +SYNCHRONIZE = long(0x00100000) +STANDARD_RIGHTS_REQUIRED = long(0x000F0000) +STANDARD_RIGHTS_READ = READ_CONTROL +STANDARD_RIGHTS_WRITE = READ_CONTROL +STANDARD_RIGHTS_EXECUTE = READ_CONTROL +STANDARD_RIGHTS_ALL = long(0x001F0000) +SPECIFIC_RIGHTS_ALL = long(0x0000FFFF) + +#--- Structures --------------------------------------------------------------- + +# typedef struct _LSA_UNICODE_STRING { +# USHORT Length; +# USHORT MaximumLength; +# PWSTR Buffer; +# } LSA_UNICODE_STRING, +# *PLSA_UNICODE_STRING, +# UNICODE_STRING, +# *PUNICODE_STRING; +class UNICODE_STRING(Structure): + _fields_ = [ + ("Length", USHORT), + ("MaximumLength", USHORT), + ("Buffer", PVOID), + ] + +# From MSDN: +# +# typedef struct _GUID { +# DWORD Data1; +# WORD Data2; +# WORD Data3; +# BYTE Data4[8]; +# } GUID; +class GUID(Structure): + _fields_ = [ + ("Data1", DWORD), + ("Data2", WORD), + ("Data3", WORD), + ("Data4", BYTE * 8), +] + +# From MSDN: +# +# typedef struct _LIST_ENTRY { +# struct _LIST_ENTRY *Flink; +# struct _LIST_ENTRY *Blink; +# } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY; +class LIST_ENTRY(Structure): + _fields_ = [ + ("Flink", PVOID), # POINTER(LIST_ENTRY) + ("Blink", PVOID), # POINTER(LIST_ENTRY) +] + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +##__all__ = [_x for _x in _all if not _x.startswith('_')] +##__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/gdi32.py b/pydevd_attach_to_process/winappdbg/win32/gdi32.py new file mode 100644 index 0000000..c3b5e6e --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/gdi32.py @@ -0,0 +1,507 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for gdi32.dll in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.kernel32 import GetLastError, SetLastError + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- Helpers ------------------------------------------------------------------ + +#--- Types -------------------------------------------------------------------- + +#--- Constants ---------------------------------------------------------------- + +# GDI object types +OBJ_PEN = 1 +OBJ_BRUSH = 2 +OBJ_DC = 3 +OBJ_METADC = 4 +OBJ_PAL = 5 +OBJ_FONT = 6 +OBJ_BITMAP = 7 +OBJ_REGION = 8 +OBJ_METAFILE = 9 +OBJ_MEMDC = 10 +OBJ_EXTPEN = 11 +OBJ_ENHMETADC = 12 +OBJ_ENHMETAFILE = 13 +OBJ_COLORSPACE = 14 +GDI_OBJ_LAST = OBJ_COLORSPACE + +# Ternary raster operations +SRCCOPY = 0x00CC0020 # dest = source +SRCPAINT = 0x00EE0086 # dest = source OR dest +SRCAND = 0x008800C6 # dest = source AND dest +SRCINVERT = 0x00660046 # dest = source XOR dest +SRCERASE = 0x00440328 # dest = source AND (NOT dest) +NOTSRCCOPY = 0x00330008 # dest = (NOT source) +NOTSRCERASE = 0x001100A6 # dest = (NOT src) AND (NOT dest) +MERGECOPY = 0x00C000CA # dest = (source AND pattern) +MERGEPAINT = 0x00BB0226 # dest = (NOT source) OR dest +PATCOPY = 0x00F00021 # dest = pattern +PATPAINT = 0x00FB0A09 # dest = DPSnoo +PATINVERT = 0x005A0049 # dest = pattern XOR dest +DSTINVERT = 0x00550009 # dest = (NOT dest) +BLACKNESS = 0x00000042 # dest = BLACK +WHITENESS = 0x00FF0062 # dest = WHITE +NOMIRRORBITMAP = 0x80000000 # Do not Mirror the bitmap in this call +CAPTUREBLT = 0x40000000 # Include layered windows + +# Region flags +ERROR = 0 +NULLREGION = 1 +SIMPLEREGION = 2 +COMPLEXREGION = 3 +RGN_ERROR = ERROR + +# CombineRgn() styles +RGN_AND = 1 +RGN_OR = 2 +RGN_XOR = 3 +RGN_DIFF = 4 +RGN_COPY = 5 +RGN_MIN = RGN_AND +RGN_MAX = RGN_COPY + +# StretchBlt() modes +BLACKONWHITE = 1 +WHITEONBLACK = 2 +COLORONCOLOR = 3 +HALFTONE = 4 +MAXSTRETCHBLTMODE = 4 +STRETCH_ANDSCANS = BLACKONWHITE +STRETCH_ORSCANS = WHITEONBLACK +STRETCH_DELETESCANS = COLORONCOLOR +STRETCH_HALFTONE = HALFTONE + +# PolyFill() modes +ALTERNATE = 1 +WINDING = 2 +POLYFILL_LAST = 2 + +# Layout orientation options +LAYOUT_RTL = 0x00000001 # Right to left +LAYOUT_BTT = 0x00000002 # Bottom to top +LAYOUT_VBH = 0x00000004 # Vertical before horizontal +LAYOUT_ORIENTATIONMASK = LAYOUT_RTL + LAYOUT_BTT + LAYOUT_VBH +LAYOUT_BITMAPORIENTATIONPRESERVED = 0x00000008 + +# Stock objects +WHITE_BRUSH = 0 +LTGRAY_BRUSH = 1 +GRAY_BRUSH = 2 +DKGRAY_BRUSH = 3 +BLACK_BRUSH = 4 +NULL_BRUSH = 5 +HOLLOW_BRUSH = NULL_BRUSH +WHITE_PEN = 6 +BLACK_PEN = 7 +NULL_PEN = 8 +OEM_FIXED_FONT = 10 +ANSI_FIXED_FONT = 11 +ANSI_VAR_FONT = 12 +SYSTEM_FONT = 13 +DEVICE_DEFAULT_FONT = 14 +DEFAULT_PALETTE = 15 +SYSTEM_FIXED_FONT = 16 + +# Metafile functions +META_SETBKCOLOR = 0x0201 +META_SETBKMODE = 0x0102 +META_SETMAPMODE = 0x0103 +META_SETROP2 = 0x0104 +META_SETRELABS = 0x0105 +META_SETPOLYFILLMODE = 0x0106 +META_SETSTRETCHBLTMODE = 0x0107 +META_SETTEXTCHAREXTRA = 0x0108 +META_SETTEXTCOLOR = 0x0209 +META_SETTEXTJUSTIFICATION = 0x020A +META_SETWINDOWORG = 0x020B +META_SETWINDOWEXT = 0x020C +META_SETVIEWPORTORG = 0x020D +META_SETVIEWPORTEXT = 0x020E +META_OFFSETWINDOWORG = 0x020F +META_SCALEWINDOWEXT = 0x0410 +META_OFFSETVIEWPORTORG = 0x0211 +META_SCALEVIEWPORTEXT = 0x0412 +META_LINETO = 0x0213 +META_MOVETO = 0x0214 +META_EXCLUDECLIPRECT = 0x0415 +META_INTERSECTCLIPRECT = 0x0416 +META_ARC = 0x0817 +META_ELLIPSE = 0x0418 +META_FLOODFILL = 0x0419 +META_PIE = 0x081A +META_RECTANGLE = 0x041B +META_ROUNDRECT = 0x061C +META_PATBLT = 0x061D +META_SAVEDC = 0x001E +META_SETPIXEL = 0x041F +META_OFFSETCLIPRGN = 0x0220 +META_TEXTOUT = 0x0521 +META_BITBLT = 0x0922 +META_STRETCHBLT = 0x0B23 +META_POLYGON = 0x0324 +META_POLYLINE = 0x0325 +META_ESCAPE = 0x0626 +META_RESTOREDC = 0x0127 +META_FILLREGION = 0x0228 +META_FRAMEREGION = 0x0429 +META_INVERTREGION = 0x012A +META_PAINTREGION = 0x012B +META_SELECTCLIPREGION = 0x012C +META_SELECTOBJECT = 0x012D +META_SETTEXTALIGN = 0x012E +META_CHORD = 0x0830 +META_SETMAPPERFLAGS = 0x0231 +META_EXTTEXTOUT = 0x0a32 +META_SETDIBTODEV = 0x0d33 +META_SELECTPALETTE = 0x0234 +META_REALIZEPALETTE = 0x0035 +META_ANIMATEPALETTE = 0x0436 +META_SETPALENTRIES = 0x0037 +META_POLYPOLYGON = 0x0538 +META_RESIZEPALETTE = 0x0139 +META_DIBBITBLT = 0x0940 +META_DIBSTRETCHBLT = 0x0b41 +META_DIBCREATEPATTERNBRUSH = 0x0142 +META_STRETCHDIB = 0x0f43 +META_EXTFLOODFILL = 0x0548 +META_SETLAYOUT = 0x0149 +META_DELETEOBJECT = 0x01f0 +META_CREATEPALETTE = 0x00f7 +META_CREATEPATTERNBRUSH = 0x01F9 +META_CREATEPENINDIRECT = 0x02FA +META_CREATEFONTINDIRECT = 0x02FB +META_CREATEBRUSHINDIRECT = 0x02FC +META_CREATEREGION = 0x06FF + +# Metafile escape codes +NEWFRAME = 1 +ABORTDOC = 2 +NEXTBAND = 3 +SETCOLORTABLE = 4 +GETCOLORTABLE = 5 +FLUSHOUTPUT = 6 +DRAFTMODE = 7 +QUERYESCSUPPORT = 8 +SETABORTPROC = 9 +STARTDOC = 10 +ENDDOC = 11 +GETPHYSPAGESIZE = 12 +GETPRINTINGOFFSET = 13 +GETSCALINGFACTOR = 14 +MFCOMMENT = 15 +GETPENWIDTH = 16 +SETCOPYCOUNT = 17 +SELECTPAPERSOURCE = 18 +DEVICEDATA = 19 +PASSTHROUGH = 19 +GETTECHNOLGY = 20 +GETTECHNOLOGY = 20 +SETLINECAP = 21 +SETLINEJOIN = 22 +SETMITERLIMIT = 23 +BANDINFO = 24 +DRAWPATTERNRECT = 25 +GETVECTORPENSIZE = 26 +GETVECTORBRUSHSIZE = 27 +ENABLEDUPLEX = 28 +GETSETPAPERBINS = 29 +GETSETPRINTORIENT = 30 +ENUMPAPERBINS = 31 +SETDIBSCALING = 32 +EPSPRINTING = 33 +ENUMPAPERMETRICS = 34 +GETSETPAPERMETRICS = 35 +POSTSCRIPT_DATA = 37 +POSTSCRIPT_IGNORE = 38 +MOUSETRAILS = 39 +GETDEVICEUNITS = 42 +GETEXTENDEDTEXTMETRICS = 256 +GETEXTENTTABLE = 257 +GETPAIRKERNTABLE = 258 +GETTRACKKERNTABLE = 259 +EXTTEXTOUT = 512 +GETFACENAME = 513 +DOWNLOADFACE = 514 +ENABLERELATIVEWIDTHS = 768 +ENABLEPAIRKERNING = 769 +SETKERNTRACK = 770 +SETALLJUSTVALUES = 771 +SETCHARSET = 772 +STRETCHBLT = 2048 +METAFILE_DRIVER = 2049 +GETSETSCREENPARAMS = 3072 +QUERYDIBSUPPORT = 3073 +BEGIN_PATH = 4096 +CLIP_TO_PATH = 4097 +END_PATH = 4098 +EXT_DEVICE_CAPS = 4099 +RESTORE_CTM = 4100 +SAVE_CTM = 4101 +SET_ARC_DIRECTION = 4102 +SET_BACKGROUND_COLOR = 4103 +SET_POLY_MODE = 4104 +SET_SCREEN_ANGLE = 4105 +SET_SPREAD = 4106 +TRANSFORM_CTM = 4107 +SET_CLIP_BOX = 4108 +SET_BOUNDS = 4109 +SET_MIRROR_MODE = 4110 +OPENCHANNEL = 4110 +DOWNLOADHEADER = 4111 +CLOSECHANNEL = 4112 +POSTSCRIPT_PASSTHROUGH = 4115 +ENCAPSULATED_POSTSCRIPT = 4116 +POSTSCRIPT_IDENTIFY = 4117 +POSTSCRIPT_INJECTION = 4118 +CHECKJPEGFORMAT = 4119 +CHECKPNGFORMAT = 4120 +GET_PS_FEATURESETTING = 4121 +GDIPLUS_TS_QUERYVER = 4122 +GDIPLUS_TS_RECORD = 4123 +SPCLPASSTHROUGH2 = 4568 + +#--- Structures --------------------------------------------------------------- + +# typedef struct _RECT { +# LONG left; +# LONG top; +# LONG right; +# LONG bottom; +# }RECT, *PRECT; +class RECT(Structure): + _fields_ = [ + ('left', LONG), + ('top', LONG), + ('right', LONG), + ('bottom', LONG), + ] +PRECT = POINTER(RECT) +LPRECT = PRECT + +# typedef struct tagPOINT { +# LONG x; +# LONG y; +# } POINT; +class POINT(Structure): + _fields_ = [ + ('x', LONG), + ('y', LONG), + ] +PPOINT = POINTER(POINT) +LPPOINT = PPOINT + +# typedef struct tagBITMAP { +# LONG bmType; +# LONG bmWidth; +# LONG bmHeight; +# LONG bmWidthBytes; +# WORD bmPlanes; +# WORD bmBitsPixel; +# LPVOID bmBits; +# } BITMAP, *PBITMAP; +class BITMAP(Structure): + _fields_ = [ + ("bmType", LONG), + ("bmWidth", LONG), + ("bmHeight", LONG), + ("bmWidthBytes", LONG), + ("bmPlanes", WORD), + ("bmBitsPixel", WORD), + ("bmBits", LPVOID), + ] +PBITMAP = POINTER(BITMAP) +LPBITMAP = PBITMAP + +#--- High level classes ------------------------------------------------------- + +#--- gdi32.dll ---------------------------------------------------------------- + +# HDC GetDC( +# __in HWND hWnd +# ); +def GetDC(hWnd): + _GetDC = windll.gdi32.GetDC + _GetDC.argtypes = [HWND] + _GetDC.restype = HDC + _GetDC.errcheck = RaiseIfZero + return _GetDC(hWnd) + +# HDC GetWindowDC( +# __in HWND hWnd +# ); +def GetWindowDC(hWnd): + _GetWindowDC = windll.gdi32.GetWindowDC + _GetWindowDC.argtypes = [HWND] + _GetWindowDC.restype = HDC + _GetWindowDC.errcheck = RaiseIfZero + return _GetWindowDC(hWnd) + +# int ReleaseDC( +# __in HWND hWnd, +# __in HDC hDC +# ); +def ReleaseDC(hWnd, hDC): + _ReleaseDC = windll.gdi32.ReleaseDC + _ReleaseDC.argtypes = [HWND, HDC] + _ReleaseDC.restype = ctypes.c_int + _ReleaseDC.errcheck = RaiseIfZero + _ReleaseDC(hWnd, hDC) + +# HGDIOBJ SelectObject( +# __in HDC hdc, +# __in HGDIOBJ hgdiobj +# ); +def SelectObject(hdc, hgdiobj): + _SelectObject = windll.gdi32.SelectObject + _SelectObject.argtypes = [HDC, HGDIOBJ] + _SelectObject.restype = HGDIOBJ + _SelectObject.errcheck = RaiseIfZero + return _SelectObject(hdc, hgdiobj) + +# HGDIOBJ GetStockObject( +# __in int fnObject +# ); +def GetStockObject(fnObject): + _GetStockObject = windll.gdi32.GetStockObject + _GetStockObject.argtypes = [ctypes.c_int] + _GetStockObject.restype = HGDIOBJ + _GetStockObject.errcheck = RaiseIfZero + return _GetStockObject(fnObject) + +# DWORD GetObjectType( +# __in HGDIOBJ h +# ); +def GetObjectType(h): + _GetObjectType = windll.gdi32.GetObjectType + _GetObjectType.argtypes = [HGDIOBJ] + _GetObjectType.restype = DWORD + _GetObjectType.errcheck = RaiseIfZero + return _GetObjectType(h) + +# int GetObject( +# __in HGDIOBJ hgdiobj, +# __in int cbBuffer, +# __out LPVOID lpvObject +# ); +def GetObject(hgdiobj, cbBuffer = None, lpvObject = None): + _GetObject = windll.gdi32.GetObject + _GetObject.argtypes = [HGDIOBJ, ctypes.c_int, LPVOID] + _GetObject.restype = ctypes.c_int + _GetObject.errcheck = RaiseIfZero + + # Both cbBuffer and lpvObject can be omitted, the correct + # size and structure to return are automatically deduced. + # If lpvObject is given it must be a ctypes object, not a pointer. + # Always returns a ctypes object. + + if cbBuffer is not None: + if lpvObject is None: + lpvObject = ctypes.create_string_buffer("", cbBuffer) + elif lpvObject is not None: + cbBuffer = sizeof(lpvObject) + else: # most likely case, both are None + t = GetObjectType(hgdiobj) + if t == OBJ_PEN: + cbBuffer = sizeof(LOGPEN) + lpvObject = LOGPEN() + elif t == OBJ_BRUSH: + cbBuffer = sizeof(LOGBRUSH) + lpvObject = LOGBRUSH() + elif t == OBJ_PAL: + cbBuffer = _GetObject(hgdiobj, 0, None) + lpvObject = (WORD * (cbBuffer // sizeof(WORD)))() + elif t == OBJ_FONT: + cbBuffer = sizeof(LOGFONT) + lpvObject = LOGFONT() + elif t == OBJ_BITMAP: # try the two possible types of bitmap + cbBuffer = sizeof(DIBSECTION) + lpvObject = DIBSECTION() + try: + _GetObject(hgdiobj, cbBuffer, byref(lpvObject)) + return lpvObject + except WindowsError: + cbBuffer = sizeof(BITMAP) + lpvObject = BITMAP() + elif t == OBJ_EXTPEN: + cbBuffer = sizeof(LOGEXTPEN) + lpvObject = LOGEXTPEN() + else: + cbBuffer = _GetObject(hgdiobj, 0, None) + lpvObject = ctypes.create_string_buffer("", cbBuffer) + _GetObject(hgdiobj, cbBuffer, byref(lpvObject)) + return lpvObject + +# LONG GetBitmapBits( +# __in HBITMAP hbmp, +# __in LONG cbBuffer, +# __out LPVOID lpvBits +# ); +def GetBitmapBits(hbmp): + _GetBitmapBits = windll.gdi32.GetBitmapBits + _GetBitmapBits.argtypes = [HBITMAP, LONG, LPVOID] + _GetBitmapBits.restype = LONG + _GetBitmapBits.errcheck = RaiseIfZero + + bitmap = GetObject(hbmp, lpvObject = BITMAP()) + cbBuffer = bitmap.bmWidthBytes * bitmap.bmHeight + lpvBits = ctypes.create_string_buffer("", cbBuffer) + _GetBitmapBits(hbmp, cbBuffer, byref(lpvBits)) + return lpvBits.raw + +# HBITMAP CreateBitmapIndirect( +# __in const BITMAP *lpbm +# ); +def CreateBitmapIndirect(lpbm): + _CreateBitmapIndirect = windll.gdi32.CreateBitmapIndirect + _CreateBitmapIndirect.argtypes = [PBITMAP] + _CreateBitmapIndirect.restype = HBITMAP + _CreateBitmapIndirect.errcheck = RaiseIfZero + return _CreateBitmapIndirect(lpbm) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/kernel32.py b/pydevd_attach_to_process/winappdbg/win32/kernel32.py new file mode 100644 index 0000000..d0c0468 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/kernel32.py @@ -0,0 +1,4716 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for kernel32.dll in ctypes. +""" + +__revision__ = "$Id$" + +import warnings + +from winappdbg.win32.defines import * + +from winappdbg.win32 import context_i386 +from winappdbg.win32 import context_amd64 + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +_all.add('version') +#============================================================================== + +from winappdbg.win32.version import * + +#------------------------------------------------------------------------------ + +# This can't be defined in defines.py because it calls GetLastError(). +def RaiseIfLastError(result, func = None, arguments = ()): + """ + Error checking for Win32 API calls with no error-specific return value. + + Regardless of the return value, the function calls GetLastError(). If the + code is not C{ERROR_SUCCESS} then a C{WindowsError} exception is raised. + + For this to work, the user MUST call SetLastError(ERROR_SUCCESS) prior to + calling the API. Otherwise an exception may be raised even on success, + since most API calls don't clear the error status code. + """ + code = GetLastError() + if code != ERROR_SUCCESS: + raise ctypes.WinError(code) + return result + +#--- CONTEXT structure and constants ------------------------------------------ + +ContextArchMask = 0x0FFF0000 # just guessing here! seems to work, though + +if arch == ARCH_I386: + from winappdbg.win32.context_i386 import * +elif arch == ARCH_AMD64: + if bits == 64: + from winappdbg.win32.context_amd64 import * + else: + from winappdbg.win32.context_i386 import * +else: + warnings.warn("Unknown or unsupported architecture: %s" % arch) + +#--- Constants ---------------------------------------------------------------- + +STILL_ACTIVE = 259 + +WAIT_TIMEOUT = 0x102 +WAIT_FAILED = -1 +WAIT_OBJECT_0 = 0 + +EXCEPTION_NONCONTINUABLE = 0x1 # Noncontinuable exception +EXCEPTION_MAXIMUM_PARAMETERS = 15 # maximum number of exception parameters +MAXIMUM_WAIT_OBJECTS = 64 # Maximum number of wait objects +MAXIMUM_SUSPEND_COUNT = 0x7f # Maximum times thread can be suspended + +FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100 +FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 + +GR_GDIOBJECTS = 0 +GR_USEROBJECTS = 1 + +PROCESS_NAME_NATIVE = 1 + +MAXINTATOM = 0xC000 + +STD_INPUT_HANDLE = 0xFFFFFFF6 # (DWORD)-10 +STD_OUTPUT_HANDLE = 0xFFFFFFF5 # (DWORD)-11 +STD_ERROR_HANDLE = 0xFFFFFFF4 # (DWORD)-12 + +ATTACH_PARENT_PROCESS = 0xFFFFFFFF # (DWORD)-1 + +# LoadLibraryEx constants +DONT_RESOLVE_DLL_REFERENCES = 0x00000001 +LOAD_LIBRARY_AS_DATAFILE = 0x00000002 +LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 +LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010 +LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020 +LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040 + +# SetSearchPathMode flags +# TODO I couldn't find these constants :( +##BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE = ??? +##BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE = ??? +##BASE_SEARCH_PATH_PERMANENT = ??? + +# Console control events +CTRL_C_EVENT = 0 +CTRL_BREAK_EVENT = 1 +CTRL_CLOSE_EVENT = 2 +CTRL_LOGOFF_EVENT = 5 +CTRL_SHUTDOWN_EVENT = 6 + +# Heap flags +HEAP_NO_SERIALIZE = 0x00000001 +HEAP_GENERATE_EXCEPTIONS = 0x00000004 +HEAP_ZERO_MEMORY = 0x00000008 +HEAP_CREATE_ENABLE_EXECUTE = 0x00040000 + +# Standard access rights +DELETE = long(0x00010000) +READ_CONTROL = long(0x00020000) +WRITE_DAC = long(0x00040000) +WRITE_OWNER = long(0x00080000) +SYNCHRONIZE = long(0x00100000) +STANDARD_RIGHTS_REQUIRED = long(0x000F0000) +STANDARD_RIGHTS_READ = (READ_CONTROL) +STANDARD_RIGHTS_WRITE = (READ_CONTROL) +STANDARD_RIGHTS_EXECUTE = (READ_CONTROL) +STANDARD_RIGHTS_ALL = long(0x001F0000) +SPECIFIC_RIGHTS_ALL = long(0x0000FFFF) + +# Mutex access rights +MUTEX_ALL_ACCESS = 0x1F0001 +MUTEX_MODIFY_STATE = 1 + +# Event access rights +EVENT_ALL_ACCESS = 0x1F0003 +EVENT_MODIFY_STATE = 2 + +# Semaphore access rights +SEMAPHORE_ALL_ACCESS = 0x1F0003 +SEMAPHORE_MODIFY_STATE = 2 + +# Timer access rights +TIMER_ALL_ACCESS = 0x1F0003 +TIMER_MODIFY_STATE = 2 +TIMER_QUERY_STATE = 1 + +# Process access rights for OpenProcess +PROCESS_TERMINATE = 0x0001 +PROCESS_CREATE_THREAD = 0x0002 +PROCESS_SET_SESSIONID = 0x0004 +PROCESS_VM_OPERATION = 0x0008 +PROCESS_VM_READ = 0x0010 +PROCESS_VM_WRITE = 0x0020 +PROCESS_DUP_HANDLE = 0x0040 +PROCESS_CREATE_PROCESS = 0x0080 +PROCESS_SET_QUOTA = 0x0100 +PROCESS_SET_INFORMATION = 0x0200 +PROCESS_QUERY_INFORMATION = 0x0400 +PROCESS_SUSPEND_RESUME = 0x0800 +PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 + +# Thread access rights for OpenThread +THREAD_TERMINATE = 0x0001 +THREAD_SUSPEND_RESUME = 0x0002 +THREAD_ALERT = 0x0004 +THREAD_GET_CONTEXT = 0x0008 +THREAD_SET_CONTEXT = 0x0010 +THREAD_SET_INFORMATION = 0x0020 +THREAD_QUERY_INFORMATION = 0x0040 +THREAD_SET_THREAD_TOKEN = 0x0080 +THREAD_IMPERSONATE = 0x0100 +THREAD_DIRECT_IMPERSONATION = 0x0200 +THREAD_SET_LIMITED_INFORMATION = 0x0400 +THREAD_QUERY_LIMITED_INFORMATION = 0x0800 + +# The values of PROCESS_ALL_ACCESS and THREAD_ALL_ACCESS were changed in Vista/2008 +PROCESS_ALL_ACCESS_NT = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF) +PROCESS_ALL_ACCESS_VISTA = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF) +THREAD_ALL_ACCESS_NT = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3FF) +THREAD_ALL_ACCESS_VISTA = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF) +if NTDDI_VERSION < NTDDI_VISTA: + PROCESS_ALL_ACCESS = PROCESS_ALL_ACCESS_NT + THREAD_ALL_ACCESS = THREAD_ALL_ACCESS_NT +else: + PROCESS_ALL_ACCESS = PROCESS_ALL_ACCESS_VISTA + THREAD_ALL_ACCESS = THREAD_ALL_ACCESS_VISTA + +# Process priority classes + +IDLE_PRIORITY_CLASS = 0x00000040 +BELOW_NORMAL_PRIORITY_CLASS = 0x00004000 +NORMAL_PRIORITY_CLASS = 0x00000020 +ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000 +HIGH_PRIORITY_CLASS = 0x00000080 +REALTIME_PRIORITY_CLASS = 0x00000100 + +PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000 +PROCESS_MODE_BACKGROUND_END = 0x00200000 + +# dwCreationFlag values + +DEBUG_PROCESS = 0x00000001 +DEBUG_ONLY_THIS_PROCESS = 0x00000002 +CREATE_SUSPENDED = 0x00000004 # Threads and processes +DETACHED_PROCESS = 0x00000008 +CREATE_NEW_CONSOLE = 0x00000010 +NORMAL_PRIORITY_CLASS = 0x00000020 +IDLE_PRIORITY_CLASS = 0x00000040 +HIGH_PRIORITY_CLASS = 0x00000080 +REALTIME_PRIORITY_CLASS = 0x00000100 +CREATE_NEW_PROCESS_GROUP = 0x00000200 +CREATE_UNICODE_ENVIRONMENT = 0x00000400 +CREATE_SEPARATE_WOW_VDM = 0x00000800 +CREATE_SHARED_WOW_VDM = 0x00001000 +CREATE_FORCEDOS = 0x00002000 +BELOW_NORMAL_PRIORITY_CLASS = 0x00004000 +ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000 +INHERIT_PARENT_AFFINITY = 0x00010000 +STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000 # Threads only +INHERIT_CALLER_PRIORITY = 0x00020000 # Deprecated +CREATE_PROTECTED_PROCESS = 0x00040000 +EXTENDED_STARTUPINFO_PRESENT = 0x00080000 +PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000 +PROCESS_MODE_BACKGROUND_END = 0x00200000 +CREATE_BREAKAWAY_FROM_JOB = 0x01000000 +CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000 +CREATE_DEFAULT_ERROR_MODE = 0x04000000 +CREATE_NO_WINDOW = 0x08000000 +PROFILE_USER = 0x10000000 +PROFILE_KERNEL = 0x20000000 +PROFILE_SERVER = 0x40000000 +CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000 + +# Thread priority values + +THREAD_BASE_PRIORITY_LOWRT = 15 # value that gets a thread to LowRealtime-1 +THREAD_BASE_PRIORITY_MAX = 2 # maximum thread base priority boost +THREAD_BASE_PRIORITY_MIN = (-2) # minimum thread base priority boost +THREAD_BASE_PRIORITY_IDLE = (-15) # value that gets a thread to idle + +THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN +THREAD_PRIORITY_BELOW_NORMAL = (THREAD_PRIORITY_LOWEST+1) +THREAD_PRIORITY_NORMAL = 0 +THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX +THREAD_PRIORITY_ABOVE_NORMAL = (THREAD_PRIORITY_HIGHEST-1) +THREAD_PRIORITY_ERROR_RETURN = long(0xFFFFFFFF) + +THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT +THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE + +# Memory access +SECTION_QUERY = 0x0001 +SECTION_MAP_WRITE = 0x0002 +SECTION_MAP_READ = 0x0004 +SECTION_MAP_EXECUTE = 0x0008 +SECTION_EXTEND_SIZE = 0x0010 +SECTION_MAP_EXECUTE_EXPLICIT = 0x0020 # not included in SECTION_ALL_ACCESS + +SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|\ + SECTION_MAP_WRITE | \ + SECTION_MAP_READ | \ + SECTION_MAP_EXECUTE | \ + SECTION_EXTEND_SIZE) +PAGE_NOACCESS = 0x01 +PAGE_READONLY = 0x02 +PAGE_READWRITE = 0x04 +PAGE_WRITECOPY = 0x08 +PAGE_EXECUTE = 0x10 +PAGE_EXECUTE_READ = 0x20 +PAGE_EXECUTE_READWRITE = 0x40 +PAGE_EXECUTE_WRITECOPY = 0x80 +PAGE_GUARD = 0x100 +PAGE_NOCACHE = 0x200 +PAGE_WRITECOMBINE = 0x400 +MEM_COMMIT = 0x1000 +MEM_RESERVE = 0x2000 +MEM_DECOMMIT = 0x4000 +MEM_RELEASE = 0x8000 +MEM_FREE = 0x10000 +MEM_PRIVATE = 0x20000 +MEM_MAPPED = 0x40000 +MEM_RESET = 0x80000 +MEM_TOP_DOWN = 0x100000 +MEM_WRITE_WATCH = 0x200000 +MEM_PHYSICAL = 0x400000 +MEM_LARGE_PAGES = 0x20000000 +MEM_4MB_PAGES = 0x80000000 +SEC_FILE = 0x800000 +SEC_IMAGE = 0x1000000 +SEC_RESERVE = 0x4000000 +SEC_COMMIT = 0x8000000 +SEC_NOCACHE = 0x10000000 +SEC_LARGE_PAGES = 0x80000000 +MEM_IMAGE = SEC_IMAGE +WRITE_WATCH_FLAG_RESET = 0x01 +FILE_MAP_ALL_ACCESS = 0xF001F + +SECTION_QUERY = 0x0001 +SECTION_MAP_WRITE = 0x0002 +SECTION_MAP_READ = 0x0004 +SECTION_MAP_EXECUTE = 0x0008 +SECTION_EXTEND_SIZE = 0x0010 +SECTION_MAP_EXECUTE_EXPLICIT = 0x0020 # not included in SECTION_ALL_ACCESS + +SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|\ + SECTION_MAP_WRITE | \ + SECTION_MAP_READ | \ + SECTION_MAP_EXECUTE | \ + SECTION_EXTEND_SIZE) + +FILE_MAP_COPY = SECTION_QUERY +FILE_MAP_WRITE = SECTION_MAP_WRITE +FILE_MAP_READ = SECTION_MAP_READ +FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS +FILE_MAP_EXECUTE = SECTION_MAP_EXECUTE_EXPLICIT # not included in FILE_MAP_ALL_ACCESS + +GENERIC_READ = 0x80000000 +GENERIC_WRITE = 0x40000000 +GENERIC_EXECUTE = 0x20000000 +GENERIC_ALL = 0x10000000 + +FILE_SHARE_READ = 0x00000001 +FILE_SHARE_WRITE = 0x00000002 +FILE_SHARE_DELETE = 0x00000004 + +CREATE_NEW = 1 +CREATE_ALWAYS = 2 +OPEN_EXISTING = 3 +OPEN_ALWAYS = 4 +TRUNCATE_EXISTING = 5 + +FILE_ATTRIBUTE_READONLY = 0x00000001 +FILE_ATTRIBUTE_NORMAL = 0x00000080 +FILE_ATTRIBUTE_TEMPORARY = 0x00000100 + +FILE_FLAG_WRITE_THROUGH = 0x80000000 +FILE_FLAG_NO_BUFFERING = 0x20000000 +FILE_FLAG_RANDOM_ACCESS = 0x10000000 +FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000 +FILE_FLAG_DELETE_ON_CLOSE = 0x04000000 +FILE_FLAG_OVERLAPPED = 0x40000000 + +FILE_ATTRIBUTE_READONLY = 0x00000001 +FILE_ATTRIBUTE_HIDDEN = 0x00000002 +FILE_ATTRIBUTE_SYSTEM = 0x00000004 +FILE_ATTRIBUTE_DIRECTORY = 0x00000010 +FILE_ATTRIBUTE_ARCHIVE = 0x00000020 +FILE_ATTRIBUTE_DEVICE = 0x00000040 +FILE_ATTRIBUTE_NORMAL = 0x00000080 +FILE_ATTRIBUTE_TEMPORARY = 0x00000100 + +# Debug events +EXCEPTION_DEBUG_EVENT = 1 +CREATE_THREAD_DEBUG_EVENT = 2 +CREATE_PROCESS_DEBUG_EVENT = 3 +EXIT_THREAD_DEBUG_EVENT = 4 +EXIT_PROCESS_DEBUG_EVENT = 5 +LOAD_DLL_DEBUG_EVENT = 6 +UNLOAD_DLL_DEBUG_EVENT = 7 +OUTPUT_DEBUG_STRING_EVENT = 8 +RIP_EVENT = 9 + +# Debug status codes (ContinueDebugEvent) +DBG_EXCEPTION_HANDLED = long(0x00010001) +DBG_CONTINUE = long(0x00010002) +DBG_REPLY_LATER = long(0x40010001) +DBG_UNABLE_TO_PROVIDE_HANDLE = long(0x40010002) +DBG_TERMINATE_THREAD = long(0x40010003) +DBG_TERMINATE_PROCESS = long(0x40010004) +DBG_CONTROL_C = long(0x40010005) +DBG_PRINTEXCEPTION_C = long(0x40010006) +DBG_RIPEXCEPTION = long(0x40010007) +DBG_CONTROL_BREAK = long(0x40010008) +DBG_COMMAND_EXCEPTION = long(0x40010009) +DBG_EXCEPTION_NOT_HANDLED = long(0x80010001) +DBG_NO_STATE_CHANGE = long(0xC0010001) +DBG_APP_NOT_IDLE = long(0xC0010002) + +# Status codes +STATUS_WAIT_0 = long(0x00000000) +STATUS_ABANDONED_WAIT_0 = long(0x00000080) +STATUS_USER_APC = long(0x000000C0) +STATUS_TIMEOUT = long(0x00000102) +STATUS_PENDING = long(0x00000103) +STATUS_SEGMENT_NOTIFICATION = long(0x40000005) +STATUS_GUARD_PAGE_VIOLATION = long(0x80000001) +STATUS_DATATYPE_MISALIGNMENT = long(0x80000002) +STATUS_BREAKPOINT = long(0x80000003) +STATUS_SINGLE_STEP = long(0x80000004) +STATUS_INVALID_INFO_CLASS = long(0xC0000003) +STATUS_ACCESS_VIOLATION = long(0xC0000005) +STATUS_IN_PAGE_ERROR = long(0xC0000006) +STATUS_INVALID_HANDLE = long(0xC0000008) +STATUS_NO_MEMORY = long(0xC0000017) +STATUS_ILLEGAL_INSTRUCTION = long(0xC000001D) +STATUS_NONCONTINUABLE_EXCEPTION = long(0xC0000025) +STATUS_INVALID_DISPOSITION = long(0xC0000026) +STATUS_ARRAY_BOUNDS_EXCEEDED = long(0xC000008C) +STATUS_FLOAT_DENORMAL_OPERAND = long(0xC000008D) +STATUS_FLOAT_DIVIDE_BY_ZERO = long(0xC000008E) +STATUS_FLOAT_INEXACT_RESULT = long(0xC000008F) +STATUS_FLOAT_INVALID_OPERATION = long(0xC0000090) +STATUS_FLOAT_OVERFLOW = long(0xC0000091) +STATUS_FLOAT_STACK_CHECK = long(0xC0000092) +STATUS_FLOAT_UNDERFLOW = long(0xC0000093) +STATUS_INTEGER_DIVIDE_BY_ZERO = long(0xC0000094) +STATUS_INTEGER_OVERFLOW = long(0xC0000095) +STATUS_PRIVILEGED_INSTRUCTION = long(0xC0000096) +STATUS_STACK_OVERFLOW = long(0xC00000FD) +STATUS_CONTROL_C_EXIT = long(0xC000013A) +STATUS_FLOAT_MULTIPLE_FAULTS = long(0xC00002B4) +STATUS_FLOAT_MULTIPLE_TRAPS = long(0xC00002B5) +STATUS_REG_NAT_CONSUMPTION = long(0xC00002C9) +STATUS_SXS_EARLY_DEACTIVATION = long(0xC015000F) +STATUS_SXS_INVALID_DEACTIVATION = long(0xC0150010) + +STATUS_STACK_BUFFER_OVERRUN = long(0xC0000409) +STATUS_WX86_BREAKPOINT = long(0x4000001F) +STATUS_HEAP_CORRUPTION = long(0xC0000374) + +STATUS_POSSIBLE_DEADLOCK = long(0xC0000194) + +STATUS_UNWIND_CONSOLIDATE = long(0x80000029) + +# Exception codes + +EXCEPTION_ACCESS_VIOLATION = STATUS_ACCESS_VIOLATION +EXCEPTION_ARRAY_BOUNDS_EXCEEDED = STATUS_ARRAY_BOUNDS_EXCEEDED +EXCEPTION_BREAKPOINT = STATUS_BREAKPOINT +EXCEPTION_DATATYPE_MISALIGNMENT = STATUS_DATATYPE_MISALIGNMENT +EXCEPTION_FLT_DENORMAL_OPERAND = STATUS_FLOAT_DENORMAL_OPERAND +EXCEPTION_FLT_DIVIDE_BY_ZERO = STATUS_FLOAT_DIVIDE_BY_ZERO +EXCEPTION_FLT_INEXACT_RESULT = STATUS_FLOAT_INEXACT_RESULT +EXCEPTION_FLT_INVALID_OPERATION = STATUS_FLOAT_INVALID_OPERATION +EXCEPTION_FLT_OVERFLOW = STATUS_FLOAT_OVERFLOW +EXCEPTION_FLT_STACK_CHECK = STATUS_FLOAT_STACK_CHECK +EXCEPTION_FLT_UNDERFLOW = STATUS_FLOAT_UNDERFLOW +EXCEPTION_ILLEGAL_INSTRUCTION = STATUS_ILLEGAL_INSTRUCTION +EXCEPTION_IN_PAGE_ERROR = STATUS_IN_PAGE_ERROR +EXCEPTION_INT_DIVIDE_BY_ZERO = STATUS_INTEGER_DIVIDE_BY_ZERO +EXCEPTION_INT_OVERFLOW = STATUS_INTEGER_OVERFLOW +EXCEPTION_INVALID_DISPOSITION = STATUS_INVALID_DISPOSITION +EXCEPTION_NONCONTINUABLE_EXCEPTION = STATUS_NONCONTINUABLE_EXCEPTION +EXCEPTION_PRIV_INSTRUCTION = STATUS_PRIVILEGED_INSTRUCTION +EXCEPTION_SINGLE_STEP = STATUS_SINGLE_STEP +EXCEPTION_STACK_OVERFLOW = STATUS_STACK_OVERFLOW + +EXCEPTION_GUARD_PAGE = STATUS_GUARD_PAGE_VIOLATION +EXCEPTION_INVALID_HANDLE = STATUS_INVALID_HANDLE +EXCEPTION_POSSIBLE_DEADLOCK = STATUS_POSSIBLE_DEADLOCK +EXCEPTION_WX86_BREAKPOINT = STATUS_WX86_BREAKPOINT + +CONTROL_C_EXIT = STATUS_CONTROL_C_EXIT + +DBG_CONTROL_C = long(0x40010005) +MS_VC_EXCEPTION = long(0x406D1388) + +# Access violation types +ACCESS_VIOLATION_TYPE_READ = EXCEPTION_READ_FAULT +ACCESS_VIOLATION_TYPE_WRITE = EXCEPTION_WRITE_FAULT +ACCESS_VIOLATION_TYPE_DEP = EXCEPTION_EXECUTE_FAULT + +# RIP event types +SLE_ERROR = 1 +SLE_MINORERROR = 2 +SLE_WARNING = 3 + +# DuplicateHandle constants +DUPLICATE_CLOSE_SOURCE = 0x00000001 +DUPLICATE_SAME_ACCESS = 0x00000002 + +# GetFinalPathNameByHandle constants +FILE_NAME_NORMALIZED = 0x0 +FILE_NAME_OPENED = 0x8 +VOLUME_NAME_DOS = 0x0 +VOLUME_NAME_GUID = 0x1 +VOLUME_NAME_NONE = 0x4 +VOLUME_NAME_NT = 0x2 + +# GetProductInfo constants +PRODUCT_BUSINESS = 0x00000006 +PRODUCT_BUSINESS_N = 0x00000010 +PRODUCT_CLUSTER_SERVER = 0x00000012 +PRODUCT_DATACENTER_SERVER = 0x00000008 +PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C +PRODUCT_DATACENTER_SERVER_CORE_V = 0x00000027 +PRODUCT_DATACENTER_SERVER_V = 0x00000025 +PRODUCT_ENTERPRISE = 0x00000004 +PRODUCT_ENTERPRISE_E = 0x00000046 +PRODUCT_ENTERPRISE_N = 0x0000001B +PRODUCT_ENTERPRISE_SERVER = 0x0000000A +PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E +PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029 +PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F +PRODUCT_ENTERPRISE_SERVER_V = 0x00000026 +PRODUCT_HOME_BASIC = 0x00000002 +PRODUCT_HOME_BASIC_E = 0x00000043 +PRODUCT_HOME_BASIC_N = 0x00000005 +PRODUCT_HOME_PREMIUM = 0x00000003 +PRODUCT_HOME_PREMIUM_E = 0x00000044 +PRODUCT_HOME_PREMIUM_N = 0x0000001A +PRODUCT_HYPERV = 0x0000002A +PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E +PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020 +PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F +PRODUCT_PROFESSIONAL = 0x00000030 +PRODUCT_PROFESSIONAL_E = 0x00000045 +PRODUCT_PROFESSIONAL_N = 0x00000031 +PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018 +PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023 +PRODUCT_SERVER_FOUNDATION = 0x00000021 +PRODUCT_SMALLBUSINESS_SERVER = 0x00000009 +PRODUCT_STANDARD_SERVER = 0x00000007 +PRODUCT_STANDARD_SERVER_CORE = 0x0000000D +PRODUCT_STANDARD_SERVER_CORE_V = 0x00000028 +PRODUCT_STANDARD_SERVER_V = 0x00000024 +PRODUCT_STARTER = 0x0000000B +PRODUCT_STARTER_E = 0x00000042 +PRODUCT_STARTER_N = 0x0000002F +PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017 +PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014 +PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015 +PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016 +PRODUCT_UNDEFINED = 0x00000000 +PRODUCT_UNLICENSED = 0xABCDABCD +PRODUCT_ULTIMATE = 0x00000001 +PRODUCT_ULTIMATE_E = 0x00000047 +PRODUCT_ULTIMATE_N = 0x0000001C +PRODUCT_WEB_SERVER = 0x00000011 +PRODUCT_WEB_SERVER_CORE = 0x0000001D + +# DEP policy flags +PROCESS_DEP_ENABLE = 1 +PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION = 2 + +# Error modes +SEM_FAILCRITICALERRORS = 0x001 +SEM_NOGPFAULTERRORBOX = 0x002 +SEM_NOALIGNMENTFAULTEXCEPT = 0x004 +SEM_NOOPENFILEERRORBOX = 0x800 + +# GetHandleInformation / SetHandleInformation +HANDLE_FLAG_INHERIT = 0x00000001 +HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002 + +#--- Handle wrappers ---------------------------------------------------------- + +class Handle (object): + """ + Encapsulates Win32 handles to avoid leaking them. + + @type inherit: bool + @ivar inherit: C{True} if the handle is to be inherited by child processes, + C{False} otherwise. + + @type protectFromClose: bool + @ivar protectFromClose: Set to C{True} to prevent the handle from being + closed. Must be set to C{False} before you're done using the handle, + or it will be left open until the debugger exits. Use with care! + + @see: + L{ProcessHandle}, L{ThreadHandle}, L{FileHandle}, L{SnapshotHandle} + """ + + # XXX DEBUG + # When this private flag is True each Handle will print a message to + # standard output when it's created and destroyed. This is useful for + # detecting handle leaks within WinAppDbg itself. + __bLeakDetection = False + + def __init__(self, aHandle = None, bOwnership = True): + """ + @type aHandle: int + @param aHandle: Win32 handle value. + + @type bOwnership: bool + @param bOwnership: + C{True} if we own the handle and we need to close it. + C{False} if someone else will be calling L{CloseHandle}. + """ + super(Handle, self).__init__() + self._value = self._normalize(aHandle) + self.bOwnership = bOwnership + if Handle.__bLeakDetection: # XXX DEBUG + print("INIT HANDLE (%r) %r" % (self.value, self)) + + @property + def value(self): + return self._value + + def __del__(self): + """ + Closes the Win32 handle when the Python object is destroyed. + """ + try: + if Handle.__bLeakDetection: # XXX DEBUG + print("DEL HANDLE %r" % self) + self.close() + except Exception: + pass + + def __enter__(self): + """ + Compatibility with the "C{with}" Python statement. + """ + if Handle.__bLeakDetection: # XXX DEBUG + print("ENTER HANDLE %r" % self) + return self + + def __exit__(self, type, value, traceback): + """ + Compatibility with the "C{with}" Python statement. + """ + if Handle.__bLeakDetection: # XXX DEBUG + print("EXIT HANDLE %r" % self) + try: + self.close() + except Exception: + pass + + def __copy__(self): + """ + Duplicates the Win32 handle when copying the Python object. + + @rtype: L{Handle} + @return: A new handle to the same Win32 object. + """ + return self.dup() + + def __deepcopy__(self): + """ + Duplicates the Win32 handle when copying the Python object. + + @rtype: L{Handle} + @return: A new handle to the same win32 object. + """ + return self.dup() + + @property + def _as_parameter_(self): + """ + Compatibility with ctypes. + Allows passing transparently a Handle object to an API call. + """ + return HANDLE(self.value) + + @staticmethod + def from_param(value): + """ + Compatibility with ctypes. + Allows passing transparently a Handle object to an API call. + + @type value: int + @param value: Numeric handle value. + """ + return HANDLE(value) + + def close(self): + """ + Closes the Win32 handle. + """ + if self.bOwnership and self.value not in (None, INVALID_HANDLE_VALUE): + if Handle.__bLeakDetection: # XXX DEBUG + print("CLOSE HANDLE (%d) %r" % (self.value, self)) + try: + self._close() + finally: + self._value = None + + def _close(self): + """ + Low-level close method. + This is a private method, do not call it. + """ + CloseHandle(self.value) + + def dup(self): + """ + @rtype: L{Handle} + @return: A new handle to the same Win32 object. + """ + if self.value is None: + raise ValueError("Closed handles can't be duplicated!") + new_handle = DuplicateHandle(self.value) + if Handle.__bLeakDetection: # XXX DEBUG + print("DUP HANDLE (%d -> %d) %r %r" % \ + (self.value, new_handle.value, self, new_handle)) + return new_handle + + @staticmethod + def _normalize(value): + """ + Normalize handle values. + """ + if hasattr(value, 'value'): + value = value.value + if value is not None: + value = long(value) + return value + + def wait(self, dwMilliseconds = None): + """ + Wait for the Win32 object to be signaled. + + @type dwMilliseconds: int + @param dwMilliseconds: (Optional) Timeout value in milliseconds. + Use C{INFINITE} or C{None} for no timeout. + """ + if self.value is None: + raise ValueError("Handle is already closed!") + if dwMilliseconds is None: + dwMilliseconds = INFINITE + r = WaitForSingleObject(self.value, dwMilliseconds) + if r != WAIT_OBJECT_0: + raise ctypes.WinError(r) + + def __repr__(self): + return '<%s: %s>' % (self.__class__.__name__, self.value) + + def __get_inherit(self): + if self.value is None: + raise ValueError("Handle is already closed!") + return bool( GetHandleInformation(self.value) & HANDLE_FLAG_INHERIT ) + + def __set_inherit(self, value): + if self.value is None: + raise ValueError("Handle is already closed!") + flag = (0, HANDLE_FLAG_INHERIT)[ bool(value) ] + SetHandleInformation(self.value, flag, flag) + + inherit = property(__get_inherit, __set_inherit) + + def __get_protectFromClose(self): + if self.value is None: + raise ValueError("Handle is already closed!") + return bool( GetHandleInformation(self.value) & HANDLE_FLAG_PROTECT_FROM_CLOSE ) + + def __set_protectFromClose(self, value): + if self.value is None: + raise ValueError("Handle is already closed!") + flag = (0, HANDLE_FLAG_PROTECT_FROM_CLOSE)[ bool(value) ] + SetHandleInformation(self.value, flag, flag) + + protectFromClose = property(__get_protectFromClose, __set_protectFromClose) + +class UserModeHandle (Handle): + """ + Base class for non-kernel handles. Generally this means they are closed + by special Win32 API functions instead of CloseHandle() and some standard + operations (synchronizing, duplicating, inheritance) are not supported. + + @type _TYPE: C type + @cvar _TYPE: C type to translate this handle to. + Subclasses should override this. + Defaults to L{HANDLE}. + """ + + # Subclasses should override this. + _TYPE = HANDLE + + # This method must be implemented by subclasses. + def _close(self): + raise NotImplementedError() + + # Translation to C type. + @property + def _as_parameter_(self): + return self._TYPE(self.value) + + # Translation to C type. + @staticmethod + def from_param(value): + return self._TYPE(self.value) + + # Operation not supported. + @property + def inherit(self): + return False + + # Operation not supported. + @property + def protectFromClose(self): + return False + + # Operation not supported. + def dup(self): + raise NotImplementedError() + + # Operation not supported. + def wait(self, dwMilliseconds = None): + raise NotImplementedError() + +class ProcessHandle (Handle): + """ + Win32 process handle. + + @type dwAccess: int + @ivar dwAccess: Current access flags to this handle. + This is the same value passed to L{OpenProcess}. + Can only be C{None} if C{aHandle} is also C{None}. + Defaults to L{PROCESS_ALL_ACCESS}. + + @see: L{Handle} + """ + + def __init__(self, aHandle = None, bOwnership = True, + dwAccess = PROCESS_ALL_ACCESS): + """ + @type aHandle: int + @param aHandle: Win32 handle value. + + @type bOwnership: bool + @param bOwnership: + C{True} if we own the handle and we need to close it. + C{False} if someone else will be calling L{CloseHandle}. + + @type dwAccess: int + @param dwAccess: Current access flags to this handle. + This is the same value passed to L{OpenProcess}. + Can only be C{None} if C{aHandle} is also C{None}. + Defaults to L{PROCESS_ALL_ACCESS}. + """ + super(ProcessHandle, self).__init__(aHandle, bOwnership) + self.dwAccess = dwAccess + if aHandle is not None and dwAccess is None: + msg = "Missing access flags for process handle: %x" % aHandle + raise TypeError(msg) + + def get_pid(self): + """ + @rtype: int + @return: Process global ID. + """ + return GetProcessId(self.value) + +class ThreadHandle (Handle): + """ + Win32 thread handle. + + @type dwAccess: int + @ivar dwAccess: Current access flags to this handle. + This is the same value passed to L{OpenThread}. + Can only be C{None} if C{aHandle} is also C{None}. + Defaults to L{THREAD_ALL_ACCESS}. + + @see: L{Handle} + """ + + def __init__(self, aHandle = None, bOwnership = True, + dwAccess = THREAD_ALL_ACCESS): + """ + @type aHandle: int + @param aHandle: Win32 handle value. + + @type bOwnership: bool + @param bOwnership: + C{True} if we own the handle and we need to close it. + C{False} if someone else will be calling L{CloseHandle}. + + @type dwAccess: int + @param dwAccess: Current access flags to this handle. + This is the same value passed to L{OpenThread}. + Can only be C{None} if C{aHandle} is also C{None}. + Defaults to L{THREAD_ALL_ACCESS}. + """ + super(ThreadHandle, self).__init__(aHandle, bOwnership) + self.dwAccess = dwAccess + if aHandle is not None and dwAccess is None: + msg = "Missing access flags for thread handle: %x" % aHandle + raise TypeError(msg) + + def get_tid(self): + """ + @rtype: int + @return: Thread global ID. + """ + return GetThreadId(self.value) + +class FileHandle (Handle): + """ + Win32 file handle. + + @see: L{Handle} + """ + + def get_filename(self): + """ + @rtype: None or str + @return: Name of the open file, or C{None} if unavailable. + """ + # + # XXX BUG + # + # This code truncates the first two bytes of the path. + # It seems to be the expected behavior of NtQueryInformationFile. + # + # My guess is it only returns the NT pathname, without the device name. + # It's like dropping the drive letter in a Win32 pathname. + # + # Note that using the "official" GetFileInformationByHandleEx + # API introduced in Vista doesn't change the results! + # + dwBufferSize = 0x1004 + lpFileInformation = ctypes.create_string_buffer(dwBufferSize) + try: + GetFileInformationByHandleEx(self.value, + FILE_INFO_BY_HANDLE_CLASS.FileNameInfo, + lpFileInformation, dwBufferSize) + except AttributeError: + from winappdbg.win32.ntdll import NtQueryInformationFile, \ + FileNameInformation, \ + FILE_NAME_INFORMATION + NtQueryInformationFile(self.value, + FileNameInformation, + lpFileInformation, + dwBufferSize) + FileName = compat.unicode(lpFileInformation.raw[sizeof(DWORD):], 'U16') + FileName = ctypes.create_unicode_buffer(FileName).value + if not FileName: + FileName = None + elif FileName[1:2] != ':': + # When the drive letter is missing, we'll assume SYSTEMROOT. + # Not a good solution but it could be worse. + import os + FileName = os.environ['SYSTEMROOT'][:2] + FileName + return FileName + +class FileMappingHandle (Handle): + """ + File mapping handle. + + @see: L{Handle} + """ + pass + +# XXX maybe add functions related to the toolhelp snapshots here? +class SnapshotHandle (Handle): + """ + Toolhelp32 snapshot handle. + + @see: L{Handle} + """ + pass + +#--- Structure wrappers ------------------------------------------------------- + +class ProcessInformation (object): + """ + Process information object returned by L{CreateProcess}. + """ + + def __init__(self, pi): + self.hProcess = ProcessHandle(pi.hProcess) + self.hThread = ThreadHandle(pi.hThread) + self.dwProcessId = pi.dwProcessId + self.dwThreadId = pi.dwThreadId + +# Don't psyco-optimize this class because it needs to be serialized. +class MemoryBasicInformation (object): + """ + Memory information object returned by L{VirtualQueryEx}. + """ + + READABLE = ( + PAGE_EXECUTE_READ | + PAGE_EXECUTE_READWRITE | + PAGE_EXECUTE_WRITECOPY | + PAGE_READONLY | + PAGE_READWRITE | + PAGE_WRITECOPY + ) + + WRITEABLE = ( + PAGE_EXECUTE_READWRITE | + PAGE_EXECUTE_WRITECOPY | + PAGE_READWRITE | + PAGE_WRITECOPY + ) + + COPY_ON_WRITE = ( + PAGE_EXECUTE_WRITECOPY | + PAGE_WRITECOPY + ) + + EXECUTABLE = ( + PAGE_EXECUTE | + PAGE_EXECUTE_READ | + PAGE_EXECUTE_READWRITE | + PAGE_EXECUTE_WRITECOPY + ) + + EXECUTABLE_AND_WRITEABLE = ( + PAGE_EXECUTE_READWRITE | + PAGE_EXECUTE_WRITECOPY + ) + + def __init__(self, mbi=None): + """ + @type mbi: L{MEMORY_BASIC_INFORMATION} or L{MemoryBasicInformation} + @param mbi: Either a L{MEMORY_BASIC_INFORMATION} structure or another + L{MemoryBasicInformation} instance. + """ + if mbi is None: + self.BaseAddress = None + self.AllocationBase = None + self.AllocationProtect = None + self.RegionSize = None + self.State = None + self.Protect = None + self.Type = None + else: + self.BaseAddress = mbi.BaseAddress + self.AllocationBase = mbi.AllocationBase + self.AllocationProtect = mbi.AllocationProtect + self.RegionSize = mbi.RegionSize + self.State = mbi.State + self.Protect = mbi.Protect + self.Type = mbi.Type + + # Only used when copying MemoryBasicInformation objects, instead of + # instancing them from a MEMORY_BASIC_INFORMATION structure. + if hasattr(mbi, 'content'): + self.content = mbi.content + if hasattr(mbi, 'filename'): + self.content = mbi.filename + + def __contains__(self, address): + """ + Test if the given memory address falls within this memory region. + + @type address: int + @param address: Memory address to test. + + @rtype: bool + @return: C{True} if the given memory address falls within this memory + region, C{False} otherwise. + """ + return self.BaseAddress <= address < (self.BaseAddress + self.RegionSize) + + def is_free(self): + """ + @rtype: bool + @return: C{True} if the memory in this region is free. + """ + return self.State == MEM_FREE + + def is_reserved(self): + """ + @rtype: bool + @return: C{True} if the memory in this region is reserved. + """ + return self.State == MEM_RESERVE + + def is_commited(self): + """ + @rtype: bool + @return: C{True} if the memory in this region is commited. + """ + return self.State == MEM_COMMIT + + def is_image(self): + """ + @rtype: bool + @return: C{True} if the memory in this region belongs to an executable + image. + """ + return self.Type == MEM_IMAGE + + def is_mapped(self): + """ + @rtype: bool + @return: C{True} if the memory in this region belongs to a mapped file. + """ + return self.Type == MEM_MAPPED + + def is_private(self): + """ + @rtype: bool + @return: C{True} if the memory in this region is private. + """ + return self.Type == MEM_PRIVATE + + def is_guard(self): + """ + @rtype: bool + @return: C{True} if all pages in this region are guard pages. + """ + return self.is_commited() and bool(self.Protect & PAGE_GUARD) + + def has_content(self): + """ + @rtype: bool + @return: C{True} if the memory in this region has any data in it. + """ + return self.is_commited() and not bool(self.Protect & (PAGE_GUARD | PAGE_NOACCESS)) + + def is_readable(self): + """ + @rtype: bool + @return: C{True} if all pages in this region are readable. + """ + return self.has_content() and bool(self.Protect & self.READABLE) + + def is_writeable(self): + """ + @rtype: bool + @return: C{True} if all pages in this region are writeable. + """ + return self.has_content() and bool(self.Protect & self.WRITEABLE) + + def is_copy_on_write(self): + """ + @rtype: bool + @return: C{True} if all pages in this region are marked as + copy-on-write. This means the pages are writeable, but changes + are not propagated to disk. + @note: + Tipically data sections in executable images are marked like this. + """ + return self.has_content() and bool(self.Protect & self.COPY_ON_WRITE) + + def is_executable(self): + """ + @rtype: bool + @return: C{True} if all pages in this region are executable. + @note: Executable pages are always readable. + """ + return self.has_content() and bool(self.Protect & self.EXECUTABLE) + + def is_executable_and_writeable(self): + """ + @rtype: bool + @return: C{True} if all pages in this region are executable and + writeable. + @note: The presence of such pages make memory corruption + vulnerabilities much easier to exploit. + """ + return self.has_content() and bool(self.Protect & self.EXECUTABLE_AND_WRITEABLE) + +class ProcThreadAttributeList (object): + """ + Extended process and thread attribute support. + + To be used with L{STARTUPINFOEX}. + Only available for Windows Vista and above. + + @type AttributeList: list of tuple( int, ctypes-compatible object ) + @ivar AttributeList: List of (Attribute, Value) pairs. + + @type AttributeListBuffer: L{LPPROC_THREAD_ATTRIBUTE_LIST} + @ivar AttributeListBuffer: Memory buffer used to store the attribute list. + L{InitializeProcThreadAttributeList}, + L{UpdateProcThreadAttribute}, + L{DeleteProcThreadAttributeList} and + L{STARTUPINFOEX}. + """ + + def __init__(self, AttributeList): + """ + @type AttributeList: list of tuple( int, ctypes-compatible object ) + @param AttributeList: List of (Attribute, Value) pairs. + """ + self.AttributeList = AttributeList + self.AttributeListBuffer = InitializeProcThreadAttributeList( + len(AttributeList)) + try: + for Attribute, Value in AttributeList: + UpdateProcThreadAttribute(self.AttributeListBuffer, + Attribute, Value) + except: + ProcThreadAttributeList.__del__(self) + raise + + def __del__(self): + try: + DeleteProcThreadAttributeList(self.AttributeListBuffer) + del self.AttributeListBuffer + except Exception: + pass + + def __copy__(self): + return self.__deepcopy__() + + def __deepcopy__(self): + return self.__class__(self.AttributeList) + + @property + def value(self): + return ctypes.cast(ctypes.pointer(self.AttributeListBuffer), LPVOID) + + @property + def _as_parameter_(self): + return self.value + + # XXX TODO + @staticmethod + def from_param(value): + raise NotImplementedError() + +#--- OVERLAPPED structure ----------------------------------------------------- + +# typedef struct _OVERLAPPED { +# ULONG_PTR Internal; +# ULONG_PTR InternalHigh; +# union { +# struct { +# DWORD Offset; +# DWORD OffsetHigh; +# } ; +# PVOID Pointer; +# } ; +# HANDLE hEvent; +# }OVERLAPPED, *LPOVERLAPPED; +class _OVERLAPPED_STRUCT(Structure): + _fields_ = [ + ('Offset', DWORD), + ('OffsetHigh', DWORD), + ] +class _OVERLAPPED_UNION(Union): + _fields_ = [ + ('s', _OVERLAPPED_STRUCT), + ('Pointer', PVOID), + ] +class OVERLAPPED(Structure): + _fields_ = [ + ('Internal', ULONG_PTR), + ('InternalHigh', ULONG_PTR), + ('u', _OVERLAPPED_UNION), + ('hEvent', HANDLE), + ] +LPOVERLAPPED = POINTER(OVERLAPPED) + +#--- SECURITY_ATTRIBUTES structure -------------------------------------------- + +# typedef struct _SECURITY_ATTRIBUTES { +# DWORD nLength; +# LPVOID lpSecurityDescriptor; +# BOOL bInheritHandle; +# } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; +class SECURITY_ATTRIBUTES(Structure): + _fields_ = [ + ('nLength', DWORD), + ('lpSecurityDescriptor', LPVOID), + ('bInheritHandle', BOOL), + ] +LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES) + +# --- Extended process and thread attribute support --------------------------- + +PPROC_THREAD_ATTRIBUTE_LIST = LPVOID +LPPROC_THREAD_ATTRIBUTE_LIST = PPROC_THREAD_ATTRIBUTE_LIST + +PROC_THREAD_ATTRIBUTE_NUMBER = 0x0000FFFF +PROC_THREAD_ATTRIBUTE_THREAD = 0x00010000 # Attribute may be used with thread creation +PROC_THREAD_ATTRIBUTE_INPUT = 0x00020000 # Attribute is input only +PROC_THREAD_ATTRIBUTE_ADDITIVE = 0x00040000 # Attribute may be "accumulated," e.g. bitmasks, counters, etc. + +# PROC_THREAD_ATTRIBUTE_NUM +ProcThreadAttributeParentProcess = 0 +ProcThreadAttributeExtendedFlags = 1 +ProcThreadAttributeHandleList = 2 +ProcThreadAttributeGroupAffinity = 3 +ProcThreadAttributePreferredNode = 4 +ProcThreadAttributeIdealProcessor = 5 +ProcThreadAttributeUmsThread = 6 +ProcThreadAttributeMitigationPolicy = 7 +ProcThreadAttributeMax = 8 + +PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = ProcThreadAttributeParentProcess | PROC_THREAD_ATTRIBUTE_INPUT +PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS = ProcThreadAttributeExtendedFlags | PROC_THREAD_ATTRIBUTE_INPUT | PROC_THREAD_ATTRIBUTE_ADDITIVE +PROC_THREAD_ATTRIBUTE_HANDLE_LIST = ProcThreadAttributeHandleList | PROC_THREAD_ATTRIBUTE_INPUT +PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY = ProcThreadAttributeGroupAffinity | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT +PROC_THREAD_ATTRIBUTE_PREFERRED_NODE = ProcThreadAttributePreferredNode | PROC_THREAD_ATTRIBUTE_INPUT +PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR = ProcThreadAttributeIdealProcessor | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT +PROC_THREAD_ATTRIBUTE_UMS_THREAD = ProcThreadAttributeUmsThread | PROC_THREAD_ATTRIBUTE_THREAD | PROC_THREAD_ATTRIBUTE_INPUT +PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY = ProcThreadAttributeMitigationPolicy | PROC_THREAD_ATTRIBUTE_INPUT + +PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE = 0x01 +PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE = 0x02 +PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE = 0x04 + +#--- VS_FIXEDFILEINFO structure ----------------------------------------------- + +# struct VS_FIXEDFILEINFO { +# DWORD dwSignature; +# DWORD dwStrucVersion; +# DWORD dwFileVersionMS; +# DWORD dwFileVersionLS; +# DWORD dwProductVersionMS; +# DWORD dwProductVersionLS; +# DWORD dwFileFlagsMask; +# DWORD dwFileFlags; +# DWORD dwFileOS; +# DWORD dwFileType; +# DWORD dwFileSubtype; +# DWORD dwFileDateMS; +# DWORD dwFileDateLS; +# }; +class VS_FIXEDFILEINFO (Structure): + _fields_ = [ + ("dwSignature", DWORD), # 0xFEEF04BD + ("dwStrucVersion", DWORD), + ("dwFileVersionMS", DWORD), + ("dwFileVersionLS", DWORD), + ("dwProductVersionMS", DWORD), + ("dwProductVersionLS", DWORD), + ("dwFileFlagsMask", DWORD), + ("dwFileFlags", DWORD), + ("dwFileOS", DWORD), + ("dwFileType", DWORD), + ("dwFileSubtype", DWORD), + ("dwFileDateMS", DWORD), + ("dwFileDateLS", DWORD), + ] + +#--- THREADNAME_INFO structure ------------------------------------------------ + +# typedef struct tagTHREADNAME_INFO +# { +# DWORD dwType; // Must be 0x1000. +# LPCSTR szName; // Pointer to name (in user addr space). +# DWORD dwThreadID; // Thread ID (-1=caller thread). +# DWORD dwFlags; // Reserved for future use, must be zero. +# } THREADNAME_INFO; +class THREADNAME_INFO(Structure): + _fields_ = [ + ("dwType", DWORD), # 0x1000 + ("szName", LPVOID), # remote pointer + ("dwThreadID", DWORD), # -1 usually + ("dwFlags", DWORD), # 0 + ] + +#--- MEMORY_BASIC_INFORMATION structure --------------------------------------- + +# typedef struct _MEMORY_BASIC_INFORMATION32 { +# DWORD BaseAddress; +# DWORD AllocationBase; +# DWORD AllocationProtect; +# DWORD RegionSize; +# DWORD State; +# DWORD Protect; +# DWORD Type; +# } MEMORY_BASIC_INFORMATION32, *PMEMORY_BASIC_INFORMATION32; +class MEMORY_BASIC_INFORMATION32(Structure): + _fields_ = [ + ('BaseAddress', DWORD), # remote pointer + ('AllocationBase', DWORD), # remote pointer + ('AllocationProtect', DWORD), + ('RegionSize', DWORD), + ('State', DWORD), + ('Protect', DWORD), + ('Type', DWORD), + ] + +# typedef struct DECLSPEC_ALIGN(16) _MEMORY_BASIC_INFORMATION64 { +# ULONGLONG BaseAddress; +# ULONGLONG AllocationBase; +# DWORD AllocationProtect; +# DWORD __alignment1; +# ULONGLONG RegionSize; +# DWORD State; +# DWORD Protect; +# DWORD Type; +# DWORD __alignment2; +# } MEMORY_BASIC_INFORMATION64, *PMEMORY_BASIC_INFORMATION64; +class MEMORY_BASIC_INFORMATION64(Structure): + _fields_ = [ + ('BaseAddress', ULONGLONG), # remote pointer + ('AllocationBase', ULONGLONG), # remote pointer + ('AllocationProtect', DWORD), + ('__alignment1', DWORD), + ('RegionSize', ULONGLONG), + ('State', DWORD), + ('Protect', DWORD), + ('Type', DWORD), + ('__alignment2', DWORD), + ] + +# typedef struct _MEMORY_BASIC_INFORMATION { +# PVOID BaseAddress; +# PVOID AllocationBase; +# DWORD AllocationProtect; +# SIZE_T RegionSize; +# DWORD State; +# DWORD Protect; +# DWORD Type; +# } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; +class MEMORY_BASIC_INFORMATION(Structure): + _fields_ = [ + ('BaseAddress', SIZE_T), # remote pointer + ('AllocationBase', SIZE_T), # remote pointer + ('AllocationProtect', DWORD), + ('RegionSize', SIZE_T), + ('State', DWORD), + ('Protect', DWORD), + ('Type', DWORD), + ] +PMEMORY_BASIC_INFORMATION = POINTER(MEMORY_BASIC_INFORMATION) + +#--- BY_HANDLE_FILE_INFORMATION structure ------------------------------------- + +# typedef struct _FILETIME { +# DWORD dwLowDateTime; +# DWORD dwHighDateTime; +# } FILETIME, *PFILETIME; +class FILETIME(Structure): + _fields_ = [ + ('dwLowDateTime', DWORD), + ('dwHighDateTime', DWORD), + ] +LPFILETIME = POINTER(FILETIME) + +# typedef struct _SYSTEMTIME { +# WORD wYear; +# WORD wMonth; +# WORD wDayOfWeek; +# WORD wDay; +# WORD wHour; +# WORD wMinute; +# WORD wSecond; +# WORD wMilliseconds; +# }SYSTEMTIME, *PSYSTEMTIME; +class SYSTEMTIME(Structure): + _fields_ = [ + ('wYear', WORD), + ('wMonth', WORD), + ('wDayOfWeek', WORD), + ('wDay', WORD), + ('wHour', WORD), + ('wMinute', WORD), + ('wSecond', WORD), + ('wMilliseconds', WORD), + ] +LPSYSTEMTIME = POINTER(SYSTEMTIME) + +# typedef struct _BY_HANDLE_FILE_INFORMATION { +# DWORD dwFileAttributes; +# FILETIME ftCreationTime; +# FILETIME ftLastAccessTime; +# FILETIME ftLastWriteTime; +# DWORD dwVolumeSerialNumber; +# DWORD nFileSizeHigh; +# DWORD nFileSizeLow; +# DWORD nNumberOfLinks; +# DWORD nFileIndexHigh; +# DWORD nFileIndexLow; +# } BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION; +class BY_HANDLE_FILE_INFORMATION(Structure): + _fields_ = [ + ('dwFileAttributes', DWORD), + ('ftCreationTime', FILETIME), + ('ftLastAccessTime', FILETIME), + ('ftLastWriteTime', FILETIME), + ('dwVolumeSerialNumber', DWORD), + ('nFileSizeHigh', DWORD), + ('nFileSizeLow', DWORD), + ('nNumberOfLinks', DWORD), + ('nFileIndexHigh', DWORD), + ('nFileIndexLow', DWORD), + ] +LPBY_HANDLE_FILE_INFORMATION = POINTER(BY_HANDLE_FILE_INFORMATION) + +# typedef enum _FILE_INFO_BY_HANDLE_CLASS { +# FileBasicInfo = 0, +# FileStandardInfo = 1, +# FileNameInfo = 2, +# FileRenameInfo = 3, +# FileDispositionInfo = 4, +# FileAllocationInfo = 5, +# FileEndOfFileInfo = 6, +# FileStreamInfo = 7, +# FileCompressionInfo = 8, +# FileAttributeTagInfo = 9, +# FileIdBothDirectoryInfo = 10, +# FileIdBothDirectoryRestartInfo = 11, +# FileIoPriorityHintInfo = 12, +# MaximumFileInfoByHandlesClass = 13 +# } FILE_INFO_BY_HANDLE_CLASS, *PFILE_INFO_BY_HANDLE_CLASS; +class FILE_INFO_BY_HANDLE_CLASS(object): + FileBasicInfo = 0 + FileStandardInfo = 1 + FileNameInfo = 2 + FileRenameInfo = 3 + FileDispositionInfo = 4 + FileAllocationInfo = 5 + FileEndOfFileInfo = 6 + FileStreamInfo = 7 + FileCompressionInfo = 8 + FileAttributeTagInfo = 9 + FileIdBothDirectoryInfo = 10 + FileIdBothDirectoryRestartInfo = 11 + FileIoPriorityHintInfo = 12 + MaximumFileInfoByHandlesClass = 13 + +# typedef struct _FILE_NAME_INFO { +# DWORD FileNameLength; +# WCHAR FileName[1]; +# } FILE_NAME_INFO, *PFILE_NAME_INFO; +##class FILE_NAME_INFO(Structure): +## _fields_ = [ +## ('FileNameLength', DWORD), +## ('FileName', WCHAR * 1), +## ] + +# TO DO: add more structures used by GetFileInformationByHandleEx() + +#--- PROCESS_INFORMATION structure -------------------------------------------- + +# typedef struct _PROCESS_INFORMATION { +# HANDLE hProcess; +# HANDLE hThread; +# DWORD dwProcessId; +# DWORD dwThreadId; +# } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION; +class PROCESS_INFORMATION(Structure): + _fields_ = [ + ('hProcess', HANDLE), + ('hThread', HANDLE), + ('dwProcessId', DWORD), + ('dwThreadId', DWORD), + ] +LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION) + +#--- STARTUPINFO and STARTUPINFOEX structures --------------------------------- + +# typedef struct _STARTUPINFO { +# DWORD cb; +# LPTSTR lpReserved; +# LPTSTR lpDesktop; +# LPTSTR lpTitle; +# DWORD dwX; +# DWORD dwY; +# DWORD dwXSize; +# DWORD dwYSize; +# DWORD dwXCountChars; +# DWORD dwYCountChars; +# DWORD dwFillAttribute; +# DWORD dwFlags; +# WORD wShowWindow; +# WORD cbReserved2; +# LPBYTE lpReserved2; +# HANDLE hStdInput; +# HANDLE hStdOutput; +# HANDLE hStdError; +# }STARTUPINFO, *LPSTARTUPINFO; +class STARTUPINFO(Structure): + _fields_ = [ + ('cb', DWORD), + ('lpReserved', LPSTR), + ('lpDesktop', LPSTR), + ('lpTitle', LPSTR), + ('dwX', DWORD), + ('dwY', DWORD), + ('dwXSize', DWORD), + ('dwYSize', DWORD), + ('dwXCountChars', DWORD), + ('dwYCountChars', DWORD), + ('dwFillAttribute', DWORD), + ('dwFlags', DWORD), + ('wShowWindow', WORD), + ('cbReserved2', WORD), + ('lpReserved2', LPVOID), # LPBYTE + ('hStdInput', HANDLE), + ('hStdOutput', HANDLE), + ('hStdError', HANDLE), + ] +LPSTARTUPINFO = POINTER(STARTUPINFO) + +# typedef struct _STARTUPINFOEX { +# STARTUPINFO StartupInfo; +# PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList; +# } STARTUPINFOEX, *LPSTARTUPINFOEX; +class STARTUPINFOEX(Structure): + _fields_ = [ + ('StartupInfo', STARTUPINFO), + ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST), + ] +LPSTARTUPINFOEX = POINTER(STARTUPINFOEX) + +class STARTUPINFOW(Structure): + _fields_ = [ + ('cb', DWORD), + ('lpReserved', LPWSTR), + ('lpDesktop', LPWSTR), + ('lpTitle', LPWSTR), + ('dwX', DWORD), + ('dwY', DWORD), + ('dwXSize', DWORD), + ('dwYSize', DWORD), + ('dwXCountChars', DWORD), + ('dwYCountChars', DWORD), + ('dwFillAttribute', DWORD), + ('dwFlags', DWORD), + ('wShowWindow', WORD), + ('cbReserved2', WORD), + ('lpReserved2', LPVOID), # LPBYTE + ('hStdInput', HANDLE), + ('hStdOutput', HANDLE), + ('hStdError', HANDLE), + ] +LPSTARTUPINFOW = POINTER(STARTUPINFOW) + +class STARTUPINFOEXW(Structure): + _fields_ = [ + ('StartupInfo', STARTUPINFOW), + ('lpAttributeList', PPROC_THREAD_ATTRIBUTE_LIST), + ] +LPSTARTUPINFOEXW = POINTER(STARTUPINFOEXW) + +#--- JIT_DEBUG_INFO structure ------------------------------------------------- + +# typedef struct _JIT_DEBUG_INFO { +# DWORD dwSize; +# DWORD dwProcessorArchitecture; +# DWORD dwThreadID; +# DWORD dwReserved0; +# ULONG64 lpExceptionAddress; +# ULONG64 lpExceptionRecord; +# ULONG64 lpContextRecord; +# } JIT_DEBUG_INFO, *LPJIT_DEBUG_INFO; +class JIT_DEBUG_INFO(Structure): + _fields_ = [ + ('dwSize', DWORD), + ('dwProcessorArchitecture', DWORD), + ('dwThreadID', DWORD), + ('dwReserved0', DWORD), + ('lpExceptionAddress', ULONG64), + ('lpExceptionRecord', ULONG64), + ('lpContextRecord', ULONG64), + ] +JIT_DEBUG_INFO32 = JIT_DEBUG_INFO +JIT_DEBUG_INFO64 = JIT_DEBUG_INFO + +LPJIT_DEBUG_INFO = POINTER(JIT_DEBUG_INFO) +LPJIT_DEBUG_INFO32 = POINTER(JIT_DEBUG_INFO32) +LPJIT_DEBUG_INFO64 = POINTER(JIT_DEBUG_INFO64) + +#--- DEBUG_EVENT structure ---------------------------------------------------- + +# typedef struct _EXCEPTION_RECORD32 { +# DWORD ExceptionCode; +# DWORD ExceptionFlags; +# DWORD ExceptionRecord; +# DWORD ExceptionAddress; +# DWORD NumberParameters; +# DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +# } EXCEPTION_RECORD32, *PEXCEPTION_RECORD32; +class EXCEPTION_RECORD32(Structure): + _fields_ = [ + ('ExceptionCode', DWORD), + ('ExceptionFlags', DWORD), + ('ExceptionRecord', DWORD), + ('ExceptionAddress', DWORD), + ('NumberParameters', DWORD), + ('ExceptionInformation', DWORD * EXCEPTION_MAXIMUM_PARAMETERS), + ] + +PEXCEPTION_RECORD32 = POINTER(EXCEPTION_RECORD32) + +# typedef struct _EXCEPTION_RECORD64 { +# DWORD ExceptionCode; +# DWORD ExceptionFlags; +# DWORD64 ExceptionRecord; +# DWORD64 ExceptionAddress; +# DWORD NumberParameters; +# DWORD __unusedAlignment; +# DWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +# } EXCEPTION_RECORD64, *PEXCEPTION_RECORD64; +class EXCEPTION_RECORD64(Structure): + _fields_ = [ + ('ExceptionCode', DWORD), + ('ExceptionFlags', DWORD), + ('ExceptionRecord', DWORD64), + ('ExceptionAddress', DWORD64), + ('NumberParameters', DWORD), + ('__unusedAlignment', DWORD), + ('ExceptionInformation', DWORD64 * EXCEPTION_MAXIMUM_PARAMETERS), + ] + +PEXCEPTION_RECORD64 = POINTER(EXCEPTION_RECORD64) + +# typedef struct _EXCEPTION_RECORD { +# DWORD ExceptionCode; +# DWORD ExceptionFlags; +# LPVOID ExceptionRecord; +# LPVOID ExceptionAddress; +# DWORD NumberParameters; +# LPVOID ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +# } EXCEPTION_RECORD, *PEXCEPTION_RECORD; +class EXCEPTION_RECORD(Structure): + pass +PEXCEPTION_RECORD = POINTER(EXCEPTION_RECORD) +EXCEPTION_RECORD._fields_ = [ + ('ExceptionCode', DWORD), + ('ExceptionFlags', DWORD), + ('ExceptionRecord', PEXCEPTION_RECORD), + ('ExceptionAddress', LPVOID), + ('NumberParameters', DWORD), + ('ExceptionInformation', LPVOID * EXCEPTION_MAXIMUM_PARAMETERS), + ] + +# typedef struct _EXCEPTION_DEBUG_INFO { +# EXCEPTION_RECORD ExceptionRecord; +# DWORD dwFirstChance; +# } EXCEPTION_DEBUG_INFO; +class EXCEPTION_DEBUG_INFO(Structure): + _fields_ = [ + ('ExceptionRecord', EXCEPTION_RECORD), + ('dwFirstChance', DWORD), + ] + +# typedef struct _CREATE_THREAD_DEBUG_INFO { +# HANDLE hThread; +# LPVOID lpThreadLocalBase; +# LPTHREAD_START_ROUTINE lpStartAddress; +# } CREATE_THREAD_DEBUG_INFO; +class CREATE_THREAD_DEBUG_INFO(Structure): + _fields_ = [ + ('hThread', HANDLE), + ('lpThreadLocalBase', LPVOID), + ('lpStartAddress', LPVOID), + ] + +# typedef struct _CREATE_PROCESS_DEBUG_INFO { +# HANDLE hFile; +# HANDLE hProcess; +# HANDLE hThread; +# LPVOID lpBaseOfImage; +# DWORD dwDebugInfoFileOffset; +# DWORD nDebugInfoSize; +# LPVOID lpThreadLocalBase; +# LPTHREAD_START_ROUTINE lpStartAddress; +# LPVOID lpImageName; +# WORD fUnicode; +# } CREATE_PROCESS_DEBUG_INFO; +class CREATE_PROCESS_DEBUG_INFO(Structure): + _fields_ = [ + ('hFile', HANDLE), + ('hProcess', HANDLE), + ('hThread', HANDLE), + ('lpBaseOfImage', LPVOID), + ('dwDebugInfoFileOffset', DWORD), + ('nDebugInfoSize', DWORD), + ('lpThreadLocalBase', LPVOID), + ('lpStartAddress', LPVOID), + ('lpImageName', LPVOID), + ('fUnicode', WORD), + ] + +# typedef struct _EXIT_THREAD_DEBUG_INFO { +# DWORD dwExitCode; +# } EXIT_THREAD_DEBUG_INFO; +class EXIT_THREAD_DEBUG_INFO(Structure): + _fields_ = [ + ('dwExitCode', DWORD), + ] + +# typedef struct _EXIT_PROCESS_DEBUG_INFO { +# DWORD dwExitCode; +# } EXIT_PROCESS_DEBUG_INFO; +class EXIT_PROCESS_DEBUG_INFO(Structure): + _fields_ = [ + ('dwExitCode', DWORD), + ] + +# typedef struct _LOAD_DLL_DEBUG_INFO { +# HANDLE hFile; +# LPVOID lpBaseOfDll; +# DWORD dwDebugInfoFileOffset; +# DWORD nDebugInfoSize; +# LPVOID lpImageName; +# WORD fUnicode; +# } LOAD_DLL_DEBUG_INFO; +class LOAD_DLL_DEBUG_INFO(Structure): + _fields_ = [ + ('hFile', HANDLE), + ('lpBaseOfDll', LPVOID), + ('dwDebugInfoFileOffset', DWORD), + ('nDebugInfoSize', DWORD), + ('lpImageName', LPVOID), + ('fUnicode', WORD), + ] + +# typedef struct _UNLOAD_DLL_DEBUG_INFO { +# LPVOID lpBaseOfDll; +# } UNLOAD_DLL_DEBUG_INFO; +class UNLOAD_DLL_DEBUG_INFO(Structure): + _fields_ = [ + ('lpBaseOfDll', LPVOID), + ] + +# typedef struct _OUTPUT_DEBUG_STRING_INFO { +# LPSTR lpDebugStringData; +# WORD fUnicode; +# WORD nDebugStringLength; +# } OUTPUT_DEBUG_STRING_INFO; +class OUTPUT_DEBUG_STRING_INFO(Structure): + _fields_ = [ + ('lpDebugStringData', LPVOID), # don't use LPSTR + ('fUnicode', WORD), + ('nDebugStringLength', WORD), + ] + +# typedef struct _RIP_INFO { +# DWORD dwError; +# DWORD dwType; +# } RIP_INFO, *LPRIP_INFO; +class RIP_INFO(Structure): + _fields_ = [ + ('dwError', DWORD), + ('dwType', DWORD), + ] + +# typedef struct _DEBUG_EVENT { +# DWORD dwDebugEventCode; +# DWORD dwProcessId; +# DWORD dwThreadId; +# union { +# EXCEPTION_DEBUG_INFO Exception; +# CREATE_THREAD_DEBUG_INFO CreateThread; +# CREATE_PROCESS_DEBUG_INFO CreateProcessInfo; +# EXIT_THREAD_DEBUG_INFO ExitThread; +# EXIT_PROCESS_DEBUG_INFO ExitProcess; +# LOAD_DLL_DEBUG_INFO LoadDll; +# UNLOAD_DLL_DEBUG_INFO UnloadDll; +# OUTPUT_DEBUG_STRING_INFO DebugString; +# RIP_INFO RipInfo; +# } u; +# } DEBUG_EVENT;. +class _DEBUG_EVENT_UNION_(Union): + _fields_ = [ + ('Exception', EXCEPTION_DEBUG_INFO), + ('CreateThread', CREATE_THREAD_DEBUG_INFO), + ('CreateProcessInfo', CREATE_PROCESS_DEBUG_INFO), + ('ExitThread', EXIT_THREAD_DEBUG_INFO), + ('ExitProcess', EXIT_PROCESS_DEBUG_INFO), + ('LoadDll', LOAD_DLL_DEBUG_INFO), + ('UnloadDll', UNLOAD_DLL_DEBUG_INFO), + ('DebugString', OUTPUT_DEBUG_STRING_INFO), + ('RipInfo', RIP_INFO), + ] +class DEBUG_EVENT(Structure): + _fields_ = [ + ('dwDebugEventCode', DWORD), + ('dwProcessId', DWORD), + ('dwThreadId', DWORD), + ('u', _DEBUG_EVENT_UNION_), + ] +LPDEBUG_EVENT = POINTER(DEBUG_EVENT) + +#--- Console API defines and structures --------------------------------------- + +FOREGROUND_MASK = 0x000F +BACKGROUND_MASK = 0x00F0 +COMMON_LVB_MASK = 0xFF00 + +FOREGROUND_BLACK = 0x0000 +FOREGROUND_BLUE = 0x0001 +FOREGROUND_GREEN = 0x0002 +FOREGROUND_CYAN = 0x0003 +FOREGROUND_RED = 0x0004 +FOREGROUND_MAGENTA = 0x0005 +FOREGROUND_YELLOW = 0x0006 +FOREGROUND_GREY = 0x0007 +FOREGROUND_INTENSITY = 0x0008 + +BACKGROUND_BLACK = 0x0000 +BACKGROUND_BLUE = 0x0010 +BACKGROUND_GREEN = 0x0020 +BACKGROUND_CYAN = 0x0030 +BACKGROUND_RED = 0x0040 +BACKGROUND_MAGENTA = 0x0050 +BACKGROUND_YELLOW = 0x0060 +BACKGROUND_GREY = 0x0070 +BACKGROUND_INTENSITY = 0x0080 + +COMMON_LVB_LEADING_BYTE = 0x0100 +COMMON_LVB_TRAILING_BYTE = 0x0200 +COMMON_LVB_GRID_HORIZONTAL = 0x0400 +COMMON_LVB_GRID_LVERTICAL = 0x0800 +COMMON_LVB_GRID_RVERTICAL = 0x1000 +COMMON_LVB_REVERSE_VIDEO = 0x4000 +COMMON_LVB_UNDERSCORE = 0x8000 + +# typedef struct _CHAR_INFO { +# union { +# WCHAR UnicodeChar; +# CHAR AsciiChar; +# } Char; +# WORD Attributes; +# } CHAR_INFO, *PCHAR_INFO; +class _CHAR_INFO_CHAR(Union): + _fields_ = [ + ('UnicodeChar', WCHAR), + ('AsciiChar', CHAR), + ] +class CHAR_INFO(Structure): + _fields_ = [ + ('Char', _CHAR_INFO_CHAR), + ('Attributes', WORD), + ] +PCHAR_INFO = POINTER(CHAR_INFO) + +# typedef struct _COORD { +# SHORT X; +# SHORT Y; +# } COORD, *PCOORD; +class COORD(Structure): + _fields_ = [ + ('X', SHORT), + ('Y', SHORT), + ] +PCOORD = POINTER(COORD) + +# typedef struct _SMALL_RECT { +# SHORT Left; +# SHORT Top; +# SHORT Right; +# SHORT Bottom; +# } SMALL_RECT; +class SMALL_RECT(Structure): + _fields_ = [ + ('Left', SHORT), + ('Top', SHORT), + ('Right', SHORT), + ('Bottom', SHORT), + ] +PSMALL_RECT = POINTER(SMALL_RECT) + +# typedef struct _CONSOLE_SCREEN_BUFFER_INFO { +# COORD dwSize; +# COORD dwCursorPosition; +# WORD wAttributes; +# SMALL_RECT srWindow; +# COORD dwMaximumWindowSize; +# } CONSOLE_SCREEN_BUFFER_INFO; +class CONSOLE_SCREEN_BUFFER_INFO(Structure): + _fields_ = [ + ('dwSize', COORD), + ('dwCursorPosition', COORD), + ('wAttributes', WORD), + ('srWindow', SMALL_RECT), + ('dwMaximumWindowSize', COORD), + ] +PCONSOLE_SCREEN_BUFFER_INFO = POINTER(CONSOLE_SCREEN_BUFFER_INFO) + +#--- Toolhelp library defines and structures ---------------------------------- + +TH32CS_SNAPHEAPLIST = 0x00000001 +TH32CS_SNAPPROCESS = 0x00000002 +TH32CS_SNAPTHREAD = 0x00000004 +TH32CS_SNAPMODULE = 0x00000008 +TH32CS_INHERIT = 0x80000000 +TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE) + +# typedef struct tagTHREADENTRY32 { +# DWORD dwSize; +# DWORD cntUsage; +# DWORD th32ThreadID; +# DWORD th32OwnerProcessID; +# LONG tpBasePri; +# LONG tpDeltaPri; +# DWORD dwFlags; +# } THREADENTRY32, *PTHREADENTRY32; +class THREADENTRY32(Structure): + _fields_ = [ + ('dwSize', DWORD), + ('cntUsage', DWORD), + ('th32ThreadID', DWORD), + ('th32OwnerProcessID', DWORD), + ('tpBasePri', LONG), + ('tpDeltaPri', LONG), + ('dwFlags', DWORD), + ] +LPTHREADENTRY32 = POINTER(THREADENTRY32) + +# typedef struct tagPROCESSENTRY32 { +# DWORD dwSize; +# DWORD cntUsage; +# DWORD th32ProcessID; +# ULONG_PTR th32DefaultHeapID; +# DWORD th32ModuleID; +# DWORD cntThreads; +# DWORD th32ParentProcessID; +# LONG pcPriClassBase; +# DWORD dwFlags; +# TCHAR szExeFile[MAX_PATH]; +# } PROCESSENTRY32, *PPROCESSENTRY32; +class PROCESSENTRY32(Structure): + _fields_ = [ + ('dwSize', DWORD), + ('cntUsage', DWORD), + ('th32ProcessID', DWORD), + ('th32DefaultHeapID', ULONG_PTR), + ('th32ModuleID', DWORD), + ('cntThreads', DWORD), + ('th32ParentProcessID', DWORD), + ('pcPriClassBase', LONG), + ('dwFlags', DWORD), + ('szExeFile', TCHAR * 260), + ] +LPPROCESSENTRY32 = POINTER(PROCESSENTRY32) + +# typedef struct tagMODULEENTRY32 { +# DWORD dwSize; +# DWORD th32ModuleID; +# DWORD th32ProcessID; +# DWORD GlblcntUsage; +# DWORD ProccntUsage; +# BYTE* modBaseAddr; +# DWORD modBaseSize; +# HMODULE hModule; +# TCHAR szModule[MAX_MODULE_NAME32 + 1]; +# TCHAR szExePath[MAX_PATH]; +# } MODULEENTRY32, *PMODULEENTRY32; +class MODULEENTRY32(Structure): + _fields_ = [ + ("dwSize", DWORD), + ("th32ModuleID", DWORD), + ("th32ProcessID", DWORD), + ("GlblcntUsage", DWORD), + ("ProccntUsage", DWORD), + ("modBaseAddr", LPVOID), # BYTE* + ("modBaseSize", DWORD), + ("hModule", HMODULE), + ("szModule", TCHAR * (MAX_MODULE_NAME32 + 1)), + ("szExePath", TCHAR * MAX_PATH), + ] +LPMODULEENTRY32 = POINTER(MODULEENTRY32) + +# typedef struct tagHEAPENTRY32 { +# SIZE_T dwSize; +# HANDLE hHandle; +# ULONG_PTR dwAddress; +# SIZE_T dwBlockSize; +# DWORD dwFlags; +# DWORD dwLockCount; +# DWORD dwResvd; +# DWORD th32ProcessID; +# ULONG_PTR th32HeapID; +# } HEAPENTRY32, +# *PHEAPENTRY32; +class HEAPENTRY32(Structure): + _fields_ = [ + ("dwSize", SIZE_T), + ("hHandle", HANDLE), + ("dwAddress", ULONG_PTR), + ("dwBlockSize", SIZE_T), + ("dwFlags", DWORD), + ("dwLockCount", DWORD), + ("dwResvd", DWORD), + ("th32ProcessID", DWORD), + ("th32HeapID", ULONG_PTR), +] +LPHEAPENTRY32 = POINTER(HEAPENTRY32) + +# typedef struct tagHEAPLIST32 { +# SIZE_T dwSize; +# DWORD th32ProcessID; +# ULONG_PTR th32HeapID; +# DWORD dwFlags; +# } HEAPLIST32, +# *PHEAPLIST32; +class HEAPLIST32(Structure): + _fields_ = [ + ("dwSize", SIZE_T), + ("th32ProcessID", DWORD), + ("th32HeapID", ULONG_PTR), + ("dwFlags", DWORD), +] +LPHEAPLIST32 = POINTER(HEAPLIST32) + +#--- kernel32.dll ------------------------------------------------------------- + +# DWORD WINAPI GetLastError(void); +def GetLastError(): + _GetLastError = windll.kernel32.GetLastError + _GetLastError.argtypes = [] + _GetLastError.restype = DWORD + return _GetLastError() + +# void WINAPI SetLastError( +# __in DWORD dwErrCode +# ); +def SetLastError(dwErrCode): + _SetLastError = windll.kernel32.SetLastError + _SetLastError.argtypes = [DWORD] + _SetLastError.restype = None + _SetLastError(dwErrCode) + +# UINT WINAPI GetErrorMode(void); +def GetErrorMode(): + _GetErrorMode = windll.kernel32.GetErrorMode + _GetErrorMode.argtypes = [] + _GetErrorMode.restype = UINT + return _GetErrorMode() + +# UINT WINAPI SetErrorMode( +# __in UINT uMode +# ); +def SetErrorMode(uMode): + _SetErrorMode = windll.kernel32.SetErrorMode + _SetErrorMode.argtypes = [UINT] + _SetErrorMode.restype = UINT + return _SetErrorMode(dwErrCode) + +# DWORD GetThreadErrorMode(void); +def GetThreadErrorMode(): + _GetThreadErrorMode = windll.kernel32.GetThreadErrorMode + _GetThreadErrorMode.argtypes = [] + _GetThreadErrorMode.restype = DWORD + return _GetThreadErrorMode() + +# BOOL SetThreadErrorMode( +# __in DWORD dwNewMode, +# __out LPDWORD lpOldMode +# ); +def SetThreadErrorMode(dwNewMode): + _SetThreadErrorMode = windll.kernel32.SetThreadErrorMode + _SetThreadErrorMode.argtypes = [DWORD, LPDWORD] + _SetThreadErrorMode.restype = BOOL + _SetThreadErrorMode.errcheck = RaiseIfZero + + old = DWORD(0) + _SetThreadErrorMode(dwErrCode, byref(old)) + return old.value + +# BOOL WINAPI CloseHandle( +# __in HANDLE hObject +# ); +def CloseHandle(hHandle): + if isinstance(hHandle, Handle): + # Prevents the handle from being closed without notifying the Handle object. + hHandle.close() + else: + _CloseHandle = windll.kernel32.CloseHandle + _CloseHandle.argtypes = [HANDLE] + _CloseHandle.restype = bool + _CloseHandle.errcheck = RaiseIfZero + _CloseHandle(hHandle) + +# BOOL WINAPI DuplicateHandle( +# __in HANDLE hSourceProcessHandle, +# __in HANDLE hSourceHandle, +# __in HANDLE hTargetProcessHandle, +# __out LPHANDLE lpTargetHandle, +# __in DWORD dwDesiredAccess, +# __in BOOL bInheritHandle, +# __in DWORD dwOptions +# ); +def DuplicateHandle(hSourceHandle, hSourceProcessHandle = None, hTargetProcessHandle = None, dwDesiredAccess = STANDARD_RIGHTS_ALL, bInheritHandle = False, dwOptions = DUPLICATE_SAME_ACCESS): + _DuplicateHandle = windll.kernel32.DuplicateHandle + _DuplicateHandle.argtypes = [HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, BOOL, DWORD] + _DuplicateHandle.restype = bool + _DuplicateHandle.errcheck = RaiseIfZero + + # NOTE: the arguments to this function are in a different order, + # so we can set default values for all of them but one (hSourceHandle). + + if hSourceProcessHandle is None: + hSourceProcessHandle = GetCurrentProcess() + if hTargetProcessHandle is None: + hTargetProcessHandle = hSourceProcessHandle + lpTargetHandle = HANDLE(INVALID_HANDLE_VALUE) + _DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, byref(lpTargetHandle), dwDesiredAccess, bool(bInheritHandle), dwOptions) + if isinstance(hSourceHandle, Handle): + HandleClass = hSourceHandle.__class__ + else: + HandleClass = Handle + if hasattr(hSourceHandle, 'dwAccess'): + return HandleClass(lpTargetHandle.value, dwAccess = hSourceHandle.dwAccess) + else: + return HandleClass(lpTargetHandle.value) + +# HLOCAL WINAPI LocalFree( +# __in HLOCAL hMem +# ); +def LocalFree(hMem): + _LocalFree = windll.kernel32.LocalFree + _LocalFree.argtypes = [HLOCAL] + _LocalFree.restype = HLOCAL + + result = _LocalFree(hMem) + if result != NULL: + ctypes.WinError() + +#------------------------------------------------------------------------------ +# Console API + +# HANDLE WINAPI GetStdHandle( +# _In_ DWORD nStdHandle +# ); +def GetStdHandle(nStdHandle): + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argytpes = [DWORD] + _GetStdHandle.restype = HANDLE + _GetStdHandle.errcheck = RaiseIfZero + return Handle( _GetStdHandle(nStdHandle), bOwnership = False ) + +# BOOL WINAPI SetStdHandle( +# _In_ DWORD nStdHandle, +# _In_ HANDLE hHandle +# ); + +# TODO + +# UINT WINAPI GetConsoleCP(void); +def GetConsoleCP(): + _GetConsoleCP = windll.kernel32.GetConsoleCP + _GetConsoleCP.argytpes = [] + _GetConsoleCP.restype = UINT + return _GetConsoleCP() + +# UINT WINAPI GetConsoleOutputCP(void); +def GetConsoleOutputCP(): + _GetConsoleOutputCP = windll.kernel32.GetConsoleOutputCP + _GetConsoleOutputCP.argytpes = [] + _GetConsoleOutputCP.restype = UINT + return _GetConsoleOutputCP() + +#BOOL WINAPI SetConsoleCP( +# _In_ UINT wCodePageID +#); +def SetConsoleCP(wCodePageID): + _SetConsoleCP = windll.kernel32.SetConsoleCP + _SetConsoleCP.argytpes = [UINT] + _SetConsoleCP.restype = bool + _SetConsoleCP.errcheck = RaiseIfZero + _SetConsoleCP(wCodePageID) + +#BOOL WINAPI SetConsoleOutputCP( +# _In_ UINT wCodePageID +#); +def SetConsoleOutputCP(wCodePageID): + _SetConsoleOutputCP = windll.kernel32.SetConsoleOutputCP + _SetConsoleOutputCP.argytpes = [UINT] + _SetConsoleOutputCP.restype = bool + _SetConsoleOutputCP.errcheck = RaiseIfZero + _SetConsoleOutputCP(wCodePageID) + +# HANDLE WINAPI CreateConsoleScreenBuffer( +# _In_ DWORD dwDesiredAccess, +# _In_ DWORD dwShareMode, +# _In_opt_ const SECURITY_ATTRIBUTES *lpSecurityAttributes, +# _In_ DWORD dwFlags, +# _Reserved_ LPVOID lpScreenBufferData +# ); + +# TODO + +# BOOL WINAPI SetConsoleActiveScreenBuffer( +# _In_ HANDLE hConsoleOutput +# ); +def SetConsoleActiveScreenBuffer(hConsoleOutput = None): + _SetConsoleActiveScreenBuffer = windll.kernel32.SetConsoleActiveScreenBuffer + _SetConsoleActiveScreenBuffer.argytpes = [HANDLE] + _SetConsoleActiveScreenBuffer.restype = bool + _SetConsoleActiveScreenBuffer.errcheck = RaiseIfZero + + if hConsoleOutput is None: + hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE) + _SetConsoleActiveScreenBuffer(hConsoleOutput) + +# BOOL WINAPI GetConsoleScreenBufferInfo( +# _In_ HANDLE hConsoleOutput, +# _Out_ PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo +# ); +def GetConsoleScreenBufferInfo(hConsoleOutput = None): + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argytpes = [HANDLE, PCONSOLE_SCREEN_BUFFER_INFO] + _GetConsoleScreenBufferInfo.restype = bool + _GetConsoleScreenBufferInfo.errcheck = RaiseIfZero + + if hConsoleOutput is None: + hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE) + ConsoleScreenBufferInfo = CONSOLE_SCREEN_BUFFER_INFO() + _GetConsoleScreenBufferInfo(hConsoleOutput, byref(ConsoleScreenBufferInfo)) + return ConsoleScreenBufferInfo + +# BOOL WINAPI GetConsoleScreenBufferInfoEx( +# _In_ HANDLE hConsoleOutput, +# _Out_ PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx +# ); + +# TODO + +# BOOL WINAPI SetConsoleWindowInfo( +# _In_ HANDLE hConsoleOutput, +# _In_ BOOL bAbsolute, +# _In_ const SMALL_RECT *lpConsoleWindow +# ); +def SetConsoleWindowInfo(hConsoleOutput, bAbsolute, lpConsoleWindow): + _SetConsoleWindowInfo = windll.kernel32.SetConsoleWindowInfo + _SetConsoleWindowInfo.argytpes = [HANDLE, BOOL, PSMALL_RECT] + _SetConsoleWindowInfo.restype = bool + _SetConsoleWindowInfo.errcheck = RaiseIfZero + + if hConsoleOutput is None: + hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE) + if isinstance(lpConsoleWindow, SMALL_RECT): + ConsoleWindow = lpConsoleWindow + else: + ConsoleWindow = SMALL_RECT(*lpConsoleWindow) + _SetConsoleWindowInfo(hConsoleOutput, bAbsolute, byref(ConsoleWindow)) + +# BOOL WINAPI SetConsoleTextAttribute( +# _In_ HANDLE hConsoleOutput, +# _In_ WORD wAttributes +# ); +def SetConsoleTextAttribute(hConsoleOutput = None, wAttributes = 0): + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argytpes = [HANDLE, WORD] + _SetConsoleTextAttribute.restype = bool + _SetConsoleTextAttribute.errcheck = RaiseIfZero + + if hConsoleOutput is None: + hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE) + _SetConsoleTextAttribute(hConsoleOutput, wAttributes) + +# HANDLE WINAPI CreateConsoleScreenBuffer( +# _In_ DWORD dwDesiredAccess, +# _In_ DWORD dwShareMode, +# _In_opt_ const SECURITY_ATTRIBUTES *lpSecurityAttributes, +# _In_ DWORD dwFlags, +# _Reserved_ LPVOID lpScreenBufferData +# ); + +# TODO + +# BOOL WINAPI AllocConsole(void); +def AllocConsole(): + _AllocConsole = windll.kernel32.AllocConsole + _AllocConsole.argytpes = [] + _AllocConsole.restype = bool + _AllocConsole.errcheck = RaiseIfZero + _AllocConsole() + +# BOOL WINAPI AttachConsole( +# _In_ DWORD dwProcessId +# ); +def AttachConsole(dwProcessId = ATTACH_PARENT_PROCESS): + _AttachConsole = windll.kernel32.AttachConsole + _AttachConsole.argytpes = [DWORD] + _AttachConsole.restype = bool + _AttachConsole.errcheck = RaiseIfZero + _AttachConsole(dwProcessId) + +# BOOL WINAPI FreeConsole(void); +def FreeConsole(): + _FreeConsole = windll.kernel32.FreeConsole + _FreeConsole.argytpes = [] + _FreeConsole.restype = bool + _FreeConsole.errcheck = RaiseIfZero + _FreeConsole() + +# DWORD WINAPI GetConsoleProcessList( +# _Out_ LPDWORD lpdwProcessList, +# _In_ DWORD dwProcessCount +# ); + +# TODO + +# DWORD WINAPI GetConsoleTitle( +# _Out_ LPTSTR lpConsoleTitle, +# _In_ DWORD nSize +# ); + +# TODO + +#BOOL WINAPI SetConsoleTitle( +# _In_ LPCTSTR lpConsoleTitle +#); + +# TODO + +# COORD WINAPI GetLargestConsoleWindowSize( +# _In_ HANDLE hConsoleOutput +# ); + +# TODO + +# BOOL WINAPI GetConsoleHistoryInfo( +# _Out_ PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo +# ); + +# TODO + +#------------------------------------------------------------------------------ +# DLL API + +# DWORD WINAPI GetDllDirectory( +# __in DWORD nBufferLength, +# __out LPTSTR lpBuffer +# ); +def GetDllDirectoryA(): + _GetDllDirectoryA = windll.kernel32.GetDllDirectoryA + _GetDllDirectoryA.argytpes = [DWORD, LPSTR] + _GetDllDirectoryA.restype = DWORD + + nBufferLength = _GetDllDirectoryA(0, None) + if nBufferLength == 0: + return None + lpBuffer = ctypes.create_string_buffer("", nBufferLength) + _GetDllDirectoryA(nBufferLength, byref(lpBuffer)) + return lpBuffer.value + +def GetDllDirectoryW(): + _GetDllDirectoryW = windll.kernel32.GetDllDirectoryW + _GetDllDirectoryW.argytpes = [DWORD, LPWSTR] + _GetDllDirectoryW.restype = DWORD + + nBufferLength = _GetDllDirectoryW(0, None) + if nBufferLength == 0: + return None + lpBuffer = ctypes.create_unicode_buffer(u"", nBufferLength) + _GetDllDirectoryW(nBufferLength, byref(lpBuffer)) + return lpBuffer.value + +GetDllDirectory = GuessStringType(GetDllDirectoryA, GetDllDirectoryW) + +# BOOL WINAPI SetDllDirectory( +# __in_opt LPCTSTR lpPathName +# ); +def SetDllDirectoryA(lpPathName = None): + _SetDllDirectoryA = windll.kernel32.SetDllDirectoryA + _SetDllDirectoryA.argytpes = [LPSTR] + _SetDllDirectoryA.restype = bool + _SetDllDirectoryA.errcheck = RaiseIfZero + _SetDllDirectoryA(lpPathName) + +def SetDllDirectoryW(lpPathName): + _SetDllDirectoryW = windll.kernel32.SetDllDirectoryW + _SetDllDirectoryW.argytpes = [LPWSTR] + _SetDllDirectoryW.restype = bool + _SetDllDirectoryW.errcheck = RaiseIfZero + _SetDllDirectoryW(lpPathName) + +SetDllDirectory = GuessStringType(SetDllDirectoryA, SetDllDirectoryW) + +# HMODULE WINAPI LoadLibrary( +# __in LPCTSTR lpFileName +# ); +def LoadLibraryA(pszLibrary): + _LoadLibraryA = windll.kernel32.LoadLibraryA + _LoadLibraryA.argtypes = [LPSTR] + _LoadLibraryA.restype = HMODULE + hModule = _LoadLibraryA(pszLibrary) + if hModule == NULL: + raise ctypes.WinError() + return hModule + +def LoadLibraryW(pszLibrary): + _LoadLibraryW = windll.kernel32.LoadLibraryW + _LoadLibraryW.argtypes = [LPWSTR] + _LoadLibraryW.restype = HMODULE + hModule = _LoadLibraryW(pszLibrary) + if hModule == NULL: + raise ctypes.WinError() + return hModule + +LoadLibrary = GuessStringType(LoadLibraryA, LoadLibraryW) + +# HMODULE WINAPI LoadLibraryEx( +# __in LPCTSTR lpFileName, +# __reserved HANDLE hFile, +# __in DWORD dwFlags +# ); +def LoadLibraryExA(pszLibrary, dwFlags = 0): + _LoadLibraryExA = windll.kernel32.LoadLibraryExA + _LoadLibraryExA.argtypes = [LPSTR, HANDLE, DWORD] + _LoadLibraryExA.restype = HMODULE + hModule = _LoadLibraryExA(pszLibrary, NULL, dwFlags) + if hModule == NULL: + raise ctypes.WinError() + return hModule + +def LoadLibraryExW(pszLibrary, dwFlags = 0): + _LoadLibraryExW = windll.kernel32.LoadLibraryExW + _LoadLibraryExW.argtypes = [LPWSTR, HANDLE, DWORD] + _LoadLibraryExW.restype = HMODULE + hModule = _LoadLibraryExW(pszLibrary, NULL, dwFlags) + if hModule == NULL: + raise ctypes.WinError() + return hModule + +LoadLibraryEx = GuessStringType(LoadLibraryExA, LoadLibraryExW) + +# HMODULE WINAPI GetModuleHandle( +# __in_opt LPCTSTR lpModuleName +# ); +def GetModuleHandleA(lpModuleName): + _GetModuleHandleA = windll.kernel32.GetModuleHandleA + _GetModuleHandleA.argtypes = [LPSTR] + _GetModuleHandleA.restype = HMODULE + hModule = _GetModuleHandleA(lpModuleName) + if hModule == NULL: + raise ctypes.WinError() + return hModule + +def GetModuleHandleW(lpModuleName): + _GetModuleHandleW = windll.kernel32.GetModuleHandleW + _GetModuleHandleW.argtypes = [LPWSTR] + _GetModuleHandleW.restype = HMODULE + hModule = _GetModuleHandleW(lpModuleName) + if hModule == NULL: + raise ctypes.WinError() + return hModule + +GetModuleHandle = GuessStringType(GetModuleHandleA, GetModuleHandleW) + +# FARPROC WINAPI GetProcAddress( +# __in HMODULE hModule, +# __in LPCSTR lpProcName +# ); +def GetProcAddressA(hModule, lpProcName): + _GetProcAddress = windll.kernel32.GetProcAddress + _GetProcAddress.argtypes = [HMODULE, LPVOID] + _GetProcAddress.restype = LPVOID + + if type(lpProcName) in (type(0), type(long(0))): + lpProcName = LPVOID(lpProcName) + if lpProcName.value & (~0xFFFF): + raise ValueError('Ordinal number too large: %d' % lpProcName.value) + elif type(lpProcName) == type(compat.b("")): + lpProcName = ctypes.c_char_p(lpProcName) + else: + raise TypeError(str(type(lpProcName))) + return _GetProcAddress(hModule, lpProcName) + +GetProcAddressW = MakeWideVersion(GetProcAddressA) +GetProcAddress = GuessStringType(GetProcAddressA, GetProcAddressW) + +# BOOL WINAPI FreeLibrary( +# __in HMODULE hModule +# ); +def FreeLibrary(hModule): + _FreeLibrary = windll.kernel32.FreeLibrary + _FreeLibrary.argtypes = [HMODULE] + _FreeLibrary.restype = bool + _FreeLibrary.errcheck = RaiseIfZero + _FreeLibrary(hModule) + +# PVOID WINAPI RtlPcToFileHeader( +# __in PVOID PcValue, +# __out PVOID *BaseOfImage +# ); +def RtlPcToFileHeader(PcValue): + _RtlPcToFileHeader = windll.kernel32.RtlPcToFileHeader + _RtlPcToFileHeader.argtypes = [PVOID, POINTER(PVOID)] + _RtlPcToFileHeader.restype = PRUNTIME_FUNCTION + + BaseOfImage = PVOID(0) + _RtlPcToFileHeader(PcValue, byref(BaseOfImage)) + return BaseOfImage.value + +#------------------------------------------------------------------------------ +# File API and related + +# BOOL WINAPI GetHandleInformation( +# __in HANDLE hObject, +# __out LPDWORD lpdwFlags +# ); +def GetHandleInformation(hObject): + _GetHandleInformation = windll.kernel32.GetHandleInformation + _GetHandleInformation.argtypes = [HANDLE, PDWORD] + _GetHandleInformation.restype = bool + _GetHandleInformation.errcheck = RaiseIfZero + + dwFlags = DWORD(0) + _GetHandleInformation(hObject, byref(dwFlags)) + return dwFlags.value + +# BOOL WINAPI SetHandleInformation( +# __in HANDLE hObject, +# __in DWORD dwMask, +# __in DWORD dwFlags +# ); +def SetHandleInformation(hObject, dwMask, dwFlags): + _SetHandleInformation = windll.kernel32.SetHandleInformation + _SetHandleInformation.argtypes = [HANDLE, DWORD, DWORD] + _SetHandleInformation.restype = bool + _SetHandleInformation.errcheck = RaiseIfZero + _SetHandleInformation(hObject, dwMask, dwFlags) + +# UINT WINAPI GetWindowModuleFileName( +# __in HWND hwnd, +# __out LPTSTR lpszFileName, +# __in UINT cchFileNameMax +# ); +# Not included because it doesn't work in other processes. +# See: http://support.microsoft.com/?id=228469 + +# BOOL WINAPI QueryFullProcessImageName( +# __in HANDLE hProcess, +# __in DWORD dwFlags, +# __out LPTSTR lpExeName, +# __inout PDWORD lpdwSize +# ); +def QueryFullProcessImageNameA(hProcess, dwFlags = 0): + _QueryFullProcessImageNameA = windll.kernel32.QueryFullProcessImageNameA + _QueryFullProcessImageNameA.argtypes = [HANDLE, DWORD, LPSTR, PDWORD] + _QueryFullProcessImageNameA.restype = bool + + dwSize = MAX_PATH + while 1: + lpdwSize = DWORD(dwSize) + lpExeName = ctypes.create_string_buffer('', lpdwSize.value + 1) + success = _QueryFullProcessImageNameA(hProcess, dwFlags, lpExeName, byref(lpdwSize)) + if success and 0 < lpdwSize.value < dwSize: + break + error = GetLastError() + if error != ERROR_INSUFFICIENT_BUFFER: + raise ctypes.WinError(error) + dwSize = dwSize + 256 + if dwSize > 0x1000: + # this prevents an infinite loop in Windows 2008 when the path has spaces, + # see http://msdn.microsoft.com/en-us/library/ms684919(VS.85).aspx#4 + raise ctypes.WinError(error) + return lpExeName.value + +def QueryFullProcessImageNameW(hProcess, dwFlags = 0): + _QueryFullProcessImageNameW = windll.kernel32.QueryFullProcessImageNameW + _QueryFullProcessImageNameW.argtypes = [HANDLE, DWORD, LPWSTR, PDWORD] + _QueryFullProcessImageNameW.restype = bool + + dwSize = MAX_PATH + while 1: + lpdwSize = DWORD(dwSize) + lpExeName = ctypes.create_unicode_buffer('', lpdwSize.value + 1) + success = _QueryFullProcessImageNameW(hProcess, dwFlags, lpExeName, byref(lpdwSize)) + if success and 0 < lpdwSize.value < dwSize: + break + error = GetLastError() + if error != ERROR_INSUFFICIENT_BUFFER: + raise ctypes.WinError(error) + dwSize = dwSize + 256 + if dwSize > 0x1000: + # this prevents an infinite loop in Windows 2008 when the path has spaces, + # see http://msdn.microsoft.com/en-us/library/ms684919(VS.85).aspx#4 + raise ctypes.WinError(error) + return lpExeName.value + +QueryFullProcessImageName = GuessStringType(QueryFullProcessImageNameA, QueryFullProcessImageNameW) + +# DWORD WINAPI GetLogicalDriveStrings( +# __in DWORD nBufferLength, +# __out LPTSTR lpBuffer +# ); +def GetLogicalDriveStringsA(): + _GetLogicalDriveStringsA = ctypes.windll.kernel32.GetLogicalDriveStringsA + _GetLogicalDriveStringsA.argtypes = [DWORD, LPSTR] + _GetLogicalDriveStringsA.restype = DWORD + _GetLogicalDriveStringsA.errcheck = RaiseIfZero + + nBufferLength = (4 * 26) + 1 # "X:\\\0" from A to Z plus empty string + lpBuffer = ctypes.create_string_buffer('', nBufferLength) + _GetLogicalDriveStringsA(nBufferLength, lpBuffer) + drive_strings = list() + string_p = addressof(lpBuffer) + sizeof_char = sizeof(ctypes.c_char) + while True: + string_v = ctypes.string_at(string_p) + if string_v == '': + break + drive_strings.append(string_v) + string_p += len(string_v) + sizeof_char + return drive_strings + +def GetLogicalDriveStringsW(): + _GetLogicalDriveStringsW = ctypes.windll.kernel32.GetLogicalDriveStringsW + _GetLogicalDriveStringsW.argtypes = [DWORD, LPWSTR] + _GetLogicalDriveStringsW.restype = DWORD + _GetLogicalDriveStringsW.errcheck = RaiseIfZero + + nBufferLength = (4 * 26) + 1 # "X:\\\0" from A to Z plus empty string + lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength) + _GetLogicalDriveStringsW(nBufferLength, lpBuffer) + drive_strings = list() + string_p = addressof(lpBuffer) + sizeof_wchar = sizeof(ctypes.c_wchar) + while True: + string_v = ctypes.wstring_at(string_p) + if string_v == u'': + break + drive_strings.append(string_v) + string_p += (len(string_v) * sizeof_wchar) + sizeof_wchar + return drive_strings + +##def GetLogicalDriveStringsA(): +## _GetLogicalDriveStringsA = windll.kernel32.GetLogicalDriveStringsA +## _GetLogicalDriveStringsA.argtypes = [DWORD, LPSTR] +## _GetLogicalDriveStringsA.restype = DWORD +## _GetLogicalDriveStringsA.errcheck = RaiseIfZero +## +## nBufferLength = (4 * 26) + 1 # "X:\\\0" from A to Z plus empty string +## lpBuffer = ctypes.create_string_buffer('', nBufferLength) +## _GetLogicalDriveStringsA(nBufferLength, lpBuffer) +## result = list() +## index = 0 +## while 1: +## string = list() +## while 1: +## character = lpBuffer[index] +## index = index + 1 +## if character == '\0': +## break +## string.append(character) +## if not string: +## break +## result.append(''.join(string)) +## return result +## +##def GetLogicalDriveStringsW(): +## _GetLogicalDriveStringsW = windll.kernel32.GetLogicalDriveStringsW +## _GetLogicalDriveStringsW.argtypes = [DWORD, LPWSTR] +## _GetLogicalDriveStringsW.restype = DWORD +## _GetLogicalDriveStringsW.errcheck = RaiseIfZero +## +## nBufferLength = (4 * 26) + 1 # "X:\\\0" from A to Z plus empty string +## lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength) +## _GetLogicalDriveStringsW(nBufferLength, lpBuffer) +## result = list() +## index = 0 +## while 1: +## string = list() +## while 1: +## character = lpBuffer[index] +## index = index + 1 +## if character == u'\0': +## break +## string.append(character) +## if not string: +## break +## result.append(u''.join(string)) +## return result + +GetLogicalDriveStrings = GuessStringType(GetLogicalDriveStringsA, GetLogicalDriveStringsW) + +# DWORD WINAPI QueryDosDevice( +# __in_opt LPCTSTR lpDeviceName, +# __out LPTSTR lpTargetPath, +# __in DWORD ucchMax +# ); +def QueryDosDeviceA(lpDeviceName = None): + _QueryDosDeviceA = windll.kernel32.QueryDosDeviceA + _QueryDosDeviceA.argtypes = [LPSTR, LPSTR, DWORD] + _QueryDosDeviceA.restype = DWORD + _QueryDosDeviceA.errcheck = RaiseIfZero + + if not lpDeviceName: + lpDeviceName = None + ucchMax = 0x1000 + lpTargetPath = ctypes.create_string_buffer('', ucchMax) + _QueryDosDeviceA(lpDeviceName, lpTargetPath, ucchMax) + return lpTargetPath.value + +def QueryDosDeviceW(lpDeviceName): + _QueryDosDeviceW = windll.kernel32.QueryDosDeviceW + _QueryDosDeviceW.argtypes = [LPWSTR, LPWSTR, DWORD] + _QueryDosDeviceW.restype = DWORD + _QueryDosDeviceW.errcheck = RaiseIfZero + + if not lpDeviceName: + lpDeviceName = None + ucchMax = 0x1000 + lpTargetPath = ctypes.create_unicode_buffer(u'', ucchMax) + _QueryDosDeviceW(lpDeviceName, lpTargetPath, ucchMax) + return lpTargetPath.value + +QueryDosDevice = GuessStringType(QueryDosDeviceA, QueryDosDeviceW) + +# LPVOID WINAPI MapViewOfFile( +# __in HANDLE hFileMappingObject, +# __in DWORD dwDesiredAccess, +# __in DWORD dwFileOffsetHigh, +# __in DWORD dwFileOffsetLow, +# __in SIZE_T dwNumberOfBytesToMap +# ); +def MapViewOfFile(hFileMappingObject, dwDesiredAccess = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, dwFileOffsetHigh = 0, dwFileOffsetLow = 0, dwNumberOfBytesToMap = 0): + _MapViewOfFile = windll.kernel32.MapViewOfFile + _MapViewOfFile.argtypes = [HANDLE, DWORD, DWORD, DWORD, SIZE_T] + _MapViewOfFile.restype = LPVOID + lpBaseAddress = _MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap) + if lpBaseAddress == NULL: + raise ctypes.WinError() + return lpBaseAddress + +# BOOL WINAPI UnmapViewOfFile( +# __in LPCVOID lpBaseAddress +# ); +def UnmapViewOfFile(lpBaseAddress): + _UnmapViewOfFile = windll.kernel32.UnmapViewOfFile + _UnmapViewOfFile.argtypes = [LPVOID] + _UnmapViewOfFile.restype = bool + _UnmapViewOfFile.errcheck = RaiseIfZero + _UnmapViewOfFile(lpBaseAddress) + +# HANDLE WINAPI OpenFileMapping( +# __in DWORD dwDesiredAccess, +# __in BOOL bInheritHandle, +# __in LPCTSTR lpName +# ); +def OpenFileMappingA(dwDesiredAccess, bInheritHandle, lpName): + _OpenFileMappingA = windll.kernel32.OpenFileMappingA + _OpenFileMappingA.argtypes = [DWORD, BOOL, LPSTR] + _OpenFileMappingA.restype = HANDLE + _OpenFileMappingA.errcheck = RaiseIfZero + hFileMappingObject = _OpenFileMappingA(dwDesiredAccess, bool(bInheritHandle), lpName) + return FileMappingHandle(hFileMappingObject) + +def OpenFileMappingW(dwDesiredAccess, bInheritHandle, lpName): + _OpenFileMappingW = windll.kernel32.OpenFileMappingW + _OpenFileMappingW.argtypes = [DWORD, BOOL, LPWSTR] + _OpenFileMappingW.restype = HANDLE + _OpenFileMappingW.errcheck = RaiseIfZero + hFileMappingObject = _OpenFileMappingW(dwDesiredAccess, bool(bInheritHandle), lpName) + return FileMappingHandle(hFileMappingObject) + +OpenFileMapping = GuessStringType(OpenFileMappingA, OpenFileMappingW) + +# HANDLE WINAPI CreateFileMapping( +# __in HANDLE hFile, +# __in_opt LPSECURITY_ATTRIBUTES lpAttributes, +# __in DWORD flProtect, +# __in DWORD dwMaximumSizeHigh, +# __in DWORD dwMaximumSizeLow, +# __in_opt LPCTSTR lpName +# ); +def CreateFileMappingA(hFile, lpAttributes = None, flProtect = PAGE_EXECUTE_READWRITE, dwMaximumSizeHigh = 0, dwMaximumSizeLow = 0, lpName = None): + _CreateFileMappingA = windll.kernel32.CreateFileMappingA + _CreateFileMappingA.argtypes = [HANDLE, LPVOID, DWORD, DWORD, DWORD, LPSTR] + _CreateFileMappingA.restype = HANDLE + _CreateFileMappingA.errcheck = RaiseIfZero + + if lpAttributes: + lpAttributes = ctypes.pointer(lpAttributes) + if not lpName: + lpName = None + hFileMappingObject = _CreateFileMappingA(hFile, lpAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName) + return FileMappingHandle(hFileMappingObject) + +def CreateFileMappingW(hFile, lpAttributes = None, flProtect = PAGE_EXECUTE_READWRITE, dwMaximumSizeHigh = 0, dwMaximumSizeLow = 0, lpName = None): + _CreateFileMappingW = windll.kernel32.CreateFileMappingW + _CreateFileMappingW.argtypes = [HANDLE, LPVOID, DWORD, DWORD, DWORD, LPWSTR] + _CreateFileMappingW.restype = HANDLE + _CreateFileMappingW.errcheck = RaiseIfZero + + if lpAttributes: + lpAttributes = ctypes.pointer(lpAttributes) + if not lpName: + lpName = None + hFileMappingObject = _CreateFileMappingW(hFile, lpAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName) + return FileMappingHandle(hFileMappingObject) + +CreateFileMapping = GuessStringType(CreateFileMappingA, CreateFileMappingW) + +# HANDLE WINAPI CreateFile( +# __in LPCTSTR lpFileName, +# __in DWORD dwDesiredAccess, +# __in DWORD dwShareMode, +# __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, +# __in DWORD dwCreationDisposition, +# __in DWORD dwFlagsAndAttributes, +# __in_opt HANDLE hTemplateFile +# ); +def CreateFileA(lpFileName, dwDesiredAccess = GENERIC_ALL, dwShareMode = 0, lpSecurityAttributes = None, dwCreationDisposition = OPEN_ALWAYS, dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, hTemplateFile = None): + _CreateFileA = windll.kernel32.CreateFileA + _CreateFileA.argtypes = [LPSTR, DWORD, DWORD, LPVOID, DWORD, DWORD, HANDLE] + _CreateFileA.restype = HANDLE + + if not lpFileName: + lpFileName = None + if lpSecurityAttributes: + lpSecurityAttributes = ctypes.pointer(lpSecurityAttributes) + hFile = _CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile) + if hFile == INVALID_HANDLE_VALUE: + raise ctypes.WinError() + return FileHandle(hFile) + +def CreateFileW(lpFileName, dwDesiredAccess = GENERIC_ALL, dwShareMode = 0, lpSecurityAttributes = None, dwCreationDisposition = OPEN_ALWAYS, dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, hTemplateFile = None): + _CreateFileW = windll.kernel32.CreateFileW + _CreateFileW.argtypes = [LPWSTR, DWORD, DWORD, LPVOID, DWORD, DWORD, HANDLE] + _CreateFileW.restype = HANDLE + + if not lpFileName: + lpFileName = None + if lpSecurityAttributes: + lpSecurityAttributes = ctypes.pointer(lpSecurityAttributes) + hFile = _CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile) + if hFile == INVALID_HANDLE_VALUE: + raise ctypes.WinError() + return FileHandle(hFile) + +CreateFile = GuessStringType(CreateFileA, CreateFileW) + +# BOOL WINAPI FlushFileBuffers( +# __in HANDLE hFile +# ); +def FlushFileBuffers(hFile): + _FlushFileBuffers = windll.kernel32.FlushFileBuffers + _FlushFileBuffers.argtypes = [HANDLE] + _FlushFileBuffers.restype = bool + _FlushFileBuffers.errcheck = RaiseIfZero + _FlushFileBuffers(hFile) + +# BOOL WINAPI FlushViewOfFile( +# __in LPCVOID lpBaseAddress, +# __in SIZE_T dwNumberOfBytesToFlush +# ); +def FlushViewOfFile(lpBaseAddress, dwNumberOfBytesToFlush = 0): + _FlushViewOfFile = windll.kernel32.FlushViewOfFile + _FlushViewOfFile.argtypes = [LPVOID, SIZE_T] + _FlushViewOfFile.restype = bool + _FlushViewOfFile.errcheck = RaiseIfZero + _FlushViewOfFile(lpBaseAddress, dwNumberOfBytesToFlush) + +# DWORD WINAPI SearchPath( +# __in_opt LPCTSTR lpPath, +# __in LPCTSTR lpFileName, +# __in_opt LPCTSTR lpExtension, +# __in DWORD nBufferLength, +# __out LPTSTR lpBuffer, +# __out_opt LPTSTR *lpFilePart +# ); +def SearchPathA(lpPath, lpFileName, lpExtension): + _SearchPathA = windll.kernel32.SearchPathA + _SearchPathA.argtypes = [LPSTR, LPSTR, LPSTR, DWORD, LPSTR, POINTER(LPSTR)] + _SearchPathA.restype = DWORD + _SearchPathA.errcheck = RaiseIfZero + + if not lpPath: + lpPath = None + if not lpExtension: + lpExtension = None + nBufferLength = _SearchPathA(lpPath, lpFileName, lpExtension, 0, None, None) + lpBuffer = ctypes.create_string_buffer('', nBufferLength + 1) + lpFilePart = LPSTR() + _SearchPathA(lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, byref(lpFilePart)) + lpFilePart = lpFilePart.value + lpBuffer = lpBuffer.value + if lpBuffer == '': + if GetLastError() == ERROR_SUCCESS: + raise ctypes.WinError(ERROR_FILE_NOT_FOUND) + raise ctypes.WinError() + return (lpBuffer, lpFilePart) + +def SearchPathW(lpPath, lpFileName, lpExtension): + _SearchPathW = windll.kernel32.SearchPathW + _SearchPathW.argtypes = [LPWSTR, LPWSTR, LPWSTR, DWORD, LPWSTR, POINTER(LPWSTR)] + _SearchPathW.restype = DWORD + _SearchPathW.errcheck = RaiseIfZero + + if not lpPath: + lpPath = None + if not lpExtension: + lpExtension = None + nBufferLength = _SearchPathW(lpPath, lpFileName, lpExtension, 0, None, None) + lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength + 1) + lpFilePart = LPWSTR() + _SearchPathW(lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, byref(lpFilePart)) + lpFilePart = lpFilePart.value + lpBuffer = lpBuffer.value + if lpBuffer == u'': + if GetLastError() == ERROR_SUCCESS: + raise ctypes.WinError(ERROR_FILE_NOT_FOUND) + raise ctypes.WinError() + return (lpBuffer, lpFilePart) + +SearchPath = GuessStringType(SearchPathA, SearchPathW) + +# BOOL SetSearchPathMode( +# __in DWORD Flags +# ); +def SetSearchPathMode(Flags): + _SetSearchPathMode = windll.kernel32.SetSearchPathMode + _SetSearchPathMode.argtypes = [DWORD] + _SetSearchPathMode.restype = bool + _SetSearchPathMode.errcheck = RaiseIfZero + _SetSearchPathMode(Flags) + +# BOOL WINAPI DeviceIoControl( +# __in HANDLE hDevice, +# __in DWORD dwIoControlCode, +# __in_opt LPVOID lpInBuffer, +# __in DWORD nInBufferSize, +# __out_opt LPVOID lpOutBuffer, +# __in DWORD nOutBufferSize, +# __out_opt LPDWORD lpBytesReturned, +# __inout_opt LPOVERLAPPED lpOverlapped +# ); +def DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpOverlapped): + _DeviceIoControl = windll.kernel32.DeviceIoControl + _DeviceIoControl.argtypes = [HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPOVERLAPPED] + _DeviceIoControl.restype = bool + _DeviceIoControl.errcheck = RaiseIfZero + + if not lpInBuffer: + lpInBuffer = None + if not lpOutBuffer: + lpOutBuffer = None + if lpOverlapped: + lpOverlapped = ctypes.pointer(lpOverlapped) + lpBytesReturned = DWORD(0) + _DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, byref(lpBytesReturned), lpOverlapped) + return lpBytesReturned.value + +# BOOL GetFileInformationByHandle( +# HANDLE hFile, +# LPBY_HANDLE_FILE_INFORMATION lpFileInformation +# ); +def GetFileInformationByHandle(hFile): + _GetFileInformationByHandle = windll.kernel32.GetFileInformationByHandle + _GetFileInformationByHandle.argtypes = [HANDLE, LPBY_HANDLE_FILE_INFORMATION] + _GetFileInformationByHandle.restype = bool + _GetFileInformationByHandle.errcheck = RaiseIfZero + + lpFileInformation = BY_HANDLE_FILE_INFORMATION() + _GetFileInformationByHandle(hFile, byref(lpFileInformation)) + return lpFileInformation + +# BOOL WINAPI GetFileInformationByHandleEx( +# __in HANDLE hFile, +# __in FILE_INFO_BY_HANDLE_CLASS FileInformationClass, +# __out LPVOID lpFileInformation, +# __in DWORD dwBufferSize +# ); +def GetFileInformationByHandleEx(hFile, FileInformationClass, lpFileInformation, dwBufferSize): + _GetFileInformationByHandleEx = windll.kernel32.GetFileInformationByHandleEx + _GetFileInformationByHandleEx.argtypes = [HANDLE, DWORD, LPVOID, DWORD] + _GetFileInformationByHandleEx.restype = bool + _GetFileInformationByHandleEx.errcheck = RaiseIfZero + # XXX TODO + # support each FileInformationClass so the function can allocate the + # corresponding structure for the lpFileInformation parameter + _GetFileInformationByHandleEx(hFile, FileInformationClass, byref(lpFileInformation), dwBufferSize) + +# DWORD WINAPI GetFinalPathNameByHandle( +# __in HANDLE hFile, +# __out LPTSTR lpszFilePath, +# __in DWORD cchFilePath, +# __in DWORD dwFlags +# ); +def GetFinalPathNameByHandleA(hFile, dwFlags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS): + _GetFinalPathNameByHandleA = windll.kernel32.GetFinalPathNameByHandleA + _GetFinalPathNameByHandleA.argtypes = [HANDLE, LPSTR, DWORD, DWORD] + _GetFinalPathNameByHandleA.restype = DWORD + + cchFilePath = _GetFinalPathNameByHandleA(hFile, None, 0, dwFlags) + if cchFilePath == 0: + raise ctypes.WinError() + lpszFilePath = ctypes.create_string_buffer('', cchFilePath + 1) + nCopied = _GetFinalPathNameByHandleA(hFile, lpszFilePath, cchFilePath, dwFlags) + if nCopied <= 0 or nCopied > cchFilePath: + raise ctypes.WinError() + return lpszFilePath.value + +def GetFinalPathNameByHandleW(hFile, dwFlags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS): + _GetFinalPathNameByHandleW = windll.kernel32.GetFinalPathNameByHandleW + _GetFinalPathNameByHandleW.argtypes = [HANDLE, LPWSTR, DWORD, DWORD] + _GetFinalPathNameByHandleW.restype = DWORD + + cchFilePath = _GetFinalPathNameByHandleW(hFile, None, 0, dwFlags) + if cchFilePath == 0: + raise ctypes.WinError() + lpszFilePath = ctypes.create_unicode_buffer(u'', cchFilePath + 1) + nCopied = _GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags) + if nCopied <= 0 or nCopied > cchFilePath: + raise ctypes.WinError() + return lpszFilePath.value + +GetFinalPathNameByHandle = GuessStringType(GetFinalPathNameByHandleA, GetFinalPathNameByHandleW) + +# DWORD GetFullPathName( +# LPCTSTR lpFileName, +# DWORD nBufferLength, +# LPTSTR lpBuffer, +# LPTSTR* lpFilePart +# ); +def GetFullPathNameA(lpFileName): + _GetFullPathNameA = windll.kernel32.GetFullPathNameA + _GetFullPathNameA.argtypes = [LPSTR, DWORD, LPSTR, POINTER(LPSTR)] + _GetFullPathNameA.restype = DWORD + + nBufferLength = _GetFullPathNameA(lpFileName, 0, None, None) + if nBufferLength <= 0: + raise ctypes.WinError() + lpBuffer = ctypes.create_string_buffer('', nBufferLength + 1) + lpFilePart = LPSTR() + nCopied = _GetFullPathNameA(lpFileName, nBufferLength, lpBuffer, byref(lpFilePart)) + if nCopied > nBufferLength or nCopied == 0: + raise ctypes.WinError() + return lpBuffer.value, lpFilePart.value + +def GetFullPathNameW(lpFileName): + _GetFullPathNameW = windll.kernel32.GetFullPathNameW + _GetFullPathNameW.argtypes = [LPWSTR, DWORD, LPWSTR, POINTER(LPWSTR)] + _GetFullPathNameW.restype = DWORD + + nBufferLength = _GetFullPathNameW(lpFileName, 0, None, None) + if nBufferLength <= 0: + raise ctypes.WinError() + lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength + 1) + lpFilePart = LPWSTR() + nCopied = _GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, byref(lpFilePart)) + if nCopied > nBufferLength or nCopied == 0: + raise ctypes.WinError() + return lpBuffer.value, lpFilePart.value + +GetFullPathName = GuessStringType(GetFullPathNameA, GetFullPathNameW) + +# DWORD WINAPI GetTempPath( +# __in DWORD nBufferLength, +# __out LPTSTR lpBuffer +# ); +def GetTempPathA(): + _GetTempPathA = windll.kernel32.GetTempPathA + _GetTempPathA.argtypes = [DWORD, LPSTR] + _GetTempPathA.restype = DWORD + + nBufferLength = _GetTempPathA(0, None) + if nBufferLength <= 0: + raise ctypes.WinError() + lpBuffer = ctypes.create_string_buffer('', nBufferLength) + nCopied = _GetTempPathA(nBufferLength, lpBuffer) + if nCopied > nBufferLength or nCopied == 0: + raise ctypes.WinError() + return lpBuffer.value + +def GetTempPathW(): + _GetTempPathW = windll.kernel32.GetTempPathW + _GetTempPathW.argtypes = [DWORD, LPWSTR] + _GetTempPathW.restype = DWORD + + nBufferLength = _GetTempPathW(0, None) + if nBufferLength <= 0: + raise ctypes.WinError() + lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength) + nCopied = _GetTempPathW(nBufferLength, lpBuffer) + if nCopied > nBufferLength or nCopied == 0: + raise ctypes.WinError() + return lpBuffer.value + +GetTempPath = GuessStringType(GetTempPathA, GetTempPathW) + +# UINT WINAPI GetTempFileName( +# __in LPCTSTR lpPathName, +# __in LPCTSTR lpPrefixString, +# __in UINT uUnique, +# __out LPTSTR lpTempFileName +# ); +def GetTempFileNameA(lpPathName = None, lpPrefixString = "TMP", uUnique = 0): + _GetTempFileNameA = windll.kernel32.GetTempFileNameA + _GetTempFileNameA.argtypes = [LPSTR, LPSTR, UINT, LPSTR] + _GetTempFileNameA.restype = UINT + + if lpPathName is None: + lpPathName = GetTempPathA() + lpTempFileName = ctypes.create_string_buffer('', MAX_PATH) + uUnique = _GetTempFileNameA(lpPathName, lpPrefixString, uUnique, lpTempFileName) + if uUnique == 0: + raise ctypes.WinError() + return lpTempFileName.value, uUnique + +def GetTempFileNameW(lpPathName = None, lpPrefixString = u"TMP", uUnique = 0): + _GetTempFileNameW = windll.kernel32.GetTempFileNameW + _GetTempFileNameW.argtypes = [LPWSTR, LPWSTR, UINT, LPWSTR] + _GetTempFileNameW.restype = UINT + + if lpPathName is None: + lpPathName = GetTempPathW() + lpTempFileName = ctypes.create_unicode_buffer(u'', MAX_PATH) + uUnique = _GetTempFileNameW(lpPathName, lpPrefixString, uUnique, lpTempFileName) + if uUnique == 0: + raise ctypes.WinError() + return lpTempFileName.value, uUnique + +GetTempFileName = GuessStringType(GetTempFileNameA, GetTempFileNameW) + +# DWORD WINAPI GetCurrentDirectory( +# __in DWORD nBufferLength, +# __out LPTSTR lpBuffer +# ); +def GetCurrentDirectoryA(): + _GetCurrentDirectoryA = windll.kernel32.GetCurrentDirectoryA + _GetCurrentDirectoryA.argtypes = [DWORD, LPSTR] + _GetCurrentDirectoryA.restype = DWORD + + nBufferLength = _GetCurrentDirectoryA(0, None) + if nBufferLength <= 0: + raise ctypes.WinError() + lpBuffer = ctypes.create_string_buffer('', nBufferLength) + nCopied = _GetCurrentDirectoryA(nBufferLength, lpBuffer) + if nCopied > nBufferLength or nCopied == 0: + raise ctypes.WinError() + return lpBuffer.value + +def GetCurrentDirectoryW(): + _GetCurrentDirectoryW = windll.kernel32.GetCurrentDirectoryW + _GetCurrentDirectoryW.argtypes = [DWORD, LPWSTR] + _GetCurrentDirectoryW.restype = DWORD + + nBufferLength = _GetCurrentDirectoryW(0, None) + if nBufferLength <= 0: + raise ctypes.WinError() + lpBuffer = ctypes.create_unicode_buffer(u'', nBufferLength) + nCopied = _GetCurrentDirectoryW(nBufferLength, lpBuffer) + if nCopied > nBufferLength or nCopied == 0: + raise ctypes.WinError() + return lpBuffer.value + +GetCurrentDirectory = GuessStringType(GetCurrentDirectoryA, GetCurrentDirectoryW) + +#------------------------------------------------------------------------------ +# Contrl-C handler + +# BOOL WINAPI HandlerRoutine( +# __in DWORD dwCtrlType +# ); +PHANDLER_ROUTINE = ctypes.WINFUNCTYPE(BOOL, DWORD) + +# BOOL WINAPI SetConsoleCtrlHandler( +# __in_opt PHANDLER_ROUTINE HandlerRoutine, +# __in BOOL Add +# ); +def SetConsoleCtrlHandler(HandlerRoutine = None, Add = True): + _SetConsoleCtrlHandler = windll.kernel32.SetConsoleCtrlHandler + _SetConsoleCtrlHandler.argtypes = [PHANDLER_ROUTINE, BOOL] + _SetConsoleCtrlHandler.restype = bool + _SetConsoleCtrlHandler.errcheck = RaiseIfZero + _SetConsoleCtrlHandler(HandlerRoutine, bool(Add)) + # we can't automagically transform Python functions to PHANDLER_ROUTINE + # because a) the actual pointer value is meaningful to the API + # and b) if it gets garbage collected bad things would happen + +# BOOL WINAPI GenerateConsoleCtrlEvent( +# __in DWORD dwCtrlEvent, +# __in DWORD dwProcessGroupId +# ); +def GenerateConsoleCtrlEvent(dwCtrlEvent, dwProcessGroupId): + _GenerateConsoleCtrlEvent = windll.kernel32.GenerateConsoleCtrlEvent + _GenerateConsoleCtrlEvent.argtypes = [DWORD, DWORD] + _GenerateConsoleCtrlEvent.restype = bool + _GenerateConsoleCtrlEvent.errcheck = RaiseIfZero + _GenerateConsoleCtrlEvent(dwCtrlEvent, dwProcessGroupId) + +#------------------------------------------------------------------------------ +# Synchronization API + +# XXX NOTE +# +# Instead of waiting forever, we wait for a small period of time and loop. +# This is a workaround for an unwanted behavior of psyco-accelerated code: +# you can't interrupt a blocking call using Ctrl+C, because signal processing +# is only done between C calls. +# +# Also see: bug #2793618 in Psyco project +# http://sourceforge.net/tracker/?func=detail&aid=2793618&group_id=41036&atid=429622 + +# DWORD WINAPI WaitForSingleObject( +# HANDLE hHandle, +# DWORD dwMilliseconds +# ); +def WaitForSingleObject(hHandle, dwMilliseconds = INFINITE): + _WaitForSingleObject = windll.kernel32.WaitForSingleObject + _WaitForSingleObject.argtypes = [HANDLE, DWORD] + _WaitForSingleObject.restype = DWORD + + if not dwMilliseconds and dwMilliseconds != 0: + dwMilliseconds = INFINITE + if dwMilliseconds != INFINITE: + r = _WaitForSingleObject(hHandle, dwMilliseconds) + if r == WAIT_FAILED: + raise ctypes.WinError() + else: + while 1: + r = _WaitForSingleObject(hHandle, 100) + if r == WAIT_FAILED: + raise ctypes.WinError() + if r != WAIT_TIMEOUT: + break + return r + +# DWORD WINAPI WaitForSingleObjectEx( +# HANDLE hHandle, +# DWORD dwMilliseconds, +# BOOL bAlertable +# ); +def WaitForSingleObjectEx(hHandle, dwMilliseconds = INFINITE, bAlertable = True): + _WaitForSingleObjectEx = windll.kernel32.WaitForSingleObjectEx + _WaitForSingleObjectEx.argtypes = [HANDLE, DWORD, BOOL] + _WaitForSingleObjectEx.restype = DWORD + + if not dwMilliseconds and dwMilliseconds != 0: + dwMilliseconds = INFINITE + if dwMilliseconds != INFINITE: + r = _WaitForSingleObjectEx(hHandle, dwMilliseconds, bool(bAlertable)) + if r == WAIT_FAILED: + raise ctypes.WinError() + else: + while 1: + r = _WaitForSingleObjectEx(hHandle, 100, bool(bAlertable)) + if r == WAIT_FAILED: + raise ctypes.WinError() + if r != WAIT_TIMEOUT: + break + return r + +# DWORD WINAPI WaitForMultipleObjects( +# DWORD nCount, +# const HANDLE *lpHandles, +# BOOL bWaitAll, +# DWORD dwMilliseconds +# ); +def WaitForMultipleObjects(handles, bWaitAll = False, dwMilliseconds = INFINITE): + _WaitForMultipleObjects = windll.kernel32.WaitForMultipleObjects + _WaitForMultipleObjects.argtypes = [DWORD, POINTER(HANDLE), BOOL, DWORD] + _WaitForMultipleObjects.restype = DWORD + + if not dwMilliseconds and dwMilliseconds != 0: + dwMilliseconds = INFINITE + nCount = len(handles) + lpHandlesType = HANDLE * nCount + lpHandles = lpHandlesType(*handles) + if dwMilliseconds != INFINITE: + r = _WaitForMultipleObjects(byref(lpHandles), bool(bWaitAll), dwMilliseconds) + if r == WAIT_FAILED: + raise ctypes.WinError() + else: + while 1: + r = _WaitForMultipleObjects(byref(lpHandles), bool(bWaitAll), 100) + if r == WAIT_FAILED: + raise ctypes.WinError() + if r != WAIT_TIMEOUT: + break + return r + +# DWORD WINAPI WaitForMultipleObjectsEx( +# DWORD nCount, +# const HANDLE *lpHandles, +# BOOL bWaitAll, +# DWORD dwMilliseconds, +# BOOL bAlertable +# ); +def WaitForMultipleObjectsEx(handles, bWaitAll = False, dwMilliseconds = INFINITE, bAlertable = True): + _WaitForMultipleObjectsEx = windll.kernel32.WaitForMultipleObjectsEx + _WaitForMultipleObjectsEx.argtypes = [DWORD, POINTER(HANDLE), BOOL, DWORD] + _WaitForMultipleObjectsEx.restype = DWORD + + if not dwMilliseconds and dwMilliseconds != 0: + dwMilliseconds = INFINITE + nCount = len(handles) + lpHandlesType = HANDLE * nCount + lpHandles = lpHandlesType(*handles) + if dwMilliseconds != INFINITE: + r = _WaitForMultipleObjectsEx(byref(lpHandles), bool(bWaitAll), dwMilliseconds, bool(bAlertable)) + if r == WAIT_FAILED: + raise ctypes.WinError() + else: + while 1: + r = _WaitForMultipleObjectsEx(byref(lpHandles), bool(bWaitAll), 100, bool(bAlertable)) + if r == WAIT_FAILED: + raise ctypes.WinError() + if r != WAIT_TIMEOUT: + break + return r + +# HANDLE WINAPI CreateMutex( +# _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, +# _In_ BOOL bInitialOwner, +# _In_opt_ LPCTSTR lpName +# ); +def CreateMutexA(lpMutexAttributes = None, bInitialOwner = True, lpName = None): + _CreateMutexA = windll.kernel32.CreateMutexA + _CreateMutexA.argtypes = [LPVOID, BOOL, LPSTR] + _CreateMutexA.restype = HANDLE + _CreateMutexA.errcheck = RaiseIfZero + return Handle( _CreateMutexA(lpMutexAttributes, bInitialOwner, lpName) ) + +def CreateMutexW(lpMutexAttributes = None, bInitialOwner = True, lpName = None): + _CreateMutexW = windll.kernel32.CreateMutexW + _CreateMutexW.argtypes = [LPVOID, BOOL, LPWSTR] + _CreateMutexW.restype = HANDLE + _CreateMutexW.errcheck = RaiseIfZero + return Handle( _CreateMutexW(lpMutexAttributes, bInitialOwner, lpName) ) + +CreateMutex = GuessStringType(CreateMutexA, CreateMutexW) + +# HANDLE WINAPI OpenMutex( +# _In_ DWORD dwDesiredAccess, +# _In_ BOOL bInheritHandle, +# _In_ LPCTSTR lpName +# ); +def OpenMutexA(dwDesiredAccess = MUTEX_ALL_ACCESS, bInitialOwner = True, lpName = None): + _OpenMutexA = windll.kernel32.OpenMutexA + _OpenMutexA.argtypes = [DWORD, BOOL, LPSTR] + _OpenMutexA.restype = HANDLE + _OpenMutexA.errcheck = RaiseIfZero + return Handle( _OpenMutexA(lpMutexAttributes, bInitialOwner, lpName) ) + +def OpenMutexW(dwDesiredAccess = MUTEX_ALL_ACCESS, bInitialOwner = True, lpName = None): + _OpenMutexW = windll.kernel32.OpenMutexW + _OpenMutexW.argtypes = [DWORD, BOOL, LPWSTR] + _OpenMutexW.restype = HANDLE + _OpenMutexW.errcheck = RaiseIfZero + return Handle( _OpenMutexW(lpMutexAttributes, bInitialOwner, lpName) ) + +OpenMutex = GuessStringType(OpenMutexA, OpenMutexW) + +# HANDLE WINAPI CreateEvent( +# _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, +# _In_ BOOL bManualReset, +# _In_ BOOL bInitialState, +# _In_opt_ LPCTSTR lpName +# ); +def CreateEventA(lpMutexAttributes = None, bManualReset = False, bInitialState = False, lpName = None): + _CreateEventA = windll.kernel32.CreateEventA + _CreateEventA.argtypes = [LPVOID, BOOL, BOOL, LPSTR] + _CreateEventA.restype = HANDLE + _CreateEventA.errcheck = RaiseIfZero + return Handle( _CreateEventA(lpMutexAttributes, bManualReset, bInitialState, lpName) ) + +def CreateEventW(lpMutexAttributes = None, bManualReset = False, bInitialState = False, lpName = None): + _CreateEventW = windll.kernel32.CreateEventW + _CreateEventW.argtypes = [LPVOID, BOOL, BOOL, LPWSTR] + _CreateEventW.restype = HANDLE + _CreateEventW.errcheck = RaiseIfZero + return Handle( _CreateEventW(lpMutexAttributes, bManualReset, bInitialState, lpName) ) + +CreateEvent = GuessStringType(CreateEventA, CreateEventW) + +# HANDLE WINAPI OpenEvent( +# _In_ DWORD dwDesiredAccess, +# _In_ BOOL bInheritHandle, +# _In_ LPCTSTR lpName +# ); +def OpenEventA(dwDesiredAccess = EVENT_ALL_ACCESS, bInheritHandle = False, lpName = None): + _OpenEventA = windll.kernel32.OpenEventA + _OpenEventA.argtypes = [DWORD, BOOL, LPSTR] + _OpenEventA.restype = HANDLE + _OpenEventA.errcheck = RaiseIfZero + return Handle( _OpenEventA(dwDesiredAccess, bInheritHandle, lpName) ) + +def OpenEventW(dwDesiredAccess = EVENT_ALL_ACCESS, bInheritHandle = False, lpName = None): + _OpenEventW = windll.kernel32.OpenEventW + _OpenEventW.argtypes = [DWORD, BOOL, LPWSTR] + _OpenEventW.restype = HANDLE + _OpenEventW.errcheck = RaiseIfZero + return Handle( _OpenEventW(dwDesiredAccess, bInheritHandle, lpName) ) + +OpenEvent = GuessStringType(OpenEventA, OpenEventW) + +# HANDLE WINAPI CreateSemaphore( +# _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, +# _In_ LONG lInitialCount, +# _In_ LONG lMaximumCount, +# _In_opt_ LPCTSTR lpName +# ); + +# TODO + +# HANDLE WINAPI OpenSemaphore( +# _In_ DWORD dwDesiredAccess, +# _In_ BOOL bInheritHandle, +# _In_ LPCTSTR lpName +# ); + +# TODO + +# BOOL WINAPI ReleaseMutex( +# _In_ HANDLE hMutex +# ); +def ReleaseMutex(hMutex): + _ReleaseMutex = windll.kernel32.ReleaseMutex + _ReleaseMutex.argtypes = [HANDLE] + _ReleaseMutex.restype = bool + _ReleaseMutex.errcheck = RaiseIfZero + _ReleaseMutex(hMutex) + +# BOOL WINAPI SetEvent( +# _In_ HANDLE hEvent +# ); +def SetEvent(hEvent): + _SetEvent = windll.kernel32.SetEvent + _SetEvent.argtypes = [HANDLE] + _SetEvent.restype = bool + _SetEvent.errcheck = RaiseIfZero + _SetEvent(hEvent) + +# BOOL WINAPI ResetEvent( +# _In_ HANDLE hEvent +# ); +def ResetEvent(hEvent): + _ResetEvent = windll.kernel32.ResetEvent + _ResetEvent.argtypes = [HANDLE] + _ResetEvent.restype = bool + _ResetEvent.errcheck = RaiseIfZero + _ResetEvent(hEvent) + +# BOOL WINAPI PulseEvent( +# _In_ HANDLE hEvent +# ); +def PulseEvent(hEvent): + _PulseEvent = windll.kernel32.PulseEvent + _PulseEvent.argtypes = [HANDLE] + _PulseEvent.restype = bool + _PulseEvent.errcheck = RaiseIfZero + _PulseEvent(hEvent) + +# BOOL WINAPI ReleaseSemaphore( +# _In_ HANDLE hSemaphore, +# _In_ LONG lReleaseCount, +# _Out_opt_ LPLONG lpPreviousCount +# ); + +# TODO + +#------------------------------------------------------------------------------ +# Debug API + +# BOOL WaitForDebugEvent( +# LPDEBUG_EVENT lpDebugEvent, +# DWORD dwMilliseconds +# ); +def WaitForDebugEvent(dwMilliseconds = INFINITE): + _WaitForDebugEvent = windll.kernel32.WaitForDebugEvent + _WaitForDebugEvent.argtypes = [LPDEBUG_EVENT, DWORD] + _WaitForDebugEvent.restype = DWORD + + if not dwMilliseconds and dwMilliseconds != 0: + dwMilliseconds = INFINITE + lpDebugEvent = DEBUG_EVENT() + lpDebugEvent.dwDebugEventCode = 0 + lpDebugEvent.dwProcessId = 0 + lpDebugEvent.dwThreadId = 0 + if dwMilliseconds != INFINITE: + success = _WaitForDebugEvent(byref(lpDebugEvent), dwMilliseconds) + if success == 0: + raise ctypes.WinError() + else: + # this avoids locking the Python GIL for too long + while 1: + success = _WaitForDebugEvent(byref(lpDebugEvent), 100) + if success != 0: + break + code = GetLastError() + if code not in (ERROR_SEM_TIMEOUT, WAIT_TIMEOUT): + raise ctypes.WinError(code) + return lpDebugEvent + +# BOOL ContinueDebugEvent( +# DWORD dwProcessId, +# DWORD dwThreadId, +# DWORD dwContinueStatus +# ); +def ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED): + _ContinueDebugEvent = windll.kernel32.ContinueDebugEvent + _ContinueDebugEvent.argtypes = [DWORD, DWORD, DWORD] + _ContinueDebugEvent.restype = bool + _ContinueDebugEvent.errcheck = RaiseIfZero + _ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus) + +# BOOL WINAPI FlushInstructionCache( +# __in HANDLE hProcess, +# __in LPCVOID lpBaseAddress, +# __in SIZE_T dwSize +# ); +def FlushInstructionCache(hProcess, lpBaseAddress = None, dwSize = 0): + # http://blogs.msdn.com/oldnewthing/archive/2003/12/08/55954.aspx#55958 + _FlushInstructionCache = windll.kernel32.FlushInstructionCache + _FlushInstructionCache.argtypes = [HANDLE, LPVOID, SIZE_T] + _FlushInstructionCache.restype = bool + _FlushInstructionCache.errcheck = RaiseIfZero + _FlushInstructionCache(hProcess, lpBaseAddress, dwSize) + +# BOOL DebugActiveProcess( +# DWORD dwProcessId +# ); +def DebugActiveProcess(dwProcessId): + _DebugActiveProcess = windll.kernel32.DebugActiveProcess + _DebugActiveProcess.argtypes = [DWORD] + _DebugActiveProcess.restype = bool + _DebugActiveProcess.errcheck = RaiseIfZero + _DebugActiveProcess(dwProcessId) + +# BOOL DebugActiveProcessStop( +# DWORD dwProcessId +# ); +def DebugActiveProcessStop(dwProcessId): + _DebugActiveProcessStop = windll.kernel32.DebugActiveProcessStop + _DebugActiveProcessStop.argtypes = [DWORD] + _DebugActiveProcessStop.restype = bool + _DebugActiveProcessStop.errcheck = RaiseIfZero + _DebugActiveProcessStop(dwProcessId) + +# BOOL CheckRemoteDebuggerPresent( +# HANDLE hProcess, +# PBOOL pbDebuggerPresent +# ); +def CheckRemoteDebuggerPresent(hProcess): + _CheckRemoteDebuggerPresent = windll.kernel32.CheckRemoteDebuggerPresent + _CheckRemoteDebuggerPresent.argtypes = [HANDLE, PBOOL] + _CheckRemoteDebuggerPresent.restype = bool + _CheckRemoteDebuggerPresent.errcheck = RaiseIfZero + + pbDebuggerPresent = BOOL(0) + _CheckRemoteDebuggerPresent(hProcess, byref(pbDebuggerPresent)) + return bool(pbDebuggerPresent.value) + +# BOOL DebugSetProcessKillOnExit( +# BOOL KillOnExit +# ); +def DebugSetProcessKillOnExit(KillOnExit): + _DebugSetProcessKillOnExit = windll.kernel32.DebugSetProcessKillOnExit + _DebugSetProcessKillOnExit.argtypes = [BOOL] + _DebugSetProcessKillOnExit.restype = bool + _DebugSetProcessKillOnExit.errcheck = RaiseIfZero + _DebugSetProcessKillOnExit(bool(KillOnExit)) + +# BOOL DebugBreakProcess( +# HANDLE Process +# ); +def DebugBreakProcess(hProcess): + _DebugBreakProcess = windll.kernel32.DebugBreakProcess + _DebugBreakProcess.argtypes = [HANDLE] + _DebugBreakProcess.restype = bool + _DebugBreakProcess.errcheck = RaiseIfZero + _DebugBreakProcess(hProcess) + +# void WINAPI OutputDebugString( +# __in_opt LPCTSTR lpOutputString +# ); +def OutputDebugStringA(lpOutputString): + _OutputDebugStringA = windll.kernel32.OutputDebugStringA + _OutputDebugStringA.argtypes = [LPSTR] + _OutputDebugStringA.restype = None + _OutputDebugStringA(lpOutputString) + +def OutputDebugStringW(lpOutputString): + _OutputDebugStringW = windll.kernel32.OutputDebugStringW + _OutputDebugStringW.argtypes = [LPWSTR] + _OutputDebugStringW.restype = None + _OutputDebugStringW(lpOutputString) + +OutputDebugString = GuessStringType(OutputDebugStringA, OutputDebugStringW) + +# BOOL WINAPI ReadProcessMemory( +# __in HANDLE hProcess, +# __in LPCVOID lpBaseAddress, +# __out LPVOID lpBuffer, +# __in SIZE_T nSize, +# __out SIZE_T* lpNumberOfBytesRead +# ); +def ReadProcessMemory(hProcess, lpBaseAddress, nSize): + _ReadProcessMemory = windll.kernel32.ReadProcessMemory + _ReadProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)] + _ReadProcessMemory.restype = bool + + lpBuffer = ctypes.create_string_buffer(compat.b(''), nSize) + lpNumberOfBytesRead = SIZE_T(0) + success = _ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, byref(lpNumberOfBytesRead)) + if not success and GetLastError() != ERROR_PARTIAL_COPY: + raise ctypes.WinError() + return compat.b(lpBuffer.raw)[:lpNumberOfBytesRead.value] + +# BOOL WINAPI WriteProcessMemory( +# __in HANDLE hProcess, +# __in LPCVOID lpBaseAddress, +# __in LPVOID lpBuffer, +# __in SIZE_T nSize, +# __out SIZE_T* lpNumberOfBytesWritten +# ); +def WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer): + _WriteProcessMemory = windll.kernel32.WriteProcessMemory + _WriteProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)] + _WriteProcessMemory.restype = bool + + nSize = len(lpBuffer) + lpBuffer = ctypes.create_string_buffer(lpBuffer) + lpNumberOfBytesWritten = SIZE_T(0) + success = _WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, byref(lpNumberOfBytesWritten)) + if not success and GetLastError() != ERROR_PARTIAL_COPY: + raise ctypes.WinError() + return lpNumberOfBytesWritten.value + +# LPVOID WINAPI VirtualAllocEx( +# __in HANDLE hProcess, +# __in_opt LPVOID lpAddress, +# __in SIZE_T dwSize, +# __in DWORD flAllocationType, +# __in DWORD flProtect +# ); +def VirtualAllocEx(hProcess, lpAddress = 0, dwSize = 0x1000, flAllocationType = MEM_COMMIT | MEM_RESERVE, flProtect = PAGE_EXECUTE_READWRITE): + _VirtualAllocEx = windll.kernel32.VirtualAllocEx + _VirtualAllocEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD, DWORD] + _VirtualAllocEx.restype = LPVOID + + lpAddress = _VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect) + if lpAddress == NULL: + raise ctypes.WinError() + return lpAddress + +# SIZE_T WINAPI VirtualQueryEx( +# __in HANDLE hProcess, +# __in_opt LPCVOID lpAddress, +# __out PMEMORY_BASIC_INFORMATION lpBuffer, +# __in SIZE_T dwLength +# ); +def VirtualQueryEx(hProcess, lpAddress): + _VirtualQueryEx = windll.kernel32.VirtualQueryEx + _VirtualQueryEx.argtypes = [HANDLE, LPVOID, PMEMORY_BASIC_INFORMATION, SIZE_T] + _VirtualQueryEx.restype = SIZE_T + + lpBuffer = MEMORY_BASIC_INFORMATION() + dwLength = sizeof(MEMORY_BASIC_INFORMATION) + success = _VirtualQueryEx(hProcess, lpAddress, byref(lpBuffer), dwLength) + if success == 0: + raise ctypes.WinError() + return MemoryBasicInformation(lpBuffer) + +# BOOL WINAPI VirtualProtectEx( +# __in HANDLE hProcess, +# __in LPVOID lpAddress, +# __in SIZE_T dwSize, +# __in DWORD flNewProtect, +# __out PDWORD lpflOldProtect +# ); +def VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect = PAGE_EXECUTE_READWRITE): + _VirtualProtectEx = windll.kernel32.VirtualProtectEx + _VirtualProtectEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD, PDWORD] + _VirtualProtectEx.restype = bool + _VirtualProtectEx.errcheck = RaiseIfZero + + flOldProtect = DWORD(0) + _VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, byref(flOldProtect)) + return flOldProtect.value + +# BOOL WINAPI VirtualFreeEx( +# __in HANDLE hProcess, +# __in LPVOID lpAddress, +# __in SIZE_T dwSize, +# __in DWORD dwFreeType +# ); +def VirtualFreeEx(hProcess, lpAddress, dwSize = 0, dwFreeType = MEM_RELEASE): + _VirtualFreeEx = windll.kernel32.VirtualFreeEx + _VirtualFreeEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD] + _VirtualFreeEx.restype = bool + _VirtualFreeEx.errcheck = RaiseIfZero + _VirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType) + +# HANDLE WINAPI CreateRemoteThread( +# __in HANDLE hProcess, +# __in LPSECURITY_ATTRIBUTES lpThreadAttributes, +# __in SIZE_T dwStackSize, +# __in LPTHREAD_START_ROUTINE lpStartAddress, +# __in LPVOID lpParameter, +# __in DWORD dwCreationFlags, +# __out LPDWORD lpThreadId +# ); +def CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags): + _CreateRemoteThread = windll.kernel32.CreateRemoteThread + _CreateRemoteThread.argtypes = [HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPVOID, LPVOID, DWORD, LPDWORD] + _CreateRemoteThread.restype = HANDLE + + if not lpThreadAttributes: + lpThreadAttributes = None + else: + lpThreadAttributes = byref(lpThreadAttributes) + dwThreadId = DWORD(0) + hThread = _CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, byref(dwThreadId)) + if not hThread: + raise ctypes.WinError() + return ThreadHandle(hThread), dwThreadId.value + +#------------------------------------------------------------------------------ +# Process API + +# BOOL WINAPI CreateProcess( +# __in_opt LPCTSTR lpApplicationName, +# __inout_opt LPTSTR lpCommandLine, +# __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, +# __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, +# __in BOOL bInheritHandles, +# __in DWORD dwCreationFlags, +# __in_opt LPVOID lpEnvironment, +# __in_opt LPCTSTR lpCurrentDirectory, +# __in LPSTARTUPINFO lpStartupInfo, +# __out LPPROCESS_INFORMATION lpProcessInformation +# ); +def CreateProcessA(lpApplicationName, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None): + _CreateProcessA = windll.kernel32.CreateProcessA + _CreateProcessA.argtypes = [LPSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPSTR, LPVOID, LPPROCESS_INFORMATION] + _CreateProcessA.restype = bool + _CreateProcessA.errcheck = RaiseIfZero + + if not lpApplicationName: + lpApplicationName = None + if not lpCommandLine: + lpCommandLine = None + else: + lpCommandLine = ctypes.create_string_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine))) + if not lpEnvironment: + lpEnvironment = None + else: + lpEnvironment = ctypes.create_string_buffer(lpEnvironment) + if not lpCurrentDirectory: + lpCurrentDirectory = None + if not lpProcessAttributes: + lpProcessAttributes = None + else: + lpProcessAttributes = byref(lpProcessAttributes) + if not lpThreadAttributes: + lpThreadAttributes = None + else: + lpThreadAttributes = byref(lpThreadAttributes) + if not lpStartupInfo: + lpStartupInfo = STARTUPINFO() + lpStartupInfo.cb = sizeof(STARTUPINFO) + lpStartupInfo.lpReserved = 0 + lpStartupInfo.lpDesktop = 0 + lpStartupInfo.lpTitle = 0 + lpStartupInfo.dwFlags = 0 + lpStartupInfo.cbReserved2 = 0 + lpStartupInfo.lpReserved2 = 0 + lpProcessInformation = PROCESS_INFORMATION() + lpProcessInformation.hProcess = INVALID_HANDLE_VALUE + lpProcessInformation.hThread = INVALID_HANDLE_VALUE + lpProcessInformation.dwProcessId = 0 + lpProcessInformation.dwThreadId = 0 + _CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHandles), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation)) + return ProcessInformation(lpProcessInformation) + +def CreateProcessW(lpApplicationName, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None): + _CreateProcessW = windll.kernel32.CreateProcessW + _CreateProcessW.argtypes = [LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPWSTR, LPVOID, LPPROCESS_INFORMATION] + _CreateProcessW.restype = bool + _CreateProcessW.errcheck = RaiseIfZero + + if not lpApplicationName: + lpApplicationName = None + if not lpCommandLine: + lpCommandLine = None + else: + lpCommandLine = ctypes.create_unicode_buffer(lpCommandLine, max(MAX_PATH, len(lpCommandLine))) + if not lpEnvironment: + lpEnvironment = None + else: + lpEnvironment = ctypes.create_unicode_buffer(lpEnvironment) + if not lpCurrentDirectory: + lpCurrentDirectory = None + if not lpProcessAttributes: + lpProcessAttributes = None + else: + lpProcessAttributes = byref(lpProcessAttributes) + if not lpThreadAttributes: + lpThreadAttributes = None + else: + lpThreadAttributes = byref(lpThreadAttributes) + if not lpStartupInfo: + lpStartupInfo = STARTUPINFO() + lpStartupInfo.cb = sizeof(STARTUPINFO) + lpStartupInfo.lpReserved = 0 + lpStartupInfo.lpDesktop = 0 + lpStartupInfo.lpTitle = 0 + lpStartupInfo.dwFlags = 0 + lpStartupInfo.cbReserved2 = 0 + lpStartupInfo.lpReserved2 = 0 + lpProcessInformation = PROCESS_INFORMATION() + lpProcessInformation.hProcess = INVALID_HANDLE_VALUE + lpProcessInformation.hThread = INVALID_HANDLE_VALUE + lpProcessInformation.dwProcessId = 0 + lpProcessInformation.dwThreadId = 0 + _CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bool(bInheritHandles), dwCreationFlags, lpEnvironment, lpCurrentDirectory, byref(lpStartupInfo), byref(lpProcessInformation)) + return ProcessInformation(lpProcessInformation) + +CreateProcess = GuessStringType(CreateProcessA, CreateProcessW) + +# BOOL WINAPI InitializeProcThreadAttributeList( +# __out_opt LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList, +# __in DWORD dwAttributeCount, +# __reserved DWORD dwFlags, +# __inout PSIZE_T lpSize +# ); +def InitializeProcThreadAttributeList(dwAttributeCount): + _InitializeProcThreadAttributeList = windll.kernel32.InitializeProcThreadAttributeList + _InitializeProcThreadAttributeList.argtypes = [LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T] + _InitializeProcThreadAttributeList.restype = bool + + Size = SIZE_T(0) + _InitializeProcThreadAttributeList(None, dwAttributeCount, 0, byref(Size)) + RaiseIfZero(Size.value) + AttributeList = (BYTE * Size.value)() + success = _InitializeProcThreadAttributeList(byref(AttributeList), dwAttributeCount, 0, byref(Size)) + RaiseIfZero(success) + return AttributeList + +# BOOL WINAPI UpdateProcThreadAttribute( +# __inout LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList, +# __in DWORD dwFlags, +# __in DWORD_PTR Attribute, +# __in PVOID lpValue, +# __in SIZE_T cbSize, +# __out_opt PVOID lpPreviousValue, +# __in_opt PSIZE_T lpReturnSize +# ); +def UpdateProcThreadAttribute(lpAttributeList, Attribute, Value, cbSize = None): + _UpdateProcThreadAttribute = windll.kernel32.UpdateProcThreadAttribute + _UpdateProcThreadAttribute.argtypes = [LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, PVOID, SIZE_T, PVOID, PSIZE_T] + _UpdateProcThreadAttribute.restype = bool + _UpdateProcThreadAttribute.errcheck = RaiseIfZero + + if cbSize is None: + cbSize = sizeof(Value) + _UpdateProcThreadAttribute(byref(lpAttributeList), 0, Attribute, byref(Value), cbSize, None, None) + +# VOID WINAPI DeleteProcThreadAttributeList( +# __inout LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList +# ); +def DeleteProcThreadAttributeList(lpAttributeList): + _DeleteProcThreadAttributeList = windll.kernel32.DeleteProcThreadAttributeList + _DeleteProcThreadAttributeList.restype = None + _DeleteProcThreadAttributeList(byref(lpAttributeList)) + +# HANDLE WINAPI OpenProcess( +# __in DWORD dwDesiredAccess, +# __in BOOL bInheritHandle, +# __in DWORD dwProcessId +# ); +def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId): + _OpenProcess = windll.kernel32.OpenProcess + _OpenProcess.argtypes = [DWORD, BOOL, DWORD] + _OpenProcess.restype = HANDLE + + hProcess = _OpenProcess(dwDesiredAccess, bool(bInheritHandle), dwProcessId) + if hProcess == NULL: + raise ctypes.WinError() + return ProcessHandle(hProcess, dwAccess = dwDesiredAccess) + +# HANDLE WINAPI OpenThread( +# __in DWORD dwDesiredAccess, +# __in BOOL bInheritHandle, +# __in DWORD dwThreadId +# ); +def OpenThread(dwDesiredAccess, bInheritHandle, dwThreadId): + _OpenThread = windll.kernel32.OpenThread + _OpenThread.argtypes = [DWORD, BOOL, DWORD] + _OpenThread.restype = HANDLE + + hThread = _OpenThread(dwDesiredAccess, bool(bInheritHandle), dwThreadId) + if hThread == NULL: + raise ctypes.WinError() + return ThreadHandle(hThread, dwAccess = dwDesiredAccess) + +# DWORD WINAPI SuspendThread( +# __in HANDLE hThread +# ); +def SuspendThread(hThread): + _SuspendThread = windll.kernel32.SuspendThread + _SuspendThread.argtypes = [HANDLE] + _SuspendThread.restype = DWORD + + previousCount = _SuspendThread(hThread) + if previousCount == DWORD(-1).value: + raise ctypes.WinError() + return previousCount + +# DWORD WINAPI ResumeThread( +# __in HANDLE hThread +# ); +def ResumeThread(hThread): + _ResumeThread = windll.kernel32.ResumeThread + _ResumeThread.argtypes = [HANDLE] + _ResumeThread.restype = DWORD + + previousCount = _ResumeThread(hThread) + if previousCount == DWORD(-1).value: + raise ctypes.WinError() + return previousCount + +# BOOL WINAPI TerminateThread( +# __inout HANDLE hThread, +# __in DWORD dwExitCode +# ); +def TerminateThread(hThread, dwExitCode = 0): + _TerminateThread = windll.kernel32.TerminateThread + _TerminateThread.argtypes = [HANDLE, DWORD] + _TerminateThread.restype = bool + _TerminateThread.errcheck = RaiseIfZero + _TerminateThread(hThread, dwExitCode) + +# BOOL WINAPI TerminateProcess( +# __inout HANDLE hProcess, +# __in DWORD dwExitCode +# ); +def TerminateProcess(hProcess, dwExitCode = 0): + _TerminateProcess = windll.kernel32.TerminateProcess + _TerminateProcess.argtypes = [HANDLE, DWORD] + _TerminateProcess.restype = bool + _TerminateProcess.errcheck = RaiseIfZero + _TerminateProcess(hProcess, dwExitCode) + +# DWORD WINAPI GetCurrentProcessId(void); +def GetCurrentProcessId(): + _GetCurrentProcessId = windll.kernel32.GetCurrentProcessId + _GetCurrentProcessId.argtypes = [] + _GetCurrentProcessId.restype = DWORD + return _GetCurrentProcessId() + +# DWORD WINAPI GetCurrentThreadId(void); +def GetCurrentThreadId(): + _GetCurrentThreadId = windll.kernel32.GetCurrentThreadId + _GetCurrentThreadId.argtypes = [] + _GetCurrentThreadId.restype = DWORD + return _GetCurrentThreadId() + +# DWORD WINAPI GetProcessId( +# __in HANDLE hProcess +# ); +def GetProcessId(hProcess): + _GetProcessId = windll.kernel32.GetProcessId + _GetProcessId.argtypes = [HANDLE] + _GetProcessId.restype = DWORD + _GetProcessId.errcheck = RaiseIfZero + return _GetProcessId(hProcess) + +# DWORD WINAPI GetThreadId( +# __in HANDLE hThread +# ); +def GetThreadId(hThread): + _GetThreadId = windll.kernel32._GetThreadId + _GetThreadId.argtypes = [HANDLE] + _GetThreadId.restype = DWORD + + dwThreadId = _GetThreadId(hThread) + if dwThreadId == 0: + raise ctypes.WinError() + return dwThreadId + +# DWORD WINAPI GetProcessIdOfThread( +# __in HANDLE hThread +# ); +def GetProcessIdOfThread(hThread): + _GetProcessIdOfThread = windll.kernel32.GetProcessIdOfThread + _GetProcessIdOfThread.argtypes = [HANDLE] + _GetProcessIdOfThread.restype = DWORD + + dwProcessId = _GetProcessIdOfThread(hThread) + if dwProcessId == 0: + raise ctypes.WinError() + return dwProcessId + +# BOOL WINAPI GetExitCodeProcess( +# __in HANDLE hProcess, +# __out LPDWORD lpExitCode +# ); +def GetExitCodeProcess(hProcess): + _GetExitCodeProcess = windll.kernel32.GetExitCodeProcess + _GetExitCodeProcess.argtypes = [HANDLE] + _GetExitCodeProcess.restype = bool + _GetExitCodeProcess.errcheck = RaiseIfZero + + lpExitCode = DWORD(0) + _GetExitCodeProcess(hProcess, byref(lpExitCode)) + return lpExitCode.value + +# BOOL WINAPI GetExitCodeThread( +# __in HANDLE hThread, +# __out LPDWORD lpExitCode +# ); +def GetExitCodeThread(hThread): + _GetExitCodeThread = windll.kernel32.GetExitCodeThread + _GetExitCodeThread.argtypes = [HANDLE] + _GetExitCodeThread.restype = bool + _GetExitCodeThread.errcheck = RaiseIfZero + + lpExitCode = DWORD(0) + _GetExitCodeThread(hThread, byref(lpExitCode)) + return lpExitCode.value + +# DWORD WINAPI GetProcessVersion( +# __in DWORD ProcessId +# ); +def GetProcessVersion(ProcessId): + _GetProcessVersion = windll.kernel32.GetProcessVersion + _GetProcessVersion.argtypes = [DWORD] + _GetProcessVersion.restype = DWORD + + retval = _GetProcessVersion(ProcessId) + if retval == 0: + raise ctypes.WinError() + return retval + +# DWORD WINAPI GetPriorityClass( +# __in HANDLE hProcess +# ); +def GetPriorityClass(hProcess): + _GetPriorityClass = windll.kernel32.GetPriorityClass + _GetPriorityClass.argtypes = [HANDLE] + _GetPriorityClass.restype = DWORD + + retval = _GetPriorityClass(hProcess) + if retval == 0: + raise ctypes.WinError() + return retval + +# BOOL WINAPI SetPriorityClass( +# __in HANDLE hProcess, +# __in DWORD dwPriorityClass +# ); +def SetPriorityClass(hProcess, dwPriorityClass = NORMAL_PRIORITY_CLASS): + _SetPriorityClass = windll.kernel32.SetPriorityClass + _SetPriorityClass.argtypes = [HANDLE, DWORD] + _SetPriorityClass.restype = bool + _SetPriorityClass.errcheck = RaiseIfZero + _SetPriorityClass(hProcess, dwPriorityClass) + +# BOOL WINAPI GetProcessPriorityBoost( +# __in HANDLE hProcess, +# __out PBOOL pDisablePriorityBoost +# ); +def GetProcessPriorityBoost(hProcess): + _GetProcessPriorityBoost = windll.kernel32.GetProcessPriorityBoost + _GetProcessPriorityBoost.argtypes = [HANDLE, PBOOL] + _GetProcessPriorityBoost.restype = bool + _GetProcessPriorityBoost.errcheck = RaiseIfZero + + pDisablePriorityBoost = BOOL(False) + _GetProcessPriorityBoost(hProcess, byref(pDisablePriorityBoost)) + return bool(pDisablePriorityBoost.value) + +# BOOL WINAPI SetProcessPriorityBoost( +# __in HANDLE hProcess, +# __in BOOL DisablePriorityBoost +# ); +def SetProcessPriorityBoost(hProcess, DisablePriorityBoost): + _SetProcessPriorityBoost = windll.kernel32.SetProcessPriorityBoost + _SetProcessPriorityBoost.argtypes = [HANDLE, BOOL] + _SetProcessPriorityBoost.restype = bool + _SetProcessPriorityBoost.errcheck = RaiseIfZero + _SetProcessPriorityBoost(hProcess, bool(DisablePriorityBoost)) + +# BOOL WINAPI GetProcessAffinityMask( +# __in HANDLE hProcess, +# __out PDWORD_PTR lpProcessAffinityMask, +# __out PDWORD_PTR lpSystemAffinityMask +# ); +def GetProcessAffinityMask(hProcess): + _GetProcessAffinityMask = windll.kernel32.GetProcessAffinityMask + _GetProcessAffinityMask.argtypes = [HANDLE, PDWORD_PTR, PDWORD_PTR] + _GetProcessAffinityMask.restype = bool + _GetProcessAffinityMask.errcheck = RaiseIfZero + + lpProcessAffinityMask = DWORD_PTR(0) + lpSystemAffinityMask = DWORD_PTR(0) + _GetProcessAffinityMask(hProcess, byref(lpProcessAffinityMask), byref(lpSystemAffinityMask)) + return lpProcessAffinityMask.value, lpSystemAffinityMask.value + +# BOOL WINAPI SetProcessAffinityMask( +# __in HANDLE hProcess, +# __in DWORD_PTR dwProcessAffinityMask +# ); +def SetProcessAffinityMask(hProcess, dwProcessAffinityMask): + _SetProcessAffinityMask = windll.kernel32.SetProcessAffinityMask + _SetProcessAffinityMask.argtypes = [HANDLE, DWORD_PTR] + _SetProcessAffinityMask.restype = bool + _SetProcessAffinityMask.errcheck = RaiseIfZero + _SetProcessAffinityMask(hProcess, dwProcessAffinityMask) + +#------------------------------------------------------------------------------ +# Toolhelp32 API + +# HANDLE WINAPI CreateToolhelp32Snapshot( +# __in DWORD dwFlags, +# __in DWORD th32ProcessID +# ); +def CreateToolhelp32Snapshot(dwFlags = TH32CS_SNAPALL, th32ProcessID = 0): + _CreateToolhelp32Snapshot = windll.kernel32.CreateToolhelp32Snapshot + _CreateToolhelp32Snapshot.argtypes = [DWORD, DWORD] + _CreateToolhelp32Snapshot.restype = HANDLE + + hSnapshot = _CreateToolhelp32Snapshot(dwFlags, th32ProcessID) + if hSnapshot == INVALID_HANDLE_VALUE: + raise ctypes.WinError() + return SnapshotHandle(hSnapshot) + +# BOOL WINAPI Process32First( +# __in HANDLE hSnapshot, +# __inout LPPROCESSENTRY32 lppe +# ); +def Process32First(hSnapshot): + _Process32First = windll.kernel32.Process32First + _Process32First.argtypes = [HANDLE, LPPROCESSENTRY32] + _Process32First.restype = bool + + pe = PROCESSENTRY32() + pe.dwSize = sizeof(PROCESSENTRY32) + success = _Process32First(hSnapshot, byref(pe)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return pe + +# BOOL WINAPI Process32Next( +# __in HANDLE hSnapshot, +# __out LPPROCESSENTRY32 lppe +# ); +def Process32Next(hSnapshot, pe = None): + _Process32Next = windll.kernel32.Process32Next + _Process32Next.argtypes = [HANDLE, LPPROCESSENTRY32] + _Process32Next.restype = bool + + if pe is None: + pe = PROCESSENTRY32() + pe.dwSize = sizeof(PROCESSENTRY32) + success = _Process32Next(hSnapshot, byref(pe)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return pe + +# BOOL WINAPI Thread32First( +# __in HANDLE hSnapshot, +# __inout LPTHREADENTRY32 lpte +# ); +def Thread32First(hSnapshot): + _Thread32First = windll.kernel32.Thread32First + _Thread32First.argtypes = [HANDLE, LPTHREADENTRY32] + _Thread32First.restype = bool + + te = THREADENTRY32() + te.dwSize = sizeof(THREADENTRY32) + success = _Thread32First(hSnapshot, byref(te)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return te + +# BOOL WINAPI Thread32Next( +# __in HANDLE hSnapshot, +# __out LPTHREADENTRY32 lpte +# ); +def Thread32Next(hSnapshot, te = None): + _Thread32Next = windll.kernel32.Thread32Next + _Thread32Next.argtypes = [HANDLE, LPTHREADENTRY32] + _Thread32Next.restype = bool + + if te is None: + te = THREADENTRY32() + te.dwSize = sizeof(THREADENTRY32) + success = _Thread32Next(hSnapshot, byref(te)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return te + +# BOOL WINAPI Module32First( +# __in HANDLE hSnapshot, +# __inout LPMODULEENTRY32 lpme +# ); +def Module32First(hSnapshot): + _Module32First = windll.kernel32.Module32First + _Module32First.argtypes = [HANDLE, LPMODULEENTRY32] + _Module32First.restype = bool + + me = MODULEENTRY32() + me.dwSize = sizeof(MODULEENTRY32) + success = _Module32First(hSnapshot, byref(me)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return me + +# BOOL WINAPI Module32Next( +# __in HANDLE hSnapshot, +# __out LPMODULEENTRY32 lpme +# ); +def Module32Next(hSnapshot, me = None): + _Module32Next = windll.kernel32.Module32Next + _Module32Next.argtypes = [HANDLE, LPMODULEENTRY32] + _Module32Next.restype = bool + + if me is None: + me = MODULEENTRY32() + me.dwSize = sizeof(MODULEENTRY32) + success = _Module32Next(hSnapshot, byref(me)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return me + +# BOOL WINAPI Heap32First( +# __inout LPHEAPENTRY32 lphe, +# __in DWORD th32ProcessID, +# __in ULONG_PTR th32HeapID +# ); +def Heap32First(th32ProcessID, th32HeapID): + _Heap32First = windll.kernel32.Heap32First + _Heap32First.argtypes = [LPHEAPENTRY32, DWORD, ULONG_PTR] + _Heap32First.restype = bool + + he = HEAPENTRY32() + he.dwSize = sizeof(HEAPENTRY32) + success = _Heap32First(byref(he), th32ProcessID, th32HeapID) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return he + +# BOOL WINAPI Heap32Next( +# __out LPHEAPENTRY32 lphe +# ); +def Heap32Next(he): + _Heap32Next = windll.kernel32.Heap32Next + _Heap32Next.argtypes = [LPHEAPENTRY32] + _Heap32Next.restype = bool + + he.dwSize = sizeof(HEAPENTRY32) + success = _Heap32Next(byref(he)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return he + +# BOOL WINAPI Heap32ListFirst( +# __in HANDLE hSnapshot, +# __inout LPHEAPLIST32 lphl +# ); +def Heap32ListFirst(hSnapshot): + _Heap32ListFirst = windll.kernel32.Heap32ListFirst + _Heap32ListFirst.argtypes = [HANDLE, LPHEAPLIST32] + _Heap32ListFirst.restype = bool + + hl = HEAPLIST32() + hl.dwSize = sizeof(HEAPLIST32) + success = _Heap32ListFirst(hSnapshot, byref(hl)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return hl + +# BOOL WINAPI Heap32ListNext( +# __in HANDLE hSnapshot, +# __out LPHEAPLIST32 lphl +# ); +def Heap32ListNext(hSnapshot, hl = None): + _Heap32ListNext = windll.kernel32.Heap32ListNext + _Heap32ListNext.argtypes = [HANDLE, LPHEAPLIST32] + _Heap32ListNext.restype = bool + + if hl is None: + hl = HEAPLIST32() + hl.dwSize = sizeof(HEAPLIST32) + success = _Heap32ListNext(hSnapshot, byref(hl)) + if not success: + if GetLastError() == ERROR_NO_MORE_FILES: + return None + raise ctypes.WinError() + return hl + +# BOOL WINAPI Toolhelp32ReadProcessMemory( +# __in DWORD th32ProcessID, +# __in LPCVOID lpBaseAddress, +# __out LPVOID lpBuffer, +# __in SIZE_T cbRead, +# __out SIZE_T lpNumberOfBytesRead +# ); +def Toolhelp32ReadProcessMemory(th32ProcessID, lpBaseAddress, cbRead): + _Toolhelp32ReadProcessMemory = windll.kernel32.Toolhelp32ReadProcessMemory + _Toolhelp32ReadProcessMemory.argtypes = [DWORD, LPVOID, LPVOID, SIZE_T, POINTER(SIZE_T)] + _Toolhelp32ReadProcessMemory.restype = bool + + lpBuffer = ctypes.create_string_buffer('', cbRead) + lpNumberOfBytesRead = SIZE_T(0) + success = _Toolhelp32ReadProcessMemory(th32ProcessID, lpBaseAddress, lpBuffer, cbRead, byref(lpNumberOfBytesRead)) + if not success and GetLastError() != ERROR_PARTIAL_COPY: + raise ctypes.WinError() + return str(lpBuffer.raw)[:lpNumberOfBytesRead.value] + +#------------------------------------------------------------------------------ +# Miscellaneous system information + +# BOOL WINAPI GetProcessDEPPolicy( +# __in HANDLE hProcess, +# __out LPDWORD lpFlags, +# __out PBOOL lpPermanent +# ); +# Contribution by ivanlef0u (http://ivanlef0u.fr/) +# XP SP3 and > only +def GetProcessDEPPolicy(hProcess): + _GetProcessDEPPolicy = windll.kernel32.GetProcessDEPPolicy + _GetProcessDEPPolicy.argtypes = [HANDLE, LPDWORD, PBOOL] + _GetProcessDEPPolicy.restype = bool + _GetProcessDEPPolicy.errcheck = RaiseIfZero + + lpFlags = DWORD(0) + lpPermanent = BOOL(0) + _GetProcessDEPPolicy(hProcess, byref(lpFlags), byref(lpPermanent)) + return (lpFlags.value, lpPermanent.value) + +# DWORD WINAPI GetCurrentProcessorNumber(void); +def GetCurrentProcessorNumber(): + _GetCurrentProcessorNumber = windll.kernel32.GetCurrentProcessorNumber + _GetCurrentProcessorNumber.argtypes = [] + _GetCurrentProcessorNumber.restype = DWORD + _GetCurrentProcessorNumber.errcheck = RaiseIfZero + return _GetCurrentProcessorNumber() + +# VOID WINAPI FlushProcessWriteBuffers(void); +def FlushProcessWriteBuffers(): + _FlushProcessWriteBuffers = windll.kernel32.FlushProcessWriteBuffers + _FlushProcessWriteBuffers.argtypes = [] + _FlushProcessWriteBuffers.restype = None + _FlushProcessWriteBuffers() + +# BOOL WINAPI GetLogicalProcessorInformation( +# __out PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, +# __inout PDWORD ReturnLength +# ); + +# TO DO http://msdn.microsoft.com/en-us/library/ms683194(VS.85).aspx + +# BOOL WINAPI GetProcessIoCounters( +# __in HANDLE hProcess, +# __out PIO_COUNTERS lpIoCounters +# ); + +# TO DO http://msdn.microsoft.com/en-us/library/ms683218(VS.85).aspx + +# DWORD WINAPI GetGuiResources( +# __in HANDLE hProcess, +# __in DWORD uiFlags +# ); +def GetGuiResources(hProcess, uiFlags = GR_GDIOBJECTS): + _GetGuiResources = windll.kernel32.GetGuiResources + _GetGuiResources.argtypes = [HANDLE, DWORD] + _GetGuiResources.restype = DWORD + + dwCount = _GetGuiResources(hProcess, uiFlags) + if dwCount == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return dwCount + +# BOOL WINAPI GetProcessHandleCount( +# __in HANDLE hProcess, +# __inout PDWORD pdwHandleCount +# ); +def GetProcessHandleCount(hProcess): + _GetProcessHandleCount = windll.kernel32.GetProcessHandleCount + _GetProcessHandleCount.argtypes = [HANDLE, PDWORD] + _GetProcessHandleCount.restype = DWORD + _GetProcessHandleCount.errcheck = RaiseIfZero + + pdwHandleCount = DWORD(0) + _GetProcessHandleCount(hProcess, byref(pdwHandleCount)) + return pdwHandleCount.value + +# BOOL WINAPI GetProcessTimes( +# __in HANDLE hProcess, +# __out LPFILETIME lpCreationTime, +# __out LPFILETIME lpExitTime, +# __out LPFILETIME lpKernelTime, +# __out LPFILETIME lpUserTime +# ); +def GetProcessTimes(hProcess = None): + _GetProcessTimes = windll.kernel32.GetProcessTimes + _GetProcessTimes.argtypes = [HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME] + _GetProcessTimes.restype = bool + _GetProcessTimes.errcheck = RaiseIfZero + + if hProcess is None: + hProcess = GetCurrentProcess() + + CreationTime = FILETIME() + ExitTime = FILETIME() + KernelTime = FILETIME() + UserTime = FILETIME() + + _GetProcessTimes(hProcess, byref(CreationTime), byref(ExitTime), byref(KernelTime), byref(UserTime)) + + return (CreationTime, ExitTime, KernelTime, UserTime) + +# BOOL WINAPI FileTimeToSystemTime( +# __in const FILETIME *lpFileTime, +# __out LPSYSTEMTIME lpSystemTime +# ); +def FileTimeToSystemTime(lpFileTime): + _FileTimeToSystemTime = windll.kernel32.FileTimeToSystemTime + _FileTimeToSystemTime.argtypes = [LPFILETIME, LPSYSTEMTIME] + _FileTimeToSystemTime.restype = bool + _FileTimeToSystemTime.errcheck = RaiseIfZero + + if isinstance(lpFileTime, FILETIME): + FileTime = lpFileTime + else: + FileTime = FILETIME() + FileTime.dwLowDateTime = lpFileTime & 0xFFFFFFFF + FileTime.dwHighDateTime = lpFileTime >> 32 + SystemTime = SYSTEMTIME() + _FileTimeToSystemTime(byref(FileTime), byref(SystemTime)) + return SystemTime + +# void WINAPI GetSystemTimeAsFileTime( +# __out LPFILETIME lpSystemTimeAsFileTime +# ); +def GetSystemTimeAsFileTime(): + _GetSystemTimeAsFileTime = windll.kernel32.GetSystemTimeAsFileTime + _GetSystemTimeAsFileTime.argtypes = [LPFILETIME] + _GetSystemTimeAsFileTime.restype = None + + FileTime = FILETIME() + _GetSystemTimeAsFileTime(byref(FileTime)) + return FileTime + +#------------------------------------------------------------------------------ +# Global ATOM API + +# ATOM GlobalAddAtom( +# __in LPCTSTR lpString +# ); +def GlobalAddAtomA(lpString): + _GlobalAddAtomA = windll.kernel32.GlobalAddAtomA + _GlobalAddAtomA.argtypes = [LPSTR] + _GlobalAddAtomA.restype = ATOM + _GlobalAddAtomA.errcheck = RaiseIfZero + return _GlobalAddAtomA(lpString) + +def GlobalAddAtomW(lpString): + _GlobalAddAtomW = windll.kernel32.GlobalAddAtomW + _GlobalAddAtomW.argtypes = [LPWSTR] + _GlobalAddAtomW.restype = ATOM + _GlobalAddAtomW.errcheck = RaiseIfZero + return _GlobalAddAtomW(lpString) + +GlobalAddAtom = GuessStringType(GlobalAddAtomA, GlobalAddAtomW) + +# ATOM GlobalFindAtom( +# __in LPCTSTR lpString +# ); +def GlobalFindAtomA(lpString): + _GlobalFindAtomA = windll.kernel32.GlobalFindAtomA + _GlobalFindAtomA.argtypes = [LPSTR] + _GlobalFindAtomA.restype = ATOM + _GlobalFindAtomA.errcheck = RaiseIfZero + return _GlobalFindAtomA(lpString) + +def GlobalFindAtomW(lpString): + _GlobalFindAtomW = windll.kernel32.GlobalFindAtomW + _GlobalFindAtomW.argtypes = [LPWSTR] + _GlobalFindAtomW.restype = ATOM + _GlobalFindAtomW.errcheck = RaiseIfZero + return _GlobalFindAtomW(lpString) + +GlobalFindAtom = GuessStringType(GlobalFindAtomA, GlobalFindAtomW) + +# UINT GlobalGetAtomName( +# __in ATOM nAtom, +# __out LPTSTR lpBuffer, +# __in int nSize +# ); +def GlobalGetAtomNameA(nAtom): + _GlobalGetAtomNameA = windll.kernel32.GlobalGetAtomNameA + _GlobalGetAtomNameA.argtypes = [ATOM, LPSTR, ctypes.c_int] + _GlobalGetAtomNameA.restype = UINT + _GlobalGetAtomNameA.errcheck = RaiseIfZero + + nSize = 64 + while 1: + lpBuffer = ctypes.create_string_buffer("", nSize) + nCopied = _GlobalGetAtomNameA(nAtom, lpBuffer, nSize) + if nCopied < nSize - 1: + break + nSize = nSize + 64 + return lpBuffer.value + +def GlobalGetAtomNameW(nAtom): + _GlobalGetAtomNameW = windll.kernel32.GlobalGetAtomNameW + _GlobalGetAtomNameW.argtypes = [ATOM, LPWSTR, ctypes.c_int] + _GlobalGetAtomNameW.restype = UINT + _GlobalGetAtomNameW.errcheck = RaiseIfZero + + nSize = 64 + while 1: + lpBuffer = ctypes.create_unicode_buffer(u"", nSize) + nCopied = _GlobalGetAtomNameW(nAtom, lpBuffer, nSize) + if nCopied < nSize - 1: + break + nSize = nSize + 64 + return lpBuffer.value + +GlobalGetAtomName = GuessStringType(GlobalGetAtomNameA, GlobalGetAtomNameW) + +# ATOM GlobalDeleteAtom( +# __in ATOM nAtom +# ); +def GlobalDeleteAtom(nAtom): + _GlobalDeleteAtom = windll.kernel32.GlobalDeleteAtom + _GlobalDeleteAtom.argtypes + _GlobalDeleteAtom.restype + SetLastError(ERROR_SUCCESS) + _GlobalDeleteAtom(nAtom) + error = GetLastError() + if error != ERROR_SUCCESS: + raise ctypes.WinError(error) + +#------------------------------------------------------------------------------ +# Wow64 + +# DWORD WINAPI Wow64SuspendThread( +# _In_ HANDLE hThread +# ); +def Wow64SuspendThread(hThread): + _Wow64SuspendThread = windll.kernel32.Wow64SuspendThread + _Wow64SuspendThread.argtypes = [HANDLE] + _Wow64SuspendThread.restype = DWORD + + previousCount = _Wow64SuspendThread(hThread) + if previousCount == DWORD(-1).value: + raise ctypes.WinError() + return previousCount + +# BOOLEAN WINAPI Wow64EnableWow64FsRedirection( +# __in BOOLEAN Wow64FsEnableRedirection +# ); +def Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection): + """ + This function may not work reliably when there are nested calls. Therefore, + this function has been replaced by the L{Wow64DisableWow64FsRedirection} + and L{Wow64RevertWow64FsRedirection} functions. + + @see: U{http://msdn.microsoft.com/en-us/library/windows/desktop/aa365744(v=vs.85).aspx} + """ + _Wow64EnableWow64FsRedirection = windll.kernel32.Wow64EnableWow64FsRedirection + _Wow64EnableWow64FsRedirection.argtypes = [BOOLEAN] + _Wow64EnableWow64FsRedirection.restype = BOOLEAN + _Wow64EnableWow64FsRedirection.errcheck = RaiseIfZero + +# BOOL WINAPI Wow64DisableWow64FsRedirection( +# __out PVOID *OldValue +# ); +def Wow64DisableWow64FsRedirection(): + _Wow64DisableWow64FsRedirection = windll.kernel32.Wow64DisableWow64FsRedirection + _Wow64DisableWow64FsRedirection.argtypes = [PPVOID] + _Wow64DisableWow64FsRedirection.restype = BOOL + _Wow64DisableWow64FsRedirection.errcheck = RaiseIfZero + + OldValue = PVOID(None) + _Wow64DisableWow64FsRedirection(byref(OldValue)) + return OldValue + +# BOOL WINAPI Wow64RevertWow64FsRedirection( +# __in PVOID OldValue +# ); +def Wow64RevertWow64FsRedirection(OldValue): + _Wow64RevertWow64FsRedirection = windll.kernel32.Wow64RevertWow64FsRedirection + _Wow64RevertWow64FsRedirection.argtypes = [PVOID] + _Wow64RevertWow64FsRedirection.restype = BOOL + _Wow64RevertWow64FsRedirection.errcheck = RaiseIfZero + _Wow64RevertWow64FsRedirection(OldValue) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== + +#============================================================================== +# Mark functions that Psyco cannot compile. +# In your programs, don't use psyco.full(). +# Call psyco.bind() on your main function instead. + +try: + import psyco + psyco.cannotcompile(WaitForDebugEvent) + psyco.cannotcompile(WaitForSingleObject) + psyco.cannotcompile(WaitForSingleObjectEx) + psyco.cannotcompile(WaitForMultipleObjects) + psyco.cannotcompile(WaitForMultipleObjectsEx) +except ImportError: + pass +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/ntdll.py b/pydevd_attach_to_process/winappdbg/win32/ntdll.py new file mode 100644 index 0000000..3903766 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/ntdll.py @@ -0,0 +1,539 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for ntdll.dll in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +_all.add('peb_teb') +#============================================================================== + +from winappdbg.win32.peb_teb import * + +#--- Types -------------------------------------------------------------------- + +SYSDBG_COMMAND = DWORD +PROCESSINFOCLASS = DWORD +THREADINFOCLASS = DWORD +FILE_INFORMATION_CLASS = DWORD + +#--- Constants ---------------------------------------------------------------- + +# DEP flags for ProcessExecuteFlags +MEM_EXECUTE_OPTION_ENABLE = 1 +MEM_EXECUTE_OPTION_DISABLE = 2 +MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4 +MEM_EXECUTE_OPTION_PERMANENT = 8 + +# SYSTEM_INFORMATION_CLASS +# http://www.informit.com/articles/article.aspx?p=22442&seqNum=4 +SystemBasicInformation = 1 # 0x002C +SystemProcessorInformation = 2 # 0x000C +SystemPerformanceInformation = 3 # 0x0138 +SystemTimeInformation = 4 # 0x0020 +SystemPathInformation = 5 # not implemented +SystemProcessInformation = 6 # 0x00F8 + per process +SystemCallInformation = 7 # 0x0018 + (n * 0x0004) +SystemConfigurationInformation = 8 # 0x0018 +SystemProcessorCounters = 9 # 0x0030 per cpu +SystemGlobalFlag = 10 # 0x0004 +SystemInfo10 = 11 # not implemented +SystemModuleInformation = 12 # 0x0004 + (n * 0x011C) +SystemLockInformation = 13 # 0x0004 + (n * 0x0024) +SystemInfo13 = 14 # not implemented +SystemPagedPoolInformation = 15 # checked build only +SystemNonPagedPoolInformation = 16 # checked build only +SystemHandleInformation = 17 # 0x0004 + (n * 0x0010) +SystemObjectInformation = 18 # 0x0038+ + (n * 0x0030+) +SystemPagefileInformation = 19 # 0x0018+ per page file +SystemInstemulInformation = 20 # 0x0088 +SystemInfo20 = 21 # invalid info class +SystemCacheInformation = 22 # 0x0024 +SystemPoolTagInformation = 23 # 0x0004 + (n * 0x001C) +SystemProcessorStatistics = 24 # 0x0000, or 0x0018 per cpu +SystemDpcInformation = 25 # 0x0014 +SystemMemoryUsageInformation1 = 26 # checked build only +SystemLoadImage = 27 # 0x0018, set mode only +SystemUnloadImage = 28 # 0x0004, set mode only +SystemTimeAdjustmentInformation = 29 # 0x000C, 0x0008 writeable +SystemMemoryUsageInformation2 = 30 # checked build only +SystemInfo30 = 31 # checked build only +SystemInfo31 = 32 # checked build only +SystemCrashDumpInformation = 33 # 0x0004 +SystemExceptionInformation = 34 # 0x0010 +SystemCrashDumpStateInformation = 35 # 0x0008 +SystemDebuggerInformation = 36 # 0x0002 +SystemThreadSwitchInformation = 37 # 0x0030 +SystemRegistryQuotaInformation = 38 # 0x000C +SystemLoadDriver = 39 # 0x0008, set mode only +SystemPrioritySeparationInformation = 40 # 0x0004, set mode only +SystemInfo40 = 41 # not implemented +SystemInfo41 = 42 # not implemented +SystemInfo42 = 43 # invalid info class +SystemInfo43 = 44 # invalid info class +SystemTimeZoneInformation = 45 # 0x00AC +SystemLookasideInformation = 46 # n * 0x0020 +# info classes specific to Windows 2000 +# WTS = Windows Terminal Server +SystemSetTimeSlipEvent = 47 # set mode only +SystemCreateSession = 48 # WTS, set mode only +SystemDeleteSession = 49 # WTS, set mode only +SystemInfo49 = 50 # invalid info class +SystemRangeStartInformation = 51 # 0x0004 +SystemVerifierInformation = 52 # 0x0068 +SystemAddVerifier = 53 # set mode only +SystemSessionProcessesInformation = 54 # WTS + +# NtQueryInformationProcess constants (from MSDN) +##ProcessBasicInformation = 0 +##ProcessDebugPort = 7 +##ProcessWow64Information = 26 +##ProcessImageFileName = 27 + +# PROCESS_INFORMATION_CLASS +# http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Process/PROCESS_INFORMATION_CLASS.html +ProcessBasicInformation = 0 +ProcessQuotaLimits = 1 +ProcessIoCounters = 2 +ProcessVmCounters = 3 +ProcessTimes = 4 +ProcessBasePriority = 5 +ProcessRaisePriority = 6 +ProcessDebugPort = 7 +ProcessExceptionPort = 8 +ProcessAccessToken = 9 +ProcessLdtInformation = 10 +ProcessLdtSize = 11 +ProcessDefaultHardErrorMode = 12 +ProcessIoPortHandlers = 13 +ProcessPooledUsageAndLimits = 14 +ProcessWorkingSetWatch = 15 +ProcessUserModeIOPL = 16 +ProcessEnableAlignmentFaultFixup = 17 +ProcessPriorityClass = 18 +ProcessWx86Information = 19 +ProcessHandleCount = 20 +ProcessAffinityMask = 21 +ProcessPriorityBoost = 22 + +ProcessWow64Information = 26 +ProcessImageFileName = 27 + +# http://www.codeproject.com/KB/security/AntiReverseEngineering.aspx +ProcessDebugObjectHandle = 30 + +ProcessExecuteFlags = 34 + +# THREAD_INFORMATION_CLASS +ThreadBasicInformation = 0 +ThreadTimes = 1 +ThreadPriority = 2 +ThreadBasePriority = 3 +ThreadAffinityMask = 4 +ThreadImpersonationToken = 5 +ThreadDescriptorTableEntry = 6 +ThreadEnableAlignmentFaultFixup = 7 +ThreadEventPair = 8 +ThreadQuerySetWin32StartAddress = 9 +ThreadZeroTlsCell = 10 +ThreadPerformanceCount = 11 +ThreadAmILastThread = 12 +ThreadIdealProcessor = 13 +ThreadPriorityBoost = 14 +ThreadSetTlsArrayAddress = 15 +ThreadIsIoPending = 16 +ThreadHideFromDebugger = 17 + +# OBJECT_INFORMATION_CLASS +ObjectBasicInformation = 0 +ObjectNameInformation = 1 +ObjectTypeInformation = 2 +ObjectAllTypesInformation = 3 +ObjectHandleInformation = 4 + +# FILE_INFORMATION_CLASS +FileDirectoryInformation = 1 +FileFullDirectoryInformation = 2 +FileBothDirectoryInformation = 3 +FileBasicInformation = 4 +FileStandardInformation = 5 +FileInternalInformation = 6 +FileEaInformation = 7 +FileAccessInformation = 8 +FileNameInformation = 9 +FileRenameInformation = 10 +FileLinkInformation = 11 +FileNamesInformation = 12 +FileDispositionInformation = 13 +FilePositionInformation = 14 +FileFullEaInformation = 15 +FileModeInformation = 16 +FileAlignmentInformation = 17 +FileAllInformation = 18 +FileAllocationInformation = 19 +FileEndOfFileInformation = 20 +FileAlternateNameInformation = 21 +FileStreamInformation = 22 +FilePipeInformation = 23 +FilePipeLocalInformation = 24 +FilePipeRemoteInformation = 25 +FileMailslotQueryInformation = 26 +FileMailslotSetInformation = 27 +FileCompressionInformation = 28 +FileCopyOnWriteInformation = 29 +FileCompletionInformation = 30 +FileMoveClusterInformation = 31 +FileQuotaInformation = 32 +FileReparsePointInformation = 33 +FileNetworkOpenInformation = 34 +FileObjectIdInformation = 35 +FileTrackingInformation = 36 +FileOleDirectoryInformation = 37 +FileContentIndexInformation = 38 +FileInheritContentIndexInformation = 37 +FileOleInformation = 39 +FileMaximumInformation = 40 + +# From http://www.nirsoft.net/kernel_struct/vista/EXCEPTION_DISPOSITION.html +# typedef enum _EXCEPTION_DISPOSITION +# { +# ExceptionContinueExecution = 0, +# ExceptionContinueSearch = 1, +# ExceptionNestedException = 2, +# ExceptionCollidedUnwind = 3 +# } EXCEPTION_DISPOSITION; +ExceptionContinueExecution = 0 +ExceptionContinueSearch = 1 +ExceptionNestedException = 2 +ExceptionCollidedUnwind = 3 + +#--- PROCESS_BASIC_INFORMATION structure -------------------------------------- + +# From MSDN: +# +# typedef struct _PROCESS_BASIC_INFORMATION { +# PVOID Reserved1; +# PPEB PebBaseAddress; +# PVOID Reserved2[2]; +# ULONG_PTR UniqueProcessId; +# PVOID Reserved3; +# } PROCESS_BASIC_INFORMATION; +##class PROCESS_BASIC_INFORMATION(Structure): +## _fields_ = [ +## ("Reserved1", PVOID), +## ("PebBaseAddress", PPEB), +## ("Reserved2", PVOID * 2), +## ("UniqueProcessId", ULONG_PTR), +## ("Reserved3", PVOID), +##] + +# From http://catch22.net/tuts/tips2 +# (Only valid for 32 bits) +# +# typedef struct +# { +# ULONG ExitStatus; +# PVOID PebBaseAddress; +# ULONG AffinityMask; +# ULONG BasePriority; +# ULONG_PTR UniqueProcessId; +# ULONG_PTR InheritedFromUniqueProcessId; +# } PROCESS_BASIC_INFORMATION; + +# My own definition follows: +class PROCESS_BASIC_INFORMATION(Structure): + _fields_ = [ + ("ExitStatus", SIZE_T), + ("PebBaseAddress", PVOID), # PPEB + ("AffinityMask", KAFFINITY), + ("BasePriority", SDWORD), + ("UniqueProcessId", ULONG_PTR), + ("InheritedFromUniqueProcessId", ULONG_PTR), +] + +#--- THREAD_BASIC_INFORMATION structure --------------------------------------- + +# From http://undocumented.ntinternals.net/UserMode/Structures/THREAD_BASIC_INFORMATION.html +# +# typedef struct _THREAD_BASIC_INFORMATION { +# NTSTATUS ExitStatus; +# PVOID TebBaseAddress; +# CLIENT_ID ClientId; +# KAFFINITY AffinityMask; +# KPRIORITY Priority; +# KPRIORITY BasePriority; +# } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; +class THREAD_BASIC_INFORMATION(Structure): + _fields_ = [ + ("ExitStatus", NTSTATUS), + ("TebBaseAddress", PVOID), # PTEB + ("ClientId", CLIENT_ID), + ("AffinityMask", KAFFINITY), + ("Priority", SDWORD), + ("BasePriority", SDWORD), +] + +#--- FILE_NAME_INFORMATION structure ------------------------------------------ + +# typedef struct _FILE_NAME_INFORMATION { +# ULONG FileNameLength; +# WCHAR FileName[1]; +# } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; +class FILE_NAME_INFORMATION(Structure): + _fields_ = [ + ("FileNameLength", ULONG), + ("FileName", WCHAR * 1), + ] + +#--- SYSDBG_MSR structure and constants --------------------------------------- + +SysDbgReadMsr = 16 +SysDbgWriteMsr = 17 + +class SYSDBG_MSR(Structure): + _fields_ = [ + ("Address", ULONG), + ("Data", ULONGLONG), +] + +#--- IO_STATUS_BLOCK structure ------------------------------------------------ + +# typedef struct _IO_STATUS_BLOCK { +# union { +# NTSTATUS Status; +# PVOID Pointer; +# }; +# ULONG_PTR Information; +# } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; +class IO_STATUS_BLOCK(Structure): + _fields_ = [ + ("Status", NTSTATUS), + ("Information", ULONG_PTR), + ] + def __get_Pointer(self): + return PVOID(self.Status) + def __set_Pointer(self, ptr): + self.Status = ptr.value + Pointer = property(__get_Pointer, __set_Pointer) + +PIO_STATUS_BLOCK = POINTER(IO_STATUS_BLOCK) + +#--- ntdll.dll ---------------------------------------------------------------- + +# ULONG WINAPI RtlNtStatusToDosError( +# __in NTSTATUS Status +# ); +def RtlNtStatusToDosError(Status): + _RtlNtStatusToDosError = windll.ntdll.RtlNtStatusToDosError + _RtlNtStatusToDosError.argtypes = [NTSTATUS] + _RtlNtStatusToDosError.restype = ULONG + return _RtlNtStatusToDosError(Status) + +# NTSYSAPI NTSTATUS NTAPI NtSystemDebugControl( +# IN SYSDBG_COMMAND Command, +# IN PVOID InputBuffer OPTIONAL, +# IN ULONG InputBufferLength, +# OUT PVOID OutputBuffer OPTIONAL, +# IN ULONG OutputBufferLength, +# OUT PULONG ReturnLength OPTIONAL +# ); +def NtSystemDebugControl(Command, InputBuffer = None, InputBufferLength = None, OutputBuffer = None, OutputBufferLength = None): + _NtSystemDebugControl = windll.ntdll.NtSystemDebugControl + _NtSystemDebugControl.argtypes = [SYSDBG_COMMAND, PVOID, ULONG, PVOID, ULONG, PULONG] + _NtSystemDebugControl.restype = NTSTATUS + + # Validate the input buffer + if InputBuffer is None: + if InputBufferLength is None: + InputBufferLength = 0 + else: + raise ValueError( + "Invalid call to NtSystemDebugControl: " + "input buffer length given but no input buffer!") + else: + if InputBufferLength is None: + InputBufferLength = sizeof(InputBuffer) + InputBuffer = byref(InputBuffer) + + # Validate the output buffer + if OutputBuffer is None: + if OutputBufferLength is None: + OutputBufferLength = 0 + else: + OutputBuffer = ctypes.create_string_buffer("", OutputBufferLength) + elif OutputBufferLength is None: + OutputBufferLength = sizeof(OutputBuffer) + + # Make the call (with an output buffer) + if OutputBuffer is not None: + ReturnLength = ULONG(0) + ntstatus = _NtSystemDebugControl(Command, InputBuffer, InputBufferLength, byref(OutputBuffer), OutputBufferLength, byref(ReturnLength)) + if ntstatus != 0: + raise ctypes.WinError( RtlNtStatusToDosError(ntstatus) ) + ReturnLength = ReturnLength.value + if ReturnLength != OutputBufferLength: + raise ctypes.WinError(ERROR_BAD_LENGTH) + return OutputBuffer, ReturnLength + + # Make the call (without an output buffer) + ntstatus = _NtSystemDebugControl(Command, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, None) + if ntstatus != 0: + raise ctypes.WinError( RtlNtStatusToDosError(ntstatus) ) + +ZwSystemDebugControl = NtSystemDebugControl + +# NTSTATUS WINAPI NtQueryInformationProcess( +# __in HANDLE ProcessHandle, +# __in PROCESSINFOCLASS ProcessInformationClass, +# __out PVOID ProcessInformation, +# __in ULONG ProcessInformationLength, +# __out_opt PULONG ReturnLength +# ); +def NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformationLength = None): + _NtQueryInformationProcess = windll.ntdll.NtQueryInformationProcess + _NtQueryInformationProcess.argtypes = [HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG] + _NtQueryInformationProcess.restype = NTSTATUS + if ProcessInformationLength is not None: + ProcessInformation = ctypes.create_string_buffer("", ProcessInformationLength) + else: + if ProcessInformationClass == ProcessBasicInformation: + ProcessInformation = PROCESS_BASIC_INFORMATION() + ProcessInformationLength = sizeof(PROCESS_BASIC_INFORMATION) + elif ProcessInformationClass == ProcessImageFileName: + unicode_buffer = ctypes.create_unicode_buffer(u"", 0x1000) + ProcessInformation = UNICODE_STRING(0, 0x1000, addressof(unicode_buffer)) + ProcessInformationLength = sizeof(UNICODE_STRING) + elif ProcessInformationClass in (ProcessDebugPort, ProcessWow64Information, ProcessWx86Information, ProcessHandleCount, ProcessPriorityBoost): + ProcessInformation = DWORD() + ProcessInformationLength = sizeof(DWORD) + else: + raise Exception("Unknown ProcessInformationClass, use an explicit ProcessInformationLength value instead") + ReturnLength = ULONG(0) + ntstatus = _NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, byref(ProcessInformation), ProcessInformationLength, byref(ReturnLength)) + if ntstatus != 0: + raise ctypes.WinError( RtlNtStatusToDosError(ntstatus) ) + if ProcessInformationClass == ProcessBasicInformation: + retval = ProcessInformation + elif ProcessInformationClass in (ProcessDebugPort, ProcessWow64Information, ProcessWx86Information, ProcessHandleCount, ProcessPriorityBoost): + retval = ProcessInformation.value + elif ProcessInformationClass == ProcessImageFileName: + vptr = ctypes.c_void_p(ProcessInformation.Buffer) + cptr = ctypes.cast( vptr, ctypes.c_wchar * ProcessInformation.Length ) + retval = cptr.contents.raw + else: + retval = ProcessInformation.raw[:ReturnLength.value] + return retval + +ZwQueryInformationProcess = NtQueryInformationProcess + +# NTSTATUS WINAPI NtQueryInformationThread( +# __in HANDLE ThreadHandle, +# __in THREADINFOCLASS ThreadInformationClass, +# __out PVOID ThreadInformation, +# __in ULONG ThreadInformationLength, +# __out_opt PULONG ReturnLength +# ); +def NtQueryInformationThread(ThreadHandle, ThreadInformationClass, ThreadInformationLength = None): + _NtQueryInformationThread = windll.ntdll.NtQueryInformationThread + _NtQueryInformationThread.argtypes = [HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG] + _NtQueryInformationThread.restype = NTSTATUS + if ThreadInformationLength is not None: + ThreadInformation = ctypes.create_string_buffer("", ThreadInformationLength) + else: + if ThreadInformationClass == ThreadBasicInformation: + ThreadInformation = THREAD_BASIC_INFORMATION() + elif ThreadInformationClass == ThreadHideFromDebugger: + ThreadInformation = BOOLEAN() + elif ThreadInformationClass == ThreadQuerySetWin32StartAddress: + ThreadInformation = PVOID() + elif ThreadInformationClass in (ThreadAmILastThread, ThreadPriorityBoost): + ThreadInformation = DWORD() + elif ThreadInformationClass == ThreadPerformanceCount: + ThreadInformation = LONGLONG() # LARGE_INTEGER + else: + raise Exception("Unknown ThreadInformationClass, use an explicit ThreadInformationLength value instead") + ThreadInformationLength = sizeof(ThreadInformation) + ReturnLength = ULONG(0) + ntstatus = _NtQueryInformationThread(ThreadHandle, ThreadInformationClass, byref(ThreadInformation), ThreadInformationLength, byref(ReturnLength)) + if ntstatus != 0: + raise ctypes.WinError( RtlNtStatusToDosError(ntstatus) ) + if ThreadInformationClass == ThreadBasicInformation: + retval = ThreadInformation + elif ThreadInformationClass == ThreadHideFromDebugger: + retval = bool(ThreadInformation.value) + elif ThreadInformationClass in (ThreadQuerySetWin32StartAddress, ThreadAmILastThread, ThreadPriorityBoost, ThreadPerformanceCount): + retval = ThreadInformation.value + else: + retval = ThreadInformation.raw[:ReturnLength.value] + return retval + +ZwQueryInformationThread = NtQueryInformationThread + +# NTSTATUS +# NtQueryInformationFile( +# IN HANDLE FileHandle, +# OUT PIO_STATUS_BLOCK IoStatusBlock, +# OUT PVOID FileInformation, +# IN ULONG Length, +# IN FILE_INFORMATION_CLASS FileInformationClass +# ); +def NtQueryInformationFile(FileHandle, FileInformationClass, FileInformation, Length): + _NtQueryInformationFile = windll.ntdll.NtQueryInformationFile + _NtQueryInformationFile.argtypes = [HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, DWORD] + _NtQueryInformationFile.restype = NTSTATUS + IoStatusBlock = IO_STATUS_BLOCK() + ntstatus = _NtQueryInformationFile(FileHandle, byref(IoStatusBlock), byref(FileInformation), Length, FileInformationClass) + if ntstatus != 0: + raise ctypes.WinError( RtlNtStatusToDosError(ntstatus) ) + return IoStatusBlock + +ZwQueryInformationFile = NtQueryInformationFile + +# DWORD STDCALL CsrGetProcessId (VOID); +def CsrGetProcessId(): + _CsrGetProcessId = windll.ntdll.CsrGetProcessId + _CsrGetProcessId.argtypes = [] + _CsrGetProcessId.restype = DWORD + return _CsrGetProcessId() + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/peb_teb.py b/pydevd_attach_to_process/winappdbg/win32/peb_teb.py new file mode 100644 index 0000000..9d101c7 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/peb_teb.py @@ -0,0 +1,3435 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +PEB and TEB structures, constants and data types. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.version import os + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- PEB and TEB structures, constants and data types ------------------------- + +# From http://www.nirsoft.net/kernel_struct/vista/CLIENT_ID.html +# +# typedef struct _CLIENT_ID +# { +# PVOID UniqueProcess; +# PVOID UniqueThread; +# } CLIENT_ID, *PCLIENT_ID; +class CLIENT_ID(Structure): + _fields_ = [ + ("UniqueProcess", PVOID), + ("UniqueThread", PVOID), +] + +# From MSDN: +# +# typedef struct _LDR_DATA_TABLE_ENTRY { +# BYTE Reserved1[2]; +# LIST_ENTRY InMemoryOrderLinks; +# PVOID Reserved2[2]; +# PVOID DllBase; +# PVOID EntryPoint; +# PVOID Reserved3; +# UNICODE_STRING FullDllName; +# BYTE Reserved4[8]; +# PVOID Reserved5[3]; +# union { +# ULONG CheckSum; +# PVOID Reserved6; +# }; +# ULONG TimeDateStamp; +# } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; +##class LDR_DATA_TABLE_ENTRY(Structure): +## _fields_ = [ +## ("Reserved1", BYTE * 2), +## ("InMemoryOrderLinks", LIST_ENTRY), +## ("Reserved2", PVOID * 2), +## ("DllBase", PVOID), +## ("EntryPoint", PVOID), +## ("Reserved3", PVOID), +## ("FullDllName", UNICODE_STRING), +## ("Reserved4", BYTE * 8), +## ("Reserved5", PVOID * 3), +## ("CheckSum", ULONG), +## ("TimeDateStamp", ULONG), +##] + +# From MSDN: +# +# typedef struct _PEB_LDR_DATA { +# BYTE Reserved1[8]; +# PVOID Reserved2[3]; +# LIST_ENTRY InMemoryOrderModuleList; +# } PEB_LDR_DATA, +# *PPEB_LDR_DATA; +##class PEB_LDR_DATA(Structure): +## _fields_ = [ +## ("Reserved1", BYTE), +## ("Reserved2", PVOID), +## ("InMemoryOrderModuleList", LIST_ENTRY), +##] + +# From http://undocumented.ntinternals.net/UserMode/Structures/RTL_USER_PROCESS_PARAMETERS.html +# typedef struct _RTL_USER_PROCESS_PARAMETERS { +# ULONG MaximumLength; +# ULONG Length; +# ULONG Flags; +# ULONG DebugFlags; +# PVOID ConsoleHandle; +# ULONG ConsoleFlags; +# HANDLE StdInputHandle; +# HANDLE StdOutputHandle; +# HANDLE StdErrorHandle; +# UNICODE_STRING CurrentDirectoryPath; +# HANDLE CurrentDirectoryHandle; +# UNICODE_STRING DllPath; +# UNICODE_STRING ImagePathName; +# UNICODE_STRING CommandLine; +# PVOID Environment; +# ULONG StartingPositionLeft; +# ULONG StartingPositionTop; +# ULONG Width; +# ULONG Height; +# ULONG CharWidth; +# ULONG CharHeight; +# ULONG ConsoleTextAttributes; +# ULONG WindowFlags; +# ULONG ShowWindowFlags; +# UNICODE_STRING WindowTitle; +# UNICODE_STRING DesktopName; +# UNICODE_STRING ShellInfo; +# UNICODE_STRING RuntimeData; +# RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; +# } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + +# kd> dt _RTL_USER_PROCESS_PARAMETERS +# ntdll!_RTL_USER_PROCESS_PARAMETERS +# +0x000 MaximumLength : Uint4B +# +0x004 Length : Uint4B +# +0x008 Flags : Uint4B +# +0x00c DebugFlags : Uint4B +# +0x010 ConsoleHandle : Ptr32 Void +# +0x014 ConsoleFlags : Uint4B +# +0x018 StandardInput : Ptr32 Void +# +0x01c StandardOutput : Ptr32 Void +# +0x020 StandardError : Ptr32 Void +# +0x024 CurrentDirectory : _CURDIR +# +0x030 DllPath : _UNICODE_STRING +# +0x038 ImagePathName : _UNICODE_STRING +# +0x040 CommandLine : _UNICODE_STRING +# +0x048 Environment : Ptr32 Void +# +0x04c StartingX : Uint4B +# +0x050 StartingY : Uint4B +# +0x054 CountX : Uint4B +# +0x058 CountY : Uint4B +# +0x05c CountCharsX : Uint4B +# +0x060 CountCharsY : Uint4B +# +0x064 FillAttribute : Uint4B +# +0x068 WindowFlags : Uint4B +# +0x06c ShowWindowFlags : Uint4B +# +0x070 WindowTitle : _UNICODE_STRING +# +0x078 DesktopInfo : _UNICODE_STRING +# +0x080 ShellInfo : _UNICODE_STRING +# +0x088 RuntimeData : _UNICODE_STRING +# +0x090 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR +# +0x290 EnvironmentSize : Uint4B +##class RTL_USER_PROCESS_PARAMETERS(Structure): +## _fields_ = [ +## ("MaximumLength", ULONG), +## ("Length", ULONG), +## ("Flags", ULONG), +## ("DebugFlags", ULONG), +## ("ConsoleHandle", PVOID), +## ("ConsoleFlags", ULONG), +## ("StandardInput", HANDLE), +## ("StandardOutput", HANDLE), +## ("StandardError", HANDLE), +## ("CurrentDirectory", CURDIR), +## ("DllPath", UNICODE_STRING), +## ("ImagePathName", UNICODE_STRING), +## ("CommandLine", UNICODE_STRING), +## ("Environment", PVOID), +## ("StartingX", ULONG), +## ("StartingY", ULONG), +## ("CountX", ULONG), +## ("CountY", ULONG), +## ("CountCharsX", ULONG), +## ("CountCharsY", ULONG), +## ("FillAttribute", ULONG), +## ("WindowFlags", ULONG), +## ("ShowWindowFlags", ULONG), +## ("WindowTitle", UNICODE_STRING), +## ("DesktopInfo", UNICODE_STRING), +## ("ShellInfo", UNICODE_STRING), +## ("RuntimeData", UNICODE_STRING), +## ("CurrentDirectores", RTL_DRIVE_LETTER_CURDIR * 32), # typo here? +## +## # Windows 2008 and Vista +## ("EnvironmentSize", ULONG), +##] +## @property +## def CurrentDirectories(self): +## return self.CurrentDirectores + +# From MSDN: +# +# typedef struct _RTL_USER_PROCESS_PARAMETERS { +# BYTE Reserved1[16]; +# PVOID Reserved2[10]; +# UNICODE_STRING ImagePathName; +# UNICODE_STRING CommandLine; +# } RTL_USER_PROCESS_PARAMETERS, +# *PRTL_USER_PROCESS_PARAMETERS; +class RTL_USER_PROCESS_PARAMETERS(Structure): + _fields_ = [ + ("Reserved1", BYTE * 16), + ("Reserved2", PVOID * 10), + ("ImagePathName", UNICODE_STRING), + ("CommandLine", UNICODE_STRING), + ("Environment", PVOID), # undocumented! + # + # XXX TODO + # This structure should be defined with all undocumented fields for + # each version of Windows, just like it's being done for PEB and TEB. + # +] + +PPS_POST_PROCESS_INIT_ROUTINE = PVOID + +#from MSDN: +# +# typedef struct _PEB { +# BYTE Reserved1[2]; +# BYTE BeingDebugged; +# BYTE Reserved2[21]; +# PPEB_LDR_DATA LoaderData; +# PRTL_USER_PROCESS_PARAMETERS ProcessParameters; +# BYTE Reserved3[520]; +# PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; +# BYTE Reserved4[136]; +# ULONG SessionId; +# } PEB; +##class PEB(Structure): +## _fields_ = [ +## ("Reserved1", BYTE * 2), +## ("BeingDebugged", BYTE), +## ("Reserved2", BYTE * 21), +## ("LoaderData", PVOID, # PPEB_LDR_DATA +## ("ProcessParameters", PVOID, # PRTL_USER_PROCESS_PARAMETERS +## ("Reserved3", BYTE * 520), +## ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), +## ("Reserved4", BYTE), +## ("SessionId", ULONG), +##] + +# from MSDN: +# +# typedef struct _TEB { +# BYTE Reserved1[1952]; +# PVOID Reserved2[412]; +# PVOID TlsSlots[64]; +# BYTE Reserved3[8]; +# PVOID Reserved4[26]; +# PVOID ReservedForOle; +# PVOID Reserved5[4]; +# PVOID TlsExpansionSlots; +# } TEB, +# *PTEB; +##class TEB(Structure): +## _fields_ = [ +## ("Reserved1", PVOID * 1952), +## ("Reserved2", PVOID * 412), +## ("TlsSlots", PVOID * 64), +## ("Reserved3", BYTE * 8), +## ("Reserved4", PVOID * 26), +## ("ReservedForOle", PVOID), +## ("Reserved5", PVOID * 4), +## ("TlsExpansionSlots", PVOID), +##] + +# from http://undocumented.ntinternals.net/UserMode/Structures/LDR_MODULE.html +# +# typedef struct _LDR_MODULE { +# LIST_ENTRY InLoadOrderModuleList; +# LIST_ENTRY InMemoryOrderModuleList; +# LIST_ENTRY InInitializationOrderModuleList; +# PVOID BaseAddress; +# PVOID EntryPoint; +# ULONG SizeOfImage; +# UNICODE_STRING FullDllName; +# UNICODE_STRING BaseDllName; +# ULONG Flags; +# SHORT LoadCount; +# SHORT TlsIndex; +# LIST_ENTRY HashTableEntry; +# ULONG TimeDateStamp; +# } LDR_MODULE, *PLDR_MODULE; +class LDR_MODULE(Structure): + _fields_ = [ + ("InLoadOrderModuleList", LIST_ENTRY), + ("InMemoryOrderModuleList", LIST_ENTRY), + ("InInitializationOrderModuleList", LIST_ENTRY), + ("BaseAddress", PVOID), + ("EntryPoint", PVOID), + ("SizeOfImage", ULONG), + ("FullDllName", UNICODE_STRING), + ("BaseDllName", UNICODE_STRING), + ("Flags", ULONG), + ("LoadCount", SHORT), + ("TlsIndex", SHORT), + ("HashTableEntry", LIST_ENTRY), + ("TimeDateStamp", ULONG), +] + +# from http://undocumented.ntinternals.net/UserMode/Structures/PEB_LDR_DATA.html +# +# typedef struct _PEB_LDR_DATA { +# ULONG Length; +# BOOLEAN Initialized; +# PVOID SsHandle; +# LIST_ENTRY InLoadOrderModuleList; +# LIST_ENTRY InMemoryOrderModuleList; +# LIST_ENTRY InInitializationOrderModuleList; +# } PEB_LDR_DATA, *PPEB_LDR_DATA; +class PEB_LDR_DATA(Structure): + _fields_ = [ + ("Length", ULONG), + ("Initialized", BOOLEAN), + ("SsHandle", PVOID), + ("InLoadOrderModuleList", LIST_ENTRY), + ("InMemoryOrderModuleList", LIST_ENTRY), + ("InInitializationOrderModuleList", LIST_ENTRY), +] + +# From http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Process/PEB_FREE_BLOCK.html +# +# typedef struct _PEB_FREE_BLOCK { +# PEB_FREE_BLOCK *Next; +# ULONG Size; +# } PEB_FREE_BLOCK, *PPEB_FREE_BLOCK; +class PEB_FREE_BLOCK(Structure): + pass + +##PPEB_FREE_BLOCK = POINTER(PEB_FREE_BLOCK) +PPEB_FREE_BLOCK = PVOID + +PEB_FREE_BLOCK._fields_ = [ + ("Next", PPEB_FREE_BLOCK), + ("Size", ULONG), +] + +# From http://undocumented.ntinternals.net/UserMode/Structures/RTL_DRIVE_LETTER_CURDIR.html +# +# typedef struct _RTL_DRIVE_LETTER_CURDIR { +# USHORT Flags; +# USHORT Length; +# ULONG TimeStamp; +# UNICODE_STRING DosPath; +# } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; +class RTL_DRIVE_LETTER_CURDIR(Structure): + _fields_ = [ + ("Flags", USHORT), + ("Length", USHORT), + ("TimeStamp", ULONG), + ("DosPath", UNICODE_STRING), +] + +# From http://www.nirsoft.net/kernel_struct/vista/CURDIR.html +# +# typedef struct _CURDIR +# { +# UNICODE_STRING DosPath; +# PVOID Handle; +# } CURDIR, *PCURDIR; +class CURDIR(Structure): + _fields_ = [ + ("DosPath", UNICODE_STRING), + ("Handle", PVOID), +] + +# From http://www.nirsoft.net/kernel_struct/vista/RTL_CRITICAL_SECTION_DEBUG.html +# +# typedef struct _RTL_CRITICAL_SECTION_DEBUG +# { +# WORD Type; +# WORD CreatorBackTraceIndex; +# PRTL_CRITICAL_SECTION CriticalSection; +# LIST_ENTRY ProcessLocksList; +# ULONG EntryCount; +# ULONG ContentionCount; +# ULONG Flags; +# WORD CreatorBackTraceIndexHigh; +# WORD SpareUSHORT; +# } RTL_CRITICAL_SECTION_DEBUG, *PRTL_CRITICAL_SECTION_DEBUG; +# +# From http://www.nirsoft.net/kernel_struct/vista/RTL_CRITICAL_SECTION.html +# +# typedef struct _RTL_CRITICAL_SECTION +# { +# PRTL_CRITICAL_SECTION_DEBUG DebugInfo; +# LONG LockCount; +# LONG RecursionCount; +# PVOID OwningThread; +# PVOID LockSemaphore; +# ULONG SpinCount; +# } RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION; +# +class RTL_CRITICAL_SECTION(Structure): + _fields_ = [ + ("DebugInfo", PVOID), # PRTL_CRITICAL_SECTION_DEBUG + ("LockCount", LONG), + ("RecursionCount", LONG), + ("OwningThread", PVOID), + ("LockSemaphore", PVOID), + ("SpinCount", ULONG), +] +class RTL_CRITICAL_SECTION_DEBUG(Structure): + _fields_ = [ + ("Type", WORD), + ("CreatorBackTraceIndex", WORD), + ("CriticalSection", PVOID), # PRTL_CRITICAL_SECTION + ("ProcessLocksList", LIST_ENTRY), + ("EntryCount", ULONG), + ("ContentionCount", ULONG), + ("Flags", ULONG), + ("CreatorBackTraceIndexHigh", WORD), + ("SpareUSHORT", WORD), +] +PRTL_CRITICAL_SECTION = POINTER(RTL_CRITICAL_SECTION) +PRTL_CRITICAL_SECTION_DEBUG = POINTER(RTL_CRITICAL_SECTION_DEBUG) + +PPEB_LDR_DATA = POINTER(PEB_LDR_DATA) +PRTL_USER_PROCESS_PARAMETERS = POINTER(RTL_USER_PROCESS_PARAMETERS) + +PPEBLOCKROUTINE = PVOID + +# BitField +ImageUsesLargePages = 1 << 0 +IsProtectedProcess = 1 << 1 +IsLegacyProcess = 1 << 2 +IsImageDynamicallyRelocated = 1 << 3 +SkipPatchingUser32Forwarders = 1 << 4 + +# CrossProcessFlags +ProcessInJob = 1 << 0 +ProcessInitializing = 1 << 1 +ProcessUsingVEH = 1 << 2 +ProcessUsingVCH = 1 << 3 +ProcessUsingFTH = 1 << 4 + +# TracingFlags +HeapTracingEnabled = 1 << 0 +CritSecTracingEnabled = 1 << 1 + +# NtGlobalFlags +FLG_VALID_BITS = 0x003FFFFF # not a flag +FLG_STOP_ON_EXCEPTION = 0x00000001 +FLG_SHOW_LDR_SNAPS = 0x00000002 +FLG_DEBUG_INITIAL_COMMAND = 0x00000004 +FLG_STOP_ON_HUNG_GUI = 0x00000008 +FLG_HEAP_ENABLE_TAIL_CHECK = 0x00000010 +FLG_HEAP_ENABLE_FREE_CHECK = 0x00000020 +FLG_HEAP_VALIDATE_PARAMETERS = 0x00000040 +FLG_HEAP_VALIDATE_ALL = 0x00000080 +FLG_POOL_ENABLE_TAIL_CHECK = 0x00000100 +FLG_POOL_ENABLE_FREE_CHECK = 0x00000200 +FLG_POOL_ENABLE_TAGGING = 0x00000400 +FLG_HEAP_ENABLE_TAGGING = 0x00000800 +FLG_USER_STACK_TRACE_DB = 0x00001000 +FLG_KERNEL_STACK_TRACE_DB = 0x00002000 +FLG_MAINTAIN_OBJECT_TYPELIST = 0x00004000 +FLG_HEAP_ENABLE_TAG_BY_DLL = 0x00008000 +FLG_IGNORE_DEBUG_PRIV = 0x00010000 +FLG_ENABLE_CSRDEBUG = 0x00020000 +FLG_ENABLE_KDEBUG_SYMBOL_LOAD = 0x00040000 +FLG_DISABLE_PAGE_KERNEL_STACKS = 0x00080000 +FLG_HEAP_ENABLE_CALL_TRACING = 0x00100000 +FLG_HEAP_DISABLE_COALESCING = 0x00200000 +FLG_ENABLE_CLOSE_EXCEPTION = 0x00400000 +FLG_ENABLE_EXCEPTION_LOGGING = 0x00800000 +FLG_ENABLE_HANDLE_TYPE_TAGGING = 0x01000000 +FLG_HEAP_PAGE_ALLOCS = 0x02000000 +FLG_DEBUG_WINLOGON = 0x04000000 +FLG_ENABLE_DBGPRINT_BUFFERING = 0x08000000 +FLG_EARLY_CRITICAL_SECTION_EVT = 0x10000000 +FLG_DISABLE_DLL_VERIFICATION = 0x80000000 + +class _PEB_NT(Structure): + _pack_ = 4 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("BitField", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), + ("FastPebLockRoutine", PVOID), # PPEBLOCKROUTINE + ("FastPebUnlockRoutine", PVOID), # PPEBLOCKROUTINE + ("EnvironmentUpdateCount", ULONG), + ("KernelCallbackTable", PVOID), # Ptr32 Ptr32 Void + ("EventLogSection", PVOID), + ("EventLog", PVOID), + ("FreeList", PVOID), # PPEB_FREE_BLOCK + ("TlsExpansionCounter", ULONG), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", ULONG * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("ReadOnlySharedMemoryHeap", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr32 Ptr32 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", ULONG), + ("NtGlobalFlag", ULONG), + ("Spare2", BYTE * 4), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", ULONG), + ("HeapSegmentCommit", ULONG), + ("HeapDeCommitTotalFreeThreshold", ULONG), + ("HeapDeCommitFreeBlockThreshold", ULONG), + ("NumberOfHeaps", ULONG), + ("MaximumNumberOfHeaps", ULONG), + ("ProcessHeaps", PVOID), # Ptr32 Ptr32 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", PVOID), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", ULONG), + ("OSMinorVersion", ULONG), + ("OSBuildNumber", ULONG), + ("OSPlatformId", ULONG), + ("ImageSubSystem", ULONG), + ("ImageSubSystemMajorVersion", ULONG), + ("ImageSubSystemMinorVersion", ULONG), + ("ImageProcessAffinityMask", ULONG), + ("GdiHandleBuffer", ULONG * 34), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", ULONG), + ("TlsExpansionBitmapBits", BYTE * 128), + ("SessionId", ULONG), + ] + +# not really, but "dt _PEB" in w2k isn't working for me :( +_PEB_2000 = _PEB_NT + +# +0x000 InheritedAddressSpace : UChar +# +0x001 ReadImageFileExecOptions : UChar +# +0x002 BeingDebugged : UChar +# +0x003 SpareBool : UChar +# +0x004 Mutant : Ptr32 Void +# +0x008 ImageBaseAddress : Ptr32 Void +# +0x00c Ldr : Ptr32 _PEB_LDR_DATA +# +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +# +0x014 SubSystemData : Ptr32 Void +# +0x018 ProcessHeap : Ptr32 Void +# +0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x020 FastPebLockRoutine : Ptr32 Void +# +0x024 FastPebUnlockRoutine : Ptr32 Void +# +0x028 EnvironmentUpdateCount : Uint4B +# +0x02c KernelCallbackTable : Ptr32 Void +# +0x030 SystemReserved : [1] Uint4B +# +0x034 AtlThunkSListPtr32 : Uint4B +# +0x038 FreeList : Ptr32 _PEB_FREE_BLOCK +# +0x03c TlsExpansionCounter : Uint4B +# +0x040 TlsBitmap : Ptr32 Void +# +0x044 TlsBitmapBits : [2] Uint4B +# +0x04c ReadOnlySharedMemoryBase : Ptr32 Void +# +0x050 ReadOnlySharedMemoryHeap : Ptr32 Void +# +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void +# +0x058 AnsiCodePageData : Ptr32 Void +# +0x05c OemCodePageData : Ptr32 Void +# +0x060 UnicodeCaseTableData : Ptr32 Void +# +0x064 NumberOfProcessors : Uint4B +# +0x068 NtGlobalFlag : Uint4B +# +0x070 CriticalSectionTimeout : _LARGE_INTEGER +# +0x078 HeapSegmentReserve : Uint4B +# +0x07c HeapSegmentCommit : Uint4B +# +0x080 HeapDeCommitTotalFreeThreshold : Uint4B +# +0x084 HeapDeCommitFreeBlockThreshold : Uint4B +# +0x088 NumberOfHeaps : Uint4B +# +0x08c MaximumNumberOfHeaps : Uint4B +# +0x090 ProcessHeaps : Ptr32 Ptr32 Void +# +0x094 GdiSharedHandleTable : Ptr32 Void +# +0x098 ProcessStarterHelper : Ptr32 Void +# +0x09c GdiDCAttributeList : Uint4B +# +0x0a0 LoaderLock : Ptr32 Void +# +0x0a4 OSMajorVersion : Uint4B +# +0x0a8 OSMinorVersion : Uint4B +# +0x0ac OSBuildNumber : Uint2B +# +0x0ae OSCSDVersion : Uint2B +# +0x0b0 OSPlatformId : Uint4B +# +0x0b4 ImageSubsystem : Uint4B +# +0x0b8 ImageSubsystemMajorVersion : Uint4B +# +0x0bc ImageSubsystemMinorVersion : Uint4B +# +0x0c0 ImageProcessAffinityMask : Uint4B +# +0x0c4 GdiHandleBuffer : [34] Uint4B +# +0x14c PostProcessInitRoutine : Ptr32 void +# +0x150 TlsExpansionBitmap : Ptr32 Void +# +0x154 TlsExpansionBitmapBits : [32] Uint4B +# +0x1d4 SessionId : Uint4B +# +0x1d8 AppCompatFlags : _ULARGE_INTEGER +# +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER +# +0x1e8 pShimData : Ptr32 Void +# +0x1ec AppCompatInfo : Ptr32 Void +# +0x1f0 CSDVersion : _UNICODE_STRING +# +0x1f8 ActivationContextData : Ptr32 Void +# +0x1fc ProcessAssemblyStorageMap : Ptr32 Void +# +0x200 SystemDefaultActivationContextData : Ptr32 Void +# +0x204 SystemAssemblyStorageMap : Ptr32 Void +# +0x208 MinimumStackCommit : Uint4B +class _PEB_XP(Structure): + _pack_ = 8 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("SpareBool", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), + ("FastPebLockRoutine", PVOID), + ("FastPebUnlockRoutine", PVOID), + ("EnvironmentUpdateCount", DWORD), + ("KernelCallbackTable", PVOID), + ("SystemReserved", DWORD), + ("AtlThunkSListPtr32", DWORD), + ("FreeList", PVOID), # PPEB_FREE_BLOCK + ("TlsExpansionCounter", DWORD), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", DWORD * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("ReadOnlySharedMemoryHeap", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr32 Ptr32 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", DWORD), + ("NtGlobalFlag", DWORD), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", DWORD), + ("HeapSegmentCommit", DWORD), + ("HeapDeCommitTotalFreeThreshold", DWORD), + ("HeapDeCommitFreeBlockThreshold", DWORD), + ("NumberOfHeaps", DWORD), + ("MaximumNumberOfHeaps", DWORD), + ("ProcessHeaps", PVOID), # Ptr32 Ptr32 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", DWORD), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", DWORD), + ("OSMinorVersion", DWORD), + ("OSBuildNumber", WORD), + ("OSCSDVersion", WORD), + ("OSPlatformId", DWORD), + ("ImageSubsystem", DWORD), + ("ImageSubsystemMajorVersion", DWORD), + ("ImageSubsystemMinorVersion", DWORD), + ("ImageProcessAffinityMask", DWORD), + ("GdiHandleBuffer", DWORD * 34), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", PVOID), + ("TlsExpansionBitmapBits", DWORD * 32), + ("SessionId", DWORD), + ("AppCompatFlags", ULONGLONG), # ULARGE_INTEGER + ("AppCompatFlagsUser", ULONGLONG), # ULARGE_INTEGER + ("pShimData", PVOID), + ("AppCompatInfo", PVOID), + ("CSDVersion", UNICODE_STRING), + ("ActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("ProcessAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("SystemDefaultActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("SystemAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("MinimumStackCommit", DWORD), + ] + +# +0x000 InheritedAddressSpace : UChar +# +0x001 ReadImageFileExecOptions : UChar +# +0x002 BeingDebugged : UChar +# +0x003 BitField : UChar +# +0x003 ImageUsesLargePages : Pos 0, 1 Bit +# +0x003 SpareBits : Pos 1, 7 Bits +# +0x008 Mutant : Ptr64 Void +# +0x010 ImageBaseAddress : Ptr64 Void +# +0x018 Ldr : Ptr64 _PEB_LDR_DATA +# +0x020 ProcessParameters : Ptr64 _RTL_USER_PROCESS_PARAMETERS +# +0x028 SubSystemData : Ptr64 Void +# +0x030 ProcessHeap : Ptr64 Void +# +0x038 FastPebLock : Ptr64 _RTL_CRITICAL_SECTION +# +0x040 AtlThunkSListPtr : Ptr64 Void +# +0x048 SparePtr2 : Ptr64 Void +# +0x050 EnvironmentUpdateCount : Uint4B +# +0x058 KernelCallbackTable : Ptr64 Void +# +0x060 SystemReserved : [1] Uint4B +# +0x064 SpareUlong : Uint4B +# +0x068 FreeList : Ptr64 _PEB_FREE_BLOCK +# +0x070 TlsExpansionCounter : Uint4B +# +0x078 TlsBitmap : Ptr64 Void +# +0x080 TlsBitmapBits : [2] Uint4B +# +0x088 ReadOnlySharedMemoryBase : Ptr64 Void +# +0x090 ReadOnlySharedMemoryHeap : Ptr64 Void +# +0x098 ReadOnlyStaticServerData : Ptr64 Ptr64 Void +# +0x0a0 AnsiCodePageData : Ptr64 Void +# +0x0a8 OemCodePageData : Ptr64 Void +# +0x0b0 UnicodeCaseTableData : Ptr64 Void +# +0x0b8 NumberOfProcessors : Uint4B +# +0x0bc NtGlobalFlag : Uint4B +# +0x0c0 CriticalSectionTimeout : _LARGE_INTEGER +# +0x0c8 HeapSegmentReserve : Uint8B +# +0x0d0 HeapSegmentCommit : Uint8B +# +0x0d8 HeapDeCommitTotalFreeThreshold : Uint8B +# +0x0e0 HeapDeCommitFreeBlockThreshold : Uint8B +# +0x0e8 NumberOfHeaps : Uint4B +# +0x0ec MaximumNumberOfHeaps : Uint4B +# +0x0f0 ProcessHeaps : Ptr64 Ptr64 Void +# +0x0f8 GdiSharedHandleTable : Ptr64 Void +# +0x100 ProcessStarterHelper : Ptr64 Void +# +0x108 GdiDCAttributeList : Uint4B +# +0x110 LoaderLock : Ptr64 _RTL_CRITICAL_SECTION +# +0x118 OSMajorVersion : Uint4B +# +0x11c OSMinorVersion : Uint4B +# +0x120 OSBuildNumber : Uint2B +# +0x122 OSCSDVersion : Uint2B +# +0x124 OSPlatformId : Uint4B +# +0x128 ImageSubsystem : Uint4B +# +0x12c ImageSubsystemMajorVersion : Uint4B +# +0x130 ImageSubsystemMinorVersion : Uint4B +# +0x138 ImageProcessAffinityMask : Uint8B +# +0x140 GdiHandleBuffer : [60] Uint4B +# +0x230 PostProcessInitRoutine : Ptr64 void +# +0x238 TlsExpansionBitmap : Ptr64 Void +# +0x240 TlsExpansionBitmapBits : [32] Uint4B +# +0x2c0 SessionId : Uint4B +# +0x2c8 AppCompatFlags : _ULARGE_INTEGER +# +0x2d0 AppCompatFlagsUser : _ULARGE_INTEGER +# +0x2d8 pShimData : Ptr64 Void +# +0x2e0 AppCompatInfo : Ptr64 Void +# +0x2e8 CSDVersion : _UNICODE_STRING +# +0x2f8 ActivationContextData : Ptr64 _ACTIVATION_CONTEXT_DATA +# +0x300 ProcessAssemblyStorageMap : Ptr64 _ASSEMBLY_STORAGE_MAP +# +0x308 SystemDefaultActivationContextData : Ptr64 _ACTIVATION_CONTEXT_DATA +# +0x310 SystemAssemblyStorageMap : Ptr64 _ASSEMBLY_STORAGE_MAP +# +0x318 MinimumStackCommit : Uint8B +# +0x320 FlsCallback : Ptr64 Ptr64 Void +# +0x328 FlsListHead : _LIST_ENTRY +# +0x338 FlsBitmap : Ptr64 Void +# +0x340 FlsBitmapBits : [4] Uint4B +# +0x350 FlsHighIndex : Uint4B +class _PEB_XP_64(Structure): + _pack_ = 8 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("BitField", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), # PRTL_CRITICAL_SECTION + ("AtlThunkSListPtr", PVOID), + ("SparePtr2", PVOID), + ("EnvironmentUpdateCount", DWORD), + ("KernelCallbackTable", PVOID), + ("SystemReserved", DWORD), + ("SpareUlong", DWORD), + ("FreeList", PVOID), # PPEB_FREE_BLOCK + ("TlsExpansionCounter", DWORD), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", DWORD * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("ReadOnlySharedMemoryHeap", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr64 Ptr64 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", DWORD), + ("NtGlobalFlag", DWORD), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", QWORD), + ("HeapSegmentCommit", QWORD), + ("HeapDeCommitTotalFreeThreshold", QWORD), + ("HeapDeCommitFreeBlockThreshold", QWORD), + ("NumberOfHeaps", DWORD), + ("MaximumNumberOfHeaps", DWORD), + ("ProcessHeaps", PVOID), # Ptr64 Ptr64 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", DWORD), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", DWORD), + ("OSMinorVersion", DWORD), + ("OSBuildNumber", WORD), + ("OSCSDVersion", WORD), + ("OSPlatformId", DWORD), + ("ImageSubsystem", DWORD), + ("ImageSubsystemMajorVersion", DWORD), + ("ImageSubsystemMinorVersion", DWORD), + ("ImageProcessAffinityMask", QWORD), + ("GdiHandleBuffer", DWORD * 60), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", PVOID), + ("TlsExpansionBitmapBits", DWORD * 32), + ("SessionId", DWORD), + ("AppCompatFlags", ULONGLONG), # ULARGE_INTEGER + ("AppCompatFlagsUser", ULONGLONG), # ULARGE_INTEGER + ("pShimData", PVOID), + ("AppCompatInfo", PVOID), + ("CSDVersion", UNICODE_STRING), + ("ActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("ProcessAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("SystemDefaultActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("SystemAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("MinimumStackCommit", QWORD), + ("FlsCallback", PVOID), # Ptr64 Ptr64 Void + ("FlsListHead", LIST_ENTRY), + ("FlsBitmap", PVOID), + ("FlsBitmapBits", DWORD * 4), + ("FlsHighIndex", DWORD), + ] + +# +0x000 InheritedAddressSpace : UChar +# +0x001 ReadImageFileExecOptions : UChar +# +0x002 BeingDebugged : UChar +# +0x003 BitField : UChar +# +0x003 ImageUsesLargePages : Pos 0, 1 Bit +# +0x003 SpareBits : Pos 1, 7 Bits +# +0x004 Mutant : Ptr32 Void +# +0x008 ImageBaseAddress : Ptr32 Void +# +0x00c Ldr : Ptr32 _PEB_LDR_DATA +# +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +# +0x014 SubSystemData : Ptr32 Void +# +0x018 ProcessHeap : Ptr32 Void +# +0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x020 AtlThunkSListPtr : Ptr32 Void +# +0x024 SparePtr2 : Ptr32 Void +# +0x028 EnvironmentUpdateCount : Uint4B +# +0x02c KernelCallbackTable : Ptr32 Void +# +0x030 SystemReserved : [1] Uint4B +# +0x034 SpareUlong : Uint4B +# +0x038 FreeList : Ptr32 _PEB_FREE_BLOCK +# +0x03c TlsExpansionCounter : Uint4B +# +0x040 TlsBitmap : Ptr32 Void +# +0x044 TlsBitmapBits : [2] Uint4B +# +0x04c ReadOnlySharedMemoryBase : Ptr32 Void +# +0x050 ReadOnlySharedMemoryHeap : Ptr32 Void +# +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void +# +0x058 AnsiCodePageData : Ptr32 Void +# +0x05c OemCodePageData : Ptr32 Void +# +0x060 UnicodeCaseTableData : Ptr32 Void +# +0x064 NumberOfProcessors : Uint4B +# +0x068 NtGlobalFlag : Uint4B +# +0x070 CriticalSectionTimeout : _LARGE_INTEGER +# +0x078 HeapSegmentReserve : Uint4B +# +0x07c HeapSegmentCommit : Uint4B +# +0x080 HeapDeCommitTotalFreeThreshold : Uint4B +# +0x084 HeapDeCommitFreeBlockThreshold : Uint4B +# +0x088 NumberOfHeaps : Uint4B +# +0x08c MaximumNumberOfHeaps : Uint4B +# +0x090 ProcessHeaps : Ptr32 Ptr32 Void +# +0x094 GdiSharedHandleTable : Ptr32 Void +# +0x098 ProcessStarterHelper : Ptr32 Void +# +0x09c GdiDCAttributeList : Uint4B +# +0x0a0 LoaderLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x0a4 OSMajorVersion : Uint4B +# +0x0a8 OSMinorVersion : Uint4B +# +0x0ac OSBuildNumber : Uint2B +# +0x0ae OSCSDVersion : Uint2B +# +0x0b0 OSPlatformId : Uint4B +# +0x0b4 ImageSubsystem : Uint4B +# +0x0b8 ImageSubsystemMajorVersion : Uint4B +# +0x0bc ImageSubsystemMinorVersion : Uint4B +# +0x0c0 ImageProcessAffinityMask : Uint4B +# +0x0c4 GdiHandleBuffer : [34] Uint4B +# +0x14c PostProcessInitRoutine : Ptr32 void +# +0x150 TlsExpansionBitmap : Ptr32 Void +# +0x154 TlsExpansionBitmapBits : [32] Uint4B +# +0x1d4 SessionId : Uint4B +# +0x1d8 AppCompatFlags : _ULARGE_INTEGER +# +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER +# +0x1e8 pShimData : Ptr32 Void +# +0x1ec AppCompatInfo : Ptr32 Void +# +0x1f0 CSDVersion : _UNICODE_STRING +# +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +# +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +# +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +# +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +# +0x208 MinimumStackCommit : Uint4B +# +0x20c FlsCallback : Ptr32 Ptr32 Void +# +0x210 FlsListHead : _LIST_ENTRY +# +0x218 FlsBitmap : Ptr32 Void +# +0x21c FlsBitmapBits : [4] Uint4B +# +0x22c FlsHighIndex : Uint4B +class _PEB_2003(Structure): + _pack_ = 8 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("BitField", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), # PRTL_CRITICAL_SECTION + ("AtlThunkSListPtr", PVOID), + ("SparePtr2", PVOID), + ("EnvironmentUpdateCount", DWORD), + ("KernelCallbackTable", PVOID), + ("SystemReserved", DWORD), + ("SpareUlong", DWORD), + ("FreeList", PVOID), # PPEB_FREE_BLOCK + ("TlsExpansionCounter", DWORD), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", DWORD * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("ReadOnlySharedMemoryHeap", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr32 Ptr32 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", DWORD), + ("NtGlobalFlag", DWORD), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", DWORD), + ("HeapSegmentCommit", DWORD), + ("HeapDeCommitTotalFreeThreshold", DWORD), + ("HeapDeCommitFreeBlockThreshold", DWORD), + ("NumberOfHeaps", DWORD), + ("MaximumNumberOfHeaps", DWORD), + ("ProcessHeaps", PVOID), # Ptr32 Ptr32 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", DWORD), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", DWORD), + ("OSMinorVersion", DWORD), + ("OSBuildNumber", WORD), + ("OSCSDVersion", WORD), + ("OSPlatformId", DWORD), + ("ImageSubsystem", DWORD), + ("ImageSubsystemMajorVersion", DWORD), + ("ImageSubsystemMinorVersion", DWORD), + ("ImageProcessAffinityMask", DWORD), + ("GdiHandleBuffer", DWORD * 34), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", PVOID), + ("TlsExpansionBitmapBits", DWORD * 32), + ("SessionId", DWORD), + ("AppCompatFlags", ULONGLONG), # ULARGE_INTEGER + ("AppCompatFlagsUser", ULONGLONG), # ULARGE_INTEGER + ("pShimData", PVOID), + ("AppCompatInfo", PVOID), + ("CSDVersion", UNICODE_STRING), + ("ActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("ProcessAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("SystemDefaultActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("SystemAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("MinimumStackCommit", QWORD), + ("FlsCallback", PVOID), # Ptr32 Ptr32 Void + ("FlsListHead", LIST_ENTRY), + ("FlsBitmap", PVOID), + ("FlsBitmapBits", DWORD * 4), + ("FlsHighIndex", DWORD), + ] + +_PEB_2003_64 = _PEB_XP_64 +_PEB_2003_R2 = _PEB_2003 +_PEB_2003_R2_64 = _PEB_2003_64 + +# +0x000 InheritedAddressSpace : UChar +# +0x001 ReadImageFileExecOptions : UChar +# +0x002 BeingDebugged : UChar +# +0x003 BitField : UChar +# +0x003 ImageUsesLargePages : Pos 0, 1 Bit +# +0x003 IsProtectedProcess : Pos 1, 1 Bit +# +0x003 IsLegacyProcess : Pos 2, 1 Bit +# +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit +# +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit +# +0x003 SpareBits : Pos 5, 3 Bits +# +0x004 Mutant : Ptr32 Void +# +0x008 ImageBaseAddress : Ptr32 Void +# +0x00c Ldr : Ptr32 _PEB_LDR_DATA +# +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +# +0x014 SubSystemData : Ptr32 Void +# +0x018 ProcessHeap : Ptr32 Void +# +0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x020 AtlThunkSListPtr : Ptr32 Void +# +0x024 IFEOKey : Ptr32 Void +# +0x028 CrossProcessFlags : Uint4B +# +0x028 ProcessInJob : Pos 0, 1 Bit +# +0x028 ProcessInitializing : Pos 1, 1 Bit +# +0x028 ProcessUsingVEH : Pos 2, 1 Bit +# +0x028 ProcessUsingVCH : Pos 3, 1 Bit +# +0x028 ReservedBits0 : Pos 4, 28 Bits +# +0x02c KernelCallbackTable : Ptr32 Void +# +0x02c UserSharedInfoPtr : Ptr32 Void +# +0x030 SystemReserved : [1] Uint4B +# +0x034 SpareUlong : Uint4B +# +0x038 SparePebPtr0 : Uint4B +# +0x03c TlsExpansionCounter : Uint4B +# +0x040 TlsBitmap : Ptr32 Void +# +0x044 TlsBitmapBits : [2] Uint4B +# +0x04c ReadOnlySharedMemoryBase : Ptr32 Void +# +0x050 HotpatchInformation : Ptr32 Void +# +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void +# +0x058 AnsiCodePageData : Ptr32 Void +# +0x05c OemCodePageData : Ptr32 Void +# +0x060 UnicodeCaseTableData : Ptr32 Void +# +0x064 NumberOfProcessors : Uint4B +# +0x068 NtGlobalFlag : Uint4B +# +0x070 CriticalSectionTimeout : _LARGE_INTEGER +# +0x078 HeapSegmentReserve : Uint4B +# +0x07c HeapSegmentCommit : Uint4B +# +0x080 HeapDeCommitTotalFreeThreshold : Uint4B +# +0x084 HeapDeCommitFreeBlockThreshold : Uint4B +# +0x088 NumberOfHeaps : Uint4B +# +0x08c MaximumNumberOfHeaps : Uint4B +# +0x090 ProcessHeaps : Ptr32 Ptr32 Void +# +0x094 GdiSharedHandleTable : Ptr32 Void +# +0x098 ProcessStarterHelper : Ptr32 Void +# +0x09c GdiDCAttributeList : Uint4B +# +0x0a0 LoaderLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x0a4 OSMajorVersion : Uint4B +# +0x0a8 OSMinorVersion : Uint4B +# +0x0ac OSBuildNumber : Uint2B +# +0x0ae OSCSDVersion : Uint2B +# +0x0b0 OSPlatformId : Uint4B +# +0x0b4 ImageSubsystem : Uint4B +# +0x0b8 ImageSubsystemMajorVersion : Uint4B +# +0x0bc ImageSubsystemMinorVersion : Uint4B +# +0x0c0 ActiveProcessAffinityMask : Uint4B +# +0x0c4 GdiHandleBuffer : [34] Uint4B +# +0x14c PostProcessInitRoutine : Ptr32 void +# +0x150 TlsExpansionBitmap : Ptr32 Void +# +0x154 TlsExpansionBitmapBits : [32] Uint4B +# +0x1d4 SessionId : Uint4B +# +0x1d8 AppCompatFlags : _ULARGE_INTEGER +# +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER +# +0x1e8 pShimData : Ptr32 Void +# +0x1ec AppCompatInfo : Ptr32 Void +# +0x1f0 CSDVersion : _UNICODE_STRING +# +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +# +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +# +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +# +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +# +0x208 MinimumStackCommit : Uint4B +# +0x20c FlsCallback : Ptr32 _FLS_CALLBACK_INFO +# +0x210 FlsListHead : _LIST_ENTRY +# +0x218 FlsBitmap : Ptr32 Void +# +0x21c FlsBitmapBits : [4] Uint4B +# +0x22c FlsHighIndex : Uint4B +# +0x230 WerRegistrationData : Ptr32 Void +# +0x234 WerShipAssertPtr : Ptr32 Void +class _PEB_2008(Structure): + _pack_ = 8 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("BitField", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), # PRTL_CRITICAL_SECTION + ("AtlThunkSListPtr", PVOID), + ("IFEOKey", PVOID), + ("CrossProcessFlags", DWORD), + ("KernelCallbackTable", PVOID), + ("SystemReserved", DWORD), + ("SpareUlong", DWORD), + ("SparePebPtr0", PVOID), + ("TlsExpansionCounter", DWORD), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", DWORD * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("HotpatchInformation", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr32 Ptr32 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", DWORD), + ("NtGlobalFlag", DWORD), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", DWORD), + ("HeapSegmentCommit", DWORD), + ("HeapDeCommitTotalFreeThreshold", DWORD), + ("HeapDeCommitFreeBlockThreshold", DWORD), + ("NumberOfHeaps", DWORD), + ("MaximumNumberOfHeaps", DWORD), + ("ProcessHeaps", PVOID), # Ptr32 Ptr32 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", DWORD), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", DWORD), + ("OSMinorVersion", DWORD), + ("OSBuildNumber", WORD), + ("OSCSDVersion", WORD), + ("OSPlatformId", DWORD), + ("ImageSubsystem", DWORD), + ("ImageSubsystemMajorVersion", DWORD), + ("ImageSubsystemMinorVersion", DWORD), + ("ActiveProcessAffinityMask", DWORD), + ("GdiHandleBuffer", DWORD * 34), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", PVOID), + ("TlsExpansionBitmapBits", DWORD * 32), + ("SessionId", DWORD), + ("AppCompatFlags", ULONGLONG), # ULARGE_INTEGER + ("AppCompatFlagsUser", ULONGLONG), # ULARGE_INTEGER + ("pShimData", PVOID), + ("AppCompatInfo", PVOID), + ("CSDVersion", UNICODE_STRING), + ("ActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("ProcessAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("SystemDefaultActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("SystemAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("MinimumStackCommit", DWORD), + ("FlsCallback", PVOID), # PFLS_CALLBACK_INFO + ("FlsListHead", LIST_ENTRY), + ("FlsBitmap", PVOID), + ("FlsBitmapBits", DWORD * 4), + ("FlsHighIndex", DWORD), + ("WerRegistrationData", PVOID), + ("WerShipAssertPtr", PVOID), + ] + def __get_UserSharedInfoPtr(self): + return self.KernelCallbackTable + def __set_UserSharedInfoPtr(self, value): + self.KernelCallbackTable = value + UserSharedInfoPtr = property(__get_UserSharedInfoPtr, __set_UserSharedInfoPtr) + +# +0x000 InheritedAddressSpace : UChar +# +0x001 ReadImageFileExecOptions : UChar +# +0x002 BeingDebugged : UChar +# +0x003 BitField : UChar +# +0x003 ImageUsesLargePages : Pos 0, 1 Bit +# +0x003 IsProtectedProcess : Pos 1, 1 Bit +# +0x003 IsLegacyProcess : Pos 2, 1 Bit +# +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit +# +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit +# +0x003 SpareBits : Pos 5, 3 Bits +# +0x008 Mutant : Ptr64 Void +# +0x010 ImageBaseAddress : Ptr64 Void +# +0x018 Ldr : Ptr64 _PEB_LDR_DATA +# +0x020 ProcessParameters : Ptr64 _RTL_USER_PROCESS_PARAMETERS +# +0x028 SubSystemData : Ptr64 Void +# +0x030 ProcessHeap : Ptr64 Void +# +0x038 FastPebLock : Ptr64 _RTL_CRITICAL_SECTION +# +0x040 AtlThunkSListPtr : Ptr64 Void +# +0x048 IFEOKey : Ptr64 Void +# +0x050 CrossProcessFlags : Uint4B +# +0x050 ProcessInJob : Pos 0, 1 Bit +# +0x050 ProcessInitializing : Pos 1, 1 Bit +# +0x050 ProcessUsingVEH : Pos 2, 1 Bit +# +0x050 ProcessUsingVCH : Pos 3, 1 Bit +# +0x050 ReservedBits0 : Pos 4, 28 Bits +# +0x058 KernelCallbackTable : Ptr64 Void +# +0x058 UserSharedInfoPtr : Ptr64 Void +# +0x060 SystemReserved : [1] Uint4B +# +0x064 SpareUlong : Uint4B +# +0x068 SparePebPtr0 : Uint8B +# +0x070 TlsExpansionCounter : Uint4B +# +0x078 TlsBitmap : Ptr64 Void +# +0x080 TlsBitmapBits : [2] Uint4B +# +0x088 ReadOnlySharedMemoryBase : Ptr64 Void +# +0x090 HotpatchInformation : Ptr64 Void +# +0x098 ReadOnlyStaticServerData : Ptr64 Ptr64 Void +# +0x0a0 AnsiCodePageData : Ptr64 Void +# +0x0a8 OemCodePageData : Ptr64 Void +# +0x0b0 UnicodeCaseTableData : Ptr64 Void +# +0x0b8 NumberOfProcessors : Uint4B +# +0x0bc NtGlobalFlag : Uint4B +# +0x0c0 CriticalSectionTimeout : _LARGE_INTEGER +# +0x0c8 HeapSegmentReserve : Uint8B +# +0x0d0 HeapSegmentCommit : Uint8B +# +0x0d8 HeapDeCommitTotalFreeThreshold : Uint8B +# +0x0e0 HeapDeCommitFreeBlockThreshold : Uint8B +# +0x0e8 NumberOfHeaps : Uint4B +# +0x0ec MaximumNumberOfHeaps : Uint4B +# +0x0f0 ProcessHeaps : Ptr64 Ptr64 Void +# +0x0f8 GdiSharedHandleTable : Ptr64 Void +# +0x100 ProcessStarterHelper : Ptr64 Void +# +0x108 GdiDCAttributeList : Uint4B +# +0x110 LoaderLock : Ptr64 _RTL_CRITICAL_SECTION +# +0x118 OSMajorVersion : Uint4B +# +0x11c OSMinorVersion : Uint4B +# +0x120 OSBuildNumber : Uint2B +# +0x122 OSCSDVersion : Uint2B +# +0x124 OSPlatformId : Uint4B +# +0x128 ImageSubsystem : Uint4B +# +0x12c ImageSubsystemMajorVersion : Uint4B +# +0x130 ImageSubsystemMinorVersion : Uint4B +# +0x138 ActiveProcessAffinityMask : Uint8B +# +0x140 GdiHandleBuffer : [60] Uint4B +# +0x230 PostProcessInitRoutine : Ptr64 void +# +0x238 TlsExpansionBitmap : Ptr64 Void +# +0x240 TlsExpansionBitmapBits : [32] Uint4B +# +0x2c0 SessionId : Uint4B +# +0x2c8 AppCompatFlags : _ULARGE_INTEGER +# +0x2d0 AppCompatFlagsUser : _ULARGE_INTEGER +# +0x2d8 pShimData : Ptr64 Void +# +0x2e0 AppCompatInfo : Ptr64 Void +# +0x2e8 CSDVersion : _UNICODE_STRING +# +0x2f8 ActivationContextData : Ptr64 _ACTIVATION_CONTEXT_DATA +# +0x300 ProcessAssemblyStorageMap : Ptr64 _ASSEMBLY_STORAGE_MAP +# +0x308 SystemDefaultActivationContextData : Ptr64 _ACTIVATION_CONTEXT_DATA +# +0x310 SystemAssemblyStorageMap : Ptr64 _ASSEMBLY_STORAGE_MAP +# +0x318 MinimumStackCommit : Uint8B +# +0x320 FlsCallback : Ptr64 _FLS_CALLBACK_INFO +# +0x328 FlsListHead : _LIST_ENTRY +# +0x338 FlsBitmap : Ptr64 Void +# +0x340 FlsBitmapBits : [4] Uint4B +# +0x350 FlsHighIndex : Uint4B +# +0x358 WerRegistrationData : Ptr64 Void +# +0x360 WerShipAssertPtr : Ptr64 Void +class _PEB_2008_64(Structure): + _pack_ = 8 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("BitField", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), # PRTL_CRITICAL_SECTION + ("AtlThunkSListPtr", PVOID), + ("IFEOKey", PVOID), + ("CrossProcessFlags", DWORD), + ("KernelCallbackTable", PVOID), + ("SystemReserved", DWORD), + ("SpareUlong", DWORD), + ("SparePebPtr0", PVOID), + ("TlsExpansionCounter", DWORD), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", DWORD * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("HotpatchInformation", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr64 Ptr64 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", DWORD), + ("NtGlobalFlag", DWORD), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", QWORD), + ("HeapSegmentCommit", QWORD), + ("HeapDeCommitTotalFreeThreshold", QWORD), + ("HeapDeCommitFreeBlockThreshold", QWORD), + ("NumberOfHeaps", DWORD), + ("MaximumNumberOfHeaps", DWORD), + ("ProcessHeaps", PVOID), # Ptr64 Ptr64 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", DWORD), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", DWORD), + ("OSMinorVersion", DWORD), + ("OSBuildNumber", WORD), + ("OSCSDVersion", WORD), + ("OSPlatformId", DWORD), + ("ImageSubsystem", DWORD), + ("ImageSubsystemMajorVersion", DWORD), + ("ImageSubsystemMinorVersion", DWORD), + ("ActiveProcessAffinityMask", QWORD), + ("GdiHandleBuffer", DWORD * 60), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", PVOID), + ("TlsExpansionBitmapBits", DWORD * 32), + ("SessionId", DWORD), + ("AppCompatFlags", ULONGLONG), # ULARGE_INTEGER + ("AppCompatFlagsUser", ULONGLONG), # ULARGE_INTEGER + ("pShimData", PVOID), + ("AppCompatInfo", PVOID), + ("CSDVersion", UNICODE_STRING), + ("ActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("ProcessAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("SystemDefaultActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("SystemAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("MinimumStackCommit", QWORD), + ("FlsCallback", PVOID), # PFLS_CALLBACK_INFO + ("FlsListHead", LIST_ENTRY), + ("FlsBitmap", PVOID), + ("FlsBitmapBits", DWORD * 4), + ("FlsHighIndex", DWORD), + ("WerRegistrationData", PVOID), + ("WerShipAssertPtr", PVOID), + ] + def __get_UserSharedInfoPtr(self): + return self.KernelCallbackTable + def __set_UserSharedInfoPtr(self, value): + self.KernelCallbackTable = value + UserSharedInfoPtr = property(__get_UserSharedInfoPtr, __set_UserSharedInfoPtr) + +# +0x000 InheritedAddressSpace : UChar +# +0x001 ReadImageFileExecOptions : UChar +# +0x002 BeingDebugged : UChar +# +0x003 BitField : UChar +# +0x003 ImageUsesLargePages : Pos 0, 1 Bit +# +0x003 IsProtectedProcess : Pos 1, 1 Bit +# +0x003 IsLegacyProcess : Pos 2, 1 Bit +# +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit +# +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit +# +0x003 SpareBits : Pos 5, 3 Bits +# +0x004 Mutant : Ptr32 Void +# +0x008 ImageBaseAddress : Ptr32 Void +# +0x00c Ldr : Ptr32 _PEB_LDR_DATA +# +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +# +0x014 SubSystemData : Ptr32 Void +# +0x018 ProcessHeap : Ptr32 Void +# +0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x020 AtlThunkSListPtr : Ptr32 Void +# +0x024 IFEOKey : Ptr32 Void +# +0x028 CrossProcessFlags : Uint4B +# +0x028 ProcessInJob : Pos 0, 1 Bit +# +0x028 ProcessInitializing : Pos 1, 1 Bit +# +0x028 ProcessUsingVEH : Pos 2, 1 Bit +# +0x028 ProcessUsingVCH : Pos 3, 1 Bit +# +0x028 ProcessUsingFTH : Pos 4, 1 Bit +# +0x028 ReservedBits0 : Pos 5, 27 Bits +# +0x02c KernelCallbackTable : Ptr32 Void +# +0x02c UserSharedInfoPtr : Ptr32 Void +# +0x030 SystemReserved : [1] Uint4B +# +0x034 AtlThunkSListPtr32 : Uint4B +# +0x038 ApiSetMap : Ptr32 Void +# +0x03c TlsExpansionCounter : Uint4B +# +0x040 TlsBitmap : Ptr32 Void +# +0x044 TlsBitmapBits : [2] Uint4B +# +0x04c ReadOnlySharedMemoryBase : Ptr32 Void +# +0x050 HotpatchInformation : Ptr32 Void +# +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void +# +0x058 AnsiCodePageData : Ptr32 Void +# +0x05c OemCodePageData : Ptr32 Void +# +0x060 UnicodeCaseTableData : Ptr32 Void +# +0x064 NumberOfProcessors : Uint4B +# +0x068 NtGlobalFlag : Uint4B +# +0x070 CriticalSectionTimeout : _LARGE_INTEGER +# +0x078 HeapSegmentReserve : Uint4B +# +0x07c HeapSegmentCommit : Uint4B +# +0x080 HeapDeCommitTotalFreeThreshold : Uint4B +# +0x084 HeapDeCommitFreeBlockThreshold : Uint4B +# +0x088 NumberOfHeaps : Uint4B +# +0x08c MaximumNumberOfHeaps : Uint4B +# +0x090 ProcessHeaps : Ptr32 Ptr32 Void +# +0x094 GdiSharedHandleTable : Ptr32 Void +# +0x098 ProcessStarterHelper : Ptr32 Void +# +0x09c GdiDCAttributeList : Uint4B +# +0x0a0 LoaderLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x0a4 OSMajorVersion : Uint4B +# +0x0a8 OSMinorVersion : Uint4B +# +0x0ac OSBuildNumber : Uint2B +# +0x0ae OSCSDVersion : Uint2B +# +0x0b0 OSPlatformId : Uint4B +# +0x0b4 ImageSubsystem : Uint4B +# +0x0b8 ImageSubsystemMajorVersion : Uint4B +# +0x0bc ImageSubsystemMinorVersion : Uint4B +# +0x0c0 ActiveProcessAffinityMask : Uint4B +# +0x0c4 GdiHandleBuffer : [34] Uint4B +# +0x14c PostProcessInitRoutine : Ptr32 void +# +0x150 TlsExpansionBitmap : Ptr32 Void +# +0x154 TlsExpansionBitmapBits : [32] Uint4B +# +0x1d4 SessionId : Uint4B +# +0x1d8 AppCompatFlags : _ULARGE_INTEGER +# +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER +# +0x1e8 pShimData : Ptr32 Void +# +0x1ec AppCompatInfo : Ptr32 Void +# +0x1f0 CSDVersion : _UNICODE_STRING +# +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +# +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +# +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +# +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +# +0x208 MinimumStackCommit : Uint4B +# +0x20c FlsCallback : Ptr32 _FLS_CALLBACK_INFO +# +0x210 FlsListHead : _LIST_ENTRY +# +0x218 FlsBitmap : Ptr32 Void +# +0x21c FlsBitmapBits : [4] Uint4B +# +0x22c FlsHighIndex : Uint4B +# +0x230 WerRegistrationData : Ptr32 Void +# +0x234 WerShipAssertPtr : Ptr32 Void +# +0x238 pContextData : Ptr32 Void +# +0x23c pImageHeaderHash : Ptr32 Void +# +0x240 TracingFlags : Uint4B +# +0x240 HeapTracingEnabled : Pos 0, 1 Bit +# +0x240 CritSecTracingEnabled : Pos 1, 1 Bit +# +0x240 SpareTracingBits : Pos 2, 30 Bits +class _PEB_2008_R2(Structure): + _pack_ = 8 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("BitField", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), # PRTL_CRITICAL_SECTION + ("AtlThunkSListPtr", PVOID), + ("IFEOKey", PVOID), + ("CrossProcessFlags", DWORD), + ("KernelCallbackTable", PVOID), + ("SystemReserved", DWORD), + ("AtlThunkSListPtr32", PVOID), + ("ApiSetMap", PVOID), + ("TlsExpansionCounter", DWORD), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", DWORD * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("HotpatchInformation", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr32 Ptr32 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", DWORD), + ("NtGlobalFlag", DWORD), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", DWORD), + ("HeapSegmentCommit", DWORD), + ("HeapDeCommitTotalFreeThreshold", DWORD), + ("HeapDeCommitFreeBlockThreshold", DWORD), + ("NumberOfHeaps", DWORD), + ("MaximumNumberOfHeaps", DWORD), + ("ProcessHeaps", PVOID), # Ptr32 Ptr32 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", DWORD), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", DWORD), + ("OSMinorVersion", DWORD), + ("OSBuildNumber", WORD), + ("OSCSDVersion", WORD), + ("OSPlatformId", DWORD), + ("ImageSubsystem", DWORD), + ("ImageSubsystemMajorVersion", DWORD), + ("ImageSubsystemMinorVersion", DWORD), + ("ActiveProcessAffinityMask", DWORD), + ("GdiHandleBuffer", DWORD * 34), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", PVOID), + ("TlsExpansionBitmapBits", DWORD * 32), + ("SessionId", DWORD), + ("AppCompatFlags", ULONGLONG), # ULARGE_INTEGER + ("AppCompatFlagsUser", ULONGLONG), # ULARGE_INTEGER + ("pShimData", PVOID), + ("AppCompatInfo", PVOID), + ("CSDVersion", UNICODE_STRING), + ("ActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("ProcessAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("SystemDefaultActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("SystemAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("MinimumStackCommit", DWORD), + ("FlsCallback", PVOID), # PFLS_CALLBACK_INFO + ("FlsListHead", LIST_ENTRY), + ("FlsBitmap", PVOID), + ("FlsBitmapBits", DWORD * 4), + ("FlsHighIndex", DWORD), + ("WerRegistrationData", PVOID), + ("WerShipAssertPtr", PVOID), + ("pContextData", PVOID), + ("pImageHeaderHash", PVOID), + ("TracingFlags", DWORD), + ] + def __get_UserSharedInfoPtr(self): + return self.KernelCallbackTable + def __set_UserSharedInfoPtr(self, value): + self.KernelCallbackTable = value + UserSharedInfoPtr = property(__get_UserSharedInfoPtr, __set_UserSharedInfoPtr) + +# +0x000 InheritedAddressSpace : UChar +# +0x001 ReadImageFileExecOptions : UChar +# +0x002 BeingDebugged : UChar +# +0x003 BitField : UChar +# +0x003 ImageUsesLargePages : Pos 0, 1 Bit +# +0x003 IsProtectedProcess : Pos 1, 1 Bit +# +0x003 IsLegacyProcess : Pos 2, 1 Bit +# +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit +# +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit +# +0x003 SpareBits : Pos 5, 3 Bits +# +0x008 Mutant : Ptr64 Void +# +0x010 ImageBaseAddress : Ptr64 Void +# +0x018 Ldr : Ptr64 _PEB_LDR_DATA +# +0x020 ProcessParameters : Ptr64 _RTL_USER_PROCESS_PARAMETERS +# +0x028 SubSystemData : Ptr64 Void +# +0x030 ProcessHeap : Ptr64 Void +# +0x038 FastPebLock : Ptr64 _RTL_CRITICAL_SECTION +# +0x040 AtlThunkSListPtr : Ptr64 Void +# +0x048 IFEOKey : Ptr64 Void +# +0x050 CrossProcessFlags : Uint4B +# +0x050 ProcessInJob : Pos 0, 1 Bit +# +0x050 ProcessInitializing : Pos 1, 1 Bit +# +0x050 ProcessUsingVEH : Pos 2, 1 Bit +# +0x050 ProcessUsingVCH : Pos 3, 1 Bit +# +0x050 ProcessUsingFTH : Pos 4, 1 Bit +# +0x050 ReservedBits0 : Pos 5, 27 Bits +# +0x058 KernelCallbackTable : Ptr64 Void +# +0x058 UserSharedInfoPtr : Ptr64 Void +# +0x060 SystemReserved : [1] Uint4B +# +0x064 AtlThunkSListPtr32 : Uint4B +# +0x068 ApiSetMap : Ptr64 Void +# +0x070 TlsExpansionCounter : Uint4B +# +0x078 TlsBitmap : Ptr64 Void +# +0x080 TlsBitmapBits : [2] Uint4B +# +0x088 ReadOnlySharedMemoryBase : Ptr64 Void +# +0x090 HotpatchInformation : Ptr64 Void +# +0x098 ReadOnlyStaticServerData : Ptr64 Ptr64 Void +# +0x0a0 AnsiCodePageData : Ptr64 Void +# +0x0a8 OemCodePageData : Ptr64 Void +# +0x0b0 UnicodeCaseTableData : Ptr64 Void +# +0x0b8 NumberOfProcessors : Uint4B +# +0x0bc NtGlobalFlag : Uint4B +# +0x0c0 CriticalSectionTimeout : _LARGE_INTEGER +# +0x0c8 HeapSegmentReserve : Uint8B +# +0x0d0 HeapSegmentCommit : Uint8B +# +0x0d8 HeapDeCommitTotalFreeThreshold : Uint8B +# +0x0e0 HeapDeCommitFreeBlockThreshold : Uint8B +# +0x0e8 NumberOfHeaps : Uint4B +# +0x0ec MaximumNumberOfHeaps : Uint4B +# +0x0f0 ProcessHeaps : Ptr64 Ptr64 Void +# +0x0f8 GdiSharedHandleTable : Ptr64 Void +# +0x100 ProcessStarterHelper : Ptr64 Void +# +0x108 GdiDCAttributeList : Uint4B +# +0x110 LoaderLock : Ptr64 _RTL_CRITICAL_SECTION +# +0x118 OSMajorVersion : Uint4B +# +0x11c OSMinorVersion : Uint4B +# +0x120 OSBuildNumber : Uint2B +# +0x122 OSCSDVersion : Uint2B +# +0x124 OSPlatformId : Uint4B +# +0x128 ImageSubsystem : Uint4B +# +0x12c ImageSubsystemMajorVersion : Uint4B +# +0x130 ImageSubsystemMinorVersion : Uint4B +# +0x138 ActiveProcessAffinityMask : Uint8B +# +0x140 GdiHandleBuffer : [60] Uint4B +# +0x230 PostProcessInitRoutine : Ptr64 void +# +0x238 TlsExpansionBitmap : Ptr64 Void +# +0x240 TlsExpansionBitmapBits : [32] Uint4B +# +0x2c0 SessionId : Uint4B +# +0x2c8 AppCompatFlags : _ULARGE_INTEGER +# +0x2d0 AppCompatFlagsUser : _ULARGE_INTEGER +# +0x2d8 pShimData : Ptr64 Void +# +0x2e0 AppCompatInfo : Ptr64 Void +# +0x2e8 CSDVersion : _UNICODE_STRING +# +0x2f8 ActivationContextData : Ptr64 _ACTIVATION_CONTEXT_DATA +# +0x300 ProcessAssemblyStorageMap : Ptr64 _ASSEMBLY_STORAGE_MAP +# +0x308 SystemDefaultActivationContextData : Ptr64 _ACTIVATION_CONTEXT_DATA +# +0x310 SystemAssemblyStorageMap : Ptr64 _ASSEMBLY_STORAGE_MAP +# +0x318 MinimumStackCommit : Uint8B +# +0x320 FlsCallback : Ptr64 _FLS_CALLBACK_INFO +# +0x328 FlsListHead : _LIST_ENTRY +# +0x338 FlsBitmap : Ptr64 Void +# +0x340 FlsBitmapBits : [4] Uint4B +# +0x350 FlsHighIndex : Uint4B +# +0x358 WerRegistrationData : Ptr64 Void +# +0x360 WerShipAssertPtr : Ptr64 Void +# +0x368 pContextData : Ptr64 Void +# +0x370 pImageHeaderHash : Ptr64 Void +# +0x378 TracingFlags : Uint4B +# +0x378 HeapTracingEnabled : Pos 0, 1 Bit +# +0x378 CritSecTracingEnabled : Pos 1, 1 Bit +# +0x378 SpareTracingBits : Pos 2, 30 Bits +class _PEB_2008_R2_64(Structure): + _pack_ = 8 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("BitField", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), # PRTL_CRITICAL_SECTION + ("AtlThunkSListPtr", PVOID), + ("IFEOKey", PVOID), + ("CrossProcessFlags", DWORD), + ("KernelCallbackTable", PVOID), + ("SystemReserved", DWORD), + ("AtlThunkSListPtr32", DWORD), + ("ApiSetMap", PVOID), + ("TlsExpansionCounter", DWORD), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", DWORD * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("HotpatchInformation", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr32 Ptr32 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", DWORD), + ("NtGlobalFlag", DWORD), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", QWORD), + ("HeapSegmentCommit", QWORD), + ("HeapDeCommitTotalFreeThreshold", QWORD), + ("HeapDeCommitFreeBlockThreshold", QWORD), + ("NumberOfHeaps", DWORD), + ("MaximumNumberOfHeaps", DWORD), + ("ProcessHeaps", PVOID), # Ptr64 Ptr64 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", DWORD), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", DWORD), + ("OSMinorVersion", DWORD), + ("OSBuildNumber", WORD), + ("OSCSDVersion", WORD), + ("OSPlatformId", DWORD), + ("ImageSubsystem", DWORD), + ("ImageSubsystemMajorVersion", DWORD), + ("ImageSubsystemMinorVersion", DWORD), + ("ActiveProcessAffinityMask", QWORD), + ("GdiHandleBuffer", DWORD * 60), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", PVOID), + ("TlsExpansionBitmapBits", DWORD * 32), + ("SessionId", DWORD), + ("AppCompatFlags", ULONGLONG), # ULARGE_INTEGER + ("AppCompatFlagsUser", ULONGLONG), # ULARGE_INTEGER + ("pShimData", PVOID), + ("AppCompatInfo", PVOID), + ("CSDVersion", UNICODE_STRING), + ("ActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("ProcessAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("SystemDefaultActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("SystemAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("MinimumStackCommit", QWORD), + ("FlsCallback", PVOID), # PFLS_CALLBACK_INFO + ("FlsListHead", LIST_ENTRY), + ("FlsBitmap", PVOID), + ("FlsBitmapBits", DWORD * 4), + ("FlsHighIndex", DWORD), + ("WerRegistrationData", PVOID), + ("WerShipAssertPtr", PVOID), + ("pContextData", PVOID), + ("pImageHeaderHash", PVOID), + ("TracingFlags", DWORD), + ] + def __get_UserSharedInfoPtr(self): + return self.KernelCallbackTable + def __set_UserSharedInfoPtr(self, value): + self.KernelCallbackTable = value + UserSharedInfoPtr = property(__get_UserSharedInfoPtr, __set_UserSharedInfoPtr) + +_PEB_Vista = _PEB_2008 +_PEB_Vista_64 = _PEB_2008_64 +_PEB_W7 = _PEB_2008_R2 +_PEB_W7_64 = _PEB_2008_R2_64 + +# +0x000 InheritedAddressSpace : UChar +# +0x001 ReadImageFileExecOptions : UChar +# +0x002 BeingDebugged : UChar +# +0x003 BitField : UChar +# +0x003 ImageUsesLargePages : Pos 0, 1 Bit +# +0x003 IsProtectedProcess : Pos 1, 1 Bit +# +0x003 IsLegacyProcess : Pos 2, 1 Bit +# +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit +# +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit +# +0x003 SpareBits : Pos 5, 3 Bits +# +0x004 Mutant : Ptr32 Void +# +0x008 ImageBaseAddress : Ptr32 Void +# +0x00c Ldr : Ptr32 _PEB_LDR_DATA +# +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +# +0x014 SubSystemData : Ptr32 Void +# +0x018 ProcessHeap : Ptr32 Void +# +0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x020 AtlThunkSListPtr : Ptr32 Void +# +0x024 IFEOKey : Ptr32 Void +# +0x028 CrossProcessFlags : Uint4B +# +0x028 ProcessInJob : Pos 0, 1 Bit +# +0x028 ProcessInitializing : Pos 1, 1 Bit +# +0x028 ProcessUsingVEH : Pos 2, 1 Bit +# +0x028 ProcessUsingVCH : Pos 3, 1 Bit +# +0x028 ProcessUsingFTH : Pos 4, 1 Bit +# +0x028 ReservedBits0 : Pos 5, 27 Bits +# +0x02c KernelCallbackTable : Ptr32 Void +# +0x02c UserSharedInfoPtr : Ptr32 Void +# +0x030 SystemReserved : [1] Uint4B +# +0x034 TracingFlags : Uint4B +# +0x034 HeapTracingEnabled : Pos 0, 1 Bit +# +0x034 CritSecTracingEnabled : Pos 1, 1 Bit +# +0x034 SpareTracingBits : Pos 2, 30 Bits +# +0x038 ApiSetMap : Ptr32 Void +# +0x03c TlsExpansionCounter : Uint4B +# +0x040 TlsBitmap : Ptr32 Void +# +0x044 TlsBitmapBits : [2] Uint4B +# +0x04c ReadOnlySharedMemoryBase : Ptr32 Void +# +0x050 HotpatchInformation : Ptr32 Void +# +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void +# +0x058 AnsiCodePageData : Ptr32 Void +# +0x05c OemCodePageData : Ptr32 Void +# +0x060 UnicodeCaseTableData : Ptr32 Void +# +0x064 NumberOfProcessors : Uint4B +# +0x068 NtGlobalFlag : Uint4B +# +0x070 CriticalSectionTimeout : _LARGE_INTEGER +# +0x078 HeapSegmentReserve : Uint4B +# +0x07c HeapSegmentCommit : Uint4B +# +0x080 HeapDeCommitTotalFreeThreshold : Uint4B +# +0x084 HeapDeCommitFreeBlockThreshold : Uint4B +# +0x088 NumberOfHeaps : Uint4B +# +0x08c MaximumNumberOfHeaps : Uint4B +# +0x090 ProcessHeaps : Ptr32 Ptr32 Void +# +0x094 GdiSharedHandleTable : Ptr32 Void +# +0x098 ProcessStarterHelper : Ptr32 Void +# +0x09c GdiDCAttributeList : Uint4B +# +0x0a0 LoaderLock : Ptr32 _RTL_CRITICAL_SECTION +# +0x0a4 OSMajorVersion : Uint4B +# +0x0a8 OSMinorVersion : Uint4B +# +0x0ac OSBuildNumber : Uint2B +# +0x0ae OSCSDVersion : Uint2B +# +0x0b0 OSPlatformId : Uint4B +# +0x0b4 ImageSubsystem : Uint4B +# +0x0b8 ImageSubsystemMajorVersion : Uint4B +# +0x0bc ImageSubsystemMinorVersion : Uint4B +# +0x0c0 ActiveProcessAffinityMask : Uint4B +# +0x0c4 GdiHandleBuffer : [34] Uint4B +# +0x14c PostProcessInitRoutine : Ptr32 void +# +0x150 TlsExpansionBitmap : Ptr32 Void +# +0x154 TlsExpansionBitmapBits : [32] Uint4B +# +0x1d4 SessionId : Uint4B +# +0x1d8 AppCompatFlags : _ULARGE_INTEGER +# +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER +# +0x1e8 pShimData : Ptr32 Void +# +0x1ec AppCompatInfo : Ptr32 Void +# +0x1f0 CSDVersion : _UNICODE_STRING +# +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +# +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +# +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +# +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +# +0x208 MinimumStackCommit : Uint4B +# +0x20c FlsCallback : Ptr32 _FLS_CALLBACK_INFO +# +0x210 FlsListHead : _LIST_ENTRY +# +0x218 FlsBitmap : Ptr32 Void +# +0x21c FlsBitmapBits : [4] Uint4B +# +0x22c FlsHighIndex : Uint4B +# +0x230 WerRegistrationData : Ptr32 Void +# +0x234 WerShipAssertPtr : Ptr32 Void +# +0x238 pContextData : Ptr32 Void +# +0x23c pImageHeaderHash : Ptr32 Void +class _PEB_W7_Beta(Structure): + """ + This definition of the PEB structure is only valid for the beta versions + of Windows 7. For the final version of Windows 7 use L{_PEB_W7} instead. + This structure is not chosen automatically. + """ + _pack_ = 8 + _fields_ = [ + ("InheritedAddressSpace", BOOLEAN), + ("ReadImageFileExecOptions", UCHAR), + ("BeingDebugged", BOOLEAN), + ("BitField", UCHAR), + ("Mutant", HANDLE), + ("ImageBaseAddress", PVOID), + ("Ldr", PVOID), # PPEB_LDR_DATA + ("ProcessParameters", PVOID), # PRTL_USER_PROCESS_PARAMETERS + ("SubSystemData", PVOID), + ("ProcessHeap", PVOID), + ("FastPebLock", PVOID), # PRTL_CRITICAL_SECTION + ("AtlThunkSListPtr", PVOID), + ("IFEOKey", PVOID), + ("CrossProcessFlags", DWORD), + ("KernelCallbackTable", PVOID), + ("SystemReserved", DWORD), + ("TracingFlags", DWORD), + ("ApiSetMap", PVOID), + ("TlsExpansionCounter", DWORD), + ("TlsBitmap", PVOID), + ("TlsBitmapBits", DWORD * 2), + ("ReadOnlySharedMemoryBase", PVOID), + ("HotpatchInformation", PVOID), + ("ReadOnlyStaticServerData", PVOID), # Ptr32 Ptr32 Void + ("AnsiCodePageData", PVOID), + ("OemCodePageData", PVOID), + ("UnicodeCaseTableData", PVOID), + ("NumberOfProcessors", DWORD), + ("NtGlobalFlag", DWORD), + ("CriticalSectionTimeout", LONGLONG), # LARGE_INTEGER + ("HeapSegmentReserve", DWORD), + ("HeapSegmentCommit", DWORD), + ("HeapDeCommitTotalFreeThreshold", DWORD), + ("HeapDeCommitFreeBlockThreshold", DWORD), + ("NumberOfHeaps", DWORD), + ("MaximumNumberOfHeaps", DWORD), + ("ProcessHeaps", PVOID), # Ptr32 Ptr32 Void + ("GdiSharedHandleTable", PVOID), + ("ProcessStarterHelper", PVOID), + ("GdiDCAttributeList", DWORD), + ("LoaderLock", PVOID), # PRTL_CRITICAL_SECTION + ("OSMajorVersion", DWORD), + ("OSMinorVersion", DWORD), + ("OSBuildNumber", WORD), + ("OSCSDVersion", WORD), + ("OSPlatformId", DWORD), + ("ImageSubsystem", DWORD), + ("ImageSubsystemMajorVersion", DWORD), + ("ImageSubsystemMinorVersion", DWORD), + ("ActiveProcessAffinityMask", DWORD), + ("GdiHandleBuffer", DWORD * 34), + ("PostProcessInitRoutine", PPS_POST_PROCESS_INIT_ROUTINE), + ("TlsExpansionBitmap", PVOID), + ("TlsExpansionBitmapBits", DWORD * 32), + ("SessionId", DWORD), + ("AppCompatFlags", ULONGLONG), # ULARGE_INTEGER + ("AppCompatFlagsUser", ULONGLONG), # ULARGE_INTEGER + ("pShimData", PVOID), + ("AppCompatInfo", PVOID), + ("CSDVersion", UNICODE_STRING), + ("ActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("ProcessAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("SystemDefaultActivationContextData", PVOID), # ACTIVATION_CONTEXT_DATA + ("SystemAssemblyStorageMap", PVOID), # ASSEMBLY_STORAGE_MAP + ("MinimumStackCommit", DWORD), + ("FlsCallback", PVOID), # PFLS_CALLBACK_INFO + ("FlsListHead", LIST_ENTRY), + ("FlsBitmap", PVOID), + ("FlsBitmapBits", DWORD * 4), + ("FlsHighIndex", DWORD), + ("WerRegistrationData", PVOID), + ("WerShipAssertPtr", PVOID), + ("pContextData", PVOID), + ("pImageHeaderHash", PVOID), + ] + def __get_UserSharedInfoPtr(self): + return self.KernelCallbackTable + def __set_UserSharedInfoPtr(self, value): + self.KernelCallbackTable = value + UserSharedInfoPtr = property(__get_UserSharedInfoPtr, __set_UserSharedInfoPtr) + +# Use the correct PEB structure definition. +# Defaults to the latest Windows version. +class PEB(Structure): + _pack_ = 8 + if os == 'Windows NT': + _pack_ = _PEB_NT._pack_ + _fields_ = _PEB_NT._fields_ + elif os == 'Windows 2000': + _pack_ = _PEB_2000._pack_ + _fields_ = _PEB_2000._fields_ + elif os == 'Windows XP': + _fields_ = _PEB_XP._fields_ + elif os == 'Windows XP (64 bits)': + _fields_ = _PEB_XP_64._fields_ + elif os == 'Windows 2003': + _fields_ = _PEB_2003._fields_ + elif os == 'Windows 2003 (64 bits)': + _fields_ = _PEB_2003_64._fields_ + elif os == 'Windows 2003 R2': + _fields_ = _PEB_2003_R2._fields_ + elif os == 'Windows 2003 R2 (64 bits)': + _fields_ = _PEB_2003_R2_64._fields_ + elif os == 'Windows 2008': + _fields_ = _PEB_2008._fields_ + elif os == 'Windows 2008 (64 bits)': + _fields_ = _PEB_2008_64._fields_ + elif os == 'Windows 2008 R2': + _fields_ = _PEB_2008_R2._fields_ + elif os == 'Windows 2008 R2 (64 bits)': + _fields_ = _PEB_2008_R2_64._fields_ + elif os == 'Windows Vista': + _fields_ = _PEB_Vista._fields_ + elif os == 'Windows Vista (64 bits)': + _fields_ = _PEB_Vista_64._fields_ + elif os == 'Windows 7': + _fields_ = _PEB_W7._fields_ + elif os == 'Windows 7 (64 bits)': + _fields_ = _PEB_W7_64._fields_ + elif sizeof(SIZE_T) == sizeof(DWORD): + _fields_ = _PEB_W7._fields_ + else: + _fields_ = _PEB_W7_64._fields_ +PPEB = POINTER(PEB) + +# PEB structure for WOW64 processes. +class PEB_32(Structure): + _pack_ = 8 + if os == 'Windows NT': + _pack_ = _PEB_NT._pack_ + _fields_ = _PEB_NT._fields_ + elif os == 'Windows 2000': + _pack_ = _PEB_2000._pack_ + _fields_ = _PEB_2000._fields_ + elif os.startswith('Windows XP'): + _fields_ = _PEB_XP._fields_ + elif os.startswith('Windows 2003 R2'): + _fields_ = _PEB_2003_R2._fields_ + elif os.startswith('Windows 2003'): + _fields_ = _PEB_2003._fields_ + elif os.startswith('Windows 2008 R2'): + _fields_ = _PEB_2008_R2._fields_ + elif os.startswith('Windows 2008'): + _fields_ = _PEB_2008._fields_ + elif os.startswith('Windows Vista'): + _fields_ = _PEB_Vista._fields_ + else: #if os.startswith('Windows 7'): + _fields_ = _PEB_W7._fields_ + +# from https://vmexplorer.svn.codeplex.com/svn/VMExplorer/src/Win32/Threads.cs +# +# [StructLayout (LayoutKind.Sequential, Size = 0x0C)] +# public struct Wx86ThreadState +# { +# public IntPtr CallBx86Eip; // Ptr32 to Uint4B +# public IntPtr DeallocationCpu; // Ptr32 to Void +# public Byte UseKnownWx86Dll; // UChar +# public Byte OleStubInvoked; // Char +# }; +class Wx86ThreadState(Structure): + _fields_ = [ + ("CallBx86Eip", PVOID), + ("DeallocationCpu", PVOID), + ("UseKnownWx86Dll", UCHAR), + ("OleStubInvoked", CHAR), +] + +# ntdll!_RTL_ACTIVATION_CONTEXT_STACK_FRAME +# +0x000 Previous : Ptr64 _RTL_ACTIVATION_CONTEXT_STACK_FRAME +# +0x008 ActivationContext : Ptr64 _ACTIVATION_CONTEXT +# +0x010 Flags : Uint4B +class RTL_ACTIVATION_CONTEXT_STACK_FRAME(Structure): + _fields_ = [ + ("Previous", PVOID), + ("ActivationContext", PVOID), + ("Flags", DWORD), +] + +# ntdll!_ACTIVATION_CONTEXT_STACK +# +0x000 ActiveFrame : Ptr64 _RTL_ACTIVATION_CONTEXT_STACK_FRAME +# +0x008 FrameListCache : _LIST_ENTRY +# +0x018 Flags : Uint4B +# +0x01c NextCookieSequenceNumber : Uint4B +# +0x020 StackId : Uint4B +class ACTIVATION_CONTEXT_STACK(Structure): + _fields_ = [ + ("ActiveFrame", PVOID), + ("FrameListCache", LIST_ENTRY), + ("Flags", DWORD), + ("NextCookieSequenceNumber", DWORD), + ("StackId", DWORD), +] + +# typedef struct _PROCESSOR_NUMBER { +# WORD Group; +# BYTE Number; +# BYTE Reserved; +# }PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; +class PROCESSOR_NUMBER(Structure): + _fields_ = [ + ("Group", WORD), + ("Number", BYTE), + ("Reserved", BYTE), +] + +# from http://www.nirsoft.net/kernel_struct/vista/NT_TIB.html +# +# typedef struct _NT_TIB +# { +# PEXCEPTION_REGISTRATION_RECORD ExceptionList; +# PVOID StackBase; +# PVOID StackLimit; +# PVOID SubSystemTib; +# union +# { +# PVOID FiberData; +# ULONG Version; +# }; +# PVOID ArbitraryUserPointer; +# PNT_TIB Self; +# } NT_TIB, *PNT_TIB; +class _NT_TIB_UNION(Union): + _fields_ = [ + ("FiberData", PVOID), + ("Version", ULONG), + ] +class NT_TIB(Structure): + _fields_ = [ + ("ExceptionList", PVOID), # PEXCEPTION_REGISTRATION_RECORD + ("StackBase", PVOID), + ("StackLimit", PVOID), + ("SubSystemTib", PVOID), + ("u", _NT_TIB_UNION), + ("ArbitraryUserPointer", PVOID), + ("Self", PVOID), # PNTTIB + ] + + def __get_FiberData(self): + return self.u.FiberData + def __set_FiberData(self, value): + self.u.FiberData = value + FiberData = property(__get_FiberData, __set_FiberData) + + def __get_Version(self): + return self.u.Version + def __set_Version(self, value): + self.u.Version = value + Version = property(__get_Version, __set_Version) + +PNTTIB = POINTER(NT_TIB) + +# From http://www.nirsoft.net/kernel_struct/vista/EXCEPTION_REGISTRATION_RECORD.html +# +# typedef struct _EXCEPTION_REGISTRATION_RECORD +# { +# PEXCEPTION_REGISTRATION_RECORD Next; +# PEXCEPTION_DISPOSITION Handler; +# } EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD; +class EXCEPTION_REGISTRATION_RECORD(Structure): + pass + +EXCEPTION_DISPOSITION = DWORD +##PEXCEPTION_DISPOSITION = POINTER(EXCEPTION_DISPOSITION) +##PEXCEPTION_REGISTRATION_RECORD = POINTER(EXCEPTION_REGISTRATION_RECORD) +PEXCEPTION_DISPOSITION = PVOID +PEXCEPTION_REGISTRATION_RECORD = PVOID + +EXCEPTION_REGISTRATION_RECORD._fields_ = [ + ("Next", PEXCEPTION_REGISTRATION_RECORD), + ("Handler", PEXCEPTION_DISPOSITION), +] + +##PPEB = POINTER(PEB) +PPEB = PVOID + +# From http://www.nirsoft.net/kernel_struct/vista/GDI_TEB_BATCH.html +# +# typedef struct _GDI_TEB_BATCH +# { +# ULONG Offset; +# ULONG HDC; +# ULONG Buffer[310]; +# } GDI_TEB_BATCH, *PGDI_TEB_BATCH; +class GDI_TEB_BATCH(Structure): + _fields_ = [ + ("Offset", ULONG), + ("HDC", ULONG), + ("Buffer", ULONG * 310), +] + +# ntdll!_TEB_ACTIVE_FRAME_CONTEXT +# +0x000 Flags : Uint4B +# +0x008 FrameName : Ptr64 Char +class TEB_ACTIVE_FRAME_CONTEXT(Structure): + _fields_ = [ + ("Flags", DWORD), + ("FrameName", LPVOID), # LPCHAR +] +PTEB_ACTIVE_FRAME_CONTEXT = POINTER(TEB_ACTIVE_FRAME_CONTEXT) + +# ntdll!_TEB_ACTIVE_FRAME +# +0x000 Flags : Uint4B +# +0x008 Previous : Ptr64 _TEB_ACTIVE_FRAME +# +0x010 Context : Ptr64 _TEB_ACTIVE_FRAME_CONTEXT +class TEB_ACTIVE_FRAME(Structure): + _fields_ = [ + ("Flags", DWORD), + ("Previous", LPVOID), # PTEB_ACTIVE_FRAME + ("Context", LPVOID), # PTEB_ACTIVE_FRAME_CONTEXT +] +PTEB_ACTIVE_FRAME = POINTER(TEB_ACTIVE_FRAME) + +# SameTebFlags +DbgSafeThunkCall = 1 << 0 +DbgInDebugPrint = 1 << 1 +DbgHasFiberData = 1 << 2 +DbgSkipThreadAttach = 1 << 3 +DbgWerInShipAssertCode = 1 << 4 +DbgRanProcessInit = 1 << 5 +DbgClonedThread = 1 << 6 +DbgSuppressDebugMsg = 1 << 7 +RtlDisableUserStackWalk = 1 << 8 +RtlExceptionAttached = 1 << 9 +RtlInitialThread = 1 << 10 + +# XXX This is quite wrong :P +class _TEB_NT(Structure): + _pack_ = 4 + _fields_ = [ + ("NtTib", NT_TIB), + ("EnvironmentPointer", PVOID), + ("ClientId", CLIENT_ID), + ("ActiveRpcHandle", HANDLE), + ("ThreadLocalStoragePointer", PVOID), + ("ProcessEnvironmentBlock", PPEB), + ("LastErrorValue", ULONG), + ("CountOfOwnedCriticalSections", ULONG), + ("CsrClientThread", PVOID), + ("Win32ThreadInfo", PVOID), + ("User32Reserved", ULONG * 26), + ("UserReserved", ULONG * 5), + ("WOW32Reserved", PVOID), # ptr to wow64cpu!X86SwitchTo64BitMode + ("CurrentLocale", ULONG), + ("FpSoftwareStatusRegister", ULONG), + ("SystemReserved1", PVOID * 54), + ("Spare1", PVOID), + ("ExceptionCode", ULONG), + ("ActivationContextStackPointer", PVOID), # PACTIVATION_CONTEXT_STACK + ("SpareBytes1", ULONG * 36), + ("TxFsContext", ULONG), + ("GdiTebBatch", GDI_TEB_BATCH), + ("RealClientId", CLIENT_ID), + ("GdiCachedProcessHandle", PVOID), + ("GdiClientPID", ULONG), + ("GdiClientTID", ULONG), + ("GdiThreadLocalInfo", PVOID), + ("Win32ClientInfo", PVOID * 62), + ("glDispatchTable", PVOID * 233), + ("glReserved1", ULONG * 29), + ("glReserved2", PVOID), + ("glSectionInfo", PVOID), + ("glSection", PVOID), + ("glTable", PVOID), + ("glCurrentRC", PVOID), + ("glContext", PVOID), + ("LastStatusValue", NTSTATUS), + ("StaticUnicodeString", UNICODE_STRING), + ("StaticUnicodeBuffer", WCHAR * 261), + ("DeallocationStack", PVOID), + ("TlsSlots", PVOID * 64), + ("TlsLinks", LIST_ENTRY), + ("Vdm", PVOID), + ("ReservedForNtRpc", PVOID), + ("DbgSsReserved", PVOID * 2), + ("HardErrorDisabled", ULONG), + ("Instrumentation", PVOID * 9), + ("ActivityId", GUID), + ("SubProcessTag", PVOID), + ("EtwLocalData", PVOID), + ("EtwTraceData", PVOID), + ("WinSockData", PVOID), + ("GdiBatchCount", ULONG), + ("SpareBool0", BOOLEAN), + ("SpareBool1", BOOLEAN), + ("SpareBool2", BOOLEAN), + ("IdealProcessor", UCHAR), + ("GuaranteedStackBytes", ULONG), + ("ReservedForPerf", PVOID), + ("ReservedForOle", PVOID), + ("WaitingOnLoaderLock", ULONG), + ("StackCommit", PVOID), + ("StackCommitMax", PVOID), + ("StackReserved", PVOID), +] + +# not really, but "dt _TEB" in w2k isn't working for me :( +_TEB_2000 = _TEB_NT + +# +0x000 NtTib : _NT_TIB +# +0x01c EnvironmentPointer : Ptr32 Void +# +0x020 ClientId : _CLIENT_ID +# +0x028 ActiveRpcHandle : Ptr32 Void +# +0x02c ThreadLocalStoragePointer : Ptr32 Void +# +0x030 ProcessEnvironmentBlock : Ptr32 _PEB +# +0x034 LastErrorValue : Uint4B +# +0x038 CountOfOwnedCriticalSections : Uint4B +# +0x03c CsrClientThread : Ptr32 Void +# +0x040 Win32ThreadInfo : Ptr32 Void +# +0x044 User32Reserved : [26] Uint4B +# +0x0ac UserReserved : [5] Uint4B +# +0x0c0 WOW32Reserved : Ptr32 Void +# +0x0c4 CurrentLocale : Uint4B +# +0x0c8 FpSoftwareStatusRegister : Uint4B +# +0x0cc SystemReserved1 : [54] Ptr32 Void +# +0x1a4 ExceptionCode : Int4B +# +0x1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK +# +0x1bc SpareBytes1 : [24] UChar +# +0x1d4 GdiTebBatch : _GDI_TEB_BATCH +# +0x6b4 RealClientId : _CLIENT_ID +# +0x6bc GdiCachedProcessHandle : Ptr32 Void +# +0x6c0 GdiClientPID : Uint4B +# +0x6c4 GdiClientTID : Uint4B +# +0x6c8 GdiThreadLocalInfo : Ptr32 Void +# +0x6cc Win32ClientInfo : [62] Uint4B +# +0x7c4 glDispatchTable : [233] Ptr32 Void +# +0xb68 glReserved1 : [29] Uint4B +# +0xbdc glReserved2 : Ptr32 Void +# +0xbe0 glSectionInfo : Ptr32 Void +# +0xbe4 glSection : Ptr32 Void +# +0xbe8 glTable : Ptr32 Void +# +0xbec glCurrentRC : Ptr32 Void +# +0xbf0 glContext : Ptr32 Void +# +0xbf4 LastStatusValue : Uint4B +# +0xbf8 StaticUnicodeString : _UNICODE_STRING +# +0xc00 StaticUnicodeBuffer : [261] Uint2B +# +0xe0c DeallocationStack : Ptr32 Void +# +0xe10 TlsSlots : [64] Ptr32 Void +# +0xf10 TlsLinks : _LIST_ENTRY +# +0xf18 Vdm : Ptr32 Void +# +0xf1c ReservedForNtRpc : Ptr32 Void +# +0xf20 DbgSsReserved : [2] Ptr32 Void +# +0xf28 HardErrorsAreDisabled : Uint4B +# +0xf2c Instrumentation : [16] Ptr32 Void +# +0xf6c WinSockData : Ptr32 Void +# +0xf70 GdiBatchCount : Uint4B +# +0xf74 InDbgPrint : UChar +# +0xf75 FreeStackOnTermination : UChar +# +0xf76 HasFiberData : UChar +# +0xf77 IdealProcessor : UChar +# +0xf78 Spare3 : Uint4B +# +0xf7c ReservedForPerf : Ptr32 Void +# +0xf80 ReservedForOle : Ptr32 Void +# +0xf84 WaitingOnLoaderLock : Uint4B +# +0xf88 Wx86Thread : _Wx86ThreadState +# +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void +# +0xf98 ImpersonationLocale : Uint4B +# +0xf9c IsImpersonating : Uint4B +# +0xfa0 NlsCache : Ptr32 Void +# +0xfa4 pShimData : Ptr32 Void +# +0xfa8 HeapVirtualAffinity : Uint4B +# +0xfac CurrentTransactionHandle : Ptr32 Void +# +0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME +# +0xfb4 SafeThunkCall : UChar +# +0xfb5 BooleanSpare : [3] UChar +class _TEB_XP(Structure): + _pack_ = 8 + _fields_ = [ + ("NtTib", NT_TIB), + ("EnvironmentPointer", PVOID), + ("ClientId", CLIENT_ID), + ("ActiveRpcHandle", HANDLE), + ("ThreadLocalStoragePointer", PVOID), + ("ProcessEnvironmentBlock", PVOID), # PPEB + ("LastErrorValue", DWORD), + ("CountOfOwnedCriticalSections", DWORD), + ("CsrClientThread", PVOID), + ("Win32ThreadInfo", PVOID), + ("User32Reserved", DWORD * 26), + ("UserReserved", DWORD * 5), + ("WOW32Reserved", PVOID), # ptr to wow64cpu!X86SwitchTo64BitMode + ("CurrentLocale", DWORD), + ("FpSoftwareStatusRegister", DWORD), + ("SystemReserved1", PVOID * 54), + ("ExceptionCode", SDWORD), + ("ActivationContextStackPointer", PVOID), # PACTIVATION_CONTEXT_STACK + ("SpareBytes1", UCHAR * 24), + ("TxFsContext", DWORD), + ("GdiTebBatch", GDI_TEB_BATCH), + ("RealClientId", CLIENT_ID), + ("GdiCachedProcessHandle", HANDLE), + ("GdiClientPID", DWORD), + ("GdiClientTID", DWORD), + ("GdiThreadLocalInfo", PVOID), + ("Win32ClientInfo", DWORD * 62), + ("glDispatchTable", PVOID * 233), + ("glReserved1", DWORD * 29), + ("glReserved2", PVOID), + ("glSectionInfo", PVOID), + ("glSection", PVOID), + ("glTable", PVOID), + ("glCurrentRC", PVOID), + ("glContext", PVOID), + ("LastStatusValue", NTSTATUS), + ("StaticUnicodeString", UNICODE_STRING), + ("StaticUnicodeBuffer", WCHAR * 261), + ("DeallocationStack", PVOID), + ("TlsSlots", PVOID * 64), + ("TlsLinks", LIST_ENTRY), + ("Vdm", PVOID), + ("ReservedForNtRpc", PVOID), + ("DbgSsReserved", PVOID * 2), + ("HardErrorsAreDisabled", DWORD), + ("Instrumentation", PVOID * 16), + ("WinSockData", PVOID), + ("GdiBatchCount", DWORD), + ("InDbgPrint", BOOLEAN), + ("FreeStackOnTermination", BOOLEAN), + ("HasFiberData", BOOLEAN), + ("IdealProcessor", UCHAR), + ("Spare3", DWORD), + ("ReservedForPerf", PVOID), + ("ReservedForOle", PVOID), + ("WaitingOnLoaderLock", DWORD), + ("Wx86Thread", Wx86ThreadState), + ("TlsExpansionSlots", PVOID), # Ptr32 Ptr32 Void + ("ImpersonationLocale", DWORD), + ("IsImpersonating", BOOL), + ("NlsCache", PVOID), + ("pShimData", PVOID), + ("HeapVirtualAffinity", DWORD), + ("CurrentTransactionHandle", HANDLE), + ("ActiveFrame", PVOID), # PTEB_ACTIVE_FRAME + ("SafeThunkCall", BOOLEAN), + ("BooleanSpare", BOOLEAN * 3), +] + +# +0x000 NtTib : _NT_TIB +# +0x038 EnvironmentPointer : Ptr64 Void +# +0x040 ClientId : _CLIENT_ID +# +0x050 ActiveRpcHandle : Ptr64 Void +# +0x058 ThreadLocalStoragePointer : Ptr64 Void +# +0x060 ProcessEnvironmentBlock : Ptr64 _PEB +# +0x068 LastErrorValue : Uint4B +# +0x06c CountOfOwnedCriticalSections : Uint4B +# +0x070 CsrClientThread : Ptr64 Void +# +0x078 Win32ThreadInfo : Ptr64 Void +# +0x080 User32Reserved : [26] Uint4B +# +0x0e8 UserReserved : [5] Uint4B +# +0x100 WOW32Reserved : Ptr64 Void +# +0x108 CurrentLocale : Uint4B +# +0x10c FpSoftwareStatusRegister : Uint4B +# +0x110 SystemReserved1 : [54] Ptr64 Void +# +0x2c0 ExceptionCode : Int4B +# +0x2c8 ActivationContextStackPointer : Ptr64 _ACTIVATION_CONTEXT_STACK +# +0x2d0 SpareBytes1 : [28] UChar +# +0x2f0 GdiTebBatch : _GDI_TEB_BATCH +# +0x7d8 RealClientId : _CLIENT_ID +# +0x7e8 GdiCachedProcessHandle : Ptr64 Void +# +0x7f0 GdiClientPID : Uint4B +# +0x7f4 GdiClientTID : Uint4B +# +0x7f8 GdiThreadLocalInfo : Ptr64 Void +# +0x800 Win32ClientInfo : [62] Uint8B +# +0x9f0 glDispatchTable : [233] Ptr64 Void +# +0x1138 glReserved1 : [29] Uint8B +# +0x1220 glReserved2 : Ptr64 Void +# +0x1228 glSectionInfo : Ptr64 Void +# +0x1230 glSection : Ptr64 Void +# +0x1238 glTable : Ptr64 Void +# +0x1240 glCurrentRC : Ptr64 Void +# +0x1248 glContext : Ptr64 Void +# +0x1250 LastStatusValue : Uint4B +# +0x1258 StaticUnicodeString : _UNICODE_STRING +# +0x1268 StaticUnicodeBuffer : [261] Uint2B +# +0x1478 DeallocationStack : Ptr64 Void +# +0x1480 TlsSlots : [64] Ptr64 Void +# +0x1680 TlsLinks : _LIST_ENTRY +# +0x1690 Vdm : Ptr64 Void +# +0x1698 ReservedForNtRpc : Ptr64 Void +# +0x16a0 DbgSsReserved : [2] Ptr64 Void +# +0x16b0 HardErrorMode : Uint4B +# +0x16b8 Instrumentation : [14] Ptr64 Void +# +0x1728 SubProcessTag : Ptr64 Void +# +0x1730 EtwTraceData : Ptr64 Void +# +0x1738 WinSockData : Ptr64 Void +# +0x1740 GdiBatchCount : Uint4B +# +0x1744 InDbgPrint : UChar +# +0x1745 FreeStackOnTermination : UChar +# +0x1746 HasFiberData : UChar +# +0x1747 IdealProcessor : UChar +# +0x1748 GuaranteedStackBytes : Uint4B +# +0x1750 ReservedForPerf : Ptr64 Void +# +0x1758 ReservedForOle : Ptr64 Void +# +0x1760 WaitingOnLoaderLock : Uint4B +# +0x1768 SparePointer1 : Uint8B +# +0x1770 SoftPatchPtr1 : Uint8B +# +0x1778 SoftPatchPtr2 : Uint8B +# +0x1780 TlsExpansionSlots : Ptr64 Ptr64 Void +# +0x1788 DeallocationBStore : Ptr64 Void +# +0x1790 BStoreLimit : Ptr64 Void +# +0x1798 ImpersonationLocale : Uint4B +# +0x179c IsImpersonating : Uint4B +# +0x17a0 NlsCache : Ptr64 Void +# +0x17a8 pShimData : Ptr64 Void +# +0x17b0 HeapVirtualAffinity : Uint4B +# +0x17b8 CurrentTransactionHandle : Ptr64 Void +# +0x17c0 ActiveFrame : Ptr64 _TEB_ACTIVE_FRAME +# +0x17c8 FlsData : Ptr64 Void +# +0x17d0 SafeThunkCall : UChar +# +0x17d1 BooleanSpare : [3] UChar +class _TEB_XP_64(Structure): + _pack_ = 8 + _fields_ = [ + ("NtTib", NT_TIB), + ("EnvironmentPointer", PVOID), + ("ClientId", CLIENT_ID), + ("ActiveRpcHandle", PVOID), + ("ThreadLocalStoragePointer", PVOID), + ("ProcessEnvironmentBlock", PVOID), # PPEB + ("LastErrorValue", DWORD), + ("CountOfOwnedCriticalSections", DWORD), + ("CsrClientThread", PVOID), + ("Win32ThreadInfo", PVOID), + ("User32Reserved", DWORD * 26), + ("UserReserved", DWORD * 5), + ("WOW32Reserved", PVOID), # ptr to wow64cpu!X86SwitchTo64BitMode + ("CurrentLocale", DWORD), + ("FpSoftwareStatusRegister", DWORD), + ("SystemReserved1", PVOID * 54), + ("ExceptionCode", SDWORD), + ("ActivationContextStackPointer", PVOID), # PACTIVATION_CONTEXT_STACK + ("SpareBytes1", UCHAR * 28), + ("GdiTebBatch", GDI_TEB_BATCH), + ("RealClientId", CLIENT_ID), + ("GdiCachedProcessHandle", HANDLE), + ("GdiClientPID", DWORD), + ("GdiClientTID", DWORD), + ("GdiThreadLocalInfo", PVOID), + ("Win32ClientInfo", QWORD * 62), + ("glDispatchTable", PVOID * 233), + ("glReserved1", QWORD * 29), + ("glReserved2", PVOID), + ("glSectionInfo", PVOID), + ("glSection", PVOID), + ("glTable", PVOID), + ("glCurrentRC", PVOID), + ("glContext", PVOID), + ("LastStatusValue", NTSTATUS), + ("StaticUnicodeString", UNICODE_STRING), + ("StaticUnicodeBuffer", WCHAR * 261), + ("DeallocationStack", PVOID), + ("TlsSlots", PVOID * 64), + ("TlsLinks", LIST_ENTRY), + ("Vdm", PVOID), + ("ReservedForNtRpc", PVOID), + ("DbgSsReserved", PVOID * 2), + ("HardErrorMode", DWORD), + ("Instrumentation", PVOID * 14), + ("SubProcessTag", PVOID), + ("EtwTraceData", PVOID), + ("WinSockData", PVOID), + ("GdiBatchCount", DWORD), + ("InDbgPrint", BOOLEAN), + ("FreeStackOnTermination", BOOLEAN), + ("HasFiberData", BOOLEAN), + ("IdealProcessor", UCHAR), + ("GuaranteedStackBytes", DWORD), + ("ReservedForPerf", PVOID), + ("ReservedForOle", PVOID), + ("WaitingOnLoaderLock", DWORD), + ("SparePointer1", PVOID), + ("SoftPatchPtr1", PVOID), + ("SoftPatchPtr2", PVOID), + ("TlsExpansionSlots", PVOID), # Ptr64 Ptr64 Void + ("DeallocationBStore", PVOID), + ("BStoreLimit", PVOID), + ("ImpersonationLocale", DWORD), + ("IsImpersonating", BOOL), + ("NlsCache", PVOID), + ("pShimData", PVOID), + ("HeapVirtualAffinity", DWORD), + ("CurrentTransactionHandle", HANDLE), + ("ActiveFrame", PVOID), # PTEB_ACTIVE_FRAME + ("FlsData", PVOID), + ("SafeThunkCall", BOOLEAN), + ("BooleanSpare", BOOLEAN * 3), +] + +# +0x000 NtTib : _NT_TIB +# +0x01c EnvironmentPointer : Ptr32 Void +# +0x020 ClientId : _CLIENT_ID +# +0x028 ActiveRpcHandle : Ptr32 Void +# +0x02c ThreadLocalStoragePointer : Ptr32 Void +# +0x030 ProcessEnvironmentBlock : Ptr32 _PEB +# +0x034 LastErrorValue : Uint4B +# +0x038 CountOfOwnedCriticalSections : Uint4B +# +0x03c CsrClientThread : Ptr32 Void +# +0x040 Win32ThreadInfo : Ptr32 Void +# +0x044 User32Reserved : [26] Uint4B +# +0x0ac UserReserved : [5] Uint4B +# +0x0c0 WOW32Reserved : Ptr32 Void +# +0x0c4 CurrentLocale : Uint4B +# +0x0c8 FpSoftwareStatusRegister : Uint4B +# +0x0cc SystemReserved1 : [54] Ptr32 Void +# +0x1a4 ExceptionCode : Int4B +# +0x1a8 ActivationContextStackPointer : Ptr32 _ACTIVATION_CONTEXT_STACK +# +0x1ac SpareBytes1 : [40] UChar +# +0x1d4 GdiTebBatch : _GDI_TEB_BATCH +# +0x6b4 RealClientId : _CLIENT_ID +# +0x6bc GdiCachedProcessHandle : Ptr32 Void +# +0x6c0 GdiClientPID : Uint4B +# +0x6c4 GdiClientTID : Uint4B +# +0x6c8 GdiThreadLocalInfo : Ptr32 Void +# +0x6cc Win32ClientInfo : [62] Uint4B +# +0x7c4 glDispatchTable : [233] Ptr32 Void +# +0xb68 glReserved1 : [29] Uint4B +# +0xbdc glReserved2 : Ptr32 Void +# +0xbe0 glSectionInfo : Ptr32 Void +# +0xbe4 glSection : Ptr32 Void +# +0xbe8 glTable : Ptr32 Void +# +0xbec glCurrentRC : Ptr32 Void +# +0xbf0 glContext : Ptr32 Void +# +0xbf4 LastStatusValue : Uint4B +# +0xbf8 StaticUnicodeString : _UNICODE_STRING +# +0xc00 StaticUnicodeBuffer : [261] Uint2B +# +0xe0c DeallocationStack : Ptr32 Void +# +0xe10 TlsSlots : [64] Ptr32 Void +# +0xf10 TlsLinks : _LIST_ENTRY +# +0xf18 Vdm : Ptr32 Void +# +0xf1c ReservedForNtRpc : Ptr32 Void +# +0xf20 DbgSsReserved : [2] Ptr32 Void +# +0xf28 HardErrorMode : Uint4B +# +0xf2c Instrumentation : [14] Ptr32 Void +# +0xf64 SubProcessTag : Ptr32 Void +# +0xf68 EtwTraceData : Ptr32 Void +# +0xf6c WinSockData : Ptr32 Void +# +0xf70 GdiBatchCount : Uint4B +# +0xf74 InDbgPrint : UChar +# +0xf75 FreeStackOnTermination : UChar +# +0xf76 HasFiberData : UChar +# +0xf77 IdealProcessor : UChar +# +0xf78 GuaranteedStackBytes : Uint4B +# +0xf7c ReservedForPerf : Ptr32 Void +# +0xf80 ReservedForOle : Ptr32 Void +# +0xf84 WaitingOnLoaderLock : Uint4B +# +0xf88 SparePointer1 : Uint4B +# +0xf8c SoftPatchPtr1 : Uint4B +# +0xf90 SoftPatchPtr2 : Uint4B +# +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void +# +0xf98 ImpersonationLocale : Uint4B +# +0xf9c IsImpersonating : Uint4B +# +0xfa0 NlsCache : Ptr32 Void +# +0xfa4 pShimData : Ptr32 Void +# +0xfa8 HeapVirtualAffinity : Uint4B +# +0xfac CurrentTransactionHandle : Ptr32 Void +# +0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME +# +0xfb4 FlsData : Ptr32 Void +# +0xfb8 SafeThunkCall : UChar +# +0xfb9 BooleanSpare : [3] UChar +class _TEB_2003(Structure): + _pack_ = 8 + _fields_ = [ + ("NtTib", NT_TIB), + ("EnvironmentPointer", PVOID), + ("ClientId", CLIENT_ID), + ("ActiveRpcHandle", HANDLE), + ("ThreadLocalStoragePointer", PVOID), + ("ProcessEnvironmentBlock", PVOID), # PPEB + ("LastErrorValue", DWORD), + ("CountOfOwnedCriticalSections", DWORD), + ("CsrClientThread", PVOID), + ("Win32ThreadInfo", PVOID), + ("User32Reserved", DWORD * 26), + ("UserReserved", DWORD * 5), + ("WOW32Reserved", PVOID), # ptr to wow64cpu!X86SwitchTo64BitMode + ("CurrentLocale", DWORD), + ("FpSoftwareStatusRegister", DWORD), + ("SystemReserved1", PVOID * 54), + ("ExceptionCode", SDWORD), + ("ActivationContextStackPointer", PVOID), # PACTIVATION_CONTEXT_STACK + ("SpareBytes1", UCHAR * 40), + ("GdiTebBatch", GDI_TEB_BATCH), + ("RealClientId", CLIENT_ID), + ("GdiCachedProcessHandle", HANDLE), + ("GdiClientPID", DWORD), + ("GdiClientTID", DWORD), + ("GdiThreadLocalInfo", PVOID), + ("Win32ClientInfo", DWORD * 62), + ("glDispatchTable", PVOID * 233), + ("glReserved1", DWORD * 29), + ("glReserved2", PVOID), + ("glSectionInfo", PVOID), + ("glSection", PVOID), + ("glTable", PVOID), + ("glCurrentRC", PVOID), + ("glContext", PVOID), + ("LastStatusValue", NTSTATUS), + ("StaticUnicodeString", UNICODE_STRING), + ("StaticUnicodeBuffer", WCHAR * 261), + ("DeallocationStack", PVOID), + ("TlsSlots", PVOID * 64), + ("TlsLinks", LIST_ENTRY), + ("Vdm", PVOID), + ("ReservedForNtRpc", PVOID), + ("DbgSsReserved", PVOID * 2), + ("HardErrorMode", DWORD), + ("Instrumentation", PVOID * 14), + ("SubProcessTag", PVOID), + ("EtwTraceData", PVOID), + ("WinSockData", PVOID), + ("GdiBatchCount", DWORD), + ("InDbgPrint", BOOLEAN), + ("FreeStackOnTermination", BOOLEAN), + ("HasFiberData", BOOLEAN), + ("IdealProcessor", UCHAR), + ("GuaranteedStackBytes", DWORD), + ("ReservedForPerf", PVOID), + ("ReservedForOle", PVOID), + ("WaitingOnLoaderLock", DWORD), + ("SparePointer1", PVOID), + ("SoftPatchPtr1", PVOID), + ("SoftPatchPtr2", PVOID), + ("TlsExpansionSlots", PVOID), # Ptr32 Ptr32 Void + ("ImpersonationLocale", DWORD), + ("IsImpersonating", BOOL), + ("NlsCache", PVOID), + ("pShimData", PVOID), + ("HeapVirtualAffinity", DWORD), + ("CurrentTransactionHandle", HANDLE), + ("ActiveFrame", PVOID), # PTEB_ACTIVE_FRAME + ("FlsData", PVOID), + ("SafeThunkCall", BOOLEAN), + ("BooleanSpare", BOOLEAN * 3), +] + +_TEB_2003_64 = _TEB_XP_64 +_TEB_2003_R2 = _TEB_2003 +_TEB_2003_R2_64 = _TEB_2003_64 + +# +0x000 NtTib : _NT_TIB +# +0x01c EnvironmentPointer : Ptr32 Void +# +0x020 ClientId : _CLIENT_ID +# +0x028 ActiveRpcHandle : Ptr32 Void +# +0x02c ThreadLocalStoragePointer : Ptr32 Void +# +0x030 ProcessEnvironmentBlock : Ptr32 _PEB +# +0x034 LastErrorValue : Uint4B +# +0x038 CountOfOwnedCriticalSections : Uint4B +# +0x03c CsrClientThread : Ptr32 Void +# +0x040 Win32ThreadInfo : Ptr32 Void +# +0x044 User32Reserved : [26] Uint4B +# +0x0ac UserReserved : [5] Uint4B +# +0x0c0 WOW32Reserved : Ptr32 Void +# +0x0c4 CurrentLocale : Uint4B +# +0x0c8 FpSoftwareStatusRegister : Uint4B +# +0x0cc SystemReserved1 : [54] Ptr32 Void +# +0x1a4 ExceptionCode : Int4B +# +0x1a8 ActivationContextStackPointer : Ptr32 _ACTIVATION_CONTEXT_STACK +# +0x1ac SpareBytes1 : [36] UChar +# +0x1d0 TxFsContext : Uint4B +# +0x1d4 GdiTebBatch : _GDI_TEB_BATCH +# +0x6b4 RealClientId : _CLIENT_ID +# +0x6bc GdiCachedProcessHandle : Ptr32 Void +# +0x6c0 GdiClientPID : Uint4B +# +0x6c4 GdiClientTID : Uint4B +# +0x6c8 GdiThreadLocalInfo : Ptr32 Void +# +0x6cc Win32ClientInfo : [62] Uint4B +# +0x7c4 glDispatchTable : [233] Ptr32 Void +# +0xb68 glReserved1 : [29] Uint4B +# +0xbdc glReserved2 : Ptr32 Void +# +0xbe0 glSectionInfo : Ptr32 Void +# +0xbe4 glSection : Ptr32 Void +# +0xbe8 glTable : Ptr32 Void +# +0xbec glCurrentRC : Ptr32 Void +# +0xbf0 glContext : Ptr32 Void +# +0xbf4 LastStatusValue : Uint4B +# +0xbf8 StaticUnicodeString : _UNICODE_STRING +# +0xc00 StaticUnicodeBuffer : [261] Wchar +# +0xe0c DeallocationStack : Ptr32 Void +# +0xe10 TlsSlots : [64] Ptr32 Void +# +0xf10 TlsLinks : _LIST_ENTRY +# +0xf18 Vdm : Ptr32 Void +# +0xf1c ReservedForNtRpc : Ptr32 Void +# +0xf20 DbgSsReserved : [2] Ptr32 Void +# +0xf28 HardErrorMode : Uint4B +# +0xf2c Instrumentation : [9] Ptr32 Void +# +0xf50 ActivityId : _GUID +# +0xf60 SubProcessTag : Ptr32 Void +# +0xf64 EtwLocalData : Ptr32 Void +# +0xf68 EtwTraceData : Ptr32 Void +# +0xf6c WinSockData : Ptr32 Void +# +0xf70 GdiBatchCount : Uint4B +# +0xf74 SpareBool0 : UChar +# +0xf75 SpareBool1 : UChar +# +0xf76 SpareBool2 : UChar +# +0xf77 IdealProcessor : UChar +# +0xf78 GuaranteedStackBytes : Uint4B +# +0xf7c ReservedForPerf : Ptr32 Void +# +0xf80 ReservedForOle : Ptr32 Void +# +0xf84 WaitingOnLoaderLock : Uint4B +# +0xf88 SavedPriorityState : Ptr32 Void +# +0xf8c SoftPatchPtr1 : Uint4B +# +0xf90 ThreadPoolData : Ptr32 Void +# +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void +# +0xf98 ImpersonationLocale : Uint4B +# +0xf9c IsImpersonating : Uint4B +# +0xfa0 NlsCache : Ptr32 Void +# +0xfa4 pShimData : Ptr32 Void +# +0xfa8 HeapVirtualAffinity : Uint4B +# +0xfac CurrentTransactionHandle : Ptr32 Void +# +0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME +# +0xfb4 FlsData : Ptr32 Void +# +0xfb8 PreferredLanguages : Ptr32 Void +# +0xfbc UserPrefLanguages : Ptr32 Void +# +0xfc0 MergedPrefLanguages : Ptr32 Void +# +0xfc4 MuiImpersonation : Uint4B +# +0xfc8 CrossTebFlags : Uint2B +# +0xfc8 SpareCrossTebBits : Pos 0, 16 Bits +# +0xfca SameTebFlags : Uint2B +# +0xfca DbgSafeThunkCall : Pos 0, 1 Bit +# +0xfca DbgInDebugPrint : Pos 1, 1 Bit +# +0xfca DbgHasFiberData : Pos 2, 1 Bit +# +0xfca DbgSkipThreadAttach : Pos 3, 1 Bit +# +0xfca DbgWerInShipAssertCode : Pos 4, 1 Bit +# +0xfca DbgRanProcessInit : Pos 5, 1 Bit +# +0xfca DbgClonedThread : Pos 6, 1 Bit +# +0xfca DbgSuppressDebugMsg : Pos 7, 1 Bit +# +0xfca RtlDisableUserStackWalk : Pos 8, 1 Bit +# +0xfca RtlExceptionAttached : Pos 9, 1 Bit +# +0xfca SpareSameTebBits : Pos 10, 6 Bits +# +0xfcc TxnScopeEnterCallback : Ptr32 Void +# +0xfd0 TxnScopeExitCallback : Ptr32 Void +# +0xfd4 TxnScopeContext : Ptr32 Void +# +0xfd8 LockCount : Uint4B +# +0xfdc ProcessRundown : Uint4B +# +0xfe0 LastSwitchTime : Uint8B +# +0xfe8 TotalSwitchOutTime : Uint8B +# +0xff0 WaitReasonBitMap : _LARGE_INTEGER +class _TEB_2008(Structure): + _pack_ = 8 + _fields_ = [ + ("NtTib", NT_TIB), + ("EnvironmentPointer", PVOID), + ("ClientId", CLIENT_ID), + ("ActiveRpcHandle", HANDLE), + ("ThreadLocalStoragePointer", PVOID), + ("ProcessEnvironmentBlock", PVOID), # PPEB + ("LastErrorValue", DWORD), + ("CountOfOwnedCriticalSections", DWORD), + ("CsrClientThread", PVOID), + ("Win32ThreadInfo", PVOID), + ("User32Reserved", DWORD * 26), + ("UserReserved", DWORD * 5), + ("WOW32Reserved", PVOID), # ptr to wow64cpu!X86SwitchTo64BitMode + ("CurrentLocale", DWORD), + ("FpSoftwareStatusRegister", DWORD), + ("SystemReserved1", PVOID * 54), + ("ExceptionCode", SDWORD), + ("ActivationContextStackPointer", PVOID), # PACTIVATION_CONTEXT_STACK + ("SpareBytes1", UCHAR * 36), + ("TxFsContext", DWORD), + ("GdiTebBatch", GDI_TEB_BATCH), + ("RealClientId", CLIENT_ID), + ("GdiCachedProcessHandle", HANDLE), + ("GdiClientPID", DWORD), + ("GdiClientTID", DWORD), + ("GdiThreadLocalInfo", PVOID), + ("Win32ClientInfo", DWORD * 62), + ("glDispatchTable", PVOID * 233), + ("glReserved1", DWORD * 29), + ("glReserved2", PVOID), + ("glSectionInfo", PVOID), + ("glSection", PVOID), + ("glTable", PVOID), + ("glCurrentRC", PVOID), + ("glContext", PVOID), + ("LastStatusValue", NTSTATUS), + ("StaticUnicodeString", UNICODE_STRING), + ("StaticUnicodeBuffer", WCHAR * 261), + ("DeallocationStack", PVOID), + ("TlsSlots", PVOID * 64), + ("TlsLinks", LIST_ENTRY), + ("Vdm", PVOID), + ("ReservedForNtRpc", PVOID), + ("DbgSsReserved", PVOID * 2), + ("HardErrorMode", DWORD), + ("Instrumentation", PVOID * 9), + ("ActivityId", GUID), + ("SubProcessTag", PVOID), + ("EtwLocalData", PVOID), + ("EtwTraceData", PVOID), + ("WinSockData", PVOID), + ("GdiBatchCount", DWORD), + ("SpareBool0", BOOLEAN), + ("SpareBool1", BOOLEAN), + ("SpareBool2", BOOLEAN), + ("IdealProcessor", UCHAR), + ("GuaranteedStackBytes", DWORD), + ("ReservedForPerf", PVOID), + ("ReservedForOle", PVOID), + ("WaitingOnLoaderLock", DWORD), + ("SavedPriorityState", PVOID), + ("SoftPatchPtr1", PVOID), + ("ThreadPoolData", PVOID), + ("TlsExpansionSlots", PVOID), # Ptr32 Ptr32 Void + ("ImpersonationLocale", DWORD), + ("IsImpersonating", BOOL), + ("NlsCache", PVOID), + ("pShimData", PVOID), + ("HeapVirtualAffinity", DWORD), + ("CurrentTransactionHandle", HANDLE), + ("ActiveFrame", PVOID), # PTEB_ACTIVE_FRAME + ("FlsData", PVOID), + ("PreferredLanguages", PVOID), + ("UserPrefLanguages", PVOID), + ("MergedPrefLanguages", PVOID), + ("MuiImpersonation", BOOL), + ("CrossTebFlags", WORD), + ("SameTebFlags", WORD), + ("TxnScopeEnterCallback", PVOID), + ("TxnScopeExitCallback", PVOID), + ("TxnScopeContext", PVOID), + ("LockCount", DWORD), + ("ProcessRundown", DWORD), + ("LastSwitchTime", QWORD), + ("TotalSwitchOutTime", QWORD), + ("WaitReasonBitMap", LONGLONG), # LARGE_INTEGER +] + +# +0x000 NtTib : _NT_TIB +# +0x038 EnvironmentPointer : Ptr64 Void +# +0x040 ClientId : _CLIENT_ID +# +0x050 ActiveRpcHandle : Ptr64 Void +# +0x058 ThreadLocalStoragePointer : Ptr64 Void +# +0x060 ProcessEnvironmentBlock : Ptr64 _PEB +# +0x068 LastErrorValue : Uint4B +# +0x06c CountOfOwnedCriticalSections : Uint4B +# +0x070 CsrClientThread : Ptr64 Void +# +0x078 Win32ThreadInfo : Ptr64 Void +# +0x080 User32Reserved : [26] Uint4B +# +0x0e8 UserReserved : [5] Uint4B +# +0x100 WOW32Reserved : Ptr64 Void +# +0x108 CurrentLocale : Uint4B +# +0x10c FpSoftwareStatusRegister : Uint4B +# +0x110 SystemReserved1 : [54] Ptr64 Void +# +0x2c0 ExceptionCode : Int4B +# +0x2c8 ActivationContextStackPointer : Ptr64 _ACTIVATION_CONTEXT_STACK +# +0x2d0 SpareBytes1 : [24] UChar +# +0x2e8 TxFsContext : Uint4B +# +0x2f0 GdiTebBatch : _GDI_TEB_BATCH +# +0x7d8 RealClientId : _CLIENT_ID +# +0x7e8 GdiCachedProcessHandle : Ptr64 Void +# +0x7f0 GdiClientPID : Uint4B +# +0x7f4 GdiClientTID : Uint4B +# +0x7f8 GdiThreadLocalInfo : Ptr64 Void +# +0x800 Win32ClientInfo : [62] Uint8B +# +0x9f0 glDispatchTable : [233] Ptr64 Void +# +0x1138 glReserved1 : [29] Uint8B +# +0x1220 glReserved2 : Ptr64 Void +# +0x1228 glSectionInfo : Ptr64 Void +# +0x1230 glSection : Ptr64 Void +# +0x1238 glTable : Ptr64 Void +# +0x1240 glCurrentRC : Ptr64 Void +# +0x1248 glContext : Ptr64 Void +# +0x1250 LastStatusValue : Uint4B +# +0x1258 StaticUnicodeString : _UNICODE_STRING +# +0x1268 StaticUnicodeBuffer : [261] Wchar +# +0x1478 DeallocationStack : Ptr64 Void +# +0x1480 TlsSlots : [64] Ptr64 Void +# +0x1680 TlsLinks : _LIST_ENTRY +# +0x1690 Vdm : Ptr64 Void +# +0x1698 ReservedForNtRpc : Ptr64 Void +# +0x16a0 DbgSsReserved : [2] Ptr64 Void +# +0x16b0 HardErrorMode : Uint4B +# +0x16b8 Instrumentation : [11] Ptr64 Void +# +0x1710 ActivityId : _GUID +# +0x1720 SubProcessTag : Ptr64 Void +# +0x1728 EtwLocalData : Ptr64 Void +# +0x1730 EtwTraceData : Ptr64 Void +# +0x1738 WinSockData : Ptr64 Void +# +0x1740 GdiBatchCount : Uint4B +# +0x1744 SpareBool0 : UChar +# +0x1745 SpareBool1 : UChar +# +0x1746 SpareBool2 : UChar +# +0x1747 IdealProcessor : UChar +# +0x1748 GuaranteedStackBytes : Uint4B +# +0x1750 ReservedForPerf : Ptr64 Void +# +0x1758 ReservedForOle : Ptr64 Void +# +0x1760 WaitingOnLoaderLock : Uint4B +# +0x1768 SavedPriorityState : Ptr64 Void +# +0x1770 SoftPatchPtr1 : Uint8B +# +0x1778 ThreadPoolData : Ptr64 Void +# +0x1780 TlsExpansionSlots : Ptr64 Ptr64 Void +# +0x1788 DeallocationBStore : Ptr64 Void +# +0x1790 BStoreLimit : Ptr64 Void +# +0x1798 ImpersonationLocale : Uint4B +# +0x179c IsImpersonating : Uint4B +# +0x17a0 NlsCache : Ptr64 Void +# +0x17a8 pShimData : Ptr64 Void +# +0x17b0 HeapVirtualAffinity : Uint4B +# +0x17b8 CurrentTransactionHandle : Ptr64 Void +# +0x17c0 ActiveFrame : Ptr64 _TEB_ACTIVE_FRAME +# +0x17c8 FlsData : Ptr64 Void +# +0x17d0 PreferredLanguages : Ptr64 Void +# +0x17d8 UserPrefLanguages : Ptr64 Void +# +0x17e0 MergedPrefLanguages : Ptr64 Void +# +0x17e8 MuiImpersonation : Uint4B +# +0x17ec CrossTebFlags : Uint2B +# +0x17ec SpareCrossTebBits : Pos 0, 16 Bits +# +0x17ee SameTebFlags : Uint2B +# +0x17ee DbgSafeThunkCall : Pos 0, 1 Bit +# +0x17ee DbgInDebugPrint : Pos 1, 1 Bit +# +0x17ee DbgHasFiberData : Pos 2, 1 Bit +# +0x17ee DbgSkipThreadAttach : Pos 3, 1 Bit +# +0x17ee DbgWerInShipAssertCode : Pos 4, 1 Bit +# +0x17ee DbgRanProcessInit : Pos 5, 1 Bit +# +0x17ee DbgClonedThread : Pos 6, 1 Bit +# +0x17ee DbgSuppressDebugMsg : Pos 7, 1 Bit +# +0x17ee RtlDisableUserStackWalk : Pos 8, 1 Bit +# +0x17ee RtlExceptionAttached : Pos 9, 1 Bit +# +0x17ee SpareSameTebBits : Pos 10, 6 Bits +# +0x17f0 TxnScopeEnterCallback : Ptr64 Void +# +0x17f8 TxnScopeExitCallback : Ptr64 Void +# +0x1800 TxnScopeContext : Ptr64 Void +# +0x1808 LockCount : Uint4B +# +0x180c ProcessRundown : Uint4B +# +0x1810 LastSwitchTime : Uint8B +# +0x1818 TotalSwitchOutTime : Uint8B +# +0x1820 WaitReasonBitMap : _LARGE_INTEGER +class _TEB_2008_64(Structure): + _pack_ = 8 + _fields_ = [ + ("NtTib", NT_TIB), + ("EnvironmentPointer", PVOID), + ("ClientId", CLIENT_ID), + ("ActiveRpcHandle", HANDLE), + ("ThreadLocalStoragePointer", PVOID), + ("ProcessEnvironmentBlock", PVOID), # PPEB + ("LastErrorValue", DWORD), + ("CountOfOwnedCriticalSections", DWORD), + ("CsrClientThread", PVOID), + ("Win32ThreadInfo", PVOID), + ("User32Reserved", DWORD * 26), + ("UserReserved", DWORD * 5), + ("WOW32Reserved", PVOID), # ptr to wow64cpu!X86SwitchTo64BitMode + ("CurrentLocale", DWORD), + ("FpSoftwareStatusRegister", DWORD), + ("SystemReserved1", PVOID * 54), + ("ExceptionCode", SDWORD), + ("ActivationContextStackPointer", PVOID), # PACTIVATION_CONTEXT_STACK + ("SpareBytes1", UCHAR * 24), + ("TxFsContext", DWORD), + ("GdiTebBatch", GDI_TEB_BATCH), + ("RealClientId", CLIENT_ID), + ("GdiCachedProcessHandle", HANDLE), + ("GdiClientPID", DWORD), + ("GdiClientTID", DWORD), + ("GdiThreadLocalInfo", PVOID), + ("Win32ClientInfo", QWORD * 62), + ("glDispatchTable", PVOID * 233), + ("glReserved1", QWORD * 29), + ("glReserved2", PVOID), + ("glSectionInfo", PVOID), + ("glSection", PVOID), + ("glTable", PVOID), + ("glCurrentRC", PVOID), + ("glContext", PVOID), + ("LastStatusValue", NTSTATUS), + ("StaticUnicodeString", UNICODE_STRING), + ("StaticUnicodeBuffer", WCHAR * 261), + ("DeallocationStack", PVOID), + ("TlsSlots", PVOID * 64), + ("TlsLinks", LIST_ENTRY), + ("Vdm", PVOID), + ("ReservedForNtRpc", PVOID), + ("DbgSsReserved", PVOID * 2), + ("HardErrorMode", DWORD), + ("Instrumentation", PVOID * 11), + ("ActivityId", GUID), + ("SubProcessTag", PVOID), + ("EtwLocalData", PVOID), + ("EtwTraceData", PVOID), + ("WinSockData", PVOID), + ("GdiBatchCount", DWORD), + ("SpareBool0", BOOLEAN), + ("SpareBool1", BOOLEAN), + ("SpareBool2", BOOLEAN), + ("IdealProcessor", UCHAR), + ("GuaranteedStackBytes", DWORD), + ("ReservedForPerf", PVOID), + ("ReservedForOle", PVOID), + ("WaitingOnLoaderLock", DWORD), + ("SavedPriorityState", PVOID), + ("SoftPatchPtr1", PVOID), + ("ThreadPoolData", PVOID), + ("TlsExpansionSlots", PVOID), # Ptr64 Ptr64 Void + ("DeallocationBStore", PVOID), + ("BStoreLimit", PVOID), + ("ImpersonationLocale", DWORD), + ("IsImpersonating", BOOL), + ("NlsCache", PVOID), + ("pShimData", PVOID), + ("HeapVirtualAffinity", DWORD), + ("CurrentTransactionHandle", HANDLE), + ("ActiveFrame", PVOID), # PTEB_ACTIVE_FRAME + ("FlsData", PVOID), + ("PreferredLanguages", PVOID), + ("UserPrefLanguages", PVOID), + ("MergedPrefLanguages", PVOID), + ("MuiImpersonation", BOOL), + ("CrossTebFlags", WORD), + ("SameTebFlags", WORD), + ("TxnScopeEnterCallback", PVOID), + ("TxnScopeExitCallback", PVOID), + ("TxnScopeContext", PVOID), + ("LockCount", DWORD), + ("ProcessRundown", DWORD), + ("LastSwitchTime", QWORD), + ("TotalSwitchOutTime", QWORD), + ("WaitReasonBitMap", LONGLONG), # LARGE_INTEGER +] + +# +0x000 NtTib : _NT_TIB +# +0x01c EnvironmentPointer : Ptr32 Void +# +0x020 ClientId : _CLIENT_ID +# +0x028 ActiveRpcHandle : Ptr32 Void +# +0x02c ThreadLocalStoragePointer : Ptr32 Void +# +0x030 ProcessEnvironmentBlock : Ptr32 _PEB +# +0x034 LastErrorValue : Uint4B +# +0x038 CountOfOwnedCriticalSections : Uint4B +# +0x03c CsrClientThread : Ptr32 Void +# +0x040 Win32ThreadInfo : Ptr32 Void +# +0x044 User32Reserved : [26] Uint4B +# +0x0ac UserReserved : [5] Uint4B +# +0x0c0 WOW32Reserved : Ptr32 Void +# +0x0c4 CurrentLocale : Uint4B +# +0x0c8 FpSoftwareStatusRegister : Uint4B +# +0x0cc SystemReserved1 : [54] Ptr32 Void +# +0x1a4 ExceptionCode : Int4B +# +0x1a8 ActivationContextStackPointer : Ptr32 _ACTIVATION_CONTEXT_STACK +# +0x1ac SpareBytes : [36] UChar +# +0x1d0 TxFsContext : Uint4B +# +0x1d4 GdiTebBatch : _GDI_TEB_BATCH +# +0x6b4 RealClientId : _CLIENT_ID +# +0x6bc GdiCachedProcessHandle : Ptr32 Void +# +0x6c0 GdiClientPID : Uint4B +# +0x6c4 GdiClientTID : Uint4B +# +0x6c8 GdiThreadLocalInfo : Ptr32 Void +# +0x6cc Win32ClientInfo : [62] Uint4B +# +0x7c4 glDispatchTable : [233] Ptr32 Void +# +0xb68 glReserved1 : [29] Uint4B +# +0xbdc glReserved2 : Ptr32 Void +# +0xbe0 glSectionInfo : Ptr32 Void +# +0xbe4 glSection : Ptr32 Void +# +0xbe8 glTable : Ptr32 Void +# +0xbec glCurrentRC : Ptr32 Void +# +0xbf0 glContext : Ptr32 Void +# +0xbf4 LastStatusValue : Uint4B +# +0xbf8 StaticUnicodeString : _UNICODE_STRING +# +0xc00 StaticUnicodeBuffer : [261] Wchar +# +0xe0c DeallocationStack : Ptr32 Void +# +0xe10 TlsSlots : [64] Ptr32 Void +# +0xf10 TlsLinks : _LIST_ENTRY +# +0xf18 Vdm : Ptr32 Void +# +0xf1c ReservedForNtRpc : Ptr32 Void +# +0xf20 DbgSsReserved : [2] Ptr32 Void +# +0xf28 HardErrorMode : Uint4B +# +0xf2c Instrumentation : [9] Ptr32 Void +# +0xf50 ActivityId : _GUID +# +0xf60 SubProcessTag : Ptr32 Void +# +0xf64 EtwLocalData : Ptr32 Void +# +0xf68 EtwTraceData : Ptr32 Void +# +0xf6c WinSockData : Ptr32 Void +# +0xf70 GdiBatchCount : Uint4B +# +0xf74 CurrentIdealProcessor : _PROCESSOR_NUMBER +# +0xf74 IdealProcessorValue : Uint4B +# +0xf74 ReservedPad0 : UChar +# +0xf75 ReservedPad1 : UChar +# +0xf76 ReservedPad2 : UChar +# +0xf77 IdealProcessor : UChar +# +0xf78 GuaranteedStackBytes : Uint4B +# +0xf7c ReservedForPerf : Ptr32 Void +# +0xf80 ReservedForOle : Ptr32 Void +# +0xf84 WaitingOnLoaderLock : Uint4B +# +0xf88 SavedPriorityState : Ptr32 Void +# +0xf8c SoftPatchPtr1 : Uint4B +# +0xf90 ThreadPoolData : Ptr32 Void +# +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void +# +0xf98 MuiGeneration : Uint4B +# +0xf9c IsImpersonating : Uint4B +# +0xfa0 NlsCache : Ptr32 Void +# +0xfa4 pShimData : Ptr32 Void +# +0xfa8 HeapVirtualAffinity : Uint4B +# +0xfac CurrentTransactionHandle : Ptr32 Void +# +0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME +# +0xfb4 FlsData : Ptr32 Void +# +0xfb8 PreferredLanguages : Ptr32 Void +# +0xfbc UserPrefLanguages : Ptr32 Void +# +0xfc0 MergedPrefLanguages : Ptr32 Void +# +0xfc4 MuiImpersonation : Uint4B +# +0xfc8 CrossTebFlags : Uint2B +# +0xfc8 SpareCrossTebBits : Pos 0, 16 Bits +# +0xfca SameTebFlags : Uint2B +# +0xfca SafeThunkCall : Pos 0, 1 Bit +# +0xfca InDebugPrint : Pos 1, 1 Bit +# +0xfca HasFiberData : Pos 2, 1 Bit +# +0xfca SkipThreadAttach : Pos 3, 1 Bit +# +0xfca WerInShipAssertCode : Pos 4, 1 Bit +# +0xfca RanProcessInit : Pos 5, 1 Bit +# +0xfca ClonedThread : Pos 6, 1 Bit +# +0xfca SuppressDebugMsg : Pos 7, 1 Bit +# +0xfca DisableUserStackWalk : Pos 8, 1 Bit +# +0xfca RtlExceptionAttached : Pos 9, 1 Bit +# +0xfca InitialThread : Pos 10, 1 Bit +# +0xfca SpareSameTebBits : Pos 11, 5 Bits +# +0xfcc TxnScopeEnterCallback : Ptr32 Void +# +0xfd0 TxnScopeExitCallback : Ptr32 Void +# +0xfd4 TxnScopeContext : Ptr32 Void +# +0xfd8 LockCount : Uint4B +# +0xfdc SpareUlong0 : Uint4B +# +0xfe0 ResourceRetValue : Ptr32 Void +class _TEB_2008_R2(Structure): + _pack_ = 8 + _fields_ = [ + ("NtTib", NT_TIB), + ("EnvironmentPointer", PVOID), + ("ClientId", CLIENT_ID), + ("ActiveRpcHandle", HANDLE), + ("ThreadLocalStoragePointer", PVOID), + ("ProcessEnvironmentBlock", PVOID), # PPEB + ("LastErrorValue", DWORD), + ("CountOfOwnedCriticalSections", DWORD), + ("CsrClientThread", PVOID), + ("Win32ThreadInfo", PVOID), + ("User32Reserved", DWORD * 26), + ("UserReserved", DWORD * 5), + ("WOW32Reserved", PVOID), # ptr to wow64cpu!X86SwitchTo64BitMode + ("CurrentLocale", DWORD), + ("FpSoftwareStatusRegister", DWORD), + ("SystemReserved1", PVOID * 54), + ("ExceptionCode", SDWORD), + ("ActivationContextStackPointer", PVOID), # PACTIVATION_CONTEXT_STACK + ("SpareBytes", UCHAR * 36), + ("TxFsContext", DWORD), + ("GdiTebBatch", GDI_TEB_BATCH), + ("RealClientId", CLIENT_ID), + ("GdiCachedProcessHandle", HANDLE), + ("GdiClientPID", DWORD), + ("GdiClientTID", DWORD), + ("GdiThreadLocalInfo", PVOID), + ("Win32ClientInfo", DWORD * 62), + ("glDispatchTable", PVOID * 233), + ("glReserved1", DWORD * 29), + ("glReserved2", PVOID), + ("glSectionInfo", PVOID), + ("glSection", PVOID), + ("glTable", PVOID), + ("glCurrentRC", PVOID), + ("glContext", PVOID), + ("LastStatusValue", NTSTATUS), + ("StaticUnicodeString", UNICODE_STRING), + ("StaticUnicodeBuffer", WCHAR * 261), + ("DeallocationStack", PVOID), + ("TlsSlots", PVOID * 64), + ("TlsLinks", LIST_ENTRY), + ("Vdm", PVOID), + ("ReservedForNtRpc", PVOID), + ("DbgSsReserved", PVOID * 2), + ("HardErrorMode", DWORD), + ("Instrumentation", PVOID * 9), + ("ActivityId", GUID), + ("SubProcessTag", PVOID), + ("EtwLocalData", PVOID), + ("EtwTraceData", PVOID), + ("WinSockData", PVOID), + ("GdiBatchCount", DWORD), + ("CurrentIdealProcessor", PROCESSOR_NUMBER), + ("IdealProcessorValue", DWORD), + ("ReservedPad0", UCHAR), + ("ReservedPad1", UCHAR), + ("ReservedPad2", UCHAR), + ("IdealProcessor", UCHAR), + ("GuaranteedStackBytes", DWORD), + ("ReservedForPerf", PVOID), + ("ReservedForOle", PVOID), + ("WaitingOnLoaderLock", DWORD), + ("SavedPriorityState", PVOID), + ("SoftPatchPtr1", PVOID), + ("ThreadPoolData", PVOID), + ("TlsExpansionSlots", PVOID), # Ptr32 Ptr32 Void + ("MuiGeneration", DWORD), + ("IsImpersonating", BOOL), + ("NlsCache", PVOID), + ("pShimData", PVOID), + ("HeapVirtualAffinity", DWORD), + ("CurrentTransactionHandle", HANDLE), + ("ActiveFrame", PVOID), # PTEB_ACTIVE_FRAME + ("FlsData", PVOID), + ("PreferredLanguages", PVOID), + ("UserPrefLanguages", PVOID), + ("MergedPrefLanguages", PVOID), + ("MuiImpersonation", BOOL), + ("CrossTebFlags", WORD), + ("SameTebFlags", WORD), + ("TxnScopeEnterCallback", PVOID), + ("TxnScopeExitCallback", PVOID), + ("TxnScopeContext", PVOID), + ("LockCount", DWORD), + ("SpareUlong0", ULONG), + ("ResourceRetValue", PVOID), +] + +# +0x000 NtTib : _NT_TIB +# +0x038 EnvironmentPointer : Ptr64 Void +# +0x040 ClientId : _CLIENT_ID +# +0x050 ActiveRpcHandle : Ptr64 Void +# +0x058 ThreadLocalStoragePointer : Ptr64 Void +# +0x060 ProcessEnvironmentBlock : Ptr64 _PEB +# +0x068 LastErrorValue : Uint4B +# +0x06c CountOfOwnedCriticalSections : Uint4B +# +0x070 CsrClientThread : Ptr64 Void +# +0x078 Win32ThreadInfo : Ptr64 Void +# +0x080 User32Reserved : [26] Uint4B +# +0x0e8 UserReserved : [5] Uint4B +# +0x100 WOW32Reserved : Ptr64 Void +# +0x108 CurrentLocale : Uint4B +# +0x10c FpSoftwareStatusRegister : Uint4B +# +0x110 SystemReserved1 : [54] Ptr64 Void +# +0x2c0 ExceptionCode : Int4B +# +0x2c8 ActivationContextStackPointer : Ptr64 _ACTIVATION_CONTEXT_STACK +# +0x2d0 SpareBytes : [24] UChar +# +0x2e8 TxFsContext : Uint4B +# +0x2f0 GdiTebBatch : _GDI_TEB_BATCH +# +0x7d8 RealClientId : _CLIENT_ID +# +0x7e8 GdiCachedProcessHandle : Ptr64 Void +# +0x7f0 GdiClientPID : Uint4B +# +0x7f4 GdiClientTID : Uint4B +# +0x7f8 GdiThreadLocalInfo : Ptr64 Void +# +0x800 Win32ClientInfo : [62] Uint8B +# +0x9f0 glDispatchTable : [233] Ptr64 Void +# +0x1138 glReserved1 : [29] Uint8B +# +0x1220 glReserved2 : Ptr64 Void +# +0x1228 glSectionInfo : Ptr64 Void +# +0x1230 glSection : Ptr64 Void +# +0x1238 glTable : Ptr64 Void +# +0x1240 glCurrentRC : Ptr64 Void +# +0x1248 glContext : Ptr64 Void +# +0x1250 LastStatusValue : Uint4B +# +0x1258 StaticUnicodeString : _UNICODE_STRING +# +0x1268 StaticUnicodeBuffer : [261] Wchar +# +0x1478 DeallocationStack : Ptr64 Void +# +0x1480 TlsSlots : [64] Ptr64 Void +# +0x1680 TlsLinks : _LIST_ENTRY +# +0x1690 Vdm : Ptr64 Void +# +0x1698 ReservedForNtRpc : Ptr64 Void +# +0x16a0 DbgSsReserved : [2] Ptr64 Void +# +0x16b0 HardErrorMode : Uint4B +# +0x16b8 Instrumentation : [11] Ptr64 Void +# +0x1710 ActivityId : _GUID +# +0x1720 SubProcessTag : Ptr64 Void +# +0x1728 EtwLocalData : Ptr64 Void +# +0x1730 EtwTraceData : Ptr64 Void +# +0x1738 WinSockData : Ptr64 Void +# +0x1740 GdiBatchCount : Uint4B +# +0x1744 CurrentIdealProcessor : _PROCESSOR_NUMBER +# +0x1744 IdealProcessorValue : Uint4B +# +0x1744 ReservedPad0 : UChar +# +0x1745 ReservedPad1 : UChar +# +0x1746 ReservedPad2 : UChar +# +0x1747 IdealProcessor : UChar +# +0x1748 GuaranteedStackBytes : Uint4B +# +0x1750 ReservedForPerf : Ptr64 Void +# +0x1758 ReservedForOle : Ptr64 Void +# +0x1760 WaitingOnLoaderLock : Uint4B +# +0x1768 SavedPriorityState : Ptr64 Void +# +0x1770 SoftPatchPtr1 : Uint8B +# +0x1778 ThreadPoolData : Ptr64 Void +# +0x1780 TlsExpansionSlots : Ptr64 Ptr64 Void +# +0x1788 DeallocationBStore : Ptr64 Void +# +0x1790 BStoreLimit : Ptr64 Void +# +0x1798 MuiGeneration : Uint4B +# +0x179c IsImpersonating : Uint4B +# +0x17a0 NlsCache : Ptr64 Void +# +0x17a8 pShimData : Ptr64 Void +# +0x17b0 HeapVirtualAffinity : Uint4B +# +0x17b8 CurrentTransactionHandle : Ptr64 Void +# +0x17c0 ActiveFrame : Ptr64 _TEB_ACTIVE_FRAME +# +0x17c8 FlsData : Ptr64 Void +# +0x17d0 PreferredLanguages : Ptr64 Void +# +0x17d8 UserPrefLanguages : Ptr64 Void +# +0x17e0 MergedPrefLanguages : Ptr64 Void +# +0x17e8 MuiImpersonation : Uint4B +# +0x17ec CrossTebFlags : Uint2B +# +0x17ec SpareCrossTebBits : Pos 0, 16 Bits +# +0x17ee SameTebFlags : Uint2B +# +0x17ee SafeThunkCall : Pos 0, 1 Bit +# +0x17ee InDebugPrint : Pos 1, 1 Bit +# +0x17ee HasFiberData : Pos 2, 1 Bit +# +0x17ee SkipThreadAttach : Pos 3, 1 Bit +# +0x17ee WerInShipAssertCode : Pos 4, 1 Bit +# +0x17ee RanProcessInit : Pos 5, 1 Bit +# +0x17ee ClonedThread : Pos 6, 1 Bit +# +0x17ee SuppressDebugMsg : Pos 7, 1 Bit +# +0x17ee DisableUserStackWalk : Pos 8, 1 Bit +# +0x17ee RtlExceptionAttached : Pos 9, 1 Bit +# +0x17ee InitialThread : Pos 10, 1 Bit +# +0x17ee SpareSameTebBits : Pos 11, 5 Bits +# +0x17f0 TxnScopeEnterCallback : Ptr64 Void +# +0x17f8 TxnScopeExitCallback : Ptr64 Void +# +0x1800 TxnScopeContext : Ptr64 Void +# +0x1808 LockCount : Uint4B +# +0x180c SpareUlong0 : Uint4B +# +0x1810 ResourceRetValue : Ptr64 Void +class _TEB_2008_R2_64(Structure): + _pack_ = 8 + _fields_ = [ + ("NtTib", NT_TIB), + ("EnvironmentPointer", PVOID), + ("ClientId", CLIENT_ID), + ("ActiveRpcHandle", HANDLE), + ("ThreadLocalStoragePointer", PVOID), + ("ProcessEnvironmentBlock", PVOID), # PPEB + ("LastErrorValue", DWORD), + ("CountOfOwnedCriticalSections", DWORD), + ("CsrClientThread", PVOID), + ("Win32ThreadInfo", PVOID), + ("User32Reserved", DWORD * 26), + ("UserReserved", DWORD * 5), + ("WOW32Reserved", PVOID), # ptr to wow64cpu!X86SwitchTo64BitMode + ("CurrentLocale", DWORD), + ("FpSoftwareStatusRegister", DWORD), + ("SystemReserved1", PVOID * 54), + ("ExceptionCode", SDWORD), + ("ActivationContextStackPointer", PVOID), # PACTIVATION_CONTEXT_STACK + ("SpareBytes", UCHAR * 24), + ("TxFsContext", DWORD), + ("GdiTebBatch", GDI_TEB_BATCH), + ("RealClientId", CLIENT_ID), + ("GdiCachedProcessHandle", HANDLE), + ("GdiClientPID", DWORD), + ("GdiClientTID", DWORD), + ("GdiThreadLocalInfo", PVOID), + ("Win32ClientInfo", DWORD * 62), + ("glDispatchTable", PVOID * 233), + ("glReserved1", QWORD * 29), + ("glReserved2", PVOID), + ("glSectionInfo", PVOID), + ("glSection", PVOID), + ("glTable", PVOID), + ("glCurrentRC", PVOID), + ("glContext", PVOID), + ("LastStatusValue", NTSTATUS), + ("StaticUnicodeString", UNICODE_STRING), + ("StaticUnicodeBuffer", WCHAR * 261), + ("DeallocationStack", PVOID), + ("TlsSlots", PVOID * 64), + ("TlsLinks", LIST_ENTRY), + ("Vdm", PVOID), + ("ReservedForNtRpc", PVOID), + ("DbgSsReserved", PVOID * 2), + ("HardErrorMode", DWORD), + ("Instrumentation", PVOID * 11), + ("ActivityId", GUID), + ("SubProcessTag", PVOID), + ("EtwLocalData", PVOID), + ("EtwTraceData", PVOID), + ("WinSockData", PVOID), + ("GdiBatchCount", DWORD), + ("CurrentIdealProcessor", PROCESSOR_NUMBER), + ("IdealProcessorValue", DWORD), + ("ReservedPad0", UCHAR), + ("ReservedPad1", UCHAR), + ("ReservedPad2", UCHAR), + ("IdealProcessor", UCHAR), + ("GuaranteedStackBytes", DWORD), + ("ReservedForPerf", PVOID), + ("ReservedForOle", PVOID), + ("WaitingOnLoaderLock", DWORD), + ("SavedPriorityState", PVOID), + ("SoftPatchPtr1", PVOID), + ("ThreadPoolData", PVOID), + ("TlsExpansionSlots", PVOID), # Ptr64 Ptr64 Void + ("DeallocationBStore", PVOID), + ("BStoreLimit", PVOID), + ("MuiGeneration", DWORD), + ("IsImpersonating", BOOL), + ("NlsCache", PVOID), + ("pShimData", PVOID), + ("HeapVirtualAffinity", DWORD), + ("CurrentTransactionHandle", HANDLE), + ("ActiveFrame", PVOID), # PTEB_ACTIVE_FRAME + ("FlsData", PVOID), + ("PreferredLanguages", PVOID), + ("UserPrefLanguages", PVOID), + ("MergedPrefLanguages", PVOID), + ("MuiImpersonation", BOOL), + ("CrossTebFlags", WORD), + ("SameTebFlags", WORD), + ("TxnScopeEnterCallback", PVOID), + ("TxnScopeExitCallback", PVOID), + ("TxnScopeContext", PVOID), + ("LockCount", DWORD), + ("SpareUlong0", ULONG), + ("ResourceRetValue", PVOID), +] + +_TEB_Vista = _TEB_2008 +_TEB_Vista_64 = _TEB_2008_64 +_TEB_W7 = _TEB_2008_R2 +_TEB_W7_64 = _TEB_2008_R2_64 + +# Use the correct TEB structure definition. +# Defaults to the latest Windows version. +class TEB(Structure): + _pack_ = 8 + if os == 'Windows NT': + _pack_ = _TEB_NT._pack_ + _fields_ = _TEB_NT._fields_ + elif os == 'Windows 2000': + _pack_ = _TEB_2000._pack_ + _fields_ = _TEB_2000._fields_ + elif os == 'Windows XP': + _fields_ = _TEB_XP._fields_ + elif os == 'Windows XP (64 bits)': + _fields_ = _TEB_XP_64._fields_ + elif os == 'Windows 2003': + _fields_ = _TEB_2003._fields_ + elif os == 'Windows 2003 (64 bits)': + _fields_ = _TEB_2003_64._fields_ + elif os == 'Windows 2008': + _fields_ = _TEB_2008._fields_ + elif os == 'Windows 2008 (64 bits)': + _fields_ = _TEB_2008_64._fields_ + elif os == 'Windows 2003 R2': + _fields_ = _TEB_2003_R2._fields_ + elif os == 'Windows 2003 R2 (64 bits)': + _fields_ = _TEB_2003_R2_64._fields_ + elif os == 'Windows 2008 R2': + _fields_ = _TEB_2008_R2._fields_ + elif os == 'Windows 2008 R2 (64 bits)': + _fields_ = _TEB_2008_R2_64._fields_ + elif os == 'Windows Vista': + _fields_ = _TEB_Vista._fields_ + elif os == 'Windows Vista (64 bits)': + _fields_ = _TEB_Vista_64._fields_ + elif os == 'Windows 7': + _fields_ = _TEB_W7._fields_ + elif os == 'Windows 7 (64 bits)': + _fields_ = _TEB_W7_64._fields_ + elif sizeof(SIZE_T) == sizeof(DWORD): + _fields_ = _TEB_W7._fields_ + else: + _fields_ = _TEB_W7_64._fields_ +PTEB = POINTER(TEB) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/psapi.py b/pydevd_attach_to_process/winappdbg/win32/psapi.py new file mode 100644 index 0000000..e353c7f --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/psapi.py @@ -0,0 +1,387 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for psapi.dll in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- PSAPI structures and constants ------------------------------------------- + +LIST_MODULES_DEFAULT = 0x00 +LIST_MODULES_32BIT = 0x01 +LIST_MODULES_64BIT = 0x02 +LIST_MODULES_ALL = 0x03 + +# typedef struct _MODULEINFO { +# LPVOID lpBaseOfDll; +# DWORD SizeOfImage; +# LPVOID EntryPoint; +# } MODULEINFO, *LPMODULEINFO; +class MODULEINFO(Structure): + _fields_ = [ + ("lpBaseOfDll", LPVOID), # remote pointer + ("SizeOfImage", DWORD), + ("EntryPoint", LPVOID), # remote pointer +] +LPMODULEINFO = POINTER(MODULEINFO) + +#--- psapi.dll ---------------------------------------------------------------- + +# BOOL WINAPI EnumDeviceDrivers( +# __out LPVOID *lpImageBase, +# __in DWORD cb, +# __out LPDWORD lpcbNeeded +# ); +def EnumDeviceDrivers(): + _EnumDeviceDrivers = windll.psapi.EnumDeviceDrivers + _EnumDeviceDrivers.argtypes = [LPVOID, DWORD, LPDWORD] + _EnumDeviceDrivers.restype = bool + _EnumDeviceDrivers.errcheck = RaiseIfZero + + size = 0x1000 + lpcbNeeded = DWORD(size) + unit = sizeof(LPVOID) + while 1: + lpImageBase = (LPVOID * (size // unit))() + _EnumDeviceDrivers(byref(lpImageBase), lpcbNeeded, byref(lpcbNeeded)) + needed = lpcbNeeded.value + if needed <= size: + break + size = needed + return [ lpImageBase[index] for index in compat.xrange(0, (needed // unit)) ] + +# BOOL WINAPI EnumProcesses( +# __out DWORD *pProcessIds, +# __in DWORD cb, +# __out DWORD *pBytesReturned +# ); +def EnumProcesses(): + _EnumProcesses = windll.psapi.EnumProcesses + _EnumProcesses.argtypes = [LPVOID, DWORD, LPDWORD] + _EnumProcesses.restype = bool + _EnumProcesses.errcheck = RaiseIfZero + + size = 0x1000 + cbBytesReturned = DWORD() + unit = sizeof(DWORD) + while 1: + ProcessIds = (DWORD * (size // unit))() + cbBytesReturned.value = size + _EnumProcesses(byref(ProcessIds), cbBytesReturned, byref(cbBytesReturned)) + returned = cbBytesReturned.value + if returned < size: + break + size = size + 0x1000 + ProcessIdList = list() + for ProcessId in ProcessIds: + if ProcessId is None: + break + ProcessIdList.append(ProcessId) + return ProcessIdList + +# BOOL WINAPI EnumProcessModules( +# __in HANDLE hProcess, +# __out HMODULE *lphModule, +# __in DWORD cb, +# __out LPDWORD lpcbNeeded +# ); +def EnumProcessModules(hProcess): + _EnumProcessModules = windll.psapi.EnumProcessModules + _EnumProcessModules.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD] + _EnumProcessModules.restype = bool + _EnumProcessModules.errcheck = RaiseIfZero + + size = 0x1000 + lpcbNeeded = DWORD(size) + unit = sizeof(HMODULE) + while 1: + lphModule = (HMODULE * (size // unit))() + _EnumProcessModules(hProcess, byref(lphModule), lpcbNeeded, byref(lpcbNeeded)) + needed = lpcbNeeded.value + if needed <= size: + break + size = needed + return [ lphModule[index] for index in compat.xrange(0, int(needed // unit)) ] + +# BOOL WINAPI EnumProcessModulesEx( +# __in HANDLE hProcess, +# __out HMODULE *lphModule, +# __in DWORD cb, +# __out LPDWORD lpcbNeeded, +# __in DWORD dwFilterFlag +# ); +def EnumProcessModulesEx(hProcess, dwFilterFlag = LIST_MODULES_DEFAULT): + _EnumProcessModulesEx = windll.psapi.EnumProcessModulesEx + _EnumProcessModulesEx.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, DWORD] + _EnumProcessModulesEx.restype = bool + _EnumProcessModulesEx.errcheck = RaiseIfZero + + size = 0x1000 + lpcbNeeded = DWORD(size) + unit = sizeof(HMODULE) + while 1: + lphModule = (HMODULE * (size // unit))() + _EnumProcessModulesEx(hProcess, byref(lphModule), lpcbNeeded, byref(lpcbNeeded), dwFilterFlag) + needed = lpcbNeeded.value + if needed <= size: + break + size = needed + return [ lphModule[index] for index in compat.xrange(0, (needed // unit)) ] + +# DWORD WINAPI GetDeviceDriverBaseName( +# __in LPVOID ImageBase, +# __out LPTSTR lpBaseName, +# __in DWORD nSize +# ); +def GetDeviceDriverBaseNameA(ImageBase): + _GetDeviceDriverBaseNameA = windll.psapi.GetDeviceDriverBaseNameA + _GetDeviceDriverBaseNameA.argtypes = [LPVOID, LPSTR, DWORD] + _GetDeviceDriverBaseNameA.restype = DWORD + + nSize = MAX_PATH + while 1: + lpBaseName = ctypes.create_string_buffer("", nSize) + nCopied = _GetDeviceDriverBaseNameA(ImageBase, lpBaseName, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpBaseName.value + +def GetDeviceDriverBaseNameW(ImageBase): + _GetDeviceDriverBaseNameW = windll.psapi.GetDeviceDriverBaseNameW + _GetDeviceDriverBaseNameW.argtypes = [LPVOID, LPWSTR, DWORD] + _GetDeviceDriverBaseNameW.restype = DWORD + + nSize = MAX_PATH + while 1: + lpBaseName = ctypes.create_unicode_buffer(u"", nSize) + nCopied = _GetDeviceDriverBaseNameW(ImageBase, lpBaseName, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpBaseName.value + +GetDeviceDriverBaseName = GuessStringType(GetDeviceDriverBaseNameA, GetDeviceDriverBaseNameW) + +# DWORD WINAPI GetDeviceDriverFileName( +# __in LPVOID ImageBase, +# __out LPTSTR lpFilename, +# __in DWORD nSize +# ); +def GetDeviceDriverFileNameA(ImageBase): + _GetDeviceDriverFileNameA = windll.psapi.GetDeviceDriverFileNameA + _GetDeviceDriverFileNameA.argtypes = [LPVOID, LPSTR, DWORD] + _GetDeviceDriverFileNameA.restype = DWORD + + nSize = MAX_PATH + while 1: + lpFilename = ctypes.create_string_buffer("", nSize) + nCopied = ctypes.windll.psapi.GetDeviceDriverFileNameA(ImageBase, lpFilename, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpFilename.value + +def GetDeviceDriverFileNameW(ImageBase): + _GetDeviceDriverFileNameW = windll.psapi.GetDeviceDriverFileNameW + _GetDeviceDriverFileNameW.argtypes = [LPVOID, LPWSTR, DWORD] + _GetDeviceDriverFileNameW.restype = DWORD + + nSize = MAX_PATH + while 1: + lpFilename = ctypes.create_unicode_buffer(u"", nSize) + nCopied = ctypes.windll.psapi.GetDeviceDriverFileNameW(ImageBase, lpFilename, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpFilename.value + +GetDeviceDriverFileName = GuessStringType(GetDeviceDriverFileNameA, GetDeviceDriverFileNameW) + +# DWORD WINAPI GetMappedFileName( +# __in HANDLE hProcess, +# __in LPVOID lpv, +# __out LPTSTR lpFilename, +# __in DWORD nSize +# ); +def GetMappedFileNameA(hProcess, lpv): + _GetMappedFileNameA = ctypes.windll.psapi.GetMappedFileNameA + _GetMappedFileNameA.argtypes = [HANDLE, LPVOID, LPSTR, DWORD] + _GetMappedFileNameA.restype = DWORD + + nSize = MAX_PATH + while 1: + lpFilename = ctypes.create_string_buffer("", nSize) + nCopied = _GetMappedFileNameA(hProcess, lpv, lpFilename, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpFilename.value + +def GetMappedFileNameW(hProcess, lpv): + _GetMappedFileNameW = ctypes.windll.psapi.GetMappedFileNameW + _GetMappedFileNameW.argtypes = [HANDLE, LPVOID, LPWSTR, DWORD] + _GetMappedFileNameW.restype = DWORD + + nSize = MAX_PATH + while 1: + lpFilename = ctypes.create_unicode_buffer(u"", nSize) + nCopied = _GetMappedFileNameW(hProcess, lpv, lpFilename, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpFilename.value + +GetMappedFileName = GuessStringType(GetMappedFileNameA, GetMappedFileNameW) + +# DWORD WINAPI GetModuleFileNameEx( +# __in HANDLE hProcess, +# __in_opt HMODULE hModule, +# __out LPTSTR lpFilename, +# __in DWORD nSize +# ); +def GetModuleFileNameExA(hProcess, hModule = None): + _GetModuleFileNameExA = ctypes.windll.psapi.GetModuleFileNameExA + _GetModuleFileNameExA.argtypes = [HANDLE, HMODULE, LPSTR, DWORD] + _GetModuleFileNameExA.restype = DWORD + + nSize = MAX_PATH + while 1: + lpFilename = ctypes.create_string_buffer("", nSize) + nCopied = _GetModuleFileNameExA(hProcess, hModule, lpFilename, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpFilename.value + +def GetModuleFileNameExW(hProcess, hModule = None): + _GetModuleFileNameExW = ctypes.windll.psapi.GetModuleFileNameExW + _GetModuleFileNameExW.argtypes = [HANDLE, HMODULE, LPWSTR, DWORD] + _GetModuleFileNameExW.restype = DWORD + + nSize = MAX_PATH + while 1: + lpFilename = ctypes.create_unicode_buffer(u"", nSize) + nCopied = _GetModuleFileNameExW(hProcess, hModule, lpFilename, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpFilename.value + +GetModuleFileNameEx = GuessStringType(GetModuleFileNameExA, GetModuleFileNameExW) + +# BOOL WINAPI GetModuleInformation( +# __in HANDLE hProcess, +# __in HMODULE hModule, +# __out LPMODULEINFO lpmodinfo, +# __in DWORD cb +# ); +def GetModuleInformation(hProcess, hModule, lpmodinfo = None): + _GetModuleInformation = windll.psapi.GetModuleInformation + _GetModuleInformation.argtypes = [HANDLE, HMODULE, LPMODULEINFO, DWORD] + _GetModuleInformation.restype = bool + _GetModuleInformation.errcheck = RaiseIfZero + + if lpmodinfo is None: + lpmodinfo = MODULEINFO() + _GetModuleInformation(hProcess, hModule, byref(lpmodinfo), sizeof(lpmodinfo)) + return lpmodinfo + +# DWORD WINAPI GetProcessImageFileName( +# __in HANDLE hProcess, +# __out LPTSTR lpImageFileName, +# __in DWORD nSize +# ); +def GetProcessImageFileNameA(hProcess): + _GetProcessImageFileNameA = windll.psapi.GetProcessImageFileNameA + _GetProcessImageFileNameA.argtypes = [HANDLE, LPSTR, DWORD] + _GetProcessImageFileNameA.restype = DWORD + + nSize = MAX_PATH + while 1: + lpFilename = ctypes.create_string_buffer("", nSize) + nCopied = _GetProcessImageFileNameA(hProcess, lpFilename, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpFilename.value + +def GetProcessImageFileNameW(hProcess): + _GetProcessImageFileNameW = windll.psapi.GetProcessImageFileNameW + _GetProcessImageFileNameW.argtypes = [HANDLE, LPWSTR, DWORD] + _GetProcessImageFileNameW.restype = DWORD + + nSize = MAX_PATH + while 1: + lpFilename = ctypes.create_unicode_buffer(u"", nSize) + nCopied = _GetProcessImageFileNameW(hProcess, lpFilename, nSize) + if nCopied == 0: + raise ctypes.WinError() + if nCopied < (nSize - 1): + break + nSize = nSize + MAX_PATH + return lpFilename.value + +GetProcessImageFileName = GuessStringType(GetProcessImageFileNameA, GetProcessImageFileNameW) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/shell32.py b/pydevd_attach_to_process/winappdbg/win32/shell32.py new file mode 100644 index 0000000..5c945db --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/shell32.py @@ -0,0 +1,382 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for shell32.dll in ctypes. +""" + +# TODO +# * Add a class wrapper to SHELLEXECUTEINFO +# * More logic into ShellExecuteEx + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.kernel32 import LocalFree + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- Constants ---------------------------------------------------------------- + +SEE_MASK_DEFAULT = 0x00000000 +SEE_MASK_CLASSNAME = 0x00000001 +SEE_MASK_CLASSKEY = 0x00000003 +SEE_MASK_IDLIST = 0x00000004 +SEE_MASK_INVOKEIDLIST = 0x0000000C +SEE_MASK_ICON = 0x00000010 +SEE_MASK_HOTKEY = 0x00000020 +SEE_MASK_NOCLOSEPROCESS = 0x00000040 +SEE_MASK_CONNECTNETDRV = 0x00000080 +SEE_MASK_NOASYNC = 0x00000100 +SEE_MASK_DOENVSUBST = 0x00000200 +SEE_MASK_FLAG_NO_UI = 0x00000400 +SEE_MASK_UNICODE = 0x00004000 +SEE_MASK_NO_CONSOLE = 0x00008000 +SEE_MASK_ASYNCOK = 0x00100000 +SEE_MASK_HMONITOR = 0x00200000 +SEE_MASK_NOZONECHECKS = 0x00800000 +SEE_MASK_WAITFORINPUTIDLE = 0x02000000 +SEE_MASK_FLAG_LOG_USAGE = 0x04000000 + +SE_ERR_FNF = 2 +SE_ERR_PNF = 3 +SE_ERR_ACCESSDENIED = 5 +SE_ERR_OOM = 8 +SE_ERR_DLLNOTFOUND = 32 +SE_ERR_SHARE = 26 +SE_ERR_ASSOCINCOMPLETE = 27 +SE_ERR_DDETIMEOUT = 28 +SE_ERR_DDEFAIL = 29 +SE_ERR_DDEBUSY = 30 +SE_ERR_NOASSOC = 31 + +SHGFP_TYPE_CURRENT = 0 +SHGFP_TYPE_DEFAULT = 1 + +CSIDL_DESKTOP = 0x0000 +CSIDL_INTERNET = 0x0001 +CSIDL_PROGRAMS = 0x0002 +CSIDL_CONTROLS = 0x0003 +CSIDL_PRINTERS = 0x0004 +CSIDL_PERSONAL = 0x0005 +CSIDL_FAVORITES = 0x0006 +CSIDL_STARTUP = 0x0007 +CSIDL_RECENT = 0x0008 +CSIDL_SENDTO = 0x0009 +CSIDL_BITBUCKET = 0x000a +CSIDL_STARTMENU = 0x000b +CSIDL_MYDOCUMENTS = CSIDL_PERSONAL +CSIDL_MYMUSIC = 0x000d +CSIDL_MYVIDEO = 0x000e +CSIDL_DESKTOPDIRECTORY = 0x0010 +CSIDL_DRIVES = 0x0011 +CSIDL_NETWORK = 0x0012 +CSIDL_NETHOOD = 0x0013 +CSIDL_FONTS = 0x0014 +CSIDL_TEMPLATES = 0x0015 +CSIDL_COMMON_STARTMENU = 0x0016 +CSIDL_COMMON_PROGRAMS = 0x0017 +CSIDL_COMMON_STARTUP = 0x0018 +CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019 +CSIDL_APPDATA = 0x001a +CSIDL_PRINTHOOD = 0x001b +CSIDL_LOCAL_APPDATA = 0x001c +CSIDL_ALTSTARTUP = 0x001d +CSIDL_COMMON_ALTSTARTUP = 0x001e +CSIDL_COMMON_FAVORITES = 0x001f +CSIDL_INTERNET_CACHE = 0x0020 +CSIDL_COOKIES = 0x0021 +CSIDL_HISTORY = 0x0022 +CSIDL_COMMON_APPDATA = 0x0023 +CSIDL_WINDOWS = 0x0024 +CSIDL_SYSTEM = 0x0025 +CSIDL_PROGRAM_FILES = 0x0026 +CSIDL_MYPICTURES = 0x0027 +CSIDL_PROFILE = 0x0028 +CSIDL_SYSTEMX86 = 0x0029 +CSIDL_PROGRAM_FILESX86 = 0x002a +CSIDL_PROGRAM_FILES_COMMON = 0x002b +CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c +CSIDL_COMMON_TEMPLATES = 0x002d +CSIDL_COMMON_DOCUMENTS = 0x002e +CSIDL_COMMON_ADMINTOOLS = 0x002f +CSIDL_ADMINTOOLS = 0x0030 +CSIDL_CONNECTIONS = 0x0031 +CSIDL_COMMON_MUSIC = 0x0035 +CSIDL_COMMON_PICTURES = 0x0036 +CSIDL_COMMON_VIDEO = 0x0037 +CSIDL_RESOURCES = 0x0038 +CSIDL_RESOURCES_LOCALIZED = 0x0039 +CSIDL_COMMON_OEM_LINKS = 0x003a +CSIDL_CDBURN_AREA = 0x003b +CSIDL_COMPUTERSNEARME = 0x003d +CSIDL_PROFILES = 0x003e + +CSIDL_FOLDER_MASK = 0x00ff + +CSIDL_FLAG_PER_USER_INIT = 0x0800 +CSIDL_FLAG_NO_ALIAS = 0x1000 +CSIDL_FLAG_DONT_VERIFY = 0x4000 +CSIDL_FLAG_CREATE = 0x8000 + +CSIDL_FLAG_MASK = 0xff00 + +#--- Structures --------------------------------------------------------------- + +# typedef struct _SHELLEXECUTEINFO { +# DWORD cbSize; +# ULONG fMask; +# HWND hwnd; +# LPCTSTR lpVerb; +# LPCTSTR lpFile; +# LPCTSTR lpParameters; +# LPCTSTR lpDirectory; +# int nShow; +# HINSTANCE hInstApp; +# LPVOID lpIDList; +# LPCTSTR lpClass; +# HKEY hkeyClass; +# DWORD dwHotKey; +# union { +# HANDLE hIcon; +# HANDLE hMonitor; +# } DUMMYUNIONNAME; +# HANDLE hProcess; +# } SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO; + +class SHELLEXECUTEINFO(Structure): + _fields_ = [ + ("cbSize", DWORD), + ("fMask", ULONG), + ("hwnd", HWND), + ("lpVerb", LPSTR), + ("lpFile", LPSTR), + ("lpParameters", LPSTR), + ("lpDirectory", LPSTR), + ("nShow", ctypes.c_int), + ("hInstApp", HINSTANCE), + ("lpIDList", LPVOID), + ("lpClass", LPSTR), + ("hkeyClass", HKEY), + ("dwHotKey", DWORD), + ("hIcon", HANDLE), + ("hProcess", HANDLE), + ] + + def __get_hMonitor(self): + return self.hIcon + def __set_hMonitor(self, hMonitor): + self.hIcon = hMonitor + hMonitor = property(__get_hMonitor, __set_hMonitor) + +LPSHELLEXECUTEINFO = POINTER(SHELLEXECUTEINFO) + +#--- shell32.dll -------------------------------------------------------------- + +# LPWSTR *CommandLineToArgvW( +# LPCWSTR lpCmdLine, +# int *pNumArgs +# ); +def CommandLineToArgvW(lpCmdLine): + _CommandLineToArgvW = windll.shell32.CommandLineToArgvW + _CommandLineToArgvW.argtypes = [LPVOID, POINTER(ctypes.c_int)] + _CommandLineToArgvW.restype = LPVOID + + if not lpCmdLine: + lpCmdLine = None + argc = ctypes.c_int(0) + vptr = ctypes.windll.shell32.CommandLineToArgvW(lpCmdLine, byref(argc)) + if vptr == NULL: + raise ctypes.WinError() + argv = vptr + try: + argc = argc.value + if argc <= 0: + raise ctypes.WinError() + argv = ctypes.cast(argv, ctypes.POINTER(LPWSTR * argc) ) + argv = [ argv.contents[i] for i in compat.xrange(0, argc) ] + finally: + if vptr is not None: + LocalFree(vptr) + return argv + +def CommandLineToArgvA(lpCmdLine): + t_ansi = GuessStringType.t_ansi + t_unicode = GuessStringType.t_unicode + if isinstance(lpCmdLine, t_ansi): + cmdline = t_unicode(lpCmdLine) + else: + cmdline = lpCmdLine + return [t_ansi(x) for x in CommandLineToArgvW(cmdline)] + +CommandLineToArgv = GuessStringType(CommandLineToArgvA, CommandLineToArgvW) + +# HINSTANCE ShellExecute( +# HWND hwnd, +# LPCTSTR lpOperation, +# LPCTSTR lpFile, +# LPCTSTR lpParameters, +# LPCTSTR lpDirectory, +# INT nShowCmd +# ); +def ShellExecuteA(hwnd = None, lpOperation = None, lpFile = None, lpParameters = None, lpDirectory = None, nShowCmd = None): + _ShellExecuteA = windll.shell32.ShellExecuteA + _ShellExecuteA.argtypes = [HWND, LPSTR, LPSTR, LPSTR, LPSTR, INT] + _ShellExecuteA.restype = HINSTANCE + + if not nShowCmd: + nShowCmd = 0 + success = _ShellExecuteA(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd) + success = ctypes.cast(success, c_int) + success = success.value + if not success > 32: # weird! isn't it? + raise ctypes.WinError(success) + +def ShellExecuteW(hwnd = None, lpOperation = None, lpFile = None, lpParameters = None, lpDirectory = None, nShowCmd = None): + _ShellExecuteW = windll.shell32.ShellExecuteW + _ShellExecuteW.argtypes = [HWND, LPWSTR, LPWSTR, LPWSTR, LPWSTR, INT] + _ShellExecuteW.restype = HINSTANCE + + if not nShowCmd: + nShowCmd = 0 + success = _ShellExecuteW(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd) + success = ctypes.cast(success, c_int) + success = success.value + if not success > 32: # weird! isn't it? + raise ctypes.WinError(success) + +ShellExecute = GuessStringType(ShellExecuteA, ShellExecuteW) + +# BOOL ShellExecuteEx( +# __inout LPSHELLEXECUTEINFO lpExecInfo +# ); +def ShellExecuteEx(lpExecInfo): + if isinstance(lpExecInfo, SHELLEXECUTEINFOA): + ShellExecuteExA(lpExecInfo) + elif isinstance(lpExecInfo, SHELLEXECUTEINFOW): + ShellExecuteExW(lpExecInfo) + else: + raise TypeError("Expected SHELLEXECUTEINFOA or SHELLEXECUTEINFOW, got %s instead" % type(lpExecInfo)) + +def ShellExecuteExA(lpExecInfo): + _ShellExecuteExA = windll.shell32.ShellExecuteExA + _ShellExecuteExA.argtypes = [LPSHELLEXECUTEINFOA] + _ShellExecuteExA.restype = BOOL + _ShellExecuteExA.errcheck = RaiseIfZero + _ShellExecuteExA(byref(lpExecInfo)) + +def ShellExecuteExW(lpExecInfo): + _ShellExecuteExW = windll.shell32.ShellExecuteExW + _ShellExecuteExW.argtypes = [LPSHELLEXECUTEINFOW] + _ShellExecuteExW.restype = BOOL + _ShellExecuteExW.errcheck = RaiseIfZero + _ShellExecuteExW(byref(lpExecInfo)) + +# HINSTANCE FindExecutable( +# __in LPCTSTR lpFile, +# __in_opt LPCTSTR lpDirectory, +# __out LPTSTR lpResult +# ); +def FindExecutableA(lpFile, lpDirectory = None): + _FindExecutableA = windll.shell32.FindExecutableA + _FindExecutableA.argtypes = [LPSTR, LPSTR, LPSTR] + _FindExecutableA.restype = HINSTANCE + + lpResult = ctypes.create_string_buffer(MAX_PATH) + success = _FindExecutableA(lpFile, lpDirectory, lpResult) + success = ctypes.cast(success, ctypes.c_void_p) + success = success.value + if not success > 32: # weird! isn't it? + raise ctypes.WinError(success) + return lpResult.value + +def FindExecutableW(lpFile, lpDirectory = None): + _FindExecutableW = windll.shell32.FindExecutableW + _FindExecutableW.argtypes = [LPWSTR, LPWSTR, LPWSTR] + _FindExecutableW.restype = HINSTANCE + + lpResult = ctypes.create_unicode_buffer(MAX_PATH) + success = _FindExecutableW(lpFile, lpDirectory, lpResult) + success = ctypes.cast(success, ctypes.c_void_p) + success = success.value + if not success > 32: # weird! isn't it? + raise ctypes.WinError(success) + return lpResult.value + +FindExecutable = GuessStringType(FindExecutableA, FindExecutableW) + +# HRESULT SHGetFolderPath( +# __in HWND hwndOwner, +# __in int nFolder, +# __in HANDLE hToken, +# __in DWORD dwFlags, +# __out LPTSTR pszPath +# ); +def SHGetFolderPathA(nFolder, hToken = None, dwFlags = SHGFP_TYPE_CURRENT): + _SHGetFolderPathA = windll.shell32.SHGetFolderPathA # shfolder.dll in older win versions + _SHGetFolderPathA.argtypes = [HWND, ctypes.c_int, HANDLE, DWORD, LPSTR] + _SHGetFolderPathA.restype = HRESULT + _SHGetFolderPathA.errcheck = RaiseIfNotZero # S_OK == 0 + + pszPath = ctypes.create_string_buffer(MAX_PATH + 1) + _SHGetFolderPathA(None, nFolder, hToken, dwFlags, pszPath) + return pszPath.value + +def SHGetFolderPathW(nFolder, hToken = None, dwFlags = SHGFP_TYPE_CURRENT): + _SHGetFolderPathW = windll.shell32.SHGetFolderPathW # shfolder.dll in older win versions + _SHGetFolderPathW.argtypes = [HWND, ctypes.c_int, HANDLE, DWORD, LPWSTR] + _SHGetFolderPathW.restype = HRESULT + _SHGetFolderPathW.errcheck = RaiseIfNotZero # S_OK == 0 + + pszPath = ctypes.create_unicode_buffer(MAX_PATH + 1) + _SHGetFolderPathW(None, nFolder, hToken, dwFlags, pszPath) + return pszPath.value + +SHGetFolderPath = DefaultStringType(SHGetFolderPathA, SHGetFolderPathW) + +# BOOL IsUserAnAdmin(void); +def IsUserAnAdmin(): + # Supposedly, IsUserAnAdmin() is deprecated in Vista. + # But I tried it on Windows 7 and it works just fine. + _IsUserAnAdmin = windll.shell32.IsUserAnAdmin + _IsUserAnAdmin.argtypes = [] + _IsUserAnAdmin.restype = bool + return _IsUserAnAdmin() + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/shlwapi.py b/pydevd_attach_to_process/winappdbg/win32/shlwapi.py new file mode 100644 index 0000000..5f6eb3e --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/shlwapi.py @@ -0,0 +1,756 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for shlwapi.dll in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.kernel32 import * + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +OS_WINDOWS = 0 +OS_NT = 1 +OS_WIN95ORGREATER = 2 +OS_NT4ORGREATER = 3 +OS_WIN98ORGREATER = 5 +OS_WIN98_GOLD = 6 +OS_WIN2000ORGREATER = 7 +OS_WIN2000PRO = 8 +OS_WIN2000SERVER = 9 +OS_WIN2000ADVSERVER = 10 +OS_WIN2000DATACENTER = 11 +OS_WIN2000TERMINAL = 12 +OS_EMBEDDED = 13 +OS_TERMINALCLIENT = 14 +OS_TERMINALREMOTEADMIN = 15 +OS_WIN95_GOLD = 16 +OS_MEORGREATER = 17 +OS_XPORGREATER = 18 +OS_HOME = 19 +OS_PROFESSIONAL = 20 +OS_DATACENTER = 21 +OS_ADVSERVER = 22 +OS_SERVER = 23 +OS_TERMINALSERVER = 24 +OS_PERSONALTERMINALSERVER = 25 +OS_FASTUSERSWITCHING = 26 +OS_WELCOMELOGONUI = 27 +OS_DOMAINMEMBER = 28 +OS_ANYSERVER = 29 +OS_WOW6432 = 30 +OS_WEBSERVER = 31 +OS_SMALLBUSINESSSERVER = 32 +OS_TABLETPC = 33 +OS_SERVERADMINUI = 34 +OS_MEDIACENTER = 35 +OS_APPLIANCE = 36 + +#--- shlwapi.dll -------------------------------------------------------------- + +# BOOL IsOS( +# DWORD dwOS +# ); +def IsOS(dwOS): + try: + _IsOS = windll.shlwapi.IsOS + _IsOS.argtypes = [DWORD] + _IsOS.restype = bool + except AttributeError: + # According to MSDN, on Windows versions prior to Vista + # this function is exported only by ordinal number 437. + # http://msdn.microsoft.com/en-us/library/bb773795%28VS.85%29.aspx + _GetProcAddress = windll.kernel32.GetProcAddress + _GetProcAddress.argtypes = [HINSTANCE, DWORD] + _GetProcAddress.restype = LPVOID + _IsOS = windll.kernel32.GetProcAddress(windll.shlwapi._handle, 437) + _IsOS = WINFUNCTYPE(bool, DWORD)(_IsOS) + return _IsOS(dwOS) + +# LPTSTR PathAddBackslash( +# LPTSTR lpszPath +# ); +def PathAddBackslashA(lpszPath): + _PathAddBackslashA = windll.shlwapi.PathAddBackslashA + _PathAddBackslashA.argtypes = [LPSTR] + _PathAddBackslashA.restype = LPSTR + + lpszPath = ctypes.create_string_buffer(lpszPath, MAX_PATH) + retval = _PathAddBackslashA(lpszPath) + if retval == NULL: + raise ctypes.WinError() + return lpszPath.value + +def PathAddBackslashW(lpszPath): + _PathAddBackslashW = windll.shlwapi.PathAddBackslashW + _PathAddBackslashW.argtypes = [LPWSTR] + _PathAddBackslashW.restype = LPWSTR + + lpszPath = ctypes.create_unicode_buffer(lpszPath, MAX_PATH) + retval = _PathAddBackslashW(lpszPath) + if retval == NULL: + raise ctypes.WinError() + return lpszPath.value + +PathAddBackslash = GuessStringType(PathAddBackslashA, PathAddBackslashW) + +# BOOL PathAddExtension( +# LPTSTR pszPath, +# LPCTSTR pszExtension +# ); +def PathAddExtensionA(lpszPath, pszExtension = None): + _PathAddExtensionA = windll.shlwapi.PathAddExtensionA + _PathAddExtensionA.argtypes = [LPSTR, LPSTR] + _PathAddExtensionA.restype = bool + _PathAddExtensionA.errcheck = RaiseIfZero + + if not pszExtension: + pszExtension = None + lpszPath = ctypes.create_string_buffer(lpszPath, MAX_PATH) + _PathAddExtensionA(lpszPath, pszExtension) + return lpszPath.value + +def PathAddExtensionW(lpszPath, pszExtension = None): + _PathAddExtensionW = windll.shlwapi.PathAddExtensionW + _PathAddExtensionW.argtypes = [LPWSTR, LPWSTR] + _PathAddExtensionW.restype = bool + _PathAddExtensionW.errcheck = RaiseIfZero + + if not pszExtension: + pszExtension = None + lpszPath = ctypes.create_unicode_buffer(lpszPath, MAX_PATH) + _PathAddExtensionW(lpszPath, pszExtension) + return lpszPath.value + +PathAddExtension = GuessStringType(PathAddExtensionA, PathAddExtensionW) + +# BOOL PathAppend( +# LPTSTR pszPath, +# LPCTSTR pszMore +# ); +def PathAppendA(lpszPath, pszMore = None): + _PathAppendA = windll.shlwapi.PathAppendA + _PathAppendA.argtypes = [LPSTR, LPSTR] + _PathAppendA.restype = bool + _PathAppendA.errcheck = RaiseIfZero + + if not pszMore: + pszMore = None + lpszPath = ctypes.create_string_buffer(lpszPath, MAX_PATH) + _PathAppendA(lpszPath, pszMore) + return lpszPath.value + +def PathAppendW(lpszPath, pszMore = None): + _PathAppendW = windll.shlwapi.PathAppendW + _PathAppendW.argtypes = [LPWSTR, LPWSTR] + _PathAppendW.restype = bool + _PathAppendW.errcheck = RaiseIfZero + + if not pszMore: + pszMore = None + lpszPath = ctypes.create_unicode_buffer(lpszPath, MAX_PATH) + _PathAppendW(lpszPath, pszMore) + return lpszPath.value + +PathAppend = GuessStringType(PathAppendA, PathAppendW) + +# LPTSTR PathCombine( +# LPTSTR lpszDest, +# LPCTSTR lpszDir, +# LPCTSTR lpszFile +# ); +def PathCombineA(lpszDir, lpszFile): + _PathCombineA = windll.shlwapi.PathCombineA + _PathCombineA.argtypes = [LPSTR, LPSTR, LPSTR] + _PathCombineA.restype = LPSTR + + lpszDest = ctypes.create_string_buffer("", max(MAX_PATH, len(lpszDir) + len(lpszFile) + 1)) + retval = _PathCombineA(lpszDest, lpszDir, lpszFile) + if retval == NULL: + return None + return lpszDest.value + +def PathCombineW(lpszDir, lpszFile): + _PathCombineW = windll.shlwapi.PathCombineW + _PathCombineW.argtypes = [LPWSTR, LPWSTR, LPWSTR] + _PathCombineW.restype = LPWSTR + + lpszDest = ctypes.create_unicode_buffer(u"", max(MAX_PATH, len(lpszDir) + len(lpszFile) + 1)) + retval = _PathCombineW(lpszDest, lpszDir, lpszFile) + if retval == NULL: + return None + return lpszDest.value + +PathCombine = GuessStringType(PathCombineA, PathCombineW) + +# BOOL PathCanonicalize( +# LPTSTR lpszDst, +# LPCTSTR lpszSrc +# ); +def PathCanonicalizeA(lpszSrc): + _PathCanonicalizeA = windll.shlwapi.PathCanonicalizeA + _PathCanonicalizeA.argtypes = [LPSTR, LPSTR] + _PathCanonicalizeA.restype = bool + _PathCanonicalizeA.errcheck = RaiseIfZero + + lpszDst = ctypes.create_string_buffer("", MAX_PATH) + _PathCanonicalizeA(lpszDst, lpszSrc) + return lpszDst.value + +def PathCanonicalizeW(lpszSrc): + _PathCanonicalizeW = windll.shlwapi.PathCanonicalizeW + _PathCanonicalizeW.argtypes = [LPWSTR, LPWSTR] + _PathCanonicalizeW.restype = bool + _PathCanonicalizeW.errcheck = RaiseIfZero + + lpszDst = ctypes.create_unicode_buffer(u"", MAX_PATH) + _PathCanonicalizeW(lpszDst, lpszSrc) + return lpszDst.value + +PathCanonicalize = GuessStringType(PathCanonicalizeA, PathCanonicalizeW) + +# BOOL PathRelativePathTo( +# _Out_ LPTSTR pszPath, +# _In_ LPCTSTR pszFrom, +# _In_ DWORD dwAttrFrom, +# _In_ LPCTSTR pszTo, +# _In_ DWORD dwAttrTo +# ); +def PathRelativePathToA(pszFrom = None, dwAttrFrom = FILE_ATTRIBUTE_DIRECTORY, pszTo = None, dwAttrTo = FILE_ATTRIBUTE_DIRECTORY): + _PathRelativePathToA = windll.shlwapi.PathRelativePathToA + _PathRelativePathToA.argtypes = [LPSTR, LPSTR, DWORD, LPSTR, DWORD] + _PathRelativePathToA.restype = bool + _PathRelativePathToA.errcheck = RaiseIfZero + + # Make the paths absolute or the function fails. + if pszFrom: + pszFrom = GetFullPathNameA(pszFrom)[0] + else: + pszFrom = GetCurrentDirectoryA() + if pszTo: + pszTo = GetFullPathNameA(pszTo)[0] + else: + pszTo = GetCurrentDirectoryA() + + # Argh, this function doesn't receive an output buffer size! + # We'll try to guess the maximum possible buffer size. + dwPath = max((len(pszFrom) + len(pszTo)) * 2 + 1, MAX_PATH + 1) + pszPath = ctypes.create_string_buffer('', dwPath) + + # Also, it doesn't set the last error value. + # Whoever coded it must have been drunk or tripping on acid. Or both. + # The only failure conditions I've seen were invalid paths, paths not + # on the same drive, or the path is not absolute. + SetLastError(ERROR_INVALID_PARAMETER) + + _PathRelativePathToA(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo) + return pszPath.value + +def PathRelativePathToW(pszFrom = None, dwAttrFrom = FILE_ATTRIBUTE_DIRECTORY, pszTo = None, dwAttrTo = FILE_ATTRIBUTE_DIRECTORY): + _PathRelativePathToW = windll.shlwapi.PathRelativePathToW + _PathRelativePathToW.argtypes = [LPWSTR, LPWSTR, DWORD, LPWSTR, DWORD] + _PathRelativePathToW.restype = bool + _PathRelativePathToW.errcheck = RaiseIfZero + + # Refer to PathRelativePathToA to know why this code is so ugly. + if pszFrom: + pszFrom = GetFullPathNameW(pszFrom)[0] + else: + pszFrom = GetCurrentDirectoryW() + if pszTo: + pszTo = GetFullPathNameW(pszTo)[0] + else: + pszTo = GetCurrentDirectoryW() + dwPath = max((len(pszFrom) + len(pszTo)) * 2 + 1, MAX_PATH + 1) + pszPath = ctypes.create_unicode_buffer(u'', dwPath) + SetLastError(ERROR_INVALID_PARAMETER) + _PathRelativePathToW(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo) + return pszPath.value + +PathRelativePathTo = GuessStringType(PathRelativePathToA, PathRelativePathToW) + +# BOOL PathFileExists( +# LPCTSTR pszPath +# ); +def PathFileExistsA(pszPath): + _PathFileExistsA = windll.shlwapi.PathFileExistsA + _PathFileExistsA.argtypes = [LPSTR] + _PathFileExistsA.restype = bool + return _PathFileExistsA(pszPath) + +def PathFileExistsW(pszPath): + _PathFileExistsW = windll.shlwapi.PathFileExistsW + _PathFileExistsW.argtypes = [LPWSTR] + _PathFileExistsW.restype = bool + return _PathFileExistsW(pszPath) + +PathFileExists = GuessStringType(PathFileExistsA, PathFileExistsW) + +# LPTSTR PathFindExtension( +# LPCTSTR pszPath +# ); +def PathFindExtensionA(pszPath): + _PathFindExtensionA = windll.shlwapi.PathFindExtensionA + _PathFindExtensionA.argtypes = [LPSTR] + _PathFindExtensionA.restype = LPSTR + pszPath = ctypes.create_string_buffer(pszPath) + return _PathFindExtensionA(pszPath) + +def PathFindExtensionW(pszPath): + _PathFindExtensionW = windll.shlwapi.PathFindExtensionW + _PathFindExtensionW.argtypes = [LPWSTR] + _PathFindExtensionW.restype = LPWSTR + pszPath = ctypes.create_unicode_buffer(pszPath) + return _PathFindExtensionW(pszPath) + +PathFindExtension = GuessStringType(PathFindExtensionA, PathFindExtensionW) + +# LPTSTR PathFindFileName( +# LPCTSTR pszPath +# ); +def PathFindFileNameA(pszPath): + _PathFindFileNameA = windll.shlwapi.PathFindFileNameA + _PathFindFileNameA.argtypes = [LPSTR] + _PathFindFileNameA.restype = LPSTR + pszPath = ctypes.create_string_buffer(pszPath) + return _PathFindFileNameA(pszPath) + +def PathFindFileNameW(pszPath): + _PathFindFileNameW = windll.shlwapi.PathFindFileNameW + _PathFindFileNameW.argtypes = [LPWSTR] + _PathFindFileNameW.restype = LPWSTR + pszPath = ctypes.create_unicode_buffer(pszPath) + return _PathFindFileNameW(pszPath) + +PathFindFileName = GuessStringType(PathFindFileNameA, PathFindFileNameW) + +# LPTSTR PathFindNextComponent( +# LPCTSTR pszPath +# ); +def PathFindNextComponentA(pszPath): + _PathFindNextComponentA = windll.shlwapi.PathFindNextComponentA + _PathFindNextComponentA.argtypes = [LPSTR] + _PathFindNextComponentA.restype = LPSTR + pszPath = ctypes.create_string_buffer(pszPath) + return _PathFindNextComponentA(pszPath) + +def PathFindNextComponentW(pszPath): + _PathFindNextComponentW = windll.shlwapi.PathFindNextComponentW + _PathFindNextComponentW.argtypes = [LPWSTR] + _PathFindNextComponentW.restype = LPWSTR + pszPath = ctypes.create_unicode_buffer(pszPath) + return _PathFindNextComponentW(pszPath) + +PathFindNextComponent = GuessStringType(PathFindNextComponentA, PathFindNextComponentW) + +# BOOL PathFindOnPath( +# LPTSTR pszFile, +# LPCTSTR *ppszOtherDirs +# ); +def PathFindOnPathA(pszFile, ppszOtherDirs = None): + _PathFindOnPathA = windll.shlwapi.PathFindOnPathA + _PathFindOnPathA.argtypes = [LPSTR, LPSTR] + _PathFindOnPathA.restype = bool + + pszFile = ctypes.create_string_buffer(pszFile, MAX_PATH) + if not ppszOtherDirs: + ppszOtherDirs = None + else: + szArray = "" + for pszOtherDirs in ppszOtherDirs: + if pszOtherDirs: + szArray = "%s%s\0" % (szArray, pszOtherDirs) + szArray = szArray + "\0" + pszOtherDirs = ctypes.create_string_buffer(szArray) + ppszOtherDirs = ctypes.pointer(pszOtherDirs) + if _PathFindOnPathA(pszFile, ppszOtherDirs): + return pszFile.value + return None + +def PathFindOnPathW(pszFile, ppszOtherDirs = None): + _PathFindOnPathW = windll.shlwapi.PathFindOnPathA + _PathFindOnPathW.argtypes = [LPWSTR, LPWSTR] + _PathFindOnPathW.restype = bool + + pszFile = ctypes.create_unicode_buffer(pszFile, MAX_PATH) + if not ppszOtherDirs: + ppszOtherDirs = None + else: + szArray = u"" + for pszOtherDirs in ppszOtherDirs: + if pszOtherDirs: + szArray = u"%s%s\0" % (szArray, pszOtherDirs) + szArray = szArray + u"\0" + pszOtherDirs = ctypes.create_unicode_buffer(szArray) + ppszOtherDirs = ctypes.pointer(pszOtherDirs) + if _PathFindOnPathW(pszFile, ppszOtherDirs): + return pszFile.value + return None + +PathFindOnPath = GuessStringType(PathFindOnPathA, PathFindOnPathW) + +# LPTSTR PathGetArgs( +# LPCTSTR pszPath +# ); +def PathGetArgsA(pszPath): + _PathGetArgsA = windll.shlwapi.PathGetArgsA + _PathGetArgsA.argtypes = [LPSTR] + _PathGetArgsA.restype = LPSTR + pszPath = ctypes.create_string_buffer(pszPath) + return _PathGetArgsA(pszPath) + +def PathGetArgsW(pszPath): + _PathGetArgsW = windll.shlwapi.PathGetArgsW + _PathGetArgsW.argtypes = [LPWSTR] + _PathGetArgsW.restype = LPWSTR + pszPath = ctypes.create_unicode_buffer(pszPath) + return _PathGetArgsW(pszPath) + +PathGetArgs = GuessStringType(PathGetArgsA, PathGetArgsW) + +# BOOL PathIsContentType( +# LPCTSTR pszPath, +# LPCTSTR pszContentType +# ); +def PathIsContentTypeA(pszPath, pszContentType): + _PathIsContentTypeA = windll.shlwapi.PathIsContentTypeA + _PathIsContentTypeA.argtypes = [LPSTR, LPSTR] + _PathIsContentTypeA.restype = bool + return _PathIsContentTypeA(pszPath, pszContentType) + +def PathIsContentTypeW(pszPath, pszContentType): + _PathIsContentTypeW = windll.shlwapi.PathIsContentTypeW + _PathIsContentTypeW.argtypes = [LPWSTR, LPWSTR] + _PathIsContentTypeW.restype = bool + return _PathIsContentTypeW(pszPath, pszContentType) + +PathIsContentType = GuessStringType(PathIsContentTypeA, PathIsContentTypeW) + +# BOOL PathIsDirectory( +# LPCTSTR pszPath +# ); +def PathIsDirectoryA(pszPath): + _PathIsDirectoryA = windll.shlwapi.PathIsDirectoryA + _PathIsDirectoryA.argtypes = [LPSTR] + _PathIsDirectoryA.restype = bool + return _PathIsDirectoryA(pszPath) + +def PathIsDirectoryW(pszPath): + _PathIsDirectoryW = windll.shlwapi.PathIsDirectoryW + _PathIsDirectoryW.argtypes = [LPWSTR] + _PathIsDirectoryW.restype = bool + return _PathIsDirectoryW(pszPath) + +PathIsDirectory = GuessStringType(PathIsDirectoryA, PathIsDirectoryW) + +# BOOL PathIsDirectoryEmpty( +# LPCTSTR pszPath +# ); +def PathIsDirectoryEmptyA(pszPath): + _PathIsDirectoryEmptyA = windll.shlwapi.PathIsDirectoryEmptyA + _PathIsDirectoryEmptyA.argtypes = [LPSTR] + _PathIsDirectoryEmptyA.restype = bool + return _PathIsDirectoryEmptyA(pszPath) + +def PathIsDirectoryEmptyW(pszPath): + _PathIsDirectoryEmptyW = windll.shlwapi.PathIsDirectoryEmptyW + _PathIsDirectoryEmptyW.argtypes = [LPWSTR] + _PathIsDirectoryEmptyW.restype = bool + return _PathIsDirectoryEmptyW(pszPath) + +PathIsDirectoryEmpty = GuessStringType(PathIsDirectoryEmptyA, PathIsDirectoryEmptyW) + +# BOOL PathIsNetworkPath( +# LPCTSTR pszPath +# ); +def PathIsNetworkPathA(pszPath): + _PathIsNetworkPathA = windll.shlwapi.PathIsNetworkPathA + _PathIsNetworkPathA.argtypes = [LPSTR] + _PathIsNetworkPathA.restype = bool + return _PathIsNetworkPathA(pszPath) + +def PathIsNetworkPathW(pszPath): + _PathIsNetworkPathW = windll.shlwapi.PathIsNetworkPathW + _PathIsNetworkPathW.argtypes = [LPWSTR] + _PathIsNetworkPathW.restype = bool + return _PathIsNetworkPathW(pszPath) + +PathIsNetworkPath = GuessStringType(PathIsNetworkPathA, PathIsNetworkPathW) + +# BOOL PathIsRelative( +# LPCTSTR lpszPath +# ); +def PathIsRelativeA(pszPath): + _PathIsRelativeA = windll.shlwapi.PathIsRelativeA + _PathIsRelativeA.argtypes = [LPSTR] + _PathIsRelativeA.restype = bool + return _PathIsRelativeA(pszPath) + +def PathIsRelativeW(pszPath): + _PathIsRelativeW = windll.shlwapi.PathIsRelativeW + _PathIsRelativeW.argtypes = [LPWSTR] + _PathIsRelativeW.restype = bool + return _PathIsRelativeW(pszPath) + +PathIsRelative = GuessStringType(PathIsRelativeA, PathIsRelativeW) + +# BOOL PathIsRoot( +# LPCTSTR pPath +# ); +def PathIsRootA(pszPath): + _PathIsRootA = windll.shlwapi.PathIsRootA + _PathIsRootA.argtypes = [LPSTR] + _PathIsRootA.restype = bool + return _PathIsRootA(pszPath) + +def PathIsRootW(pszPath): + _PathIsRootW = windll.shlwapi.PathIsRootW + _PathIsRootW.argtypes = [LPWSTR] + _PathIsRootW.restype = bool + return _PathIsRootW(pszPath) + +PathIsRoot = GuessStringType(PathIsRootA, PathIsRootW) + +# BOOL PathIsSameRoot( +# LPCTSTR pszPath1, +# LPCTSTR pszPath2 +# ); +def PathIsSameRootA(pszPath1, pszPath2): + _PathIsSameRootA = windll.shlwapi.PathIsSameRootA + _PathIsSameRootA.argtypes = [LPSTR, LPSTR] + _PathIsSameRootA.restype = bool + return _PathIsSameRootA(pszPath1, pszPath2) + +def PathIsSameRootW(pszPath1, pszPath2): + _PathIsSameRootW = windll.shlwapi.PathIsSameRootW + _PathIsSameRootW.argtypes = [LPWSTR, LPWSTR] + _PathIsSameRootW.restype = bool + return _PathIsSameRootW(pszPath1, pszPath2) + +PathIsSameRoot = GuessStringType(PathIsSameRootA, PathIsSameRootW) + +# BOOL PathIsUNC( +# LPCTSTR pszPath +# ); +def PathIsUNCA(pszPath): + _PathIsUNCA = windll.shlwapi.PathIsUNCA + _PathIsUNCA.argtypes = [LPSTR] + _PathIsUNCA.restype = bool + return _PathIsUNCA(pszPath) + +def PathIsUNCW(pszPath): + _PathIsUNCW = windll.shlwapi.PathIsUNCW + _PathIsUNCW.argtypes = [LPWSTR] + _PathIsUNCW.restype = bool + return _PathIsUNCW(pszPath) + +PathIsUNC = GuessStringType(PathIsUNCA, PathIsUNCW) + +# XXX WARNING +# PathMakePretty turns filenames into all lowercase. +# I'm not sure how well that might work on Wine. + +# BOOL PathMakePretty( +# LPCTSTR pszPath +# ); +def PathMakePrettyA(pszPath): + _PathMakePrettyA = windll.shlwapi.PathMakePrettyA + _PathMakePrettyA.argtypes = [LPSTR] + _PathMakePrettyA.restype = bool + _PathMakePrettyA.errcheck = RaiseIfZero + + pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH) + _PathMakePrettyA(pszPath) + return pszPath.value + +def PathMakePrettyW(pszPath): + _PathMakePrettyW = windll.shlwapi.PathMakePrettyW + _PathMakePrettyW.argtypes = [LPWSTR] + _PathMakePrettyW.restype = bool + _PathMakePrettyW.errcheck = RaiseIfZero + + pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH) + _PathMakePrettyW(pszPath) + return pszPath.value + +PathMakePretty = GuessStringType(PathMakePrettyA, PathMakePrettyW) + +# void PathRemoveArgs( +# LPTSTR pszPath +# ); +def PathRemoveArgsA(pszPath): + _PathRemoveArgsA = windll.shlwapi.PathRemoveArgsA + _PathRemoveArgsA.argtypes = [LPSTR] + + pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH) + _PathRemoveArgsA(pszPath) + return pszPath.value + +def PathRemoveArgsW(pszPath): + _PathRemoveArgsW = windll.shlwapi.PathRemoveArgsW + _PathRemoveArgsW.argtypes = [LPWSTR] + + pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH) + _PathRemoveArgsW(pszPath) + return pszPath.value + +PathRemoveArgs = GuessStringType(PathRemoveArgsA, PathRemoveArgsW) + +# void PathRemoveBackslash( +# LPTSTR pszPath +# ); +def PathRemoveBackslashA(pszPath): + _PathRemoveBackslashA = windll.shlwapi.PathRemoveBackslashA + _PathRemoveBackslashA.argtypes = [LPSTR] + + pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH) + _PathRemoveBackslashA(pszPath) + return pszPath.value + +def PathRemoveBackslashW(pszPath): + _PathRemoveBackslashW = windll.shlwapi.PathRemoveBackslashW + _PathRemoveBackslashW.argtypes = [LPWSTR] + + pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH) + _PathRemoveBackslashW(pszPath) + return pszPath.value + +PathRemoveBackslash = GuessStringType(PathRemoveBackslashA, PathRemoveBackslashW) + +# void PathRemoveExtension( +# LPTSTR pszPath +# ); +def PathRemoveExtensionA(pszPath): + _PathRemoveExtensionA = windll.shlwapi.PathRemoveExtensionA + _PathRemoveExtensionA.argtypes = [LPSTR] + + pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH) + _PathRemoveExtensionA(pszPath) + return pszPath.value + +def PathRemoveExtensionW(pszPath): + _PathRemoveExtensionW = windll.shlwapi.PathRemoveExtensionW + _PathRemoveExtensionW.argtypes = [LPWSTR] + + pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH) + _PathRemoveExtensionW(pszPath) + return pszPath.value + +PathRemoveExtension = GuessStringType(PathRemoveExtensionA, PathRemoveExtensionW) + +# void PathRemoveFileSpec( +# LPTSTR pszPath +# ); +def PathRemoveFileSpecA(pszPath): + _PathRemoveFileSpecA = windll.shlwapi.PathRemoveFileSpecA + _PathRemoveFileSpecA.argtypes = [LPSTR] + + pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH) + _PathRemoveFileSpecA(pszPath) + return pszPath.value + +def PathRemoveFileSpecW(pszPath): + _PathRemoveFileSpecW = windll.shlwapi.PathRemoveFileSpecW + _PathRemoveFileSpecW.argtypes = [LPWSTR] + + pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH) + _PathRemoveFileSpecW(pszPath) + return pszPath.value + +PathRemoveFileSpec = GuessStringType(PathRemoveFileSpecA, PathRemoveFileSpecW) + +# BOOL PathRenameExtension( +# LPTSTR pszPath, +# LPCTSTR pszExt +# ); +def PathRenameExtensionA(pszPath, pszExt): + _PathRenameExtensionA = windll.shlwapi.PathRenameExtensionA + _PathRenameExtensionA.argtypes = [LPSTR, LPSTR] + _PathRenameExtensionA.restype = bool + + pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH) + if _PathRenameExtensionA(pszPath, pszExt): + return pszPath.value + return None + +def PathRenameExtensionW(pszPath, pszExt): + _PathRenameExtensionW = windll.shlwapi.PathRenameExtensionW + _PathRenameExtensionW.argtypes = [LPWSTR, LPWSTR] + _PathRenameExtensionW.restype = bool + + pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH) + if _PathRenameExtensionW(pszPath, pszExt): + return pszPath.value + return None + +PathRenameExtension = GuessStringType(PathRenameExtensionA, PathRenameExtensionW) + +# BOOL PathUnExpandEnvStrings( +# LPCTSTR pszPath, +# LPTSTR pszBuf, +# UINT cchBuf +# ); +def PathUnExpandEnvStringsA(pszPath): + _PathUnExpandEnvStringsA = windll.shlwapi.PathUnExpandEnvStringsA + _PathUnExpandEnvStringsA.argtypes = [LPSTR, LPSTR] + _PathUnExpandEnvStringsA.restype = bool + _PathUnExpandEnvStringsA.errcheck = RaiseIfZero + + cchBuf = MAX_PATH + pszBuf = ctypes.create_string_buffer("", cchBuf) + _PathUnExpandEnvStringsA(pszPath, pszBuf, cchBuf) + return pszBuf.value + +def PathUnExpandEnvStringsW(pszPath): + _PathUnExpandEnvStringsW = windll.shlwapi.PathUnExpandEnvStringsW + _PathUnExpandEnvStringsW.argtypes = [LPWSTR, LPWSTR] + _PathUnExpandEnvStringsW.restype = bool + _PathUnExpandEnvStringsW.errcheck = RaiseIfZero + + cchBuf = MAX_PATH + pszBuf = ctypes.create_unicode_buffer(u"", cchBuf) + _PathUnExpandEnvStringsW(pszPath, pszBuf, cchBuf) + return pszBuf.value + +PathUnExpandEnvStrings = GuessStringType(PathUnExpandEnvStringsA, PathUnExpandEnvStringsW) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/user32.py b/pydevd_attach_to_process/winappdbg/win32/user32.py new file mode 100644 index 0000000..18560e5 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/user32.py @@ -0,0 +1,1727 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for user32.dll in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.version import bits +from winappdbg.win32.kernel32 import GetLastError, SetLastError +from winappdbg.win32.gdi32 import POINT, PPOINT, LPPOINT, RECT, PRECT, LPRECT + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- Helpers ------------------------------------------------------------------ + +def MAKE_WPARAM(wParam): + """ + Convert arguments to the WPARAM type. + Used automatically by SendMessage, PostMessage, etc. + You shouldn't need to call this function. + """ + wParam = ctypes.cast(wParam, LPVOID).value + if wParam is None: + wParam = 0 + return wParam + +def MAKE_LPARAM(lParam): + """ + Convert arguments to the LPARAM type. + Used automatically by SendMessage, PostMessage, etc. + You shouldn't need to call this function. + """ + return ctypes.cast(lParam, LPARAM) + +class __WindowEnumerator (object): + """ + Window enumerator class. Used internally by the window enumeration APIs. + """ + def __init__(self): + self.hwnd = list() + def __call__(self, hwnd, lParam): +## print hwnd # XXX DEBUG + self.hwnd.append(hwnd) + return TRUE + +#--- Types -------------------------------------------------------------------- + +WNDENUMPROC = WINFUNCTYPE(BOOL, HWND, PVOID) + +#--- Constants ---------------------------------------------------------------- + +HWND_DESKTOP = 0 +HWND_TOP = 1 +HWND_BOTTOM = 1 +HWND_TOPMOST = -1 +HWND_NOTOPMOST = -2 +HWND_MESSAGE = -3 + +# GetWindowLong / SetWindowLong +GWL_WNDPROC = -4 +GWL_HINSTANCE = -6 +GWL_HWNDPARENT = -8 +GWL_ID = -12 +GWL_STYLE = -16 +GWL_EXSTYLE = -20 +GWL_USERDATA = -21 + +# GetWindowLongPtr / SetWindowLongPtr +GWLP_WNDPROC = GWL_WNDPROC +GWLP_HINSTANCE = GWL_HINSTANCE +GWLP_HWNDPARENT = GWL_HWNDPARENT +GWLP_STYLE = GWL_STYLE +GWLP_EXSTYLE = GWL_EXSTYLE +GWLP_USERDATA = GWL_USERDATA +GWLP_ID = GWL_ID + +# ShowWindow +SW_HIDE = 0 +SW_SHOWNORMAL = 1 +SW_NORMAL = 1 +SW_SHOWMINIMIZED = 2 +SW_SHOWMAXIMIZED = 3 +SW_MAXIMIZE = 3 +SW_SHOWNOACTIVATE = 4 +SW_SHOW = 5 +SW_MINIMIZE = 6 +SW_SHOWMINNOACTIVE = 7 +SW_SHOWNA = 8 +SW_RESTORE = 9 +SW_SHOWDEFAULT = 10 +SW_FORCEMINIMIZE = 11 + +# SendMessageTimeout flags +SMTO_NORMAL = 0 +SMTO_BLOCK = 1 +SMTO_ABORTIFHUNG = 2 +SMTO_NOTIMEOUTIFNOTHUNG = 8 +SMTO_ERRORONEXIT = 0x20 + +# WINDOWPLACEMENT flags +WPF_SETMINPOSITION = 1 +WPF_RESTORETOMAXIMIZED = 2 +WPF_ASYNCWINDOWPLACEMENT = 4 + +# GetAncestor flags +GA_PARENT = 1 +GA_ROOT = 2 +GA_ROOTOWNER = 3 + +# GetWindow flags +GW_HWNDFIRST = 0 +GW_HWNDLAST = 1 +GW_HWNDNEXT = 2 +GW_HWNDPREV = 3 +GW_OWNER = 4 +GW_CHILD = 5 +GW_ENABLEDPOPUP = 6 + +#--- Window messages ---------------------------------------------------------- + +WM_USER = 0x400 +WM_APP = 0x800 + +WM_NULL = 0 +WM_CREATE = 1 +WM_DESTROY = 2 +WM_MOVE = 3 +WM_SIZE = 5 +WM_ACTIVATE = 6 +WA_INACTIVE = 0 +WA_ACTIVE = 1 +WA_CLICKACTIVE = 2 +WM_SETFOCUS = 7 +WM_KILLFOCUS = 8 +WM_ENABLE = 0x0A +WM_SETREDRAW = 0x0B +WM_SETTEXT = 0x0C +WM_GETTEXT = 0x0D +WM_GETTEXTLENGTH = 0x0E +WM_PAINT = 0x0F +WM_CLOSE = 0x10 +WM_QUERYENDSESSION = 0x11 +WM_QUIT = 0x12 +WM_QUERYOPEN = 0x13 +WM_ERASEBKGND = 0x14 +WM_SYSCOLORCHANGE = 0x15 +WM_ENDSESSION = 0x16 +WM_SHOWWINDOW = 0x18 +WM_WININICHANGE = 0x1A +WM_SETTINGCHANGE = WM_WININICHANGE +WM_DEVMODECHANGE = 0x1B +WM_ACTIVATEAPP = 0x1C +WM_FONTCHANGE = 0x1D +WM_TIMECHANGE = 0x1E +WM_CANCELMODE = 0x1F +WM_SETCURSOR = 0x20 +WM_MOUSEACTIVATE = 0x21 +WM_CHILDACTIVATE = 0x22 +WM_QUEUESYNC = 0x23 +WM_GETMINMAXINFO = 0x24 +WM_PAINTICON = 0x26 +WM_ICONERASEBKGND = 0x27 +WM_NEXTDLGCTL = 0x28 +WM_SPOOLERSTATUS = 0x2A +WM_DRAWITEM = 0x2B +WM_MEASUREITEM = 0x2C +WM_DELETEITEM = 0x2D +WM_VKEYTOITEM = 0x2E +WM_CHARTOITEM = 0x2F +WM_SETFONT = 0x30 +WM_GETFONT = 0x31 +WM_SETHOTKEY = 0x32 +WM_GETHOTKEY = 0x33 +WM_QUERYDRAGICON = 0x37 +WM_COMPAREITEM = 0x39 +WM_GETOBJECT = 0x3D +WM_COMPACTING = 0x41 +WM_OTHERWINDOWCREATED = 0x42 +WM_OTHERWINDOWDESTROYED = 0x43 +WM_COMMNOTIFY = 0x44 + +CN_RECEIVE = 0x1 +CN_TRANSMIT = 0x2 +CN_EVENT = 0x4 + +WM_WINDOWPOSCHANGING = 0x46 +WM_WINDOWPOSCHANGED = 0x47 +WM_POWER = 0x48 + +PWR_OK = 1 +PWR_FAIL = -1 +PWR_SUSPENDREQUEST = 1 +PWR_SUSPENDRESUME = 2 +PWR_CRITICALRESUME = 3 + +WM_COPYDATA = 0x4A +WM_CANCELJOURNAL = 0x4B +WM_NOTIFY = 0x4E +WM_INPUTLANGCHANGEREQUEST = 0x50 +WM_INPUTLANGCHANGE = 0x51 +WM_TCARD = 0x52 +WM_HELP = 0x53 +WM_USERCHANGED = 0x54 +WM_NOTIFYFORMAT = 0x55 +WM_CONTEXTMENU = 0x7B +WM_STYLECHANGING = 0x7C +WM_STYLECHANGED = 0x7D +WM_DISPLAYCHANGE = 0x7E +WM_GETICON = 0x7F +WM_SETICON = 0x80 +WM_NCCREATE = 0x81 +WM_NCDESTROY = 0x82 +WM_NCCALCSIZE = 0x83 +WM_NCHITTEST = 0x84 +WM_NCPAINT = 0x85 +WM_NCACTIVATE = 0x86 +WM_GETDLGCODE = 0x87 +WM_SYNCPAINT = 0x88 +WM_NCMOUSEMOVE = 0x0A0 +WM_NCLBUTTONDOWN = 0x0A1 +WM_NCLBUTTONUP = 0x0A2 +WM_NCLBUTTONDBLCLK = 0x0A3 +WM_NCRBUTTONDOWN = 0x0A4 +WM_NCRBUTTONUP = 0x0A5 +WM_NCRBUTTONDBLCLK = 0x0A6 +WM_NCMBUTTONDOWN = 0x0A7 +WM_NCMBUTTONUP = 0x0A8 +WM_NCMBUTTONDBLCLK = 0x0A9 +WM_KEYFIRST = 0x100 +WM_KEYDOWN = 0x100 +WM_KEYUP = 0x101 +WM_CHAR = 0x102 +WM_DEADCHAR = 0x103 +WM_SYSKEYDOWN = 0x104 +WM_SYSKEYUP = 0x105 +WM_SYSCHAR = 0x106 +WM_SYSDEADCHAR = 0x107 +WM_KEYLAST = 0x108 +WM_INITDIALOG = 0x110 +WM_COMMAND = 0x111 +WM_SYSCOMMAND = 0x112 +WM_TIMER = 0x113 +WM_HSCROLL = 0x114 +WM_VSCROLL = 0x115 +WM_INITMENU = 0x116 +WM_INITMENUPOPUP = 0x117 +WM_MENUSELECT = 0x11F +WM_MENUCHAR = 0x120 +WM_ENTERIDLE = 0x121 +WM_CTLCOLORMSGBOX = 0x132 +WM_CTLCOLOREDIT = 0x133 +WM_CTLCOLORLISTBOX = 0x134 +WM_CTLCOLORBTN = 0x135 +WM_CTLCOLORDLG = 0x136 +WM_CTLCOLORSCROLLBAR = 0x137 +WM_CTLCOLORSTATIC = 0x138 +WM_MOUSEFIRST = 0x200 +WM_MOUSEMOVE = 0x200 +WM_LBUTTONDOWN = 0x201 +WM_LBUTTONUP = 0x202 +WM_LBUTTONDBLCLK = 0x203 +WM_RBUTTONDOWN = 0x204 +WM_RBUTTONUP = 0x205 +WM_RBUTTONDBLCLK = 0x206 +WM_MBUTTONDOWN = 0x207 +WM_MBUTTONUP = 0x208 +WM_MBUTTONDBLCLK = 0x209 +WM_MOUSELAST = 0x209 +WM_PARENTNOTIFY = 0x210 +WM_ENTERMENULOOP = 0x211 +WM_EXITMENULOOP = 0x212 +WM_MDICREATE = 0x220 +WM_MDIDESTROY = 0x221 +WM_MDIACTIVATE = 0x222 +WM_MDIRESTORE = 0x223 +WM_MDINEXT = 0x224 +WM_MDIMAXIMIZE = 0x225 +WM_MDITILE = 0x226 +WM_MDICASCADE = 0x227 +WM_MDIICONARRANGE = 0x228 +WM_MDIGETACTIVE = 0x229 +WM_MDISETMENU = 0x230 +WM_DROPFILES = 0x233 +WM_MDIREFRESHMENU = 0x234 +WM_CUT = 0x300 +WM_COPY = 0x301 +WM_PASTE = 0x302 +WM_CLEAR = 0x303 +WM_UNDO = 0x304 +WM_RENDERFORMAT = 0x305 +WM_RENDERALLFORMATS = 0x306 +WM_DESTROYCLIPBOARD = 0x307 +WM_DRAWCLIPBOARD = 0x308 +WM_PAINTCLIPBOARD = 0x309 +WM_VSCROLLCLIPBOARD = 0x30A +WM_SIZECLIPBOARD = 0x30B +WM_ASKCBFORMATNAME = 0x30C +WM_CHANGECBCHAIN = 0x30D +WM_HSCROLLCLIPBOARD = 0x30E +WM_QUERYNEWPALETTE = 0x30F +WM_PALETTEISCHANGING = 0x310 +WM_PALETTECHANGED = 0x311 +WM_HOTKEY = 0x312 +WM_PRINT = 0x317 +WM_PRINTCLIENT = 0x318 +WM_PENWINFIRST = 0x380 +WM_PENWINLAST = 0x38F + +#--- Structures --------------------------------------------------------------- + +# typedef struct _WINDOWPLACEMENT { +# UINT length; +# UINT flags; +# UINT showCmd; +# POINT ptMinPosition; +# POINT ptMaxPosition; +# RECT rcNormalPosition; +# } WINDOWPLACEMENT; +class WINDOWPLACEMENT(Structure): + _fields_ = [ + ('length', UINT), + ('flags', UINT), + ('showCmd', UINT), + ('ptMinPosition', POINT), + ('ptMaxPosition', POINT), + ('rcNormalPosition', RECT), + ] +PWINDOWPLACEMENT = POINTER(WINDOWPLACEMENT) +LPWINDOWPLACEMENT = PWINDOWPLACEMENT + +# typedef struct tagGUITHREADINFO { +# DWORD cbSize; +# DWORD flags; +# HWND hwndActive; +# HWND hwndFocus; +# HWND hwndCapture; +# HWND hwndMenuOwner; +# HWND hwndMoveSize; +# HWND hwndCaret; +# RECT rcCaret; +# } GUITHREADINFO, *PGUITHREADINFO; +class GUITHREADINFO(Structure): + _fields_ = [ + ('cbSize', DWORD), + ('flags', DWORD), + ('hwndActive', HWND), + ('hwndFocus', HWND), + ('hwndCapture', HWND), + ('hwndMenuOwner', HWND), + ('hwndMoveSize', HWND), + ('hwndCaret', HWND), + ('rcCaret', RECT), + ] +PGUITHREADINFO = POINTER(GUITHREADINFO) +LPGUITHREADINFO = PGUITHREADINFO + +#--- High level classes ------------------------------------------------------- + +# Point() and Rect() are here instead of gdi32.py because they were mainly +# created to handle window coordinates rather than drawing on the screen. + +# XXX not sure if these classes should be psyco-optimized, +# it may not work if the user wants to serialize them for some reason + +class Point(object): + """ + Python wrapper over the L{POINT} class. + + @type x: int + @ivar x: Horizontal coordinate + @type y: int + @ivar y: Vertical coordinate + """ + + def __init__(self, x = 0, y = 0): + """ + @see: L{POINT} + @type x: int + @param x: Horizontal coordinate + @type y: int + @param y: Vertical coordinate + """ + self.x = x + self.y = y + + def __iter__(self): + return (self.x, self.y).__iter__() + + def __len__(self): + return 2 + + def __getitem__(self, index): + return (self.x, self.y) [index] + + def __setitem__(self, index, value): + if index == 0: + self.x = value + elif index == 1: + self.y = value + else: + raise IndexError("index out of range") + + @property + def _as_parameter_(self): + """ + Compatibility with ctypes. + Allows passing transparently a Point object to an API call. + """ + return POINT(self.x, self.y) + + def screen_to_client(self, hWnd): + """ + Translates window screen coordinates to client coordinates. + + @see: L{client_to_screen}, L{translate} + + @type hWnd: int or L{HWND} or L{system.Window} + @param hWnd: Window handle. + + @rtype: L{Point} + @return: New object containing the translated coordinates. + """ + return ScreenToClient(hWnd, self) + + def client_to_screen(self, hWnd): + """ + Translates window client coordinates to screen coordinates. + + @see: L{screen_to_client}, L{translate} + + @type hWnd: int or L{HWND} or L{system.Window} + @param hWnd: Window handle. + + @rtype: L{Point} + @return: New object containing the translated coordinates. + """ + return ClientToScreen(hWnd, self) + + def translate(self, hWndFrom = HWND_DESKTOP, hWndTo = HWND_DESKTOP): + """ + Translate coordinates from one window to another. + + @note: To translate multiple points it's more efficient to use the + L{MapWindowPoints} function instead. + + @see: L{client_to_screen}, L{screen_to_client} + + @type hWndFrom: int or L{HWND} or L{system.Window} + @param hWndFrom: Window handle to translate from. + Use C{HWND_DESKTOP} for screen coordinates. + + @type hWndTo: int or L{HWND} or L{system.Window} + @param hWndTo: Window handle to translate to. + Use C{HWND_DESKTOP} for screen coordinates. + + @rtype: L{Point} + @return: New object containing the translated coordinates. + """ + return MapWindowPoints(hWndFrom, hWndTo, [self]) + +class Rect(object): + """ + Python wrapper over the L{RECT} class. + + @type left: int + @ivar left: Horizontal coordinate for the top left corner. + @type top: int + @ivar top: Vertical coordinate for the top left corner. + @type right: int + @ivar right: Horizontal coordinate for the bottom right corner. + @type bottom: int + @ivar bottom: Vertical coordinate for the bottom right corner. + + @type width: int + @ivar width: Width in pixels. Same as C{right - left}. + @type height: int + @ivar height: Height in pixels. Same as C{bottom - top}. + """ + + def __init__(self, left = 0, top = 0, right = 0, bottom = 0): + """ + @see: L{RECT} + @type left: int + @param left: Horizontal coordinate for the top left corner. + @type top: int + @param top: Vertical coordinate for the top left corner. + @type right: int + @param right: Horizontal coordinate for the bottom right corner. + @type bottom: int + @param bottom: Vertical coordinate for the bottom right corner. + """ + self.left = left + self.top = top + self.right = right + self.bottom = bottom + + def __iter__(self): + return (self.left, self.top, self.right, self.bottom).__iter__() + + def __len__(self): + return 2 + + def __getitem__(self, index): + return (self.left, self.top, self.right, self.bottom) [index] + + def __setitem__(self, index, value): + if index == 0: + self.left = value + elif index == 1: + self.top = value + elif index == 2: + self.right = value + elif index == 3: + self.bottom = value + else: + raise IndexError("index out of range") + + @property + def _as_parameter_(self): + """ + Compatibility with ctypes. + Allows passing transparently a Point object to an API call. + """ + return RECT(self.left, self.top, self.right, self.bottom) + + def __get_width(self): + return self.right - self.left + + def __get_height(self): + return self.bottom - self.top + + def __set_width(self, value): + self.right = value - self.left + + def __set_height(self, value): + self.bottom = value - self.top + + width = property(__get_width, __set_width) + height = property(__get_height, __set_height) + + def screen_to_client(self, hWnd): + """ + Translates window screen coordinates to client coordinates. + + @see: L{client_to_screen}, L{translate} + + @type hWnd: int or L{HWND} or L{system.Window} + @param hWnd: Window handle. + + @rtype: L{Rect} + @return: New object containing the translated coordinates. + """ + topleft = ScreenToClient(hWnd, (self.left, self.top)) + bottomright = ScreenToClient(hWnd, (self.bottom, self.right)) + return Rect( topleft.x, topleft.y, bottomright.x, bottomright.y ) + + def client_to_screen(self, hWnd): + """ + Translates window client coordinates to screen coordinates. + + @see: L{screen_to_client}, L{translate} + + @type hWnd: int or L{HWND} or L{system.Window} + @param hWnd: Window handle. + + @rtype: L{Rect} + @return: New object containing the translated coordinates. + """ + topleft = ClientToScreen(hWnd, (self.left, self.top)) + bottomright = ClientToScreen(hWnd, (self.bottom, self.right)) + return Rect( topleft.x, topleft.y, bottomright.x, bottomright.y ) + + def translate(self, hWndFrom = HWND_DESKTOP, hWndTo = HWND_DESKTOP): + """ + Translate coordinates from one window to another. + + @see: L{client_to_screen}, L{screen_to_client} + + @type hWndFrom: int or L{HWND} or L{system.Window} + @param hWndFrom: Window handle to translate from. + Use C{HWND_DESKTOP} for screen coordinates. + + @type hWndTo: int or L{HWND} or L{system.Window} + @param hWndTo: Window handle to translate to. + Use C{HWND_DESKTOP} for screen coordinates. + + @rtype: L{Rect} + @return: New object containing the translated coordinates. + """ + points = [ (self.left, self.top), (self.right, self.bottom) ] + return MapWindowPoints(hWndFrom, hWndTo, points) + +class WindowPlacement(object): + """ + Python wrapper over the L{WINDOWPLACEMENT} class. + """ + + def __init__(self, wp = None): + """ + @type wp: L{WindowPlacement} or L{WINDOWPLACEMENT} + @param wp: Another window placement object. + """ + + # Initialize all properties with empty values. + self.flags = 0 + self.showCmd = 0 + self.ptMinPosition = Point() + self.ptMaxPosition = Point() + self.rcNormalPosition = Rect() + + # If a window placement was given copy it's properties. + if wp: + self.flags = wp.flags + self.showCmd = wp.showCmd + self.ptMinPosition = Point( wp.ptMinPosition.x, wp.ptMinPosition.y ) + self.ptMaxPosition = Point( wp.ptMaxPosition.x, wp.ptMaxPosition.y ) + self.rcNormalPosition = Rect( + wp.rcNormalPosition.left, + wp.rcNormalPosition.top, + wp.rcNormalPosition.right, + wp.rcNormalPosition.bottom, + ) + + @property + def _as_parameter_(self): + """ + Compatibility with ctypes. + Allows passing transparently a Point object to an API call. + """ + wp = WINDOWPLACEMENT() + wp.length = sizeof(wp) + wp.flags = self.flags + wp.showCmd = self.showCmd + wp.ptMinPosition.x = self.ptMinPosition.x + wp.ptMinPosition.y = self.ptMinPosition.y + wp.ptMaxPosition.x = self.ptMaxPosition.x + wp.ptMaxPosition.y = self.ptMaxPosition.y + wp.rcNormalPosition.left = self.rcNormalPosition.left + wp.rcNormalPosition.top = self.rcNormalPosition.top + wp.rcNormalPosition.right = self.rcNormalPosition.right + wp.rcNormalPosition.bottom = self.rcNormalPosition.bottom + return wp + +#--- user32.dll --------------------------------------------------------------- + +# void WINAPI SetLastErrorEx( +# __in DWORD dwErrCode, +# __in DWORD dwType +# ); +def SetLastErrorEx(dwErrCode, dwType = 0): + _SetLastErrorEx = windll.user32.SetLastErrorEx + _SetLastErrorEx.argtypes = [DWORD, DWORD] + _SetLastErrorEx.restype = None + _SetLastErrorEx(dwErrCode, dwType) + +# HWND FindWindow( +# LPCTSTR lpClassName, +# LPCTSTR lpWindowName +# ); +def FindWindowA(lpClassName = None, lpWindowName = None): + _FindWindowA = windll.user32.FindWindowA + _FindWindowA.argtypes = [LPSTR, LPSTR] + _FindWindowA.restype = HWND + + hWnd = _FindWindowA(lpClassName, lpWindowName) + if not hWnd: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return hWnd + +def FindWindowW(lpClassName = None, lpWindowName = None): + _FindWindowW = windll.user32.FindWindowW + _FindWindowW.argtypes = [LPWSTR, LPWSTR] + _FindWindowW.restype = HWND + + hWnd = _FindWindowW(lpClassName, lpWindowName) + if not hWnd: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return hWnd + +FindWindow = GuessStringType(FindWindowA, FindWindowW) + +# HWND WINAPI FindWindowEx( +# __in_opt HWND hwndParent, +# __in_opt HWND hwndChildAfter, +# __in_opt LPCTSTR lpszClass, +# __in_opt LPCTSTR lpszWindow +# ); +def FindWindowExA(hwndParent = None, hwndChildAfter = None, lpClassName = None, lpWindowName = None): + _FindWindowExA = windll.user32.FindWindowExA + _FindWindowExA.argtypes = [HWND, HWND, LPSTR, LPSTR] + _FindWindowExA.restype = HWND + + hWnd = _FindWindowExA(hwndParent, hwndChildAfter, lpClassName, lpWindowName) + if not hWnd: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return hWnd + +def FindWindowExW(hwndParent = None, hwndChildAfter = None, lpClassName = None, lpWindowName = None): + _FindWindowExW = windll.user32.FindWindowExW + _FindWindowExW.argtypes = [HWND, HWND, LPWSTR, LPWSTR] + _FindWindowExW.restype = HWND + + hWnd = _FindWindowExW(hwndParent, hwndChildAfter, lpClassName, lpWindowName) + if not hWnd: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return hWnd + +FindWindowEx = GuessStringType(FindWindowExA, FindWindowExW) + +# int GetClassName( +# HWND hWnd, +# LPTSTR lpClassName, +# int nMaxCount +# ); +def GetClassNameA(hWnd): + _GetClassNameA = windll.user32.GetClassNameA + _GetClassNameA.argtypes = [HWND, LPSTR, ctypes.c_int] + _GetClassNameA.restype = ctypes.c_int + + nMaxCount = 0x1000 + dwCharSize = sizeof(CHAR) + while 1: + lpClassName = ctypes.create_string_buffer("", nMaxCount) + nCount = _GetClassNameA(hWnd, lpClassName, nMaxCount) + if nCount == 0: + raise ctypes.WinError() + if nCount < nMaxCount - dwCharSize: + break + nMaxCount += 0x1000 + return lpClassName.value + +def GetClassNameW(hWnd): + _GetClassNameW = windll.user32.GetClassNameW + _GetClassNameW.argtypes = [HWND, LPWSTR, ctypes.c_int] + _GetClassNameW.restype = ctypes.c_int + + nMaxCount = 0x1000 + dwCharSize = sizeof(WCHAR) + while 1: + lpClassName = ctypes.create_unicode_buffer(u"", nMaxCount) + nCount = _GetClassNameW(hWnd, lpClassName, nMaxCount) + if nCount == 0: + raise ctypes.WinError() + if nCount < nMaxCount - dwCharSize: + break + nMaxCount += 0x1000 + return lpClassName.value + +GetClassName = GuessStringType(GetClassNameA, GetClassNameW) + +# int WINAPI GetWindowText( +# __in HWND hWnd, +# __out LPTSTR lpString, +# __in int nMaxCount +# ); +def GetWindowTextA(hWnd): + _GetWindowTextA = windll.user32.GetWindowTextA + _GetWindowTextA.argtypes = [HWND, LPSTR, ctypes.c_int] + _GetWindowTextA.restype = ctypes.c_int + + nMaxCount = 0x1000 + dwCharSize = sizeof(CHAR) + while 1: + lpString = ctypes.create_string_buffer("", nMaxCount) + nCount = _GetWindowTextA(hWnd, lpString, nMaxCount) + if nCount == 0: + raise ctypes.WinError() + if nCount < nMaxCount - dwCharSize: + break + nMaxCount += 0x1000 + return lpString.value + +def GetWindowTextW(hWnd): + _GetWindowTextW = windll.user32.GetWindowTextW + _GetWindowTextW.argtypes = [HWND, LPWSTR, ctypes.c_int] + _GetWindowTextW.restype = ctypes.c_int + + nMaxCount = 0x1000 + dwCharSize = sizeof(CHAR) + while 1: + lpString = ctypes.create_string_buffer("", nMaxCount) + nCount = _GetWindowTextW(hWnd, lpString, nMaxCount) + if nCount == 0: + raise ctypes.WinError() + if nCount < nMaxCount - dwCharSize: + break + nMaxCount += 0x1000 + return lpString.value + +GetWindowText = GuessStringType(GetWindowTextA, GetWindowTextW) + +# BOOL WINAPI SetWindowText( +# __in HWND hWnd, +# __in_opt LPCTSTR lpString +# ); +def SetWindowTextA(hWnd, lpString = None): + _SetWindowTextA = windll.user32.SetWindowTextA + _SetWindowTextA.argtypes = [HWND, LPSTR] + _SetWindowTextA.restype = bool + _SetWindowTextA.errcheck = RaiseIfZero + _SetWindowTextA(hWnd, lpString) + +def SetWindowTextW(hWnd, lpString = None): + _SetWindowTextW = windll.user32.SetWindowTextW + _SetWindowTextW.argtypes = [HWND, LPWSTR] + _SetWindowTextW.restype = bool + _SetWindowTextW.errcheck = RaiseIfZero + _SetWindowTextW(hWnd, lpString) + +SetWindowText = GuessStringType(SetWindowTextA, SetWindowTextW) + +# LONG GetWindowLong( +# HWND hWnd, +# int nIndex +# ); +def GetWindowLongA(hWnd, nIndex = 0): + _GetWindowLongA = windll.user32.GetWindowLongA + _GetWindowLongA.argtypes = [HWND, ctypes.c_int] + _GetWindowLongA.restype = DWORD + + SetLastError(ERROR_SUCCESS) + retval = _GetWindowLongA(hWnd, nIndex) + if retval == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return retval + +def GetWindowLongW(hWnd, nIndex = 0): + _GetWindowLongW = windll.user32.GetWindowLongW + _GetWindowLongW.argtypes = [HWND, ctypes.c_int] + _GetWindowLongW.restype = DWORD + + SetLastError(ERROR_SUCCESS) + retval = _GetWindowLongW(hWnd, nIndex) + if retval == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return retval + +GetWindowLong = DefaultStringType(GetWindowLongA, GetWindowLongW) + +# LONG_PTR WINAPI GetWindowLongPtr( +# _In_ HWND hWnd, +# _In_ int nIndex +# ); + +if bits == 32: + + GetWindowLongPtrA = GetWindowLongA + GetWindowLongPtrW = GetWindowLongW + GetWindowLongPtr = GetWindowLong + +else: + + def GetWindowLongPtrA(hWnd, nIndex = 0): + _GetWindowLongPtrA = windll.user32.GetWindowLongPtrA + _GetWindowLongPtrA.argtypes = [HWND, ctypes.c_int] + _GetWindowLongPtrA.restype = SIZE_T + + SetLastError(ERROR_SUCCESS) + retval = _GetWindowLongPtrA(hWnd, nIndex) + if retval == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return retval + + def GetWindowLongPtrW(hWnd, nIndex = 0): + _GetWindowLongPtrW = windll.user32.GetWindowLongPtrW + _GetWindowLongPtrW.argtypes = [HWND, ctypes.c_int] + _GetWindowLongPtrW.restype = DWORD + + SetLastError(ERROR_SUCCESS) + retval = _GetWindowLongPtrW(hWnd, nIndex) + if retval == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return retval + + GetWindowLongPtr = DefaultStringType(GetWindowLongPtrA, GetWindowLongPtrW) + +# LONG WINAPI SetWindowLong( +# _In_ HWND hWnd, +# _In_ int nIndex, +# _In_ LONG dwNewLong +# ); + +def SetWindowLongA(hWnd, nIndex, dwNewLong): + _SetWindowLongA = windll.user32.SetWindowLongA + _SetWindowLongA.argtypes = [HWND, ctypes.c_int, DWORD] + _SetWindowLongA.restype = DWORD + + SetLastError(ERROR_SUCCESS) + retval = _SetWindowLongA(hWnd, nIndex, dwNewLong) + if retval == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return retval + +def SetWindowLongW(hWnd, nIndex, dwNewLong): + _SetWindowLongW = windll.user32.SetWindowLongW + _SetWindowLongW.argtypes = [HWND, ctypes.c_int, DWORD] + _SetWindowLongW.restype = DWORD + + SetLastError(ERROR_SUCCESS) + retval = _SetWindowLongW(hWnd, nIndex, dwNewLong) + if retval == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return retval + +SetWindowLong = DefaultStringType(SetWindowLongA, SetWindowLongW) + +# LONG_PTR WINAPI SetWindowLongPtr( +# _In_ HWND hWnd, +# _In_ int nIndex, +# _In_ LONG_PTR dwNewLong +# ); + +if bits == 32: + + SetWindowLongPtrA = SetWindowLongA + SetWindowLongPtrW = SetWindowLongW + SetWindowLongPtr = SetWindowLong + +else: + + def SetWindowLongPtrA(hWnd, nIndex, dwNewLong): + _SetWindowLongPtrA = windll.user32.SetWindowLongPtrA + _SetWindowLongPtrA.argtypes = [HWND, ctypes.c_int, SIZE_T] + _SetWindowLongPtrA.restype = SIZE_T + + SetLastError(ERROR_SUCCESS) + retval = _SetWindowLongPtrA(hWnd, nIndex, dwNewLong) + if retval == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return retval + + def SetWindowLongPtrW(hWnd, nIndex, dwNewLong): + _SetWindowLongPtrW = windll.user32.SetWindowLongPtrW + _SetWindowLongPtrW.argtypes = [HWND, ctypes.c_int, SIZE_T] + _SetWindowLongPtrW.restype = SIZE_T + + SetLastError(ERROR_SUCCESS) + retval = _SetWindowLongPtrW(hWnd, nIndex, dwNewLong) + if retval == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + return retval + + SetWindowLongPtr = DefaultStringType(SetWindowLongPtrA, SetWindowLongPtrW) + +# HWND GetShellWindow(VOID); +def GetShellWindow(): + _GetShellWindow = windll.user32.GetShellWindow + _GetShellWindow.argtypes = [] + _GetShellWindow.restype = HWND + _GetShellWindow.errcheck = RaiseIfZero + return _GetShellWindow() + +# DWORD GetWindowThreadProcessId( +# HWND hWnd, +# LPDWORD lpdwProcessId +# ); +def GetWindowThreadProcessId(hWnd): + _GetWindowThreadProcessId = windll.user32.GetWindowThreadProcessId + _GetWindowThreadProcessId.argtypes = [HWND, LPDWORD] + _GetWindowThreadProcessId.restype = DWORD + _GetWindowThreadProcessId.errcheck = RaiseIfZero + + dwProcessId = DWORD(0) + dwThreadId = _GetWindowThreadProcessId(hWnd, byref(dwProcessId)) + return (dwThreadId, dwProcessId.value) + +# HWND WINAPI GetWindow( +# __in HWND hwnd, +# __in UINT uCmd +# ); +def GetWindow(hWnd, uCmd): + _GetWindow = windll.user32.GetWindow + _GetWindow.argtypes = [HWND, UINT] + _GetWindow.restype = HWND + + SetLastError(ERROR_SUCCESS) + hWndTarget = _GetWindow(hWnd, uCmd) + if not hWndTarget: + winerr = GetLastError() + if winerr != ERROR_SUCCESS: + raise ctypes.WinError(winerr) + return hWndTarget + +# HWND GetParent( +# HWND hWnd +# ); +def GetParent(hWnd): + _GetParent = windll.user32.GetParent + _GetParent.argtypes = [HWND] + _GetParent.restype = HWND + + SetLastError(ERROR_SUCCESS) + hWndParent = _GetParent(hWnd) + if not hWndParent: + winerr = GetLastError() + if winerr != ERROR_SUCCESS: + raise ctypes.WinError(winerr) + return hWndParent + +# HWND WINAPI GetAncestor( +# __in HWND hwnd, +# __in UINT gaFlags +# ); +def GetAncestor(hWnd, gaFlags = GA_PARENT): + _GetAncestor = windll.user32.GetAncestor + _GetAncestor.argtypes = [HWND, UINT] + _GetAncestor.restype = HWND + + SetLastError(ERROR_SUCCESS) + hWndParent = _GetAncestor(hWnd, gaFlags) + if not hWndParent: + winerr = GetLastError() + if winerr != ERROR_SUCCESS: + raise ctypes.WinError(winerr) + return hWndParent + +# BOOL EnableWindow( +# HWND hWnd, +# BOOL bEnable +# ); +def EnableWindow(hWnd, bEnable = True): + _EnableWindow = windll.user32.EnableWindow + _EnableWindow.argtypes = [HWND, BOOL] + _EnableWindow.restype = bool + return _EnableWindow(hWnd, bool(bEnable)) + +# BOOL ShowWindow( +# HWND hWnd, +# int nCmdShow +# ); +def ShowWindow(hWnd, nCmdShow = SW_SHOW): + _ShowWindow = windll.user32.ShowWindow + _ShowWindow.argtypes = [HWND, ctypes.c_int] + _ShowWindow.restype = bool + return _ShowWindow(hWnd, nCmdShow) + +# BOOL ShowWindowAsync( +# HWND hWnd, +# int nCmdShow +# ); +def ShowWindowAsync(hWnd, nCmdShow = SW_SHOW): + _ShowWindowAsync = windll.user32.ShowWindowAsync + _ShowWindowAsync.argtypes = [HWND, ctypes.c_int] + _ShowWindowAsync.restype = bool + return _ShowWindowAsync(hWnd, nCmdShow) + +# HWND GetDesktopWindow(VOID); +def GetDesktopWindow(): + _GetDesktopWindow = windll.user32.GetDesktopWindow + _GetDesktopWindow.argtypes = [] + _GetDesktopWindow.restype = HWND + _GetDesktopWindow.errcheck = RaiseIfZero + return _GetDesktopWindow() + +# HWND GetForegroundWindow(VOID); +def GetForegroundWindow(): + _GetForegroundWindow = windll.user32.GetForegroundWindow + _GetForegroundWindow.argtypes = [] + _GetForegroundWindow.restype = HWND + _GetForegroundWindow.errcheck = RaiseIfZero + return _GetForegroundWindow() + +# BOOL IsWindow( +# HWND hWnd +# ); +def IsWindow(hWnd): + _IsWindow = windll.user32.IsWindow + _IsWindow.argtypes = [HWND] + _IsWindow.restype = bool + return _IsWindow(hWnd) + +# BOOL IsWindowVisible( +# HWND hWnd +# ); +def IsWindowVisible(hWnd): + _IsWindowVisible = windll.user32.IsWindowVisible + _IsWindowVisible.argtypes = [HWND] + _IsWindowVisible.restype = bool + return _IsWindowVisible(hWnd) + +# BOOL IsWindowEnabled( +# HWND hWnd +# ); +def IsWindowEnabled(hWnd): + _IsWindowEnabled = windll.user32.IsWindowEnabled + _IsWindowEnabled.argtypes = [HWND] + _IsWindowEnabled.restype = bool + return _IsWindowEnabled(hWnd) + +# BOOL IsZoomed( +# HWND hWnd +# ); +def IsZoomed(hWnd): + _IsZoomed = windll.user32.IsZoomed + _IsZoomed.argtypes = [HWND] + _IsZoomed.restype = bool + return _IsZoomed(hWnd) + +# BOOL IsIconic( +# HWND hWnd +# ); +def IsIconic(hWnd): + _IsIconic = windll.user32.IsIconic + _IsIconic.argtypes = [HWND] + _IsIconic.restype = bool + return _IsIconic(hWnd) + +# BOOL IsChild( +# HWND hWnd +# ); +def IsChild(hWnd): + _IsChild = windll.user32.IsChild + _IsChild.argtypes = [HWND] + _IsChild.restype = bool + return _IsChild(hWnd) + +# HWND WindowFromPoint( +# POINT Point +# ); +def WindowFromPoint(point): + _WindowFromPoint = windll.user32.WindowFromPoint + _WindowFromPoint.argtypes = [POINT] + _WindowFromPoint.restype = HWND + _WindowFromPoint.errcheck = RaiseIfZero + if isinstance(point, tuple): + point = POINT(*point) + return _WindowFromPoint(point) + +# HWND ChildWindowFromPoint( +# HWND hWndParent, +# POINT Point +# ); +def ChildWindowFromPoint(hWndParent, point): + _ChildWindowFromPoint = windll.user32.ChildWindowFromPoint + _ChildWindowFromPoint.argtypes = [HWND, POINT] + _ChildWindowFromPoint.restype = HWND + _ChildWindowFromPoint.errcheck = RaiseIfZero + if isinstance(point, tuple): + point = POINT(*point) + return _ChildWindowFromPoint(hWndParent, point) + +#HWND RealChildWindowFromPoint( +# HWND hwndParent, +# POINT ptParentClientCoords +#); +def RealChildWindowFromPoint(hWndParent, ptParentClientCoords): + _RealChildWindowFromPoint = windll.user32.RealChildWindowFromPoint + _RealChildWindowFromPoint.argtypes = [HWND, POINT] + _RealChildWindowFromPoint.restype = HWND + _RealChildWindowFromPoint.errcheck = RaiseIfZero + if isinstance(ptParentClientCoords, tuple): + ptParentClientCoords = POINT(*ptParentClientCoords) + return _RealChildWindowFromPoint(hWndParent, ptParentClientCoords) + +# BOOL ScreenToClient( +# __in HWND hWnd, +# LPPOINT lpPoint +# ); +def ScreenToClient(hWnd, lpPoint): + _ScreenToClient = windll.user32.ScreenToClient + _ScreenToClient.argtypes = [HWND, LPPOINT] + _ScreenToClient.restype = bool + _ScreenToClient.errcheck = RaiseIfZero + + if isinstance(lpPoint, tuple): + lpPoint = POINT(*lpPoint) + else: + lpPoint = POINT(lpPoint.x, lpPoint.y) + _ScreenToClient(hWnd, byref(lpPoint)) + return Point(lpPoint.x, lpPoint.y) + +# BOOL ClientToScreen( +# HWND hWnd, +# LPPOINT lpPoint +# ); +def ClientToScreen(hWnd, lpPoint): + _ClientToScreen = windll.user32.ClientToScreen + _ClientToScreen.argtypes = [HWND, LPPOINT] + _ClientToScreen.restype = bool + _ClientToScreen.errcheck = RaiseIfZero + + if isinstance(lpPoint, tuple): + lpPoint = POINT(*lpPoint) + else: + lpPoint = POINT(lpPoint.x, lpPoint.y) + _ClientToScreen(hWnd, byref(lpPoint)) + return Point(lpPoint.x, lpPoint.y) + +# int MapWindowPoints( +# __in HWND hWndFrom, +# __in HWND hWndTo, +# __inout LPPOINT lpPoints, +# __in UINT cPoints +# ); +def MapWindowPoints(hWndFrom, hWndTo, lpPoints): + _MapWindowPoints = windll.user32.MapWindowPoints + _MapWindowPoints.argtypes = [HWND, HWND, LPPOINT, UINT] + _MapWindowPoints.restype = ctypes.c_int + + cPoints = len(lpPoints) + lpPoints = (POINT * cPoints)(* lpPoints) + SetLastError(ERROR_SUCCESS) + number = _MapWindowPoints(hWndFrom, hWndTo, byref(lpPoints), cPoints) + if number == 0: + errcode = GetLastError() + if errcode != ERROR_SUCCESS: + raise ctypes.WinError(errcode) + x_delta = number & 0xFFFF + y_delta = (number >> 16) & 0xFFFF + return x_delta, y_delta, [ (Point.x, Point.y) for Point in lpPoints ] + +#BOOL SetForegroundWindow( +# HWND hWnd +#); +def SetForegroundWindow(hWnd): + _SetForegroundWindow = windll.user32.SetForegroundWindow + _SetForegroundWindow.argtypes = [HWND] + _SetForegroundWindow.restype = bool + _SetForegroundWindow.errcheck = RaiseIfZero + return _SetForegroundWindow(hWnd) + +# BOOL GetWindowPlacement( +# HWND hWnd, +# WINDOWPLACEMENT *lpwndpl +# ); +def GetWindowPlacement(hWnd): + _GetWindowPlacement = windll.user32.GetWindowPlacement + _GetWindowPlacement.argtypes = [HWND, PWINDOWPLACEMENT] + _GetWindowPlacement.restype = bool + _GetWindowPlacement.errcheck = RaiseIfZero + + lpwndpl = WINDOWPLACEMENT() + lpwndpl.length = sizeof(lpwndpl) + _GetWindowPlacement(hWnd, byref(lpwndpl)) + return WindowPlacement(lpwndpl) + +# BOOL SetWindowPlacement( +# HWND hWnd, +# WINDOWPLACEMENT *lpwndpl +# ); +def SetWindowPlacement(hWnd, lpwndpl): + _SetWindowPlacement = windll.user32.SetWindowPlacement + _SetWindowPlacement.argtypes = [HWND, PWINDOWPLACEMENT] + _SetWindowPlacement.restype = bool + _SetWindowPlacement.errcheck = RaiseIfZero + + if isinstance(lpwndpl, WINDOWPLACEMENT): + lpwndpl.length = sizeof(lpwndpl) + _SetWindowPlacement(hWnd, byref(lpwndpl)) + +# BOOL WINAPI GetWindowRect( +# __in HWND hWnd, +# __out LPRECT lpRect +# ); +def GetWindowRect(hWnd): + _GetWindowRect = windll.user32.GetWindowRect + _GetWindowRect.argtypes = [HWND, LPRECT] + _GetWindowRect.restype = bool + _GetWindowRect.errcheck = RaiseIfZero + + lpRect = RECT() + _GetWindowRect(hWnd, byref(lpRect)) + return Rect(lpRect.left, lpRect.top, lpRect.right, lpRect.bottom) + +# BOOL WINAPI GetClientRect( +# __in HWND hWnd, +# __out LPRECT lpRect +# ); +def GetClientRect(hWnd): + _GetClientRect = windll.user32.GetClientRect + _GetClientRect.argtypes = [HWND, LPRECT] + _GetClientRect.restype = bool + _GetClientRect.errcheck = RaiseIfZero + + lpRect = RECT() + _GetClientRect(hWnd, byref(lpRect)) + return Rect(lpRect.left, lpRect.top, lpRect.right, lpRect.bottom) + +#BOOL MoveWindow( +# HWND hWnd, +# int X, +# int Y, +# int nWidth, +# int nHeight, +# BOOL bRepaint +#); +def MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint = True): + _MoveWindow = windll.user32.MoveWindow + _MoveWindow.argtypes = [HWND, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, BOOL] + _MoveWindow.restype = bool + _MoveWindow.errcheck = RaiseIfZero + _MoveWindow(hWnd, X, Y, nWidth, nHeight, bool(bRepaint)) + +# BOOL GetGUIThreadInfo( +# DWORD idThread, +# LPGUITHREADINFO lpgui +# ); +def GetGUIThreadInfo(idThread): + _GetGUIThreadInfo = windll.user32.GetGUIThreadInfo + _GetGUIThreadInfo.argtypes = [DWORD, LPGUITHREADINFO] + _GetGUIThreadInfo.restype = bool + _GetGUIThreadInfo.errcheck = RaiseIfZero + + gui = GUITHREADINFO() + _GetGUIThreadInfo(idThread, byref(gui)) + return gui + +# BOOL CALLBACK EnumWndProc( +# HWND hwnd, +# LPARAM lParam +# ); +class __EnumWndProc (__WindowEnumerator): + pass + +# BOOL EnumWindows( +# WNDENUMPROC lpEnumFunc, +# LPARAM lParam +# ); +def EnumWindows(): + _EnumWindows = windll.user32.EnumWindows + _EnumWindows.argtypes = [WNDENUMPROC, LPARAM] + _EnumWindows.restype = bool + + EnumFunc = __EnumWndProc() + lpEnumFunc = WNDENUMPROC(EnumFunc) + if not _EnumWindows(lpEnumFunc, NULL): + errcode = GetLastError() + if errcode not in (ERROR_NO_MORE_FILES, ERROR_SUCCESS): + raise ctypes.WinError(errcode) + return EnumFunc.hwnd + +# BOOL CALLBACK EnumThreadWndProc( +# HWND hwnd, +# LPARAM lParam +# ); +class __EnumThreadWndProc (__WindowEnumerator): + pass + +# BOOL EnumThreadWindows( +# DWORD dwThreadId, +# WNDENUMPROC lpfn, +# LPARAM lParam +# ); +def EnumThreadWindows(dwThreadId): + _EnumThreadWindows = windll.user32.EnumThreadWindows + _EnumThreadWindows.argtypes = [DWORD, WNDENUMPROC, LPARAM] + _EnumThreadWindows.restype = bool + + fn = __EnumThreadWndProc() + lpfn = WNDENUMPROC(fn) + if not _EnumThreadWindows(dwThreadId, lpfn, NULL): + errcode = GetLastError() + if errcode not in (ERROR_NO_MORE_FILES, ERROR_SUCCESS): + raise ctypes.WinError(errcode) + return fn.hwnd + +# BOOL CALLBACK EnumChildProc( +# HWND hwnd, +# LPARAM lParam +# ); +class __EnumChildProc (__WindowEnumerator): + pass + +# BOOL EnumChildWindows( +# HWND hWndParent, +# WNDENUMPROC lpEnumFunc, +# LPARAM lParam +# ); +def EnumChildWindows(hWndParent = NULL): + _EnumChildWindows = windll.user32.EnumChildWindows + _EnumChildWindows.argtypes = [HWND, WNDENUMPROC, LPARAM] + _EnumChildWindows.restype = bool + + EnumFunc = __EnumChildProc() + lpEnumFunc = WNDENUMPROC(EnumFunc) + SetLastError(ERROR_SUCCESS) + _EnumChildWindows(hWndParent, lpEnumFunc, NULL) + errcode = GetLastError() + if errcode != ERROR_SUCCESS and errcode not in (ERROR_NO_MORE_FILES, ERROR_SUCCESS): + raise ctypes.WinError(errcode) + return EnumFunc.hwnd + +# LRESULT SendMessage( +# HWND hWnd, +# UINT Msg, +# WPARAM wParam, +# LPARAM lParam +# ); +def SendMessageA(hWnd, Msg, wParam = 0, lParam = 0): + _SendMessageA = windll.user32.SendMessageA + _SendMessageA.argtypes = [HWND, UINT, WPARAM, LPARAM] + _SendMessageA.restype = LRESULT + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + return _SendMessageA(hWnd, Msg, wParam, lParam) + +def SendMessageW(hWnd, Msg, wParam = 0, lParam = 0): + _SendMessageW = windll.user32.SendMessageW + _SendMessageW.argtypes = [HWND, UINT, WPARAM, LPARAM] + _SendMessageW.restype = LRESULT + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + return _SendMessageW(hWnd, Msg, wParam, lParam) + +SendMessage = GuessStringType(SendMessageA, SendMessageW) + +# BOOL PostMessage( +# HWND hWnd, +# UINT Msg, +# WPARAM wParam, +# LPARAM lParam +# ); +def PostMessageA(hWnd, Msg, wParam = 0, lParam = 0): + _PostMessageA = windll.user32.PostMessageA + _PostMessageA.argtypes = [HWND, UINT, WPARAM, LPARAM] + _PostMessageA.restype = bool + _PostMessageA.errcheck = RaiseIfZero + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + _PostMessageA(hWnd, Msg, wParam, lParam) + +def PostMessageW(hWnd, Msg, wParam = 0, lParam = 0): + _PostMessageW = windll.user32.PostMessageW + _PostMessageW.argtypes = [HWND, UINT, WPARAM, LPARAM] + _PostMessageW.restype = bool + _PostMessageW.errcheck = RaiseIfZero + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + _PostMessageW(hWnd, Msg, wParam, lParam) + +PostMessage = GuessStringType(PostMessageA, PostMessageW) + +# BOOL PostThreadMessage( +# DWORD idThread, +# UINT Msg, +# WPARAM wParam, +# LPARAM lParam +# ); +def PostThreadMessageA(idThread, Msg, wParam = 0, lParam = 0): + _PostThreadMessageA = windll.user32.PostThreadMessageA + _PostThreadMessageA.argtypes = [DWORD, UINT, WPARAM, LPARAM] + _PostThreadMessageA.restype = bool + _PostThreadMessageA.errcheck = RaiseIfZero + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + _PostThreadMessageA(idThread, Msg, wParam, lParam) + +def PostThreadMessageW(idThread, Msg, wParam = 0, lParam = 0): + _PostThreadMessageW = windll.user32.PostThreadMessageW + _PostThreadMessageW.argtypes = [DWORD, UINT, WPARAM, LPARAM] + _PostThreadMessageW.restype = bool + _PostThreadMessageW.errcheck = RaiseIfZero + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + _PostThreadMessageW(idThread, Msg, wParam, lParam) + +PostThreadMessage = GuessStringType(PostThreadMessageA, PostThreadMessageW) + +# LRESULT c( +# HWND hWnd, +# UINT Msg, +# WPARAM wParam, +# LPARAM lParam, +# UINT fuFlags, +# UINT uTimeout, +# PDWORD_PTR lpdwResult +# ); +def SendMessageTimeoutA(hWnd, Msg, wParam = 0, lParam = 0, fuFlags = 0, uTimeout = 0): + _SendMessageTimeoutA = windll.user32.SendMessageTimeoutA + _SendMessageTimeoutA.argtypes = [HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR] + _SendMessageTimeoutA.restype = LRESULT + _SendMessageTimeoutA.errcheck = RaiseIfZero + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + dwResult = DWORD(0) + _SendMessageTimeoutA(hWnd, Msg, wParam, lParam, fuFlags, uTimeout, byref(dwResult)) + return dwResult.value + +def SendMessageTimeoutW(hWnd, Msg, wParam = 0, lParam = 0): + _SendMessageTimeoutW = windll.user32.SendMessageTimeoutW + _SendMessageTimeoutW.argtypes = [HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR] + _SendMessageTimeoutW.restype = LRESULT + _SendMessageTimeoutW.errcheck = RaiseIfZero + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + dwResult = DWORD(0) + _SendMessageTimeoutW(hWnd, Msg, wParam, lParam, fuFlags, uTimeout, byref(dwResult)) + return dwResult.value + +SendMessageTimeout = GuessStringType(SendMessageTimeoutA, SendMessageTimeoutW) + +# BOOL SendNotifyMessage( +# HWND hWnd, +# UINT Msg, +# WPARAM wParam, +# LPARAM lParam +# ); +def SendNotifyMessageA(hWnd, Msg, wParam = 0, lParam = 0): + _SendNotifyMessageA = windll.user32.SendNotifyMessageA + _SendNotifyMessageA.argtypes = [HWND, UINT, WPARAM, LPARAM] + _SendNotifyMessageA.restype = bool + _SendNotifyMessageA.errcheck = RaiseIfZero + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + _SendNotifyMessageA(hWnd, Msg, wParam, lParam) + +def SendNotifyMessageW(hWnd, Msg, wParam = 0, lParam = 0): + _SendNotifyMessageW = windll.user32.SendNotifyMessageW + _SendNotifyMessageW.argtypes = [HWND, UINT, WPARAM, LPARAM] + _SendNotifyMessageW.restype = bool + _SendNotifyMessageW.errcheck = RaiseIfZero + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + _SendNotifyMessageW(hWnd, Msg, wParam, lParam) + +SendNotifyMessage = GuessStringType(SendNotifyMessageA, SendNotifyMessageW) + +# LRESULT SendDlgItemMessage( +# HWND hDlg, +# int nIDDlgItem, +# UINT Msg, +# WPARAM wParam, +# LPARAM lParam +# ); +def SendDlgItemMessageA(hDlg, nIDDlgItem, Msg, wParam = 0, lParam = 0): + _SendDlgItemMessageA = windll.user32.SendDlgItemMessageA + _SendDlgItemMessageA.argtypes = [HWND, ctypes.c_int, UINT, WPARAM, LPARAM] + _SendDlgItemMessageA.restype = LRESULT + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + return _SendDlgItemMessageA(hDlg, nIDDlgItem, Msg, wParam, lParam) + +def SendDlgItemMessageW(hDlg, nIDDlgItem, Msg, wParam = 0, lParam = 0): + _SendDlgItemMessageW = windll.user32.SendDlgItemMessageW + _SendDlgItemMessageW.argtypes = [HWND, ctypes.c_int, UINT, WPARAM, LPARAM] + _SendDlgItemMessageW.restype = LRESULT + + wParam = MAKE_WPARAM(wParam) + lParam = MAKE_LPARAM(lParam) + return _SendDlgItemMessageW(hDlg, nIDDlgItem, Msg, wParam, lParam) + +SendDlgItemMessage = GuessStringType(SendDlgItemMessageA, SendDlgItemMessageW) + +# DWORD WINAPI WaitForInputIdle( +# _In_ HANDLE hProcess, +# _In_ DWORD dwMilliseconds +# ); +def WaitForInputIdle(hProcess, dwMilliseconds = INFINITE): + _WaitForInputIdle = windll.user32.WaitForInputIdle + _WaitForInputIdle.argtypes = [HANDLE, DWORD] + _WaitForInputIdle.restype = DWORD + + r = _WaitForInputIdle(hProcess, dwMilliseconds) + if r == WAIT_FAILED: + raise ctypes.WinError() + return r + +# UINT RegisterWindowMessage( +# LPCTSTR lpString +# ); +def RegisterWindowMessageA(lpString): + _RegisterWindowMessageA = windll.user32.RegisterWindowMessageA + _RegisterWindowMessageA.argtypes = [LPSTR] + _RegisterWindowMessageA.restype = UINT + _RegisterWindowMessageA.errcheck = RaiseIfZero + return _RegisterWindowMessageA(lpString) + +def RegisterWindowMessageW(lpString): + _RegisterWindowMessageW = windll.user32.RegisterWindowMessageW + _RegisterWindowMessageW.argtypes = [LPWSTR] + _RegisterWindowMessageW.restype = UINT + _RegisterWindowMessageW.errcheck = RaiseIfZero + return _RegisterWindowMessageW(lpString) + +RegisterWindowMessage = GuessStringType(RegisterWindowMessageA, RegisterWindowMessageW) + +# UINT RegisterClipboardFormat( +# LPCTSTR lpString +# ); +def RegisterClipboardFormatA(lpString): + _RegisterClipboardFormatA = windll.user32.RegisterClipboardFormatA + _RegisterClipboardFormatA.argtypes = [LPSTR] + _RegisterClipboardFormatA.restype = UINT + _RegisterClipboardFormatA.errcheck = RaiseIfZero + return _RegisterClipboardFormatA(lpString) + +def RegisterClipboardFormatW(lpString): + _RegisterClipboardFormatW = windll.user32.RegisterClipboardFormatW + _RegisterClipboardFormatW.argtypes = [LPWSTR] + _RegisterClipboardFormatW.restype = UINT + _RegisterClipboardFormatW.errcheck = RaiseIfZero + return _RegisterClipboardFormatW(lpString) + +RegisterClipboardFormat = GuessStringType(RegisterClipboardFormatA, RegisterClipboardFormatW) + +# HANDLE WINAPI GetProp( +# __in HWND hWnd, +# __in LPCTSTR lpString +# ); +def GetPropA(hWnd, lpString): + _GetPropA = windll.user32.GetPropA + _GetPropA.argtypes = [HWND, LPSTR] + _GetPropA.restype = HANDLE + return _GetPropA(hWnd, lpString) + +def GetPropW(hWnd, lpString): + _GetPropW = windll.user32.GetPropW + _GetPropW.argtypes = [HWND, LPWSTR] + _GetPropW.restype = HANDLE + return _GetPropW(hWnd, lpString) + +GetProp = GuessStringType(GetPropA, GetPropW) + +# BOOL WINAPI SetProp( +# __in HWND hWnd, +# __in LPCTSTR lpString, +# __in_opt HANDLE hData +# ); +def SetPropA(hWnd, lpString, hData): + _SetPropA = windll.user32.SetPropA + _SetPropA.argtypes = [HWND, LPSTR, HANDLE] + _SetPropA.restype = BOOL + _SetPropA.errcheck = RaiseIfZero + _SetPropA(hWnd, lpString, hData) + +def SetPropW(hWnd, lpString, hData): + _SetPropW = windll.user32.SetPropW + _SetPropW.argtypes = [HWND, LPWSTR, HANDLE] + _SetPropW.restype = BOOL + _SetPropW.errcheck = RaiseIfZero + _SetPropW(hWnd, lpString, hData) + +SetProp = GuessStringType(SetPropA, SetPropW) + +# HANDLE WINAPI RemoveProp( +# __in HWND hWnd, +# __in LPCTSTR lpString +# ); +def RemovePropA(hWnd, lpString): + _RemovePropA = windll.user32.RemovePropA + _RemovePropA.argtypes = [HWND, LPSTR] + _RemovePropA.restype = HANDLE + return _RemovePropA(hWnd, lpString) + +def RemovePropW(hWnd, lpString): + _RemovePropW = windll.user32.RemovePropW + _RemovePropW.argtypes = [HWND, LPWSTR] + _RemovePropW.restype = HANDLE + return _RemovePropW(hWnd, lpString) + +RemoveProp = GuessStringType(RemovePropA, RemovePropW) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/version.py b/pydevd_attach_to_process/winappdbg/win32/version.py new file mode 100644 index 0000000..19b6d53 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/version.py @@ -0,0 +1,1038 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Detect the current architecture and operating system. + +Some functions here are really from kernel32.dll, others from version.dll. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- NTDDI version ------------------------------------------------------------ + +NTDDI_WIN8 = 0x06020000 +NTDDI_WIN7SP1 = 0x06010100 +NTDDI_WIN7 = 0x06010000 +NTDDI_WS08 = 0x06000100 +NTDDI_VISTASP1 = 0x06000100 +NTDDI_VISTA = 0x06000000 +NTDDI_LONGHORN = NTDDI_VISTA +NTDDI_WS03SP2 = 0x05020200 +NTDDI_WS03SP1 = 0x05020100 +NTDDI_WS03 = 0x05020000 +NTDDI_WINXPSP3 = 0x05010300 +NTDDI_WINXPSP2 = 0x05010200 +NTDDI_WINXPSP1 = 0x05010100 +NTDDI_WINXP = 0x05010000 +NTDDI_WIN2KSP4 = 0x05000400 +NTDDI_WIN2KSP3 = 0x05000300 +NTDDI_WIN2KSP2 = 0x05000200 +NTDDI_WIN2KSP1 = 0x05000100 +NTDDI_WIN2K = 0x05000000 +NTDDI_WINNT4 = 0x04000000 + +OSVERSION_MASK = 0xFFFF0000 +SPVERSION_MASK = 0x0000FF00 +SUBVERSION_MASK = 0x000000FF + +#--- OSVERSIONINFO and OSVERSIONINFOEX structures and constants --------------- + +VER_PLATFORM_WIN32s = 0 +VER_PLATFORM_WIN32_WINDOWS = 1 +VER_PLATFORM_WIN32_NT = 2 + +VER_SUITE_BACKOFFICE = 0x00000004 +VER_SUITE_BLADE = 0x00000400 +VER_SUITE_COMPUTE_SERVER = 0x00004000 +VER_SUITE_DATACENTER = 0x00000080 +VER_SUITE_ENTERPRISE = 0x00000002 +VER_SUITE_EMBEDDEDNT = 0x00000040 +VER_SUITE_PERSONAL = 0x00000200 +VER_SUITE_SINGLEUSERTS = 0x00000100 +VER_SUITE_SMALLBUSINESS = 0x00000001 +VER_SUITE_SMALLBUSINESS_RESTRICTED = 0x00000020 +VER_SUITE_STORAGE_SERVER = 0x00002000 +VER_SUITE_TERMINAL = 0x00000010 +VER_SUITE_WH_SERVER = 0x00008000 + +VER_NT_DOMAIN_CONTROLLER = 0x0000002 +VER_NT_SERVER = 0x0000003 +VER_NT_WORKSTATION = 0x0000001 + +VER_BUILDNUMBER = 0x0000004 +VER_MAJORVERSION = 0x0000002 +VER_MINORVERSION = 0x0000001 +VER_PLATFORMID = 0x0000008 +VER_PRODUCT_TYPE = 0x0000080 +VER_SERVICEPACKMAJOR = 0x0000020 +VER_SERVICEPACKMINOR = 0x0000010 +VER_SUITENAME = 0x0000040 + +VER_EQUAL = 1 +VER_GREATER = 2 +VER_GREATER_EQUAL = 3 +VER_LESS = 4 +VER_LESS_EQUAL = 5 +VER_AND = 6 +VER_OR = 7 + +# typedef struct _OSVERSIONINFO { +# DWORD dwOSVersionInfoSize; +# DWORD dwMajorVersion; +# DWORD dwMinorVersion; +# DWORD dwBuildNumber; +# DWORD dwPlatformId; +# TCHAR szCSDVersion[128]; +# }OSVERSIONINFO; +class OSVERSIONINFOA(Structure): + _fields_ = [ + ("dwOSVersionInfoSize", DWORD), + ("dwMajorVersion", DWORD), + ("dwMinorVersion", DWORD), + ("dwBuildNumber", DWORD), + ("dwPlatformId", DWORD), + ("szCSDVersion", CHAR * 128), + ] +class OSVERSIONINFOW(Structure): + _fields_ = [ + ("dwOSVersionInfoSize", DWORD), + ("dwMajorVersion", DWORD), + ("dwMinorVersion", DWORD), + ("dwBuildNumber", DWORD), + ("dwPlatformId", DWORD), + ("szCSDVersion", WCHAR * 128), + ] + +# typedef struct _OSVERSIONINFOEX { +# DWORD dwOSVersionInfoSize; +# DWORD dwMajorVersion; +# DWORD dwMinorVersion; +# DWORD dwBuildNumber; +# DWORD dwPlatformId; +# TCHAR szCSDVersion[128]; +# WORD wServicePackMajor; +# WORD wServicePackMinor; +# WORD wSuiteMask; +# BYTE wProductType; +# BYTE wReserved; +# }OSVERSIONINFOEX, *POSVERSIONINFOEX, *LPOSVERSIONINFOEX; +class OSVERSIONINFOEXA(Structure): + _fields_ = [ + ("dwOSVersionInfoSize", DWORD), + ("dwMajorVersion", DWORD), + ("dwMinorVersion", DWORD), + ("dwBuildNumber", DWORD), + ("dwPlatformId", DWORD), + ("szCSDVersion", CHAR * 128), + ("wServicePackMajor", WORD), + ("wServicePackMinor", WORD), + ("wSuiteMask", WORD), + ("wProductType", BYTE), + ("wReserved", BYTE), + ] +class OSVERSIONINFOEXW(Structure): + _fields_ = [ + ("dwOSVersionInfoSize", DWORD), + ("dwMajorVersion", DWORD), + ("dwMinorVersion", DWORD), + ("dwBuildNumber", DWORD), + ("dwPlatformId", DWORD), + ("szCSDVersion", WCHAR * 128), + ("wServicePackMajor", WORD), + ("wServicePackMinor", WORD), + ("wSuiteMask", WORD), + ("wProductType", BYTE), + ("wReserved", BYTE), + ] + +LPOSVERSIONINFOA = POINTER(OSVERSIONINFOA) +LPOSVERSIONINFOW = POINTER(OSVERSIONINFOW) +LPOSVERSIONINFOEXA = POINTER(OSVERSIONINFOEXA) +LPOSVERSIONINFOEXW = POINTER(OSVERSIONINFOEXW) +POSVERSIONINFOA = LPOSVERSIONINFOA +POSVERSIONINFOW = LPOSVERSIONINFOW +POSVERSIONINFOEXA = LPOSVERSIONINFOEXA +POSVERSIONINFOEXW = LPOSVERSIONINFOA + +#--- GetSystemMetrics constants ----------------------------------------------- + +SM_CXSCREEN = 0 +SM_CYSCREEN = 1 +SM_CXVSCROLL = 2 +SM_CYHSCROLL = 3 +SM_CYCAPTION = 4 +SM_CXBORDER = 5 +SM_CYBORDER = 6 +SM_CXDLGFRAME = 7 +SM_CYDLGFRAME = 8 +SM_CYVTHUMB = 9 +SM_CXHTHUMB = 10 +SM_CXICON = 11 +SM_CYICON = 12 +SM_CXCURSOR = 13 +SM_CYCURSOR = 14 +SM_CYMENU = 15 +SM_CXFULLSCREEN = 16 +SM_CYFULLSCREEN = 17 +SM_CYKANJIWINDOW = 18 +SM_MOUSEPRESENT = 19 +SM_CYVSCROLL = 20 +SM_CXHSCROLL = 21 +SM_DEBUG = 22 +SM_SWAPBUTTON = 23 +SM_RESERVED1 = 24 +SM_RESERVED2 = 25 +SM_RESERVED3 = 26 +SM_RESERVED4 = 27 +SM_CXMIN = 28 +SM_CYMIN = 29 +SM_CXSIZE = 30 +SM_CYSIZE = 31 +SM_CXFRAME = 32 +SM_CYFRAME = 33 +SM_CXMINTRACK = 34 +SM_CYMINTRACK = 35 +SM_CXDOUBLECLK = 36 +SM_CYDOUBLECLK = 37 +SM_CXICONSPACING = 38 +SM_CYICONSPACING = 39 +SM_MENUDROPALIGNMENT = 40 +SM_PENWINDOWS = 41 +SM_DBCSENABLED = 42 +SM_CMOUSEBUTTONS = 43 + +SM_CXFIXEDFRAME = SM_CXDLGFRAME # ;win40 name change +SM_CYFIXEDFRAME = SM_CYDLGFRAME # ;win40 name change +SM_CXSIZEFRAME = SM_CXFRAME # ;win40 name change +SM_CYSIZEFRAME = SM_CYFRAME # ;win40 name change + +SM_SECURE = 44 +SM_CXEDGE = 45 +SM_CYEDGE = 46 +SM_CXMINSPACING = 47 +SM_CYMINSPACING = 48 +SM_CXSMICON = 49 +SM_CYSMICON = 50 +SM_CYSMCAPTION = 51 +SM_CXSMSIZE = 52 +SM_CYSMSIZE = 53 +SM_CXMENUSIZE = 54 +SM_CYMENUSIZE = 55 +SM_ARRANGE = 56 +SM_CXMINIMIZED = 57 +SM_CYMINIMIZED = 58 +SM_CXMAXTRACK = 59 +SM_CYMAXTRACK = 60 +SM_CXMAXIMIZED = 61 +SM_CYMAXIMIZED = 62 +SM_NETWORK = 63 +SM_CLEANBOOT = 67 +SM_CXDRAG = 68 +SM_CYDRAG = 69 +SM_SHOWSOUNDS = 70 +SM_CXMENUCHECK = 71 # Use instead of GetMenuCheckMarkDimensions()! +SM_CYMENUCHECK = 72 +SM_SLOWMACHINE = 73 +SM_MIDEASTENABLED = 74 +SM_MOUSEWHEELPRESENT = 75 +SM_XVIRTUALSCREEN = 76 +SM_YVIRTUALSCREEN = 77 +SM_CXVIRTUALSCREEN = 78 +SM_CYVIRTUALSCREEN = 79 +SM_CMONITORS = 80 +SM_SAMEDISPLAYFORMAT = 81 +SM_IMMENABLED = 82 +SM_CXFOCUSBORDER = 83 +SM_CYFOCUSBORDER = 84 +SM_TABLETPC = 86 +SM_MEDIACENTER = 87 +SM_STARTER = 88 +SM_SERVERR2 = 89 +SM_MOUSEHORIZONTALWHEELPRESENT = 91 +SM_CXPADDEDBORDER = 92 + +SM_CMETRICS = 93 + +SM_REMOTESESSION = 0x1000 +SM_SHUTTINGDOWN = 0x2000 +SM_REMOTECONTROL = 0x2001 +SM_CARETBLINKINGENABLED = 0x2002 + +#--- SYSTEM_INFO structure, GetSystemInfo() and GetNativeSystemInfo() --------- + +# Values used by Wine +# Documented values at MSDN are marked with an asterisk +PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF; # Unknown architecture. +PROCESSOR_ARCHITECTURE_INTEL = 0 # x86 (AMD or Intel) * +PROCESSOR_ARCHITECTURE_MIPS = 1 # MIPS +PROCESSOR_ARCHITECTURE_ALPHA = 2 # Alpha +PROCESSOR_ARCHITECTURE_PPC = 3 # Power PC +PROCESSOR_ARCHITECTURE_SHX = 4 # SHX +PROCESSOR_ARCHITECTURE_ARM = 5 # ARM +PROCESSOR_ARCHITECTURE_IA64 = 6 # Intel Itanium * +PROCESSOR_ARCHITECTURE_ALPHA64 = 7 # Alpha64 +PROCESSOR_ARCHITECTURE_MSIL = 8 # MSIL +PROCESSOR_ARCHITECTURE_AMD64 = 9 # x64 (AMD or Intel) * +PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 = 10 # IA32 on Win64 +PROCESSOR_ARCHITECTURE_SPARC = 20 # Sparc (Wine) + +# Values used by Wine +# PROCESSOR_OPTIL value found at http://code.google.com/p/ddab-lib/ +# Documented values at MSDN are marked with an asterisk +PROCESSOR_INTEL_386 = 386 # Intel i386 * +PROCESSOR_INTEL_486 = 486 # Intel i486 * +PROCESSOR_INTEL_PENTIUM = 586 # Intel Pentium * +PROCESSOR_INTEL_IA64 = 2200 # Intel IA64 (Itanium) * +PROCESSOR_AMD_X8664 = 8664 # AMD X86 64 * +PROCESSOR_MIPS_R4000 = 4000 # MIPS R4000, R4101, R3910 +PROCESSOR_ALPHA_21064 = 21064 # Alpha 210 64 +PROCESSOR_PPC_601 = 601 # PPC 601 +PROCESSOR_PPC_603 = 603 # PPC 603 +PROCESSOR_PPC_604 = 604 # PPC 604 +PROCESSOR_PPC_620 = 620 # PPC 620 +PROCESSOR_HITACHI_SH3 = 10003 # Hitachi SH3 (Windows CE) +PROCESSOR_HITACHI_SH3E = 10004 # Hitachi SH3E (Windows CE) +PROCESSOR_HITACHI_SH4 = 10005 # Hitachi SH4 (Windows CE) +PROCESSOR_MOTOROLA_821 = 821 # Motorola 821 (Windows CE) +PROCESSOR_SHx_SH3 = 103 # SHx SH3 (Windows CE) +PROCESSOR_SHx_SH4 = 104 # SHx SH4 (Windows CE) +PROCESSOR_STRONGARM = 2577 # StrongARM (Windows CE) +PROCESSOR_ARM720 = 1824 # ARM 720 (Windows CE) +PROCESSOR_ARM820 = 2080 # ARM 820 (Windows CE) +PROCESSOR_ARM920 = 2336 # ARM 920 (Windows CE) +PROCESSOR_ARM_7TDMI = 70001 # ARM 7TDMI (Windows CE) +PROCESSOR_OPTIL = 0x494F # MSIL + +# typedef struct _SYSTEM_INFO { +# union { +# DWORD dwOemId; +# struct { +# WORD wProcessorArchitecture; +# WORD wReserved; +# } ; +# } ; +# DWORD dwPageSize; +# LPVOID lpMinimumApplicationAddress; +# LPVOID lpMaximumApplicationAddress; +# DWORD_PTR dwActiveProcessorMask; +# DWORD dwNumberOfProcessors; +# DWORD dwProcessorType; +# DWORD dwAllocationGranularity; +# WORD wProcessorLevel; +# WORD wProcessorRevision; +# } SYSTEM_INFO; + +class _SYSTEM_INFO_OEM_ID_STRUCT(Structure): + _fields_ = [ + ("wProcessorArchitecture", WORD), + ("wReserved", WORD), +] + +class _SYSTEM_INFO_OEM_ID(Union): + _fields_ = [ + ("dwOemId", DWORD), + ("w", _SYSTEM_INFO_OEM_ID_STRUCT), +] + +class SYSTEM_INFO(Structure): + _fields_ = [ + ("id", _SYSTEM_INFO_OEM_ID), + ("dwPageSize", DWORD), + ("lpMinimumApplicationAddress", LPVOID), + ("lpMaximumApplicationAddress", LPVOID), + ("dwActiveProcessorMask", DWORD_PTR), + ("dwNumberOfProcessors", DWORD), + ("dwProcessorType", DWORD), + ("dwAllocationGranularity", DWORD), + ("wProcessorLevel", WORD), + ("wProcessorRevision", WORD), + ] + + def __get_dwOemId(self): + return self.id.dwOemId + def __set_dwOemId(self, value): + self.id.dwOemId = value + dwOemId = property(__get_dwOemId, __set_dwOemId) + + def __get_wProcessorArchitecture(self): + return self.id.w.wProcessorArchitecture + def __set_wProcessorArchitecture(self, value): + self.id.w.wProcessorArchitecture = value + wProcessorArchitecture = property(__get_wProcessorArchitecture, __set_wProcessorArchitecture) + +LPSYSTEM_INFO = ctypes.POINTER(SYSTEM_INFO) + +# void WINAPI GetSystemInfo( +# __out LPSYSTEM_INFO lpSystemInfo +# ); +def GetSystemInfo(): + _GetSystemInfo = windll.kernel32.GetSystemInfo + _GetSystemInfo.argtypes = [LPSYSTEM_INFO] + _GetSystemInfo.restype = None + + sysinfo = SYSTEM_INFO() + _GetSystemInfo(byref(sysinfo)) + return sysinfo + +# void WINAPI GetNativeSystemInfo( +# __out LPSYSTEM_INFO lpSystemInfo +# ); +def GetNativeSystemInfo(): + _GetNativeSystemInfo = windll.kernel32.GetNativeSystemInfo + _GetNativeSystemInfo.argtypes = [LPSYSTEM_INFO] + _GetNativeSystemInfo.restype = None + + sysinfo = SYSTEM_INFO() + _GetNativeSystemInfo(byref(sysinfo)) + return sysinfo + +# int WINAPI GetSystemMetrics( +# __in int nIndex +# ); +def GetSystemMetrics(nIndex): + _GetSystemMetrics = windll.user32.GetSystemMetrics + _GetSystemMetrics.argtypes = [ctypes.c_int] + _GetSystemMetrics.restype = ctypes.c_int + return _GetSystemMetrics(nIndex) + +# SIZE_T WINAPI GetLargePageMinimum(void); +def GetLargePageMinimum(): + _GetLargePageMinimum = windll.user32.GetLargePageMinimum + _GetLargePageMinimum.argtypes = [] + _GetLargePageMinimum.restype = SIZE_T + return _GetLargePageMinimum() + +# HANDLE WINAPI GetCurrentProcess(void); +def GetCurrentProcess(): +## return 0xFFFFFFFFFFFFFFFFL + _GetCurrentProcess = windll.kernel32.GetCurrentProcess + _GetCurrentProcess.argtypes = [] + _GetCurrentProcess.restype = HANDLE + return _GetCurrentProcess() + +# HANDLE WINAPI GetCurrentThread(void); +def GetCurrentThread(): +## return 0xFFFFFFFFFFFFFFFEL + _GetCurrentThread = windll.kernel32.GetCurrentThread + _GetCurrentThread.argtypes = [] + _GetCurrentThread.restype = HANDLE + return _GetCurrentThread() + +# BOOL WINAPI IsWow64Process( +# __in HANDLE hProcess, +# __out PBOOL Wow64Process +# ); +def IsWow64Process(hProcess): + _IsWow64Process = windll.kernel32.IsWow64Process + _IsWow64Process.argtypes = [HANDLE, PBOOL] + _IsWow64Process.restype = bool + _IsWow64Process.errcheck = RaiseIfZero + + Wow64Process = BOOL(FALSE) + _IsWow64Process(hProcess, byref(Wow64Process)) + return bool(Wow64Process) + +# DWORD WINAPI GetVersion(void); +def GetVersion(): + _GetVersion = windll.kernel32.GetVersion + _GetVersion.argtypes = [] + _GetVersion.restype = DWORD + _GetVersion.errcheck = RaiseIfZero + + # See the example code here: + # http://msdn.microsoft.com/en-us/library/ms724439(VS.85).aspx + + dwVersion = _GetVersion() + dwMajorVersion = dwVersion & 0x000000FF + dwMinorVersion = (dwVersion & 0x0000FF00) >> 8 + if (dwVersion & 0x80000000) == 0: + dwBuild = (dwVersion & 0x7FFF0000) >> 16 + else: + dwBuild = None + return int(dwMajorVersion), int(dwMinorVersion), int(dwBuild) + +# BOOL WINAPI GetVersionEx( +# __inout LPOSVERSIONINFO lpVersionInfo +# ); +def GetVersionExA(): + _GetVersionExA = windll.kernel32.GetVersionExA + _GetVersionExA.argtypes = [POINTER(OSVERSIONINFOEXA)] + _GetVersionExA.restype = bool + _GetVersionExA.errcheck = RaiseIfZero + + osi = OSVERSIONINFOEXA() + osi.dwOSVersionInfoSize = sizeof(osi) + try: + _GetVersionExA(byref(osi)) + except WindowsError: + osi = OSVERSIONINFOA() + osi.dwOSVersionInfoSize = sizeof(osi) + _GetVersionExA.argtypes = [POINTER(OSVERSIONINFOA)] + _GetVersionExA(byref(osi)) + return osi + +def GetVersionExW(): + _GetVersionExW = windll.kernel32.GetVersionExW + _GetVersionExW.argtypes = [POINTER(OSVERSIONINFOEXW)] + _GetVersionExW.restype = bool + _GetVersionExW.errcheck = RaiseIfZero + + osi = OSVERSIONINFOEXW() + osi.dwOSVersionInfoSize = sizeof(osi) + try: + _GetVersionExW(byref(osi)) + except WindowsError: + osi = OSVERSIONINFOW() + osi.dwOSVersionInfoSize = sizeof(osi) + _GetVersionExW.argtypes = [POINTER(OSVERSIONINFOW)] + _GetVersionExW(byref(osi)) + return osi + +GetVersionEx = GuessStringType(GetVersionExA, GetVersionExW) + +# BOOL WINAPI GetProductInfo( +# __in DWORD dwOSMajorVersion, +# __in DWORD dwOSMinorVersion, +# __in DWORD dwSpMajorVersion, +# __in DWORD dwSpMinorVersion, +# __out PDWORD pdwReturnedProductType +# ); +def GetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion): + _GetProductInfo = windll.kernel32.GetProductInfo + _GetProductInfo.argtypes = [DWORD, DWORD, DWORD, DWORD, PDWORD] + _GetProductInfo.restype = BOOL + _GetProductInfo.errcheck = RaiseIfZero + + dwReturnedProductType = DWORD(0) + _GetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion, byref(dwReturnedProductType)) + return dwReturnedProductType.value + +# BOOL WINAPI VerifyVersionInfo( +# __in LPOSVERSIONINFOEX lpVersionInfo, +# __in DWORD dwTypeMask, +# __in DWORDLONG dwlConditionMask +# ); +def VerifyVersionInfo(lpVersionInfo, dwTypeMask, dwlConditionMask): + if isinstance(lpVersionInfo, OSVERSIONINFOEXA): + return VerifyVersionInfoA(lpVersionInfo, dwTypeMask, dwlConditionMask) + if isinstance(lpVersionInfo, OSVERSIONINFOEXW): + return VerifyVersionInfoW(lpVersionInfo, dwTypeMask, dwlConditionMask) + raise TypeError("Bad OSVERSIONINFOEX structure") + +def VerifyVersionInfoA(lpVersionInfo, dwTypeMask, dwlConditionMask): + _VerifyVersionInfoA = windll.kernel32.VerifyVersionInfoA + _VerifyVersionInfoA.argtypes = [LPOSVERSIONINFOEXA, DWORD, DWORDLONG] + _VerifyVersionInfoA.restype = bool + return _VerifyVersionInfoA(byref(lpVersionInfo), dwTypeMask, dwlConditionMask) + +def VerifyVersionInfoW(lpVersionInfo, dwTypeMask, dwlConditionMask): + _VerifyVersionInfoW = windll.kernel32.VerifyVersionInfoW + _VerifyVersionInfoW.argtypes = [LPOSVERSIONINFOEXW, DWORD, DWORDLONG] + _VerifyVersionInfoW.restype = bool + return _VerifyVersionInfoW(byref(lpVersionInfo), dwTypeMask, dwlConditionMask) + +# ULONGLONG WINAPI VerSetConditionMask( +# __in ULONGLONG dwlConditionMask, +# __in DWORD dwTypeBitMask, +# __in BYTE dwConditionMask +# ); +def VerSetConditionMask(dwlConditionMask, dwTypeBitMask, dwConditionMask): + _VerSetConditionMask = windll.kernel32.VerSetConditionMask + _VerSetConditionMask.argtypes = [ULONGLONG, DWORD, BYTE] + _VerSetConditionMask.restype = ULONGLONG + return _VerSetConditionMask(dwlConditionMask, dwTypeBitMask, dwConditionMask) + +#--- get_bits, get_arch and get_os -------------------------------------------- + +ARCH_UNKNOWN = "unknown" +ARCH_I386 = "i386" +ARCH_MIPS = "mips" +ARCH_ALPHA = "alpha" +ARCH_PPC = "ppc" +ARCH_SHX = "shx" +ARCH_ARM = "arm" +ARCH_ARM64 = "arm64" +ARCH_THUMB = "thumb" +ARCH_IA64 = "ia64" +ARCH_ALPHA64 = "alpha64" +ARCH_MSIL = "msil" +ARCH_AMD64 = "amd64" +ARCH_SPARC = "sparc" + +# aliases +ARCH_IA32 = ARCH_I386 +ARCH_X86 = ARCH_I386 +ARCH_X64 = ARCH_AMD64 +ARCH_ARM7 = ARCH_ARM +ARCH_ARM8 = ARCH_ARM64 +ARCH_T32 = ARCH_THUMB +ARCH_AARCH32 = ARCH_ARM7 +ARCH_AARCH64 = ARCH_ARM8 +ARCH_POWERPC = ARCH_PPC +ARCH_HITACHI = ARCH_SHX +ARCH_ITANIUM = ARCH_IA64 + +# win32 constants -> our constants +_arch_map = { + PROCESSOR_ARCHITECTURE_INTEL : ARCH_I386, + PROCESSOR_ARCHITECTURE_MIPS : ARCH_MIPS, + PROCESSOR_ARCHITECTURE_ALPHA : ARCH_ALPHA, + PROCESSOR_ARCHITECTURE_PPC : ARCH_PPC, + PROCESSOR_ARCHITECTURE_SHX : ARCH_SHX, + PROCESSOR_ARCHITECTURE_ARM : ARCH_ARM, + PROCESSOR_ARCHITECTURE_IA64 : ARCH_IA64, + PROCESSOR_ARCHITECTURE_ALPHA64 : ARCH_ALPHA64, + PROCESSOR_ARCHITECTURE_MSIL : ARCH_MSIL, + PROCESSOR_ARCHITECTURE_AMD64 : ARCH_AMD64, + PROCESSOR_ARCHITECTURE_SPARC : ARCH_SPARC, +} + +OS_UNKNOWN = "Unknown" +OS_NT = "Windows NT" +OS_W2K = "Windows 2000" +OS_XP = "Windows XP" +OS_XP_64 = "Windows XP (64 bits)" +OS_W2K3 = "Windows 2003" +OS_W2K3_64 = "Windows 2003 (64 bits)" +OS_W2K3R2 = "Windows 2003 R2" +OS_W2K3R2_64 = "Windows 2003 R2 (64 bits)" +OS_W2K8 = "Windows 2008" +OS_W2K8_64 = "Windows 2008 (64 bits)" +OS_W2K8R2 = "Windows 2008 R2" +OS_W2K8R2_64 = "Windows 2008 R2 (64 bits)" +OS_VISTA = "Windows Vista" +OS_VISTA_64 = "Windows Vista (64 bits)" +OS_W7 = "Windows 7" +OS_W7_64 = "Windows 7 (64 bits)" + +OS_SEVEN = OS_W7 +OS_SEVEN_64 = OS_W7_64 + +OS_WINDOWS_NT = OS_NT +OS_WINDOWS_2000 = OS_W2K +OS_WINDOWS_XP = OS_XP +OS_WINDOWS_XP_64 = OS_XP_64 +OS_WINDOWS_2003 = OS_W2K3 +OS_WINDOWS_2003_64 = OS_W2K3_64 +OS_WINDOWS_2003_R2 = OS_W2K3R2 +OS_WINDOWS_2003_R2_64 = OS_W2K3R2_64 +OS_WINDOWS_2008 = OS_W2K8 +OS_WINDOWS_2008_64 = OS_W2K8_64 +OS_WINDOWS_2008_R2 = OS_W2K8R2 +OS_WINDOWS_2008_R2_64 = OS_W2K8R2_64 +OS_WINDOWS_VISTA = OS_VISTA +OS_WINDOWS_VISTA_64 = OS_VISTA_64 +OS_WINDOWS_SEVEN = OS_W7 +OS_WINDOWS_SEVEN_64 = OS_W7_64 + +def _get_bits(): + """ + Determines the current integer size in bits. + + This is useful to know if we're running in a 32 bits or a 64 bits machine. + + @rtype: int + @return: Returns the size of L{SIZE_T} in bits. + """ + return sizeof(SIZE_T) * 8 + +def _get_arch(): + """ + Determines the current processor architecture. + + @rtype: str + @return: + On error, returns: + + - L{ARCH_UNKNOWN} (C{"unknown"}) meaning the architecture could not be detected or is not known to WinAppDbg. + + On success, returns one of the following values: + + - L{ARCH_I386} (C{"i386"}) for Intel 32-bit x86 processor or compatible. + - L{ARCH_AMD64} (C{"amd64"}) for Intel 64-bit x86_64 processor or compatible. + + May also return one of the following values if you get both Python and + WinAppDbg to work in such machines... let me know if you do! :) + + - L{ARCH_MIPS} (C{"mips"}) for MIPS compatible processors. + - L{ARCH_ALPHA} (C{"alpha"}) for Alpha processors. + - L{ARCH_PPC} (C{"ppc"}) for PowerPC compatible processors. + - L{ARCH_SHX} (C{"shx"}) for Hitachi SH processors. + - L{ARCH_ARM} (C{"arm"}) for ARM compatible processors. + - L{ARCH_IA64} (C{"ia64"}) for Intel Itanium processor or compatible. + - L{ARCH_ALPHA64} (C{"alpha64"}) for Alpha64 processors. + - L{ARCH_MSIL} (C{"msil"}) for the .NET virtual machine. + - L{ARCH_SPARC} (C{"sparc"}) for Sun Sparc processors. + + Probably IronPython returns C{ARCH_MSIL} but I haven't tried it. Python + on Windows CE and Windows Mobile should return C{ARCH_ARM}. Python on + Solaris using Wine would return C{ARCH_SPARC}. Python in an Itanium + machine should return C{ARCH_IA64} both on Wine and proper Windows. + All other values should only be returned on Linux using Wine. + """ + try: + si = GetNativeSystemInfo() + except Exception: + si = GetSystemInfo() + try: + return _arch_map[si.id.w.wProcessorArchitecture] + except KeyError: + return ARCH_UNKNOWN + +def _get_wow64(): + """ + Determines if the current process is running in Windows-On-Windows 64 bits. + + @rtype: bool + @return: C{True} of the current process is a 32 bit program running in a + 64 bit version of Windows, C{False} if it's either a 32 bit program + in a 32 bit Windows or a 64 bit program in a 64 bit Windows. + """ + # Try to determine if the debugger itself is running on WOW64. + # On error assume False. + if bits == 64: + wow64 = False + else: + try: + wow64 = IsWow64Process( GetCurrentProcess() ) + except Exception: + wow64 = False + return wow64 + +def _get_os(osvi = None): + """ + Determines the current operating system. + + This function allows you to quickly tell apart major OS differences. + For more detailed information call L{GetVersionEx} instead. + + @note: + Wine reports itself as Windows XP 32 bits + (even if the Linux host is 64 bits). + ReactOS may report itself as Windows 2000 or Windows XP, + depending on the version of ReactOS. + + @type osvi: L{OSVERSIONINFOEXA} + @param osvi: Optional. The return value from L{GetVersionEx}. + + @rtype: str + @return: + One of the following values: + - L{OS_UNKNOWN} (C{"Unknown"}) + - L{OS_NT} (C{"Windows NT"}) + - L{OS_W2K} (C{"Windows 2000"}) + - L{OS_XP} (C{"Windows XP"}) + - L{OS_XP_64} (C{"Windows XP (64 bits)"}) + - L{OS_W2K3} (C{"Windows 2003"}) + - L{OS_W2K3_64} (C{"Windows 2003 (64 bits)"}) + - L{OS_W2K3R2} (C{"Windows 2003 R2"}) + - L{OS_W2K3R2_64} (C{"Windows 2003 R2 (64 bits)"}) + - L{OS_W2K8} (C{"Windows 2008"}) + - L{OS_W2K8_64} (C{"Windows 2008 (64 bits)"}) + - L{OS_W2K8R2} (C{"Windows 2008 R2"}) + - L{OS_W2K8R2_64} (C{"Windows 2008 R2 (64 bits)"}) + - L{OS_VISTA} (C{"Windows Vista"}) + - L{OS_VISTA_64} (C{"Windows Vista (64 bits)"}) + - L{OS_W7} (C{"Windows 7"}) + - L{OS_W7_64} (C{"Windows 7 (64 bits)"}) + """ + # rough port of http://msdn.microsoft.com/en-us/library/ms724429%28VS.85%29.aspx + if not osvi: + osvi = GetVersionEx() + if osvi.dwPlatformId == VER_PLATFORM_WIN32_NT and osvi.dwMajorVersion > 4: + if osvi.dwMajorVersion == 6: + if osvi.dwMinorVersion == 0: + if osvi.wProductType == VER_NT_WORKSTATION: + if bits == 64 or wow64: + return 'Windows Vista (64 bits)' + return 'Windows Vista' + else: + if bits == 64 or wow64: + return 'Windows 2008 (64 bits)' + return 'Windows 2008' + if osvi.dwMinorVersion == 1: + if osvi.wProductType == VER_NT_WORKSTATION: + if bits == 64 or wow64: + return 'Windows 7 (64 bits)' + return 'Windows 7' + else: + if bits == 64 or wow64: + return 'Windows 2008 R2 (64 bits)' + return 'Windows 2008 R2' + if osvi.dwMajorVersion == 5: + if osvi.dwMinorVersion == 2: + if GetSystemMetrics(SM_SERVERR2): + if bits == 64 or wow64: + return 'Windows 2003 R2 (64 bits)' + return 'Windows 2003 R2' + if osvi.wSuiteMask in (VER_SUITE_STORAGE_SERVER, VER_SUITE_WH_SERVER): + if bits == 64 or wow64: + return 'Windows 2003 (64 bits)' + return 'Windows 2003' + if osvi.wProductType == VER_NT_WORKSTATION and arch == ARCH_AMD64: + return 'Windows XP (64 bits)' + else: + if bits == 64 or wow64: + return 'Windows 2003 (64 bits)' + return 'Windows 2003' + if osvi.dwMinorVersion == 1: + return 'Windows XP' + if osvi.dwMinorVersion == 0: + return 'Windows 2000' + if osvi.dwMajorVersion == 4: + return 'Windows NT' + return 'Unknown' + +def _get_ntddi(osvi): + """ + Determines the current operating system. + + This function allows you to quickly tell apart major OS differences. + For more detailed information call L{kernel32.GetVersionEx} instead. + + @note: + Wine reports itself as Windows XP 32 bits + (even if the Linux host is 64 bits). + ReactOS may report itself as Windows 2000 or Windows XP, + depending on the version of ReactOS. + + @type osvi: L{OSVERSIONINFOEXA} + @param osvi: Optional. The return value from L{kernel32.GetVersionEx}. + + @rtype: int + @return: NTDDI version number. + """ + if not osvi: + osvi = GetVersionEx() + ntddi = 0 + ntddi += (osvi.dwMajorVersion & 0xFF) << 24 + ntddi += (osvi.dwMinorVersion & 0xFF) << 16 + ntddi += (osvi.wServicePackMajor & 0xFF) << 8 + ntddi += (osvi.wServicePackMinor & 0xFF) + return ntddi + +# The order of the following definitions DOES matter! + +# Current integer size in bits. See L{_get_bits} for more details. +bits = _get_bits() + +# Current processor architecture. See L{_get_arch} for more details. +arch = _get_arch() + +# Set to C{True} if the current process is running in WOW64. See L{_get_wow64} for more details. +wow64 = _get_wow64() + +_osvi = GetVersionEx() + +# Current operating system. See L{_get_os} for more details. +os = _get_os(_osvi) + +# Current operating system as an NTDDI constant. See L{_get_ntddi} for more details. +NTDDI_VERSION = _get_ntddi(_osvi) + +# Upper word of L{NTDDI_VERSION}, contains the OS major and minor version number. +WINVER = NTDDI_VERSION >> 16 + +#--- version.dll -------------------------------------------------------------- + +VS_FF_DEBUG = 0x00000001 +VS_FF_PRERELEASE = 0x00000002 +VS_FF_PATCHED = 0x00000004 +VS_FF_PRIVATEBUILD = 0x00000008 +VS_FF_INFOINFERRED = 0x00000010 +VS_FF_SPECIALBUILD = 0x00000020 + +VOS_UNKNOWN = 0x00000000 +VOS__WINDOWS16 = 0x00000001 +VOS__PM16 = 0x00000002 +VOS__PM32 = 0x00000003 +VOS__WINDOWS32 = 0x00000004 +VOS_DOS = 0x00010000 +VOS_OS216 = 0x00020000 +VOS_OS232 = 0x00030000 +VOS_NT = 0x00040000 + +VOS_DOS_WINDOWS16 = 0x00010001 +VOS_DOS_WINDOWS32 = 0x00010004 +VOS_NT_WINDOWS32 = 0x00040004 +VOS_OS216_PM16 = 0x00020002 +VOS_OS232_PM32 = 0x00030003 + +VFT_UNKNOWN = 0x00000000 +VFT_APP = 0x00000001 +VFT_DLL = 0x00000002 +VFT_DRV = 0x00000003 +VFT_FONT = 0x00000004 +VFT_VXD = 0x00000005 +VFT_RESERVED = 0x00000006 # undocumented +VFT_STATIC_LIB = 0x00000007 + +VFT2_UNKNOWN = 0x00000000 + +VFT2_DRV_PRINTER = 0x00000001 +VFT2_DRV_KEYBOARD = 0x00000002 +VFT2_DRV_LANGUAGE = 0x00000003 +VFT2_DRV_DISPLAY = 0x00000004 +VFT2_DRV_MOUSE = 0x00000005 +VFT2_DRV_NETWORK = 0x00000006 +VFT2_DRV_SYSTEM = 0x00000007 +VFT2_DRV_INSTALLABLE = 0x00000008 +VFT2_DRV_SOUND = 0x00000009 +VFT2_DRV_COMM = 0x0000000A +VFT2_DRV_RESERVED = 0x0000000B # undocumented +VFT2_DRV_VERSIONED_PRINTER = 0x0000000C + +VFT2_FONT_RASTER = 0x00000001 +VFT2_FONT_VECTOR = 0x00000002 +VFT2_FONT_TRUETYPE = 0x00000003 + +# typedef struct tagVS_FIXEDFILEINFO { +# DWORD dwSignature; +# DWORD dwStrucVersion; +# DWORD dwFileVersionMS; +# DWORD dwFileVersionLS; +# DWORD dwProductVersionMS; +# DWORD dwProductVersionLS; +# DWORD dwFileFlagsMask; +# DWORD dwFileFlags; +# DWORD dwFileOS; +# DWORD dwFileType; +# DWORD dwFileSubtype; +# DWORD dwFileDateMS; +# DWORD dwFileDateLS; +# } VS_FIXEDFILEINFO; +class VS_FIXEDFILEINFO(Structure): + _fields_ = [ + ("dwSignature", DWORD), + ("dwStrucVersion", DWORD), + ("dwFileVersionMS", DWORD), + ("dwFileVersionLS", DWORD), + ("dwProductVersionMS", DWORD), + ("dwProductVersionLS", DWORD), + ("dwFileFlagsMask", DWORD), + ("dwFileFlags", DWORD), + ("dwFileOS", DWORD), + ("dwFileType", DWORD), + ("dwFileSubtype", DWORD), + ("dwFileDateMS", DWORD), + ("dwFileDateLS", DWORD), +] +PVS_FIXEDFILEINFO = POINTER(VS_FIXEDFILEINFO) +LPVS_FIXEDFILEINFO = PVS_FIXEDFILEINFO + +# BOOL WINAPI GetFileVersionInfo( +# _In_ LPCTSTR lptstrFilename, +# _Reserved_ DWORD dwHandle, +# _In_ DWORD dwLen, +# _Out_ LPVOID lpData +# ); +# DWORD WINAPI GetFileVersionInfoSize( +# _In_ LPCTSTR lptstrFilename, +# _Out_opt_ LPDWORD lpdwHandle +# ); +def GetFileVersionInfoA(lptstrFilename): + _GetFileVersionInfoA = windll.version.GetFileVersionInfoA + _GetFileVersionInfoA.argtypes = [LPSTR, DWORD, DWORD, LPVOID] + _GetFileVersionInfoA.restype = bool + _GetFileVersionInfoA.errcheck = RaiseIfZero + + _GetFileVersionInfoSizeA = windll.version.GetFileVersionInfoSizeA + _GetFileVersionInfoSizeA.argtypes = [LPSTR, LPVOID] + _GetFileVersionInfoSizeA.restype = DWORD + _GetFileVersionInfoSizeA.errcheck = RaiseIfZero + + dwLen = _GetFileVersionInfoSizeA(lptstrFilename, None) + lpData = ctypes.create_string_buffer(dwLen) + _GetFileVersionInfoA(lptstrFilename, 0, dwLen, byref(lpData)) + return lpData + +def GetFileVersionInfoW(lptstrFilename): + _GetFileVersionInfoW = windll.version.GetFileVersionInfoW + _GetFileVersionInfoW.argtypes = [LPWSTR, DWORD, DWORD, LPVOID] + _GetFileVersionInfoW.restype = bool + _GetFileVersionInfoW.errcheck = RaiseIfZero + + _GetFileVersionInfoSizeW = windll.version.GetFileVersionInfoSizeW + _GetFileVersionInfoSizeW.argtypes = [LPWSTR, LPVOID] + _GetFileVersionInfoSizeW.restype = DWORD + _GetFileVersionInfoSizeW.errcheck = RaiseIfZero + + dwLen = _GetFileVersionInfoSizeW(lptstrFilename, None) + lpData = ctypes.create_string_buffer(dwLen) # not a string! + _GetFileVersionInfoW(lptstrFilename, 0, dwLen, byref(lpData)) + return lpData + +GetFileVersionInfo = GuessStringType(GetFileVersionInfoA, GetFileVersionInfoW) + +# BOOL WINAPI VerQueryValue( +# _In_ LPCVOID pBlock, +# _In_ LPCTSTR lpSubBlock, +# _Out_ LPVOID *lplpBuffer, +# _Out_ PUINT puLen +# ); +def VerQueryValueA(pBlock, lpSubBlock): + _VerQueryValueA = windll.version.VerQueryValueA + _VerQueryValueA.argtypes = [LPVOID, LPSTR, LPVOID, POINTER(UINT)] + _VerQueryValueA.restype = bool + _VerQueryValueA.errcheck = RaiseIfZero + + lpBuffer = LPVOID(0) + uLen = UINT(0) + _VerQueryValueA(pBlock, lpSubBlock, byref(lpBuffer), byref(uLen)) + return lpBuffer, uLen.value + +def VerQueryValueW(pBlock, lpSubBlock): + _VerQueryValueW = windll.version.VerQueryValueW + _VerQueryValueW.argtypes = [LPVOID, LPWSTR, LPVOID, POINTER(UINT)] + _VerQueryValueW.restype = bool + _VerQueryValueW.errcheck = RaiseIfZero + + lpBuffer = LPVOID(0) + uLen = UINT(0) + _VerQueryValueW(pBlock, lpSubBlock, byref(lpBuffer), byref(uLen)) + return lpBuffer, uLen.value + +VerQueryValue = GuessStringType(VerQueryValueA, VerQueryValueW) + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/win32/wtsapi32.py b/pydevd_attach_to_process/winappdbg/win32/wtsapi32.py new file mode 100644 index 0000000..13227db --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/win32/wtsapi32.py @@ -0,0 +1,337 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper for wtsapi32.dll in ctypes. +""" + +__revision__ = "$Id$" + +from winappdbg.win32.defines import * +from winappdbg.win32.advapi32 import * + +#============================================================================== +# This is used later on to calculate the list of exported symbols. +_all = None +_all = set(vars().keys()) +#============================================================================== + +#--- Constants ---------------------------------------------------------------- + +WTS_CURRENT_SERVER_HANDLE = 0 +WTS_CURRENT_SESSION = 1 + +#--- WTS_PROCESS_INFO structure ----------------------------------------------- + +# typedef struct _WTS_PROCESS_INFO { +# DWORD SessionId; +# DWORD ProcessId; +# LPTSTR pProcessName; +# PSID pUserSid; +# } WTS_PROCESS_INFO, *PWTS_PROCESS_INFO; + +class WTS_PROCESS_INFOA(Structure): + _fields_ = [ + ("SessionId", DWORD), + ("ProcessId", DWORD), + ("pProcessName", LPSTR), + ("pUserSid", PSID), + ] +PWTS_PROCESS_INFOA = POINTER(WTS_PROCESS_INFOA) + +class WTS_PROCESS_INFOW(Structure): + _fields_ = [ + ("SessionId", DWORD), + ("ProcessId", DWORD), + ("pProcessName", LPWSTR), + ("pUserSid", PSID), + ] +PWTS_PROCESS_INFOW = POINTER(WTS_PROCESS_INFOW) + +#--- WTSQuerySessionInformation enums and structures -------------------------- + +# typedef enum _WTS_INFO_CLASS { +# WTSInitialProgram = 0, +# WTSApplicationName = 1, +# WTSWorkingDirectory = 2, +# WTSOEMId = 3, +# WTSSessionId = 4, +# WTSUserName = 5, +# WTSWinStationName = 6, +# WTSDomainName = 7, +# WTSConnectState = 8, +# WTSClientBuildNumber = 9, +# WTSClientName = 10, +# WTSClientDirectory = 11, +# WTSClientProductId = 12, +# WTSClientHardwareId = 13, +# WTSClientAddress = 14, +# WTSClientDisplay = 15, +# WTSClientProtocolType = 16, +# WTSIdleTime = 17, +# WTSLogonTime = 18, +# WTSIncomingBytes = 19, +# WTSOutgoingBytes = 20, +# WTSIncomingFrames = 21, +# WTSOutgoingFrames = 22, +# WTSClientInfo = 23, +# WTSSessionInfo = 24, +# WTSSessionInfoEx = 25, +# WTSConfigInfo = 26, +# WTSValidationInfo = 27, +# WTSSessionAddressV4 = 28, +# WTSIsRemoteSession = 29 +# } WTS_INFO_CLASS; + +WTSInitialProgram = 0 +WTSApplicationName = 1 +WTSWorkingDirectory = 2 +WTSOEMId = 3 +WTSSessionId = 4 +WTSUserName = 5 +WTSWinStationName = 6 +WTSDomainName = 7 +WTSConnectState = 8 +WTSClientBuildNumber = 9 +WTSClientName = 10 +WTSClientDirectory = 11 +WTSClientProductId = 12 +WTSClientHardwareId = 13 +WTSClientAddress = 14 +WTSClientDisplay = 15 +WTSClientProtocolType = 16 +WTSIdleTime = 17 +WTSLogonTime = 18 +WTSIncomingBytes = 19 +WTSOutgoingBytes = 20 +WTSIncomingFrames = 21 +WTSOutgoingFrames = 22 +WTSClientInfo = 23 +WTSSessionInfo = 24 +WTSSessionInfoEx = 25 +WTSConfigInfo = 26 +WTSValidationInfo = 27 +WTSSessionAddressV4 = 28 +WTSIsRemoteSession = 29 + +WTS_INFO_CLASS = ctypes.c_int + +# typedef enum _WTS_CONNECTSTATE_CLASS { +# WTSActive, +# WTSConnected, +# WTSConnectQuery, +# WTSShadow, +# WTSDisconnected, +# WTSIdle, +# WTSListen, +# WTSReset, +# WTSDown, +# WTSInit +# } WTS_CONNECTSTATE_CLASS; + +WTSActive = 0 +WTSConnected = 1 +WTSConnectQuery = 2 +WTSShadow = 3 +WTSDisconnected = 4 +WTSIdle = 5 +WTSListen = 6 +WTSReset = 7 +WTSDown = 8 +WTSInit = 9 + +WTS_CONNECTSTATE_CLASS = ctypes.c_int + +# typedef struct _WTS_CLIENT_DISPLAY { +# DWORD HorizontalResolution; +# DWORD VerticalResolution; +# DWORD ColorDepth; +# } WTS_CLIENT_DISPLAY, *PWTS_CLIENT_DISPLAY; +class WTS_CLIENT_DISPLAY(Structure): + _fields_ = [ + ("HorizontalResolution", DWORD), + ("VerticalResolution", DWORD), + ("ColorDepth", DWORD), + ] +PWTS_CLIENT_DISPLAY = POINTER(WTS_CLIENT_DISPLAY) + +# typedef struct _WTS_CLIENT_ADDRESS { +# DWORD AddressFamily; +# BYTE Address[20]; +# } WTS_CLIENT_ADDRESS, *PWTS_CLIENT_ADDRESS; + +# XXX TODO + +# typedef struct _WTSCLIENT { +# WCHAR ClientName[CLIENTNAME_LENGTH + 1]; +# WCHAR Domain[DOMAIN_LENGTH + 1 ]; +# WCHAR UserName[USERNAME_LENGTH + 1]; +# WCHAR WorkDirectory[MAX_PATH + 1]; +# WCHAR InitialProgram[MAX_PATH + 1]; +# BYTE EncryptionLevel; +# ULONG ClientAddressFamily; +# USHORT ClientAddress[CLIENTADDRESS_LENGTH + 1]; +# USHORT HRes; +# USHORT VRes; +# USHORT ColorDepth; +# WCHAR ClientDirectory[MAX_PATH + 1]; +# ULONG ClientBuildNumber; +# ULONG ClientHardwareId; +# USHORT ClientProductId; +# USHORT OutBufCountHost; +# USHORT OutBufCountClient; +# USHORT OutBufLength; +# WCHAR DeviceId[MAX_PATH + 1]; +# } WTSCLIENT, *PWTSCLIENT; + +# XXX TODO + +# typedef struct _WTSINFO { +# WTS_CONNECTSTATE_CLASS State; +# DWORD SessionId; +# DWORD IncomingBytes; +# DWORD OutgoingBytes; +# DWORD IncomingCompressedBytes; +# DWORD OutgoingCompressedBytes; +# WCHAR WinStationName; +# WCHAR Domain; +# WCHAR UserName; +# LARGE_INTEGER ConnectTime; +# LARGE_INTEGER DisconnectTime; +# LARGE_INTEGER LastInputTime; +# LARGE_INTEGER LogonTime; +# LARGE_INTEGER CurrentTime; +# } WTSINFO, *PWTSINFO; + +# XXX TODO + +# typedef struct _WTSINFOEX { +# DWORD Level; +# WTSINFOEX_LEVEL Data; +# } WTSINFOEX, *PWTSINFOEX; + +# XXX TODO + +#--- wtsapi32.dll ------------------------------------------------------------- + +# void WTSFreeMemory( +# __in PVOID pMemory +# ); +def WTSFreeMemory(pMemory): + _WTSFreeMemory = windll.wtsapi32.WTSFreeMemory + _WTSFreeMemory.argtypes = [PVOID] + _WTSFreeMemory.restype = None + _WTSFreeMemory(pMemory) + +# BOOL WTSEnumerateProcesses( +# __in HANDLE hServer, +# __in DWORD Reserved, +# __in DWORD Version, +# __out PWTS_PROCESS_INFO *ppProcessInfo, +# __out DWORD *pCount +# ); +def WTSEnumerateProcessesA(hServer = WTS_CURRENT_SERVER_HANDLE): + _WTSEnumerateProcessesA = windll.wtsapi32.WTSEnumerateProcessesA + _WTSEnumerateProcessesA.argtypes = [HANDLE, DWORD, DWORD, POINTER(PWTS_PROCESS_INFOA), PDWORD] + _WTSEnumerateProcessesA.restype = bool + _WTSEnumerateProcessesA.errcheck = RaiseIfZero + + pProcessInfo = PWTS_PROCESS_INFOA() + Count = DWORD(0) + _WTSEnumerateProcessesA(hServer, 0, 1, byref(pProcessInfo), byref(Count)) + return pProcessInfo, Count.value + +def WTSEnumerateProcessesW(hServer = WTS_CURRENT_SERVER_HANDLE): + _WTSEnumerateProcessesW = windll.wtsapi32.WTSEnumerateProcessesW + _WTSEnumerateProcessesW.argtypes = [HANDLE, DWORD, DWORD, POINTER(PWTS_PROCESS_INFOW), PDWORD] + _WTSEnumerateProcessesW.restype = bool + _WTSEnumerateProcessesW.errcheck = RaiseIfZero + + pProcessInfo = PWTS_PROCESS_INFOW() + Count = DWORD(0) + _WTSEnumerateProcessesW(hServer, 0, 1, byref(pProcessInfo), byref(Count)) + return pProcessInfo, Count.value + +WTSEnumerateProcesses = DefaultStringType(WTSEnumerateProcessesA, WTSEnumerateProcessesW) + +# BOOL WTSTerminateProcess( +# __in HANDLE hServer, +# __in DWORD ProcessId, +# __in DWORD ExitCode +# ); +def WTSTerminateProcess(hServer, ProcessId, ExitCode): + _WTSTerminateProcess = windll.wtsapi32.WTSTerminateProcess + _WTSTerminateProcess.argtypes = [HANDLE, DWORD, DWORD] + _WTSTerminateProcess.restype = bool + _WTSTerminateProcess.errcheck = RaiseIfZero + _WTSTerminateProcess(hServer, ProcessId, ExitCode) + +# BOOL WTSQuerySessionInformation( +# __in HANDLE hServer, +# __in DWORD SessionId, +# __in WTS_INFO_CLASS WTSInfoClass, +# __out LPTSTR *ppBuffer, +# __out DWORD *pBytesReturned +# ); + +# XXX TODO + +#--- kernel32.dll ------------------------------------------------------------- + +# I've no idea why these functions are in kernel32.dll instead of wtsapi32.dll + +# BOOL ProcessIdToSessionId( +# __in DWORD dwProcessId, +# __out DWORD *pSessionId +# ); +def ProcessIdToSessionId(dwProcessId): + _ProcessIdToSessionId = windll.kernel32.ProcessIdToSessionId + _ProcessIdToSessionId.argtypes = [DWORD, PDWORD] + _ProcessIdToSessionId.restype = bool + _ProcessIdToSessionId.errcheck = RaiseIfZero + + dwSessionId = DWORD(0) + _ProcessIdToSessionId(dwProcessId, byref(dwSessionId)) + return dwSessionId.value + +# DWORD WTSGetActiveConsoleSessionId(void); +def WTSGetActiveConsoleSessionId(): + _WTSGetActiveConsoleSessionId = windll.kernel32.WTSGetActiveConsoleSessionId + _WTSGetActiveConsoleSessionId.argtypes = [] + _WTSGetActiveConsoleSessionId.restype = DWORD + _WTSGetActiveConsoleSessionId.errcheck = RaiseIfZero + return _WTSGetActiveConsoleSessionId() + +#============================================================================== +# This calculates the list of exported symbols. +_all = set(vars().keys()).difference(_all) +__all__ = [_x for _x in _all if not _x.startswith('_')] +__all__.sort() +#============================================================================== diff --git a/pydevd_attach_to_process/winappdbg/window.py b/pydevd_attach_to_process/winappdbg/window.py new file mode 100644 index 0000000..6e865e7 --- /dev/null +++ b/pydevd_attach_to_process/winappdbg/window.py @@ -0,0 +1,759 @@ +#!~/.wine/drive_c/Python25/python.exe +# -*- coding: utf-8 -*- + +# Copyright (c) 2009-2014, Mario Vilas +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice,this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Window instrumentation. + +@group Instrumentation: + Window +""" + +__revision__ = "$Id$" + +__all__ = ['Window'] + +from winappdbg import win32 + +# delayed imports +Process = None +Thread = None + +#============================================================================== + +# Unlike Process, Thread and Module, there's no container for Window objects. +# That's because Window objects don't really store any data besides the handle. + +# XXX TODO +# * implement sending fake user input (mouse and keyboard messages) +# * maybe implement low-level hooks? (they don't require a dll to be injected) + +# XXX TODO +# +# Will it be possible to implement window hooks too? That requires a DLL to be +# injected in the target process. Perhaps with CPython it could be done easier, +# compiling a native extension is the safe bet, but both require having a non +# pure Python module, which is something I was trying to avoid so far. +# +# Another possibility would be to malloc some CC's in the target process and +# point the hook callback to it. We'd need to have the remote procedure call +# feature first as (I believe) the hook can't be set remotely in this case. + +class Window (object): + """ + Interface to an open window in the current desktop. + + @group Properties: + get_handle, get_pid, get_tid, + get_process, get_thread, + set_process, set_thread, + get_classname, get_style, get_extended_style, + get_text, set_text, + get_placement, set_placement, + get_screen_rect, get_client_rect, + screen_to_client, client_to_screen + + @group State: + is_valid, is_visible, is_enabled, is_maximized, is_minimized, is_child, + is_zoomed, is_iconic + + @group Navigation: + get_parent, get_children, get_root, get_tree, + get_child_at + + @group Instrumentation: + enable, disable, show, hide, maximize, minimize, restore, move, kill + + @group Low-level access: + send, post + + @type hWnd: int + @ivar hWnd: Window handle. + + @type dwProcessId: int + @ivar dwProcessId: Global ID of the process that owns this window. + + @type dwThreadId: int + @ivar dwThreadId: Global ID of the thread that owns this window. + + @type process: L{Process} + @ivar process: Process that owns this window. + Use the L{get_process} method instead. + + @type thread: L{Thread} + @ivar thread: Thread that owns this window. + Use the L{get_thread} method instead. + + @type classname: str + @ivar classname: Window class name. + + @type text: str + @ivar text: Window text (caption). + + @type placement: L{win32.WindowPlacement} + @ivar placement: Window placement in the desktop. + """ + + def __init__(self, hWnd = None, process = None, thread = None): + """ + @type hWnd: int or L{win32.HWND} + @param hWnd: Window handle. + + @type process: L{Process} + @param process: (Optional) Process that owns this window. + + @type thread: L{Thread} + @param thread: (Optional) Thread that owns this window. + """ + self.hWnd = hWnd + self.dwProcessId = None + self.dwThreadId = None + self.set_process(process) + self.set_thread(thread) + + @property + def _as_parameter_(self): + """ + Compatibility with ctypes. + Allows passing transparently a Window object to an API call. + """ + return self.get_handle() + + def get_handle(self): + """ + @rtype: int + @return: Window handle. + @raise ValueError: No window handle set. + """ + if self.hWnd is None: + raise ValueError("No window handle set!") + return self.hWnd + + def get_pid(self): + """ + @rtype: int + @return: Global ID of the process that owns this window. + """ + if self.dwProcessId is not None: + return self.dwProcessId + self.__get_pid_and_tid() + return self.dwProcessId + + def get_tid(self): + """ + @rtype: int + @return: Global ID of the thread that owns this window. + """ + if self.dwThreadId is not None: + return self.dwThreadId + self.__get_pid_and_tid() + return self.dwThreadId + + def __get_pid_and_tid(self): + "Internally used by get_pid() and get_tid()." + self.dwThreadId, self.dwProcessId = \ + win32.GetWindowThreadProcessId(self.get_handle()) + + def __load_Process_class(self): + global Process # delayed import + if Process is None: + from winappdbg.process import Process + + def __load_Thread_class(self): + global Thread # delayed import + if Thread is None: + from winappdbg.thread import Thread + + def get_process(self): + """ + @rtype: L{Process} + @return: Parent Process object. + """ + if self.__process is not None: + return self.__process + self.__load_Process_class() + self.__process = Process(self.get_pid()) + return self.__process + + def set_process(self, process = None): + """ + Manually set the parent process. Use with care! + + @type process: L{Process} + @param process: (Optional) Process object. Use C{None} to autodetect. + """ + if process is None: + self.__process = None + else: + self.__load_Process_class() + if not isinstance(process, Process): + msg = "Parent process must be a Process instance, " + msg += "got %s instead" % type(process) + raise TypeError(msg) + self.dwProcessId = process.get_pid() + self.__process = process + + def get_thread(self): + """ + @rtype: L{Thread} + @return: Parent Thread object. + """ + if self.__thread is not None: + return self.__thread + self.__load_Thread_class() + self.__thread = Thread(self.get_tid()) + return self.__thread + + def set_thread(self, thread = None): + """ + Manually set the thread process. Use with care! + + @type thread: L{Thread} + @param thread: (Optional) Thread object. Use C{None} to autodetect. + """ + if thread is None: + self.__thread = None + else: + self.__load_Thread_class() + if not isinstance(thread, Thread): + msg = "Parent thread must be a Thread instance, " + msg += "got %s instead" % type(thread) + raise TypeError(msg) + self.dwThreadId = thread.get_tid() + self.__thread = thread + + def __get_window(self, hWnd): + """ + User internally to get another Window from this one. + It'll try to copy the parent Process and Thread references if possible. + """ + window = Window(hWnd) + if window.get_pid() == self.get_pid(): + window.set_process( self.get_process() ) + if window.get_tid() == self.get_tid(): + window.set_thread( self.get_thread() ) + return window + +#------------------------------------------------------------------------------ + + def get_classname(self): + """ + @rtype: str + @return: Window class name. + + @raise WindowsError: An error occured while processing this request. + """ + return win32.GetClassName( self.get_handle() ) + + def get_style(self): + """ + @rtype: int + @return: Window style mask. + + @raise WindowsError: An error occured while processing this request. + """ + return win32.GetWindowLongPtr( self.get_handle(), win32.GWL_STYLE ) + + def get_extended_style(self): + """ + @rtype: int + @return: Window extended style mask. + + @raise WindowsError: An error occured while processing this request. + """ + return win32.GetWindowLongPtr( self.get_handle(), win32.GWL_EXSTYLE ) + + def get_text(self): + """ + @see: L{set_text} + @rtype: str + @return: Window text (caption) on success, C{None} on error. + """ + try: + return win32.GetWindowText( self.get_handle() ) + except WindowsError: + return None + + def set_text(self, text): + """ + Set the window text (caption). + + @see: L{get_text} + + @type text: str + @param text: New window text. + + @raise WindowsError: An error occured while processing this request. + """ + win32.SetWindowText( self.get_handle(), text ) + + def get_placement(self): + """ + Retrieve the window placement in the desktop. + + @see: L{set_placement} + + @rtype: L{win32.WindowPlacement} + @return: Window placement in the desktop. + + @raise WindowsError: An error occured while processing this request. + """ + return win32.GetWindowPlacement( self.get_handle() ) + + def set_placement(self, placement): + """ + Set the window placement in the desktop. + + @see: L{get_placement} + + @type placement: L{win32.WindowPlacement} + @param placement: Window placement in the desktop. + + @raise WindowsError: An error occured while processing this request. + """ + win32.SetWindowPlacement( self.get_handle(), placement ) + + def get_screen_rect(self): + """ + Get the window coordinates in the desktop. + + @rtype: L{win32.Rect} + @return: Rectangle occupied by the window in the desktop. + + @raise WindowsError: An error occured while processing this request. + """ + return win32.GetWindowRect( self.get_handle() ) + + def get_client_rect(self): + """ + Get the window's client area coordinates in the desktop. + + @rtype: L{win32.Rect} + @return: Rectangle occupied by the window's client area in the desktop. + + @raise WindowsError: An error occured while processing this request. + """ + cr = win32.GetClientRect( self.get_handle() ) + cr.left, cr.top = self.client_to_screen(cr.left, cr.top) + cr.right, cr.bottom = self.client_to_screen(cr.right, cr.bottom) + return cr + + # XXX TODO + # * properties x, y, width, height + # * properties left, top, right, bottom + + process = property(get_process, set_process, doc="") + thread = property(get_thread, set_thread, doc="") + classname = property(get_classname, doc="") + style = property(get_style, doc="") + exstyle = property(get_extended_style, doc="") + text = property(get_text, set_text, doc="") + placement = property(get_placement, set_placement, doc="") + +#------------------------------------------------------------------------------ + + def client_to_screen(self, x, y): + """ + Translates window client coordinates to screen coordinates. + + @note: This is a simplified interface to some of the functionality of + the L{win32.Point} class. + + @see: {win32.Point.client_to_screen} + + @type x: int + @param x: Horizontal coordinate. + @type y: int + @param y: Vertical coordinate. + + @rtype: tuple( int, int ) + @return: Translated coordinates in a tuple (x, y). + + @raise WindowsError: An error occured while processing this request. + """ + return tuple( win32.ClientToScreen( self.get_handle(), (x, y) ) ) + + def screen_to_client(self, x, y): + """ + Translates window screen coordinates to client coordinates. + + @note: This is a simplified interface to some of the functionality of + the L{win32.Point} class. + + @see: {win32.Point.screen_to_client} + + @type x: int + @param x: Horizontal coordinate. + @type y: int + @param y: Vertical coordinate. + + @rtype: tuple( int, int ) + @return: Translated coordinates in a tuple (x, y). + + @raise WindowsError: An error occured while processing this request. + """ + return tuple( win32.ScreenToClient( self.get_handle(), (x, y) ) ) + +#------------------------------------------------------------------------------ + + def get_parent(self): + """ + @see: L{get_children} + @rtype: L{Window} or None + @return: Parent window. Returns C{None} if the window has no parent. + @raise WindowsError: An error occured while processing this request. + """ + hWnd = win32.GetParent( self.get_handle() ) + if hWnd: + return self.__get_window(hWnd) + + def get_children(self): + """ + @see: L{get_parent} + @rtype: list( L{Window} ) + @return: List of child windows. + @raise WindowsError: An error occured while processing this request. + """ + return [ + self.__get_window(hWnd) \ + for hWnd in win32.EnumChildWindows( self.get_handle() ) + ] + + def get_tree(self): + """ + @see: L{get_root} + @rtype: dict( L{Window} S{->} dict( ... ) ) + @return: Dictionary of dictionaries forming a tree of child windows. + @raise WindowsError: An error occured while processing this request. + """ + subtree = dict() + for aWindow in self.get_children(): + subtree[ aWindow ] = aWindow.get_tree() + return subtree + + def get_root(self): + """ + @see: L{get_tree} + @rtype: L{Window} + @return: If this is a child window, return the top-level window it + belongs to. + If this window is already a top-level window, returns itself. + @raise WindowsError: An error occured while processing this request. + """ + hWnd = self.get_handle() + history = set() + hPrevWnd = hWnd + while hWnd and hWnd not in history: + history.add(hWnd) + hPrevWnd = hWnd + hWnd = win32.GetParent(hWnd) + if hWnd in history: + # See: https://docs.google.com/View?id=dfqd62nk_228h28szgz + return self + if hPrevWnd != self.get_handle(): + return self.__get_window(hPrevWnd) + return self + + def get_child_at(self, x, y, bAllowTransparency = True): + """ + Get the child window located at the given coordinates. If no such + window exists an exception is raised. + + @see: L{get_children} + + @type x: int + @param x: Horizontal coordinate. + + @type y: int + @param y: Vertical coordinate. + + @type bAllowTransparency: bool + @param bAllowTransparency: If C{True} transparent areas in windows are + ignored, returning the window behind them. If C{False} transparent + areas are treated just like any other area. + + @rtype: L{Window} + @return: Child window at the requested position, or C{None} if there + is no window at those coordinates. + """ + try: + if bAllowTransparency: + hWnd = win32.RealChildWindowFromPoint( self.get_handle(), (x, y) ) + else: + hWnd = win32.ChildWindowFromPoint( self.get_handle(), (x, y) ) + if hWnd: + return self.__get_window(hWnd) + except WindowsError: + pass + return None + +#------------------------------------------------------------------------------ + + def is_valid(self): + """ + @rtype: bool + @return: C{True} if the window handle is still valid. + """ + return win32.IsWindow( self.get_handle() ) + + def is_visible(self): + """ + @see: {show}, {hide} + @rtype: bool + @return: C{True} if the window is in a visible state. + """ + return win32.IsWindowVisible( self.get_handle() ) + + def is_enabled(self): + """ + @see: {enable}, {disable} + @rtype: bool + @return: C{True} if the window is in an enabled state. + """ + return win32.IsWindowEnabled( self.get_handle() ) + + def is_maximized(self): + """ + @see: L{maximize} + @rtype: bool + @return: C{True} if the window is maximized. + """ + return win32.IsZoomed( self.get_handle() ) + + def is_minimized(self): + """ + @see: L{minimize} + @rtype: bool + @return: C{True} if the window is minimized. + """ + return win32.IsIconic( self.get_handle() ) + + def is_child(self): + """ + @see: L{get_parent} + @rtype: bool + @return: C{True} if the window is a child window. + """ + return win32.IsChild( self.get_handle() ) + + is_zoomed = is_maximized + is_iconic = is_minimized + +#------------------------------------------------------------------------------ + + def enable(self): + """ + Enable the user input for the window. + + @see: L{disable} + + @raise WindowsError: An error occured while processing this request. + """ + win32.EnableWindow( self.get_handle(), True ) + + def disable(self): + """ + Disable the user input for the window. + + @see: L{enable} + + @raise WindowsError: An error occured while processing this request. + """ + win32.EnableWindow( self.get_handle(), False ) + + def show(self, bAsync = True): + """ + Make the window visible. + + @see: L{hide} + + @type bAsync: bool + @param bAsync: Perform the request asynchronously. + + @raise WindowsError: An error occured while processing this request. + """ + if bAsync: + win32.ShowWindowAsync( self.get_handle(), win32.SW_SHOW ) + else: + win32.ShowWindow( self.get_handle(), win32.SW_SHOW ) + + def hide(self, bAsync = True): + """ + Make the window invisible. + + @see: L{show} + + @type bAsync: bool + @param bAsync: Perform the request asynchronously. + + @raise WindowsError: An error occured while processing this request. + """ + if bAsync: + win32.ShowWindowAsync( self.get_handle(), win32.SW_HIDE ) + else: + win32.ShowWindow( self.get_handle(), win32.SW_HIDE ) + + def maximize(self, bAsync = True): + """ + Maximize the window. + + @see: L{minimize}, L{restore} + + @type bAsync: bool + @param bAsync: Perform the request asynchronously. + + @raise WindowsError: An error occured while processing this request. + """ + if bAsync: + win32.ShowWindowAsync( self.get_handle(), win32.SW_MAXIMIZE ) + else: + win32.ShowWindow( self.get_handle(), win32.SW_MAXIMIZE ) + + def minimize(self, bAsync = True): + """ + Minimize the window. + + @see: L{maximize}, L{restore} + + @type bAsync: bool + @param bAsync: Perform the request asynchronously. + + @raise WindowsError: An error occured while processing this request. + """ + if bAsync: + win32.ShowWindowAsync( self.get_handle(), win32.SW_MINIMIZE ) + else: + win32.ShowWindow( self.get_handle(), win32.SW_MINIMIZE ) + + def restore(self, bAsync = True): + """ + Unmaximize and unminimize the window. + + @see: L{maximize}, L{minimize} + + @type bAsync: bool + @param bAsync: Perform the request asynchronously. + + @raise WindowsError: An error occured while processing this request. + """ + if bAsync: + win32.ShowWindowAsync( self.get_handle(), win32.SW_RESTORE ) + else: + win32.ShowWindow( self.get_handle(), win32.SW_RESTORE ) + + def move(self, x = None, y = None, width = None, height = None, + bRepaint = True): + """ + Moves and/or resizes the window. + + @note: This is request is performed syncronously. + + @type x: int + @param x: (Optional) New horizontal coordinate. + + @type y: int + @param y: (Optional) New vertical coordinate. + + @type width: int + @param width: (Optional) Desired window width. + + @type height: int + @param height: (Optional) Desired window height. + + @type bRepaint: bool + @param bRepaint: + (Optional) C{True} if the window should be redrawn afterwards. + + @raise WindowsError: An error occured while processing this request. + """ + if None in (x, y, width, height): + rect = self.get_screen_rect() + if x is None: + x = rect.left + if y is None: + y = rect.top + if width is None: + width = rect.right - rect.left + if height is None: + height = rect.bottom - rect.top + win32.MoveWindow(self.get_handle(), x, y, width, height, bRepaint) + + def kill(self): + """ + Signals the program to quit. + + @note: This is an asyncronous request. + + @raise WindowsError: An error occured while processing this request. + """ + self.post(win32.WM_QUIT) + + def send(self, uMsg, wParam = None, lParam = None, dwTimeout = None): + """ + Send a low-level window message syncronically. + + @type uMsg: int + @param uMsg: Message code. + + @param wParam: + The type and meaning of this parameter depends on the message. + + @param lParam: + The type and meaning of this parameter depends on the message. + + @param dwTimeout: Optional timeout for the operation. + Use C{None} to wait indefinitely. + + @rtype: int + @return: The meaning of the return value depends on the window message. + Typically a value of C{0} means an error occured. You can get the + error code by calling L{win32.GetLastError}. + """ + if dwTimeout is None: + return win32.SendMessage(self.get_handle(), uMsg, wParam, lParam) + return win32.SendMessageTimeout( + self.get_handle(), uMsg, wParam, lParam, + win32.SMTO_ABORTIFHUNG | win32.SMTO_ERRORONEXIT, dwTimeout) + + def post(self, uMsg, wParam = None, lParam = None): + """ + Post a low-level window message asyncronically. + + @type uMsg: int + @param uMsg: Message code. + + @param wParam: + The type and meaning of this parameter depends on the message. + + @param lParam: + The type and meaning of this parameter depends on the message. + + @raise WindowsError: An error occured while sending the message. + """ + win32.PostMessage(self.get_handle(), uMsg, wParam, lParam) diff --git a/pydevd_attach_to_process/windows/attach.cpp b/pydevd_attach_to_process/windows/attach.cpp new file mode 100644 index 0000000..e44c6e1 --- /dev/null +++ b/pydevd_attach_to_process/windows/attach.cpp @@ -0,0 +1,634 @@ +/* **************************************************************************** +* +* Copyright (c) Microsoft Corporation. +* +* This source code is subject to terms and conditions of the Apache License, Version 2.0. A +* copy of the license can be found in the License.html file at the root of this distribution. If +* you cannot locate the Apache License, Version 2.0, please send an email to +* vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound +* by the terms of the Apache License, Version 2.0. +* +* You must not remove this notice, or any other, from this software. +* +* Contributor: Fabio Zadrozny +* +* Based on PyDebugAttach.cpp from PVTS. Windows only. +* +* https://github.com/Microsoft/PTVS/blob/master/Python/Product/PyDebugAttach/PyDebugAttach.cpp +* +* Initially we did an attach completely based on shellcode which got the +* GIL called PyRun_SimpleString with the needed code and was done with it +* (so, none of this code was needed). +* Now, newer version of Python don't initialize threading by default, so, +* most of this code is done only to overcome this limitation (and as a plus, +* if there's no code running, we also pause the threads to make our code run). +* +* On Linux the approach is still the simpler one (using gdb), so, on newer +* versions of Python it may not work unless the user has some code running +* and threads are initialized. +* I.e.: +* +* The user may have to add the code below in the start of its script for +* a successful attach (if he doesn't already use threads). +* +* from threading import Thread +* Thread(target=str).start() +* +* -- this is the workaround for the fact that we can't get the gil +* if there aren't any threads (PyGILState_Ensure gives an error). +* ***************************************************************************/ + + +// Access to std::cout and std::endl +#include +#include +// DECLDIR will perform an export for us +#define DLL_EXPORT + +#include "attach.h" +#include "stdafx.h" + +#include "../common/python.h" +#include "../common/ref_utils.hpp" +#include "../common/py_utils.hpp" +#include "../common/py_settrace.hpp" + + +#pragma comment(lib, "kernel32.lib") +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "advapi32.lib") +#pragma comment(lib, "psapi.lib") + +#include "py_win_helpers.hpp" +#include "run_code_in_memory.hpp" + +// _Always_ is not defined for all versions, so make it a no-op if missing. +#ifndef _Always_ +#define _Always_(x) x +#endif + + +typedef void (PyEval_Lock)(); // Acquire/Release lock +typedef void (PyThreadState_API)(PyThreadState *); // Acquire/Release lock +typedef PyObject* (Py_CompileString)(const char *str, const char *filename, int start); +typedef PyObject* (PyEval_EvalCode)(PyObject *co, PyObject *globals, PyObject *locals); +typedef PyObject* (PyDict_GetItemString)(PyObject *p, const char *key); +typedef PyObject* (PyEval_GetBuiltins)(); +typedef int (PyDict_SetItemString)(PyObject *dp, const char *key, PyObject *item); +typedef int (PyEval_ThreadsInitialized)(); +typedef int (Py_AddPendingCall)(int (*func)(void *), void*); +typedef PyObject* (PyString_FromString)(const char* s); +typedef void PyEval_SetTrace(Py_tracefunc func, PyObject *obj); +typedef PyObject* (PyErr_Print)(); +typedef PyObject* (PyObject_SetAttrString)(PyObject *o, const char *attr_name, PyObject* value); +typedef PyObject* (PyBool_FromLong)(long v); +typedef unsigned long (_PyEval_GetSwitchInterval)(void); +typedef void (_PyEval_SetSwitchInterval)(unsigned long microseconds); +typedef PyGILState_STATE PyGILState_EnsureFunc(void); +typedef void PyGILState_ReleaseFunc(PyGILState_STATE); +typedef PyThreadState *PyThreadState_NewFunc(PyInterpreterState *interp); + +typedef PyObject *PyList_New(Py_ssize_t len); +typedef int PyList_Append(PyObject *list, PyObject *item); + + + +std::wstring GetCurrentModuleFilename() { + HMODULE hModule = nullptr; + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)GetCurrentModuleFilename, &hModule) != 0) { + wchar_t filename[MAX_PATH]; + GetModuleFileName(hModule, filename, MAX_PATH); + return filename; + } + return std::wstring(); +} + + +struct InitializeThreadingInfo { + PyImport_ImportModule* pyImportMod; + PyEval_Lock* initThreads; + + std::mutex mutex; + HANDLE initedEvent; // Note: only access with mutex locked (and check if not already nullptr). + bool completed; // Note: only access with mutex locked +}; + + +int AttachCallback(void *voidInitializeThreadingInfo) { + // initialize us for threading, this will acquire the GIL if not already created, and is a nop if the GIL is created. + // This leaves us in the proper state when we return back to the runtime whether the GIL was created or not before + // we were called. + InitializeThreadingInfo* initializeThreadingInfo = reinterpret_cast(voidInitializeThreadingInfo); + initializeThreadingInfo->initThreads(); // Note: calling multiple times is ok. + initializeThreadingInfo->pyImportMod("threading"); + + initializeThreadingInfo->mutex.lock(); + if(initializeThreadingInfo->initedEvent != nullptr) { + SetEvent(initializeThreadingInfo->initedEvent); + } + initializeThreadingInfo->completed = true; + initializeThreadingInfo->mutex.unlock(); + return 0; +} + + +// create a custom heap for our unordered map. This is necessary because if we suspend a thread while in a heap function +// then we could deadlock here. We need to be VERY careful about what we do while the threads are suspended. +static HANDLE g_heap = 0; + +template +class PrivateHeapAllocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + template + struct rebind { + typedef PrivateHeapAllocator other; + }; + + explicit PrivateHeapAllocator() {} + + PrivateHeapAllocator(PrivateHeapAllocator const&) {} + + ~PrivateHeapAllocator() {} + + template + PrivateHeapAllocator(PrivateHeapAllocator const&) {} + + pointer allocate(size_type size, std::allocator::const_pointer hint = 0) { + UNREFERENCED_PARAMETER(hint); + + if (g_heap == nullptr) { + g_heap = HeapCreate(0, 0, 0); + } + auto mem = HeapAlloc(g_heap, 0, size * sizeof(T)); + return static_cast(mem); + } + + void deallocate(pointer p, size_type n) { + UNREFERENCED_PARAMETER(n); + + HeapFree(g_heap, 0, p); + } + + size_type max_size() const { + return (std::numeric_limits::max)() / sizeof(T); + } + + void construct(pointer p, const T& t) { + new(p) T(t); + } + + void destroy(pointer p) { + p->~T(); + } +}; + +typedef std::unordered_map, std::equal_to, PrivateHeapAllocator>> ThreadMap; + +void ResumeThreads(ThreadMap &suspendedThreads) { + for (auto start = suspendedThreads.begin(); start != suspendedThreads.end(); start++) { + ResumeThread((*start).second); + CloseHandle((*start).second); + } + suspendedThreads.clear(); +} + +// Suspends all threads ensuring that they are not currently in a call to Py_AddPendingCall. +void SuspendThreads(ThreadMap &suspendedThreads, Py_AddPendingCall* addPendingCall, PyEval_ThreadsInitialized* threadsInited) { + DWORD curThreadId = GetCurrentThreadId(); + DWORD curProcess = GetCurrentProcessId(); + // suspend all the threads in the process so we can do things safely... + bool suspended; + + do { + suspended = false; + HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (h != INVALID_HANDLE_VALUE) { + + THREADENTRY32 te; + te.dwSize = sizeof(te); + if (Thread32First(h, &te)) { + do { + if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID) && te.th32OwnerProcessID == curProcess) { + + + if (te.th32ThreadID != curThreadId && suspendedThreads.find(te.th32ThreadID) == suspendedThreads.end()) { + auto hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID); + if (hThread != nullptr) { + SuspendThread(hThread); + + bool addingPendingCall = false; + + CONTEXT context; + memset(&context, 0x00, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_ALL; + GetThreadContext(hThread, &context); + +#if defined(_X86_) + if (context.Eip >= *(reinterpret_cast(addPendingCall)) && context.Eip <= (*(reinterpret_cast(addPendingCall))) + 0x100) { + addingPendingCall = true; + } +#elif defined(_AMD64_) + if (context.Rip >= *(reinterpret_cast(addPendingCall)) && context.Rip <= *(reinterpret_cast(addPendingCall) + 0x100)) { + addingPendingCall = true; + } +#endif + + if (addingPendingCall) { + // we appear to be adding a pending call via this thread - wait for this to finish so we can add our own pending call... + ResumeThread(hThread); + SwitchToThread(); // yield to the resumed thread if it's on our CPU... + CloseHandle(hThread); + } else { + suspendedThreads[te.th32ThreadID] = hThread; + } + suspended = true; + } + } + } + + te.dwSize = sizeof(te); + } while (Thread32Next(h, &te) && !threadsInited()); + } + CloseHandle(h); + } + } while (suspended && !threadsInited()); +} + + + +extern "C" +{ + + /** + * The returned value signals the error that happened! + * + * Return codes: + * 0 = all OK. + * 1 = Py_IsInitialized not found + * 2 = Py_IsInitialized returned false + * 3 = Missing Python API + * 4 = Interpreter not initialized + * 5 = Python version unknown + * 6 = Connect timeout + **/ + int DoAttach(HMODULE module, bool isDebug, const char *command, bool showDebugInfo ) + { + auto isInit = reinterpret_cast(GetProcAddress(module, "Py_IsInitialized")); + + if (isInit == nullptr) { + std::cerr << "Py_IsInitialized not found. " << std::endl << std::flush; + return 1; + } + if (!isInit()) { + std::cerr << "Py_IsInitialized returned false. " << std::endl << std::flush; + return 2; + } + + auto version = GetPythonVersion(module); + + // found initialized Python runtime, gather and check the APIs we need for a successful attach... + DEFINE_PROC(addPendingCall, Py_AddPendingCall*, "Py_AddPendingCall", -100); + DEFINE_PROC(interpHead, PyInterpreterState_Head*, "PyInterpreterState_Head", -110); + DEFINE_PROC(gilEnsure, PyGILState_Ensure*, "PyGILState_Ensure", -120); + DEFINE_PROC(gilRelease, PyGILState_Release*, "PyGILState_Release", -130); + DEFINE_PROC(threadHead, PyInterpreterState_ThreadHead*, "PyInterpreterState_ThreadHead", -140); + DEFINE_PROC(initThreads, PyEval_Lock*, "PyEval_InitThreads", -150); + DEFINE_PROC(releaseLock, PyEval_Lock*, "PyEval_ReleaseLock", -160); + DEFINE_PROC(threadsInited, PyEval_ThreadsInitialized*, "PyEval_ThreadsInitialized", -170); + DEFINE_PROC(threadNext, PyThreadState_Next*, "PyThreadState_Next", -180); + DEFINE_PROC(pyImportMod, PyImport_ImportModule*, "PyImport_ImportModule", -190); + DEFINE_PROC(pyNone, PyObject*, "_Py_NoneStruct", -2000); + DEFINE_PROC(pyRun_SimpleString, PyRun_SimpleString*, "PyRun_SimpleString", -210); + + // Either _PyThreadState_Current or _PyThreadState_UncheckedGet are required + DEFINE_PROC_NO_CHECK(curPythonThread, PyThreadState**, "_PyThreadState_Current", -220); // optional + DEFINE_PROC_NO_CHECK(getPythonThread, _PyThreadState_UncheckedGet*, "_PyThreadState_UncheckedGet", -230); // optional + + if (curPythonThread == nullptr && getPythonThread == nullptr) { + // we're missing some APIs, we cannot attach. + std::cerr << "Error, missing Python threading API!!" << std::endl << std::flush; + return -240; + } + + // Either _Py_CheckInterval or _PyEval_[GS]etSwitchInterval are useful, but not required + DEFINE_PROC_NO_CHECK(intervalCheck, int*, "_Py_CheckInterval", -250); // optional + DEFINE_PROC_NO_CHECK(getSwitchInterval, _PyEval_GetSwitchInterval*, "_PyEval_GetSwitchInterval", -260); // optional + DEFINE_PROC_NO_CHECK(setSwitchInterval, _PyEval_SetSwitchInterval*, "_PyEval_SetSwitchInterval", -270); // optional + + auto head = interpHead(); + if (head == nullptr) { + // this interpreter is loaded but not initialized. + std::cerr << "Interpreter not initialized! " << std::endl << std::flush; + return 4; + } + + // check that we're a supported version + if (version == PythonVersion_Unknown) { + std::cerr << "Python version unknown! " << std::endl << std::flush; + return 5; + } else if (version == PythonVersion_25 || version == PythonVersion_26 || + version == PythonVersion_30 || version == PythonVersion_31 || version == PythonVersion_32) { + std::cerr << "Python version unsupported! " << std::endl << std::flush; + return 5; + } + + + // We always try to initialize threading and import the threading module in the main thread in the code + // below... + // + // We need to initialize multiple threading support but we need to do so safely, so we call + // Py_AddPendingCall and have our callback then initialize multi threading. This is completely safe on 2.7 + // and up. Unfortunately that doesn't work if we're not actively running code on the main thread (blocked on a lock + // or reading input). + // + // Another option is to make sure no code is running - if there is no active thread then we can safely call + // PyEval_InitThreads and we're in business. But to know this is safe we need to first suspend all the other + // threads in the process and then inspect if any code is running (note that this is still not ideal because + // this thread will be the thread head for Python, but still better than not attach at all). + // + // Finally if code is running after we've suspended the threads then we can go ahead and do Py_AddPendingCall + // on down-level interpreters as long as we're sure no one else is making a call to Py_AddPendingCall at the same + // time. + // + // Therefore our strategy becomes: Make the Py_AddPendingCall on interpreters and wait for it. If it doesn't + // call after a timeout, suspend all threads - if a threads is in Py_AddPendingCall resume and try again. Once we've got all of the threads + // stopped and not in Py_AddPendingCall (which calls no functions its self, you can see this and it's size in the + // debugger) then see if we have a current thread. If not go ahead and initialize multiple threading (it's now safe, + // no Python code is running). + + InitializeThreadingInfo *initializeThreadingInfo = new InitializeThreadingInfo(); + initializeThreadingInfo->pyImportMod = pyImportMod; + initializeThreadingInfo->initThreads = initThreads; + initializeThreadingInfo->initedEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + + // Add the call to initialize threading. + addPendingCall(&AttachCallback, initializeThreadingInfo); + + ::WaitForSingleObject(initializeThreadingInfo->initedEvent, 5000); + + // Whether this completed or not, release the event handle as we won't use it anymore. + initializeThreadingInfo->mutex.lock(); + CloseHandle(initializeThreadingInfo->initedEvent); + bool completed = initializeThreadingInfo->completed; + initializeThreadingInfo->initedEvent = nullptr; + initializeThreadingInfo->mutex.unlock(); + + if(completed) { + // Note that this structure will leak if addPendingCall did not complete in the timeout + // (we can't release now because it's possible that it'll still be called). + delete initializeThreadingInfo; + if (showDebugInfo) { + std::cout << "addPendingCall to initialize threads/import threading completed. " << std::endl << std::flush; + } + } else { + if (showDebugInfo) { + std::cout << "addPendingCall to initialize threads/import threading did NOT complete. " << std::endl << std::flush; + } + } + + if (threadsInited()) { + // Note that since Python 3.7, threads are *always* initialized! + if (showDebugInfo) { + std::cout << "Threads initialized! " << std::endl << std::flush; + } + + } else { + int saveIntervalCheck; + unsigned long saveLongIntervalCheck; + if (intervalCheck != nullptr) { + // not available on 3.2 + saveIntervalCheck = *intervalCheck; + *intervalCheck = -1; // lower the interval check so pending calls are processed faster + saveLongIntervalCheck = 0; // prevent compiler warning + } else if (getSwitchInterval != nullptr && setSwitchInterval != nullptr) { + saveLongIntervalCheck = getSwitchInterval(); + setSwitchInterval(0); + saveIntervalCheck = 0; // prevent compiler warning + } + else { + saveIntervalCheck = 0; // prevent compiler warning + saveLongIntervalCheck = 0; // prevent compiler warning + } + + // If threads weren't initialized in our pending call, instead of giving a timeout, try + // to initialize it in this thread. + for(int attempts = 0; !threadsInited() && attempts < 20; attempts++) { + if(attempts > 0){ + // If we haven't been able to do it in the first time, wait a bit before retrying. + Sleep(10); + } + + ThreadMap suspendedThreads; + if (showDebugInfo) { + std::cout << "SuspendThreads(suspendedThreads, addPendingCall, threadsInited);" << std::endl << std::flush; + } + SuspendThreads(suspendedThreads, addPendingCall, threadsInited); + + if(!threadsInited()){ // Check again with threads suspended. + if (showDebugInfo) { + std::cout << "ENTERED if (!threadsInited()) {" << std::endl << std::flush; + } + auto curPyThread = getPythonThread ? getPythonThread() : *curPythonThread; + + if (curPyThread == nullptr) { + if (showDebugInfo) { + std::cout << "ENTERED if (curPyThread == nullptr) {" << std::endl << std::flush; + } + // no threads are currently running, it is safe to initialize multi threading. + PyGILState_STATE gilState; + if (version >= PythonVersion_34) { + // in 3.4 due to http://bugs.python.org/issue20891, + // we need to create our thread state manually + // before we can call PyGILState_Ensure() before we + // can call PyEval_InitThreads(). + + // Don't require this function unless we need it. + auto threadNew = (PyThreadState_NewFunc*)GetProcAddress(module, "PyThreadState_New"); + if (threadNew != nullptr) { + threadNew(head); + } + } + + if (version >= PythonVersion_32) { + // in 3.2 due to the new GIL and later we can't call Py_InitThreads + // without a thread being initialized. + // So we use PyGilState_Ensure here to first + // initialize the current thread, and then we use + // Py_InitThreads to bring up multi-threading. + // Some context here: http://bugs.python.org/issue11329 + // http://pytools.codeplex.com/workitem/834 + gilState = gilEnsure(); + } + else { + gilState = PyGILState_LOCKED; // prevent compiler warning + } + + if (showDebugInfo) { + std::cout << "Called initThreads()" << std::endl << std::flush; + } + // Initialize threads in our secondary thread (this is NOT ideal because + // this thread will be the thread head), but is still better than not being + // able to attach if the main thread is not actually running any code. + initThreads(); + + if (version >= PythonVersion_32) { + // we will release the GIL here + gilRelease(gilState); + } else { + releaseLock(); + } + } + } + ResumeThreads(suspendedThreads); + } + + + if (intervalCheck != nullptr) { + *intervalCheck = saveIntervalCheck; + } else if (setSwitchInterval != nullptr) { + setSwitchInterval(saveLongIntervalCheck); + } + + } + + if (g_heap != nullptr) { + HeapDestroy(g_heap); + g_heap = nullptr; + } + + if (!threadsInited()) { + std::cerr << "Unable to initialize threads in the given timeout! " << std::endl << std::flush; + return 8; + } + + GilHolder gilLock(gilEnsure, gilRelease); // acquire and hold the GIL until done... + + pyRun_SimpleString(command); + return 0; + + } + + + + + // ======================================== Code related to setting tracing to existing threads. + + + /** + * This function is meant to be called to execute some arbitrary python code to be + * run. It'll initialize threads as needed and then run the code with pyRun_SimpleString. + * + * @param command: the python code to be run + * @param attachInfo: pointer to an int specifying whether we should show debug info (1) or not (0). + **/ + DECLDIR int AttachAndRunPythonCode(const char *command, int *attachInfo ) + { + + int SHOW_DEBUG_INFO = 1; + + bool showDebugInfo = (*attachInfo & SHOW_DEBUG_INFO) != 0; + + if (showDebugInfo) { + std::cout << "AttachAndRunPythonCode started (showing debug info). " << std::endl << std::flush; + } + + ModuleInfo moduleInfo = GetPythonModule(); + if (moduleInfo.errorGettingModule != 0) { + return moduleInfo.errorGettingModule; + } + HMODULE module = moduleInfo.module; + int attached = DoAttach(module, moduleInfo.isDebug, command, showDebugInfo); + + if (attached != 0) { + std::cerr << "Error when injecting code in target process. Error code (on windows): " << attached << std::endl << std::flush; + } + return attached; + } + + + DECLDIR int PrintDebugInfo() { + PRINT("Getting debug info..."); + ModuleInfo moduleInfo = GetPythonModule(); + if (moduleInfo.errorGettingModule != 0) { + PRINT("Error getting python module"); + return 0; + } + HMODULE module = moduleInfo.module; + + DEFINE_PROC(interpHead, PyInterpreterState_Head*, "PyInterpreterState_Head", 0); + DEFINE_PROC(threadHead, PyInterpreterState_ThreadHead*, "PyInterpreterState_ThreadHead", 0); + DEFINE_PROC(threadNext, PyThreadState_Next*, "PyThreadState_Next", 160); + DEFINE_PROC(gilEnsure, PyGILState_Ensure*, "PyGILState_Ensure", 0); + DEFINE_PROC(gilRelease, PyGILState_Release*, "PyGILState_Release", 0); + + auto head = interpHead(); + if (head == nullptr) { + // this interpreter is loaded but not initialized. + PRINT("Interpreter not initialized!"); + return 0; + } + + auto version = GetPythonVersion(module); + printf("Python version: %d\n", version); + + GilHolder gilLock(gilEnsure, gilRelease); // acquire and hold the GIL until done... + auto curThread = threadHead(head); + if (curThread == nullptr) { + PRINT("Thread head is NULL.") + return 0; + } + + for (auto curThread = threadHead(head); curThread != nullptr; curThread = threadNext(curThread)) { + printf("Found thread id: %d\n", GetPythonThreadId(version, curThread)); + } + + PRINT("Finished getting debug info.") + return 0; + } + + + /** + * This function may be called to set a tracing function to existing python threads. + **/ + DECLDIR int AttachDebuggerTracing(bool showDebugInfo, void* pSetTraceFunc, void* pTraceFunc, unsigned int threadId, void* pPyNone) + { + ModuleInfo moduleInfo = GetPythonModule(); + if (moduleInfo.errorGettingModule != 0) { + return moduleInfo.errorGettingModule; + } + HMODULE module = moduleInfo.module; + if (showDebugInfo) { + std::cout << "Setting sys trace for existing threads." << std::endl << std::flush; + } + int attached = 0; + PyObjectHolder traceFunc(moduleInfo.isDebug, reinterpret_cast(pTraceFunc), true); + PyObjectHolder setTraceFunc(moduleInfo.isDebug, reinterpret_cast(pSetTraceFunc), true); + PyObjectHolder pyNone(moduleInfo.isDebug, reinterpret_cast(pPyNone), true); + + int temp = InternalSetSysTraceFunc(module, moduleInfo.isDebug, showDebugInfo, &traceFunc, &setTraceFunc, threadId, &pyNone); + if (temp == 0) { + // we've successfully attached the debugger + return 0; + } else { + if (temp > attached) { + //I.e.: the higher the value the more significant it is. + attached = temp; + } + } + + if (showDebugInfo) { + std::cout << "Setting sys trace for existing threads failed with code: " << attached << "." << std::endl << std::flush; + } + return attached; + } + +} + diff --git a/pydevd_attach_to_process/windows/attach.h b/pydevd_attach_to_process/windows/attach.h new file mode 100644 index 0000000..3a2b582 --- /dev/null +++ b/pydevd_attach_to_process/windows/attach.h @@ -0,0 +1,57 @@ +/* **************************************************************************** + * + * Copyright (c) Brainwy software Ltda. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Apache License, Version 2.0, please send an email to + * vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + * + * ***************************************************************************/ + +#ifndef _ATTACH_DLL_H_ +#define _ATTACH_DLL_H_ + +#if defined DLL_EXPORT +#define DECLDIR __declspec(dllexport) +#else +#define DECLDIR __declspec(dllimport) +#endif + + +extern "C" +{ + DECLDIR int AttachAndRunPythonCode(const char *command, int *result ); + + /* + * Helper to print debug information from the current process + */ + DECLDIR int PrintDebugInfo(); + + /* + Could be used with ctypes (note that the threading should be initialized, so, + doing it in a thread as below is recommended): + + def check(): + + import ctypes + lib = ctypes.cdll.LoadLibrary(r'C:\...\attach_x86.dll') + print 'result', lib.AttachDebuggerTracing(0) + + t = threading.Thread(target=check) + t.start() + t.join() + */ + DECLDIR int AttachDebuggerTracing( + bool showDebugInfo, + void* pSetTraceFunc, // Actually PyObject*, but we don't want to include it here. + void* pTraceFunc, // Actually PyObject*, but we don't want to include it here. + unsigned int threadId, + void* pPyNone // Actually PyObject*, but we don't want to include it here. + ); +} + +#endif \ No newline at end of file diff --git a/pydevd_attach_to_process/windows/compile_windows.bat b/pydevd_attach_to_process/windows/compile_windows.bat new file mode 100644 index 0000000..0dafd06 --- /dev/null +++ b/pydevd_attach_to_process/windows/compile_windows.bat @@ -0,0 +1,39 @@ +@set VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe +@echo Using vswhere at %VSWHERE% +@for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set VSDIR=%%i +@echo Using Visual C++ at %VSDIR% + +call "%VSDIR%\VC\Auxiliary\Build\vcvarsall.bat" x86 -vcvars_spectre_libs=spectre + +cl -DUNICODE -D_UNICODE /EHsc /Zi /O1 /W3 /LD /MD /Qspectre attach.cpp /link /DEBUG /OPT:REF /OPT:ICF /GUARD:CF /out:attach_x86.dll +copy attach_x86.dll ..\attach_x86.dll /Y +copy attach_x86.pdb ..\attach_x86.pdb /Y + +cl -DUNICODE -D_UNICODE /EHsc /Zi /O1 /W3 /LD /MD /D BITS_32 /Qspectre run_code_on_dllmain.cpp /link /DEBUG /OPT:REF /OPT:ICF /GUARD:CF /out:run_code_on_dllmain_x86.dll +copy run_code_on_dllmain_x86.dll ..\run_code_on_dllmain_x86.dll /Y +copy run_code_on_dllmain_x86.pdb ..\run_code_on_dllmain_x86.pdb /Y + +cl /EHsc /Zi /O1 /W3 /Qspectre inject_dll.cpp /link /DEBUG /OPT:REF /OPT:ICF /GUARD:CF /out:inject_dll_x86.exe +copy inject_dll_x86.exe ..\inject_dll_x86.exe /Y +copy inject_dll_x86.pdb ..\inject_dll_x86.pdb /Y + +call "%VSDIR%\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 -vcvars_spectre_libs=spectre + +cl -DUNICODE -D_UNICODE /EHsc /Zi /O1 /W3 /LD /MD /Qspectre attach.cpp /link /DEBUG /OPT:REF /OPT:ICF /GUARD:CF /out:attach_amd64.dll +copy attach_amd64.dll ..\attach_amd64.dll /Y +copy attach_amd64.pdb ..\attach_amd64.pdb /Y + +cl -DUNICODE -D_UNICODE /EHsc /Zi /O1 /W3 /LD /MD /D BITS_64 /Qspectre run_code_on_dllmain.cpp /link /DEBUG /OPT:REF /OPT:ICF /GUARD:CF /out:run_code_on_dllmain_amd64.dll +copy run_code_on_dllmain_amd64.dll ..\run_code_on_dllmain_amd64.dll /Y +copy run_code_on_dllmain_amd64.pdb ..\run_code_on_dllmain_amd64.pdb /Y + +cl /EHsc /Zi /O1 /W3 /Qspectre inject_dll.cpp /link /DEBUG /OPT:REF /OPT:ICF /GUARD:CF /out:inject_dll_amd64.exe +copy inject_dll_amd64.exe ..\inject_dll_amd64.exe /Y +copy inject_dll_amd64.pdb ..\inject_dll_amd64.pdb /Y + +del *.exe +del *.lib +del *.obj +del *.pdb +del *.dll +del *.exp \ No newline at end of file diff --git a/pydevd_attach_to_process/windows/inject_dll.cpp b/pydevd_attach_to_process/windows/inject_dll.cpp new file mode 100644 index 0000000..5b2b34f --- /dev/null +++ b/pydevd_attach_to_process/windows/inject_dll.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "kernel32.lib") +#pragma comment(lib, "user32.lib") + +// Helper to free data when we leave the scope. +class DataToFree { +public: + HANDLE hProcess; + HANDLE snapshotHandle; + + LPVOID remoteMemoryAddr; + int remoteMemorySize; + + DataToFree(){ + this->hProcess = nullptr; + this->snapshotHandle = nullptr; + + this->remoteMemoryAddr = nullptr; + this->remoteMemorySize = 0; + } + + ~DataToFree() { + if(this->hProcess != nullptr){ + + if(this->remoteMemoryAddr != nullptr && this->remoteMemorySize != 0){ + VirtualFreeEx(this->hProcess, this->remoteMemoryAddr, this->remoteMemorySize, MEM_RELEASE); + this->remoteMemoryAddr = nullptr; + this->remoteMemorySize = 0; + } + + CloseHandle(this->hProcess); + this->hProcess = nullptr; + } + + if(this->snapshotHandle != nullptr){ + CloseHandle(this->snapshotHandle); + this->snapshotHandle = nullptr; + } + } +}; + + +/** + * All we do here is load a dll in a remote program (in a remote thread). + * + * Arguments must be the pid and the dll name to run. + * + * i.e.: inject_dll.exe + */ +int wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] ) +{ + std::cout << "Running executable to inject dll." << std::endl; + + // Helper to clear resources. + DataToFree dataToFree; + + if(argc != 3){ + std::cout << "Expected 2 arguments (pid, dll name)." << std::endl; + return 1; + } + + const int pid = _wtoi(argv[1]); + if(pid == 0){ + std::cout << "Invalid pid." << std::endl; + return 2; + } + + const int MAX_PATH_SIZE_PADDED = MAX_PATH + 1; + char dllPath[MAX_PATH_SIZE_PADDED]; + memset(&dllPath[0], '\0', MAX_PATH_SIZE_PADDED); + size_t pathLen = 0; + wcstombs_s(&pathLen, dllPath, argv[2], MAX_PATH); + + const bool inheritable = false; + const HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, inheritable, pid); + if(hProcess == nullptr || hProcess == INVALID_HANDLE_VALUE){ + std::cout << "Unable to open process with pid: " << pid << ". Error code: " << GetLastError() << "." << std::endl; + return 3; + } + dataToFree.hProcess = hProcess; + std::cout << "OpenProcess with pid: " << pid << std::endl; + + const LPVOID remoteMemoryAddr = VirtualAllocEx(hProcess, nullptr, MAX_PATH_SIZE_PADDED, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if(remoteMemoryAddr == nullptr){ + std::cout << "Error. Unable to allocate memory in pid: " << pid << ". Error code: " << GetLastError() << "." << std::endl; + return 4; + } + dataToFree.remoteMemorySize = MAX_PATH_SIZE_PADDED; + dataToFree.remoteMemoryAddr = remoteMemoryAddr; + + std::cout << "VirtualAllocEx in pid: " << pid << std::endl; + + const bool written = WriteProcessMemory(hProcess, remoteMemoryAddr, dllPath, pathLen, nullptr); + if(!written){ + std::cout << "Error. Unable to write to memory in pid: " << pid << ". Error code: " << GetLastError() << "." << std::endl; + return 5; + } + std::cout << "WriteProcessMemory in pid: " << pid << std::endl; + + const LPVOID loadLibraryAddress = (LPVOID) GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); + if(loadLibraryAddress == nullptr){ + std::cout << "Error. Unable to get LoadLibraryA address. Error code: " << GetLastError() << "." << std::endl; + return 6; + } + std::cout << "loadLibraryAddress: " << pid << std::endl; + + const HANDLE remoteThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE) loadLibraryAddress, remoteMemoryAddr, 0, nullptr); + if (remoteThread == nullptr) { + std::cout << "Error. Unable to CreateRemoteThread. Error code: " << GetLastError() << "." << std::endl; + return 7; + } + + // We wait for the load to finish before proceeding to get the function to actually do the attach. + std::cout << "Waiting for LoadLibraryA to complete." << std::endl; + DWORD result = WaitForSingleObject(remoteThread, 5 * 1000); + + if(result == WAIT_TIMEOUT) { + std::cout << "WaitForSingleObject(LoadLibraryA thread) timed out." << std::endl; + return 8; + + } else if(result == WAIT_FAILED) { + std::cout << "WaitForSingleObject(LoadLibraryA thread) failed. Error code: " << GetLastError() << "." << std::endl; + return 9; + } + + std::cout << "Ok, finished dll injection." << std::endl; + return 0; +} \ No newline at end of file diff --git a/pydevd_attach_to_process/windows/py_win_helpers.hpp b/pydevd_attach_to_process/windows/py_win_helpers.hpp new file mode 100644 index 0000000..ffd6078 --- /dev/null +++ b/pydevd_attach_to_process/windows/py_win_helpers.hpp @@ -0,0 +1,77 @@ +#ifndef _PY_WIN_HELPERS_HPP_ +#define _PY_WIN_HELPERS_HPP_ + +bool IsPythonModule(HMODULE module, bool &isDebug) { + wchar_t mod_name[MAX_PATH]; + isDebug = false; + if (GetModuleBaseName(GetCurrentProcess(), module, mod_name, MAX_PATH)) { + if (_wcsnicmp(mod_name, L"python", 6) == 0) { + if (wcslen(mod_name) >= 10 && _wcsnicmp(mod_name + 8, L"_d", 2) == 0) { + isDebug = true; + } + + // Check if the module has Py_IsInitialized. + DEFINE_PROC_NO_CHECK(isInit, Py_IsInitialized*, "Py_IsInitialized", 0); + DEFINE_PROC_NO_CHECK(gilEnsure, PyGILState_Ensure*, "PyGILState_Ensure", 51); + DEFINE_PROC_NO_CHECK(gilRelease, PyGILState_Release*, "PyGILState_Release", 51); + if (isInit == nullptr || gilEnsure == nullptr || gilRelease == nullptr) { + return false; + } + + + return true; + } + } + return false; +} + + +struct ModuleInfo { + HMODULE module; + bool isDebug; + int errorGettingModule; // 0 means ok, negative values some error (should never be positive). +}; + + +ModuleInfo GetPythonModule() { + HANDLE hProcess = GetCurrentProcess(); + ModuleInfo moduleInfo; + moduleInfo.module = nullptr; + moduleInfo.isDebug = false; + moduleInfo.errorGettingModule = 0; + + DWORD modSize = sizeof(HMODULE) * 1024; + HMODULE* hMods = (HMODULE*)_malloca(modSize); + if (hMods == nullptr) { + std::cout << "hmods not allocated! " << std::endl << std::flush; + moduleInfo.errorGettingModule = -1; + return moduleInfo; + } + + DWORD modsNeeded; + while (!EnumProcessModules(hProcess, hMods, modSize, &modsNeeded)) { + // try again w/ more space... + _freea(hMods); + hMods = (HMODULE*)_malloca(modsNeeded); + if (hMods == nullptr) { + std::cout << "hmods not allocated (2)! " << std::endl << std::flush; + moduleInfo.errorGettingModule = -2; + return moduleInfo; + } + modSize = modsNeeded; + } + + for (size_t i = 0; i < modsNeeded / sizeof(HMODULE); i++) { + bool isDebug; + if (IsPythonModule(hMods[i], isDebug)) { + moduleInfo.isDebug = isDebug; + moduleInfo.module = hMods[i]; + return moduleInfo; + } + } + std::cout << "Unable to find python module. " << std::endl << std::flush; + moduleInfo.errorGettingModule = -3; + return moduleInfo; +} + +#endif \ No newline at end of file diff --git a/pydevd_attach_to_process/windows/run_code_in_memory.hpp b/pydevd_attach_to_process/windows/run_code_in_memory.hpp new file mode 100644 index 0000000..6839810 --- /dev/null +++ b/pydevd_attach_to_process/windows/run_code_in_memory.hpp @@ -0,0 +1,116 @@ +#ifndef _PY_RUN_CODE_IN_MEMORY_HPP_ +#define _PY_RUN_CODE_IN_MEMORY_HPP_ + +#include +#include "attach.h" +#include "stdafx.h" + +#include +#include +#include +#include + +#include "../common/python.h" +#include "../common/ref_utils.hpp" +#include "../common/py_utils.hpp" +#include "../common/py_settrace.hpp" + +#include "py_win_helpers.hpp" + +#pragma comment(lib, "kernel32.lib") +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "advapi32.lib") + +DECLDIR int AttachAndRunPythonCode(const char *command, int *attachInfo ); + +// NOTE: BUFSIZE must be the same from add_code_to_python_process.py +#define BUFSIZE 2048 + +// Helper to free data when we leave the scope. +class DataToFree { + +public: + + HANDLE hMapFile; + void* mapViewOfFile; + char* codeToRun; + + DataToFree() { + this->hMapFile = nullptr; + this->mapViewOfFile = nullptr; + this->codeToRun = nullptr; + } + + ~DataToFree() { + if (this->hMapFile != nullptr) { + CloseHandle(this->hMapFile); + this->hMapFile = nullptr; + } + if (this->mapViewOfFile != nullptr) { + UnmapViewOfFile(this->mapViewOfFile); + this->mapViewOfFile = nullptr; + } + if (this->codeToRun != nullptr) { + delete this->codeToRun; + this->codeToRun = nullptr; + } + } +}; + + + +extern "C" +{ + /** + * This method will read the code to be executed from the named shared memory + * and execute it. + */ + DECLDIR int RunCodeInMemoryInAttachedDll() { + // PRINT("Attempting to run Python code from named shared memory.") + //get the code to be run (based on https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory). + HANDLE hMapFile; + char* mapViewOfFile; + + DataToFree dataToFree; + + std::string namedSharedMemoryName("__pydevd_pid_code_to_run__"); + namedSharedMemoryName += std::to_string(GetCurrentProcessId()); + + hMapFile = OpenFileMappingA( + FILE_MAP_ALL_ACCESS, // read/write access + FALSE, // do not inherit the name + namedSharedMemoryName.c_str()); // name of mapping object + + if (hMapFile == nullptr) { + std::cout << "Error opening named shared memory (OpenFileMapping): " << GetLastError() + " name: " << namedSharedMemoryName << std::endl; + return 1; + } else { + // PRINT("Opened named shared memory.") + } + + dataToFree.hMapFile = hMapFile; + + mapViewOfFile = reinterpret_cast < char* > (MapViewOfFile(hMapFile, // handle to map object + FILE_MAP_ALL_ACCESS, // read/write permission + 0, + 0, + BUFSIZE)); + + if (mapViewOfFile == nullptr) { + std::cout << "Error mapping view of named shared memory (MapViewOfFile): " << GetLastError() << std::endl; + return 1; + } else { + // PRINT("Mapped view of file.") + } + dataToFree.mapViewOfFile = mapViewOfFile; + // std::cout << "Will run contents: " << mapViewOfFile << std::endl; + + dataToFree.codeToRun = new char[BUFSIZE]; + memmove(dataToFree.codeToRun, mapViewOfFile, BUFSIZE); + + int attachInfo = 0; + return AttachAndRunPythonCode(dataToFree.codeToRun, &attachInfo); + } +} + +#endif \ No newline at end of file diff --git a/pydevd_attach_to_process/windows/run_code_on_dllmain.cpp b/pydevd_attach_to_process/windows/run_code_on_dllmain.cpp new file mode 100644 index 0000000..fcf7354 --- /dev/null +++ b/pydevd_attach_to_process/windows/run_code_on_dllmain.cpp @@ -0,0 +1,78 @@ +#include +#include +#include "attach.h" +#include "stdafx.h" + +#include +#include +#include +#include + +typedef int (_RunCodeInMemoryInAttachedDll)(); + +HINSTANCE globalDllInstance = NULL; + +class NotificationHelper { +public: +#pragma warning( push ) +#pragma warning( disable : 4722 ) +// disable c4722 here: Destructor never returns warning. Compiler sees ExitThread and assumes that +// there is a potential memory leak. + ~NotificationHelper(){ + std::string eventName("_pydevd_pid_event_"); + eventName += std::to_string(GetCurrentProcessId()); + + // When we finish we need to set the event that the caller is waiting for and + // unload the dll (if we don't exit this dll we won't be able to reattach later on). + auto event = CreateEventA(nullptr, false, false, eventName.c_str()); + if (event != nullptr) { + SetEvent(event); + CloseHandle(event); + } + FreeLibraryAndExitThread(globalDllInstance, 0); + } +#pragma warning( pop ) +}; + +DWORD WINAPI RunCodeInThread(LPVOID lpParam){ + NotificationHelper notificationHelper; // When we exit the scope the destructor should take care of the cleanup. + +#ifdef BITS_32 + HMODULE attachModule = GetModuleHandleA("attach_x86.dll"); +#else + HMODULE attachModule = GetModuleHandleA("attach_amd64.dll"); +#endif + + if (attachModule == nullptr) { + std::cout << "Error: unable to get attach_x86.dll or attach_amd64.dll module handle." << std::endl; + return 900; + } + + _RunCodeInMemoryInAttachedDll* runCode = reinterpret_cast < _RunCodeInMemoryInAttachedDll* > (GetProcAddress(attachModule, "RunCodeInMemoryInAttachedDll")); + if (runCode == nullptr) { + std::cout << "Error: unable to GetProcAddress(attachModule, RunCodeInMemoryInAttachedDll) from attach_x86.dll or attach_amd64.dll." << std::endl; + return 901; + } + + runCode(); + return 0; +} + +/** + * When the dll is loaded we create a thread that will call 'RunCodeInMemoryInAttachedDll' + * in the attach dll (when completed we unload this library for a reattach to work later on). + */ +BOOL WINAPI DllMain( + _In_ HINSTANCE hinstDLL, + _In_ DWORD fdwReason, + _In_ LPVOID lpvReserved +){ + if(fdwReason == DLL_PROCESS_ATTACH){ + globalDllInstance = hinstDLL; + DWORD threadId; + CreateThread(nullptr, 0, &RunCodeInThread, nullptr, 0, &threadId); + } + else if(fdwReason == DLL_PROCESS_DETACH){ + } + return true; +} diff --git a/pydevd_attach_to_process/windows/stdafx.cpp b/pydevd_attach_to_process/windows/stdafx.cpp new file mode 100644 index 0000000..4b80b54 --- /dev/null +++ b/pydevd_attach_to_process/windows/stdafx.cpp @@ -0,0 +1,22 @@ +/* **************************************************************************** + * + * Copyright (c) Microsoft Corporation. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Apache License, Version 2.0, please send an email to + * vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + * + * ***************************************************************************/ + +// stdafx.cpp : source file that includes just the standard includes +// PyDebugAttach.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/pydevd_attach_to_process/windows/stdafx.h b/pydevd_attach_to_process/windows/stdafx.h new file mode 100644 index 0000000..15274c0 --- /dev/null +++ b/pydevd_attach_to_process/windows/stdafx.h @@ -0,0 +1,36 @@ +/* **************************************************************************** + * + * Copyright (c) Microsoft Corporation. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Apache License, Version 2.0, please send an email to + * vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + * + * ***************************************************************************/ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include +#include +#include +#include + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include diff --git a/pydevd_attach_to_process/windows/targetver.h b/pydevd_attach_to_process/windows/targetver.h new file mode 100644 index 0000000..acff541 --- /dev/null +++ b/pydevd_attach_to_process/windows/targetver.h @@ -0,0 +1,22 @@ +/* **************************************************************************** + * + * Copyright (c) Microsoft Corporation. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Apache License, Version 2.0, please send an email to + * vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + * + * ***************************************************************************/ + +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/pydevd_file_utils.py b/pydevd_file_utils.py new file mode 100644 index 0000000..ffe0d7f --- /dev/null +++ b/pydevd_file_utils.py @@ -0,0 +1,911 @@ +r''' + This module provides utilities to get the absolute filenames so that we can be sure that: + - The case of a file will match the actual file in the filesystem (otherwise breakpoints won't be hit). + - Providing means for the user to make path conversions when doing a remote debugging session in + one machine and debugging in another. + + To do that, the PATHS_FROM_ECLIPSE_TO_PYTHON constant must be filled with the appropriate paths. + + @note: + in this context, the server is where your python process is running + and the client is where eclipse is running. + + E.g.: + If the server (your python process) has the structure + /user/projects/my_project/src/package/module1.py + + and the client has: + c:\my_project\src\package\module1.py + + the PATHS_FROM_ECLIPSE_TO_PYTHON would have to be: + PATHS_FROM_ECLIPSE_TO_PYTHON = [(r'c:\my_project\src', r'/user/projects/my_project/src')] + + alternatively, this can be set with an environment variable from the command line: + set PATHS_FROM_ECLIPSE_TO_PYTHON=[['c:\my_project\src','/user/projects/my_project/src']] + + @note: DEBUG_CLIENT_SERVER_TRANSLATION can be set to True to debug the result of those translations + + @note: the case of the paths is important! Note that this can be tricky to get right when one machine + uses a case-independent filesystem and the other uses a case-dependent filesystem (if the system being + debugged is case-independent, 'normcase()' should be used on the paths defined in PATHS_FROM_ECLIPSE_TO_PYTHON). + + @note: all the paths with breakpoints must be translated (otherwise they won't be found in the server) + + @note: to enable remote debugging in the target machine (pydev extensions in the eclipse installation) + import pydevd;pydevd.settrace(host, stdoutToServer, stderrToServer, port, suspend) + + see parameter docs on pydevd.py + + @note: for doing a remote debugging session, all the pydevd_ files must be on the server accessible + through the PYTHONPATH (and the PATHS_FROM_ECLIPSE_TO_PYTHON only needs to be set on the target + machine for the paths that'll actually have breakpoints). +''' + +from _pydev_bundle import pydev_log +from _pydevd_bundle.pydevd_constants import DebugInfoHolder, IS_WINDOWS, IS_JYTHON, \ + DISABLE_FILE_VALIDATION, is_true_in_env +from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding +from _pydevd_bundle.pydevd_comm_constants import file_system_encoding, filesystem_encoding_is_utf8 +from _pydev_bundle.pydev_log import error_once + +import json +import os.path +import sys +import itertools +import ntpath +from functools import partial + +_nt_os_normcase = ntpath.normcase +os_path_basename = os.path.basename +os_path_exists = os.path.exists +join = os.path.join + +try: + FileNotFoundError +except NameError: + FileNotFoundError = IOError # noqa + +try: + os_path_real_path = os.path.realpath # @UndefinedVariable +except: + # jython does not support os.path.realpath + # realpath is a no-op on systems without islink support + os_path_real_path = os.path.abspath + + +def _get_library_dir(): + library_dir = None + try: + import sysconfig + library_dir = sysconfig.get_path('purelib') + except ImportError: + pass # i.e.: Only 2.7 onwards + + if library_dir is None or not os_path_exists(library_dir): + for path in sys.path: + if os_path_exists(path) and os.path.basename(path) == 'site-packages': + library_dir = path + break + + if library_dir is None or not os_path_exists(library_dir): + library_dir = os.path.dirname(os.__file__) + + return library_dir + + +# Note: we can't call sysconfig.get_path from _apply_func_and_normalize_case (it deadlocks on Python 2.7) so, we +# need to get the library dir during module loading. +_library_dir = _get_library_dir() + +# defined as a list of tuples where the 1st element of the tuple is the path in the client machine +# and the 2nd element is the path in the server machine. +# see module docstring for more details. +try: + PATHS_FROM_ECLIPSE_TO_PYTHON = json.loads(os.environ.get('PATHS_FROM_ECLIPSE_TO_PYTHON', '[]')) +except Exception: + pydev_log.critical('Error loading PATHS_FROM_ECLIPSE_TO_PYTHON from environment variable.') + pydev_log.exception() + PATHS_FROM_ECLIPSE_TO_PYTHON = [] +else: + if not isinstance(PATHS_FROM_ECLIPSE_TO_PYTHON, list): + pydev_log.critical('Expected PATHS_FROM_ECLIPSE_TO_PYTHON loaded from environment variable to be a list.') + PATHS_FROM_ECLIPSE_TO_PYTHON = [] + else: + # Converting json lists to tuple + PATHS_FROM_ECLIPSE_TO_PYTHON = [tuple(x) for x in PATHS_FROM_ECLIPSE_TO_PYTHON] + +# example: +# PATHS_FROM_ECLIPSE_TO_PYTHON = [ +# (r'd:\temp\temp_workspace_2\test_python\src\yyy\yyy', +# r'd:\temp\temp_workspace_2\test_python\src\hhh\xxx') +# ] + +convert_to_long_pathname = lambda filename:filename +convert_to_short_pathname = lambda filename:filename +get_path_with_real_case = lambda filename:filename + +if sys.platform == 'win32': + try: + import ctypes + from ctypes.wintypes import MAX_PATH, LPCWSTR, LPWSTR, DWORD + + GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW # noqa + GetLongPathName.argtypes = [LPCWSTR, LPWSTR, DWORD] + GetLongPathName.restype = DWORD + + GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW # noqa + GetShortPathName.argtypes = [LPCWSTR, LPWSTR, DWORD] + GetShortPathName.restype = DWORD + + def _convert_to_long_pathname(filename): + buf = ctypes.create_unicode_buffer(MAX_PATH) + + rv = GetLongPathName(filename, buf, MAX_PATH) + if rv != 0 and rv <= MAX_PATH: + filename = buf.value + + return filename + + def _convert_to_short_pathname(filename): + buf = ctypes.create_unicode_buffer(MAX_PATH) + + rv = GetShortPathName(filename, buf, MAX_PATH) + if rv != 0 and rv <= MAX_PATH: + filename = buf.value + + return filename + + # Note that we have a cache for previous list dirs... the only case where this may be an + # issue is if the user actually changes the case of an existing file on windows while + # the debugger is executing (as this seems very unlikely and the cache can save a + # reasonable time -- especially on mapped drives -- it seems nice to have it). + _listdir_cache = {} + + def _resolve_listing(resolved, iter_parts, cache=_listdir_cache): + while True: # Note: while True to make iterative and not recursive + try: + resolve_lowercase = next(iter_parts) # must be lowercase already + except StopIteration: + return resolved + + resolved_lower = resolved.lower() + + resolved_joined = cache.get((resolved_lower, resolve_lowercase)) + if resolved_joined is None: + dir_contents = cache.get(resolved_lower) + if dir_contents is None: + dir_contents = cache[resolved_lower] = os.listdir(resolved) + + for filename in dir_contents: + if filename.lower() == resolve_lowercase: + resolved_joined = os.path.join(resolved, filename) + cache[(resolved_lower, resolve_lowercase)] = resolved_joined + break + else: + raise FileNotFoundError('Unable to find: %s in %s' % ( + resolve_lowercase, resolved)) + + resolved = resolved_joined + + def _get_path_with_real_case(filename): + # Note: this previously made: + # convert_to_long_pathname(convert_to_short_pathname(filename)) + # but this is no longer done because we can't rely on getting the shortname + # consistently (there are settings to disable it on Windows). + # So, using approach which resolves by listing the dir. + + if '~' in filename: + filename = convert_to_long_pathname(filename) + + if filename.startswith('<') or not os_path_exists(filename): + return filename # Not much we can do. + + drive, parts = os.path.splitdrive(os.path.normpath(filename)) + drive = drive.upper() + while parts.startswith(os.path.sep): + parts = parts[1:] + drive += os.path.sep + parts = parts.lower().split(os.path.sep) + + try: + if parts == ['']: + return drive + return _resolve_listing(drive, iter(parts)) + except FileNotFoundError: + _listdir_cache.clear() + # Retry once after clearing the cache we have. + try: + return _resolve_listing(drive, iter(parts)) + except FileNotFoundError: + if os_path_exists(filename): + # This is really strange, ask the user to report as error. + pydev_log.critical( + 'pydev debugger: critical: unable to get real case for file. Details:\n' + 'filename: %s\ndrive: %s\nparts: %s\n' + '(please create a ticket in the tracker to address this).', + filename, drive, parts + ) + pydev_log.exception() + # Don't fail, just return the original file passed. + return filename + + # Check that it actually works + _get_path_with_real_case(__file__) + except: + # Something didn't quite work out, leave no-op conversions in place. + if DebugInfoHolder.DEBUG_TRACE_LEVEL > 2: + pydev_log.exception() + else: + convert_to_long_pathname = _convert_to_long_pathname + convert_to_short_pathname = _convert_to_short_pathname + get_path_with_real_case = _get_path_with_real_case + +elif IS_JYTHON and IS_WINDOWS: + + def get_path_with_real_case(filename): + from java.io import File # noqa + f = File(filename) + ret = f.getCanonicalPath() + return ret + +if IS_JYTHON: + + def _normcase_windows(filename): + return filename.lower() + +else: + + def _normcase_windows(filename): + # `normcase` doesn't lower case on Python 2 for non-English locale, so we should do it manually. + if '~' in filename: + filename = convert_to_long_pathname(filename) + + filename = _nt_os_normcase(filename) + return filename.lower() + + +def _normcase_linux(filename): + return filename # no-op + + +_filename_normalization = os.environ.get('PYDEVD_FILENAME_NORMALIZATION', '').lower() +if _filename_normalization == 'lower': + # Note: this is mostly for testing (forcing to always lower-case all contents + # internally -- used to mimick Windows normalization on Linux). + + def _normcase_lower(filename): + return filename.lower() + + _default_normcase = _normcase_lower + +elif _filename_normalization == 'none': + # Disable any filename normalization may be an option on Windows if the + # user is having issues under some circumstances. + _default_normcase = _normcase_linux + +elif IS_WINDOWS: + _default_normcase = _normcase_windows + +else: + _default_normcase = _normcase_linux + + +def normcase(s, NORMCASE_CACHE={}): + try: + return NORMCASE_CACHE[s] + except: + normalized = NORMCASE_CACHE[s] = _default_normcase(s) + return normalized + + +_ide_os = 'WINDOWS' if IS_WINDOWS else 'UNIX' + +_normcase_from_client = normcase + + +def normcase_from_client(s): + return _normcase_from_client(s) + + +DEBUG_CLIENT_SERVER_TRANSLATION = os.environ.get('DEBUG_PYDEVD_PATHS_TRANSLATION', 'False').lower() in ('1', 'true') + + +def set_ide_os(os): + ''' + We need to set the IDE os because the host where the code is running may be + actually different from the client (and the point is that we want the proper + paths to translate from the client to the server). + + :param os: + 'UNIX' or 'WINDOWS' + ''' + global _ide_os + global _normcase_from_client + prev = _ide_os + if os == 'WIN': # Apparently PyCharm uses 'WIN' (https://github.com/fabioz/PyDev.Debugger/issues/116) + os = 'WINDOWS' + + assert os in ('WINDOWS', 'UNIX') + + if DEBUG_CLIENT_SERVER_TRANSLATION: + print('pydev debugger: client OS: %s' % (os,)) + + _normcase_from_client = normcase + if os == 'WINDOWS': + + # Client in Windows and server in Unix, we need to normalize the case. + if not IS_WINDOWS: + _normcase_from_client = _normcase_windows + + else: + # Client in Unix and server in Windows, we can't normalize the case. + if IS_WINDOWS: + _normcase_from_client = _normcase_linux + + if prev != os: + _ide_os = os + # We need to (re)setup how the client <-> server translation works to provide proper separators. + setup_client_server_paths(_last_client_server_paths_set) + + +# Caches filled as requested during the debug session. +NORM_PATHS_CONTAINER = {} +NORM_PATHS_AND_BASE_CONTAINER = {} + + +def canonical_normalized_path(filename): + ''' + This returns a filename that is canonical and it's meant to be used internally + to store information on breakpoints and see if there's any hit on it. + + Note that this version is only internal as it may not match the case and + may have symlinks resolved (and thus may not match what the user expects + in the editor). + ''' + return get_abs_path_real_path_and_base_from_file(filename)[1] + + +def absolute_path(filename): + ''' + Provides a version of the filename that's absolute (and NOT normalized). + ''' + return get_abs_path_real_path_and_base_from_file(filename)[0] + + +def basename(filename): + ''' + Provides the basename for a file. + ''' + return get_abs_path_real_path_and_base_from_file(filename)[2] + + +# Returns tuple of absolute path and real path for given filename +def _abs_and_canonical_path(filename, NORM_PATHS_CONTAINER=NORM_PATHS_CONTAINER): + try: + return NORM_PATHS_CONTAINER[filename] + except: + if filename.__class__ != str: + raise AssertionError('Paths passed to _abs_and_canonical_path must be str. Found: %s (%s)' % (filename, type(filename))) + if os is None: # Interpreter shutdown + return filename, filename + + os_path = os.path + if os_path is None: # Interpreter shutdown + return filename, filename + + os_path_abspath = os_path.abspath + os_path_isabs = os_path.isabs + + if os_path_abspath is None or os_path_isabs is None or os_path_real_path is None: # Interpreter shutdown + return filename, filename + + isabs = os_path_isabs(filename) + + if _global_resolve_symlinks: + os_path_abspath = os_path_real_path + + normalize = False + abs_path = _apply_func_and_normalize_case(filename, os_path_abspath, isabs, normalize) + + normalize = True + real_path = _apply_func_and_normalize_case(filename, os_path_real_path, isabs, normalize) + + # cache it for fast access later + NORM_PATHS_CONTAINER[filename] = abs_path, real_path + return abs_path, real_path + + +def _get_relative_filename_abs_path(filename, func, os_path_exists=os_path_exists): + # If we have a relative path and the file does not exist when made absolute, try to + # resolve it based on the sys.path entries. + for p in sys.path: + r = func(os.path.join(p, filename)) + if os_path_exists(r): + return r + + # We couldn't find the real file for the relative path. Resolve it as if it was in + # a library (so that it's considered a library file and not a project file). + r = func(os.path.join(_library_dir, filename)) + return r + + +def _apply_func_and_normalize_case(filename, func, isabs, normalize_case, os_path_exists=os_path_exists, join=join): + if filename.startswith('<'): + # Not really a file, rather a synthetic name like or ; + # shouldn't be normalized. + return filename + + r = func(filename) + + if not isabs: + if not os_path_exists(r): + r = _get_relative_filename_abs_path(filename, func) + + ind = r.find('.zip') + if ind == -1: + ind = r.find('.egg') + if ind != -1: + ind += 4 + zip_path = r[:ind] + inner_path = r[ind:] + if inner_path.startswith('!'): + # Note (fabioz): although I can replicate this by creating a file ending as + # .zip! or .egg!, I don't really know what's the real-world case for this + # (still kept as it was added by @jetbrains, but it should probably be reviewed + # later on). + # Note 2: it goes hand-in-hand with 'exists'. + inner_path = inner_path[1:] + zip_path = zip_path + '!' + + if inner_path.startswith('/') or inner_path.startswith('\\'): + inner_path = inner_path[1:] + if inner_path: + if normalize_case: + r = join(normcase(zip_path), inner_path) + else: + r = join(zip_path, inner_path) + return r + + if normalize_case: + r = normcase(r) + return r + + +_ZIP_SEARCH_CACHE = {} +_NOT_FOUND_SENTINEL = object() + + +def exists(filename): + if os_path_exists(filename): + return True + + if not os.path.isabs(filename): + filename = _get_relative_filename_abs_path(filename, os.path.abspath) + if os_path_exists(filename): + return True + + ind = filename.find('.zip') + if ind == -1: + ind = filename.find('.egg') + + if ind != -1: + ind += 4 + zip_path = filename[:ind] + inner_path = filename[ind:] + if inner_path.startswith("!"): + # Note (fabioz): although I can replicate this by creating a file ending as + # .zip! or .egg!, I don't really know what's the real-world case for this + # (still kept as it was added by @jetbrains, but it should probably be reviewed + # later on). + # Note 2: it goes hand-in-hand with '_apply_func_and_normalize_case'. + inner_path = inner_path[1:] + zip_path = zip_path + '!' + + zip_file_obj = _ZIP_SEARCH_CACHE.get(zip_path, _NOT_FOUND_SENTINEL) + if zip_file_obj is None: + return False + elif zip_file_obj is _NOT_FOUND_SENTINEL: + try: + import zipfile + zip_file_obj = zipfile.ZipFile(zip_path, 'r') + _ZIP_SEARCH_CACHE[zip_path] = zip_file_obj + except: + _ZIP_SEARCH_CACHE[zip_path] = _NOT_FOUND_SENTINEL + return False + + try: + if inner_path.startswith('/') or inner_path.startswith('\\'): + inner_path = inner_path[1:] + + _info = zip_file_obj.getinfo(inner_path.replace('\\', '/')) + + return join(zip_path, inner_path) + except KeyError: + return False + + else: + pydev_log.debug('os.path.exists(%r) returned False.', filename) + + return False + + +try: + report = pydev_log.critical + if DISABLE_FILE_VALIDATION: + report = pydev_log.debug + + try: + code = os_path_real_path.func_code + except AttributeError: + code = os_path_real_path.__code__ + + if code.co_filename.startswith(' in this case). + f = '' + + if f.startswith('<'): + return f, normcase(f), f + + if _abs_and_canonical_path is None: # Interpreter shutdown + i = max(f.rfind('/'), f.rfind('\\')) + return (f, f, f[i + 1:]) + + if f is not None: + if f.endswith('.pyc'): + f = f[:-1] + elif f.endswith('$py.class'): + f = f[:-len('$py.class')] + '.py' + + abs_path, canonical_normalized_filename = _abs_and_canonical_path(f) + + try: + base = os_path_basename(canonical_normalized_filename) + except AttributeError: + # Error during shutdown. + i = max(f.rfind('/'), f.rfind('\\')) + base = f[i + 1:] + ret = abs_path, canonical_normalized_filename, base + NORM_PATHS_AND_BASE_CONTAINER[filename] = ret + return ret + + +def get_abs_path_real_path_and_base_from_frame(frame, NORM_PATHS_AND_BASE_CONTAINER=NORM_PATHS_AND_BASE_CONTAINER): + try: + return NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] + except: + # This one is just internal (so, does not need any kind of client-server translation) + f = frame.f_code.co_filename + + if f is not None and f.startswith (('build/bdist.', 'build\\bdist.')): + # files from eggs in Python 2.7 have paths like build/bdist.linux-x86_64/egg/ + f = frame.f_globals['__file__'] + + if get_abs_path_real_path_and_base_from_file is None: + # Interpreter shutdown + if not f: + # i.e.: it's possible that the user compiled code with an empty string (consider + # it as in this case). + f = '' + i = max(f.rfind('/'), f.rfind('\\')) + return f, f, f[i + 1:] + + ret = get_abs_path_real_path_and_base_from_file(f) + # Also cache based on the frame.f_code.co_filename (if we had it inside build/bdist it can make a difference). + NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] = ret + return ret + + +def get_fullname(mod_name): + import pkgutil + try: + loader = pkgutil.get_loader(mod_name) + except: + return None + if loader is not None: + for attr in ("get_filename", "_get_filename"): + meth = getattr(loader, attr, None) + if meth is not None: + return meth(mod_name) + return None + + +def get_package_dir(mod_name): + for path in sys.path: + mod_path = join(path, mod_name.replace('.', '/')) + if os.path.isdir(mod_path): + return mod_path + return None + diff --git a/pydevd_plugins/__init__.py b/pydevd_plugins/__init__.py new file mode 100644 index 0000000..f471804 --- /dev/null +++ b/pydevd_plugins/__init__.py @@ -0,0 +1,8 @@ +import warnings +with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + try: + __import__('pkg_resources').declare_namespace(__name__) + except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/pydevd_plugins/django_debug.py b/pydevd_plugins/django_debug.py new file mode 100644 index 0000000..ff7f1eb --- /dev/null +++ b/pydevd_plugins/django_debug.py @@ -0,0 +1,613 @@ +import inspect + +from _pydev_bundle import pydev_log +from _pydevd_bundle.pydevd_comm import CMD_SET_BREAK, CMD_ADD_EXCEPTION_BREAK +from _pydevd_bundle.pydevd_constants import STATE_SUSPEND, DJANGO_SUSPEND, \ + DebugInfoHolder +from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, FCode, just_raised, ignore_exception_trace +from pydevd_file_utils import canonical_normalized_path, absolute_path +from _pydevd_bundle.pydevd_api import PyDevdAPI +from pydevd_plugins.pydevd_line_validation import LineBreakpointWithLazyValidation, ValidationInfo +from _pydev_bundle.pydev_override import overrides + +IS_DJANGO18 = False +IS_DJANGO19 = False +IS_DJANGO19_OR_HIGHER = False +try: + import django + version = django.VERSION + IS_DJANGO18 = version[0] == 1 and version[1] == 8 + IS_DJANGO19 = version[0] == 1 and version[1] == 9 + IS_DJANGO19_OR_HIGHER = ((version[0] == 1 and version[1] >= 9) or version[0] > 1) +except: + pass + + +class DjangoLineBreakpoint(LineBreakpointWithLazyValidation): + + def __init__(self, canonical_normalized_filename, breakpoint_id, line, condition, func_name, expression, hit_condition=None, is_logpoint=False): + self.canonical_normalized_filename = canonical_normalized_filename + LineBreakpointWithLazyValidation.__init__(self, breakpoint_id, line, condition, func_name, expression, hit_condition=hit_condition, is_logpoint=is_logpoint) + + def __str__(self): + return "DjangoLineBreakpoint: %s-%d" % (self.canonical_normalized_filename, self.line) + + +class _DjangoValidationInfo(ValidationInfo): + + @overrides(ValidationInfo._collect_valid_lines_in_template_uncached) + def _collect_valid_lines_in_template_uncached(self, template): + lines = set() + for node in self._iternodes(template.nodelist): + if node.__class__.__name__ in _IGNORE_RENDER_OF_CLASSES: + continue + lineno = self._get_lineno(node) + if lineno is not None: + lines.add(lineno) + return lines + + def _get_lineno(self, node): + if hasattr(node, 'token') and hasattr(node.token, 'lineno'): + return node.token.lineno + return None + + def _iternodes(self, nodelist): + for node in nodelist: + yield node + + try: + children = node.child_nodelists + except: + pass + else: + for attr in children: + nodelist = getattr(node, attr, None) + if nodelist: + # i.e.: yield from _iternodes(nodelist) + for node in self._iternodes(nodelist): + yield node + + +def add_line_breakpoint(plugin, pydb, type, canonical_normalized_filename, breakpoint_id, line, condition, expression, func_name, hit_condition=None, is_logpoint=False, add_breakpoint_result=None, on_changed_breakpoint_state=None): + if type == 'django-line': + django_line_breakpoint = DjangoLineBreakpoint(canonical_normalized_filename, breakpoint_id, line, condition, func_name, expression, hit_condition=hit_condition, is_logpoint=is_logpoint) + if not hasattr(pydb, 'django_breakpoints'): + _init_plugin_breaks(pydb) + + if IS_DJANGO19_OR_HIGHER: + add_breakpoint_result.error_code = PyDevdAPI.ADD_BREAKPOINT_LAZY_VALIDATION + django_line_breakpoint.add_breakpoint_result = add_breakpoint_result + django_line_breakpoint.on_changed_breakpoint_state = on_changed_breakpoint_state + else: + add_breakpoint_result.error_code = PyDevdAPI.ADD_BREAKPOINT_NO_ERROR + + return django_line_breakpoint, pydb.django_breakpoints + return None + + +def after_breakpoints_consolidated(plugin, py_db, canonical_normalized_filename, id_to_pybreakpoint, file_to_line_to_breakpoints): + if IS_DJANGO19_OR_HIGHER: + django_breakpoints_for_file = file_to_line_to_breakpoints.get(canonical_normalized_filename) + if not django_breakpoints_for_file: + return + + if not hasattr(py_db, 'django_validation_info'): + _init_plugin_breaks(py_db) + + # In general we validate the breakpoints only when the template is loaded, but if the template + # was already loaded, we can validate the breakpoints based on the last loaded value. + py_db.django_validation_info.verify_breakpoints_from_template_cached_lines( + py_db, canonical_normalized_filename, django_breakpoints_for_file) + + +def add_exception_breakpoint(plugin, pydb, type, exception): + if type == 'django': + if not hasattr(pydb, 'django_exception_break'): + _init_plugin_breaks(pydb) + pydb.django_exception_break[exception] = True + return True + return False + + +def _init_plugin_breaks(pydb): + pydb.django_exception_break = {} + pydb.django_breakpoints = {} + + pydb.django_validation_info = _DjangoValidationInfo() + + +def remove_exception_breakpoint(plugin, pydb, type, exception): + if type == 'django': + try: + del pydb.django_exception_break[exception] + return True + except: + pass + return False + + +def remove_all_exception_breakpoints(plugin, pydb): + if hasattr(pydb, 'django_exception_break'): + pydb.django_exception_break = {} + return True + return False + + +def get_breakpoints(plugin, pydb, type): + if type == 'django-line': + return pydb.django_breakpoints + return None + + +def _inherits(cls, *names): + if cls.__name__ in names: + return True + inherits_node = False + for base in inspect.getmro(cls): + if base.__name__ in names: + inherits_node = True + break + return inherits_node + + +_IGNORE_RENDER_OF_CLASSES = ('TextNode', 'NodeList') + + +def _is_django_render_call(frame, debug=False): + try: + name = frame.f_code.co_name + if name != 'render': + return False + + if 'self' not in frame.f_locals: + return False + + cls = frame.f_locals['self'].__class__ + + inherits_node = _inherits(cls, 'Node') + + if not inherits_node: + return False + + clsname = cls.__name__ + if IS_DJANGO19: + # in Django 1.9 we need to save the flag that there is included template + if clsname == 'IncludeNode': + if 'context' in frame.f_locals: + context = frame.f_locals['context'] + context._has_included_template = True + + return clsname not in _IGNORE_RENDER_OF_CLASSES + except: + pydev_log.exception() + return False + + +def _is_django_context_get_call(frame): + try: + if 'self' not in frame.f_locals: + return False + + cls = frame.f_locals['self'].__class__ + + return _inherits(cls, 'BaseContext') + except: + pydev_log.exception() + return False + + +def _is_django_resolve_call(frame): + try: + name = frame.f_code.co_name + if name != '_resolve_lookup': + return False + + if 'self' not in frame.f_locals: + return False + + cls = frame.f_locals['self'].__class__ + + clsname = cls.__name__ + return clsname == 'Variable' + except: + pydev_log.exception() + return False + + +def _is_django_suspended(thread): + return thread.additional_info.suspend_type == DJANGO_SUSPEND + + +def suspend_django(main_debugger, thread, frame, cmd=CMD_SET_BREAK): + if frame.f_lineno is None: + return None + + main_debugger.set_suspend(thread, cmd) + thread.additional_info.suspend_type = DJANGO_SUSPEND + + return frame + + +def _find_django_render_frame(frame): + while frame is not None and not _is_django_render_call(frame): + frame = frame.f_back + + return frame + +#======================================================================================================================= +# Django Frame +#======================================================================================================================= + + +def _read_file(filename): + # type: (str) -> str + f = open(filename, 'r', encoding='utf-8', errors='replace') + s = f.read() + f.close() + return s + + +def _offset_to_line_number(text, offset): + curLine = 1 + curOffset = 0 + while curOffset < offset: + if curOffset == len(text): + return -1 + c = text[curOffset] + if c == '\n': + curLine += 1 + elif c == '\r': + curLine += 1 + if curOffset < len(text) and text[curOffset + 1] == '\n': + curOffset += 1 + + curOffset += 1 + + return curLine + + +def _get_source_django_18_or_lower(frame): + # This method is usable only for the Django <= 1.8 + try: + node = frame.f_locals['self'] + if hasattr(node, 'source'): + return node.source + else: + if IS_DJANGO18: + # The debug setting was changed since Django 1.8 + pydev_log.error_once("WARNING: Template path is not available. Set the 'debug' option in the OPTIONS of a DjangoTemplates " + "backend.") + else: + # The debug setting for Django < 1.8 + pydev_log.error_once("WARNING: Template path is not available. Please set TEMPLATE_DEBUG=True in your settings.py to make " + "django template breakpoints working") + return None + + except: + pydev_log.exception() + return None + + +def _convert_to_str(s): + return s + + +def _get_template_original_file_name_from_frame(frame): + try: + if IS_DJANGO19: + # The Node source was removed since Django 1.9 + if 'context' in frame.f_locals: + context = frame.f_locals['context'] + if hasattr(context, '_has_included_template'): + # if there was included template we need to inspect the previous frames and find its name + back = frame.f_back + while back is not None and frame.f_code.co_name in ('render', '_render'): + locals = back.f_locals + if 'self' in locals: + self = locals['self'] + if self.__class__.__name__ == 'Template' and hasattr(self, 'origin') and \ + hasattr(self.origin, 'name'): + return _convert_to_str(self.origin.name) + back = back.f_back + else: + if hasattr(context, 'template') and hasattr(context.template, 'origin') and \ + hasattr(context.template.origin, 'name'): + return _convert_to_str(context.template.origin.name) + return None + elif IS_DJANGO19_OR_HIGHER: + # For Django 1.10 and later there is much simpler way to get template name + if 'self' in frame.f_locals: + self = frame.f_locals['self'] + if hasattr(self, 'origin') and hasattr(self.origin, 'name'): + return _convert_to_str(self.origin.name) + return None + + source = _get_source_django_18_or_lower(frame) + if source is None: + pydev_log.debug("Source is None\n") + return None + fname = _convert_to_str(source[0].name) + + if fname == '': + pydev_log.debug("Source name is %s\n" % fname) + return None + else: + return fname + except: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 2: + pydev_log.exception('Error getting django template filename.') + return None + + +def _get_template_line(frame): + if IS_DJANGO19_OR_HIGHER: + node = frame.f_locals['self'] + if hasattr(node, 'token') and hasattr(node.token, 'lineno'): + return node.token.lineno + else: + return None + + source = _get_source_django_18_or_lower(frame) + original_filename = _get_template_original_file_name_from_frame(frame) + if original_filename is not None: + try: + absolute_filename = absolute_path(original_filename) + return _offset_to_line_number(_read_file(absolute_filename), source[1][0]) + except: + return None + return None + + +class DjangoTemplateFrame(object): + + IS_PLUGIN_FRAME = True + + def __init__(self, frame): + original_filename = _get_template_original_file_name_from_frame(frame) + self._back_context = frame.f_locals['context'] + self.f_code = FCode('Django Template', original_filename) + self.f_lineno = _get_template_line(frame) + self.f_back = frame + self.f_globals = {} + self.f_locals = self._collect_context(self._back_context) + self.f_trace = None + + def _collect_context(self, context): + res = {} + try: + for d in context.dicts: + for k, v in d.items(): + res[k] = v + except AttributeError: + pass + return res + + def _change_variable(self, name, value): + for d in self._back_context.dicts: + for k, v in d.items(): + if k == name: + d[k] = value + + +class DjangoTemplateSyntaxErrorFrame(object): + + IS_PLUGIN_FRAME = True + + def __init__(self, frame, original_filename, lineno, f_locals): + self.f_code = FCode('Django TemplateSyntaxError', original_filename) + self.f_lineno = lineno + self.f_back = frame + self.f_globals = {} + self.f_locals = f_locals + self.f_trace = None + + +def change_variable(plugin, frame, attr, expression): + if isinstance(frame, DjangoTemplateFrame): + result = eval(expression, frame.f_globals, frame.f_locals) + frame._change_variable(attr, result) + return result + return False + + +def _is_django_variable_does_not_exist_exception_break_context(frame): + try: + name = frame.f_code.co_name + except: + name = None + return name in ('_resolve_lookup', 'find_template') + + +def _is_ignoring_failures(frame): + while frame is not None: + if frame.f_code.co_name == 'resolve': + ignore_failures = frame.f_locals.get('ignore_failures') + if ignore_failures: + return True + frame = frame.f_back + + return False + +#======================================================================================================================= +# Django Step Commands +#======================================================================================================================= + + +def can_skip(plugin, main_debugger, frame): + if main_debugger.django_breakpoints: + if _is_django_render_call(frame): + return False + + if main_debugger.django_exception_break: + module_name = frame.f_globals.get('__name__', '') + + if module_name == 'django.template.base': + # Exceptions raised at django.template.base must be checked. + return False + + return True + + +def has_exception_breaks(plugin): + if len(plugin.main_debugger.django_exception_break) > 0: + return True + return False + + +def has_line_breaks(plugin): + for _canonical_normalized_filename, breakpoints in plugin.main_debugger.django_breakpoints.items(): + if len(breakpoints) > 0: + return True + return False + + +def cmd_step_into(plugin, main_debugger, frame, event, args, stop_info, stop): + info = args[2] + thread = args[3] + plugin_stop = False + if _is_django_suspended(thread): + stop_info['django_stop'] = event == 'call' and _is_django_render_call(frame) + plugin_stop = stop_info['django_stop'] + stop = stop and _is_django_resolve_call(frame.f_back) and not _is_django_context_get_call(frame) + if stop: + info.pydev_django_resolve_frame = True # we remember that we've go into python code from django rendering frame + return stop, plugin_stop + + +def cmd_step_over(plugin, main_debugger, frame, event, args, stop_info, stop): + info = args[2] + thread = args[3] + plugin_stop = False + if _is_django_suspended(thread): + stop_info['django_stop'] = event == 'call' and _is_django_render_call(frame) + plugin_stop = stop_info['django_stop'] + stop = False + return stop, plugin_stop + else: + if event == 'return' and info.pydev_django_resolve_frame and _is_django_resolve_call(frame.f_back): + # we return to Django suspend mode and should not stop before django rendering frame + info.pydev_step_stop = frame.f_back + info.pydev_django_resolve_frame = False + thread.additional_info.suspend_type = DJANGO_SUSPEND + stop = info.pydev_step_stop is frame and event in ('line', 'return') + return stop, plugin_stop + + +def stop(plugin, main_debugger, frame, event, args, stop_info, arg, step_cmd): + main_debugger = args[0] + thread = args[3] + if 'django_stop' in stop_info and stop_info['django_stop']: + frame = suspend_django(main_debugger, thread, DjangoTemplateFrame(frame), step_cmd) + if frame: + main_debugger.do_wait_suspend(thread, frame, event, arg) + return True + return False + + +def get_breakpoint(plugin, py_db, pydb_frame, frame, event, args): + py_db = args[0] + _filename = args[1] + info = args[2] + breakpoint_type = 'django' + + if event == 'call' and info.pydev_state != STATE_SUSPEND and py_db.django_breakpoints and _is_django_render_call(frame): + original_filename = _get_template_original_file_name_from_frame(frame) + pydev_log.debug("Django is rendering a template: %s", original_filename) + + canonical_normalized_filename = canonical_normalized_path(original_filename) + django_breakpoints_for_file = py_db.django_breakpoints.get(canonical_normalized_filename) + + if django_breakpoints_for_file: + + # At this point, let's validate whether template lines are correct. + if IS_DJANGO19_OR_HIGHER: + django_validation_info = py_db.django_validation_info + context = frame.f_locals['context'] + django_template = context.template + django_validation_info.verify_breakpoints(py_db, canonical_normalized_filename, django_breakpoints_for_file, django_template) + + pydev_log.debug("Breakpoints for that file: %s", django_breakpoints_for_file) + template_line = _get_template_line(frame) + pydev_log.debug("Tracing template line: %s", template_line) + + if template_line in django_breakpoints_for_file: + django_breakpoint = django_breakpoints_for_file[template_line] + new_frame = DjangoTemplateFrame(frame) + return True, django_breakpoint, new_frame, breakpoint_type + + return False, None, None, breakpoint_type + + +def suspend(plugin, main_debugger, thread, frame, bp_type): + if bp_type == 'django': + return suspend_django(main_debugger, thread, DjangoTemplateFrame(frame)) + return None + + +def _get_original_filename_from_origin_in_parent_frame_locals(frame, parent_frame_name): + filename = None + parent_frame = frame + while parent_frame.f_code.co_name != parent_frame_name: + parent_frame = parent_frame.f_back + + origin = None + if parent_frame is not None: + origin = parent_frame.f_locals.get('origin') + + if hasattr(origin, 'name') and origin.name is not None: + filename = _convert_to_str(origin.name) + return filename + + +def exception_break(plugin, main_debugger, pydb_frame, frame, args, arg): + main_debugger = args[0] + thread = args[3] + exception, value, trace = arg + + if main_debugger.django_exception_break and exception is not None: + if exception.__name__ in ['VariableDoesNotExist', 'TemplateDoesNotExist', 'TemplateSyntaxError'] and \ + just_raised(trace) and not ignore_exception_trace(trace): + + if exception.__name__ == 'TemplateSyntaxError': + # In this case we don't actually have a regular render frame with the context + # (we didn't really get to that point). + token = getattr(value, 'token', None) + + if token is None: + # Django 1.7 does not have token in exception. Try to get it from locals. + token = frame.f_locals.get('token') + + lineno = getattr(token, 'lineno', None) + + original_filename = None + if lineno is not None: + original_filename = _get_original_filename_from_origin_in_parent_frame_locals(frame, 'get_template') + + if original_filename is None: + # Django 1.7 does not have origin in get_template. Try to get it from + # load_template. + original_filename = _get_original_filename_from_origin_in_parent_frame_locals(frame, 'load_template') + + if original_filename is not None and lineno is not None: + syntax_error_frame = DjangoTemplateSyntaxErrorFrame( + frame, original_filename, lineno, {'token': token, 'exception': exception}) + + suspend_frame = suspend_django( + main_debugger, thread, syntax_error_frame, CMD_ADD_EXCEPTION_BREAK) + return True, suspend_frame + + elif exception.__name__ == 'VariableDoesNotExist': + if _is_django_variable_does_not_exist_exception_break_context(frame): + if not getattr(exception, 'silent_variable_failure', False) and not _is_ignoring_failures(frame): + render_frame = _find_django_render_frame(frame) + if render_frame: + suspend_frame = suspend_django( + main_debugger, thread, DjangoTemplateFrame(render_frame), CMD_ADD_EXCEPTION_BREAK) + if suspend_frame: + add_exception_to_frame(suspend_frame, (exception, value, trace)) + thread.additional_info.pydev_message = 'VariableDoesNotExist' + suspend_frame.f_back = frame + frame = suspend_frame + return True, frame + + return None diff --git a/pydevd_plugins/extensions/README.md b/pydevd_plugins/extensions/README.md new file mode 100644 index 0000000..030e303 --- /dev/null +++ b/pydevd_plugins/extensions/README.md @@ -0,0 +1,30 @@ +Extensions allow extending the debugger without modifying the debugger code. This is implemented with explicit namespace +packages. + +To implement your own extension: + +1. Ensure that the root folder of your extension is in sys.path (add it to PYTHONPATH) +2. Ensure that your module follows the directory structure below +3. The ``__init__.py`` files inside the pydevd_plugin and extension folder must contain the preamble below, +and nothing else. +Preamble: +```python +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) +``` +4. Your plugin name inside the extensions folder must start with `"pydevd_plugin"` +5. Implement one or more of the abstract base classes defined in `_pydevd_bundle.pydevd_extension_api`. This can be done +by either inheriting from them or registering with the abstract base class. + +* Directory structure: +``` +|-- root_directory-> must be on python path +| |-- pydevd_plugins +| | |-- __init__.py -> must contain preamble +| | |-- extensions +| | | |-- __init__.py -> must contain preamble +| | | |-- pydevd_plugin_plugin_name.py +``` \ No newline at end of file diff --git a/pydevd_plugins/extensions/__init__.py b/pydevd_plugins/extensions/__init__.py new file mode 100644 index 0000000..274d7bc --- /dev/null +++ b/pydevd_plugins/extensions/__init__.py @@ -0,0 +1,7 @@ +import warnings +with warnings.catch_warnings(): + try: + __import__('pkg_resources').declare_namespace(__name__) + except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/pydevd_plugins/extensions/types/__init__.py b/pydevd_plugins/extensions/types/__init__.py new file mode 100644 index 0000000..274d7bc --- /dev/null +++ b/pydevd_plugins/extensions/types/__init__.py @@ -0,0 +1,7 @@ +import warnings +with warnings.catch_warnings(): + try: + __import__('pkg_resources').declare_namespace(__name__) + except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/pydevd_plugins/extensions/types/pydevd_helpers.py b/pydevd_plugins/extensions/types/pydevd_helpers.py new file mode 100644 index 0000000..7c5a4fe --- /dev/null +++ b/pydevd_plugins/extensions/types/pydevd_helpers.py @@ -0,0 +1,26 @@ +import sys + + +def find_cached_module(mod_name): + return sys.modules.get(mod_name, None) + +def find_mod_attr(mod_name, attr): + mod = find_cached_module(mod_name) + if mod is None: + return None + return getattr(mod, attr, None) + + +def find_class_name(val): + class_name = str(val.__class__) + if class_name.find('.') != -1: + class_name = class_name.split('.')[-1] + + elif class_name.find("'") != -1: #does not have '.' (could be something like ) + class_name = class_name[class_name.index("'") + 1:] + + if class_name.endswith("'>"): + class_name = class_name[:-2] + + return class_name + diff --git a/pydevd_plugins/extensions/types/pydevd_plugin_numpy_types.py b/pydevd_plugins/extensions/types/pydevd_plugin_numpy_types.py new file mode 100644 index 0000000..1e3e6e9 --- /dev/null +++ b/pydevd_plugins/extensions/types/pydevd_plugin_numpy_types.py @@ -0,0 +1,86 @@ +from _pydevd_bundle.pydevd_extension_api import TypeResolveProvider +from _pydevd_bundle.pydevd_resolver import defaultResolver, MAX_ITEMS_TO_HANDLE, TOO_LARGE_ATTR, TOO_LARGE_MSG +from .pydevd_helpers import find_mod_attr + + +class NdArrayItemsContainer(object): + pass + + +class NDArrayTypeResolveProvider(object): + ''' + This resolves a numpy ndarray returning some metadata about the NDArray + ''' + + def can_provide(self, type_object, type_name): + nd_array = find_mod_attr('numpy', 'ndarray') + return nd_array is not None and issubclass(type_object, nd_array) + + def is_numeric(self, obj): + if not hasattr(obj, 'dtype'): + return False + return obj.dtype.kind in 'biufc' + + def resolve(self, obj, attribute): + if attribute == '__internals__': + return defaultResolver.get_dictionary(obj) + if attribute == 'min': + if self.is_numeric(obj) and obj.size > 0: + return obj.min() + else: + return None + if attribute == 'max': + if self.is_numeric(obj) and obj.size > 0: + return obj.max() + else: + return None + if attribute == 'shape': + return obj.shape + if attribute == 'dtype': + return obj.dtype + if attribute == 'size': + return obj.size + if attribute.startswith('['): + container = NdArrayItemsContainer() + i = 0 + format_str = '%0' + str(int(len(str(len(obj))))) + 'd' + for item in obj: + setattr(container, format_str % i, item) + i += 1 + if i > MAX_ITEMS_TO_HANDLE: + setattr(container, TOO_LARGE_ATTR, TOO_LARGE_MSG) + break + return container + return None + + def get_dictionary(self, obj): + ret = dict() + ret['__internals__'] = defaultResolver.get_dictionary(obj) + if obj.size > 1024 * 1024: + ret['min'] = 'ndarray too big, calculating min would slow down debugging' + ret['max'] = 'ndarray too big, calculating max would slow down debugging' + elif obj.size == 0: + ret['min'] = 'array is empty' + ret['max'] = 'array is empty' + else: + if self.is_numeric(obj): + ret['min'] = obj.min() + ret['max'] = obj.max() + else: + ret['min'] = 'not a numeric object' + ret['max'] = 'not a numeric object' + ret['shape'] = obj.shape + ret['dtype'] = obj.dtype + ret['size'] = obj.size + try: + ret['[0:%s] ' % (len(obj))] = list(obj[0:MAX_ITEMS_TO_HANDLE]) + except: + # This may not work depending on the array shape. + pass + return ret + + +import sys + +if not sys.platform.startswith("java"): + TypeResolveProvider.register(NDArrayTypeResolveProvider) diff --git a/pydevd_plugins/extensions/types/pydevd_plugin_pandas_types.py b/pydevd_plugins/extensions/types/pydevd_plugin_pandas_types.py new file mode 100644 index 0000000..2c1090c --- /dev/null +++ b/pydevd_plugins/extensions/types/pydevd_plugin_pandas_types.py @@ -0,0 +1,160 @@ +import sys + +from _pydevd_bundle.pydevd_constants import PANDAS_MAX_ROWS, PANDAS_MAX_COLS, PANDAS_MAX_COLWIDTH +from _pydevd_bundle.pydevd_extension_api import TypeResolveProvider, StrPresentationProvider +from _pydevd_bundle.pydevd_resolver import inspect, MethodWrapperType +from _pydevd_bundle.pydevd_utils import Timer + +from .pydevd_helpers import find_mod_attr +from contextlib import contextmanager + + +def _get_dictionary(obj, replacements): + ret = dict() + cls = obj.__class__ + for attr_name in dir(obj): + + # This is interesting but it actually hides too much info from the dataframe. + # attr_type_in_cls = type(getattr(cls, attr_name, None)) + # if attr_type_in_cls == property: + # ret[attr_name] = '' + # continue + + timer = Timer() + try: + replacement = replacements.get(attr_name) + if replacement is not None: + ret[attr_name] = replacement + continue + + attr_value = getattr(obj, attr_name, '') + if inspect.isroutine(attr_value) or isinstance(attr_value, MethodWrapperType): + continue + ret[attr_name] = attr_value + except Exception as e: + ret[attr_name] = '' % (e,) + finally: + timer.report_if_getting_attr_slow(cls, attr_name) + + return ret + + +@contextmanager +def customize_pandas_options(): + # The default repr depends on the settings of: + # + # pandas.set_option('display.max_columns', None) + # pandas.set_option('display.max_rows', None) + # + # which can make the repr **very** slow on some cases, so, we customize pandas to have + # smaller values if the current values are too big. + custom_options = [] + + from pandas import get_option + + max_rows = get_option("display.max_rows") + max_cols = get_option("display.max_columns") + max_colwidth = get_option("display.max_colwidth") + + if max_rows is None or max_rows > PANDAS_MAX_ROWS: + custom_options.append("display.max_rows") + custom_options.append(PANDAS_MAX_ROWS) + + if max_cols is None or max_cols > PANDAS_MAX_COLS: + custom_options.append("display.max_columns") + custom_options.append(PANDAS_MAX_COLS) + + if max_colwidth is None or max_colwidth > PANDAS_MAX_COLWIDTH: + custom_options.append("display.max_colwidth") + custom_options.append(PANDAS_MAX_COLWIDTH) + + if custom_options: + from pandas import option_context + with option_context(*custom_options): + yield + else: + yield + + +class PandasDataFrameTypeResolveProvider(object): + + def can_provide(self, type_object, type_name): + data_frame_class = find_mod_attr('pandas.core.frame', 'DataFrame') + return data_frame_class is not None and issubclass(type_object, data_frame_class) + + def resolve(self, obj, attribute): + return getattr(obj, attribute) + + def get_dictionary(self, obj): + replacements = { + # This actually calls: DataFrame.transpose(), which can be expensive, so, + # let's just add some string representation for it. + 'T': '', + + # This creates a whole new dict{index: Series) for each column. Doing a + # subsequent repr() from this dict can be very slow, so, don't return it. + '_series': '', + + 'style': '', + } + return _get_dictionary(obj, replacements) + + def get_str(self, df): + with customize_pandas_options(): + return repr(df) + + +class PandasSeriesTypeResolveProvider(object): + + def can_provide(self, type_object, type_name): + series_class = find_mod_attr('pandas.core.series', 'Series') + return series_class is not None and issubclass(type_object, series_class) + + def resolve(self, obj, attribute): + return getattr(obj, attribute) + + def get_dictionary(self, obj): + replacements = { + # This actually calls: DataFrame.transpose(), which can be expensive, so, + # let's just add some string representation for it. + 'T': '', + + # This creates a whole new dict{index: Series) for each column. Doing a + # subsequent repr() from this dict can be very slow, so, don't return it. + '_series': '', + + 'style': '', + } + return _get_dictionary(obj, replacements) + + def get_str(self, series): + with customize_pandas_options(): + return repr(series) + + +class PandasStylerTypeResolveProvider(object): + + def can_provide(self, type_object, type_name): + series_class = find_mod_attr('pandas.io.formats.style', 'Styler') + return series_class is not None and issubclass(type_object, series_class) + + def resolve(self, obj, attribute): + return getattr(obj, attribute) + + def get_dictionary(self, obj): + replacements = { + 'data': '', + + '__dict__': '', + } + return _get_dictionary(obj, replacements) + + +if not sys.platform.startswith("java"): + TypeResolveProvider.register(PandasDataFrameTypeResolveProvider) + StrPresentationProvider.register(PandasDataFrameTypeResolveProvider) + + TypeResolveProvider.register(PandasSeriesTypeResolveProvider) + StrPresentationProvider.register(PandasSeriesTypeResolveProvider) + + TypeResolveProvider.register(PandasStylerTypeResolveProvider) diff --git a/pydevd_plugins/extensions/types/pydevd_plugins_django_form_str.py b/pydevd_plugins/extensions/types/pydevd_plugins_django_form_str.py new file mode 100644 index 0000000..8d64095 --- /dev/null +++ b/pydevd_plugins/extensions/types/pydevd_plugins_django_form_str.py @@ -0,0 +1,16 @@ +from _pydevd_bundle.pydevd_extension_api import StrPresentationProvider +from .pydevd_helpers import find_mod_attr, find_class_name + + +class DjangoFormStr(object): + def can_provide(self, type_object, type_name): + form_class = find_mod_attr('django.forms', 'Form') + return form_class is not None and issubclass(type_object, form_class) + + def get_str(self, val): + return '%s: %r' % (find_class_name(val), val) + +import sys + +if not sys.platform.startswith("java"): + StrPresentationProvider.register(DjangoFormStr) diff --git a/pydevd_plugins/jinja2_debug.py b/pydevd_plugins/jinja2_debug.py new file mode 100644 index 0000000..a5e4a00 --- /dev/null +++ b/pydevd_plugins/jinja2_debug.py @@ -0,0 +1,506 @@ +from _pydevd_bundle.pydevd_constants import STATE_SUSPEND, JINJA2_SUSPEND +from _pydevd_bundle.pydevd_comm import CMD_SET_BREAK, CMD_ADD_EXCEPTION_BREAK +from pydevd_file_utils import canonical_normalized_path +from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, FCode +from _pydev_bundle import pydev_log +from pydevd_plugins.pydevd_line_validation import LineBreakpointWithLazyValidation, ValidationInfo +from _pydev_bundle.pydev_override import overrides +from _pydevd_bundle.pydevd_api import PyDevdAPI + + +class Jinja2LineBreakpoint(LineBreakpointWithLazyValidation): + + def __init__(self, canonical_normalized_filename, breakpoint_id, line, condition, func_name, expression, hit_condition=None, is_logpoint=False): + self.canonical_normalized_filename = canonical_normalized_filename + LineBreakpointWithLazyValidation.__init__(self, breakpoint_id, line, condition, func_name, expression, hit_condition=hit_condition, is_logpoint=is_logpoint) + + def __str__(self): + return "Jinja2LineBreakpoint: %s-%d" % (self.canonical_normalized_filename, self.line) + + +class _Jinja2ValidationInfo(ValidationInfo): + + @overrides(ValidationInfo._collect_valid_lines_in_template_uncached) + def _collect_valid_lines_in_template_uncached(self, template): + lineno_mapping = _get_frame_lineno_mapping(template) + if not lineno_mapping: + return set() + + return set(x[0] for x in lineno_mapping) + + +def add_line_breakpoint(plugin, pydb, type, canonical_normalized_filename, breakpoint_id, line, condition, expression, func_name, hit_condition=None, is_logpoint=False, add_breakpoint_result=None, on_changed_breakpoint_state=None): + if type == 'jinja2-line': + jinja2_line_breakpoint = Jinja2LineBreakpoint(canonical_normalized_filename, breakpoint_id, line, condition, func_name, expression, hit_condition=hit_condition, is_logpoint=is_logpoint) + if not hasattr(pydb, 'jinja2_breakpoints'): + _init_plugin_breaks(pydb) + + add_breakpoint_result.error_code = PyDevdAPI.ADD_BREAKPOINT_LAZY_VALIDATION + jinja2_line_breakpoint.add_breakpoint_result = add_breakpoint_result + jinja2_line_breakpoint.on_changed_breakpoint_state = on_changed_breakpoint_state + + return jinja2_line_breakpoint, pydb.jinja2_breakpoints + return None + + +def after_breakpoints_consolidated(plugin, py_db, canonical_normalized_filename, id_to_pybreakpoint, file_to_line_to_breakpoints): + jinja2_breakpoints_for_file = file_to_line_to_breakpoints.get(canonical_normalized_filename) + if not jinja2_breakpoints_for_file: + return + + if not hasattr(py_db, 'jinja2_validation_info'): + _init_plugin_breaks(py_db) + + # In general we validate the breakpoints only when the template is loaded, but if the template + # was already loaded, we can validate the breakpoints based on the last loaded value. + py_db.jinja2_validation_info.verify_breakpoints_from_template_cached_lines( + py_db, canonical_normalized_filename, jinja2_breakpoints_for_file) + + +def add_exception_breakpoint(plugin, pydb, type, exception): + if type == 'jinja2': + if not hasattr(pydb, 'jinja2_exception_break'): + _init_plugin_breaks(pydb) + pydb.jinja2_exception_break[exception] = True + return True + return False + + +def _init_plugin_breaks(pydb): + pydb.jinja2_exception_break = {} + pydb.jinja2_breakpoints = {} + + pydb.jinja2_validation_info = _Jinja2ValidationInfo() + + +def remove_all_exception_breakpoints(plugin, pydb): + if hasattr(pydb, 'jinja2_exception_break'): + pydb.jinja2_exception_break = {} + return True + return False + + +def remove_exception_breakpoint(plugin, pydb, type, exception): + if type == 'jinja2': + try: + del pydb.jinja2_exception_break[exception] + return True + except: + pass + return False + + +def get_breakpoints(plugin, pydb, type): + if type == 'jinja2-line': + return pydb.jinja2_breakpoints + return None + + +def _is_jinja2_render_call(frame): + try: + name = frame.f_code.co_name + if "__jinja_template__" in frame.f_globals and name in ("root", "loop", "macro") or name.startswith("block_"): + return True + return False + except: + pydev_log.exception() + return False + + +def _suspend_jinja2(pydb, thread, frame, cmd=CMD_SET_BREAK, message=None): + frame = Jinja2TemplateFrame(frame) + + if frame.f_lineno is None: + return None + + pydb.set_suspend(thread, cmd) + + thread.additional_info.suspend_type = JINJA2_SUSPEND + if cmd == CMD_ADD_EXCEPTION_BREAK: + # send exception name as message + if message: + message = str(message) + thread.additional_info.pydev_message = message + + return frame + + +def _is_jinja2_suspended(thread): + return thread.additional_info.suspend_type == JINJA2_SUSPEND + + +def _is_jinja2_context_call(frame): + return "_Context__obj" in frame.f_locals + + +def _is_jinja2_internal_function(frame): + return 'self' in frame.f_locals and frame.f_locals['self'].__class__.__name__ in \ + ('LoopContext', 'TemplateReference', 'Macro', 'BlockReference') + + +def _find_jinja2_render_frame(frame): + while frame is not None and not _is_jinja2_render_call(frame): + frame = frame.f_back + + return frame + +#======================================================================================================================= +# Jinja2 Frame +#======================================================================================================================= + + +class Jinja2TemplateFrame(object): + + IS_PLUGIN_FRAME = True + + def __init__(self, frame, original_filename=None, template_lineno=None): + + if original_filename is None: + original_filename = _get_jinja2_template_original_filename(frame) + + if template_lineno is None: + template_lineno = _get_jinja2_template_line(frame) + + self.back_context = None + if 'context' in frame.f_locals: + # sometimes we don't have 'context', e.g. in macros + self.back_context = frame.f_locals['context'] + self.f_code = FCode('template', original_filename) + self.f_lineno = template_lineno + self.f_back = frame + self.f_globals = {} + self.f_locals = self.collect_context(frame) + self.f_trace = None + + def _get_real_var_name(self, orig_name): + # replace leading number for local variables + parts = orig_name.split('_') + if len(parts) > 1 and parts[0].isdigit(): + return parts[1] + return orig_name + + def collect_context(self, frame): + res = {} + for k, v in frame.f_locals.items(): + if not k.startswith('l_'): + res[k] = v + elif v and not _is_missing(v): + res[self._get_real_var_name(k[2:])] = v + if self.back_context is not None: + for k, v in self.back_context.items(): + res[k] = v + return res + + def _change_variable(self, frame, name, value): + in_vars_or_parents = False + if 'context' in frame.f_locals: + if name in frame.f_locals['context'].parent: + self.back_context.parent[name] = value + in_vars_or_parents = True + if name in frame.f_locals['context'].vars: + self.back_context.vars[name] = value + in_vars_or_parents = True + + l_name = 'l_' + name + if l_name in frame.f_locals: + if in_vars_or_parents: + frame.f_locals[l_name] = self.back_context.resolve(name) + else: + frame.f_locals[l_name] = value + + +class Jinja2TemplateSyntaxErrorFrame(object): + + IS_PLUGIN_FRAME = True + + def __init__(self, frame, exception_cls_name, filename, lineno, f_locals): + self.f_code = FCode('Jinja2 %s' % (exception_cls_name,), filename) + self.f_lineno = lineno + self.f_back = frame + self.f_globals = {} + self.f_locals = f_locals + self.f_trace = None + + +def change_variable(plugin, frame, attr, expression): + if isinstance(frame, Jinja2TemplateFrame): + result = eval(expression, frame.f_globals, frame.f_locals) + frame._change_variable(frame.f_back, attr, result) + return result + return False + + +def _is_missing(item): + if item.__class__.__name__ == 'MissingType': + return True + return False + + +def _find_render_function_frame(frame): + # in order to hide internal rendering functions + old_frame = frame + try: + while not ('self' in frame.f_locals and frame.f_locals['self'].__class__.__name__ == 'Template' and \ + frame.f_code.co_name == 'render'): + frame = frame.f_back + if frame is None: + return old_frame + return frame + except: + return old_frame + + +def _get_jinja2_template_debug_info(frame): + frame_globals = frame.f_globals + + jinja_template = frame_globals.get('__jinja_template__') + + if jinja_template is None: + return None + + return _get_frame_lineno_mapping(jinja_template) + + +def _get_frame_lineno_mapping(jinja_template): + ''' + :rtype: list(tuple(int,int)) + :return: list((original_line, line_in_frame)) + ''' + # _debug_info is a string with the mapping from frame line to actual line + # i.e.: "5=13&8=14" + _debug_info = jinja_template._debug_info + if not _debug_info: + # Sometimes template contains only plain text. + return None + + # debug_info is a list with the mapping from frame line to actual line + # i.e.: [(5, 13), (8, 14)] + return jinja_template.debug_info + + +def _get_jinja2_template_line(frame): + debug_info = _get_jinja2_template_debug_info(frame) + if debug_info is None: + return None + + lineno = frame.f_lineno + + for pair in debug_info: + if pair[1] == lineno: + return pair[0] + + return None + + +def _convert_to_str(s): + return s + + +def _get_jinja2_template_original_filename(frame): + if '__jinja_template__' in frame.f_globals: + return _convert_to_str(frame.f_globals['__jinja_template__'].filename) + + return None + +#======================================================================================================================= +# Jinja2 Step Commands +#======================================================================================================================= + + +def has_exception_breaks(plugin): + if len(plugin.main_debugger.jinja2_exception_break) > 0: + return True + return False + + +def has_line_breaks(plugin): + for _canonical_normalized_filename, breakpoints in plugin.main_debugger.jinja2_breakpoints.items(): + if len(breakpoints) > 0: + return True + return False + + +def can_skip(plugin, pydb, frame): + if pydb.jinja2_breakpoints and _is_jinja2_render_call(frame): + filename = _get_jinja2_template_original_filename(frame) + if filename is not None: + canonical_normalized_filename = canonical_normalized_path(filename) + jinja2_breakpoints_for_file = pydb.jinja2_breakpoints.get(canonical_normalized_filename) + if jinja2_breakpoints_for_file: + return False + + if pydb.jinja2_exception_break: + name = frame.f_code.co_name + + # errors in compile time + if name in ('template', 'top-level template code', '') or name.startswith('block '): + f_back = frame.f_back + module_name = '' + if f_back is not None: + module_name = f_back.f_globals.get('__name__', '') + if module_name.startswith('jinja2.'): + return False + + return True + + +def cmd_step_into(plugin, pydb, frame, event, args, stop_info, stop): + info = args[2] + thread = args[3] + plugin_stop = False + stop_info['jinja2_stop'] = False + if _is_jinja2_suspended(thread): + stop_info['jinja2_stop'] = event in ('call', 'line') and _is_jinja2_render_call(frame) + plugin_stop = stop_info['jinja2_stop'] + stop = False + if info.pydev_call_from_jinja2 is not None: + if _is_jinja2_internal_function(frame): + # if internal Jinja2 function was called, we sould continue debugging inside template + info.pydev_call_from_jinja2 = None + else: + # we go into python code from Jinja2 rendering frame + stop = True + + if event == 'call' and _is_jinja2_context_call(frame.f_back): + # we called function from context, the next step will be in function + info.pydev_call_from_jinja2 = 1 + + if event == 'return' and _is_jinja2_context_call(frame.f_back): + # we return from python code to Jinja2 rendering frame + info.pydev_step_stop = info.pydev_call_from_jinja2 + info.pydev_call_from_jinja2 = None + thread.additional_info.suspend_type = JINJA2_SUSPEND + stop = False + + # print "info.pydev_call_from_jinja2", info.pydev_call_from_jinja2, "stop_info", stop_info, \ + # "thread.additional_info.suspend_type", thread.additional_info.suspend_type + # print "event", event, "farme.locals", frame.f_locals + return stop, plugin_stop + + +def cmd_step_over(plugin, pydb, frame, event, args, stop_info, stop): + info = args[2] + thread = args[3] + plugin_stop = False + stop_info['jinja2_stop'] = False + if _is_jinja2_suspended(thread): + stop = False + + if info.pydev_call_inside_jinja2 is None: + if _is_jinja2_render_call(frame): + if event == 'call': + info.pydev_call_inside_jinja2 = frame.f_back + if event in ('line', 'return'): + info.pydev_call_inside_jinja2 = frame + else: + if event == 'line': + if _is_jinja2_render_call(frame) and info.pydev_call_inside_jinja2 is frame: + stop_info['jinja2_stop'] = True + plugin_stop = stop_info['jinja2_stop'] + if event == 'return': + if frame is info.pydev_call_inside_jinja2 and 'event' not in frame.f_back.f_locals: + info.pydev_call_inside_jinja2 = _find_jinja2_render_frame(frame.f_back) + return stop, plugin_stop + else: + if event == 'return' and _is_jinja2_context_call(frame.f_back): + # we return from python code to Jinja2 rendering frame + info.pydev_call_from_jinja2 = None + info.pydev_call_inside_jinja2 = _find_jinja2_render_frame(frame) + thread.additional_info.suspend_type = JINJA2_SUSPEND + stop = False + return stop, plugin_stop + # print "info.pydev_call_from_jinja2", info.pydev_call_from_jinja2, "stop", stop, "jinja_stop", jinja2_stop, \ + # "thread.additional_info.suspend_type", thread.additional_info.suspend_type + # print "event", event, "info.pydev_call_inside_jinja2", info.pydev_call_inside_jinja2 + # print "frame", frame, "frame.f_back", frame.f_back, "step_stop", info.pydev_step_stop + # print "is_context_call", _is_jinja2_context_call(frame) + # print "render", _is_jinja2_render_call(frame) + # print "-------------" + return stop, plugin_stop + + +def stop(plugin, pydb, frame, event, args, stop_info, arg, step_cmd): + pydb = args[0] + thread = args[3] + if 'jinja2_stop' in stop_info and stop_info['jinja2_stop']: + frame = _suspend_jinja2(pydb, thread, frame, step_cmd) + if frame: + pydb.do_wait_suspend(thread, frame, event, arg) + return True + return False + + +def get_breakpoint(plugin, py_db, pydb_frame, frame, event, args): + py_db = args[0] + _filename = args[1] + info = args[2] + break_type = 'jinja2' + + if event == 'line' and info.pydev_state != STATE_SUSPEND and py_db.jinja2_breakpoints and _is_jinja2_render_call(frame): + + jinja_template = frame.f_globals.get('__jinja_template__') + if jinja_template is None: + return False, None, None, break_type + + original_filename = _get_jinja2_template_original_filename(frame) + if original_filename is not None: + pydev_log.debug("Jinja2 is rendering a template: %s", original_filename) + canonical_normalized_filename = canonical_normalized_path(original_filename) + jinja2_breakpoints_for_file = py_db.jinja2_breakpoints.get(canonical_normalized_filename) + + if jinja2_breakpoints_for_file: + + jinja2_validation_info = py_db.jinja2_validation_info + jinja2_validation_info.verify_breakpoints(py_db, canonical_normalized_filename, jinja2_breakpoints_for_file, jinja_template) + + template_lineno = _get_jinja2_template_line(frame) + if template_lineno is not None: + jinja2_breakpoint = jinja2_breakpoints_for_file.get(template_lineno) + if jinja2_breakpoint is not None: + new_frame = Jinja2TemplateFrame(frame, original_filename, template_lineno) + return True, jinja2_breakpoint, new_frame, break_type + + return False, None, None, break_type + + +def suspend(plugin, pydb, thread, frame, bp_type): + if bp_type == 'jinja2': + return _suspend_jinja2(pydb, thread, frame) + return None + + +def exception_break(plugin, pydb, pydb_frame, frame, args, arg): + pydb = args[0] + thread = args[3] + exception, value, trace = arg + if pydb.jinja2_exception_break and exception is not None: + exception_type = list(pydb.jinja2_exception_break.keys())[0] + if exception.__name__ in ('UndefinedError', 'TemplateNotFound', 'TemplatesNotFound'): + # errors in rendering + render_frame = _find_jinja2_render_frame(frame) + if render_frame: + suspend_frame = _suspend_jinja2(pydb, thread, render_frame, CMD_ADD_EXCEPTION_BREAK, message=exception_type) + if suspend_frame: + add_exception_to_frame(suspend_frame, (exception, value, trace)) + suspend_frame.f_back = frame + frame = suspend_frame + return True, frame + + elif exception.__name__ in ('TemplateSyntaxError', 'TemplateAssertionError'): + name = frame.f_code.co_name + + # errors in compile time + if name in ('template', 'top-level template code', '') or name.startswith('block '): + + f_back = frame.f_back + if f_back is not None: + module_name = f_back.f_globals.get('__name__', '') + + if module_name.startswith('jinja2.'): + # Jinja2 translates exception info and creates fake frame on his own + pydb_frame.set_suspend(thread, CMD_ADD_EXCEPTION_BREAK) + add_exception_to_frame(frame, (exception, value, trace)) + thread.additional_info.suspend_type = JINJA2_SUSPEND + thread.additional_info.pydev_message = str(exception_type) + return True, frame + return None diff --git a/pydevd_plugins/pydevd_line_validation.py b/pydevd_plugins/pydevd_line_validation.py new file mode 100644 index 0000000..2b64a52 --- /dev/null +++ b/pydevd_plugins/pydevd_line_validation.py @@ -0,0 +1,107 @@ +from _pydevd_bundle.pydevd_breakpoints import LineBreakpoint +from _pydevd_bundle.pydevd_api import PyDevdAPI +import bisect +from _pydev_bundle import pydev_log + + +class LineBreakpointWithLazyValidation(LineBreakpoint): + + def __init__(self, *args, **kwargs): + LineBreakpoint.__init__(self, *args, **kwargs) + # This is the _AddBreakpointResult that'll be modified (and then re-sent on the + # on_changed_breakpoint_state). + self.add_breakpoint_result = None + + # The signature for the callback should be: + # on_changed_breakpoint_state(breakpoint_id: int, add_breakpoint_result: _AddBreakpointResult) + self.on_changed_breakpoint_state = None + + # When its state is checked (in which case it'd call on_changed_breakpoint_state if the + # state changed), we store a cache key in 'verified_cache_key' -- in case it changes + # we'd need to re-verify it (for instance, the template could have changed on disk). + self.verified_cache_key = None + + +class ValidationInfo(object): + + def __init__(self): + self._canonical_normalized_filename_to_last_template_lines = {} + + def _collect_valid_lines_in_template(self, template): + # We cache the lines in the template itself. Note that among requests the + # template may be a different instance (because the template contents could be + # changed on disk), but this may still be called multiple times during the + # same render session, so, caching is interesting. + lines_cache = getattr(template, '__pydevd_lines_cache__', None) + if lines_cache is not None: + lines, sorted_lines = lines_cache + return lines, sorted_lines + + lines = self._collect_valid_lines_in_template_uncached(template) + + lines = frozenset(lines) + sorted_lines = tuple(sorted(lines)) + template.__pydevd_lines_cache__ = lines, sorted_lines + return lines, sorted_lines + + def _collect_valid_lines_in_template_uncached(self, template): + raise NotImplementedError() + + def verify_breakpoints(self, py_db, canonical_normalized_filename, template_breakpoints_for_file, template): + ''' + This function should be called whenever a rendering is detected. + + :param str canonical_normalized_filename: + :param dict[int:LineBreakpointWithLazyValidation] template_breakpoints_for_file: + ''' + valid_lines_frozenset, sorted_lines = self._collect_valid_lines_in_template(template) + + self._canonical_normalized_filename_to_last_template_lines[canonical_normalized_filename] = valid_lines_frozenset, sorted_lines + self._verify_breakpoints_with_lines_collected(py_db, canonical_normalized_filename, template_breakpoints_for_file, valid_lines_frozenset, sorted_lines) + + def verify_breakpoints_from_template_cached_lines(self, py_db, canonical_normalized_filename, template_breakpoints_for_file): + ''' + This is used when the lines are already available (if just the template is available, + `verify_breakpoints` should be used instead). + ''' + cached = self._canonical_normalized_filename_to_last_template_lines.get(canonical_normalized_filename) + if cached is not None: + valid_lines_frozenset, sorted_lines = cached + self._verify_breakpoints_with_lines_collected(py_db, canonical_normalized_filename, template_breakpoints_for_file, valid_lines_frozenset, sorted_lines) + + def _verify_breakpoints_with_lines_collected(self, py_db, canonical_normalized_filename, template_breakpoints_for_file, valid_lines_frozenset, sorted_lines): + for line, template_bp in list(template_breakpoints_for_file.items()): # Note: iterate in a copy (we may mutate it). + if template_bp.verified_cache_key != valid_lines_frozenset: + template_bp.verified_cache_key = valid_lines_frozenset + valid = line in valid_lines_frozenset + + if not valid: + new_line = -1 + if sorted_lines: + # Adjust to the first preceding valid line. + idx = bisect.bisect_left(sorted_lines, line) + if idx > 0: + new_line = sorted_lines[idx - 1] + + if new_line >= 0 and new_line not in template_breakpoints_for_file: + # We just add it if found and if there's no existing breakpoint at that + # location. + if template_bp.add_breakpoint_result.error_code != PyDevdAPI.ADD_BREAKPOINT_NO_ERROR and template_bp.add_breakpoint_result.translated_line != new_line: + pydev_log.debug('Template breakpoint in %s in line: %s moved to line: %s', canonical_normalized_filename, line, new_line) + template_bp.add_breakpoint_result.error_code = PyDevdAPI.ADD_BREAKPOINT_NO_ERROR + template_bp.add_breakpoint_result.translated_line = new_line + + # Add it to a new line. + template_breakpoints_for_file.pop(line, None) + template_breakpoints_for_file[new_line] = template_bp + template_bp.on_changed_breakpoint_state(template_bp.breakpoint_id, template_bp.add_breakpoint_result) + else: + if template_bp.add_breakpoint_result.error_code != PyDevdAPI.ADD_BREAKPOINT_INVALID_LINE: + pydev_log.debug('Template breakpoint in %s in line: %s invalid (valid lines: %s)', canonical_normalized_filename, line, valid_lines_frozenset) + template_bp.add_breakpoint_result.error_code = PyDevdAPI.ADD_BREAKPOINT_INVALID_LINE + template_bp.on_changed_breakpoint_state(template_bp.breakpoint_id, template_bp.add_breakpoint_result) + else: + if template_bp.add_breakpoint_result.error_code != PyDevdAPI.ADD_BREAKPOINT_NO_ERROR: + template_bp.add_breakpoint_result.error_code = PyDevdAPI.ADD_BREAKPOINT_NO_ERROR + template_bp.on_changed_breakpoint_state(template_bp.breakpoint_id, template_bp.add_breakpoint_result) + diff --git a/pydevd_tracing.py b/pydevd_tracing.py new file mode 100644 index 0000000..5061a53 --- /dev/null +++ b/pydevd_tracing.py @@ -0,0 +1,375 @@ +from _pydevd_bundle.pydevd_constants import get_frame, IS_CPYTHON, IS_64BIT_PROCESS, IS_WINDOWS, \ + IS_LINUX, IS_MAC, DebugInfoHolder, LOAD_NATIVE_LIB_FLAG, \ + ENV_FALSE_LOWER_VALUES, ForkSafeLock +from _pydev_bundle._pydev_saved_modules import thread, threading +from _pydev_bundle import pydev_log, pydev_monkey +import os.path +import platform +import ctypes +from io import StringIO +import sys +import traceback + +_original_settrace = sys.settrace + + +class TracingFunctionHolder: + '''This class exists just to keep some variables (so that we don't keep them in the global namespace). + ''' + _original_tracing = None + _warn = True + _traceback_limit = 1 + _warnings_shown = {} + + +def get_exception_traceback_str(): + exc_info = sys.exc_info() + s = StringIO() + traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], file=s) + return s.getvalue() + + +def _get_stack_str(frame): + + msg = '\nIf this is needed, please check: ' + \ + '\nhttp://pydev.blogspot.com/2007/06/why-cant-pydev-debugger-work-with.html' + \ + '\nto see how to restore the debug tracing back correctly.\n' + + if TracingFunctionHolder._traceback_limit: + s = StringIO() + s.write('Call Location:\n') + traceback.print_stack(f=frame, limit=TracingFunctionHolder._traceback_limit, file=s) + msg = msg + s.getvalue() + + return msg + + +def _internal_set_trace(tracing_func): + if TracingFunctionHolder._warn: + frame = get_frame() + if frame is not None and frame.f_back is not None: + filename = frame.f_back.f_code.co_filename.lower() + if not filename.endswith('threading.py') and not filename.endswith('pydevd_tracing.py'): + + message = \ + '\nPYDEV DEBUGGER WARNING:' + \ + '\nsys.settrace() should not be used when the debugger is being used.' + \ + '\nThis may cause the debugger to stop working correctly.' + \ + '%s' % _get_stack_str(frame.f_back) + + if message not in TracingFunctionHolder._warnings_shown: + # only warn about each message once... + TracingFunctionHolder._warnings_shown[message] = 1 + sys.stderr.write('%s\n' % (message,)) + sys.stderr.flush() + + if TracingFunctionHolder._original_tracing: + TracingFunctionHolder._original_tracing(tracing_func) + + +_last_tracing_func_thread_local = threading.local() + + +def SetTrace(tracing_func): + _last_tracing_func_thread_local.tracing_func = tracing_func + + if tracing_func is not None: + if set_trace_to_threads(tracing_func, thread_idents=[thread.get_ident()], create_dummy_thread=False) == 0: + # If we can use our own tracer instead of the one from sys.settrace, do it (the reason + # is that this is faster than the Python version because we don't call + # PyFrame_FastToLocalsWithError and PyFrame_LocalsToFast at each event! + # (the difference can be huge when checking line events on frames as the + # time increases based on the number of local variables in the scope) + # See: InternalCallTrampoline (on the C side) for details. + return + + # If it didn't work (or if it was None), use the Python version. + set_trace = TracingFunctionHolder._original_tracing or sys.settrace + set_trace(tracing_func) + + +def reapply_settrace(): + try: + tracing_func = _last_tracing_func_thread_local.tracing_func + except AttributeError: + return + else: + SetTrace(tracing_func) + + +def replace_sys_set_trace_func(): + if TracingFunctionHolder._original_tracing is None: + TracingFunctionHolder._original_tracing = sys.settrace + sys.settrace = _internal_set_trace + + +def restore_sys_set_trace_func(): + if TracingFunctionHolder._original_tracing is not None: + sys.settrace = TracingFunctionHolder._original_tracing + TracingFunctionHolder._original_tracing = None + + +_lock = ForkSafeLock() + + +def _load_python_helper_lib(): + try: + # If it's already loaded, just return it. + return _load_python_helper_lib.__lib__ + except AttributeError: + pass + with _lock: + try: + return _load_python_helper_lib.__lib__ + except AttributeError: + pass + + lib = _load_python_helper_lib_uncached() + _load_python_helper_lib.__lib__ = lib + return lib + + +def get_python_helper_lib_filename(): + # Note: we have an independent (and similar -- but not equal) version of this method in + # `add_code_to_python_process.py` which should be kept synchronized with this one (we do a copy + # because the `pydevd_attach_to_process` is mostly independent and shouldn't be imported in the + # debugger -- the only situation where it's imported is if the user actually does an attach to + # process, through `attach_pydevd.py`, but this should usually be called from the IDE directly + # and not from the debugger). + libdir = os.path.join(os.path.dirname(__file__), 'pydevd_attach_to_process') + + arch = '' + if IS_WINDOWS: + # prefer not using platform.machine() when possible (it's a bit heavyweight as it may + # spawn a subprocess). + arch = os.environ.get("PROCESSOR_ARCHITEW6432", os.environ.get('PROCESSOR_ARCHITECTURE', '')) + + if not arch: + arch = platform.machine() + if not arch: + pydev_log.info('platform.machine() did not return valid value.') # This shouldn't happen... + return None + + if IS_WINDOWS: + extension = '.dll' + suffix_64 = 'amd64' + suffix_32 = 'x86' + + elif IS_LINUX: + extension = '.so' + suffix_64 = 'amd64' + suffix_32 = 'x86' + + elif IS_MAC: + extension = '.dylib' + suffix_64 = 'x86_64' + suffix_32 = 'x86' + + else: + pydev_log.info('Unable to set trace to all threads in platform: %s', sys.platform) + return None + + if arch.lower() not in ('amd64', 'x86', 'x86_64', 'i386', 'x86'): + # We don't support this processor by default. Still, let's support the case where the + # user manually compiled it himself with some heuristics. + # + # Ideally the user would provide a library in the format: "attach_." + # based on the way it's currently compiled -- see: + # - windows/compile_windows.bat + # - linux_and_mac/compile_linux.sh + # - linux_and_mac/compile_mac.sh + + try: + found = [name for name in os.listdir(libdir) if name.startswith('attach_') and name.endswith(extension)] + except: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + # There is no need to show this unless debug tracing is enabled. + pydev_log.exception('Error listing dir: %s', libdir) + return None + + expected_name = 'attach_' + arch + extension + expected_name_linux = 'attach_linux_' + arch + extension + + filename = None + if expected_name in found: # Heuristic: user compiled with "attach_." + filename = os.path.join(libdir, expected_name) + + elif IS_LINUX and expected_name_linux in found: # Heuristic: user compiled with "attach_linux_." + filename = os.path.join(libdir, expected_name_linux) + + elif len(found) == 1: # Heuristic: user removed all libraries and just left his own lib. + filename = os.path.join(libdir, found[0]) + + else: # Heuristic: there's one additional library which doesn't seem to be our own. Find the odd one. + filtered = [name for name in found if not name.endswith((suffix_64 + extension, suffix_32 + extension))] + if len(filtered) == 1: # If more than one is available we can't be sure... + filename = os.path.join(libdir, found[0]) + + if filename is None: + pydev_log.info( + 'Unable to set trace to all threads in arch: %s (did not find a %s lib in %s).', + arch, expected_name, libdir + + ) + return None + + pydev_log.info('Using %s lib in arch: %s.', filename, arch) + + else: + # Happy path for which we have pre-compiled binaries. + if IS_64BIT_PROCESS: + suffix = suffix_64 + else: + suffix = suffix_32 + + if IS_WINDOWS or IS_MAC: # just the extension changes + prefix = 'attach_' + elif IS_LINUX: # + prefix = 'attach_linux_' # historically it has a different name + else: + pydev_log.info('Unable to set trace to all threads in platform: %s', sys.platform) + return None + + filename = os.path.join(libdir, '%s%s%s' % (prefix, suffix, extension)) + + if not os.path.exists(filename): + pydev_log.critical('Expected: %s to exist.', filename) + return None + + return filename + + +def _load_python_helper_lib_uncached(): + if (not IS_CPYTHON or sys.version_info[:2] > (3, 11) + or hasattr(sys, 'gettotalrefcount') or LOAD_NATIVE_LIB_FLAG in ENV_FALSE_LOWER_VALUES): + pydev_log.info('Helper lib to set tracing to all threads not loaded.') + return None + + try: + filename = get_python_helper_lib_filename() + if filename is None: + return None + # Load as pydll so that we don't release the gil. + lib = ctypes.pydll.LoadLibrary(filename) + pydev_log.info('Successfully Loaded helper lib to set tracing to all threads.') + return lib + except: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + # Only show message if tracing is on (we don't have pre-compiled + # binaries for all architectures -- i.e.: ARM). + pydev_log.exception('Error loading: %s', filename) + return None + + +def set_trace_to_threads(tracing_func, thread_idents=None, create_dummy_thread=True): + assert tracing_func is not None + + ret = 0 + + # Note: use sys._current_frames() keys to get the thread ids because it'll return + # thread ids created in C/C++ where there's user code running, unlike the APIs + # from the threading module which see only threads created through it (unless + # a call for threading.current_thread() was previously done in that thread, + # in which case a dummy thread would've been created for it). + if thread_idents is None: + thread_idents = set(sys._current_frames().keys()) + + for t in threading.enumerate(): + # PY-44778: ignore pydevd threads and also add any thread that wasn't found on + # sys._current_frames() as some existing threads may not appear in + # sys._current_frames() but may be available through the `threading` module. + if getattr(t, 'pydev_do_not_trace', False): + thread_idents.discard(t.ident) + else: + thread_idents.add(t.ident) + + curr_ident = thread.get_ident() + curr_thread = threading._active.get(curr_ident) + + if curr_ident in thread_idents and len(thread_idents) != 1: + # The current thread must be updated first (because we need to set + # the reference to `curr_thread`). + thread_idents = list(thread_idents) + thread_idents.remove(curr_ident) + thread_idents.insert(0, curr_ident) + + for thread_ident in thread_idents: + # If that thread is not available in the threading module we also need to create a + # dummy thread for it (otherwise it'll be invisible to the debugger). + if create_dummy_thread: + if thread_ident not in threading._active: + + class _DummyThread(threading._DummyThread): + + def _set_ident(self): + # Note: Hack to set the thread ident that we want. + self._ident = thread_ident + + t = _DummyThread() + # Reset to the base class (don't expose our own version of the class). + t.__class__ = threading._DummyThread + + if thread_ident == curr_ident: + curr_thread = t + + with threading._active_limbo_lock: + # On Py2 it'll put in active getting the current indent, not using the + # ident that was set, so, we have to update it (should be harmless on Py3 + # so, do it always). + threading._active[thread_ident] = t + threading._active[curr_ident] = curr_thread + + if t.ident != thread_ident: + # Check if it actually worked. + pydev_log.critical('pydevd: creation of _DummyThread with fixed thread ident did not succeed.') + + # Some (ptvsd) tests failed because of this, so, leave it always disabled for now. + # show_debug_info = 1 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1 else 0 + show_debug_info = 0 + + # Hack to increase _Py_TracingPossible. + # See comments on py_custom_pyeval_settrace.hpp + proceed = thread.allocate_lock() + proceed.acquire() + + def dummy_trace(frame, event, arg): + return dummy_trace + + def increase_tracing_count(): + set_trace = TracingFunctionHolder._original_tracing or sys.settrace + set_trace(dummy_trace) + proceed.release() + + start_new_thread = pydev_monkey.get_original_start_new_thread(thread) + start_new_thread(increase_tracing_count, ()) + proceed.acquire() # Only proceed after the release() is done. + proceed = None + + # Note: The set_trace_func is not really used anymore in the C side. + set_trace_func = TracingFunctionHolder._original_tracing or sys.settrace + + lib = _load_python_helper_lib() + if lib is None: # This is the case if it's not CPython. + pydev_log.info('Unable to load helper lib to set tracing to all threads (unsupported python vm).') + ret = -1 + else: + try: + result = lib.AttachDebuggerTracing( + ctypes.c_int(show_debug_info), + ctypes.py_object(set_trace_func), + ctypes.py_object(tracing_func), + ctypes.c_uint(thread_ident), + ctypes.py_object(None), + ) + except: + if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1: + # There is no need to show this unless debug tracing is enabled. + pydev_log.exception('Error attaching debugger tracing') + ret = -1 + else: + if result != 0: + pydev_log.info('Unable to set tracing for existing thread. Result: %s', result) + ret = result + + return ret + diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..cd47002 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +norecursedirs=tests_runfiles/samples +addopts=-vv +testpaths=test_pydevd_reload tests tests_mainloop tests_python tests_runfiles \ No newline at end of file diff --git a/runfiles.py b/runfiles.py new file mode 100644 index 0000000..15b9f3a --- /dev/null +++ b/runfiles.py @@ -0,0 +1,317 @@ +''' +Entry point module (keep at root): + +Used to run with tests with unittest/pytest/nose. +''' + +import os + + +def main(): + import sys + + # Separate the nose params and the pydev params. + pydev_params = [] + other_test_framework_params = [] + found_other_test_framework_param = None + + NOSE_PARAMS = '--nose-params' + PY_TEST_PARAMS = '--py-test-params' + + for arg in sys.argv[1:]: + if not found_other_test_framework_param and arg != NOSE_PARAMS and arg != PY_TEST_PARAMS: + pydev_params.append(arg) + + else: + if not found_other_test_framework_param: + found_other_test_framework_param = arg + else: + other_test_framework_params.append(arg) + + try: + # Convert to the case stored in the filesystem + import win32api + + def get_with_filesystem_case(f): + return win32api.GetLongPathName(win32api.GetShortPathName(f)) + + except: + + def get_with_filesystem_case(f): + return f + + # Here we'll run either with nose or with the pydev_runfiles. + from _pydev_runfiles import pydev_runfiles + from _pydev_runfiles import pydev_runfiles_xml_rpc + from _pydevd_bundle import pydevd_constants + from pydevd_file_utils import canonical_normalized_path + + DEBUG = 0 + if DEBUG: + sys.stdout.write('Received parameters: %s\n' % (sys.argv,)) + sys.stdout.write('Params for pydev: %s\n' % (pydev_params,)) + if found_other_test_framework_param: + sys.stdout.write('Params for test framework: %s, %s\n' % (found_other_test_framework_param, other_test_framework_params)) + + try: + configuration = pydev_runfiles.parse_cmdline([sys.argv[0]] + pydev_params) + except: + sys.stderr.write('Command line received: %s\n' % (sys.argv,)) + raise + pydev_runfiles_xml_rpc.initialize_server(configuration.port) # Note that if the port is None, a Null server will be initialized. + + NOSE_FRAMEWORK = "nose" + PY_TEST_FRAMEWORK = "py.test" + test_framework = None # Default (pydev) + try: + if found_other_test_framework_param: + if found_other_test_framework_param == NOSE_PARAMS: + test_framework = NOSE_FRAMEWORK + import nose + + elif found_other_test_framework_param == PY_TEST_PARAMS: + test_framework = PY_TEST_FRAMEWORK + import pytest + + else: + raise ImportError('Test framework: %s not supported.' % (found_other_test_framework_param,)) + + else: + raise ImportError() + + except ImportError: + if found_other_test_framework_param: + raise + + test_framework = None + + # Clear any exception that may be there so that clients don't see it. + # See: https://sourceforge.net/tracker/?func=detail&aid=3408057&group_id=85796&atid=577329 + if hasattr(sys, 'exc_clear'): + sys.exc_clear() + + if not test_framework: + + return pydev_runfiles.main(configuration) # Note: still doesn't return a proper value. + + else: + # We'll convert the parameters to what nose or py.test expects. + # The supported parameters are: + # runfiles.py --config-file|-t|--tests dirs|files --nose-params xxx yyy zzz + # (all after --nose-params should be passed directly to nose) + + # In java: + # --tests = Constants.ATTR_UNITTEST_TESTS + # --config-file = Constants.ATTR_UNITTEST_CONFIGURATION_FILE + + # The only thing actually handled here are the tests that we want to run, which we'll + # handle and pass as what the test framework expects. + + py_test_accept_filter = {} + files_to_tests = configuration.files_to_tests + + if files_to_tests: + # Handling through the file contents (file where each line is a test) + files_or_dirs = [] + for file, tests in files_to_tests.items(): + if test_framework == NOSE_FRAMEWORK: + for test in tests: + files_or_dirs.append(file + ':' + test) + + elif test_framework == PY_TEST_FRAMEWORK: + py_test_accept_filter[file] = tests + py_test_accept_filter[canonical_normalized_path(file)] = tests + files_or_dirs.append(file) + + else: + raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,)) + + else: + if configuration.tests: + # Tests passed (works together with the files_or_dirs) + files_or_dirs = [] + for file in configuration.files_or_dirs: + if test_framework == NOSE_FRAMEWORK: + for t in configuration.tests: + files_or_dirs.append(file + ':' + t) + + elif test_framework == PY_TEST_FRAMEWORK: + py_test_accept_filter[file] = configuration.tests + py_test_accept_filter[canonical_normalized_path(file)] = configuration.tests + files_or_dirs.append(file) + + else: + raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,)) + else: + # Only files or dirs passed (let it do the test-loading based on those paths) + files_or_dirs = configuration.files_or_dirs + + argv = other_test_framework_params + files_or_dirs + + if test_framework == NOSE_FRAMEWORK: + # Nose usage: http://somethingaboutorange.com/mrl/projects/nose/0.11.2/usage.html + # show_stdout_option = ['-s'] + # processes_option = ['--processes=2'] + argv.insert(0, sys.argv[0]) + if DEBUG: + sys.stdout.write('Final test framework args: %s\n' % (argv[1:],)) + + from _pydev_runfiles import pydev_runfiles_nose + PYDEV_NOSE_PLUGIN_SINGLETON = pydev_runfiles_nose.start_pydev_nose_plugin_singleton(configuration) + argv.append('--with-pydevplugin') + # Return 'not' because it will return 'success' (so, exit == 0 if success) + return not nose.run(argv=argv, addplugins=[PYDEV_NOSE_PLUGIN_SINGLETON]) + + elif test_framework == PY_TEST_FRAMEWORK: + + if '--coverage_output_dir' in pydev_params and '--coverage_include' in pydev_params: + coverage_output_dir = pydev_params[pydev_params.index('--coverage_output_dir') + 1] + coverage_include = pydev_params[pydev_params.index('--coverage_include') + 1] + try: + import pytest_cov + except ImportError: + sys.stderr.write('To do a coverage run with pytest the pytest-cov library is needed (i.e.: pip install pytest-cov).\n\n') + raise + + argv.insert(0, '--cov-append') + argv.insert(1, '--cov-report=') + argv.insert(2, '--cov=%s' % (coverage_include,)) + + import time + os.environ['COVERAGE_FILE'] = os.path.join(coverage_output_dir, '.coverage.%s' % (time.time(),)) + + if DEBUG: + sys.stdout.write('Final test framework args: %s\n' % (argv,)) + sys.stdout.write('py_test_accept_filter: %s\n' % (py_test_accept_filter,)) + + def dotted(p): + # Helper to convert path to have dots instead of slashes + return os.path.normpath(p).replace(os.sep, "/").replace('/', '.') + + curr_dir = os.path.realpath('.') + curr_dotted = dotted(curr_dir) + '.' + + # Overcome limitation on py.test: + # When searching conftest if we have a structure as: + # /my_package + # /my_package/conftest.py + # /my_package/tests + # /my_package/tests/test_my_package.py + # The test_my_package won't have access to the conftest contents from the + # test_my_package.py file unless the working dir is set to /my_package. + # + # See related issue (for which we work-around below): + # https://bitbucket.org/hpk42/pytest/issue/639/conftest-being-loaded-twice-giving + + for path in sys.path: + path_dotted = dotted(path) + if curr_dotted.startswith(path_dotted): + os.chdir(path) + break + + remove = [] + for i in range(len(argv)): + arg = argv[i] + # Workaround bug in py.test: if we pass the full path it ends up importing conftest + # more than once (so, always work with relative paths). + if os.path.isfile(arg) or os.path.isdir(arg): + + # Args must be passed with the proper case in the filesystem (otherwise + # python itself may not recognize it). + arg = get_with_filesystem_case(arg) + argv[i] = arg + + from os.path import relpath + try: + # May fail if on different drives + arg = relpath(arg) + except ValueError: + pass + else: + argv[i] = arg + elif '' in arg: + remove.append(i) + + for i in reversed(remove): + del argv[i] + + # To find our runfile helpers (i.e.: plugin)... + d = os.path.dirname(__file__) + if d not in sys.path: + sys.path.insert(0, d) + + import pickle, zlib, base64 + + # Update environment PYTHONPATH so that it finds our plugin if using xdist. + os.environ['PYTHONPATH'] = os.pathsep.join(sys.path) + + # Set what should be skipped in the plugin through an environment variable + s = base64.b64encode(zlib.compress(pickle.dumps(py_test_accept_filter))) + s = s.decode('ascii') # Must be str in py3. + os.environ['PYDEV_PYTEST_SKIP'] = s + + # Identifies the main pid (i.e.: if it's not the main pid it has to connect back to the + # main pid to give xml-rpc notifications). + os.environ['PYDEV_MAIN_PID'] = str(os.getpid()) + os.environ['PYDEV_PYTEST_SERVER'] = str(configuration.port) + + argv.append('-p') + argv.append('_pydev_runfiles.pydev_runfiles_pytest2') + return pytest.main(argv) + + else: + raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,)) + + +if __name__ == '__main__': + try: + main() + finally: + try: + # The server is not a daemon thread, so, we have to ask for it to be killed! + from _pydev_runfiles import pydev_runfiles_xml_rpc + pydev_runfiles_xml_rpc.force_server_kill() + except: + pass # Ignore any errors here + + import sys + import threading + if hasattr(sys, '_current_frames') and hasattr(threading, 'enumerate'): + import time + import traceback + + class DumpThreads(threading.Thread): + + def run(self): + time.sleep(10) + + thread_id_to_name = {} + try: + for t in threading.enumerate(): + thread_id_to_name[t.ident] = '%s (daemon: %s)' % (t.name, t.daemon) + except: + pass + + stack_trace = [ + '===============================================================================', + 'pydev pyunit runner: Threads still found running after tests finished', + '================================= Thread Dump ================================='] + + for thread_id, stack in sys._current_frames().items(): + stack_trace.append('\n-------------------------------------------------------------------------------') + stack_trace.append(" Thread %s" % thread_id_to_name.get(thread_id, thread_id)) + stack_trace.append('') + + if 'self' in stack.f_locals: + sys.stderr.write(str(stack.f_locals['self']) + '\n') + + for filename, lineno, name, line in traceback.extract_stack(stack): + stack_trace.append(' File "%s", line %d, in %s' % (filename, lineno, name)) + if line: + stack_trace.append(" %s" % (line.strip())) + stack_trace.append('\n=============================== END Thread Dump ===============================') + sys.stderr.write('\n'.join(stack_trace)) + + dump_current_frames_thread = DumpThreads() + dump_current_frames_thread.daemon = True # Daemon so that this thread doesn't halt it! + dump_current_frames_thread.start() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..1d4fc68 --- /dev/null +++ b/setup.py @@ -0,0 +1,181 @@ +r''' +Full setup, used to distribute the debugger backend to PyPi. + +Note that this is mostly so that users can do: + +pip install pydevd + +in a machine for doing remote-debugging, as a local installation with the IDE should have +everything already distributed. + +Reference on wheels: +https://hynek.me/articles/sharing-your-labor-of-love-pypi-quick-and-dirty/ +http://lucumr.pocoo.org/2014/1/27/python-on-wheels/ + +Another (no wheels): https://jamie.curle.io/blog/my-first-experience-adding-package-pypi/ + +See: + +build_tools\pydevd_release_process.txt + +for release process. +''' + +from setuptools import setup +from setuptools.dist import Distribution +from distutils.extension import Extension +import os + + +class BinaryDistribution(Distribution): + + def is_pure(self): + return False + + +data_files = [] + + +def accept_file(f): + f = f.lower() + for ext in '.py .dll .so .dylib .txt .cpp .h .bat .c .sh .md .txt'.split(): + if f.endswith(ext): + return True + + return f in ['readme', 'makefile'] + + +data_files.append(('pydevd_attach_to_process', [os.path.join('pydevd_attach_to_process', f) for f in os.listdir('pydevd_attach_to_process') if accept_file(f)])) +for root, dirs, files in os.walk("pydevd_attach_to_process"): + for d in dirs: + data_files.append((os.path.join(root, d), [os.path.join(root, d, f) for f in os.listdir(os.path.join(root, d)) if accept_file(f)])) + +import pydevd +version = pydevd.__version__ + +args = dict( + name='pydevd', + version=version, + description='PyDev.Debugger (used in PyDev, PyCharm and VSCode Python)', + author='Fabio Zadrozny and others', + url='https://github.com/fabioz/PyDev.Debugger/', + license='EPL (Eclipse Public License)', + packages=[ + '_pydev_bundle', + '_pydev_bundle.fsnotify', + '_pydev_runfiles', + '_pydevd_bundle', + '_pydevd_bundle._debug_adapter', + '_pydevd_bundle.pydevd_concurrency_analyser', + '_pydevd_frame_eval', + '_pydevd_frame_eval.vendored', + '_pydevd_frame_eval.vendored.bytecode', + 'pydev_ipython', + + # 'pydev_sitecustomize', -- Not actually a package (not added) + + 'pydevd_attach_to_process', + + 'pydevd_plugins', + 'pydevd_plugins.extensions', + 'pydevd_plugins.extensions.types', + ], + py_modules=[ + # 'interpreterInfo', -- Not needed for debugger + # 'pycompletionserver', -- Not needed for debugger + 'pydev_app_engine_debug_startup', + # 'pydev_coverage', -- Not needed for debugger + # 'pydev_pysrc', -- Not needed for debugger + 'pydev_run_in_console', + 'pydevconsole', + 'pydevd_file_utils', + 'pydevd', + 'pydevd_tracing', + # 'runfiles', -- Not needed for debugger + 'setup_pydevd_cython', # Distributed to clients. See: https://github.com/fabioz/PyDev.Debugger/issues/102 + # 'setup', -- Should not be included as a module + ], + classifiers=[ + 'Development Status :: 6 - Mature', + 'Environment :: Console', + 'Intended Audience :: Developers', + + 'License :: OSI Approved :: Eclipse Public License 1.0 (EPL-1.0)', + + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Topic :: Software Development :: Debuggers', + ], + entry_points={ + 'console_scripts':[ + 'pydevd = pydevd:main', + ], + }, + data_files=data_files, + keywords=['pydev', 'pydevd', 'pydev.debugger'], + include_package_data=True, + zip_safe=False, +) + +import sys +try: + extra_compile_args = [] + extra_link_args = [] + + if 'linux' in sys.platform: + # Enabling -flto brings executable from 4MB to 0.56MB and -Os to 0.41MB + # Profiling shows an execution around 3-5% slower with -Os vs -O3, + # so, kept only -flto. + extra_compile_args = ["-flto", "-O3"] + extra_link_args = extra_compile_args[:] + + # Note: also experimented with profile-guided optimization. The executable + # size became a bit smaller (from 0.56MB to 0.5MB) but this would add an + # extra step to run the debugger to obtain the optimizations + # so, skipped it for now (note: the actual benchmarks time was in the + # margin of a 0-1% improvement, which is probably not worth it for + # speed increments). + # extra_compile_args = ["-flto", "-fprofile-generate"] + # ... Run benchmarks ... + # extra_compile_args = ["-flto", "-fprofile-use", "-fprofile-correction"] + elif 'win32' in sys.platform: + pass + # uncomment to generate pdbs for visual studio. + # extra_compile_args=["-Zi", "/Od"] + # extra_link_args=["-debug"] + + kwargs = {} + if extra_link_args: + kwargs['extra_link_args'] = extra_link_args + if extra_compile_args: + kwargs['extra_compile_args'] = extra_compile_args + + args_with_binaries = args.copy() + args_with_binaries.update(dict( + distclass=BinaryDistribution, + ext_modules=[ + # In this setup, don't even try to compile with cython, just go with the .c file which should've + # been properly generated from a tested version. + Extension( + '_pydevd_bundle.pydevd_cython', + ["_pydevd_bundle/pydevd_cython.c", ], + define_macros=[('Py_BUILD_CORE_MODULE', '1')], + **kwargs + ) + ] + )) + setup(**args_with_binaries) +except: + # Compile failed: just setup without compiling cython deps. + setup(**args) + sys.stdout.write('Plain-python version of pydevd installed (cython speedups not available).\n') diff --git a/setup_pydevd_cython.py b/setup_pydevd_cython.py new file mode 100644 index 0000000..5b395dd --- /dev/null +++ b/setup_pydevd_cython.py @@ -0,0 +1,250 @@ +''' +A simpler setup version just to compile the speedup module. + +It should be used as: + +python setup_pydevd_cython build_ext --inplace + +Note: the .c file and other generated files are regenerated from +the .pyx file by running "python build_tools/build.py" +''' + +import os +import sys +from setuptools import setup + +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +IS_PY36_OR_GREATER = sys.version_info > (3, 6) +TODO_PY311 = sys.version_info > (3, 11) + + +def process_args(): + extension_folder = None + target_pydevd_name = None + target_frame_eval = None + force_cython = False + + for i, arg in enumerate(sys.argv[:]): + if arg == '--build-lib': + extension_folder = sys.argv[i + 1] + # It shouldn't be removed from sys.argv (among with --build-temp) because they're passed further to setup() + if arg.startswith('--target-pyd-name='): + sys.argv.remove(arg) + target_pydevd_name = arg[len('--target-pyd-name='):] + if arg.startswith('--target-pyd-frame-eval='): + sys.argv.remove(arg) + target_frame_eval = arg[len('--target-pyd-frame-eval='):] + if arg == '--force-cython': + sys.argv.remove(arg) + force_cython = True + + return extension_folder, target_pydevd_name, target_frame_eval, force_cython + + +def process_template_lines(template_lines): + # Create 2 versions of the template, one for Python 3.8 and another for Python 3.9 + for version in ('38', '39'): + yield '### WARNING: GENERATED CODE, DO NOT EDIT!' + yield '### WARNING: GENERATED CODE, DO NOT EDIT!' + yield '### WARNING: GENERATED CODE, DO NOT EDIT!' + + for line in template_lines: + if version == '38': + line = line.replace('get_bytecode_while_frame_eval(PyFrameObject * frame_obj, int exc)', 'get_bytecode_while_frame_eval_38(PyFrameObject * frame_obj, int exc)') + line = line.replace('CALL_EvalFrameDefault', 'CALL_EvalFrameDefault_38(frame_obj, exc)') + else: # 3.9 + line = line.replace('get_bytecode_while_frame_eval(PyFrameObject * frame_obj, int exc)', 'get_bytecode_while_frame_eval_39(PyThreadState* tstate, PyFrameObject * frame_obj, int exc)') + line = line.replace('CALL_EvalFrameDefault', 'CALL_EvalFrameDefault_39(tstate, frame_obj, exc)') + + yield line + + yield '### WARNING: GENERATED CODE, DO NOT EDIT!' + yield '### WARNING: GENERATED CODE, DO NOT EDIT!' + yield '### WARNING: GENERATED CODE, DO NOT EDIT!' + yield '' + yield '' + + +def process_template_file(contents): + ret = [] + template_lines = [] + + append_to = ret + for line in contents.splitlines(keepends=False): + if line.strip() == '### TEMPLATE_START': + append_to = template_lines + elif line.strip() == '### TEMPLATE_END': + append_to = ret + for line in process_template_lines(template_lines): + ret.append(line) + else: + append_to.append(line) + + return '\n'.join(ret) + + +def build_extension(dir_name, extension_name, target_pydevd_name, force_cython, extended=False, has_pxd=False, template=False): + pyx_file = os.path.join(os.path.dirname(__file__), dir_name, "%s.pyx" % (extension_name,)) + + if template: + pyx_template_file = os.path.join(os.path.dirname(__file__), dir_name, "%s.template.pyx" % (extension_name,)) + with open(pyx_template_file, 'r') as stream: + contents = stream.read() + + contents = process_template_file(contents) + + with open(pyx_file, 'w') as stream: + stream.write(contents) + + if target_pydevd_name != extension_name: + # It MUST be there in this case! + # (otherwise we'll have unresolved externals because the .c file had another name initially). + import shutil + + # We must force cython in this case (but only in this case -- for the regular setup in the user machine, we + # should always compile the .c file). + force_cython = True + + new_pyx_file = os.path.join(os.path.dirname(__file__), dir_name, "%s.pyx" % (target_pydevd_name,)) + new_c_file = os.path.join(os.path.dirname(__file__), dir_name, "%s.c" % (target_pydevd_name,)) + shutil.copy(pyx_file, new_pyx_file) + pyx_file = new_pyx_file + if has_pxd: + pxd_file = os.path.join(os.path.dirname(__file__), dir_name, "%s.pxd" % (extension_name,)) + new_pxd_file = os.path.join(os.path.dirname(__file__), dir_name, "%s.pxd" % (target_pydevd_name,)) + shutil.copy(pxd_file, new_pxd_file) + assert os.path.exists(pyx_file) + + try: + c_files = [os.path.join(dir_name, "%s.c" % target_pydevd_name), ] + if force_cython: + for c_file in c_files: + try: + os.remove(c_file) + except: + pass + from Cython.Build import cythonize # @UnusedImport + # Generate the .c files in cythonize (will not compile at this point). + + target = "%s/%s.pyx" % (dir_name, target_pydevd_name,) + cythonize([target]) + + # Workarounds needed in CPython 3.8 and 3.9 to access PyInterpreterState.eval_frame. + for c_file in c_files: + with open(c_file, 'r') as stream: + c_file_contents = stream.read() + + if '#include "internal/pycore_gc.h"' not in c_file_contents: + c_file_contents = c_file_contents.replace('#include "Python.h"', '''#include "Python.h" +#if PY_VERSION_HEX >= 0x03090000 +#include "internal/pycore_gc.h" +#include "internal/pycore_interp.h" +#endif +''') + + if '#include "internal/pycore_pystate.h"' not in c_file_contents: + c_file_contents = c_file_contents.replace('#include "pystate.h"', '''#include "pystate.h" +#if PY_VERSION_HEX >= 0x03080000 +#include "internal/pycore_pystate.h" +#endif +''') + + # We want the same output on Windows and Linux. + c_file_contents = c_file_contents.replace('\r\n', '\n').replace('\r', '\n') + c_file_contents = c_file_contents.replace(r'_pydevd_frame_eval\\release_mem.h', '_pydevd_frame_eval/release_mem.h') + c_file_contents = c_file_contents.replace(r'_pydevd_frame_eval\\pydevd_frame_evaluator.pyx', '_pydevd_frame_eval/pydevd_frame_evaluator.pyx') + c_file_contents = c_file_contents.replace(r'_pydevd_bundle\\pydevd_cython.pxd', '_pydevd_bundle/pydevd_cython.pxd') + c_file_contents = c_file_contents.replace(r'_pydevd_bundle\\pydevd_cython.pyx', '_pydevd_bundle/pydevd_cython.pyx') + + with open(c_file, 'w') as stream: + stream.write(c_file_contents) + + # Always compile the .c (and not the .pyx) file (which we should keep up-to-date by running build_tools/build.py). + from distutils.extension import Extension + extra_compile_args = [] + extra_link_args = [] + + if 'linux' in sys.platform: + # Enabling -flto brings executable from 4MB to 0.56MB and -Os to 0.41MB + # Profiling shows an execution around 3-5% slower with -Os vs -O3, + # so, kept only -flto. + extra_compile_args = ["-flto", "-O3"] + extra_link_args = extra_compile_args[:] + + # Note: also experimented with profile-guided optimization. The executable + # size became a bit smaller (from 0.56MB to 0.5MB) but this would add an + # extra step to run the debugger to obtain the optimizations + # so, skipped it for now (note: the actual benchmarks time was in the + # margin of a 0-1% improvement, which is probably not worth it for + # speed increments). + # extra_compile_args = ["-flto", "-fprofile-generate"] + # ... Run benchmarks ... + # extra_compile_args = ["-flto", "-fprofile-use", "-fprofile-correction"] + elif 'win32' in sys.platform: + pass + # uncomment to generate pdbs for visual studio. + # extra_compile_args=["-Zi", "/Od"] + # extra_link_args=["-debug"] + + kwargs = {} + if extra_link_args: + kwargs['extra_link_args'] = extra_link_args + if extra_compile_args: + kwargs['extra_compile_args'] = extra_compile_args + + ext_modules = [ + Extension( + "%s%s.%s" % (dir_name, "_ext" if extended else "", target_pydevd_name,), + c_files, + **kwargs + )] + + # This is needed in CPython 3.8 to be able to include internal/pycore_pystate.h + # (needed to set PyInterpreterState.eval_frame). + for module in ext_modules: + module.define_macros = [('Py_BUILD_CORE_MODULE', '1')] + setup( + name='Cythonize', + ext_modules=ext_modules + ) + finally: + if target_pydevd_name != extension_name: + try: + os.remove(new_pyx_file) + except: + import traceback + traceback.print_exc() + try: + os.remove(new_c_file) + except: + import traceback + traceback.print_exc() + if has_pxd: + try: + os.remove(new_pxd_file) + except: + import traceback + traceback.print_exc() + + +extension_folder, target_pydevd_name, target_frame_eval, force_cython = process_args() + +extension_name = "pydevd_cython" +if target_pydevd_name is None: + target_pydevd_name = extension_name +build_extension("_pydevd_bundle", extension_name, target_pydevd_name, force_cython, extension_folder, True) + +if IS_PY36_OR_GREATER and not TODO_PY311: + extension_name = "pydevd_frame_evaluator" + if target_frame_eval is None: + target_frame_eval = extension_name + build_extension("_pydevd_frame_eval", extension_name, target_frame_eval, force_cython, extension_folder, True, template=True) + +if extension_folder: + os.chdir(extension_folder) + for folder in [file for file in os.listdir(extension_folder) if + file != 'build' and os.path.isdir(os.path.join(extension_folder, file))]: + file = os.path.join(folder, "__init__.py") + if not os.path.exists(file): + open(file, 'a').close() diff --git a/stubs/_django_manager_body.py b/stubs/_django_manager_body.py new file mode 100644 index 0000000..2bf4706 --- /dev/null +++ b/stubs/_django_manager_body.py @@ -0,0 +1,414 @@ +# This is a dummy for code-completion purposes. + +def __unicode__(self): + """ + Return "app_label.model_label.manager_name". + """ + +def _copy_to_model(self, model): + """ + Makes a copy of the manager and assigns it to 'model', which should be + a child of the existing model (used when inheriting a manager from an + abstract base class). + """ + + +def _db(self): + """ + + """ + + +def _get_queryset_methods(cls, queryset_class): + """ + + """ + + +def _hints(self): + """ + dict() -> new empty dictionary + dict(mapping) -> new dictionary initialized from a mapping object's + (key, value) pairs + dict(iterable) -> new dictionary initialized as if via: + d = {} + for k, v in iterable: + d[k] = v + dict(**kwargs) -> new dictionary initialized with the name=value pairs + in the keyword argument list. For example: dict(one=1, two=2) + """ + + +def _inherited(self): + """ + + """ + + +def _insert(self, *args, **kwargs): + """ + Inserts a new record for the given model. This provides an interface to + the InsertQuery class and is how Model.save() is implemented. + """ + + +def _queryset_class(self): + """ + Represents a lazy database lookup for a set of objects. + """ + + +def _set_creation_counter(self): + """ + Sets the creation counter value for this instance and increments the + class-level copy. + """ + + +def _update(self, *args, **kwargs): + """ + A version of update that accepts field objects instead of field names. + Used primarily for model saving and not intended for use by general + code (it requires too much poking around at model internals to be + useful at that level). + """ + + +def aggregate(self, *args, **kwargs): + """ + Returns a dictionary containing the calculations (aggregation) + over the current queryset + + If args is present the expression is passed as a kwarg using + the Aggregate object's default alias. + """ + + +def all(self): + """ + @rtype: django.db.models.query.QuerySet + """ + + +def annotate(self, *args, **kwargs): + """ + Return a query set in which the returned objects have been annotated + with data aggregated from related fields. + """ + + +def bulk_create(self, *args, **kwargs): + """ + Inserts each of the instances into the database. This does *not* call + save() on each of the instances, does not send any pre/post save + signals, and does not set the primary key attribute if it is an + autoincrement field. + """ + + +def check(self, **kwargs): + """ + + """ + + +def complex_filter(self, *args, **kwargs): + """ + Returns a new QuerySet instance with filter_obj added to the filters. + + filter_obj can be a Q object (or anything with an add_to_query() + method) or a dictionary of keyword lookup arguments. + + This exists to support framework features such as 'limit_choices_to', + and usually it will be more natural to use other methods. + + @rtype: django.db.models.query.QuerySet + """ + + +def contribute_to_class(self, model, name): + """ + + """ + + +def count(self, *args, **kwargs): + """ + Performs a SELECT COUNT() and returns the number of records as an + integer. + + If the QuerySet is already fully cached this simply returns the length + of the cached results set to avoid multiple SELECT COUNT(*) calls. + """ + + +def create(self, *args, **kwargs): + """ + Creates a new object with the given kwargs, saving it to the database + and returning the created object. + """ + + +def creation_counter(self): + """ + + """ + + +def dates(self, *args, **kwargs): + """ + Returns a list of date objects representing all available dates for + the given field_name, scoped to 'kind'. + """ + + +def datetimes(self, *args, **kwargs): + """ + Returns a list of datetime objects representing all available + datetimes for the given field_name, scoped to 'kind'. + """ + + +def db(self): + """ + + """ + + +def db_manager(self, using=None, hints=None): + """ + + """ + + +def defer(self, *args, **kwargs): + """ + Defers the loading of data for certain fields until they are accessed. + The set of fields to defer is added to any existing set of deferred + fields. The only exception to this is if None is passed in as the only + parameter, in which case all deferrals are removed (None acts as a + reset option). + """ + + +def distinct(self, *args, **kwargs): + """ + Returns a new QuerySet instance that will select only distinct results. + + @rtype: django.db.models.query.QuerySet + """ + + +def earliest(self, *args, **kwargs): + """ + + """ + + +def exclude(self, *args, **kwargs): + """ + Returns a new QuerySet instance with NOT (args) ANDed to the existing + set. + + @rtype: django.db.models.query.QuerySet + """ + + +def exists(self, *args, **kwargs): + """ + + """ + + +def extra(self, *args, **kwargs): + """ + Adds extra SQL fragments to the query. + """ + + +def filter(self, *args, **kwargs): + """ + Returns a new QuerySet instance with the args ANDed to the existing + set. + + @rtype: django.db.models.query.QuerySet + """ + + +def first(self, *args, **kwargs): + """ + Returns the first object of a query, returns None if no match is found. + """ + + +def from_queryset(cls, queryset_class, class_name=None): + """ + + """ + + +def get(self, *args, **kwargs): + """ + Performs the query and returns a single object matching the given + keyword arguments. + """ + + +def get_or_create(self, *args, **kwargs): + """ + Looks up an object with the given kwargs, creating one if necessary. + Returns a tuple of (object, created), where created is a boolean + specifying whether an object was created. + """ + + +def get_queryset(self): + """ + Returns a new QuerySet object. Subclasses can override this method to + easily customize the behavior of the Manager. + + @rtype: django.db.models.query.QuerySet + """ + + +def in_bulk(self, *args, **kwargs): + """ + Returns a dictionary mapping each of the given IDs to the object with + that ID. + """ + + +def iterator(self, *args, **kwargs): + """ + An iterator over the results from applying this QuerySet to the + database. + """ + + +def last(self, *args, **kwargs): + """ + Returns the last object of a query, returns None if no match is found. + """ + + +def latest(self, *args, **kwargs): + """ + + """ + + +def model(self): + """ + MyModel(id) + """ + + +def none(self, *args, **kwargs): + """ + Returns an empty QuerySet. + + @rtype: django.db.models.query.QuerySet + """ + + +def only(self, *args, **kwargs): + """ + Essentially, the opposite of defer. Only the fields passed into this + method and that are not already specified as deferred are loaded + immediately when the queryset is evaluated. + """ + + +def order_by(self, *args, **kwargs): + """ + Returns a new QuerySet instance with the ordering changed. + + @rtype: django.db.models.query.QuerySet + """ + + +def prefetch_related(self, *args, **kwargs): + """ + Returns a new QuerySet instance that will prefetch the specified + Many-To-One and Many-To-Many related objects when the QuerySet is + evaluated. + + When prefetch_related() is called more than once, the list of lookups to + prefetch is appended to. If prefetch_related(None) is called, the list + is cleared. + + @rtype: django.db.models.query.QuerySet + """ + + +def raw(self, *args, **kwargs): + """ + + """ + + +def reverse(self, *args, **kwargs): + """ + Reverses the ordering of the QuerySet. + + @rtype: django.db.models.query.QuerySet + """ + + +def select_for_update(self, *args, **kwargs): + """ + Returns a new QuerySet instance that will select objects with a + FOR UPDATE lock. + + @rtype: django.db.models.query.QuerySet + """ + + +def select_related(self, *args, **kwargs): + """ + Returns a new QuerySet instance that will select related objects. + + If fields are specified, they must be ForeignKey fields and only those + related objects are included in the selection. + + If select_related(None) is called, the list is cleared. + + @rtype: django.db.models.query.QuerySet + """ + + +def update(self, *args, **kwargs): + """ + Updates all elements in the current QuerySet, setting all the given + fields to the appropriate values. + """ + + +def update_or_create(self, *args, **kwargs): + """ + Looks up an object with the given kwargs, updating one with defaults + if it exists, otherwise creates a new one. + Returns a tuple (object, created), where created is a boolean + specifying whether an object was created. + """ + + +def using(self, *args, **kwargs): + """ + Selects which database this QuerySet should execute its query against. + + @rtype: django.db.models.query.QuerySet + """ + + +def values(self, *args, **kwargs): + """ + + """ + + +def values_list(self, *args, **kwargs): + """ + + """ + diff --git a/test_pydevd_reload/__init__.py b/test_pydevd_reload/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test_pydevd_reload/test_pydevd_reload.py b/test_pydevd_reload/test_pydevd_reload.py new file mode 100644 index 0000000..067f3da --- /dev/null +++ b/test_pydevd_reload/test_pydevd_reload.py @@ -0,0 +1,573 @@ +import os # @NoMove +import sys # @NoMove +import pytest + +from _pydevd_bundle import pydevd_reload +import tempfile +import unittest + +SAMPLE_CODE = """ +class C: + def foo(self): + return 0 + + @classmethod + def bar(cls): + return (0, 0) + + @staticmethod + def stomp(): + return (0, 0, 0) + + def unchanged(self): + return 'unchanged' +""" + +from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_IRONPYTHON + + +@pytest.mark.skipif(IS_JYTHON or IS_IRONPYTHON, reason='CPython related test') +class Test(unittest.TestCase): + + def setUp(self): + unittest.TestCase.setUp(self) + self.tempdir = None + self.save_path = None + self.tempdir = tempfile.mkdtemp() + self.save_path = list(sys.path) + sys.path.append(self.tempdir) + try: + del sys.modules['x'] + except: + pass + + def tearDown(self): + unittest.TestCase.tearDown(self) + sys.path = self.save_path + try: + del sys.modules['x'] + except: + pass + + def make_mod(self, name="x", repl=None, subst=None, sample=SAMPLE_CODE): + basedir = self.tempdir + if '.' in name: + splitted = name.split('.') + basedir = os.path.join(self.tempdir, *splitted[:-1]) + name = splitted[-1] + try: + os.makedirs(basedir) + except: + pass + + fn = os.path.join(basedir, name + ".py") + f = open(fn, "w") + if repl is not None and subst is not None: + sample = sample.replace(repl, subst) + try: + f.write(sample) + finally: + f.close() + + def test_pydevd_reload(self): + + self.make_mod() + import x # @UnresolvedImport + + C = x.C + COut = C + Cfoo = C.foo + Cbar = C.bar + Cstomp = C.stomp + + def check2(expected): + C = x.C + Cfoo = C.foo + Cbar = C.bar + Cstomp = C.stomp + b = C() + bfoo = b.foo + self.assertEqual(expected, b.foo()) + self.assertEqual(expected, bfoo()) + self.assertEqual(expected, Cfoo(b)) + + def check(expected): + b = COut() + bfoo = b.foo + self.assertEqual(expected, b.foo()) + self.assertEqual(expected, bfoo()) + self.assertEqual(expected, Cfoo(b)) + self.assertEqual((expected, expected), Cbar()) + self.assertEqual((expected, expected, expected), Cstomp()) + check2(expected) + + check(0) + + # modify mod and reload + count = 0 + while count < 1: + count += 1 + self.make_mod(repl="0", subst=str(count)) + pydevd_reload.xreload(x) + check(count) + + def test_pydevd_reload2(self): + + self.make_mod() + import x # @UnresolvedImport + + c = x.C() + cfoo = c.foo + self.assertEqual(0, c.foo()) + self.assertEqual(0, cfoo()) + + self.make_mod(repl="0", subst='1') + pydevd_reload.xreload(x) + self.assertEqual(1, c.foo()) + self.assertEqual(1, cfoo()) + + def test_pydevd_reload3(self): + + class F: + + def m1(self): + return 1 + + class G: + + def m1(self): + return 2 + + self.assertEqual(F().m1(), 1) + pydevd_reload.Reload(None)._update(None, None, F, G) + self.assertEqual(F().m1(), 2) + + def test_pydevd_reload4(self): + + class F: + pass + + F.m1 = lambda a:None + + class G: + pass + + G.m1 = lambda a:10 + + self.assertEqual(F().m1(), None) + pydevd_reload.Reload(None)._update(None, None, F, G) + self.assertEqual(F().m1(), 10) + + def test_if_code_obj_equals(self): + + class F: + + def m1(self): + return 1 + + class G: + + def m1(self): + return 1 + + class H: + + def m1(self): + return 2 + + if hasattr(F.m1, 'func_code'): + self.assertTrue(pydevd_reload.code_objects_equal(F.m1.func_code, G.m1.func_code)) + self.assertFalse(pydevd_reload.code_objects_equal(F.m1.func_code, H.m1.func_code)) + else: + self.assertTrue(pydevd_reload.code_objects_equal(F.m1.__code__, G.m1.__code__)) + self.assertFalse(pydevd_reload.code_objects_equal(F.m1.__code__, H.m1.__code__)) + + def test_metaclass(self): + + class Meta(type): + + def __init__(cls, name, bases, attrs): + super(Meta, cls).__init__(name, bases, attrs) + + class F: + __metaclass__ = Meta + + def m1(self): + return 1 + + class G: + __metaclass__ = Meta + + def m1(self): + return 2 + + self.assertEqual(F().m1(), 1) + pydevd_reload.Reload(None)._update(None, None, F, G) + self.assertEqual(F().m1(), 2) + + def test_change_hierarchy(self): + + class F(object): + + def m1(self): + return 1 + + class B(object): + + def super_call(self): + return 2 + + class G(B): + + def m1(self): + return self.super_call() + + self.assertEqual(F().m1(), 1) + old = pydevd_reload.notify_error + self._called = False + + def on_error(*args): + self._called = True + + try: + pydevd_reload.notify_error = on_error + pydevd_reload.Reload(None)._update(None, None, F, G) + self.assertTrue(self._called) + finally: + pydevd_reload.notify_error = old + + def test_change_hierarchy_old_style(self): + + class F: + + def m1(self): + return 1 + + class B: + + def super_call(self): + return 2 + + class G(B): + + def m1(self): + return self.super_call() + + self.assertEqual(F().m1(), 1) + old = pydevd_reload.notify_error + self._called = False + + def on_error(*args): + self._called = True + + try: + pydevd_reload.notify_error = on_error + pydevd_reload.Reload(None)._update(None, None, F, G) + self.assertTrue(self._called) + finally: + pydevd_reload.notify_error = old + + def test_create_class(self): + SAMPLE_CODE1 = """ +class C: + def foo(self): + return 0 +""" + # Creating a new class and using it from old class + SAMPLE_CODE2 = """ +class B: + pass + +class C: + def foo(self): + return B +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + foo = x.C().foo + self.assertEqual(foo(), 0) + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + self.assertEqual(foo().__name__, 'B') + + def test_create_class2(self): + SAMPLE_CODE1 = """ +class C(object): + def foo(self): + return 0 +""" + # Creating a new class and using it from old class + SAMPLE_CODE2 = """ +class B(object): + pass + +class C(object): + def foo(self): + return B +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + foo = x.C().foo + self.assertEqual(foo(), 0) + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + self.assertEqual(foo().__name__, 'B') + + def test_parent_function(self): + SAMPLE_CODE1 = """ +class B(object): + def foo(self): + return 0 + +class C(B): + def call(self): + return self.foo() +""" + # Creating a new class and using it from old class + SAMPLE_CODE2 = """ +class B(object): + def foo(self): + return 0 + def bar(self): + return 'bar' + +class C(B): + def call(self): + return self.bar() +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + call = x.C().call + self.assertEqual(call(), 0) + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + self.assertEqual(call(), 'bar') + + def test_update_constant(self): + SAMPLE_CODE1 = """ +CONSTANT = 1 + +class B(object): + def foo(self): + return CONSTANT +""" + SAMPLE_CODE2 = """ +CONSTANT = 2 + +class B(object): + def foo(self): + return CONSTANT +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + foo = x.B().foo + self.assertEqual(foo(), 1) + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + self.assertEqual(foo(), 1) # Just making it explicit we don't reload constants. + + def test_update_constant_with_custom_code(self): + SAMPLE_CODE1 = """ +CONSTANT = 1 + +class B(object): + def foo(self): + return CONSTANT +""" + SAMPLE_CODE2 = """ +CONSTANT = 2 + +def __xreload_old_new__(namespace, name, old, new): + if name == 'CONSTANT': + namespace[name] = new + +class B(object): + def foo(self): + return CONSTANT +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + foo = x.B().foo + self.assertEqual(foo(), 1) + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + self.assertEqual(foo(), 2) # Actually updated it now! + + def test_reload_custom_code_after_changes(self): + SAMPLE_CODE1 = """ +CONSTANT = 1 + +class B(object): + def foo(self): + return CONSTANT +""" + SAMPLE_CODE2 = """ +CONSTANT = 1 + +def __xreload_after_reload_update__(namespace): + namespace['CONSTANT'] = 2 + +class B(object): + def foo(self): + return CONSTANT +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + foo = x.B().foo + self.assertEqual(foo(), 1) + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + self.assertEqual(foo(), 2) # Actually updated it now! + + def test_reload_custom_code_after_changes_in_class(self): + SAMPLE_CODE1 = """ + +class B(object): + CONSTANT = 1 + + def foo(self): + return self.CONSTANT +""" + SAMPLE_CODE2 = """ + + +class B(object): + CONSTANT = 1 + + @classmethod + def __xreload_after_reload_update__(cls): + cls.CONSTANT = 2 + + def foo(self): + return self.CONSTANT +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + foo = x.B().foo + self.assertEqual(foo(), 1) + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + self.assertEqual(foo(), 2) # Actually updated it now! + + def test_update_constant_with_custom_code2(self): + SAMPLE_CODE1 = """ + +class B(object): + CONSTANT = 1 + + def foo(self): + return self.CONSTANT +""" + SAMPLE_CODE2 = """ + + +class B(object): + + CONSTANT = 2 + + def __xreload_old_new__(cls, name, old, new): + if name == 'CONSTANT': + cls.CONSTANT = new + __xreload_old_new__ = classmethod(__xreload_old_new__) + + def foo(self): + return self.CONSTANT +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + foo = x.B().foo + self.assertEqual(foo(), 1) + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + self.assertEqual(foo(), 2) # Actually updated it now! + + def test_update_with_slots(self): + SAMPLE_CODE1 = """ +class B(object): + + __slots__ = ['bar'] + +""" + SAMPLE_CODE2 = """ +class B(object): + + __slots__ = ['bar', 'foo'] + + def m1(self): + self.bar = 10 + return 1 + +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + B = x.B + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + b = B() + self.assertEqual(1, b.m1()) + self.assertEqual(10, b.bar) + self.assertRaises(Exception, setattr, b, 'foo', 20) # __slots__ can't be updated + + def test_reload_numpy(self): + SAMPLE_CODE1 = """ +import numpy as np +global_numpy = np.array([1, 2, 3]) +def method(): + return 1 +""" + SAMPLE_CODE2 = """ +import numpy as np +global_numpy = np.array([1, 2, 3, 4]) +def method(): + return 2 +""" + + self.make_mod(sample=SAMPLE_CODE1) + import x # @UnresolvedImport + assert str(x.global_numpy) == '[1 2 3]' + self.make_mod(sample=SAMPLE_CODE2) + pydevd_reload.xreload(x) + # Note that we don't patch globals (the user could do that in a module, + # but he'd have to create a custom `__xreload_old_new__` method to + # do it). + assert str(x.global_numpy) == '[1 2 3]' + + def test_reload_relative(self): + MODULE_CODE = """ +def add_text(s): + return s + " module" +""" + MODULE1_CODE = """ +from . import module + +def add_more_text(s): + s = module.add_text(s) + return s + ' module1' +""" + + MODULE1_CODE_V2 = """ +from . import module + +def add_more_text(s): + s = module.add_text(s) + return s + ' module1V2' +""" + + self.make_mod(sample='', name='package.__init__') + self.make_mod(sample=MODULE_CODE, name='package.module') + self.make_mod(sample=MODULE1_CODE, name='package.module1') + from package import module1 # @UnresolvedImport + assert module1.add_more_text('1') == '1 module module1' + + self.make_mod(sample=MODULE1_CODE_V2, name='package.module1') + pydevd_reload.xreload(module1) + assert module1.add_more_text('1') == '1 module module1V2' diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_check_pydevconsole.py b/tests/test_check_pydevconsole.py new file mode 100644 index 0000000..8795918 --- /dev/null +++ b/tests/test_check_pydevconsole.py @@ -0,0 +1,113 @@ +import threading +import unittest +import os +import pytest +import pydevconsole + +from _pydev_bundle.pydev_imports import xmlrpclib, SimpleXMLRPCServer +from _pydev_bundle.pydev_localhost import get_localhost + +try: + raw_input + raw_input_name = 'raw_input' +except NameError: + raw_input_name = 'input' + +try: + from IPython import core # @UnusedImport + has_ipython = True +except: + has_ipython = False + + +#======================================================================================================================= +# Test +#======================================================================================================================= +@pytest.mark.skipif(os.environ.get('TRAVIS') == 'true' or not has_ipython, reason='Too flaky on Travis (and requires IPython).') +class Test(unittest.TestCase): + + def start_client_thread(self, client_port): + class ClientThread(threading.Thread): + def __init__(self, client_port): + threading.Thread.__init__(self) + self.client_port = client_port + + def run(self): + class HandleRequestInput: + def RequestInput(self): + client_thread.requested_input = True + return 'RequestInput: OK' + + def NotifyFinished(self, *args, **kwargs): + client_thread.notified_finished += 1 + return 1 + + handle_request_input = HandleRequestInput() + + from _pydev_bundle import pydev_localhost + self.client_server = client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False) + client_server.register_function(handle_request_input.RequestInput) + client_server.register_function(handle_request_input.NotifyFinished) + client_server.serve_forever() + + def shutdown(self): + return + self.client_server.shutdown() + + client_thread = ClientThread(client_port) + client_thread.requested_input = False + client_thread.notified_finished = 0 + client_thread.daemon = True + client_thread.start() + return client_thread + + + def get_free_addresses(self): + from _pydev_bundle.pydev_localhost import get_socket_names + socket_names = get_socket_names(2, close=True) + return [socket_name[1] for socket_name in socket_names] + + def test_server(self): + # Just making sure that the singleton is created in this thread. + from _pydev_bundle.pydev_ipython_console_011 import get_pydev_frontend + get_pydev_frontend(get_localhost(), 0) + + client_port, server_port = self.get_free_addresses() + class ServerThread(threading.Thread): + def __init__(self, client_port, server_port): + threading.Thread.__init__(self) + self.client_port = client_port + self.server_port = server_port + + def run(self): + from _pydev_bundle import pydev_localhost + print('Starting server with:', pydev_localhost.get_localhost(), self.server_port, self.client_port) + pydevconsole.start_server(pydev_localhost.get_localhost(), self.server_port, self.client_port) + server_thread = ServerThread(client_port, server_port) + server_thread.daemon = True + server_thread.start() + + client_thread = self.start_client_thread(client_port) #@UnusedVariable + + try: + import time + time.sleep(.3) #let's give it some time to start the threads + + from _pydev_bundle import pydev_localhost + server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), server_port)) + server.execLine("import sys; print('Running with: %s %s' % (sys.executable or sys.platform, sys.version))") + server.execLine('class Foo:') + server.execLine(' pass') + server.execLine('') + server.execLine('foo = Foo()') + server.execLine('a = %s()' % raw_input_name) + initial = time.time() + while not client_thread.requested_input: + if time.time() - initial > 2: + raise AssertionError('Did not get the return asked before the timeout.') + time.sleep(.1) + frame_xml = server.getFrame() + self.assertTrue('RequestInput' in frame_xml, 'Did not fid RequestInput in:\n%s' % (frame_xml,)) + finally: + client_thread.shutdown() + diff --git a/tests/test_get_referrers.py b/tests/test_get_referrers.py new file mode 100644 index 0000000..c4f7c14 --- /dev/null +++ b/tests/test_get_referrers.py @@ -0,0 +1,125 @@ +import sys +import threading +import time +import unittest +import pytest +from _pydevd_bundle import pydevd_referrers +from io import StringIO +from tests_python.debugger_unittest import IS_PYPY + +try: + import gc + gc.get_referrers(unittest) + has_referrers = True +except NotImplementedError: + has_referrers = False + + +# Only do get referrers tests if it's actually available. +@pytest.mark.skipif(not has_referrers or IS_PYPY, reason='gc.get_referrers not implemented') +class Test(unittest.TestCase): + + def test_get_referrers1(self): + + container = [] + contained = [1, 2] + container.append(0) + container.append(contained) + + # Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too). + # we should skip temporary references inside the get_referrer_info. + result = pydevd_referrers.get_referrer_info(contained) + assert 'list[1]' in result + pydevd_referrers.print_referrers(contained, stream=StringIO()) + + def test_get_referrers2(self): + + class MyClass(object): + + def __init__(self): + pass + + contained = [1, 2] + obj = MyClass() + obj.contained = contained + del contained + + # Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too). + # we should skip temporary references inside the get_referrer_info. + result = pydevd_referrers.get_referrer_info(obj.contained) + assert 'found_as="contained"' in result + assert 'MyClass' in result + + def test_get_referrers3(self): + + class MyClass(object): + + def __init__(self): + pass + + contained = [1, 2] + obj = MyClass() + obj.contained = contained + del contained + + # Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too). + # we should skip temporary references inside the get_referrer_info. + result = pydevd_referrers.get_referrer_info(obj.contained) + assert 'found_as="contained"' in result + assert 'MyClass' in result + + def test_get_referrers4(self): + + class MyClass(object): + + def __init__(self): + pass + + obj = MyClass() + obj.me = obj + + # Let's see if we detect the cycle... + result = pydevd_referrers.get_referrer_info(obj) + assert 'found_as="me"' in result # Cyclic ref + + def test_get_referrers5(self): + container = dict(a=[1]) + + # Let's see if we detect the cycle... + result = pydevd_referrers.get_referrer_info(container['a']) + assert 'test_get_referrers5' not in result # I.e.: NOT in the current method + assert 'found_as="a"' in result + assert 'dict' in result + assert str(id(container)) in result + + def test_get_referrers6(self): + import sys + container = dict(a=[1]) + + def should_appear(obj): + # Let's see if we detect the cycle... + return pydevd_referrers.get_referrer_info(obj) + + result = should_appear(container['a']) + if sys.version_info[:2] >= (3, 7): + # In Python 3.7 the frame is not appearing in gc.get_referrers. + assert 'should_appear' not in result + else: + assert 'should_appear' in result + + def test_get_referrers7(self): + + class MyThread(threading.Thread): + + def run(self): + # Note: we do that because if we do + self.frame = sys._getframe() + + t = MyThread() + t.start() + while not hasattr(t, 'frame'): + time.sleep(0.01) + + result = pydevd_referrers.get_referrer_info(t.frame) + assert 'MyThread' in result + diff --git a/tests/test_jyserver.py b/tests/test_jyserver.py new file mode 100644 index 0000000..7e7a9f5 --- /dev/null +++ b/tests/test_jyserver.py @@ -0,0 +1,140 @@ +''' +@author Fabio Zadrozny +''' +import sys +import unittest +import socket +import urllib +import pytest +import pycompletionserver + + +IS_JYTHON = sys.platform.find('java') != -1 +DEBUG = 0 + +def dbg(s): + if DEBUG: + sys.stdout.write('TEST %s\n' % s) + +@pytest.mark.skipif(not IS_JYTHON, reason='Jython related test') +class TestJython(unittest.TestCase): + + def test_it(self): + dbg('ok') + + + def test_message(self): + t = pycompletionserver.CompletionServer(0) + t.exit_process_on_kill = False + + l = [] + l.append(('Def', 'description' , 'args')) + l.append(('Def1', 'description1', 'args1')) + l.append(('Def2', 'description2', 'args2')) + + msg = t.processor.format_completion_message('test_jyserver.py', l) + + self.assertEqual('@@COMPLETIONS(test_jyserver.py,(Def,description,args),(Def1,description1,args1),(Def2,description2,args2))END@@', msg) + + l = [] + l.append(('Def', 'desc,,r,,i()ption', '')) + l.append(('Def(1', 'descriptio(n1', '')) + l.append(('De,f)2', 'de,s,c,ription2', '')) + msg = t.processor.format_completion_message(None, l) + expected = '@@COMPLETIONS(None,(Def,desc%2C%2Cr%2C%2Ci%28%29ption, ),(Def%281,descriptio%28n1, ),(De%2Cf%292,de%2Cs%2Cc%2Cription2, ))END@@' + + self.assertEqual(expected, msg) + + + def test_completion_sockets_and_messages(self): + dbg('test_completion_sockets_and_messages') + t, socket = self.create_connections() + self.socket = socket + dbg('connections created') + + try: + #now that we have the connections all set up, check the code completion messages. + msg = urllib.quote_plus('math') + + toWrite = '@@IMPORTS:%sEND@@' % msg + dbg('writing' + str(toWrite)) + socket.send(toWrite) #math completions + completions = self.read_msg() + dbg(urllib.unquote_plus(completions)) + + start = '@@COMPLETIONS(' + self.assertTrue(completions.startswith(start), '%s DOESNT START WITH %s' % (completions, start)) + self.assertTrue(completions.find('@@COMPLETIONS') != -1) + self.assertTrue(completions.find('END@@') != -1) + + + msg = urllib.quote_plus('__builtin__.str') + toWrite = '@@IMPORTS:%sEND@@' % msg + dbg('writing' + str(toWrite)) + socket.send(toWrite) #math completions + completions = self.read_msg() + dbg(urllib.unquote_plus(completions)) + + start = '@@COMPLETIONS(' + self.assertTrue(completions.startswith(start), '%s DOESNT START WITH %s' % (completions, start)) + self.assertTrue(completions.find('@@COMPLETIONS') != -1) + self.assertTrue(completions.find('END@@') != -1) + + + + finally: + try: + self.send_kill_msg(socket) + + + while not t.ended: + pass #wait until it receives the message and quits. + + + socket.close() + except: + pass + + def get_free_port(self): + from _pydev_bundle.pydev_localhost import get_socket_name + return get_socket_name(close=True)[1] + + def create_connections(self): + ''' + Creates the connections needed for testing. + ''' + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server.bind((pycompletionserver.HOST, 0)) + server.listen(1) #socket to receive messages. + + from thread import start_new_thread + t = pycompletionserver.CompletionServer(server.getsockname()[1]) + t.exit_process_on_kill = False + + start_new_thread(t.run, ()) + + sock, _addr = server.accept() + + return t, sock + + def read_msg(self): + msg = '@@PROCESSING_END@@' + while msg.startswith('@@PROCESSING'): + msg = self.socket.recv(1024) + if msg.startswith('@@PROCESSING:'): + dbg('Status msg:' + str(msg)) + + while msg.find('END@@') == -1: + msg += self.socket.recv(1024) + + return msg + + def send_kill_msg(self, socket): + socket.send(pycompletionserver.MSG_KILL_SERVER) + + + + +# Run for jython in command line: +# c:\bin\jython2.7.0\bin\jython.exe -m py.test tests\test_jyserver.py diff --git a/tests/test_jysimpleTipper.py b/tests/test_jysimpleTipper.py new file mode 100644 index 0000000..a1790cf --- /dev/null +++ b/tests/test_jysimpleTipper.py @@ -0,0 +1,242 @@ +import unittest +import os +import sys +import pytest + +# Note: ant.jar and junit.jar must be in the PYTHONPATH (see jython_test_deps) + +IS_JYTHON = False +if sys.platform.find('java') != -1: + IS_JYTHON = True + from _pydev_bundle._pydev_jy_imports_tipper import ismethod + from _pydev_bundle._pydev_jy_imports_tipper import isclass + from _pydev_bundle._pydev_jy_imports_tipper import dir_obj + from _pydev_bundle import _pydev_jy_imports_tipper + from java.lang.reflect import Method # @UnresolvedImport + from java.lang import System # @UnresolvedImport + from java.lang import String # @UnresolvedImport + from java.lang.System import arraycopy # @UnresolvedImport + from java.lang.System import out # @UnresolvedImport + import java.lang.String # @UnresolvedImport + import org.python.core.PyDictionary # @UnresolvedImport + +__DBG = 0 + + +def dbg(s): + if __DBG: + sys.stdout.write('%s\n' % (s,)) + + +@pytest.mark.skipif(not IS_JYTHON, reason='Jython related test') +class TestMod(unittest.TestCase): + + def assert_args(self, tok, args, tips): + for a in tips: + if tok == a[0]: + self.assertEqual(args, a[2]) + return + raise AssertionError('%s not in %s', tok, tips) + + def assert_in(self, tok, tips): + self.assertEqual(4, len(tips[0])) + for a in tips: + if tok == a[0]: + return a + s = '' + for a in tips: + s += str(a) + s += '\n' + raise AssertionError('%s not in %s' % (tok, s)) + + def test_imports1a(self): + f, tip = _pydev_jy_imports_tipper.generate_tip('java.util.HashMap') + if f is None: + return # Not ok with java 9 + + assert f.endswith('rt.jar') + + def test_imports1c(self): + f, tip = _pydev_jy_imports_tipper.generate_tip('java.lang.Class') + if f is None: + return # Not ok with java 9 + assert f.endswith('rt.jar') + + def test_imports1b(self): + try: + f, tip = _pydev_jy_imports_tipper.generate_tip('__builtin__.m') + self.fail('err') + except: + pass + + def test_imports1(self): + f, tip = _pydev_jy_imports_tipper.generate_tip('junit.framework.TestCase') + assert f.endswith('junit.jar') + ret = self.assert_in('assertEquals', tip) +# self.assertEqual('', ret[2]) + + def test_imports2(self): + f, tip = _pydev_jy_imports_tipper.generate_tip('junit.framework') + assert f.endswith('junit.jar') + ret = self.assert_in('TestCase', tip) + self.assertEqual('', ret[2]) + + def test_imports2a(self): + f, tip = _pydev_jy_imports_tipper.generate_tip('org.apache.tools.ant') + assert f.endswith('ant.jar') + ret = self.assert_in('Task', tip) + self.assertEqual('', ret[2]) + + def test_imports3(self): + f, tip = _pydev_jy_imports_tipper.generate_tip('os') + assert f.endswith('os.py') + ret = self.assert_in('path', tip) + self.assertEqual('', ret[2]) + + def test_tip_on_string(self): + f, tip = _pydev_jy_imports_tipper.generate_tip('string') + self.assert_in('join', tip) + self.assert_in('uppercase', tip) + + def test_imports(self): + tip = _pydev_jy_imports_tipper.generate_tip('__builtin__')[1] + self.assert_in('tuple' , tip) + self.assert_in('RuntimeError' , tip) + self.assert_in('RuntimeWarning' , tip) + + def test_imports5(self): + f, tip = _pydev_jy_imports_tipper.generate_tip('java.lang') + if f is None: + return # Not ok with java 9 + assert f.endswith('rt.jar') + tup = self.assert_in('String' , tip) + self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_CLASS), tup[3]) + + tip = _pydev_jy_imports_tipper.generate_tip('java')[1] + tup = self.assert_in('lang' , tip) + self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_IMPORT), tup[3]) + + tip = _pydev_jy_imports_tipper.generate_tip('java.lang.String')[1] + tup = self.assert_in('indexOf' , tip) + self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3]) + + tip = _pydev_jy_imports_tipper.generate_tip('java.lang.String')[1] + tup = self.assert_in('charAt' , tip) + self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3]) + self.assertEqual('(int)', tup[2]) + + tup = self.assert_in('format' , tip) + self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3]) + self.assertEqual('(string, objectArray)', tup[2]) + self.assertTrue(tup[1].find('[Ljava.lang.Object;') == -1) + + tup = self.assert_in('getBytes', tip) + self.assertEqual(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3]) + assert '[B' not in tup[1] + assert 'byte[]' in tup[1] + + f, tip = _pydev_jy_imports_tipper.generate_tip('__builtin__.str') + assert f is None or f.endswith('jython.jar') # Depends on jython version + self.assert_in('find' , tip) + + f, tip = _pydev_jy_imports_tipper.generate_tip('__builtin__.dict') + assert f is None or f.endswith('jython.jar') # Depends on jython version + self.assert_in('get' , tip) + + +@pytest.mark.skipif(not IS_JYTHON, reason='Jython related test') +class TestSearch(unittest.TestCase): + + def test_search_on_jython(self): + assert _pydev_jy_imports_tipper.search_definition('os')[0][0].split(os.sep)[-1] in ('javaos.py', 'os.py') + self.assertEqual(0, _pydev_jy_imports_tipper.search_definition('os')[0][1]) + + assert _pydev_jy_imports_tipper.search_definition('os.makedirs')[0][0].split(os.sep)[-1] in ('javaos.py', 'os.py') + self.assertNotEqual(0, _pydev_jy_imports_tipper.search_definition('os.makedirs')[0][1]) + + # print _pydev_jy_imports_tipper.search_definition('os.makedirs') + + +@pytest.mark.skipif(not IS_JYTHON, reason='Jython related test') +class TestCompl(unittest.TestCase): + + def test_getting_info_on_jython(self): + + dbg('\n\n--------------------------- java') + assert not ismethod(java)[0] + assert not isclass(java) + assert _pydev_jy_imports_tipper.ismodule(java) + + dbg('\n\n--------------------------- java.lang') + assert not ismethod(java.lang)[0] + assert not isclass(java.lang) + assert _pydev_jy_imports_tipper.ismodule(java.lang) + + dbg('\n\n--------------------------- Method') + assert not ismethod(Method)[0] + assert isclass(Method) + + dbg('\n\n--------------------------- System') + assert not ismethod(System)[0] + assert isclass(System) + + dbg('\n\n--------------------------- String') + assert not ismethod(System)[0] + assert isclass(String) + assert len(dir_obj(String)) > 10 + + dbg('\n\n--------------------------- arraycopy') + isMet = ismethod(arraycopy) + assert isMet[0] + assert isMet[1][0].basic_as_str() == "function:arraycopy args=['java.lang.Object', 'int', 'java.lang.Object', 'int', 'int'], varargs=None, kwargs=None, docs:None" + assert not isclass(arraycopy) + + dbg('\n\n--------------------------- out') + isMet = ismethod(out) + assert not isMet[0] + assert not isclass(out) + + dbg('\n\n--------------------------- out.println') + isMet = ismethod(out.println) # @UndefinedVariable + assert isMet[0] + assert len(isMet[1]) == 10 + self.assertEqual(isMet[1][0].basic_as_str(), "function:println args=[], varargs=None, kwargs=None, docs:None") + assert isMet[1][1].basic_as_str() == "function:println args=['long'], varargs=None, kwargs=None, docs:None" + assert not isclass(out.println) # @UndefinedVariable + + dbg('\n\n--------------------------- str') + isMet = ismethod(str) + # the code below should work, but is failing on jython 22a1 + # assert isMet[0] + # assert isMet[1][0].basic_as_str() == "function:str args=['org.python.core.PyObject'], varargs=None, kwargs=None, docs:None" + assert not isclass(str) + + def met1(): + a = 3 + return a + + dbg('\n\n--------------------------- met1') + isMet = ismethod(met1) + assert isMet[0] + assert isMet[1][0].basic_as_str() == "function:met1 args=[], varargs=None, kwargs=None, docs:None" + assert not isclass(met1) + + def met2(arg1, arg2, *vararg, **kwarg): + '''docmet2''' + + a = 1 + return a + + dbg('\n\n--------------------------- met2') + isMet = ismethod(met2) + assert isMet[0] + assert isMet[1][0].basic_as_str() == "function:met2 args=['arg1', 'arg2'], varargs=vararg, kwargs=kwarg, docs:docmet2" + assert not isclass(met2) + +# Run for jython in command line: + +# On Windows: +# c:/bin/jython2.7.0/bin/jython.exe -Dpython.path=jython_test_deps/ant.jar;jython_test_deps/junit.jar -m py.test tests/test_jysimpleTipper.py + +# On Linux (different path separator for jars) +# jython -Dpython.path=jython_test_deps/ant.jar:jython_test_deps/junit.jar -m py.test tests/test_jysimpleTipper.py diff --git a/tests/test_pydev_ipython_011.py b/tests/test_pydev_ipython_011.py new file mode 100644 index 0000000..030dc4a --- /dev/null +++ b/tests/test_pydev_ipython_011.py @@ -0,0 +1,308 @@ +import sys +import unittest +import threading +import os +from _pydev_bundle.pydev_imports import SimpleXMLRPCServer +from _pydev_bundle.pydev_localhost import get_localhost +from _pydev_bundle.pydev_console_utils import StdIn +import socket +import time +from _pydevd_bundle import pydevd_io +import pytest + + +def eq_(a, b): + if a != b: + raise AssertionError('%s != %s' % (a, b)) + + +try: + from IPython import core + has_ipython = True +except: + has_ipython = False + + +@pytest.mark.skipif(not has_ipython, reason='IPython not available') +class TestBase(unittest.TestCase): + + def setUp(self): + from _pydev_bundle.pydev_ipython_console_011 import get_pydev_frontend + + # PyDevFrontEnd depends on singleton in IPython, so you + # can't make multiple versions. So we reuse self.front_end for + # all the tests + self.front_end = get_pydev_frontend(get_localhost(), 0) + + from pydev_ipython.inputhook import set_return_control_callback + set_return_control_callback(lambda:True) + self.front_end.clear_buffer() + + def tearDown(self): + pass + + def add_exec(self, code, expected_more=False): + more = self.front_end.add_exec(code) + eq_(expected_more, more) + + def redirect_stdout(self): + from IPython.utils import io + + self.original_stdout = sys.stdout + sys.stdout = io.stdout = pydevd_io.IOBuf() + + def restore_stdout(self): + from IPython.utils import io + io.stdout = sys.stdout = self.original_stdout + + +@pytest.mark.skipif(not has_ipython, reason='IPython not available') +class TestPyDevFrontEnd(TestBase): + + def testAddExec_1(self): + self.add_exec('if True:', True) + + def testAddExec_2(self): + # Change: 'more' must now be controlled in the client side after the initial 'True' returned. + self.add_exec('if True:\n testAddExec_a = 10\n', False) + assert 'testAddExec_a' in self.front_end.get_namespace() + + def testAddExec_3(self): + assert 'testAddExec_x' not in self.front_end.get_namespace() + self.add_exec('if True:\n testAddExec_x = 10\n\n') + assert 'testAddExec_x' in self.front_end.get_namespace() + eq_(self.front_end.get_namespace()['testAddExec_x'], 10) + + def test_get_namespace(self): + assert 'testGetNamespace_a' not in self.front_end.get_namespace() + self.add_exec('testGetNamespace_a = 10') + assert 'testGetNamespace_a' in self.front_end.get_namespace() + eq_(self.front_end.get_namespace()['testGetNamespace_a'], 10) + + def test_complete(self): + unused_text, matches = self.front_end.complete('%') + assert len(matches) > 1, 'at least one magic should appear in completions' + + def test_complete_does_not_do_python_matches(self): + # Test that IPython's completions do not do the things that + # PyDev's completions will handle + self.add_exec('testComplete_a = 5') + self.add_exec('testComplete_b = 10') + self.add_exec('testComplete_c = 15') + unused_text, matches = self.front_end.complete('testComplete_') + assert len(matches) == 0 + + def testGetCompletions_1(self): + # Test the merged completions include the standard completions + self.add_exec('testComplete_a = 5') + self.add_exec('testComplete_b = 10') + self.add_exec('testComplete_c = 15') + res = self.front_end.getCompletions('testComplete_', 'testComplete_') + matches = [f[0] for f in res] + assert len(matches) == 3 + eq_(set(['testComplete_a', 'testComplete_b', 'testComplete_c']), set(matches)) + + def testGetCompletions_2(self): + # Test that we get IPython completions in results + # we do this by checking kw completion which PyDev does + # not do by default + self.add_exec('def ccc(ABC=123): pass') + res = self.front_end.getCompletions('ccc(', '') + matches = [f[0] for f in res] + assert 'ABC=' in matches + + def testGetCompletions_3(self): + # Test that magics return IPYTHON magic as type + res = self.front_end.getCompletions('%cd', '%cd') + assert len(res) == 1 + eq_(res[0][3], '12') # '12' == IToken.TYPE_IPYTHON_MAGIC + assert len(res[0][1]) > 100, 'docstring for %cd should be a reasonably long string' + + +@pytest.mark.skipif(not has_ipython, reason='IPython not available') +class TestRunningCode(TestBase): + + def test_print(self): + self.redirect_stdout() + try: + self.add_exec('print("output")') + eq_(sys.stdout.getvalue(), 'output\n') + finally: + self.restore_stdout() + + def testQuestionMark_1(self): + self.redirect_stdout() + try: + self.add_exec('?') + found = sys.stdout.getvalue() + if len(found) < 1000: + raise AssertionError('Expected IPython help to be big. Found: %s' % (found,)) + finally: + self.restore_stdout() + + def testQuestionMark_2(self): + self.redirect_stdout() + try: + self.add_exec('int?') + found = sys.stdout.getvalue() + if 'Convert' not in found: + raise AssertionError('Expected to find "Convert" in %s' % (found,)) + finally: + self.restore_stdout() + + def test_gui(self): + try: + import Tkinter + except: + return + else: + from pydev_ipython.inputhook import get_inputhook + assert get_inputhook() is None + self.add_exec('%gui tk') + # we can't test the GUI works here because we aren't connected to XML-RPC so + # nowhere for hook to run + assert get_inputhook() is not None + self.add_exec('%gui none') + assert get_inputhook() is None + + def test_history(self): + ''' Make sure commands are added to IPython's history ''' + self.redirect_stdout() + try: + self.add_exec('a=1') + self.add_exec('b=2') + _ih = self.front_end.get_namespace()['_ih'] + eq_(_ih[-1], 'b=2') + eq_(_ih[-2], 'a=1') + + self.add_exec('history') + hist = sys.stdout.getvalue().split('\n') + eq_(hist[-1], '') + eq_(hist[-2], 'history') + eq_(hist[-3], 'b=2') + eq_(hist[-4], 'a=1') + finally: + self.restore_stdout() + + def test_edit(self): + ''' Make sure we can issue an edit command''' + if os.environ.get('TRAVIS') == 'true': + # This test is too flaky on travis. + return + + from _pydev_bundle.pydev_ipython_console_011 import get_pydev_frontend + + called_RequestInput = [False] + called_IPythonEditor = [False] + + def start_client_thread(client_port): + + class ClientThread(threading.Thread): + + def __init__(self, client_port): + threading.Thread.__init__(self) + self.client_port = client_port + + def run(self): + + class HandleRequestInput: + + def RequestInput(self): + called_RequestInput[0] = True + return '\n' + + def IPythonEditor(self, name, line): + called_IPythonEditor[0] = (name, line) + return True + + handle_request_input = HandleRequestInput() + + from _pydev_bundle import pydev_localhost + self.client_server = client_server = SimpleXMLRPCServer( + (pydev_localhost.get_localhost(), self.client_port), logRequests=False) + client_server.register_function(handle_request_input.RequestInput) + client_server.register_function(handle_request_input.IPythonEditor) + client_server.serve_forever() + + def shutdown(self): + return + self.client_server.shutdown() + + client_thread = ClientThread(client_port) + client_thread.daemon = True + client_thread.start() + return client_thread + + # PyDevFrontEnd depends on singleton in IPython, so you + # can't make multiple versions. So we reuse self.front_end for + # all the tests + s = socket.socket() + s.bind(('', 0)) + self.client_port = client_port = s.getsockname()[1] + s.close() + self.front_end = get_pydev_frontend(get_localhost(), client_port) + + client_thread = start_client_thread(self.client_port) + orig_stdin = sys.stdin + sys.stdin = StdIn(self, get_localhost(), self.client_port) + try: + filename = 'made_up_file.py' + self.add_exec('%edit ' + filename) + + for i in range(10): + if called_IPythonEditor[0] == (os.path.abspath(filename), '0'): + break + time.sleep(.1) + + if not called_IPythonEditor[0]: + # File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/interactiveshell.py", line 2883, in run_code + # exec(code_obj, self.user_global_ns, self.user_ns) + # File "", line 1, in + # get_ipython().magic('edit made_up_file.py') + # File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/interactiveshell.py", line 2205, in magic + # return self.run_line_magic(magic_name, magic_arg_s) + # File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/interactiveshell.py", line 2126, in run_line_magic + # result = fn(*args,**kwargs) + # File "", line 2, in edit + # File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/magic.py", line 193, in + # call = lambda f, *a, **k: f(*a, **k) + # File "/home/travis/miniconda/lib/python3.3/site-packages/IPython/core/magics/code.py", line 662, in edit + # self.shell.hooks.editor(filename,lineno) + # File "/home/travis/build/fabioz/PyDev.Debugger/pydev_ipython_console_011.py", line 70, in call_editor + # server.IPythonEditor(filename, str(line)) + # File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1090, in __call__ + # return self.__send(self.__name, args) + # File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1419, in __request + # verbose=self.__verbose + # File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1132, in request + # return self.single_request(host, handler, request_body, verbose) + # File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1143, in single_request + # http_conn = self.send_request(host, handler, request_body, verbose) + # File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1255, in send_request + # self.send_content(connection, request_body) + # File "/home/travis/miniconda/lib/python3.3/xmlrpc/client.py", line 1285, in send_content + # connection.endheaders(request_body) + # File "/home/travis/miniconda/lib/python3.3/http/client.py", line 1061, in endheaders + # self._send_output(message_body) + # File "/home/travis/miniconda/lib/python3.3/http/client.py", line 906, in _send_output + # self.send(msg) + # File "/home/travis/miniconda/lib/python3.3/http/client.py", line 844, in send + # self.connect() + # File "/home/travis/miniconda/lib/python3.3/http/client.py", line 822, in connect + # self.timeout, self.source_address) + # File "/home/travis/miniconda/lib/python3.3/socket.py", line 435, in create_connection + # raise err + # File "/home/travis/miniconda/lib/python3.3/socket.py", line 426, in create_connection + # sock.connect(sa) + # ConnectionRefusedError: [Errno 111] Connection refused + + # I.e.: just warn that the test failing, don't actually fail. + sys.stderr.write('Test failed: this test is brittle in travis because sometimes the connection is refused (as above) and we do not have a callback.\n') + return + + eq_(called_IPythonEditor[0], (os.path.abspath(filename), '0')) + assert called_RequestInput[0], "Make sure the 'wait' parameter has been respected" + finally: + sys.stdin = orig_stdin + client_thread.shutdown() + diff --git a/tests/test_pydevconsole.py b/tests/test_pydevconsole.py new file mode 100644 index 0000000..bbfc16e --- /dev/null +++ b/tests/test_pydevconsole.py @@ -0,0 +1,277 @@ +import threading +import unittest +import sys +import pydevconsole +from _pydev_bundle.pydev_imports import xmlrpclib, SimpleXMLRPCServer +from _pydevd_bundle import pydevd_io +from contextlib import contextmanager +import pytest + +try: + from ast import PyCF_ALLOW_TOP_LEVEL_AWAIT # @UnusedImport + CAN_EVALUATE_TOP_LEVEL_ASYNC = True +except: + CAN_EVALUATE_TOP_LEVEL_ASYNC = False + + +#======================================================================================================================= +# Test +#======================================================================================================================= +class Test(unittest.TestCase): + + @contextmanager + def interpreter(self): + self.original_stdout = sys.stdout + self.original_stderr = sys.stderr + sys.stdout = pydevd_io.IOBuf() + sys.stderr = pydevd_io.IOBuf() + try: + sys.stdout.encoding = sys.stdin.encoding + sys.stderr.encoding = sys.stdin.encoding + except AttributeError: + # In Python 3 encoding is not writable (whereas in Python 2 it doesn't exist). + pass + + try: + client_port, _server_port = self.get_free_addresses() + client_thread = self.start_client_thread(client_port) # @UnusedVariable + import time + time.sleep(.3) # let's give it some time to start the threads + + from _pydev_bundle import pydev_localhost + interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.current_thread()) + yield interpreter + except: + # if there's some error, print the output to the actual output. + self.original_stdout.write(sys.stdout.getvalue()) + self.original_stderr.write(sys.stderr.getvalue()) + raise + finally: + sys.stderr = self.original_stderr + sys.stdout = self.original_stdout + + def test_console_hello(self): + with self.interpreter() as interpreter: + (result,) = interpreter.hello("Hello pydevconsole") + self.assertEqual(result, "Hello eclipse") + + @pytest.mark.skipif(not CAN_EVALUATE_TOP_LEVEL_ASYNC, reason='Requires top-level async.') + def test_console_async(self): + with self.interpreter() as interpreter: + from _pydev_bundle.pydev_console_utils import CodeFragment + more = interpreter.add_exec(CodeFragment(''' +async def async_func(a): + return a +''')) + assert not more + assert not sys.stderr.getvalue() + assert not sys.stdout.getvalue() + + more = interpreter.add_exec(CodeFragment('''x = await async_func(1111)''')) + assert not more + assert not sys.stderr.getvalue() + assert not sys.stdout.getvalue() + + more = interpreter.add_exec(CodeFragment('''print(x)''')) + assert not more + assert not sys.stderr.getvalue() + assert '1111' in sys.stdout.getvalue() + + def test_console_requests(self): + with self.interpreter() as interpreter: + from _pydev_bundle.pydev_console_utils import CodeFragment + interpreter.add_exec(CodeFragment('class Foo:\n CONSTANT=1\n')) + interpreter.add_exec(CodeFragment('foo=Foo()')) + interpreter.add_exec(CodeFragment('foo.__doc__=None')) + interpreter.add_exec(CodeFragment('val = input()')) + interpreter.add_exec(CodeFragment('50')) + interpreter.add_exec(CodeFragment('print (val)')) + found = sys.stdout.getvalue().split() + try: + self.assertEqual(['50', 'input_request'], found) + except: + try: + self.assertEqual(['input_request'], found) # IPython + except: + self.assertEqual([u'50', u'input_request'], found[1:]) # IPython 5.1 + self.assertTrue(found[0].startswith(u'Out')) + + comps = interpreter.getCompletions('foo.', 'foo.') + self.assertTrue( + ('CONSTANT', '', '', '3') in comps or ('CONSTANT', '', '', '4') in comps, \ + 'Found: %s' % comps + ) + + comps = interpreter.getCompletions('"".', '"".') + self.assertTrue( + ('__add__', 'x.__add__(y) <==> x+y', '', '3') in comps or + ('__add__', '', '', '4') in comps or + ('__add__', 'x.__add__(y) <==> x+y\r\nx.__add__(y) <==> x+y', '()', '2') in comps or + ('__add__', 'x.\n__add__(y) <==> x+yx.\n__add__(y) <==> x+y', '()', '2'), + 'Did not find __add__ in : %s' % (comps,) + ) + + completions = interpreter.getCompletions('', '') + for c in completions: + if c[0] == 'AssertionError': + break + else: + self.fail('Could not find AssertionError') + + completions = interpreter.getCompletions('Assert', 'Assert') + for c in completions: + if c[0] == 'RuntimeError': + self.fail('Did not expect to find RuntimeError there') + + assert ('__doc__', None, '', '3') not in interpreter.getCompletions('foo.CO', 'foo.') + + comps = interpreter.getCompletions('va', 'va') + assert ('val', '', '', '3') in comps or ('val', '', '', '4') in comps + + interpreter.add_exec(CodeFragment('s = "mystring"')) + + desc = interpreter.getDescription('val') + self.assertTrue(desc.find('str(object) -> string') >= 0 or + desc == "'input_request'" or + desc.find('str(string[, encoding[, errors]]) -> str') >= 0 or + desc.find('str(Char* value)') >= 0 or + desc.find('str(object=\'\') -> string') >= 0 or + desc.find('str(value: Char*)') >= 0 or + desc.find('str(object=\'\') -> str') >= 0 or + desc.find('The most base type') >= 0 # Jython 2.7 is providing this :P + , + 'Could not find what was needed in %s' % desc) + + desc = interpreter.getDescription('val.join') + self.assertTrue(desc.find('S.join(sequence) -> string') >= 0 or + desc.find('S.join(sequence) -> str') >= 0 or + desc.find('S.join(iterable) -> string') >= 0 or + desc == "" or + desc == "" or + desc.find('str join(str self, list sequence)') >= 0 or + desc.find('S.join(iterable) -> str') >= 0 or + desc.find('join(self: str, sequence: list) -> str') >= 0 or + desc.find('Concatenate any number of strings.') >= 0 or + desc.find('bound method str.join') >= 0, # PyPy + "Could not recognize: %s" % (desc,)) + + def start_client_thread(self, client_port): + + class ClientThread(threading.Thread): + + def __init__(self, client_port): + threading.Thread.__init__(self) + self.client_port = client_port + + def run(self): + + class HandleRequestInput: + + def RequestInput(self): + client_thread.requested_input = True + return 'input_request' + + def NotifyFinished(self, *args, **kwargs): + client_thread.notified_finished += 1 + return 1 + + handle_request_input = HandleRequestInput() + + from _pydev_bundle import pydev_localhost + client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False) + client_server.register_function(handle_request_input.RequestInput) + client_server.register_function(handle_request_input.NotifyFinished) + client_server.serve_forever() + + client_thread = ClientThread(client_port) + client_thread.requested_input = False + client_thread.notified_finished = 0 + client_thread.daemon = True + client_thread.start() + return client_thread + + def start_debugger_server_thread(self, debugger_port, socket_code): + + class DebuggerServerThread(threading.Thread): + + def __init__(self, debugger_port, socket_code): + threading.Thread.__init__(self) + self.debugger_port = debugger_port + self.socket_code = socket_code + + def run(self): + import socket + s = socket.socket() + s.bind(('', debugger_port)) + s.listen(1) + socket, unused_addr = s.accept() + socket_code(socket) + + debugger_thread = DebuggerServerThread(debugger_port, socket_code) + debugger_thread.daemon = True + debugger_thread.start() + return debugger_thread + + def get_free_addresses(self): + from _pydev_bundle.pydev_localhost import get_socket_names + socket_names = get_socket_names(2, True) + port0 = socket_names[0][1] + port1 = socket_names[1][1] + + assert port0 != port1 + assert port0 > 0 + assert port1 > 0 + + return port0, port1 + + def test_server(self): + self.original_stdout = sys.stdout + sys.stdout = pydevd_io.IOBuf() + try: + client_port, server_port = self.get_free_addresses() + + class ServerThread(threading.Thread): + + def __init__(self, client_port, server_port): + threading.Thread.__init__(self) + self.client_port = client_port + self.server_port = server_port + + def run(self): + from _pydev_bundle import pydev_localhost + pydevconsole.start_server(pydev_localhost.get_localhost(), self.server_port, self.client_port) + + server_thread = ServerThread(client_port, server_port) + server_thread.daemon = True + server_thread.start() + + client_thread = self.start_client_thread(client_port) # @UnusedVariable + + import time + time.sleep(.3) # let's give it some time to start the threads + sys.stdout = pydevd_io.IOBuf() + + from _pydev_bundle import pydev_localhost + server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), server_port)) + server.execLine('class Foo:') + server.execLine(' pass') + server.execLine('') + server.execLine('foo = Foo()') + server.execLine('a = input()') + server.execLine('print (a)') + initial = time.time() + while not client_thread.requested_input: + if time.time() - initial > 2: + raise AssertionError('Did not get the return asked before the timeout.') + time.sleep(.1) + + found = sys.stdout.getvalue() + while ['input_request'] != found.split(): + found += sys.stdout.getvalue() + if time.time() - initial > 2: + break + time.sleep(.1) + self.assertEqual(['input_request'], found.split()) + finally: + sys.stdout = self.original_stdout + diff --git a/tests/test_pyserver.py b/tests/test_pyserver.py new file mode 100644 index 0000000..da82aad --- /dev/null +++ b/tests/test_pyserver.py @@ -0,0 +1,155 @@ +import sys +from _pydev_bundle._pydev_saved_modules import thread +import pycompletionserver +import socket +from urllib.parse import quote_plus + +start_new_thread = thread.start_new_thread + +BUILTIN_MOD = 'builtins' + + +def send(s, msg): + s.send(bytearray(msg, 'utf-8')) + + +import unittest + + +class TestCPython(unittest.TestCase): + + def test_message(self): + t = pycompletionserver.CompletionServer(0) + + l = [] + l.append(('Def', 'description' , 'args')) + l.append(('Def1', 'description1', 'args1')) + l.append(('Def2', 'description2', 'args2')) + + msg = t.processor.format_completion_message(None, l) + + self.assertEqual('@@COMPLETIONS(None,(Def,description,args),(Def1,description1,args1),(Def2,description2,args2))END@@', msg) + l = [] + l.append(('Def', 'desc,,r,,i()ption', '')) + l.append(('Def(1', 'descriptio(n1', '')) + l.append(('De,f)2', 'de,s,c,ription2', '')) + msg = t.processor.format_completion_message(None, l) + self.assertEqual('@@COMPLETIONS(None,(Def,desc%2C%2Cr%2C%2Ci%28%29ption, ),(Def%281,descriptio%28n1, ),(De%2Cf%292,de%2Cs%2Cc%2Cription2, ))END@@', msg) + + def create_connections(self): + ''' + Creates the connections needed for testing. + ''' + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server.bind((pycompletionserver.HOST, 0)) + server.listen(1) # socket to receive messages. + + t = pycompletionserver.CompletionServer(server.getsockname()[1]) + t.exit_process_on_kill = False + start_new_thread(t.run, ()) + + s, _addr = server.accept() + + return t, s + + def read_msg(self): + finish = False + msg = '' + while finish == False: + m = self.socket.recv(1024 * 4) + m = m.decode('utf-8') + if m.startswith('@@PROCESSING'): + sys.stdout.write('Status msg: %s\n' % (msg,)) + else: + msg += m + + if msg.find('END@@') != -1: + finish = True + + return msg + + def test_completion_sockets_and_messages(self): + t, socket = self.create_connections() + self.socket = socket + + try: + # now that we have the connections all set up, check the code completion messages. + msg = quote_plus('math') + send(socket, '@@IMPORTS:%sEND@@' % msg) # math completions + completions = self.read_msg() + # print_ unquote_plus(completions) + + # math is a builtin and because of that, it starts with None as a file + start = '@@COMPLETIONS(None,(__doc__,' + start_2 = '@@COMPLETIONS(None,(__name__,' + if ('/math.so,' in completions or + '/math.cpython-33m.so,' in completions or + '/math.cpython-34m.so,' in completions or + 'math.cpython-35m' in completions or + 'math.cpython-36m' in completions or + 'math.cpython-37m' in completions or + 'math.cpython-38' in completions or + 'math.cpython-39' in completions or + 'math.cpython-310' in completions or + 'math.cpython-311' in completions + ): + return + self.assertTrue(completions.startswith(start) or completions.startswith(start_2), '%s DOESNT START WITH %s' % (completions, (start, start_2))) + + self.assertTrue('@@COMPLETIONS' in completions) + self.assertTrue('END@@' in completions) + + # now, test i + msg = quote_plus('%s.list' % BUILTIN_MOD) + send(socket, "@@IMPORTS:%s\nEND@@" % msg) + found = self.read_msg() + self.assertTrue('sort' in found, 'Could not find sort in: %s' % (found,)) + + # now, test search + msg = quote_plus('inspect.ismodule') + send(socket, '@@SEARCH%sEND@@' % msg) # math completions + found = self.read_msg() + self.assertTrue('inspect.py' in found) + for i in range(33, 100): + if str(i) in found: + break + else: + self.fail('Could not find the ismodule line in %s' % (found,)) + + # now, test search + msg = quote_plus('inspect.CO_NEWLOCALS') + send(socket, '@@SEARCH%sEND@@' % msg) # math completions + found = self.read_msg() + self.assertTrue('inspect.py' in found) + self.assertTrue('CO_NEWLOCALS' in found) + + # now, test search + msg = quote_plus('inspect.BlockFinder.tokeneater') + send(socket, '@@SEARCH%sEND@@' % msg) + found = self.read_msg() + self.assertTrue('inspect.py' in found) +# self.assertTrue('CO_NEWLOCALS' in found) + + # reload modules test +# send(socket, '@@RELOAD_MODULES_END@@') +# ok = self.read_msg() +# self.assertEqual('@@MSG_OK_END@@' , ok) +# this test is not executed because it breaks our current enviroment. + + finally: + try: + sys.stdout.write('succedded...sending kill msg\n') + self.send_kill_msg(socket) + +# while not hasattr(t, 'ended'): +# pass #wait until it receives the message and quits. + + socket.close() + self.socket.close() + except: + pass + + def send_kill_msg(self, socket): + socket.send(pycompletionserver.MSG_KILL_SERVER) + diff --git a/tests/test_simpleTipper.py b/tests/test_simpleTipper.py new file mode 100644 index 0000000..a08136b --- /dev/null +++ b/tests/test_simpleTipper.py @@ -0,0 +1,243 @@ +''' +@author Fabio Zadrozny +''' +from _pydev_bundle import _pydev_imports_tipper +import inspect +import pytest +import sys +import unittest + +try: + import __builtin__ # @UnusedImport + BUILTIN_MOD = '__builtin__' +except ImportError: + BUILTIN_MOD = 'builtins' + +IS_JYTHON = sys.platform.find('java') != -1 + +HAS_WX = False + + +@pytest.mark.skipif(IS_JYTHON, reason='CPython related test') +class TestCPython(unittest.TestCase): + + def p(self, t): + for a in t: + sys.stdout.write('%s\n' % (a,)) + + def test_imports3(self): + tip = _pydev_imports_tipper.generate_tip('os') + ret = self.assert_in('path', tip) + self.assertEqual('', ret[2]) + + def test_imports2(self): + try: + tip = _pydev_imports_tipper.generate_tip('OpenGL.GLUT') + self.assert_in('glutDisplayFunc', tip) + self.assert_in('glutInitDisplayMode', tip) + except ImportError: + pass + + def test_imports4(self): + try: + tip = _pydev_imports_tipper.generate_tip('mx.DateTime.mxDateTime.mxDateTime') + self.assert_in('now', tip) + except ImportError: + pass + + def test_imports5(self): + tip = _pydev_imports_tipper.generate_tip('%s.list' % BUILTIN_MOD) + s = self.assert_in('sort', tip) + self.check_args( + s, + '(cmp=None, key=None, reverse=False)', + '(self, object cmp, object key, bool reverse)', + '(self, cmp: object, key: object, reverse: bool)', + '(key=None, reverse=False)', + '(self, key=None, reverse=False)', + '(self, cmp, key, reverse)', + '(self, key, reverse)', + ) + + def test_imports2a(self): + tips = _pydev_imports_tipper.generate_tip('%s.RuntimeError' % BUILTIN_MOD) + self.assert_in('__doc__', tips) + + def test_imports2b(self): + try: + file + except: + pass + else: + tips = _pydev_imports_tipper.generate_tip('%s' % BUILTIN_MOD) + t = self.assert_in('file' , tips) + self.assertTrue('->' in t[1].strip() or 'file' in t[1]) + + def test_imports2c(self): + try: + file # file is not available on py 3 + except: + pass + else: + tips = _pydev_imports_tipper.generate_tip('%s.file' % BUILTIN_MOD) + t = self.assert_in('readlines' , tips) + self.assertTrue('->' in t[1] or 'sizehint' in t[1]) + + def test_imports(self): + ''' + You can print_ the results to check... + ''' + if HAS_WX: + tip = _pydev_imports_tipper.generate_tip('wxPython.wx') + self.assert_in('wxApp' , tip) + + tip = _pydev_imports_tipper.generate_tip('wxPython.wx.wxApp') + + try: + tip = _pydev_imports_tipper.generate_tip('qt') + self.assert_in('QWidget' , tip) + self.assert_in('QDialog' , tip) + + tip = _pydev_imports_tipper.generate_tip('qt.QWidget') + self.assert_in('rect' , tip) + self.assert_in('rect' , tip) + self.assert_in('AltButton' , tip) + + tip = _pydev_imports_tipper.generate_tip('qt.QWidget.AltButton') + self.assert_in('__xor__' , tip) + + tip = _pydev_imports_tipper.generate_tip('qt.QWidget.AltButton.__xor__') + self.assert_in('__class__' , tip) + except ImportError: + pass + + tip = _pydev_imports_tipper.generate_tip(BUILTIN_MOD) +# for t in tip[1]: +# print_ t + self.assert_in('object' , tip) + self.assert_in('tuple' , tip) + self.assert_in('list' , tip) + self.assert_in('RuntimeError' , tip) + self.assert_in('RuntimeWarning' , tip) + + # Remove cmp as it's not available on py 3 + # t = self.assert_in('cmp' , tip) + # self.check_args(t, '(x, y)', '(object x, object y)', '(x: object, y: object)') #args + + t = self.assert_in('isinstance' , tip) + self.check_args( + t, + '(object, class_or_type_or_tuple)', + '(object o, type typeinfo)', + '(o: object, typeinfo: type)', + '(obj, class_or_tuple)', + '(obj, klass_or_tuple)', + ) # args + + t = self.assert_in('compile' , tip) + self.check_args( + t, + '(source, filename, mode)', + '()', + '(o: object, name: str, val: object)', + '(source, filename, mode, flags, dont_inherit, optimize)', + '(source, filename, mode, flags, dont_inherit)', + '(source, filename, mode, flags, dont_inherit, optimize, _feature_version=-1)' + ) # args + + t = self.assert_in('setattr' , tip) + self.check_args( + t, + '(object, name, value)', + '(object o, str name, object val)', + '(o: object, name: str, val: object)', + '(obj, name, value)', + '(object, name, val)', + ) # args + + try: + import compiler + compiler_module = 'compiler' + except ImportError: + try: + import ast + compiler_module = 'ast' + except ImportError: + compiler_module = None + + if compiler_module is not None: # Not available in iron python + tip = _pydev_imports_tipper.generate_tip(compiler_module) + if compiler_module == 'compiler': + self.assert_args('parse', '(buf, mode)', tip) + self.assert_args('walk', '(tree, visitor, walker, verbose)', tip) + self.assert_in('parseFile' , tip) + else: + self.assert_args('parse', [ + '(source, filename, mode)', + '(source, filename, mode, type_comments=False, feature_version=None)' + ], tip + ) + self.assert_args('walk', '(node)', tip) + self.assert_in('parse' , tip) + + def check_args(self, t, *expected): + for x in expected: + if x == t[2]: + return + self.fail('Found: %s. Expected: %s' % (t[2], expected)) + + def assert_args(self, tok, args, tips): + if not isinstance(args, (list, tuple)): + args = (args,) + + for a in tips[1]: + if tok == a[0]: + for arg in args: + if arg == a[2]: + return + raise AssertionError('%s not in %s', a[2], args) + + raise AssertionError('%s not in %s', tok, tips) + + def assert_in(self, tok, tips): + for a in tips[1]: + if tok == a[0]: + return a + raise AssertionError('%s not in %s' % (tok, tips)) + + def test_search(self): + s = _pydev_imports_tipper.search_definition('inspect.ismodule') + (f, line, col), foundAs = s + self.assertTrue(line > 0) + + def test_dot_net_libraries(self): + if sys.platform == 'cli': + tip = _pydev_imports_tipper.generate_tip('System.Drawing') + self.assert_in('Brushes' , tip) + + tip = _pydev_imports_tipper.generate_tip('System.Drawing.Brushes') + self.assert_in('Aqua' , tip) + + def test_tips_hasattr_failure(self): + + class MyClass(object): + + def __getattribute__(self, attr): + raise RuntimeError() + + obj = MyClass() + + _pydev_imports_tipper.generate_imports_tip_for_module(obj) + + def test_inspect(self): + + class C(object): + + def metA(self, a, b): + pass + + obj = C.metA + if inspect.ismethod (obj): + pass +# print_ obj.im_func +# print_ inspect.getargspec(obj.im_func) diff --git a/tests_mainloop/README b/tests_mainloop/README new file mode 100644 index 0000000..65e699b --- /dev/null +++ b/tests_mainloop/README @@ -0,0 +1,4 @@ +# Parts of IPython, files from: https://github.com/ipython/ipython/tree/rel-1.0.0/examples/lib +# The files in this folder are manual tests for main loop integration + +# These tests have been modified to work in the PyDev Console context diff --git a/tests_mainloop/__init__.py b/tests_mainloop/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_mainloop/gui-glut.py b/tests_mainloop/gui-glut.py new file mode 100644 index 0000000..34a16b4 --- /dev/null +++ b/tests_mainloop/gui-glut.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +"""Simple GLUT example to manually test event loop integration. + +To run this: +1) Enable the PyDev GUI event loop integration for glut +2) do an execfile on this script +3) ensure you have a working GUI simultaneously with an + interactive console +4) run: gl.glClearColor(1,1,1,1) +""" + +if __name__ == '__main__': + + #!/usr/bin/env python + import sys + import OpenGL.GL as gl + import OpenGL.GLUT as glut + + def close(): + glut.glutDestroyWindow(glut.glutGetWindow()) + + def display(): + gl.glClear (gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) + glut.glutSwapBuffers() + + def resize(width,height): + gl.glViewport(0, 0, width, height+4) + gl.glMatrixMode(gl.GL_PROJECTION) + gl.glLoadIdentity() + gl.glOrtho(0, width, 0, height+4, -1, 1) + gl.glMatrixMode(gl.GL_MODELVIEW) + + if glut.glutGetWindow() > 0: + interactive = True + glut.glutInit(sys.argv) + glut.glutInitDisplayMode(glut.GLUT_DOUBLE | + glut.GLUT_RGBA | + glut.GLUT_DEPTH) + else: + interactive = False + + glut.glutCreateWindow('gui-glut') + glut.glutDisplayFunc(display) + glut.glutReshapeFunc(resize) + # This is necessary on osx to be able to close the window + # (else the close button is disabled) + if sys.platform == 'darwin' and not bool(glut.HAVE_FREEGLUT): + glut.glutWMCloseFunc(close) + gl.glClearColor(0,0,0,1) + + if not interactive: + glut.glutMainLoop() diff --git a/tests_mainloop/gui-gtk.py b/tests_mainloop/gui-gtk.py new file mode 100644 index 0000000..6df5c78 --- /dev/null +++ b/tests_mainloop/gui-gtk.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +"""Simple GTK example to manually test event loop integration. + +To run this: +1) Enable the PyDev GUI event loop integration for gtk +2) do an execfile on this script +3) ensure you have a working GUI simultaneously with an + interactive console +""" + +if __name__ == '__main__': + import pygtk + pygtk.require('2.0') + import gtk + + + def hello_world(wigdet, data=None): + print("Hello World") + + def delete_event(widget, event, data=None): + return False + + def destroy(widget, data=None): + gtk.main_quit() + + window = gtk.Window(gtk.WINDOW_TOPLEVEL) + window.connect("delete_event", delete_event) + window.connect("destroy", destroy) + button = gtk.Button("Hello World") + button.connect("clicked", hello_world, None) + + window.add(button) + button.show() + window.show() + diff --git a/tests_mainloop/gui-gtk3.py b/tests_mainloop/gui-gtk3.py new file mode 100644 index 0000000..6351d52 --- /dev/null +++ b/tests_mainloop/gui-gtk3.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +"""Simple Gtk example to manually test event loop integration. + +To run this: +1) Enable the PyDev GUI event loop integration for gtk3 +2) do an execfile on this script +3) ensure you have a working GUI simultaneously with an + interactive console +""" + +if __name__ == '__main__': + from gi.repository import Gtk + + + def hello_world(wigdet, data=None): + print("Hello World") + + def delete_event(widget, event, data=None): + return False + + def destroy(widget, data=None): + Gtk.main_quit() + + window = Gtk.Window(Gtk.WindowType.TOPLEVEL) + window.connect("delete_event", delete_event) + window.connect("destroy", destroy) + button = Gtk.Button("Hello World") + button.connect("clicked", hello_world, None) + + window.add(button) + button.show() + window.show() + diff --git a/tests_mainloop/gui-pyglet.py b/tests_mainloop/gui-pyglet.py new file mode 100644 index 0000000..70f1a7f --- /dev/null +++ b/tests_mainloop/gui-pyglet.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +"""Simple pyglet example to manually test event loop integration. + +To run this: +1) Enable the PyDev GUI event loop integration for pyglet +2) do an execfile on this script +3) ensure you have a working GUI simultaneously with an + interactive console +""" + +if __name__ == '__main__': + import pyglet + + + window = pyglet.window.Window() + label = pyglet.text.Label('Hello, world', + font_name='Times New Roman', + font_size=36, + x=window.width//2, y=window.height//2, + anchor_x='center', anchor_y='center') + @window.event + def on_close(): + window.close() + + @window.event + def on_draw(): + window.clear() + label.draw() diff --git a/tests_mainloop/gui-qt.py b/tests_mainloop/gui-qt.py new file mode 100644 index 0000000..30fc48d --- /dev/null +++ b/tests_mainloop/gui-qt.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +"""Simple Qt4 example to manually test event loop integration. + +To run this: +1) Enable the PyDev GUI event loop integration for qt +2) do an execfile on this script +3) ensure you have a working GUI simultaneously with an + interactive console + +Ref: Modified from http://zetcode.com/tutorials/pyqt4/firstprograms/ +""" + +if __name__ == '__main__': + import sys + from PyQt4 import QtGui, QtCore + + class SimpleWindow(QtGui.QWidget): + def __init__(self, parent=None): + QtGui.QWidget.__init__(self, parent) + + self.setGeometry(300, 300, 200, 80) + self.setWindowTitle('Hello World') + + quit = QtGui.QPushButton('Close', self) + quit.setGeometry(10, 10, 60, 35) + + self.connect(quit, QtCore.SIGNAL('clicked()'), + self, QtCore.SLOT('close()')) + + if __name__ == '__main__': + app = QtCore.QCoreApplication.instance() + if app is None: + app = QtGui.QApplication([]) + + sw = SimpleWindow() + sw.show() diff --git a/tests_mainloop/gui-tk.py b/tests_mainloop/gui-tk.py new file mode 100644 index 0000000..4cef45f --- /dev/null +++ b/tests_mainloop/gui-tk.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +"""Simple Tk example to manually test event loop integration. + +To run this: +1) Enable the PyDev GUI event loop integration for tk +2) do an execfile on this script +3) ensure you have a working GUI simultaneously with an + interactive console +""" + +if __name__ == '__main__': + + try: + from Tkinter import * + except: + # Python 3 + from tkinter import * + + class MyApp: + + def __init__(self, root): + frame = Frame(root) + frame.pack() + + self.button = Button(frame, text="Hello", command=self.hello_world) + self.button.pack(side=LEFT) + + def hello_world(self): + print("Hello World!") + + root = Tk() + + app = MyApp(root) diff --git a/tests_mainloop/gui-wx.py b/tests_mainloop/gui-wx.py new file mode 100644 index 0000000..dfd35d8 --- /dev/null +++ b/tests_mainloop/gui-wx.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +""" +A Simple wx example to test PyDev's event loop integration. + +To run this: +1) Enable the PyDev GUI event loop integration for wx +2) do an execfile on this script +3) ensure you have a working GUI simultaneously with an + interactive console + +Ref: Modified from wxPython source code wxPython/samples/simple/simple.py +""" + +if __name__ == '__main__': + + import wx + + + class MyFrame(wx.Frame): + """ + This is MyFrame. It just shows a few controls on a wxPanel, + and has a simple menu. + """ + def __init__(self, parent, title): + wx.Frame.__init__(self, parent, -1, title, + pos=(150, 150), size=(350, 200)) + + # Create the menubar + menuBar = wx.MenuBar() + + # and a menu + menu = wx.Menu() + + # add an item to the menu, using \tKeyName automatically + # creates an accelerator, the third param is some help text + # that will show up in the statusbar + menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample") + + # bind the menu event to an event handler + self.Bind(wx.EVT_MENU, self.on_time_to_close, id=wx.ID_EXIT) + + # and put the menu on the menubar + menuBar.Append(menu, "&File") + self.SetMenuBar(menuBar) + + self.CreateStatusBar() + + # Now create the Panel to put the other controls on. + panel = wx.Panel(self) + + # and a few controls + text = wx.StaticText(panel, -1, "Hello World!") + text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD)) + text.SetSize(text.GetBestSize()) + btn = wx.Button(panel, -1, "Close") + funbtn = wx.Button(panel, -1, "Just for fun...") + + # bind the button events to handlers + self.Bind(wx.EVT_BUTTON, self.on_time_to_close, btn) + self.Bind(wx.EVT_BUTTON, self.on_fun_button, funbtn) + + # Use a sizer to layout the controls, stacked vertically and with + # a 10 pixel border around each + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(text, 0, wx.ALL, 10) + sizer.Add(btn, 0, wx.ALL, 10) + sizer.Add(funbtn, 0, wx.ALL, 10) + panel.SetSizer(sizer) + panel.Layout() + + + def on_time_to_close(self, evt): + """Event handler for the button click.""" + print("See ya later!") + self.Close() + + def on_fun_button(self, evt): + """Event handler for the button click.""" + print("Having fun yet?") + + + class MyApp(wx.App): + def OnInit(self): + frame = MyFrame(None, "Simple wxPython App") + self.SetTopWindow(frame) + + print("Print statements go to this stdout window by default.") + + frame.Show(True) + return True + + + if __name__ == '__main__': + + app = wx.GetApp() + if app is None: + app = MyApp(redirect=False, clearSigInt=False) + else: + frame = MyFrame(None, "Simple wxPython App") + app.SetTopWindow(frame) + print("Print statements go to this stdout window by default.") + frame.Show(True) + diff --git a/tests_python/__init__.py b/tests_python/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/check_debug_python.py b/tests_python/check_debug_python.py new file mode 100644 index 0000000..3027e9a --- /dev/null +++ b/tests_python/check_debug_python.py @@ -0,0 +1,38 @@ +import sys +import threading +from _pydev_bundle import pydev_log + + +def check(): + with pydev_log.log_context(3, sys.stderr): + assert hasattr(sys, 'gettotalrefcount') + import pydevd_tracing + + proceed1 = threading.Event() + proceed2 = threading.Event() + + class SomeThread(threading.Thread): + + def run(self): + proceed1.set() + proceed2.wait() + + t = SomeThread() + t.start() + proceed1.wait() + try: + + def some_func(frame, event, arg): + return some_func + + pydevd_tracing.set_trace_to_threads(some_func) + finally: + proceed2.set() + + lib = pydevd_tracing._load_python_helper_lib() + assert lib is None + print('Finished OK') + + +if __name__ == '__main__': + check() diff --git a/tests_python/debug_constants.py b/tests_python/debug_constants.py new file mode 100644 index 0000000..ed4c6f2 --- /dev/null +++ b/tests_python/debug_constants.py @@ -0,0 +1,45 @@ +import os +import sys +import platform + +TEST_CYTHON = os.getenv('PYDEVD_USE_CYTHON', None) == 'YES' +PYDEVD_TEST_VM = os.getenv('PYDEVD_TEST_VM', None) + +IS_PY36_OR_GREATER = sys.version_info[0:2] >= (3, 6) +IS_PY311_OR_GREATER = sys.version_info[0:2] >= (3, 11) +IS_CPYTHON = platform.python_implementation() == 'CPython' + +TODO_PY311 = IS_PY311_OR_GREATER # Code which needs to be fixed in 3.11 should use this constant. + +IS_PY36 = False +if sys.version_info[0] == 3 and sys.version_info[1] == 6: + IS_PY36 = True + +TEST_DJANGO = False +TEST_FLASK = False +TEST_CHERRYPY = False +TEST_GEVENT = False + +try: + import django + TEST_DJANGO = True +except: + pass + +try: + import flask + TEST_FLASK = True +except: + pass + +try: + import cherrypy + TEST_CHERRYPY = True +except: + pass + +try: + import gevent + TEST_GEVENT = True +except: + pass diff --git a/tests_python/debugger_fixtures.py b/tests_python/debugger_fixtures.py new file mode 100644 index 0000000..2ab0d23 --- /dev/null +++ b/tests_python/debugger_fixtures.py @@ -0,0 +1,524 @@ +# coding: utf-8 +from contextlib import contextmanager +import os + +import pytest + +from tests_python import debugger_unittest +from tests_python.debugger_unittest import (get_free_port, overrides, IS_CPYTHON, IS_JYTHON, IS_IRONPYTHON, + CMD_ADD_DJANGO_EXCEPTION_BREAK, CMD_REMOVE_DJANGO_EXCEPTION_BREAK, + CMD_ADD_EXCEPTION_BREAK, wait_for_condition, IS_PYPY) +from _pydevd_bundle.pydevd_comm_constants import file_system_encoding + +import sys +from _pydevd_bundle.pydevd_constants import IS_WINDOWS + + +def get_java_location(): + from java.lang import System # @UnresolvedImport + jre_dir = System.getProperty("java.home") + for f in [os.path.join(jre_dir, 'bin', 'java.exe'), os.path.join(jre_dir, 'bin', 'java')]: + if os.path.exists(f): + return f + raise RuntimeError('Unable to find java executable') + + +def get_jython_jar(): + from java.lang import ClassLoader # @UnresolvedImport + cl = ClassLoader.getSystemClassLoader() + paths = map(lambda url: url.getFile(), cl.getURLs()) + for p in paths: + if 'jython.jar' in p: + return p + raise RuntimeError('Unable to find jython.jar') + + +class _WriterThreadCaseMSwitch(debugger_unittest.AbstractWriterThread): + + TEST_FILE = 'tests_python.resources._debugger_case_m_switch' + IS_MODULE = True + + @overrides(debugger_unittest.AbstractWriterThread.get_environ) + def get_environ(self): + env = os.environ.copy() + curr_pythonpath = env.get('PYTHONPATH', '') + + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + curr_pythonpath += root_dirname + os.pathsep + env['PYTHONPATH'] = curr_pythonpath + return env + + @overrides(debugger_unittest.AbstractWriterThread.get_main_filename) + def get_main_filename(self): + return debugger_unittest._get_debugger_test_file('_debugger_case_m_switch.py') + + +class _WriterThreadCaseModuleWithEntryPoint(_WriterThreadCaseMSwitch): + + TEST_FILE = 'tests_python.resources._debugger_case_module_entry_point:main' + IS_MODULE = True + + @overrides(_WriterThreadCaseMSwitch.get_main_filename) + def get_main_filename(self): + return debugger_unittest._get_debugger_test_file('_debugger_case_module_entry_point.py') + + +class AbstractWriterThreadCaseFlask(debugger_unittest.AbstractWriterThread): + + FORCE_KILL_PROCESS_WHEN_FINISHED_OK = True + FLASK_FOLDER = None + + TEST_FILE = 'flask' + IS_MODULE = True + + def write_add_breakpoint_jinja2(self, line, func, template): + ''' + @param line: starts at 1 + ''' + assert self.FLASK_FOLDER is not None + breakpoint_id = self.next_breakpoint_id() + template_file = debugger_unittest._get_debugger_test_file(os.path.join(self.FLASK_FOLDER, 'templates', template)) + self.write("111\t%s\t%s\t%s\t%s\t%s\t%s\tNone\tNone" % (self.next_seq(), breakpoint_id, 'jinja2-line', template_file, line, func)) + self.log.append('write_add_breakpoint_jinja: %s line: %s func: %s' % (breakpoint_id, line, func)) + return breakpoint_id + + def write_add_exception_breakpoint_jinja2(self, exception='jinja2-Exception'): + self.write('%s\t%s\t%s\t%s\t%s\t%s' % (CMD_ADD_EXCEPTION_BREAK, self.next_seq(), exception, 2, 0, 0)) + + @overrides(debugger_unittest.AbstractWriterThread.get_environ) + def get_environ(self): + import platform + + env = os.environ.copy() + env['FLASK_APP'] = 'app.py' + env['FLASK_ENV'] = 'development' + env['FLASK_DEBUG'] = '0' + if platform.system() != 'Windows': + locale = 'en_US.utf8' if platform.system() == 'Linux' else 'en_US.UTF-8' + env.update({ + 'LC_ALL': locale, + 'LANG': locale, + }) + return env + + def get_cwd(self): + return debugger_unittest._get_debugger_test_file(self.FLASK_FOLDER) + + def get_command_line_args(self): + assert self.FLASK_FOLDER is not None + free_port = get_free_port() + self.flask_port = free_port + return [ + 'flask', + 'run', + '--no-debugger', + '--no-reload', + '--with-threads', + '--port', + str(free_port), + ] + + def _ignore_stderr_line(self, line): + if debugger_unittest.AbstractWriterThread._ignore_stderr_line(self, line): + return True + + if 'Running on http:' in line: + return True + + if 'GET / HTTP/' in line: + return True + + return False + + def create_request_thread(self, url=''): + return debugger_unittest.AbstractWriterThread.create_request_thread( + self, 'http://127.0.0.1:%s%s' % (self.flask_port, url)) + + +class AbstractWriterThreadCaseDjango(debugger_unittest.AbstractWriterThread): + + FORCE_KILL_PROCESS_WHEN_FINISHED_OK = True + DJANGO_FOLDER = None + + def _ignore_stderr_line(self, line): + if debugger_unittest.AbstractWriterThread._ignore_stderr_line(self, line): + return True + + if 'GET /my_app' in line: + return True + + return False + + def get_command_line_args(self): + assert self.DJANGO_FOLDER is not None + free_port = get_free_port() + self.django_port = free_port + return [ + debugger_unittest._get_debugger_test_file(os.path.join(self.DJANGO_FOLDER, 'manage.py')), + 'runserver', + '--noreload', + '--nothreading', + str(free_port), + ] + + def write_add_breakpoint_django(self, line, func, template): + ''' + @param line: starts at 1 + ''' + assert self.DJANGO_FOLDER is not None + breakpoint_id = self.next_breakpoint_id() + template_file = debugger_unittest._get_debugger_test_file(os.path.join(self.DJANGO_FOLDER, 'my_app', 'templates', 'my_app', template)) + self.write("111\t%s\t%s\t%s\t%s\t%s\t%s\tNone\tNone" % (self.next_seq(), breakpoint_id, 'django-line', template_file, line, func)) + self.log.append('write_add_django_breakpoint: %s line: %s func: %s' % (breakpoint_id, line, func)) + return breakpoint_id + + def write_add_exception_breakpoint_django(self, exception='Exception'): + self.write('%s\t%s\t%s' % (CMD_ADD_DJANGO_EXCEPTION_BREAK, self.next_seq(), exception)) + + def write_remove_exception_breakpoint_django(self, exception='Exception'): + self.write('%s\t%s\t%s' % (CMD_REMOVE_DJANGO_EXCEPTION_BREAK, self.next_seq(), exception)) + + def create_request_thread(self, url=''): + return debugger_unittest.AbstractWriterThread.create_request_thread( + self, 'http://127.0.0.1:%s/%s' % (self.django_port, url)) + + +class DebuggerRunnerSimple(debugger_unittest.DebuggerRunner): + + def get_command_line(self): + if IS_JYTHON: + if sys.executable is not None: + # i.e.: we're running with the provided jython.exe + return [sys.executable] + else: + + return [ + get_java_location(), + '-classpath', + get_jython_jar(), + 'org.python.util.jython' + ] + + if IS_CPYTHON or IS_PYPY: + return [sys.executable, '-u'] + + if IS_IRONPYTHON: + return [ + sys.executable, + '-X:Frames' + ] + + raise RuntimeError('Unable to provide command line') + + +class DebuggerRunnerRemote(debugger_unittest.DebuggerRunner): + + def get_command_line(self): + return [sys.executable, '-u'] + + def add_command_line_args(self, args): + writer = self.writer + + ret = args + [self.writer.TEST_FILE] + ret = writer.update_command_line_args(ret) # Provide a hook for the writer + return ret + + +@pytest.fixture +def debugger_runner_simple(tmpdir): + return DebuggerRunnerSimple(tmpdir) + + +@pytest.fixture +def debugger_runner_remote(tmpdir): + return DebuggerRunnerRemote(tmpdir) + + +@pytest.fixture +def case_setup(tmpdir, debugger_runner_simple): + runner = debugger_runner_simple + + class WriterThread(debugger_unittest.AbstractWriterThread): + pass + + class CaseSetup(object): + + check_non_ascii = False + NON_ASCII_CHARS = u'áéíóú汉字' + + @contextmanager + def test_file( + self, + filename, + wait_for_port=True, + wait_for_initialization=True, + **kwargs + ): + import shutil + filename = debugger_unittest._get_debugger_test_file(filename) + if self.check_non_ascii: + basedir = str(tmpdir) + if isinstance(basedir, bytes): + basedir = basedir.decode('utf-8') + if isinstance(filename, bytes): + filename = filename.decode('utf-8') + + new_dir = os.path.join(basedir, self.NON_ASCII_CHARS) + os.makedirs(new_dir) + + new_filename = os.path.join(new_dir, self.NON_ASCII_CHARS + os.path.basename(filename)) + shutil.copyfile(filename, new_filename) + filename = new_filename + + WriterThread.TEST_FILE = filename + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + + with runner.check_case( + WriterThread, + wait_for_port=wait_for_port, + wait_for_initialization=wait_for_initialization + ) as writer: + yield writer + + return CaseSetup() + + +@pytest.fixture +def case_setup_unhandled_exceptions(case_setup): + + original = case_setup.test_file + + def check_test_suceeded_msg(writer, stdout, stderr): + return 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + # Don't call super as we have an expected exception + if 'ValueError: TEST SUCEEDED' not in stderr: + raise AssertionError('"ValueError: TEST SUCEEDED" not in stderr.\nstdout:\n%s\n\nstderr:\n%s' % ( + stdout, stderr)) + + def test_file(*args, **kwargs): + kwargs.setdefault('check_test_suceeded_msg', check_test_suceeded_msg) + kwargs.setdefault('additional_output_checks', additional_output_checks) + return original(*args, **kwargs) + + case_setup.test_file = test_file + + return case_setup + + +@pytest.fixture +def case_setup_remote(debugger_runner_remote): + + class WriterThread(debugger_unittest.AbstractWriterThread): + pass + + class CaseSetup(object): + + @contextmanager + def test_file( + self, + filename, + wait_for_port=True, + access_token=None, + client_access_token=None, + append_command_line_args=(), + **kwargs + ): + + def update_command_line_args(writer, args): + ret = debugger_unittest.AbstractWriterThread.update_command_line_args(writer, args) + wait_for_condition(lambda: hasattr(writer, 'port')) + ret.append(str(writer.port)) + + if access_token is not None: + ret.append('--access-token') + ret.append(access_token) + if client_access_token is not None: + ret.append('--client-access-token') + ret.append(client_access_token) + + ret.extend(append_command_line_args) + return ret + + WriterThread.TEST_FILE = debugger_unittest._get_debugger_test_file(filename) + WriterThread.update_command_line_args = update_command_line_args + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + + with debugger_runner_remote.check_case(WriterThread, wait_for_port=wait_for_port) as writer: + yield writer + + return CaseSetup() + + +@pytest.fixture +def case_setup_remote_attach_to(debugger_runner_remote): + ''' + The difference from this to case_setup_remote is that this one will connect to a server + socket started by the debugger and case_setup_remote will create the server socket and wait + for a connection from the debugger. + ''' + + class WriterThread(debugger_unittest.AbstractWriterThread): + + @overrides(debugger_unittest.AbstractWriterThread.run) + def run(self): + # I.e.: don't start socket on start(), rather, the test should call + # start_socket_client() when needed. + pass + + class CaseSetup(object): + + @contextmanager + def test_file( + self, + filename, + port, + **kwargs + ): + additional_args = kwargs.pop('additional_args', []) + + def update_command_line_args(writer, args): + ret = debugger_unittest.AbstractWriterThread.update_command_line_args(writer, args) + ret.append(str(port)) + ret.extend(additional_args) + return ret + + WriterThread.TEST_FILE = debugger_unittest._get_debugger_test_file(filename) + WriterThread.update_command_line_args = update_command_line_args + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + + with debugger_runner_remote.check_case(WriterThread, wait_for_port=False) as writer: + yield writer + + return CaseSetup() + + +@pytest.fixture +def case_setup_multiprocessing(debugger_runner_simple): + + class WriterThread(debugger_unittest.AbstractWriterThread): + pass + + class CaseSetup(object): + + @contextmanager + def test_file( + self, + filename, + **kwargs + ): + + def update_command_line_args(writer, args): + ret = debugger_unittest.AbstractWriterThread.update_command_line_args(writer, args) + ret.insert(ret.index('--client'), '--multiprocess') + return ret + + WriterThread.update_command_line_args = update_command_line_args + WriterThread.TEST_FILE = debugger_unittest._get_debugger_test_file(filename) + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + + with debugger_runner_simple.check_case(WriterThread) as writer: + yield writer + + return CaseSetup() + + +@pytest.fixture +def case_setup_m_switch(debugger_runner_simple): + + class WriterThread(_WriterThreadCaseMSwitch): + pass + + class CaseSetup(object): + + @contextmanager + def test_file(self, **kwargs): + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + with debugger_runner_simple.check_case(WriterThread) as writer: + yield writer + + return CaseSetup() + + +@pytest.fixture +def case_setup_m_switch_entry_point(debugger_runner_simple): + + runner = debugger_runner_simple + + class WriterThread(_WriterThreadCaseModuleWithEntryPoint): + pass + + class CaseSetup(object): + + @contextmanager + def test_file(self, **kwargs): + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + with runner.check_case(WriterThread) as writer: + yield writer + + return CaseSetup() + + +@pytest.fixture +def case_setup_django(debugger_runner_simple): + + class WriterThread(AbstractWriterThreadCaseDjango): + pass + + class CaseSetup(object): + + @contextmanager + def test_file(self, **kwargs): + import django + version = [int(x) for x in django.get_version().split('.')][:2] + if version == [1, 7]: + django_folder = 'my_django_proj_17' + elif version in ([2, 1], [2, 2], [3, 0], [3, 1], [3, 2], [4, 0]): + django_folder = 'my_django_proj_21' + else: + raise AssertionError('Can only check django 1.7, 2.1, 2.2, 3.0, 3.1, 3.2 and 4.0 right now. Found: %s' % (version,)) + + WriterThread.DJANGO_FOLDER = django_folder + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + + with debugger_runner_simple.check_case(WriterThread) as writer: + yield writer + + return CaseSetup() + + +@pytest.fixture +def case_setup_flask(debugger_runner_simple): + + class WriterThread(AbstractWriterThreadCaseFlask): + pass + + class CaseSetup(object): + + @contextmanager + def test_file(self, **kwargs): + WriterThread.FLASK_FOLDER = 'flask1' + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + + with debugger_runner_simple.check_case(WriterThread) as writer: + yield writer + + return CaseSetup() diff --git a/tests_python/debugger_unittest.py b/tests_python/debugger_unittest.py new file mode 100644 index 0000000..bdf7008 --- /dev/null +++ b/tests_python/debugger_unittest.py @@ -0,0 +1,1446 @@ +from collections import namedtuple +from contextlib import contextmanager +import json +from urllib.parse import quote, quote_plus, unquote_plus + +import re +import socket +import subprocess +import threading +import time +import traceback +from tests_python.debug_constants import * + +from _pydev_bundle import pydev_localhost, pydev_log + +# Note: copied (don't import because we want it to be independent on the actual code because of backward compatibility). +CMD_RUN = 101 +CMD_LIST_THREADS = 102 +CMD_THREAD_CREATE = 103 +CMD_THREAD_KILL = 104 +CMD_THREAD_SUSPEND = 105 +CMD_THREAD_RUN = 106 +CMD_STEP_INTO = 107 +CMD_STEP_OVER = 108 +CMD_STEP_RETURN = 109 +CMD_GET_VARIABLE = 110 +CMD_SET_BREAK = 111 +CMD_REMOVE_BREAK = 112 +CMD_EVALUATE_EXPRESSION = 113 +CMD_GET_FRAME = 114 +CMD_EXEC_EXPRESSION = 115 +CMD_WRITE_TO_CONSOLE = 116 +CMD_CHANGE_VARIABLE = 117 +CMD_RUN_TO_LINE = 118 +CMD_RELOAD_CODE = 119 +CMD_GET_COMPLETIONS = 120 + +# Note: renumbered (conflicted on merge) +CMD_CONSOLE_EXEC = 121 +CMD_ADD_EXCEPTION_BREAK = 122 +CMD_REMOVE_EXCEPTION_BREAK = 123 +CMD_LOAD_SOURCE = 124 +CMD_ADD_DJANGO_EXCEPTION_BREAK = 125 +CMD_REMOVE_DJANGO_EXCEPTION_BREAK = 126 +CMD_SET_NEXT_STATEMENT = 127 +CMD_SMART_STEP_INTO = 128 +CMD_EXIT = 129 +CMD_SIGNATURE_CALL_TRACE = 130 + +CMD_SET_PY_EXCEPTION = 131 +CMD_GET_FILE_CONTENTS = 132 +CMD_SET_PROPERTY_TRACE = 133 +# Pydev debug console commands +CMD_EVALUATE_CONSOLE_EXPRESSION = 134 +CMD_RUN_CUSTOM_OPERATION = 135 +CMD_GET_BREAKPOINT_EXCEPTION = 136 +CMD_STEP_CAUGHT_EXCEPTION = 137 +CMD_SEND_CURR_EXCEPTION_TRACE = 138 +CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED = 139 +CMD_IGNORE_THROWN_EXCEPTION_AT = 140 +CMD_ENABLE_DONT_TRACE = 141 +CMD_SHOW_CONSOLE = 142 + +CMD_GET_ARRAY = 143 +CMD_STEP_INTO_MY_CODE = 144 +CMD_GET_CONCURRENCY_EVENT = 145 +CMD_SHOW_RETURN_VALUES = 146 + +CMD_GET_THREAD_STACK = 152 +CMD_THREAD_DUMP_TO_STDERR = 153 # This is mostly for unit-tests to diagnose errors on ci. +CMD_STOP_ON_START = 154 +CMD_GET_EXCEPTION_DETAILS = 155 +CMD_PYDEVD_JSON_CONFIG = 156 + +CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION = 157 +CMD_THREAD_RESUME_SINGLE_NOTIFICATION = 158 + +CMD_STEP_OVER_MY_CODE = 159 +CMD_STEP_RETURN_MY_CODE = 160 + +CMD_SET_PY_EXCEPTION = 161 +CMD_SET_PATH_MAPPING_JSON = 162 + +CMD_GET_SMART_STEP_INTO_VARIANTS = 163 # XXX: PyCharm has 160 for this (we're currently incompatible anyways). + +CMD_REDIRECT_OUTPUT = 200 +CMD_GET_NEXT_STATEMENT_TARGETS = 201 +CMD_SET_PROJECT_ROOTS = 202 + +CMD_AUTHENTICATE = 205 + +CMD_VERSION = 501 +CMD_RETURN = 502 +CMD_SET_PROTOCOL = 503 +CMD_ERROR = 901 + +REASON_CAUGHT_EXCEPTION = CMD_STEP_CAUGHT_EXCEPTION +REASON_UNCAUGHT_EXCEPTION = CMD_ADD_EXCEPTION_BREAK +REASON_STOP_ON_BREAKPOINT = CMD_SET_BREAK +REASON_THREAD_SUSPEND = CMD_THREAD_SUSPEND +REASON_STEP_INTO = CMD_STEP_INTO +REASON_STEP_INTO_MY_CODE = CMD_STEP_INTO_MY_CODE +REASON_STOP_ON_START = CMD_STOP_ON_START +REASON_STEP_RETURN = CMD_STEP_RETURN +REASON_STEP_RETURN_MY_CODE = CMD_STEP_RETURN_MY_CODE +REASON_STEP_OVER = CMD_STEP_OVER +REASON_STEP_OVER_MY_CODE = CMD_STEP_OVER_MY_CODE + +# Always True (because otherwise when we do have an error, it's hard to diagnose). +SHOW_WRITES_AND_READS = True +SHOW_OTHER_DEBUG_INFO = True +SHOW_STDOUT = True + +import platform + +IS_CPYTHON = platform.python_implementation() == 'CPython' +IS_IRONPYTHON = platform.python_implementation() == 'IronPython' +IS_JYTHON = platform.python_implementation() == 'Jython' +IS_PYPY = platform.python_implementation() == 'PyPy' +IS_APPVEYOR = os.environ.get('APPVEYOR', '') in ('True', 'true', '1') + +try: + from thread import start_new_thread +except ImportError: + from _thread import start_new_thread # @UnresolvedImport + +Hit = namedtuple('Hit', 'thread_id, frame_id, line, suspend_type, name, file') + + +def overrides(method): + ''' + Helper to check that one method overrides another (redeclared in unit-tests to avoid importing pydevd). + ''' + + def wrapper(func): + if func.__name__ != method.__name__: + msg = "Wrong @override: %r expected, but overwriting %r." + msg = msg % (func.__name__, method.__name__) + raise AssertionError(msg) + + if func.__doc__ is None: + func.__doc__ = method.__doc__ + + return func + + return wrapper + + +TIMEOUT = 20 + +try: + TimeoutError = TimeoutError # @ReservedAssignment +except NameError: + + class TimeoutError(RuntimeError): # @ReservedAssignment + pass + + +def wait_for_condition(condition, msg=None, timeout=TIMEOUT, sleep=.05): + curtime = time.time() + while True: + if condition(): + break + if time.time() - curtime > timeout: + error_msg = 'Condition not reached in %s seconds' % (timeout,) + if msg is not None: + error_msg += '\n' + if callable(msg): + error_msg += msg() + else: + error_msg += str(msg) + + raise TimeoutError(error_msg) + time.sleep(sleep) + + +class IgnoreFailureError(RuntimeError): + pass + + +#======================================================================================================================= +# ReaderThread +#======================================================================================================================= +class ReaderThread(threading.Thread): + + MESSAGES_TIMEOUT = 15 + + def __init__(self, sock): + threading.Thread.__init__(self) + self.name = 'Test Reader Thread' + try: + from queue import Queue + except ImportError: + from Queue import Queue + + self.daemon = True + self._buffer = b'' + self.sock = sock + self._queue = Queue() + self._kill = False + self.accept_xml_messages = True + self.on_message_found = lambda msg: None + + def set_messages_timeout(self, timeout): + self.MESSAGES_TIMEOUT = timeout + + def get_next_message(self, context_message, timeout=None): + if timeout is None: + timeout = self.MESSAGES_TIMEOUT + try: + msg = self._queue.get(block=True, timeout=timeout) + self.on_message_found(msg) + except: + raise TimeoutError('No message was written in %s seconds. Error message:\n%s' % (timeout, context_message,)) + else: + frame = sys._getframe().f_back.f_back + frame_info = '' + while frame: + if not frame.f_code.co_name.startswith('test_'): + frame = frame.f_back + continue + + if frame.f_code.co_filename.endswith('debugger_unittest.py'): + frame = frame.f_back + continue + + stack_msg = ' -- File "%s", line %s, in %s\n' % (frame.f_code.co_filename, frame.f_lineno, frame.f_code.co_name) + if 'run' == frame.f_code.co_name: + frame_info = stack_msg # Ok, found the writer thread 'run' method (show only that). + break + frame_info += stack_msg + frame = frame.f_back + # Just print the first which is not debugger_unittest.py + break + + frame = None + sys.stdout.write('Message returned in get_next_message(): %s -- ctx: %s, asked at:\n%s\n' % (unquote_plus(unquote_plus(msg)), context_message, frame_info)) + + if not self.accept_xml_messages: + if ' size: + ret = self._buffer[:size] + self._buffer = self._buffer[size:] + return ret + + r = self.sock.recv(max(size - buffer_len, 1024)) + if not r: + return b'' + self._buffer += r + + def _read_line(self): + while True: + i = self._buffer.find(b'\n') + if i != -1: + i += 1 # Add the newline to the return + ret = self._buffer[:i] + self._buffer = self._buffer[i:] + return ret + else: + r = self.sock.recv(1024) + if not r: + return b'' + self._buffer += r + + def run(self): + try: + content_len = -1 + + while not self._kill: + line = self._read_line() + + if not line: + break + + if SHOW_WRITES_AND_READS: + show_line = line + show_line = line.decode('utf-8') + + print('%s Received %s' % (self.name, show_line,)) + + if line.startswith(b'Content-Length:'): + content_len = int(line.strip().split(b':', 1)[1]) + continue + + if content_len != -1: + # If we previously received a content length, read until a '\r\n'. + if line == b'\r\n': + json_contents = self._read(content_len) + content_len = -1 + + if len(json_contents) == 0: + self.handle_except() + return # Finished communication. + + msg = json_contents + msg = msg.decode('utf-8') + print('Test Reader Thread Received %s' % (msg,)) + self._queue.put(msg) + + continue + else: + # No content len, regular line-based protocol message (remove trailing new-line). + if line.endswith(b'\n\n'): + line = line[:-2] + + elif line.endswith(b'\n'): + line = line[:-1] + + elif line.endswith(b'\r'): + line = line[:-1] + + msg = line + msg = msg.decode('utf-8') + print('Test Reader Thread Received %s' % (msg,)) + self._queue.put(msg) + + except: + pass # ok, finished it + finally: + # When the socket from pydevd is closed the client should shutdown to notify + # it acknowledged it. + try: + self.sock.shutdown(socket.SHUT_RDWR) + except: + pass + try: + self.sock.close() + except: + pass + + def do_kill(self): + self._kill = True + if hasattr(self, 'sock'): + from socket import SHUT_RDWR + try: + self.sock.shutdown(SHUT_RDWR) + except: + pass + try: + self.sock.close() + except: + pass + delattr(self, 'sock') + + +def read_process(stream, buffer, debug_stream, stream_name, finish): + while True: + line = stream.readline() + if not line: + break + + line = line.decode('utf-8', errors='replace') + + if SHOW_STDOUT: + debug_stream.write('%s: %s' % (stream_name, line,)) + buffer.append(line) + + if finish[0]: + return + + +def start_in_daemon_thread(target, args): + t0 = threading.Thread(target=target, args=args) + t0.daemon = True + t0.start() + + +class DebuggerRunner(object): + + def __init__(self, tmpdir): + if tmpdir is not None: + self.pydevd_debug_file = os.path.join(str(tmpdir), 'pydevd_debug_file_%s.txt' % (os.getpid(),)) + else: + self.pydevd_debug_file = None + + def get_command_line(self): + ''' + Returns the base command line (i.e.: ['python.exe', '-u']) + ''' + raise NotImplementedError + + def add_command_line_args(self, args): + writer = self.writer + port = int(writer.port) + + localhost = pydev_localhost.get_localhost() + ret = [ + writer.get_pydevd_file(), + ] + + if not IS_PY36_OR_GREATER or not IS_CPYTHON or not TEST_CYTHON: + # i.e.: in frame-eval mode we support native threads, whereas + # on other cases we need the qt monkeypatch. + ret += ['--qt-support'] + + ret += [ + '--client', + localhost, + '--port', + str(port), + ] + + if writer.IS_MODULE: + ret += ['--module'] + + ret += ['--file'] + writer.get_command_line_args() + ret = writer.update_command_line_args(ret) # Provide a hook for the writer + return args + ret + + @contextmanager + def check_case(self, writer_class, wait_for_port=True, wait_for_initialization=True): + try: + if callable(writer_class): + writer = writer_class() + else: + writer = writer_class + try: + writer.start() + if wait_for_port: + wait_for_condition(lambda: hasattr(writer, 'port')) + self.writer = writer + + args = self.get_command_line() + + args = self.add_command_line_args(args) + + if SHOW_OTHER_DEBUG_INFO: + print('executing: %s' % (' '.join(args),)) + + with self.run_process(args, writer) as dct_with_stdout_stder: + try: + if not wait_for_initialization: + # The use-case for this is that the debugger can't even start-up in this + # scenario, as such, sleep a bit so that the output can be collected. + time.sleep(1) + elif wait_for_port: + wait_for_condition(lambda: writer.finished_initialization) + except TimeoutError: + sys.stderr.write('Timed out waiting for initialization\n') + sys.stderr.write('stdout:\n%s\n\nstderr:\n%s\n' % ( + ''.join(dct_with_stdout_stder['stdout']), + ''.join(dct_with_stdout_stder['stderr']), + )) + raise + finally: + writer.get_stdout = lambda: ''.join(dct_with_stdout_stder['stdout']) + writer.get_stderr = lambda: ''.join(dct_with_stdout_stder['stderr']) + + yield writer + finally: + writer.do_kill() + writer.log = [] + + stdout = dct_with_stdout_stder['stdout'] + stderr = dct_with_stdout_stder['stderr'] + writer.additional_output_checks(''.join(stdout), ''.join(stderr)) + except IgnoreFailureError: + sys.stderr.write('Test finished with ignored failure.\n') + return + + def create_process(self, args, writer): + env = writer.get_environ() if writer is not None else None + if env is None: + env = os.environ.copy() + + if self.pydevd_debug_file: + env['PYDEVD_DEBUG'] = 'True' + env['PYDEVD_DEBUG_FILE'] = self.pydevd_debug_file + print('Logging to: %s' % (self.pydevd_debug_file,)) + process = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + cwd=writer.get_cwd() if writer is not None else '.', + env=env, + ) + return process + + @contextmanager + def run_process(self, args, writer): + process = self.create_process(args, writer) + writer.process = process + stdout = [] + stderr = [] + finish = [False] + dct_with_stdout_stder = {} + fail_with_message = False + + try: + start_in_daemon_thread(read_process, (process.stdout, stdout, sys.stdout, 'stdout', finish)) + start_in_daemon_thread(read_process, (process.stderr, stderr, sys.stderr, 'stderr', finish)) + + if SHOW_OTHER_DEBUG_INFO: + print('Both processes started') + + # polls can fail (because the process may finish and the thread still not -- so, we give it some more chances to + # finish successfully). + initial_time = time.time() + shown_intermediate = False + dumped_threads = False + + dct_with_stdout_stder['stdout'] = stdout + dct_with_stdout_stder['stderr'] = stderr + try: + yield dct_with_stdout_stder + except: + fail_with_message = True + # Let's print the actuayl exception here (it doesn't appear properly on Python 2 and + # on Python 3 it's hard to find because pytest output is too verbose). + sys.stderr.write('***********\n') + sys.stderr.write('***********\n') + sys.stderr.write('***********\n') + traceback.print_exc() + sys.stderr.write('***********\n') + sys.stderr.write('***********\n') + sys.stderr.write('***********\n') + raise + + if not writer.finished_ok: + self.fail_with_message( + "The thread that was doing the tests didn't finish successfully (writer.finished_ok = True not set).", + stdout, + stderr, + writer + ) + + while True: + if process.poll() is not None: + if writer.EXPECTED_RETURNCODE != 'any': + expected_returncode = writer.EXPECTED_RETURNCODE + if not isinstance(expected_returncode, (list, tuple)): + expected_returncode = (expected_returncode,) + + if process.returncode not in expected_returncode: + self.fail_with_message('Expected process.returncode to be %s. Found: %s' % ( + writer.EXPECTED_RETURNCODE, process.returncode), stdout, stderr, writer) + break + else: + if writer is not None: + if writer.FORCE_KILL_PROCESS_WHEN_FINISHED_OK: + process.kill() + continue + + if not shown_intermediate and (time.time() - initial_time > (TIMEOUT / 3.)): # 1/3 of timeout + print('Warning: writer thread exited and process still did not (%.2f seconds elapsed).' % (time.time() - initial_time,)) + shown_intermediate = True + + if time.time() - initial_time > ((TIMEOUT / 3.) * 2.): # 2/3 of timeout + if not dumped_threads: + dumped_threads = True + # It still didn't finish. Ask for a thread dump + # (we'll be able to see it later on the test output stderr). + try: + writer.write_dump_threads() + except: + traceback.print_exc() + + if time.time() - initial_time > TIMEOUT: # timed out + process.kill() + time.sleep(.2) + self.fail_with_message( + "The other process should've exited but still didn't (%.2f seconds timeout for process to exit)." % (time.time() - initial_time,), + stdout, stderr, writer + ) + time.sleep(.2) + + if writer is not None: + if not writer.FORCE_KILL_PROCESS_WHEN_FINISHED_OK: + if stdout is None: + self.fail_with_message( + "The other process may still be running -- and didn't give any output.", stdout, stderr, writer) + + check = 0 + while not writer.check_test_suceeded_msg(stdout, stderr): + check += 1 + if check == 50: + self.fail_with_message("TEST SUCEEDED not found.", stdout, stderr, writer) + time.sleep(.1) + + except TimeoutError: + msg = 'TimeoutError' + try: + writer.write_dump_threads() + except: + msg += ' (note: error trying to dump threads on timeout).' + time.sleep(.2) + self.fail_with_message(msg, stdout, stderr, writer) + except Exception as e: + if fail_with_message: + self.fail_with_message(str(e), stdout, stderr, writer) + else: + raise + finally: + try: + if process.poll() is None: + process.kill() + except: + traceback.print_exc() + finish[0] = True + + def fail_with_message(self, msg, stdout, stderr, writerThread): + log_contents = '' + for f in pydev_log.list_log_files(self.pydevd_debug_file): + if os.path.exists(f): + with open(f, 'r') as stream: + log_contents += '\n-------------------- %s ------------------\n\n' % (f,) + log_contents += stream.read() + msg += ("\n\n===========================\nStdout: \n" + ''.join(stdout) + + "\n\n===========================\nStderr:" + ''.join(stderr) + + "\n\n===========================\nWriter Log:\n" + '\n'.join(getattr(writerThread, 'log', [])) + + "\n\n===========================\nLog:" + log_contents) + + if IS_JYTHON: + # It seems we have some spurious errors which make Jython tests flaky (on a test run it's + # not unusual for one test among all the tests to fail with this error on Jython). + # The usual traceback in this case is: + # + # Traceback (most recent call last): + # File "/home/travis/build/fabioz/PyDev.Debugger/_pydevd_bundle/pydevd_comm.py", line 287, in _on_run + # line = self._read_line() + # File "/home/travis/build/fabioz/PyDev.Debugger/_pydevd_bundle/pydevd_comm.py", line 270, in _read_line + # r = self.sock.recv(1024) + # File "/home/travis/build/fabioz/PyDev.Debugger/_pydevd_bundle/pydevd_comm.py", line 270, in _read_line + # r = self.sock.recv(1024) + # File "/home/travis/jython/Lib/_socket.py", line 1270, in recv + # data, _ = self._get_message(bufsize, "recv") + # File "/home/travis/jython/Lib/_socket.py", line 384, in handle_exception + # raise _map_exception(jlx) + # error: [Errno -1] Unmapped exception: java.lang.NullPointerException + # + # So, ignore errors in this situation. + + if 'error: [Errno -1] Unmapped exception: java.lang.NullPointerException' in msg: + raise IgnoreFailureError() + raise AssertionError(msg) + + +#======================================================================================================================= +# AbstractWriterThread +#======================================================================================================================= +class AbstractWriterThread(threading.Thread): + + FORCE_KILL_PROCESS_WHEN_FINISHED_OK = False + IS_MODULE = False + TEST_FILE = None + EXPECTED_RETURNCODE = 0 + + def __init__(self, *args, **kwargs): + threading.Thread.__init__(self, *args, **kwargs) + self.process = None # Set after the process is created. + self.daemon = True + self.finished_ok = False + self.finished_initialization = False + self._next_breakpoint_id = 0 + self.log = [] + + def run(self): + self.start_socket() + + def check_test_suceeded_msg(self, stdout, stderr): + return 'TEST SUCEEDED' in ''.join(stdout) + + def update_command_line_args(self, args): + return args + + def _ignore_stderr_line(self, line): + if line.startswith(( + 'debugger: ', + '>>', + '<<', + 'warning: Debugger speedups', + 'pydev debugger: New process is launching', + 'pydev debugger: To debug that process', + '*** Multiprocess', + )): + return True + + for expected in ( + 'PyDev console: using IPython', + 'Attempting to work in a virtualenv. If you encounter problems, please', + 'Unable to create basic Accelerated OpenGL', # Issue loading qt5 + 'Core Image is now using the software OpenGL', # Issue loading qt5 + 'XDG_RUNTIME_DIR not set', # Issue loading qt5 + ): + if expected in line: + return True + + if re.match(r'^(\d+)\t(\d)+', line): + return True + + if IS_JYTHON: + for expected in ( + 'org.python.netty.util.concurrent.DefaultPromise', + 'org.python.netty.util.concurrent.SingleThreadEventExecutor', + 'Failed to submit a listener notification task. Event loop shut down?', + 'java.util.concurrent.RejectedExecutionException', + 'An event executor terminated with non-empty task', + 'java.lang.UnsupportedOperationException', + "RuntimeWarning: Parent module '_pydevd_bundle' not found while handling absolute import", + 'from _pydevd_bundle.pydevd_additional_thread_info_regular import _current_frames', + 'from _pydevd_bundle.pydevd_additional_thread_info import _current_frames', + 'import org.python.core as PyCore #@UnresolvedImport', + 'from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info', + "RuntimeWarning: Parent module '_pydevd_bundle._debug_adapter' not found while handling absolute import", + 'import json', + + # Issues with Jython and Java 9. + 'WARNING: Illegal reflective access by org.python.core.PySystemState', + 'WARNING: Please consider reporting this to the maintainers of org.python.core.PySystemState', + 'WARNING: An illegal reflective access operation has occurred', + 'WARNING: Illegal reflective access by jnr.posix.JavaLibCHelper', + 'WARNING: Please consider reporting this to the maintainers of jnr.posix.JavaLibCHelper', + 'WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations', + 'WARNING: All illegal access operations will be denied in a future release', + ): + if expected in line: + return True + + if line.strip().startswith('at '): + return True + + return False + + def additional_output_checks(self, stdout, stderr): + lines_with_error = [] + for line in stderr.splitlines(): + line = line.strip() + if not line: + continue + if not self._ignore_stderr_line(line): + lines_with_error.append(line) + + if lines_with_error: + raise AssertionError('Did not expect to have line(s) in stderr:\n\n%s\n\nFull stderr:\n\n%s' % ( + '\n'.join(lines_with_error), stderr)) + + def get_environ(self): + return None + + def get_pydevd_file(self): + dirname = os.path.dirname(__file__) + dirname = os.path.dirname(dirname) + return os.path.abspath(os.path.join(dirname, 'pydevd.py')) + + def get_pydevconsole_file(self): + dirname = os.path.dirname(__file__) + dirname = os.path.dirname(dirname) + return os.path.abspath(os.path.join(dirname, 'pydevconsole.py')) + + def get_line_index_with_content(self, line_content, filename=None): + ''' + :return the line index which has the given content (1-based). + ''' + if filename is None: + filename = self.TEST_FILE + with open(filename, 'r') as stream: + for i_line, line in enumerate(stream): + if line_content in line: + return i_line + 1 + raise AssertionError('Did not find: %s in %s' % (line_content, self.TEST_FILE)) + + def get_cwd(self): + return os.path.dirname(self.get_pydevd_file()) + + def get_command_line_args(self): + return [self.TEST_FILE] + + def do_kill(self): + if hasattr(self, 'server_socket'): + self.server_socket.close() + delattr(self, 'server_socket') + + if hasattr(self, 'reader_thread'): + # if it's not created, it's not there... + self.reader_thread.do_kill() + delattr(self, 'reader_thread') + + if hasattr(self, 'sock'): + self.sock.close() + delattr(self, 'sock') + + if hasattr(self, 'port'): + delattr(self, 'port') + + def write_with_content_len(self, msg): + self.log.append('write: %s' % (msg,)) + + if SHOW_WRITES_AND_READS: + print('Test Writer Thread Written %s' % (msg,)) + + if not hasattr(self, 'sock'): + print('%s.sock not available when sending: %s' % (self, msg)) + return + + if not isinstance(msg, bytes): + msg = msg.encode('utf-8') + + self.sock.sendall((u'Content-Length: %s\r\n\r\n' % len(msg)).encode('ascii')) + self.sock.sendall(msg) + + _WRITE_LOG_PREFIX = 'write: ' + + def write(self, s): + from _pydevd_bundle.pydevd_comm import ID_TO_MEANING + meaning = ID_TO_MEANING.get(re.search(r'\d+', s).group(), '') + if meaning: + meaning += ': ' + + self.log.append(self._WRITE_LOG_PREFIX + '%s%s' % (meaning, s,)) + + if SHOW_WRITES_AND_READS: + print('Test Writer Thread Written %s%s' % (meaning, s,)) + msg = s + '\n' + + if not hasattr(self, 'sock'): + print('%s.sock not available when sending: %s' % (self, msg)) + return + + msg = msg.encode('utf-8') + + self.sock.send(msg) + + def get_next_message(self, context_message, timeout=None): + return self.reader_thread.get_next_message(context_message, timeout=timeout) + + def start_socket(self, port=None): + assert not hasattr(self, 'port'), 'Socket already initialized.' + from _pydev_bundle.pydev_localhost import get_socket_name + if SHOW_WRITES_AND_READS: + print('start_socket') + + self._sequence = -1 + if port is None: + socket_name = get_socket_name(close=True) + else: + socket_name = (pydev_localhost.get_localhost(), port) + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server_socket.bind(socket_name) + self.port = socket_name[1] + server_socket.listen(1) + if SHOW_WRITES_AND_READS: + print('Waiting in socket.accept()') + self.server_socket = server_socket + new_socket, addr = server_socket.accept() + if SHOW_WRITES_AND_READS: + print('Test Writer Thread Socket:', new_socket, addr) + + self._set_socket(new_socket) + + def _set_socket(self, new_socket): + curr_socket = getattr(self, 'sock', None) + if curr_socket: + try: + curr_socket.shutdown(socket.SHUT_WR) + except: + pass + try: + curr_socket.close() + except: + pass + + reader_thread = self.reader_thread = ReaderThread(new_socket) + self.sock = new_socket + reader_thread.start() + + # initial command is always the version + self.write_version() + self.log.append('start_socket') + self.finished_initialization = True + + def start_socket_client(self, host, port): + self._sequence = -1 + if SHOW_WRITES_AND_READS: + print("Connecting to %s:%s" % (host, port)) + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + # Set TCP keepalive on an open socket. + # It activates after 1 second (TCP_KEEPIDLE,) of idleness, + # then sends a keepalive ping once every 3 seconds (TCP_KEEPINTVL), + # and closes the connection after 5 failed ping (TCP_KEEPCNT), or 15 seconds + try: + from socket import IPPROTO_TCP, SO_KEEPALIVE, TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT + s.setsockopt(socket.SOL_SOCKET, SO_KEEPALIVE, 1) + s.setsockopt(IPPROTO_TCP, TCP_KEEPIDLE, 1) + s.setsockopt(IPPROTO_TCP, TCP_KEEPINTVL, 3) + s.setsockopt(IPPROTO_TCP, TCP_KEEPCNT, 5) + except ImportError: + pass # May not be available everywhere. + + # 10 seconds default timeout + timeout = int(os.environ.get('PYDEVD_CONNECT_TIMEOUT', 10)) + s.settimeout(timeout) + for _i in range(20): + try: + s.connect((host, port)) + break + except: + time.sleep(.5) # We may have to wait a bit more and retry (especially on PyPy). + s.settimeout(None) # no timeout after connected + if SHOW_WRITES_AND_READS: + print("Connected.") + self._set_socket(s) + return s + + def next_breakpoint_id(self): + self._next_breakpoint_id += 1 + return self._next_breakpoint_id + + def next_seq(self): + self._sequence += 2 + return self._sequence + + def wait_for_new_thread(self): + # wait for hit breakpoint + last = '' + while not ' + splitted = last.split('"') + thread_id = splitted[3] + return thread_id + + def wait_for_output(self): + # Something as: + # + while True: + msg = self.get_next_message('wait_output') + if "' in last: + last = self.get_next_message('wait_for_get_next_statement_targets') + + matches = re.finditer(r"(([0-9]*)<\/line>)", last, re.IGNORECASE) + lines = [] + for _, match in enumerate(matches): + try: + lines.append(int(match.group(2))) + except ValueError: + pass + return set(lines) + + def wait_for_custom_operation(self, expected): + # wait for custom operation response, the response is double encoded + expected_encoded = quote(quote_plus(expected)) + last = '' + while not expected_encoded in last: + last = self.get_next_message('wait_for_custom_operation. Expected (encoded): %s' % (expected_encoded,)) + + return True + + def _is_var_in_last(self, expected, last): + if expected in last: + return True + + last = unquote_plus(last) + if expected in last: + return True + + # We actually quote 2 times on the backend... + last = unquote_plus(last) + if expected in last: + return True + + return False + + def wait_for_multiple_vars(self, expected_vars): + if not isinstance(expected_vars, (list, tuple)): + expected_vars = [expected_vars] + + all_found = [] + ignored = [] + + while True: + try: + last = self.get_next_message('wait_for_multiple_vars: %s' % (expected_vars,)) + except: + missing = [] + for v in expected_vars: + if v not in all_found: + missing.append(v) + raise ValueError('Not Found:\n%s\nNot found messages: %s\nFound messages: %s\nExpected messages: %s\nIgnored messages:\n%s' % ( + '\n'.join(str(x) for x in missing), len(missing), len(all_found), len(expected_vars), '\n'.join(str(x) for x in ignored))) + + was_message_used = False + new_expected = [] + for expected in expected_vars: + found_expected = False + if isinstance(expected, (tuple, list)): + for e in expected: + if self._is_var_in_last(e, last): + was_message_used = True + found_expected = True + all_found.append(expected) + break + else: + if self._is_var_in_last(expected, last): + was_message_used = True + found_expected = True + all_found.append(expected) + + if not found_expected: + new_expected.append(expected) + + expected_vars = new_expected + + if not expected_vars: + return True + + if not was_message_used: + ignored.append(last) + + wait_for_var = wait_for_multiple_vars + wait_for_vars = wait_for_multiple_vars + wait_for_evaluation = wait_for_multiple_vars + + def write_make_initial_run(self): + self.write("101\t%s\t" % self.next_seq()) + self.log.append('write_make_initial_run') + + def write_set_protocol(self, protocol): + self.write("%s\t%s\t%s" % (CMD_SET_PROTOCOL, self.next_seq(), protocol)) + + def write_authenticate(self, access_token, client_access_token): + msg = "%s\t%s\t%s" % (CMD_AUTHENTICATE, self.next_seq(), access_token) + self.write(msg) + + self.wait_for_message(lambda msg:client_access_token in msg, expect_xml=False) + + def write_version(self): + from _pydevd_bundle.pydevd_constants import IS_WINDOWS + self.write("%s\t%s\t1.0\t%s\tID" % (CMD_VERSION, self.next_seq(), 'WINDOWS' if IS_WINDOWS else 'UNIX')) + + def get_main_filename(self): + return self.TEST_FILE + + def write_show_return_vars(self, show=1): + self.write("%s\t%s\tCMD_SHOW_RETURN_VALUES\t%s" % (CMD_SHOW_RETURN_VALUES, self.next_seq(), show)) + + def write_add_breakpoint(self, line, func='None', filename=None, hit_condition=None, is_logpoint=False, suspend_policy=None, condition=None): + ''' + :param line: starts at 1 + :param func: if None, may hit in any context, empty string only top level, otherwise must be method name. + ''' + if filename is None: + filename = self.get_main_filename() + breakpoint_id = self.next_breakpoint_id() + if hit_condition is None and not is_logpoint and suspend_policy is None and condition is None: + # Format kept for backward compatibility tests + self.write("%s\t%s\t%s\t%s\t%s\t%s\t%s\tNone\tNone" % ( + CMD_SET_BREAK, self.next_seq(), breakpoint_id, 'python-line', filename, line, func)) + else: + # Format: breakpoint_id, type, file, line, func_name, condition, expression, hit_condition, is_logpoint, suspend_policy + self.write("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\tNone\t%s\t%s\t%s" % ( + CMD_SET_BREAK, self.next_seq(), breakpoint_id, 'python-line', filename, line, func, condition, hit_condition, is_logpoint, suspend_policy)) + self.log.append('write_add_breakpoint: %s line: %s func: %s' % (breakpoint_id, line, func)) + return breakpoint_id + + def write_multi_threads_single_notification(self, multi_threads_single_notification): + self.write_json_config(dict( + multi_threads_single_notification=multi_threads_single_notification, + )) + + def write_suspend_on_breakpoint_exception(self, skip_suspend_on_breakpoint_exception, skip_print_breakpoint_exception): + self.write_json_config(dict( + skip_suspend_on_breakpoint_exception=skip_suspend_on_breakpoint_exception, + skip_print_breakpoint_exception=skip_print_breakpoint_exception + )) + + def write_json_config(self, config_dict): + self.write("%s\t%s\t%s" % (CMD_PYDEVD_JSON_CONFIG, self.next_seq(), + json.dumps(config_dict) + )) + + def write_stop_on_start(self, stop=True): + self.write("%s\t%s\t%s" % (CMD_STOP_ON_START, self.next_seq(), stop)) + + def write_dump_threads(self): + self.write("%s\t%s\t" % (CMD_THREAD_DUMP_TO_STDERR, self.next_seq())) + + def write_add_exception_breakpoint(self, exception): + self.write("%s\t%s\t%s" % (CMD_ADD_EXCEPTION_BREAK, self.next_seq(), exception)) + self.log.append('write_add_exception_breakpoint: %s' % (exception,)) + + def write_get_current_exception(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_GET_EXCEPTION_DETAILS, self.next_seq(), thread_id)) + + def write_set_py_exception_globals( + self, + break_on_uncaught, + break_on_caught, + skip_on_exceptions_thrown_in_same_context, + ignore_exceptions_thrown_in_lines_with_ignore_exception, + ignore_libraries, + exceptions=() + ): + # Only set the globals, others + self.write("131\t%s\t%s" % (self.next_seq(), '%s;%s;%s;%s;%s;%s' % ( + 'true' if break_on_uncaught else 'false', + 'true' if break_on_caught else 'false', + 'true' if skip_on_exceptions_thrown_in_same_context else 'false', + 'true' if ignore_exceptions_thrown_in_lines_with_ignore_exception else 'false', + 'true' if ignore_libraries else 'false', + ';'.join(exceptions) + ))) + self.log.append('write_set_py_exception_globals') + + def write_start_redirect(self): + self.write("%s\t%s\t%s" % (CMD_REDIRECT_OUTPUT, self.next_seq(), 'STDERR STDOUT')) + + def write_set_project_roots(self, project_roots): + self.write("%s\t%s\t%s" % (CMD_SET_PROJECT_ROOTS, self.next_seq(), '\t'.join(str(x) for x in project_roots))) + + def write_add_exception_breakpoint_with_policy( + self, exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries): + self.write("%s\t%s\t%s" % (CMD_ADD_EXCEPTION_BREAK, self.next_seq(), '\t'.join(str(x) for x in [ + exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries]))) + self.log.append('write_add_exception_breakpoint: %s' % (exception,)) + + def write_remove_exception_breakpoint(self, exception): + self.write('%s\t%s\t%s' % (CMD_REMOVE_EXCEPTION_BREAK, self.next_seq(), exception)) + + def write_remove_breakpoint(self, breakpoint_id): + self.write("%s\t%s\t%s\t%s\t%s" % ( + CMD_REMOVE_BREAK, self.next_seq(), 'python-line', self.get_main_filename(), breakpoint_id)) + + def write_change_variable(self, thread_id, frame_id, varname, value): + self.write("%s\t%s\t%s\t%s\t%s\t%s\t%s" % ( + CMD_CHANGE_VARIABLE, self.next_seq(), thread_id, frame_id, 'FRAME', varname, value)) + + def write_get_frame(self, thread_id, frame_id): + self.write("%s\t%s\t%s\t%s\tFRAME" % (CMD_GET_FRAME, self.next_seq(), thread_id, frame_id)) + self.log.append('write_get_frame') + + def write_get_variable(self, thread_id, frame_id, var_attrs): + self.write("%s\t%s\t%s\t%s\tFRAME\t%s" % (CMD_GET_VARIABLE, self.next_seq(), thread_id, frame_id, var_attrs)) + + def write_step_over(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_STEP_OVER, self.next_seq(), thread_id,)) + + def write_step_in(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_STEP_INTO, self.next_seq(), thread_id,)) + + def write_step_in_my_code(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_STEP_INTO_MY_CODE, self.next_seq(), thread_id,)) + + def write_step_return(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_STEP_RETURN, self.next_seq(), thread_id,)) + + def write_step_return_my_code(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_STEP_RETURN_MY_CODE, self.next_seq(), thread_id,)) + + def write_step_over_my_code(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_STEP_OVER_MY_CODE, self.next_seq(), thread_id,)) + + def write_suspend_thread(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_THREAD_SUSPEND, self.next_seq(), thread_id,)) + + def write_reload(self, module_name): + self.log.append('write_reload') + self.write("%s\t%s\t%s" % (CMD_RELOAD_CODE, self.next_seq(), module_name,)) + + def write_run_thread(self, thread_id): + self.log.append('write_run_thread') + self.write("%s\t%s\t%s" % (CMD_THREAD_RUN, self.next_seq(), thread_id,)) + + def write_get_thread_stack(self, thread_id): + self.log.append('write_get_thread_stack') + self.write("%s\t%s\t%s" % (CMD_GET_THREAD_STACK, self.next_seq(), thread_id,)) + + def write_load_source(self, filename): + self.log.append('write_load_source') + self.write("%s\t%s\t%s" % (CMD_LOAD_SOURCE, self.next_seq(), filename,)) + + def write_load_source_from_frame_id(self, frame_id): + from _pydevd_bundle.pydevd_comm_constants import CMD_LOAD_SOURCE_FROM_FRAME_ID + self.log.append('write_load_source_from_frame_id') + self.write("%s\t%s\t%s" % (CMD_LOAD_SOURCE_FROM_FRAME_ID, self.next_seq(), frame_id,)) + + def write_kill_thread(self, thread_id): + self.write("%s\t%s\t%s" % (CMD_THREAD_KILL, self.next_seq(), thread_id,)) + + def write_set_next_statement(self, thread_id, line, func_name): + self.write("%s\t%s\t%s\t%s\t%s" % (CMD_SET_NEXT_STATEMENT, self.next_seq(), thread_id, line, func_name,)) + + def write_smart_step_into(self, thread_id, line, func_name): + self.write("%s\t%s\t%s\t%s\t%s" % (CMD_SMART_STEP_INTO, self.next_seq(), thread_id, line, func_name,)) + + def write_debug_console_expression(self, locator): + self.write("%s\t%s\t%s" % (CMD_EVALUATE_CONSOLE_EXPRESSION, self.next_seq(), locator)) + + def write_custom_operation(self, locator, style, codeOrFile, operation_fn_name): + self.write("%s\t%s\t%s||%s\t%s\t%s" % ( + CMD_RUN_CUSTOM_OPERATION, self.next_seq(), locator, style, quote_plus(codeOrFile), operation_fn_name)) + + def write_evaluate_expression(self, locator, expression): + self.write("%s\t%s\t%s\t%s\t1" % (CMD_EVALUATE_EXPRESSION, self.next_seq(), locator, expression)) + + def write_enable_dont_trace(self, enable): + if enable: + enable = 'true' + else: + enable = 'false' + self.write("%s\t%s\t%s" % (CMD_ENABLE_DONT_TRACE, self.next_seq(), enable)) + + def write_get_next_statement_targets(self, thread_id, frame_id): + self.write("201\t%s\t%s\t%s" % (self.next_seq(), thread_id, frame_id)) + self.log.append('write_get_next_statement_targets') + + def write_list_threads(self): + seq = self.next_seq() + self.write("%s\t%s\t" % (CMD_LIST_THREADS, seq)) + return seq + + def wait_for_list_threads(self, seq): + return self.wait_for_message('502') + + def wait_for_get_thread_stack_message(self): + return self.wait_for_message(CMD_GET_THREAD_STACK) + + def wait_for_curr_exc_stack(self): + return self.wait_for_message(CMD_SEND_CURR_EXCEPTION_TRACE) + + def wait_for_json_message(self, accept_message, unquote_msg=True, timeout=None): + last = self.wait_for_message(accept_message, unquote_msg, expect_xml=False, timeout=timeout) + json_msg = last.split('\t', 2)[-1] # We have something as: CMD\tSEQ\tJSON + if isinstance(json_msg, bytes): + json_msg = json_msg.decode('utf-8') + try: + return json.loads(json_msg) + except: + traceback.print_exc() + raise AssertionError('Unable to parse:\n%s\njson:\n%s' % (last, json_msg)) + + def wait_for_message(self, accept_message, unquote_msg=True, expect_xml=True, timeout=None): + if isinstance(accept_message, (str, int)): + msg_starts_with = '%s\t' % (accept_message,) + + def accept_message(msg): + return msg.startswith(msg_starts_with) + + import untangle + from io import StringIO + prev = None + while True: + last = self.get_next_message('wait_for_message', timeout=timeout) + if unquote_msg: + last = unquote_plus(unquote_plus(last)) + if accept_message(last): + if expect_xml: + # Extract xml and return untangled. + xml = '' + try: + xml = last[last.index(''):] + if isinstance(xml, bytes): + xml = xml.decode('utf-8') + xml = untangle.parse(StringIO(xml)) + except: + traceback.print_exc() + raise AssertionError('Unable to parse:\n%s\nxml:\n%s' % (last, xml)) + ret = xml.xml + ret.original_xml = last + return ret + else: + return last + if prev != last: + print('Ignored message: %r' % (last,)) + + prev = last + + def get_frame_names(self, thread_id): + self.write_get_thread_stack(thread_id) + msg = self.wait_for_message(CMD_GET_THREAD_STACK) + if msg.thread.frame: + frame_names = [frame['name'] for frame in msg.thread.frame] + return frame_names + return [msg.thread.frame['name']] + + def get_step_into_variants(self, thread_id, frame_id, start_line, end_line): + self.write("%s\t%s\t%s\t%s\t%s\t%s" % (CMD_GET_SMART_STEP_INTO_VARIANTS, self.next_seq(), thread_id, frame_id, start_line, end_line)) + msg = self.wait_for_message(CMD_GET_SMART_STEP_INTO_VARIANTS) + if msg.variant: + variant_info = [ + (variant['name'], variant['isVisited'], variant['line'], variant['callOrder'], variant['offset'], variant['childOffset']) + for variant in msg.variant + ] + return variant_info + return [] + + def wait_for_thread_join(self, main_thread_id): + + def condition(): + return self.get_frame_names(main_thread_id) in ( + ['wait', 'join', ''], + ['_wait_for_tstate_lock', 'join', ''], + ['_wait_for_tstate_lock', 'join', '', '_run_code', '_run_module_code', 'run_path'], + ) + + def msg(): + return 'Found stack: %s' % (self.get_frame_names(main_thread_id),) + + wait_for_condition(condition, msg, timeout=5, sleep=.5) + + def create_request_thread(self, full_url): + + class T(threading.Thread): + + def wait_for_contents(self): + for _ in range(10): + if hasattr(self, 'contents'): + break + time.sleep(.3) + else: + raise AssertionError('Unable to get contents from server. Url: %s' % (full_url,)) + return self.contents + + def run(self): + try: + from urllib.request import urlopen + except ImportError: + from urllib import urlopen + for _ in range(10): + try: + stream = urlopen(full_url) + contents = stream.read() + contents = contents.decode('utf-8') + self.contents = contents + break + except IOError: + continue + + t = T() + t.daemon = True + return t + + +def _get_debugger_test_file(filename): + ret = os.path.abspath(os.path.join(os.path.dirname(__file__), filename)) + if not os.path.exists(ret): + ret = os.path.join(os.path.dirname(__file__), 'resources', filename) + if not os.path.exists(ret): + raise AssertionError('Expected: %s to exist.' % (ret,)) + return ret + + +def get_free_port(): + from _pydev_bundle.pydev_localhost import get_socket_name + return get_socket_name(close=True)[1] diff --git a/tests_python/flask1/.project b/tests_python/flask1/.project new file mode 100644 index 0000000..b4528d4 --- /dev/null +++ b/tests_python/flask1/.project @@ -0,0 +1,17 @@ + + + flask1 + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/tests_python/flask1/.pydevproject b/tests_python/flask1/.pydevproject new file mode 100644 index 0000000..ad74947 --- /dev/null +++ b/tests_python/flask1/.pydevproject @@ -0,0 +1,8 @@ + + + +/${PROJECT_DIR_NAME} + +python interpreter +Default + diff --git a/tests_python/flask1/app.py b/tests_python/flask1/app.py new file mode 100644 index 0000000..2f4e4a2 --- /dev/null +++ b/tests_python/flask1/app.py @@ -0,0 +1,60 @@ +from flask import Flask +from flask import render_template + +app = Flask(__name__) + + +@app.route("/") +def home(): + content = 'Flask-Jinja-Test' + return render_template( + "hello.html", + title='Hello', + content=content + ) + + +@app.route("/handled") +def bad_route_handled(): + try: + raise ArithmeticError('Hello') + except Exception: + pass + return render_template( + "hello.html", + title='Hello', + content='Flask-Jinja-Test' + ) + + +@app.route("/unhandled") +def bad_route_unhandled(): + raise ArithmeticError('Hello') + return render_template( + "hello.html", + title='Hello', + content='Flask-Jinja-Test' + ) + + +@app.route("/bad_template") +def bad_template(): + return render_template( + "bad.html", + title='Bad', + content='Flask-Jinja-Test' + ) + + +@app.route("/exit") +def exit_app(): + from flask import request + func = request.environ.get('werkzeug.server.shutdown') + if func is None: + raise RuntimeError('No shutdown') + func() + return 'Done' + + +if __name__ == '__main__': + app.run() diff --git a/tests_python/flask1/templates/bad.html b/tests_python/flask1/templates/bad.html new file mode 100644 index 0000000..5f552c6 --- /dev/null +++ b/tests_python/flask1/templates/bad.html @@ -0,0 +1,10 @@ + + + + + Test + + + {% doesnotexist %} + + \ No newline at end of file diff --git a/tests_python/flask1/templates/hello.html b/tests_python/flask1/templates/hello.html new file mode 100644 index 0000000..3784dad --- /dev/null +++ b/tests_python/flask1/templates/hello.html @@ -0,0 +1,10 @@ + + + + + {{ title }} + + + {{ content }} + + \ No newline at end of file diff --git a/tests_python/my_django_proj_17/.project b/tests_python/my_django_proj_17/.project new file mode 100644 index 0000000..00c3a2c --- /dev/null +++ b/tests_python/my_django_proj_17/.project @@ -0,0 +1,18 @@ + + + my_django_proj_17 + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + org.python.pydev.django.djangoNature + + diff --git a/tests_python/my_django_proj_17/.pydevproject b/tests_python/my_django_proj_17/.pydevproject new file mode 100644 index 0000000..6e842d0 --- /dev/null +++ b/tests_python/my_django_proj_17/.pydevproject @@ -0,0 +1,12 @@ + + + +DJANGO_MANAGE_LOCATION +manage.py + + +/${PROJECT_DIR_NAME} + +python 2.7 +Default + diff --git a/tests_python/my_django_proj_17/manage.py b/tests_python/my_django_proj_17/manage.py new file mode 100644 index 0000000..c29c377 --- /dev/null +++ b/tests_python/my_django_proj_17/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_django_proj_17.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/tests_python/my_django_proj_17/my_app/__init__.py b/tests_python/my_django_proj_17/my_app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/my_django_proj_17/my_app/admin.py b/tests_python/my_django_proj_17/my_app/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/tests_python/my_django_proj_17/my_app/forms.py b/tests_python/my_django_proj_17/my_app/forms.py new file mode 100644 index 0000000..fe03086 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/forms.py @@ -0,0 +1,4 @@ +from django import forms + +class NameForm(forms.Form): + your_name = forms.CharField(label='Your name', max_length=100) \ No newline at end of file diff --git a/tests_python/my_django_proj_17/my_app/models.py b/tests_python/my_django_proj_17/my_app/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/tests_python/my_django_proj_17/my_app/templates/my_app/index.html b/tests_python/my_django_proj_17/my_app/templates/my_app/index.html new file mode 100644 index 0000000..5cad374 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/templates/my_app/index.html @@ -0,0 +1,13 @@ +{% if entries %} +
    + {% for entry in entries %} +
  • + {{ entry.key }} + : + {{ entry.val }} +
  • + {% endfor %} +
+{% else %} +

No entries are available.

+{% endif %} \ No newline at end of file diff --git a/tests_python/my_django_proj_17/my_app/templates/my_app/inherited.html b/tests_python/my_django_proj_17/my_app/templates/my_app/inherited.html new file mode 100644 index 0000000..0105431 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/templates/my_app/inherited.html @@ -0,0 +1,5 @@ +{% if chat_mode %} + "chat_mode=True" +{% else %} + "chat_mode=False" +{% endif %} \ No newline at end of file diff --git a/tests_python/my_django_proj_17/my_app/templates/my_app/inherits.html b/tests_python/my_django_proj_17/my_app/templates/my_app/inherits.html new file mode 100644 index 0000000..8c7b9ab --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/templates/my_app/inherits.html @@ -0,0 +1,2 @@ +{% include 'my_app/inherited.html' with chat_mode=True %} +{% include 'my_app/inherited.html' with chat_mode=False %} \ No newline at end of file diff --git a/tests_python/my_django_proj_17/my_app/templates/my_app/name.html b/tests_python/my_django_proj_17/my_app/templates/my_app/name.html new file mode 100644 index 0000000..d47a2e1 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/templates/my_app/name.html @@ -0,0 +1,7 @@ +
+ {% csrf_token %} + {{ form }} + It is {% now "jS F Y H:i" %} + +
+

End of form

\ No newline at end of file diff --git a/tests_python/my_django_proj_17/my_app/templates/my_app/no_var_error.html b/tests_python/my_django_proj_17/my_app/templates/my_app/no_var_error.html new file mode 100644 index 0000000..bdb84e5 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/templates/my_app/no_var_error.html @@ -0,0 +1,5 @@ +{% if pat.name %} + pat.name={{ pat.name }} +{% else %} + no_pat_name +{% endif %} \ No newline at end of file diff --git a/tests_python/my_django_proj_17/my_app/templates/my_app/template_error.html b/tests_python/my_django_proj_17/my_app/templates/my_app/template_error.html new file mode 100644 index 0000000..4b2d703 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/templates/my_app/template_error.html @@ -0,0 +1,13 @@ +{% if entries %} +
    + {% for entry in entries %} +
  • + {{ entry.key }} + : + {{ entry.invalid_attribute }} +
  • + {% endfor %} +
+{% else %} +

No entries are available.

+{% endif %} \ No newline at end of file diff --git a/tests_python/my_django_proj_17/my_app/templates/my_app/template_error2.html b/tests_python/my_django_proj_17/my_app/templates/my_app/template_error2.html new file mode 100644 index 0000000..439f432 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/templates/my_app/template_error2.html @@ -0,0 +1,6 @@ + + + + {% doesnotexist %} + + \ No newline at end of file diff --git a/tests_python/my_django_proj_17/my_app/tests.py b/tests_python/my_django_proj_17/my_app/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/tests_python/my_django_proj_17/my_app/urls.py b/tests_python/my_django_proj_17/my_app/urls.py new file mode 100644 index 0000000..849aaf6 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/urls.py @@ -0,0 +1,12 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^$', views.index, name='index'), + url(r'^name$', views.get_name, name='name'), + url(r'^template_error$', views.template_error, name='template_error'), + url(r'^template_error2$', views.template_error2, name='template_error2'), + url(r'^inherits$', views.inherits, name='inherits'), + url(r'^no_var_error$', views.no_var_error, name='no_var_error'), +] diff --git a/tests_python/my_django_proj_17/my_app/views.py b/tests_python/my_django_proj_17/my_app/views.py new file mode 100644 index 0000000..c15a994 --- /dev/null +++ b/tests_python/my_django_proj_17/my_app/views.py @@ -0,0 +1,73 @@ +from django.shortcuts import render + +# Create your views here. +from django.http import HttpResponse, HttpResponseRedirect +import sys +from .forms import NameForm + + +class Entry(object): + + def __init__(self, key, val): + self.key = key + self.val = val + + def __unicode__(self): + return u'%s:%s' % (self.key, self.val) + + def __str__(self): + return u'%s:%s' % (self.key, self.val) + + +def index(request): + context = { + 'entries': [Entry('v1', 'v1'), Entry('v2', 'v2')] + } + ret = render(request, 'my_app/index.html', context) + return ret + + +def get_name(request): + # if this is a POST request we need to process the form data + if request.method == 'POST': + # create a form instance and populate it with data from the request: + form = NameForm(request.POST) + # check whether it's valid: + if form.is_valid(): + # process the data in form.cleaned_data as required + # ... + # redirect to a new URL: + return HttpResponseRedirect('/thanks/') + + # if a GET (or any other method) we'll create a blank form + else: + form = NameForm(data={'your_name': 'unknown name'}) + + return render(request, 'my_app/name.html', {'form': form}) + + +def inherits(request): + context = {} + ret = render(request, 'my_app/inherits.html', context) + return ret + + +def template_error(request): + context = { + 'entries': [Entry('v1', 'v1'), Entry('v2', 'v2')] + } + + ret = render(request, 'my_app/template_error.html', context) + return ret + + +def template_error2(request): + context = {} + ret = render(request, 'my_app/template_error2.html', context) + return ret + + +def no_var_error(request): + context = {} + ret = render(request, 'my_app/no_var_error.html', context) + return ret diff --git a/tests_python/my_django_proj_17/my_django_proj_17/__init__.py b/tests_python/my_django_proj_17/my_django_proj_17/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/my_django_proj_17/my_django_proj_17/settings.py b/tests_python/my_django_proj_17/my_django_proj_17/settings.py new file mode 100644 index 0000000..404f971 --- /dev/null +++ b/tests_python/my_django_proj_17/my_django_proj_17/settings.py @@ -0,0 +1,86 @@ +""" +Django settings for my_django_proj_17 project. + +For more information on this file, see +https://docs.djangoproject.com/en/1.7/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.7/ref/settings/ +""" + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os +BASE_DIR = os.path.dirname(os.path.dirname(__file__)) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'Placeholder_5_sue9bp&j=45#%_hcx3f34k!qnt$mxfd&7zq@7c7t@sn4_l)b' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +TEMPLATE_DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'my_app', +) + +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) + +ROOT_URLCONF = 'my_django_proj_17.urls' + +WSGI_APPLICATION = 'my_django_proj_17.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.7/ref/settings/#databases + +# No database for our test. + +# DATABASES = { +# 'default': { +# 'ENGINE': 'django.db.backends.sqlite3', +# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), +# } +# } + +# Internationalization +# https://docs.djangoproject.com/en/1.7/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.7/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/tests_python/my_django_proj_17/my_django_proj_17/urls.py b/tests_python/my_django_proj_17/my_django_proj_17/urls.py new file mode 100644 index 0000000..fc5c587 --- /dev/null +++ b/tests_python/my_django_proj_17/my_django_proj_17/urls.py @@ -0,0 +1,11 @@ +from django.conf.urls import patterns, include, url +from django.contrib import admin + +urlpatterns = patterns('', + # Examples: + # url(r'^$', 'my_django_proj_17.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), + url(r'^my_app/', include('my_app.urls')), +) diff --git a/tests_python/my_django_proj_17/my_django_proj_17/wsgi.py b/tests_python/my_django_proj_17/my_django_proj_17/wsgi.py new file mode 100644 index 0000000..c410e8d --- /dev/null +++ b/tests_python/my_django_proj_17/my_django_proj_17/wsgi.py @@ -0,0 +1,14 @@ +""" +WSGI config for my_django_proj_17 project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ +""" + +import os +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_django_proj_17.settings") + +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application() diff --git a/tests_python/my_django_proj_21/.project b/tests_python/my_django_proj_21/.project new file mode 100644 index 0000000..0109ff2 --- /dev/null +++ b/tests_python/my_django_proj_21/.project @@ -0,0 +1,18 @@ + + + my_django_proj_21 + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + org.python.pydev.django.djangoNature + + diff --git a/tests_python/my_django_proj_21/.pydevproject b/tests_python/my_django_proj_21/.pydevproject new file mode 100644 index 0000000..7b25ac2 --- /dev/null +++ b/tests_python/my_django_proj_21/.pydevproject @@ -0,0 +1,14 @@ + + + +DJANGO_MANAGE_LOCATION +manage.py +DJANGO_SETTINGS_MODULE +my_django_proj_21.settings + +python interpreter +Default + +/${PROJECT_DIR_NAME} + + diff --git a/tests_python/my_django_proj_21/.settings/org.eclipse.core.resources.prefs b/tests_python/my_django_proj_21/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..922acb3 --- /dev/null +++ b/tests_python/my_django_proj_21/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,27 @@ +eclipse.preferences.version=1 +encoding//.settings/org.python.pydev.yaml=UTF-8 +encoding//_pydevd_bundle/_debug_adapter/pydevd_schema.py=utf-8 +encoding//pydev_ipython/inputhook.py=utf-8 +encoding//pydev_ipython/inputhookglut.py=utf-8 +encoding//pydev_ipython/inputhookpyglet.py=utf-8 +encoding//pydev_ipython/inputhookqt4.py=utf-8 +encoding//pydev_ipython/inputhookqt5.py=utf-8 +encoding//pydev_ipython/inputhookwx.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/breakpoint.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/crash.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/interactive.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/plugins/do_exploitable.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/process.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/__init__.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/defines.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/kernel32.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/user32.py=utf-8 +encoding//pydevd_attach_to_process/winappdbg/win32/version.py=utf-8 +encoding//tests_python/debugger_fixtures.py=utf-8 +encoding//tests_python/test_collect_bytecode_info.py=utf-8 +encoding//tests_python/test_convert_utilities.py=utf-8 +encoding//tests_python/test_debugger.py=utf-8 +encoding//tests_python/test_debugger_json.py=utf-8 +encoding//tests_python/test_extract_token.py=utf-8 +encoding//tests_python/test_pydev_monkey.py=utf-8 +encoding//tests_python/test_safe_repr.py=utf-8 diff --git a/tests_python/my_django_proj_21/.settings/org.python.pydev.yaml b/tests_python/my_django_proj_21/.settings/org.python.pydev.yaml new file mode 100644 index 0000000..4a90160 --- /dev/null +++ b/tests_python/my_django_proj_21/.settings/org.python.pydev.yaml @@ -0,0 +1,47 @@ +ADD_NEW_LINE_AT_END_OF_FILE: true +AUTOPEP8_PARAMETERS: '' +AUTO_ADD_SELF: true +AUTO_BRACES: true +AUTO_COLON: true +AUTO_DEDENT_ELSE: true +AUTO_INDENT_AFTER_PAR_WIDTH: 1 +AUTO_INDENT_TO_PAR_LEVEL: false +AUTO_LINK: false +AUTO_LITERALS: true +AUTO_PAR: true +AUTO_WRITE_IMPORT_STR: true +BLACK_PARAMETERS: '' +BLANK_LINES_INNER: 1 +BLANK_LINES_TOP_LEVEL: 2 +BREAK_IMPORTS_MODE: PARENTHESIS +DATE_FIELD_FORMAT: yyyy-MM-dd +DATE_FIELD_NAME: __updated__ +DELETE_UNUSED_IMPORTS: false +ENABLE_DATE_FIELD_ACTION: false +FORMATTER_STYLE: PYDEVF +FORMAT_BEFORE_SAVING: true +FORMAT_ONLY_CHANGED_LINES: false +FORMAT_WITH_AUTOPEP8: false +FROM_IMPORTS_FIRST: false +GROUP_IMPORTS: true +IMPORT_ENGINE: IMPORT_ENGINE_PEP_8 +INDENT_AFTER_PAR_AS_PEP8: false +MANAGE_BLANK_LINES: true +MULTILINE_IMPORTS: true +PEP8_IMPORTS: true +PYDEV_TEST_RUNNER: '2' +PYDEV_TEST_RUNNER_DEFAULT_PARAMETERS: --capture=no -vv --tb=native -n 0 +PYDEV_USE_PYUNIT_VIEW: true +SAVE_ACTIONS_ONLY_ON_WORKSPACE_FILES: true +SMART_INDENT_PAR: true +SMART_LINE_MOVE: false +SORT_IMPORTS_ON_SAVE: false +SORT_NAMES_GROUPED: false +SPACES_BEFORE_COMMENT: '2' +SPACES_IN_START_COMMENT: '1' +TRIM_EMPTY_LINES: true +TRIM_MULTILINE_LITERALS: true +USE_ASSIGN_WITH_PACES_INSIDER_PARENTESIS: false +USE_OPERATORS_WITH_SPACE: true +USE_SPACE_AFTER_COMMA: true +USE_SPACE_FOR_PARENTESIS: false diff --git a/tests_python/my_django_proj_21/manage.py b/tests_python/my_django_proj_21/manage.py new file mode 100644 index 0000000..9692bd0 --- /dev/null +++ b/tests_python/my_django_proj_21/manage.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == '__main__': + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_django_proj_21.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) diff --git a/tests_python/my_django_proj_21/my_app/__init__.py b/tests_python/my_django_proj_21/my_app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/my_django_proj_21/my_app/admin.py b/tests_python/my_django_proj_21/my_app/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/tests_python/my_django_proj_21/my_app/apps.py b/tests_python/my_django_proj_21/my_app/apps.py new file mode 100644 index 0000000..885dfa0 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class MyAppConfig(AppConfig): + name = 'my_app' diff --git a/tests_python/my_django_proj_21/my_app/forms.py b/tests_python/my_django_proj_21/my_app/forms.py new file mode 100644 index 0000000..fe03086 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/forms.py @@ -0,0 +1,4 @@ +from django import forms + +class NameForm(forms.Form): + your_name = forms.CharField(label='Your name', max_length=100) \ No newline at end of file diff --git a/tests_python/my_django_proj_21/my_app/migrations/__init__.py b/tests_python/my_django_proj_21/my_app/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/my_django_proj_21/my_app/models.py b/tests_python/my_django_proj_21/my_app/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/tests_python/my_django_proj_21/my_app/templates/my_app/index.html b/tests_python/my_django_proj_21/my_app/templates/my_app/index.html new file mode 100644 index 0000000..5cad374 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/templates/my_app/index.html @@ -0,0 +1,13 @@ +{% if entries %} +
    + {% for entry in entries %} +
  • + {{ entry.key }} + : + {{ entry.val }} +
  • + {% endfor %} +
+{% else %} +

No entries are available.

+{% endif %} \ No newline at end of file diff --git a/tests_python/my_django_proj_21/my_app/templates/my_app/inherited.html b/tests_python/my_django_proj_21/my_app/templates/my_app/inherited.html new file mode 100644 index 0000000..0105431 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/templates/my_app/inherited.html @@ -0,0 +1,5 @@ +{% if chat_mode %} + "chat_mode=True" +{% else %} + "chat_mode=False" +{% endif %} \ No newline at end of file diff --git a/tests_python/my_django_proj_21/my_app/templates/my_app/inherits.html b/tests_python/my_django_proj_21/my_app/templates/my_app/inherits.html new file mode 100644 index 0000000..8c7b9ab --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/templates/my_app/inherits.html @@ -0,0 +1,2 @@ +{% include 'my_app/inherited.html' with chat_mode=True %} +{% include 'my_app/inherited.html' with chat_mode=False %} \ No newline at end of file diff --git a/tests_python/my_django_proj_21/my_app/templates/my_app/name.html b/tests_python/my_django_proj_21/my_app/templates/my_app/name.html new file mode 100644 index 0000000..d47a2e1 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/templates/my_app/name.html @@ -0,0 +1,7 @@ +
+ {% csrf_token %} + {{ form }} + It is {% now "jS F Y H:i" %} + +
+

End of form

\ No newline at end of file diff --git a/tests_python/my_django_proj_21/my_app/templates/my_app/no_var_error.html b/tests_python/my_django_proj_21/my_app/templates/my_app/no_var_error.html new file mode 100644 index 0000000..bdb84e5 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/templates/my_app/no_var_error.html @@ -0,0 +1,5 @@ +{% if pat.name %} + pat.name={{ pat.name }} +{% else %} + no_pat_name +{% endif %} \ No newline at end of file diff --git a/tests_python/my_django_proj_21/my_app/templates/my_app/template_error.html b/tests_python/my_django_proj_21/my_app/templates/my_app/template_error.html new file mode 100644 index 0000000..4b2d703 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/templates/my_app/template_error.html @@ -0,0 +1,13 @@ +{% if entries %} +
    + {% for entry in entries %} +
  • + {{ entry.key }} + : + {{ entry.invalid_attribute }} +
  • + {% endfor %} +
+{% else %} +

No entries are available.

+{% endif %} \ No newline at end of file diff --git a/tests_python/my_django_proj_21/my_app/templates/my_app/template_error2.html b/tests_python/my_django_proj_21/my_app/templates/my_app/template_error2.html new file mode 100644 index 0000000..439f432 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/templates/my_app/template_error2.html @@ -0,0 +1,6 @@ + + + + {% doesnotexist %} + + \ No newline at end of file diff --git a/tests_python/my_django_proj_21/my_app/tests.py b/tests_python/my_django_proj_21/my_app/tests.py new file mode 100644 index 0000000..759ab0e --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/tests.py @@ -0,0 +1,72 @@ +''' +Note: run test with manage.py test my_app + +This is mostly for experimenting. + +The actual code used is mostly a copy of this that lives in `django_debug.py`. +''' + +from django.test import SimpleTestCase + + +def collect_lines_for_django_template(template_contents): + from django import template + t = template.Template(template_contents) + return _collect_valid_lines_in_django_template(t) + + +def _collect_valid_lines_in_django_template(template): + lines = set() + for node in _iternodes(template.nodelist): + lineno = _get_lineno(node) + if lineno is not None: + lines.add(lineno) + return lines + + +def _get_lineno(node): + if hasattr(node, 'token') and hasattr(node.token, 'lineno'): + return node.token.lineno + return None + + +def _iternodes(nodelist): + for node in nodelist: + yield node + + try: + children = node.child_nodelists + except: + pass + else: + for attr in children: + nodelist = getattr(node, attr, None) + if nodelist: + # i.e.: yield from _iternodes(nodelist) + for node in _iternodes(nodelist): + yield node + + +class MyTest(SimpleTestCase): + + def test_something(self): + template_contents = '''{% if entries %} +
    + {% for entry in entries %} + {% for entry in entries2 %} +
  • + {{ entry.key }} + : + {{ entry.val }} +
  • + {% endfor %} + {% endfor %} +
+{% else %} +

No entries are available.

+{% endif %}''' + + self.assertEqual( + collect_lines_for_django_template(template_contents), + {1, 3, 4, 6, 8, 10, 11, 13} + ) diff --git a/tests_python/my_django_proj_21/my_app/urls.py b/tests_python/my_django_proj_21/my_app/urls.py new file mode 100644 index 0000000..4f02174 --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/urls.py @@ -0,0 +1,15 @@ +try: + from django.conf.urls import url +except ImportError: + from django.urls import re_path as url + +from . import views + +urlpatterns = [ + url(r'^$', views.index, name='index'), + url(r'^name$', views.get_name, name='name'), + url(r'^template_error2$', views.template_error2, name='template_error2'), + url(r'^template_error$', views.template_error, name='template_error'), + url(r'^inherits$', views.inherits, name='inherits'), + url(r'^no_var_error$', views.no_var_error, name='no_var_error'), +] diff --git a/tests_python/my_django_proj_21/my_app/views.py b/tests_python/my_django_proj_21/my_app/views.py new file mode 100644 index 0000000..db7872d --- /dev/null +++ b/tests_python/my_django_proj_21/my_app/views.py @@ -0,0 +1,80 @@ +from django.shortcuts import render + +# Create your views here. +from django.http import HttpResponse, HttpResponseRedirect +import sys +from .forms import NameForm + + +class Entry(object): + + def __init__(self, key, val): + self.key = key + self.val = val + + def __unicode__(self): + return u'%s:%s' % (self.key, self.val) + + def __str__(self): + return u'%s:%s' % (self.key, self.val) + + +def index(request): + import faulthandler + faulthandler.enable() + context = { + 'entries': [Entry('v1', 'v1'), Entry('v2', 'v2')] + } + ret = render(request, 'my_app/index.html', context) + return ret + + +def get_name(request): + import faulthandler + faulthandler.enable() + # if this is a POST request we need to process the form data + if request.method == 'POST': + # create a form instance and populate it with data from the request: + form = NameForm(request.POST) + # check whether it's valid: + if form.is_valid(): + # process the data in form.cleaned_data as required + # ... + # redirect to a new URL: + return HttpResponseRedirect('/thanks/') + + # if a GET (or any other method) we'll create a blank form + else: + form = NameForm(data={'your_name': 'unknown name'}) + + return render(request, 'my_app/name.html', {'form': form}) + + +def template_error(request): + import faulthandler + faulthandler.enable() + context = { + 'entries': [Entry('v1', 'v1'), Entry('v2', 'v2')] + } + ret = render(request, 'my_app/template_error.html', context) + return ret + + +def template_error2(request): + import faulthandler + faulthandler.enable() + context = {} + ret = render(request, 'my_app/template_error2.html', context) + return ret + + +def inherits(request): + context = {} + ret = render(request, 'my_app/inherits.html', context) + return ret + + +def no_var_error(request): + context = {} + ret = render(request, 'my_app/no_var_error.html', context) + return ret diff --git a/tests_python/my_django_proj_21/my_django_proj_21/__init__.py b/tests_python/my_django_proj_21/my_django_proj_21/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/my_django_proj_21/my_django_proj_21/settings.py b/tests_python/my_django_proj_21/my_django_proj_21/settings.py new file mode 100644 index 0000000..7a4bffe --- /dev/null +++ b/tests_python/my_django_proj_21/my_django_proj_21/settings.py @@ -0,0 +1,120 @@ +""" +Django settings for my_django_proj_21 project. + +Generated by 'django-admin startproject' using Django 2.1. + +For more information on this file, see +https://docs.djangoproject.com/en/2.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.1/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'Placeholder_u1jqdxv=z@ue9)%onkenaqb*&4dzd2mmb98#j*8uq^fn#j67)p' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'my_app', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'my_django_proj_21.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'my_django_proj_21.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.1/ref/settings/#databases +# No database for our test. +# DATABASES = { +# 'default': { +# 'ENGINE': 'django.db.backends.sqlite3', +# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), +# } +# } + +# Password validation +# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/2.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.1/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/tests_python/my_django_proj_21/my_django_proj_21/urls.py b/tests_python/my_django_proj_21/my_django_proj_21/urls.py new file mode 100644 index 0000000..f8173dc --- /dev/null +++ b/tests_python/my_django_proj_21/my_django_proj_21/urls.py @@ -0,0 +1,23 @@ +"""my_django_proj_21 URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path +from django.urls.conf import include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('my_app/', include('my_app.urls')), +] diff --git a/tests_python/my_django_proj_21/my_django_proj_21/wsgi.py b/tests_python/my_django_proj_21/my_django_proj_21/wsgi.py new file mode 100644 index 0000000..0018842 --- /dev/null +++ b/tests_python/my_django_proj_21/my_django_proj_21/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for my_django_proj_21 project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_django_proj_21.settings') + +application = get_wsgi_application() diff --git a/tests_python/my_extensions/pydevd_plugins/__init__.py b/tests_python/my_extensions/pydevd_plugins/__init__.py new file mode 100644 index 0000000..274d7bc --- /dev/null +++ b/tests_python/my_extensions/pydevd_plugins/__init__.py @@ -0,0 +1,7 @@ +import warnings +with warnings.catch_warnings(): + try: + __import__('pkg_resources').declare_namespace(__name__) + except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/tests_python/my_extensions/pydevd_plugins/extensions/__init__.py b/tests_python/my_extensions/pydevd_plugins/extensions/__init__.py new file mode 100644 index 0000000..274d7bc --- /dev/null +++ b/tests_python/my_extensions/pydevd_plugins/extensions/__init__.py @@ -0,0 +1,7 @@ +import warnings +with warnings.catch_warnings(): + try: + __import__('pkg_resources').declare_namespace(__name__) + except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/tests_python/my_extensions/pydevd_plugins/extensions/pydevd_plugin_test_events.py b/tests_python/my_extensions/pydevd_plugins/extensions/pydevd_plugin_test_events.py new file mode 100644 index 0000000..71c1ef9 --- /dev/null +++ b/tests_python/my_extensions/pydevd_plugins/extensions/pydevd_plugin_test_events.py @@ -0,0 +1,18 @@ +from _pydevd_bundle.pydevd_extension_api import DebuggerEventHandler +import os +import sys + + +class VerifyEvent(object): + def on_debugger_modules_loaded(self, **kwargs): + print ("INITIALIZE EVENT RECEIVED") + # check that some core modules are loaded before this callback is invoked + modules_loaded = all(mod in sys.modules for mod in ('pydevd_file_utils', '_pydevd_bundle.pydevd_constants')) + if modules_loaded: + print ("TEST SUCEEDED") # incorrect spelling on purpose + else: + print ("TEST FAILED") + + +if os.environ.get("VERIFY_EVENT_TEST"): + DebuggerEventHandler.register(VerifyEvent) diff --git a/tests_python/my_extensions/pydevd_plugins/extensions/pydevd_plugin_test_exttype.py b/tests_python/my_extensions/pydevd_plugins/extensions/pydevd_plugin_test_exttype.py new file mode 100644 index 0000000..c3a7f78 --- /dev/null +++ b/tests_python/my_extensions/pydevd_plugins/extensions/pydevd_plugin_test_exttype.py @@ -0,0 +1,20 @@ +from _pydevd_bundle.pydevd_extension_api import StrPresentationProvider, TypeResolveProvider + + +class RectResolver(TypeResolveProvider): + def get_dictionary(self, var): + return {'length': var.length, 'width': var.width, 'area': var.length * var.width} + + def resolve(self, var, attribute): + return getattr(var, attribute, None) if attribute != 'area' else var.length * var.width + + def can_provide(self, type_object, type_name): + return type_name.endswith('Rect') + + +class RectToString(StrPresentationProvider): + def get_str(self, val): + return "Rectangle[Length: %s, Width: %s , Area: %s]" % (val.length, val.width, val.length * val.width) + + def can_provide(self, type_object, type_name): + return type_name.endswith('Rect') diff --git a/tests_python/performance_check.py b/tests_python/performance_check.py new file mode 100644 index 0000000..edb5c27 --- /dev/null +++ b/tests_python/performance_check.py @@ -0,0 +1,245 @@ +from tests_python import debugger_unittest +import sys +import re +import os + +CHECK_BASELINE, CHECK_REGULAR, CHECK_CYTHON, CHECK_FRAME_EVAL = 'baseline', 'regular', 'cython', 'frame_eval' + +pytest_plugins = [ + str('tests_python.debugger_fixtures'), +] + +RUNS = 5 + + +class PerformanceWriterThread(debugger_unittest.AbstractWriterThread): + + CHECK = None + + debugger_unittest.AbstractWriterThread.get_environ # overrides + + def get_environ(self): + env = os.environ.copy() + if self.CHECK == CHECK_BASELINE: + env['PYTHONPATH'] = r'X:\PyDev.Debugger.baseline' + + elif self.CHECK == CHECK_CYTHON: + env['PYDEVD_USE_CYTHON'] = 'YES' + env['PYDEVD_USE_FRAME_EVAL'] = 'NO' + + elif self.CHECK == CHECK_FRAME_EVAL: + env['PYDEVD_USE_CYTHON'] = 'YES' + env['PYDEVD_USE_FRAME_EVAL'] = 'YES' + + elif self.CHECK == CHECK_REGULAR: + env['PYDEVD_USE_CYTHON'] = 'NO' + env['PYDEVD_USE_FRAME_EVAL'] = 'NO' + + else: + raise AssertionError("Don't know what to check.") + return env + + debugger_unittest.AbstractWriterThread.get_pydevd_file # overrides + + def get_pydevd_file(self): + if self.CHECK == CHECK_BASELINE: + return os.path.abspath(os.path.join(r'X:\PyDev.Debugger.baseline', 'pydevd.py')) + dirname = os.path.dirname(__file__) + dirname = os.path.dirname(dirname) + return os.path.abspath(os.path.join(dirname, 'pydevd.py')) + + +class CheckDebuggerPerformance(debugger_unittest.DebuggerRunner): + + def get_command_line(self): + return [sys.executable] + + def _get_time_from_result(self, stdout): + match = re.search(r'TotalTime>>((\d|\.)+)<<', stdout) + time_taken = match.group(1) + return float(time_taken) + + def obtain_results(self, benchmark_name, filename): + + class PerformanceCheck(PerformanceWriterThread): + TEST_FILE = debugger_unittest._get_debugger_test_file(filename) + BENCHMARK_NAME = benchmark_name + + writer_thread_class = PerformanceCheck + + runs = RUNS + all_times = [] + for _ in range(runs): + stdout_ref = [] + + def store_stdout(stdout, stderr): + stdout_ref.append(stdout) + + with self.check_case(writer_thread_class) as writer: + writer.additional_output_checks = store_stdout + yield writer + + assert len(stdout_ref) == 1 + all_times.append(self._get_time_from_result(stdout_ref[0])) + print('partial for: %s: %.3fs' % (writer_thread_class.BENCHMARK_NAME, all_times[-1])) + if len(all_times) > 3: + all_times.remove(min(all_times)) + all_times.remove(max(all_times)) + time_when_debugged = sum(all_times) / float(len(all_times)) + + args = self.get_command_line() + args.append(writer_thread_class.TEST_FILE) + # regular_time = self._get_time_from_result(self.run_process(args, writer_thread=None)) + # simple_trace_time = self._get_time_from_result(self.run_process(args+['--regular-trace'], writer_thread=None)) + + if 'SPEEDTIN_AUTHORIZATION_KEY' in os.environ: + + SPEEDTIN_AUTHORIZATION_KEY = os.environ['SPEEDTIN_AUTHORIZATION_KEY'] + + # sys.path.append(r'X:\speedtin\pyspeedtin') + import pyspeedtin # If the authorization key is there, pyspeedtin must be available + import pydevd + pydevd_cython_project_id, pydevd_pure_python_project_id = 6, 7 + if writer_thread_class.CHECK == CHECK_BASELINE: + project_ids = (pydevd_cython_project_id, pydevd_pure_python_project_id) + elif writer_thread_class.CHECK == CHECK_REGULAR: + project_ids = (pydevd_pure_python_project_id,) + elif writer_thread_class.CHECK == CHECK_CYTHON: + project_ids = (pydevd_cython_project_id,) + else: + raise AssertionError('Wrong check: %s' % (writer_thread_class.CHECK)) + for project_id in project_ids: + api = pyspeedtin.PySpeedTinApi(authorization_key=SPEEDTIN_AUTHORIZATION_KEY, project_id=project_id) + + benchmark_name = writer_thread_class.BENCHMARK_NAME + + if writer_thread_class.CHECK == CHECK_BASELINE: + version = '0.0.1_baseline' + return # No longer commit the baseline (it's immutable right now). + else: + version = pydevd.__version__, + + commit_id, branch, commit_date = api.git_commit_id_branch_and_date_from_path(pydevd.__file__) + api.add_benchmark(benchmark_name) + api.add_measurement( + benchmark_name, + value=time_when_debugged, + version=version, + released=False, + branch=branch, + commit_id=commit_id, + commit_date=commit_date, + ) + api.commit() + + self.performance_msg = '%s: %.3fs ' % (writer_thread_class.BENCHMARK_NAME, time_when_debugged) + + def method_calls_with_breakpoint(self): + for writer in self.obtain_results('method_calls_with_breakpoint', '_performance_1.py'): + writer.write_add_breakpoint(17, 'method') + writer.write_make_initial_run() + writer.finished_ok = True + + return self.performance_msg + + def method_calls_without_breakpoint(self): + for writer in self.obtain_results('method_calls_without_breakpoint', '_performance_1.py'): + writer.write_make_initial_run() + writer.finished_ok = True + + return self.performance_msg + + def method_calls_with_step_over(self): + for writer in self.obtain_results('method_calls_with_step_over', '_performance_1.py'): + writer.write_add_breakpoint(26, None) + + writer.write_make_initial_run() + hit = writer.wait_for_breakpoint_hit('111') + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit('108') + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + return self.performance_msg + + def method_calls_with_exception_breakpoint(self): + for writer in self.obtain_results('method_calls_with_exception_breakpoint', '_performance_1.py'): + writer.write_add_exception_breakpoint('ValueError') + writer.write_make_initial_run() + writer.finished_ok = True + + return self.performance_msg + + def global_scope_1_with_breakpoint(self): + for writer in self.obtain_results('global_scope_1_with_breakpoint', '_performance_2.py'): + writer.write_add_breakpoint(writer.get_line_index_with_content('Breakpoint here'), None) + writer.write_make_initial_run() + writer.finished_ok = True + + return self.performance_msg + + def global_scope_2_with_breakpoint(self): + for writer in self.obtain_results('global_scope_2_with_breakpoint', '_performance_3.py'): + writer.write_add_breakpoint(17, None) + writer.write_make_initial_run() + writer.finished_ok = True + + return self.performance_msg + + +if __name__ == '__main__': + # Local times gotten (python 3.6) + # method_calls_with_breakpoint: 1.150s + # method_calls_without_breakpoint: 0.240s + # method_calls_with_step_over: 2.680s + # method_calls_with_exception_breakpoint: 0.235s + # global_scope_1_with_breakpoint: 4.249s + # global_scope_2_with_breakpoint: 2.807s + # Checking: cython + # method_calls_with_breakpoint: 0.526s + # method_calls_without_breakpoint: 0.130s + # method_calls_with_step_over: 1.133s + # method_calls_with_exception_breakpoint: 0.136s + # global_scope_1_with_breakpoint: 1.827s + # global_scope_2_with_breakpoint: 1.405s + # Checking: frame_eval + # method_calls_with_breakpoint: 0.133s + # method_calls_without_breakpoint: 0.128s + # method_calls_with_step_over: 0.130s + # method_calls_with_exception_breakpoint: 0.125s + # global_scope_1_with_breakpoint: 0.281s + # global_scope_2_with_breakpoint: 0.169s + # TotalTime for profile: 209.01s + + debugger_unittest.SHOW_WRITES_AND_READS = False + debugger_unittest.SHOW_OTHER_DEBUG_INFO = False + debugger_unittest.SHOW_STDOUT = False + + import time + start_time = time.time() + + tmpdir = None + + msgs = [] + for check in ( + # CHECK_BASELINE, -- Checks against the version checked out at X:\PyDev.Debugger.baseline. + CHECK_REGULAR, + CHECK_CYTHON, + CHECK_FRAME_EVAL, + ): + PerformanceWriterThread.CHECK = check + msgs.append('Checking: %s' % (check,)) + check_debugger_performance = CheckDebuggerPerformance(tmpdir) + msgs.append(check_debugger_performance.method_calls_with_breakpoint()) + msgs.append(check_debugger_performance.method_calls_without_breakpoint()) + msgs.append(check_debugger_performance.method_calls_with_step_over()) + msgs.append(check_debugger_performance.method_calls_with_exception_breakpoint()) + msgs.append(check_debugger_performance.global_scope_1_with_breakpoint()) + msgs.append(check_debugger_performance.global_scope_2_with_breakpoint()) + + for msg in msgs: + print(msg) + + print('TotalTime for profile: %.2fs' % (time.time() - start_time,)) diff --git a/tests_python/regression_check.py b/tests_python/regression_check.py new file mode 100644 index 0000000..a7dc74f --- /dev/null +++ b/tests_python/regression_check.py @@ -0,0 +1,240 @@ +# Based on: https://github.com/ESSS/pytest-regressions (License: MIT) +# Created copy because we need Python 2.6 which is not available on pytest-regressions. +# Note: only used for testing. + +# encoding: UTF-8 +import difflib +import pytest +import sys +from functools import partial + +if sys.version_info[0] <= 2: + from pathlib2 import Path +else: + from pathlib import Path + +FORCE_REGEN = False + + +@pytest.fixture +def original_datadir(request): + # Method from: https://github.com/gabrielcnr/pytest-datadir + # License: MIT + import os.path + return Path(os.path.splitext(request.module.__file__)[0]) + + +@pytest.fixture +def datadir(original_datadir, tmpdir): + # Method from: https://github.com/gabrielcnr/pytest-datadir + # License: MIT + import shutil + result = Path(str(tmpdir.join(original_datadir.stem))) + if original_datadir.is_dir(): + shutil.copytree(str(original_datadir), str(result)) + else: + result.mkdir() + return result + + +@pytest.fixture +def data_regression(datadir, original_datadir, request): + return DataRegressionFixture(datadir, original_datadir, request) + + +def check_text_files(obtained_fn, expected_fn, fix_callback=lambda x: x, encoding=None): + """ + Compare two files contents. If the files differ, show the diff and write a nice HTML + diff file into the data directory. + :param Path obtained_fn: path to obtained file during current testing. + :param Path expected_fn: path to the expected file, obtained from previous testing. + :param str encoding: encoding used to open the files. + :param callable fix_callback: + A callback to "fix" the contents of the obtained (first) file. + This callback receives a list of strings (lines) and must also return a list of lines, + changed as needed. + The resulting lines will be used to compare with the contents of expected_fn. + """ + __tracebackhide__ = True + + obtained_fn = Path(obtained_fn) + expected_fn = Path(expected_fn) + obtained_lines = fix_callback(obtained_fn.read_text(encoding=encoding).splitlines()) + expected_lines = expected_fn.read_text(encoding=encoding).splitlines() + + if obtained_lines != expected_lines: + diff_lines = list(difflib.unified_diff(expected_lines, obtained_lines)) + if len(diff_lines) <= 500: + html_fn = obtained_fn.with_suffix(".diff.html") + try: + differ = difflib.HtmlDiff() + html_diff = differ.make_file( + fromlines=expected_lines, + fromdesc=expected_fn, + tolines=obtained_lines, + todesc=obtained_fn, + ) + except Exception as e: + html_fn = "(failed to generate html diff: %s)" % e + else: + html_fn.write_text(html_diff, encoding="UTF-8") + + diff = ["FILES DIFFER:", str(expected_fn), str(obtained_fn)] + diff += ["HTML DIFF: %s" % html_fn] + diff += diff_lines + raise AssertionError("\n".join(diff)) + else: + # difflib has exponential scaling and for thousands of lines it starts to take minutes to render + # the HTML diff. + msg = [ + "Files are different, but diff is too big (%s lines)" % (len(diff_lines),), + "- obtained: %s" % (obtained_fn,), + "- expected: %s" % (expected_fn,), + ] + raise AssertionError("\n".join(msg)) + + +def perform_regression_check( + datadir, + original_datadir, + request, + check_fn, + dump_fn, + extension, + basename=None, + fullpath=None, + obtained_filename=None, + dump_aux_fn=lambda filename: [], +): + """ + First run of this check will generate a expected file. Following attempts will always try to + match obtained files with that expected file. + :param Path datadir: Fixture embed_data. + :param Path original_datadir: Fixture embed_data. + :param SubRequest request: Pytest request object. + :param callable check_fn: A function that receives as arguments, respectively, absolute path to + obtained file and absolute path to expected file. It must assert if contents of file match. + Function can safely assume that obtained file is already dumped and only care about + comparison. + :param callable dump_fn: A function that receive an absolute file path as argument. Implementor + must dump file in this path. + :param callable dump_aux_fn: A function that receives the same file path as ``dump_fn``, but may + dump additional files to help diagnose this regression later (for example dumping image of + 3d views and plots to compare later). Must return the list of file names written (used to display). + :param six.text_type extension: Extension of files compared by this check. + :param six.text_type obtained_filename: complete path to use to write the obtained file. By + default will prepend `.obtained` before the file extension. + ..see: `data_regression.Check` for `basename` and `fullpath` arguments. + """ + import re + + assert not (basename and fullpath), "pass either basename or fullpath, but not both" + + __tracebackhide__ = True + + if basename is None: + basename = re.sub(r"[\W]", "_", request.node.name) + + if fullpath: + filename = source_filename = Path(fullpath) + else: + filename = datadir / (basename + extension) + source_filename = original_datadir / (basename + extension) + + def make_location_message(banner, filename, aux_files): + msg = [banner, "- %s" % (filename,)] + if aux_files: + msg.append("Auxiliary:") + msg += ["- %s" % (x,) for x in aux_files] + return "\n".join(msg) + + if not filename.is_file(): + source_filename.parent.mkdir(parents=True, exist_ok=True) + dump_fn(source_filename) + aux_created = dump_aux_fn(source_filename) + + msg = make_location_message( + "File not found in data directory, created:", source_filename, aux_created + ) + pytest.fail(msg) + else: + if obtained_filename is None: + if fullpath: + obtained_filename = (datadir / basename).with_suffix( + ".obtained" + extension + ) + else: + obtained_filename = filename.with_suffix(".obtained" + extension) + + dump_fn(obtained_filename) + + try: + check_fn(obtained_filename, filename) + except AssertionError: + if FORCE_REGEN: + dump_fn(source_filename) + aux_created = dump_aux_fn(source_filename) + msg = make_location_message( + "Files differ and FORCE_REGEN set, regenerating file at:", + source_filename, + aux_created, + ) + pytest.fail(msg) + else: + dump_aux_fn(obtained_filename) + raise + + +class DataRegressionFixture(object): + """ + Implementation of `data_regression` fixture. + """ + + def __init__(self, datadir, original_datadir, request): + """ + :type datadir: Path + :type original_datadir: Path + :type request: FixtureRequest + """ + self.request = request + self.datadir = datadir + self.original_datadir = original_datadir + + def check(self, data_dict, basename=None, fullpath=None): + """ + Checks the given dict against a previously recorded version, or generate a new file. + :param dict data_dict: any yaml serializable dict. + :param str basename: basename of the file to test/record. If not given the name + of the test is used. + Use either `basename` or `fullpath`. + :param str fullpath: complete path to use as a reference file. This option + will ignore ``datadir`` fixture when reading *expected* files but will still use it to + write *obtained* files. Useful if a reference file is located in the session data dir for example. + ``basename`` and ``fullpath`` are exclusive. + """ + __tracebackhide__ = True + + def dump(filename): + """Dump dict contents to the given filename""" + import json + + s = json.dumps(data_dict, sort_keys=True, indent=4) + if isinstance(s, bytes): + s = s.decode('utf-8') + + s = u'\n'.join([line.rstrip() for line in s.splitlines()]) + s = s.encode('utf-8') + + with filename.open("wb") as f: + f.write(s) + + perform_regression_check( + datadir=self.datadir, + original_datadir=self.original_datadir, + request=self.request, + check_fn=partial(check_text_files, encoding="UTF-8"), + dump_fn=dump, + extension=".json", + basename=basename, + fullpath=fullpath, + ) diff --git a/tests_python/resource_path_translation/__init__.py b/tests_python/resource_path_translation/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resource_path_translation/other.py b/tests_python/resource_path_translation/other.py new file mode 100644 index 0000000..369a9b2 --- /dev/null +++ b/tests_python/resource_path_translation/other.py @@ -0,0 +1,6 @@ + + +def call_me_back1(callback): + a = 'other' + callback() + return a diff --git a/tests_python/resources/__init__.py b/tests_python/resources/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resources/_bytecode_big_method.py b/tests_python/resources/_bytecode_big_method.py new file mode 100644 index 0000000..2ec3cb3 --- /dev/null +++ b/tests_python/resources/_bytecode_big_method.py @@ -0,0 +1,331 @@ +def foo(): + a=1 + b=2 + c=3 + d=4 + e=5 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + if a == 1: + if b == 2: + if c == 3: + if d == 999: + x = 20 + elif d == 998: + x = 40 + elif d == 4: + if e != 5: + x = 20 + else: + x = 50 + assert x \ No newline at end of file diff --git a/tests_python/resources/_bytecode_constructs.py b/tests_python/resources/_bytecode_constructs.py new file mode 100644 index 0000000..6bda76c --- /dev/null +++ b/tests_python/resources/_bytecode_constructs.py @@ -0,0 +1,126 @@ +from contextlib import contextmanager + + +def method1(): + + _a = 0 + while _a < 2: # break while + _a += 1 + + +def method2(): + try: + raise AssertionError() + except: # break except + pass + + +@contextmanager +def ctx(): + yield '' + + +def method3(): + with ctx() as a: # break with + return a + + +def method4(): + _a = 0 + for i in range(2): # break for + _a = i + + +def method5(): + try: # break try 1 + _a = 10 + finally: + _b = 10 + + +def method6(): + try: + _a = 10 # break try 2 + finally: + _b = 10 + + +def method7(): + try: + _a = 10 + finally: + _b = 10 # break finally 1 + + +def method8(): + try: + raise AssertionError() + except: # break except 2 + _b = 10 + finally: + _c = 20 + + +def method9(): + # As a note, Python 3.10 is eager to optimize this case and it duplicates the _c = 20 + # in a codepath where the exception is raised and another where it's not raised. + # The frame eval mode must modify the bytecode so that both paths have the + # programmatic breakpoint added! + try: + _a = 10 + except: + _b = 10 + finally:_c = 20 # break finally 2 + + +def method9a(): + # Same as method9, but with exception raised (but handled). + try: + raise AssertionError() + except: + _b = 10 + finally:_c = 20 # break finally 3 + + +def method9b(): + # Same as method9, but with exception raised (unhandled). + try: + try: + raise RuntimeError() + except AssertionError: + _b = 10 + finally:_c = 20 # break finally 4 + except: + pass + + +def method10(): + _a = { + 0: 0, + 1: 1, # break in dict + 2: 2, + } + + +def method11(): + a = 11 + if a == 10: + a = 20 + else: a = 30 # break else + + +if __name__ == '__main__': + method1() + method2() + method3() + method4() + method5() + method6() + method7() + method8() + method9() + method9a() + method9b() + method10() + method11() + print('TEST SUCEEDED') diff --git a/tests_python/resources/_bytecode_many_names_example.py b/tests_python/resources/_bytecode_many_names_example.py new file mode 100644 index 0000000..6221725 --- /dev/null +++ b/tests_python/resources/_bytecode_many_names_example.py @@ -0,0 +1,268 @@ + + +def foo(): + a0 = 1 + a1 = 1 + a2 = 1 + a3 = 1 + a4 = 1 + a5 = 1 + a6 = 1 + a7 = 1 + a8 = 1 + a9 = 1 + a10 = 1 + a11 = 1 + a12 = 1 + a13 = 1 + a14 = 1 + a15 = 1 + a16 = 1 + a17 = 1 + a18 = 1 + a19 = 1 + a20 = 1 + a21 = 1 + a22 = 1 + a23 = 1 + a24 = 1 + a25 = 1 + a26 = 1 + a27 = 1 + a28 = 1 + a29 = 1 + a30 = 1 + a31 = 1 + a32 = 1 + a33 = 1 + a34 = 1 + a35 = 1 + a36 = 1 + a37 = 1 + a38 = 1 + a39 = 1 + a40 = 1 + a41 = 1 + a42 = 1 + a43 = 1 + a44 = 1 + a45 = 1 + a46 = 1 + a47 = 1 + a48 = 1 + a49 = 1 + a50 = 1 + a51 = 1 + a52 = 1 + a53 = 1 + a54 = 1 + a55 = 1 + a56 = 1 + a57 = 1 + a58 = 1 + a59 = 1 + a60 = 1 + a61 = 1 + a62 = 1 + a63 = 1 + a64 = 1 + a65 = 1 + a66 = 1 + a67 = 1 + a68 = 1 + a69 = 1 + a70 = 1 + a71 = 1 + a72 = 1 + a73 = 1 + a74 = 1 + a75 = 1 + a76 = 1 + a77 = 1 + a78 = 1 + a79 = 1 + a80 = 1 + a81 = 1 + a82 = 1 + a83 = 1 + a84 = 1 + a85 = 1 + a86 = 1 + a87 = 1 + a88 = 1 + a89 = 1 + a90 = 1 + a91 = 1 + a92 = 1 + a93 = 1 + a94 = 1 + a95 = 1 + a96 = 1 + a97 = 1 + a98 = 1 + a99 = 1 + a100 = 1 + a101 = 1 + a102 = 1 + a103 = 1 + a104 = 1 + a105 = 1 + a106 = 1 + a107 = 1 + a108 = 1 + a109 = 1 + a110 = 1 + a111 = 1 + a112 = 1 + a113 = 1 + a114 = 1 + a115 = 1 + a116 = 1 + a117 = 1 + a118 = 1 + a119 = 1 + a120 = 1 + a121 = 1 + a122 = 1 + a123 = 1 + a124 = 1 + a125 = 1 + a126 = 1 + a127 = 1 + a128 = 1 + a129 = 1 + a130 = 1 + a131 = 1 + a132 = 1 + a133 = 1 + a134 = 1 + a135 = 1 + a136 = 1 + a137 = 1 + a138 = 1 + a139 = 1 + a140 = 1 + a141 = 1 + a142 = 1 + a143 = 1 + a144 = 1 + a145 = 1 + a146 = 1 + a147 = 1 + a148 = 1 + a149 = 1 + a150 = 1 + a151 = 1 + a152 = 1 + a153 = 1 + a154 = 1 + a155 = 1 + a156 = 1 + a157 = 1 + a158 = 1 + a159 = 1 + a160 = 1 + a161 = 1 + a162 = 1 + a163 = 1 + a164 = 1 + a165 = 1 + a166 = 1 + a167 = 1 + a168 = 1 + a169 = 1 + a170 = 1 + a171 = 1 + a172 = 1 + a173 = 1 + a174 = 1 + a175 = 1 + a176 = 1 + a177 = 1 + a178 = 1 + a179 = 1 + a180 = 1 + a181 = 1 + a182 = 1 + a183 = 1 + a184 = 1 + a185 = 1 + a186 = 1 + a187 = 1 + a188 = 1 + a189 = 1 + a190 = 1 + a191 = 1 + a192 = 1 + a193 = 1 + a194 = 1 + a195 = 1 + a196 = 1 + a197 = 1 + a198 = 1 + a199 = 1 + a200 = 1 + a201 = 1 + a202 = 1 + a203 = 1 + a204 = 1 + a205 = 1 + a206 = 1 + a207 = 1 + a208 = 1 + a209 = 1 + a210 = 1 + a211 = 1 + a212 = 1 + a213 = 1 + a214 = 1 + a215 = 1 + a216 = 1 + a217 = 1 + a218 = 1 + a219 = 1 + a220 = 1 + a221 = 1 + a222 = 1 + a223 = 1 + a224 = 1 + a225 = 1 + a226 = 1 + a227 = 1 + a228 = 1 + a229 = 1 + a230 = 1 + a231 = 1 + a232 = 1 + a233 = 1 + a234 = 1 + a235 = 1 + a236 = 1 + a237 = 1 + a238 = 1 + a239 = 1 + a240 = 1 + a241 = 1 + a242 = 1 + a243 = 1 + a244 = 1 + a245 = 1 + a246 = 1 + a247 = 1 + a248 = 1 + a249 = 1 + a250 = 1 + a251 = 1 + a252 = 1 + a253 = 1 + a254 = 1 + a255 = 1 + a256 = 1 + a257 = 1 + a258 = 1 + a259 = 1 + b = a1 + a2 + a260 = 1 + a261 = 1 + return b + diff --git a/tests_python/resources/_bytecode_overflow_example.py b/tests_python/resources/_bytecode_overflow_example.py new file mode 100644 index 0000000..6f596fd --- /dev/null +++ b/tests_python/resources/_bytecode_overflow_example.py @@ -0,0 +1,89 @@ +def check_backtrack(x): # line 1 + if not (x == 'a' # line 2 + or x == 'c'): # line 3 + pass # line 4 + + +import re +import sys + +en_lang_symbols = r'[^\w!@#$%\^-_+=|\}{][\"\';:?\/><.,&)(*\s`\u2019]' +en_words_basic = [] +en_words = [] + + +class Dummy: + non_en_words_limit = 3 + + @staticmethod + def fun(text): + words = tuple(w[0].lower() for w in re.finditer(r'[a-zA-Z]+', text)) + non_en_pass = [] + for i, word in enumerate(words): + non_en = [] + if not (word in en_words_basic + or (word.endswith('s') and word[:-1] in en_words_basic) + or (word.endswith('ed') and word[:-2] in en_words_basic) + or (word.endswith('ing') and word[:-3] in en_words_basic) + or word in en_words + or (word.endswith('s') and word[:-1] in en_words) + or (word.endswith('ed') and word[:-2] in en_words) + or (word.endswith('ing') and word[:-3] in en_words) + ): + + non_en.append(word) + non_en_pass.append(word) + for j in range(1, Dummy.non_en_words_limit): + if i + j >= len(words): + break + word = words[i + j] + + if (word in en_words_basic + or (word.endswith('s') and word[:-1] in en_words_basic) + or (word.endswith('ed') and word[:-2] in en_words_basic) + or (word.endswith('ing') and word[:-3] in en_words_basic) + or word in en_words + or (word.endswith('s') and word[:-1] in en_words) + or (word.endswith('ed') and word[:-2] in en_words) + or (word.endswith('ing') and word[:-3] in en_words) + ): + break + else: + non_en.append(word) + non_en_pass.append(word) + + +def offset_overflow(stream=sys.stdout): + a = 1 + b = 2 + c = 3 + a1 = 1 if a > 1 else 2 + a2 = 1 if a > 1 else 2 + a3 = 1 if a > 1 else 2 + a4 = 1 if a > 1 else 2 + a5 = 1 if a > 1 else 2 + a6 = 1 if a > 1 else 2 + a7 = 1 if a > 1 else 2 + a8 = 1 if a > 1 else 2 + a9 = 1 if a > 1 else 2 + a10 = 1 if a > 1 else 2 + a11 = 1 if a > 1 else 2 + a12 = 1 if a > 1 else 2 + a13 = 1 if a > 1 else 2 + + for i in range(1): + if a > 0: + stream.write("111\n") + # a = 1 + else: + stream.write("222\n") + return b + + +def long_lines(): + a = 1 + b = 1 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 + c = 1 if b > 1 else 2 if b > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 + d = 1 if c > 1 else 2 if c > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 + e = d + 1 + return e diff --git a/tests_python/resources/_bytecode_super.py b/tests_python/resources/_bytecode_super.py new file mode 100644 index 0000000..6ae6ad8 --- /dev/null +++ b/tests_python/resources/_bytecode_super.py @@ -0,0 +1,22 @@ +class A(object): + + def __init__(self): + self.a = 10 + + +class B(A): + + def __init__(self): + super().__init__() # break here + assert self.a == 10 + + def method(): + self.b = self.a + + method() + assert self.b == 10 + + +if __name__ == '__main__': + B() + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case1.py b/tests_python/resources/_debugger_case1.py new file mode 100644 index 0000000..7ef8062 --- /dev/null +++ b/tests_python/resources/_debugger_case1.py @@ -0,0 +1,61 @@ +import sys +import weakref + +def set_up(): + observable = Observable() + observer = Observer() + observable.add_observer(observer) + return observable + + +class Observable(object): + def __init__(self): + self.observers = [] + + def add_observer(self, observer): + sys.stdout.write( 'observer %s\n' % (observer,)) + ref = weakref.ref(observer) + self.observers.append(ref) + sys.stdout.write('weakref: %s\n' % (ref(),)) + + def Notify(self): + for o in self.observers: + o = o() + + + try: + import gc + except ImportError: + o = None #some jython does not have gc, so, there's no sense testing this in it + else: + try: + gc.get_referrers(o) + except: + o = None #jython and ironpython do not have get_referrers + + if o is not None: + sys.stdout.write('still observing %s\n' % (o,)) + sys.stdout.write('number of referrers: %s\n' % len(gc.get_referrers(o))) + frame = gc.get_referrers(o)[0] + frame_referrers = gc.get_referrers(frame) + sys.stdout.write('frame referrer %s\n' % (frame_referrers,)) + referrers1 = gc.get_referrers(frame_referrers[1]) + sys.stdout.write('%s\n' % (referrers1,)) + sys.stderr.write('TEST FAILED: The observer should have died, even when running in debug\n') + else: + sys.stdout.write('TEST SUCEEDED: observer died\n') + + sys.stdout.flush() + sys.stderr.flush() + +class Observer(object): + pass + + +def main(): + observable = set_up() + observable.Notify() + + +if __name__ == '__main__': + main() diff --git a/tests_python/resources/_debugger_case13.py b/tests_python/resources/_debugger_case13.py new file mode 100644 index 0000000..dbdbbd4 --- /dev/null +++ b/tests_python/resources/_debugger_case13.py @@ -0,0 +1,43 @@ + +class TestProperty(object): + def __init__(self, name = "Default"): + self._x = None + self.name = name + + def get_name(self): + return self.__name + + + def set_name(self, value): + self.__name = value + + + def del_name(self): + del self.__name + name = property(get_name, set_name, del_name, "name's docstring") + + @property + def x(self): + return self._x + + @x.setter + def x(self, value): + self._x = value + + @x.deleter + def x(self): + del self._x + +def main(): + """ + """ + testObj = TestProperty() + testObj.x = 10 + val = testObj.x + + testObj.name = "Pydev" + debugType = testObj.name + print('TEST SUCEEDED!') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/tests_python/resources/_debugger_case14.py b/tests_python/resources/_debugger_case14.py new file mode 100644 index 0000000..2a5e181 --- /dev/null +++ b/tests_python/resources/_debugger_case14.py @@ -0,0 +1,29 @@ + +class Car(object): + """A car class""" + def __init__(self, model, make, color): + self.model = model + self.make = make + self.color = color + self.price = None + + def get_price(self): + return self.price + + def set_price(self, value): + self.price = value + +availableCars = [] +def main(): + global availableCars + + #Create a new car obj + carObj = Car("Maruti SX4", "2011", "Black") + carObj.set_price(950000) # Set price + # Add this to available cars + availableCars.append(carObj) + + print('TEST SUCEEDED') + +if __name__ == '__main__': + main() diff --git a/tests_python/resources/_debugger_case15.py b/tests_python/resources/_debugger_case15.py new file mode 100644 index 0000000..2a5e181 --- /dev/null +++ b/tests_python/resources/_debugger_case15.py @@ -0,0 +1,29 @@ + +class Car(object): + """A car class""" + def __init__(self, model, make, color): + self.model = model + self.make = make + self.color = color + self.price = None + + def get_price(self): + return self.price + + def set_price(self, value): + self.price = value + +availableCars = [] +def main(): + global availableCars + + #Create a new car obj + carObj = Car("Maruti SX4", "2011", "Black") + carObj.set_price(950000) # Set price + # Add this to available cars + availableCars.append(carObj) + + print('TEST SUCEEDED') + +if __name__ == '__main__': + main() diff --git a/tests_python/resources/_debugger_case15_execfile.py b/tests_python/resources/_debugger_case15_execfile.py new file mode 100644 index 0000000..7123209 --- /dev/null +++ b/tests_python/resources/_debugger_case15_execfile.py @@ -0,0 +1 @@ +f=lambda x: 'val=%s' % x diff --git a/tests_python/resources/_debugger_case16.py b/tests_python/resources/_debugger_case16.py new file mode 100644 index 0000000..5622813 --- /dev/null +++ b/tests_python/resources/_debugger_case16.py @@ -0,0 +1,12 @@ +# this test requires numpy to be installed +import numpy + +def main(): + smallarray = numpy.arange(100) * 1 + 1j + bigarray = numpy.arange(100000).reshape((10,10000)) # 100 thousand + hugearray = numpy.arange(10000000) # 10 million + + pass # location of breakpoint after all arrays defined + +main() +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case17.py b/tests_python/resources/_debugger_case17.py new file mode 100644 index 0000000..d863814 --- /dev/null +++ b/tests_python/resources/_debugger_case17.py @@ -0,0 +1,44 @@ +def get_here(): + a = 10 + + +def foo(func): + return func + + +def m1(): # @DontTrace + get_here() + + +# @DontTrace +def m2(): + get_here() + + +# @DontTrace +@foo +def m3(): + get_here() + + +@foo +@foo +def m4(): # @DontTrace + get_here() + + +def main(): + + m1() # break1 + + m2() # break2 + + m3() # break3 + + m4() # break4 + + +if __name__ == '__main__': + main() + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case17a.py b/tests_python/resources/_debugger_case17a.py new file mode 100644 index 0000000..51ea6fd --- /dev/null +++ b/tests_python/resources/_debugger_case17a.py @@ -0,0 +1,18 @@ +def m1(): + _a = 'm1' # break 1 here + + +def m2(): # @DontTrace + m1() + _a = 'm2' + + +def m3(): + m2() + _a = 'm3' # break 2 here + + +if __name__ == '__main__': + m3() + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case18.py b/tests_python/resources/_debugger_case18.py new file mode 100644 index 0000000..c221039 --- /dev/null +++ b/tests_python/resources/_debugger_case18.py @@ -0,0 +1,23 @@ +import sys + +def m2(a): + a = 10 + b = 20 #Break here and set a = 40 + c = 30 + + def function2(): + print(a) + + return a + + +def m1(a): + return m2(a) + + +if __name__ == '__main__': + found = m1(10) + if found == 40: + print('TEST SUCEEDED') + else: + raise AssertionError('Expected variable to be changed to 40. Found: %s' % (found,)) diff --git a/tests_python/resources/_debugger_case19.py b/tests_python/resources/_debugger_case19.py new file mode 100644 index 0000000..07ac951 --- /dev/null +++ b/tests_python/resources/_debugger_case19.py @@ -0,0 +1,10 @@ +class A: + + def __init__(self): + self.__var = 10 + +if __name__ == '__main__': + a = A() + print(a._A__var) + # Evaluate 'a.__var' should give a._A__var_ + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case2.py b/tests_python/resources/_debugger_case2.py new file mode 100644 index 0000000..e47a5e2 --- /dev/null +++ b/tests_python/resources/_debugger_case2.py @@ -0,0 +1,24 @@ + +def Call4(): + print('Start Call4') + print('End Call4') + +def Call3(): + print('Start Call3') + Call4() + print('End Call3') + +def Call2(): + print('Start Call2') + Call3() + print('End Call2 - a') + print('End Call2 - b') + +def Call1(): + print('Start Call1') + Call2() + print('End Call1') + +if __name__ == '__main__': + Call1() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case20.py b/tests_python/resources/_debugger_case20.py new file mode 100644 index 0000000..e18e048 --- /dev/null +++ b/tests_python/resources/_debugger_case20.py @@ -0,0 +1,38 @@ +import pydevd +import threading + +original = pydevd.PyDB.notify_thread_created + +found = set() + +def new_notify_thread_created(self, thread_id, thread, *args, **kwargs): + found.add(thread) + return original(self, thread_id, thread, *args, **kwargs) + +pydevd.PyDB.notify_thread_created = new_notify_thread_created + +ok = [] +class MyThread(threading.Thread): + + def run(self): + if self not in found: + ok.append(False) + else: + ok.append(True) + +if __name__ == '__main__': + threads = [] + for i in range(15): + t = MyThread() + t.start() + threads.append(t) + + for t in threads: + t.join() + + assert len(ok) == len(threads) + assert all(ok), 'Expected all threads to be notified of their creation before starting to run. Found: %s' % (ok,) + + found.clear() + print('TEST SUCEEDED') + diff --git a/tests_python/resources/_debugger_case3.py b/tests_python/resources/_debugger_case3.py new file mode 100644 index 0000000..64c9b10 --- /dev/null +++ b/tests_python/resources/_debugger_case3.py @@ -0,0 +1,8 @@ +import time +if __name__ == '__main__': + for i in range(15): + print('here') + time.sleep(.1) + + print('TEST SUCEEDED') + diff --git a/tests_python/resources/_debugger_case4.py b/tests_python/resources/_debugger_case4.py new file mode 100644 index 0000000..661d930 --- /dev/null +++ b/tests_python/resources/_debugger_case4.py @@ -0,0 +1,22 @@ +import time + + +class ProceedContainer: + proceed = False + + +def exit_while_loop(): + ProceedContainer.proceed = True + return 'ok' + + +def sleep(): + while not ProceedContainer.proceed: # The debugger should change the proceed to True to exit the loop. + time.sleep(.1) + + +if __name__ == '__main__': + sleep() + + print('TEST SUCEEDED') + diff --git a/tests_python/resources/_debugger_case56.py b/tests_python/resources/_debugger_case56.py new file mode 100644 index 0000000..e5de28d --- /dev/null +++ b/tests_python/resources/_debugger_case56.py @@ -0,0 +1,9 @@ +def Call2(): + print('Call2') + +def Call1(a): + print('Call1') + +if __name__ == '__main__': + Call1(Call2()) + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case89.py b/tests_python/resources/_debugger_case89.py new file mode 100644 index 0000000..e22361d --- /dev/null +++ b/tests_python/resources/_debugger_case89.py @@ -0,0 +1,16 @@ +def Method1(): + print('m1') + +def Method2(): + print('m2 before') + Method1() + print('m2 after') + +def Method3(): + print('m3 before') + Method2() + print('m3 after') + +if __name__ == '__main__': + Method3() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_adjust_breakpoint.py b/tests_python/resources/_debugger_case_adjust_breakpoint.py new file mode 100644 index 0000000..18fdd44 --- /dev/null +++ b/tests_python/resources/_debugger_case_adjust_breakpoint.py @@ -0,0 +1,11 @@ +def Call(): + b = True + while b: # expected + # requested + pass # Note: until 3.10 a pass didn't generate a line event, but starting at 3.10, it does... + break + + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_async.py b/tests_python/resources/_debugger_case_async.py new file mode 100644 index 0000000..f0a17c5 --- /dev/null +++ b/tests_python/resources/_debugger_case_async.py @@ -0,0 +1,21 @@ +import asyncio +import sys + + +async def gen(): + f = sys._getframe() + for i in range(10): + await asyncio.sleep(.01) + assert f is sys._getframe() + yield i + + +async def run(): + async for p in gen(): + print(p) + + +if __name__ == "__main__": + loop = asyncio.get_event_loop_policy().get_event_loop() + loop.run_until_complete(run()) + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_asyncio.py b/tests_python/resources/_debugger_case_asyncio.py new file mode 100644 index 0000000..af79c84 --- /dev/null +++ b/tests_python/resources/_debugger_case_asyncio.py @@ -0,0 +1,37 @@ +import asyncio + + +async def count(): + print('enter count') + await asyncio.sleep(.001) # break count 1 + await asyncio.sleep(.001) # break count 2 + + +async def count2(): + print('enter count 2') + await asyncio.sleep(.001) + await asyncio.sleep(.001) + + +async def count3(): + print('enter count 3') + await asyncio.sleep(.001) + await asyncio.sleep(.001) + + +async def main(): + await count() # break main + await count2() # step main + await count3() + + +if __name__ == "__main__": + if hasattr(asyncio, 'run'): + print('using asyncio.run') + asyncio.run(main()) + else: + print('using loop.run_until_complete') + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) + loop.close() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_attach_to_pid_multiple_threads.py b/tests_python/resources/_debugger_case_attach_to_pid_multiple_threads.py new file mode 100644 index 0000000..92c0ba1 --- /dev/null +++ b/tests_python/resources/_debugger_case_attach_to_pid_multiple_threads.py @@ -0,0 +1,47 @@ + +import time +import sys +try: + import _thread +except: + import thread as _thread + +if __name__ == '__main__': + + lock = _thread.allocate_lock() + initialized = [False] + print('Main thread ident should be: %s' % (_thread.get_ident())) + + def new_thread_function(): + sys.secondary_id = _thread.get_ident() + print('Secondary thread ident should be: %s' % (_thread.get_ident())) + wait = True + + with lock: + initialized[0] = True + while wait: + time.sleep(.1) # break thread here + + _thread.start_new_thread(new_thread_function, ()) + + wait = True + + while not initialized[0]: + time.sleep(.1) + + with lock: # It'll be here until the secondary thread finishes (i.e.: releases the lock). + pass + + import threading # Note: only import after the attach. + curr_thread_ident = threading.current_thread().ident + if hasattr(threading, 'main_thread'): + main_thread_ident = threading.main_thread().ident + else: + # Python 2 does not have main_thread, but we can still get the reference. + main_thread_ident = threading._shutdown.im_self.ident + + if curr_thread_ident != main_thread_ident: + raise AssertionError('Expected current thread ident (%s) to be the main thread ident (%s)' % ( + curr_thread_ident, main_thread_ident)) + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_attach_to_pid_simple.py b/tests_python/resources/_debugger_case_attach_to_pid_simple.py new file mode 100644 index 0000000..57f39d9 --- /dev/null +++ b/tests_python/resources/_debugger_case_attach_to_pid_simple.py @@ -0,0 +1,17 @@ +import time + +if __name__ == '__main__': + wait = True + + while wait: + time.sleep(1) # break here + + # Ok, if it got here things are looking good, let's just make + # sure that the threading module main thread has the correct ident. + import threading # Note: only import after the attach. + if hasattr(threading, 'main_thread'): + assert threading.current_thread().ident == threading.main_thread().ident + else: + # Python 2 does not have main_thread, but we can still get the reference. + assert threading.current_thread().ident == threading._shutdown.im_self.ident + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_breakpoint.py b/tests_python/resources/_debugger_case_breakpoint.py new file mode 100644 index 0000000..745833f --- /dev/null +++ b/tests_python/resources/_debugger_case_breakpoint.py @@ -0,0 +1,7 @@ + +def break_in_method(): + breakpoint() # Builtin on Py3, but we provide a backport on Py2. + + +break_in_method() +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_breakpoint2.py b/tests_python/resources/_debugger_case_breakpoint2.py new file mode 100644 index 0000000..9123ada --- /dev/null +++ b/tests_python/resources/_debugger_case_breakpoint2.py @@ -0,0 +1,7 @@ +import sys +def break_in_method(): + sys.__breakpointhook__() # Builtin on Py3, but we provide a backport on Py2. + + +break_in_method() +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_breakpoint_condition_exc.py b/tests_python/resources/_debugger_case_breakpoint_condition_exc.py new file mode 100644 index 0000000..acc2fd4 --- /dev/null +++ b/tests_python/resources/_debugger_case_breakpoint_condition_exc.py @@ -0,0 +1,8 @@ +def Call(): + for i in range(10): # break here + last_i = i + + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_breakpoint_remote.py b/tests_python/resources/_debugger_case_breakpoint_remote.py new file mode 100644 index 0000000..12c24d0 --- /dev/null +++ b/tests_python/resources/_debugger_case_breakpoint_remote.py @@ -0,0 +1,15 @@ +if __name__ == '__main__': + import os + import sys + port = int(sys.argv[1]) + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + if root_dirname not in sys.path: + sys.path.append(root_dirname) + + import pydevd + print('before pydevd.settrace') + breakpoint(port=port) + print('after pydevd.settrace') + print('TEST SUCEEDED!') + \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_breakpoint_remote_no_import.py b/tests_python/resources/_debugger_case_breakpoint_remote_no_import.py new file mode 100644 index 0000000..ae1cdfd --- /dev/null +++ b/tests_python/resources/_debugger_case_breakpoint_remote_no_import.py @@ -0,0 +1,14 @@ +if __name__ == '__main__': + import os + import sys + port = int(sys.argv[1]) + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + if root_dirname not in sys.path: + sys.path.append(root_dirname) + + print('before pydevd.settrace') + breakpoint(port=port) # Set up through custom sitecustomize.py + print('after pydevd.settrace') + print('TEST SUCEEDED!') + \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_change_breaks.py b/tests_python/resources/_debugger_case_change_breaks.py new file mode 100644 index 0000000..ce72f1a --- /dev/null +++ b/tests_python/resources/_debugger_case_change_breaks.py @@ -0,0 +1,12 @@ + + +def method(): + _a = 1 # break 1 + _a = 2 + _a = 3 # break 2 + + +if __name__ == '__main__': + for i in range(2): + method() + print('TEST SUCEEDED') # break 3 diff --git a/tests_python/resources/_debugger_case_check_tracer.py b/tests_python/resources/_debugger_case_check_tracer.py new file mode 100644 index 0000000..f0b0d35 --- /dev/null +++ b/tests_python/resources/_debugger_case_check_tracer.py @@ -0,0 +1,100 @@ +import threading, atexit, sys +from collections import namedtuple +import os.path + +if sys.version_info[0] >= 3: + from _thread import start_new_thread +else: + from thread import start_new_thread + +FrameInfo = namedtuple('FrameInfo', 'filename, name, f_trace') + + +def _atexit(): + sys.stderr.flush() + sys.stdout.flush() + + +# Register the TEST SUCEEDED msg to the exit of the process. +atexit.register(_atexit) + + +def _iter_frame_info(frame): + while frame is not None: + yield FrameInfo( + os.path.basename(frame.f_code.co_filename), + frame.f_code.co_name, + frame.f_trace.__name__ if frame.f_trace is not None else "None" + ) + frame = frame.f_back + + +def check_frame_info(expected): + found = list(_iter_frame_info(sys._getframe().f_back)) + + def fail(): + raise AssertionError('Expected:\n%s\n\nFound:\n%s\n' % ( + '\n'.join(str(x) for x in expected), + '\n'.join(str(x) for x in found))) + + for found_info, expected_info in zip(found, expected): + if found_info.filename != expected_info.filename or found_info.name != expected_info.name: + fail() + + for f_trace in expected_info.f_trace.split('|'): + if f_trace == found_info.f_trace: + break + else: + fail() + + +def thread_func(): + check_frame_info([ + FrameInfo(filename='_debugger_case_check_tracer.py', name='thread_func', f_trace='trace_exception'), + FrameInfo(filename='threading.py', name='run', f_trace='None'), + FrameInfo(filename='threading.py', name='_bootstrap_inner', f_trace='trace_unhandled_exceptions'), + FrameInfo(filename='threading.py', name='_bootstrap', f_trace='None'), + FrameInfo(filename='pydev_monkey.py', name='__call__', f_trace='None') + ]) + + +th = threading.Thread(target=thread_func) +th.daemon = True +th.start() + +event = threading.Event() + + +def thread_func2(): + try: + check_frame_info([ + FrameInfo(filename='_debugger_case_check_tracer.py', name='thread_func2', f_trace='trace_exception'), + FrameInfo(filename='pydev_monkey.py', name='__call__', f_trace='trace_unhandled_exceptions') + ]) + finally: + event.set() + + +start_new_thread(thread_func2, ()) + +event.wait() +th.join() + +# This is a bit tricky: although we waited on the event, there's a slight chance +# that we didn't get the notification because the thread could've stopped executing, +# so, sleep a bit so that the test does not become flaky. +import time +time.sleep(.3) + +check_frame_info([ + FrameInfo(filename='_debugger_case_check_tracer.py', name='', f_trace='trace_exception'), + FrameInfo(filename='pydevd_runpy.py', name='_run_code', f_trace='None'), + FrameInfo(filename='pydevd_runpy.py', name='_run_module_code', f_trace='None'), + FrameInfo(filename='pydevd_runpy.py', name='run_path', f_trace='None'), + FrameInfo(filename='pydevd.py', name='_exec', f_trace='trace_unhandled_exceptions'), + FrameInfo(filename='pydevd.py', name='run', f_trace='trace_dispatch|None'), + FrameInfo(filename='pydevd.py', name='main', f_trace='trace_dispatch|None'), + FrameInfo(filename='pydevd.py', name='', f_trace='trace_dispatch|None') +]) + +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_completions.py b/tests_python/resources/_debugger_case_completions.py new file mode 100644 index 0000000..f570209 --- /dev/null +++ b/tests_python/resources/_debugger_case_completions.py @@ -0,0 +1,23 @@ +def method1(): + yield + print('here') # Break here + + +if __name__ == '__main__': + # i.e.: make sure we create 2 frames with different frameIds. + it1 = iter(method1()) + it2 = iter(method1()) + + next(it1) # resume first + next(it2) # resume second + + try: + next(it1) # finish first + except StopIteration: + pass + try: + next(it2) # finish second + except StopIteration: + pass + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_custom_frames.py b/tests_python/resources/_debugger_case_custom_frames.py new file mode 100644 index 0000000..af30327 --- /dev/null +++ b/tests_python/resources/_debugger_case_custom_frames.py @@ -0,0 +1,23 @@ +import sys + +from _pydevd_bundle.pydevd_custom_frames import add_custom_frame +import threading + + +def call1(): + add_custom_frame(sys._getframe(), 'call1', threading.current_thread().ident) + + +def call2(): + add_custom_frame(sys._getframe(), 'call2', threading.current_thread().ident) + + +def call3(): + add_custom_frame(sys._getframe(), 'call3', threading.current_thread().ident) + + +if __name__ == '__main__': + call1() # break here + call2() + call3() + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_custom_message.py b/tests_python/resources/_debugger_case_custom_message.py new file mode 100644 index 0000000..20fb334 --- /dev/null +++ b/tests_python/resources/_debugger_case_custom_message.py @@ -0,0 +1,14 @@ +import pydevd +from _pydevd_bundle._debug_adapter import pydevd_schema + +body = pydevd_schema.OutputEventBody('some output', 'my_category') +event = pydevd_schema.OutputEvent(body) +pydevd.send_json_message(event) + +pydevd.send_json_message({ + "type": "event", + "event": "output", + "body": {"output": "some output 2", "category": "my_category2"} +}) + +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_deadlock_thread_eval.py b/tests_python/resources/_debugger_case_deadlock_thread_eval.py new file mode 100644 index 0000000..5c1054c --- /dev/null +++ b/tests_python/resources/_debugger_case_deadlock_thread_eval.py @@ -0,0 +1,72 @@ +''' +The idea here is that a secondary thread does the processing of instructions, +so, when all threads are stopped, doing an evaluation for: + +processor.process('xxx') + +would be locked until secondary threads start running. +See: https://github.com/microsoft/debugpy/issues/157 +''' + +import threading +try: + from queue import Queue +except: + from Queue import Queue + + +class EchoThread(threading.Thread): + + def __init__(self, queue): + threading.Thread.__init__(self) + self._queue = queue + self.started = threading.Event() + + def run(self): + self.started.set() + while True: + obj = self._queue.get() + if obj == 'finish': + break + + print('processed', obj.value) + obj.event.set() # Break here 2 + + +class NotificationObject(object): + + def __init__(self, value): + self.value = value + self.event = threading.Event() + + +class Processor(object): + + def __init__(self, queue): + self._queue = queue + + def process(self, i): + obj = NotificationObject(i) + self._queue.put(obj) + assert obj.event.wait() + + def finish(self): + self._queue.put('finish') + + +def main(): + queue = Queue() + echo_thread = EchoThread(queue) + processor = Processor(queue) + echo_thread.start() + echo_thread.started.wait() + + processor.process(1) # Break here 1 + processor.process(2) + processor.process(3) + processor.finish() + + +if __name__ == '__main__': + main() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_debug_options.py b/tests_python/resources/_debugger_case_debug_options.py new file mode 100644 index 0000000..4050a92 --- /dev/null +++ b/tests_python/resources/_debugger_case_debug_options.py @@ -0,0 +1,11 @@ + +import pydevd +# Some hackery to get the PyDevJsonCommandProcessor which is not exposed. +try: + json_command_processor = pydevd.get_global_debugger().reader.process_net_command_json.__self__ +except: + json_command_processor = pydevd.get_global_debugger().reader.process_net_command_json.im_self + +print(json_command_processor._options.to_json()) + +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_deep_stacks.py b/tests_python/resources/_debugger_case_deep_stacks.py new file mode 100644 index 0000000..8d06e16 --- /dev/null +++ b/tests_python/resources/_debugger_case_deep_stacks.py @@ -0,0 +1,16 @@ +def method1(n): + if n <= 0: + return 0 # Break here + method2(n - 1) + + +def method2(n): + method1(n - 1) + + +if __name__ == '__main__': + try: + method1(100) + except: + pass # Don't let it print the exception (just deal with caught exceptions). + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_dir_exception.py b/tests_python/resources/_debugger_case_dir_exception.py new file mode 100644 index 0000000..ae162fe --- /dev/null +++ b/tests_python/resources/_debugger_case_dir_exception.py @@ -0,0 +1,13 @@ +class A(): + + def __init__(self): + self.var1 = 10 + self.attr = {} # Break here + + def __dir__(self): + return list(self.attr) + + +if __name__ == '__main__': + a = A() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_dont_trace.py b/tests_python/resources/_debugger_case_dont_trace.py new file mode 100644 index 0000000..5632d14 --- /dev/null +++ b/tests_python/resources/_debugger_case_dont_trace.py @@ -0,0 +1,3 @@ +def call_me_back(callback): + if callable(callback): + callback() diff --git a/tests_python/resources/_debugger_case_dont_trace_test.py b/tests_python/resources/_debugger_case_dont_trace_test.py new file mode 100644 index 0000000..0cb797e --- /dev/null +++ b/tests_python/resources/_debugger_case_dont_trace_test.py @@ -0,0 +1,18 @@ +import sys +import os + +try: + from _debugger_case_dont_trace import call_me_back +except ImportError: + sys.path.append(os.path.dirname(__file__)) + from _debugger_case_dont_trace import call_me_back + + +def my_callback(): + print('trace me') # Break here + + +if __name__ == '__main__': + call_me_back(my_callback) + call_me_back(my_callback) + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_evaluate.py b/tests_python/resources/_debugger_case_evaluate.py new file mode 100644 index 0000000..ba01479 --- /dev/null +++ b/tests_python/resources/_debugger_case_evaluate.py @@ -0,0 +1,8 @@ +def Call(): + var_1 = 5 + + var_all = 1 # Break here + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_event_ext.py b/tests_python/resources/_debugger_case_event_ext.py new file mode 100644 index 0000000..66b9ba6 --- /dev/null +++ b/tests_python/resources/_debugger_case_event_ext.py @@ -0,0 +1 @@ +# File empty. Output is in the extension itself \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_exceptions.py b/tests_python/resources/_debugger_case_exceptions.py new file mode 100644 index 0000000..f4a7be2 --- /dev/null +++ b/tests_python/resources/_debugger_case_exceptions.py @@ -0,0 +1,22 @@ +import sys + + +def method3(): + raise IndexError('foo') # raise indexerror line + + +def method2(): + return method3() # reraise on method2 + + +def method1(): + try: + method2() # handle on method1 + except: + pass # Ok, handled + assert '__exception__' not in sys._getframe().f_locals + + +if __name__ == '__main__': + method1() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_frame_eval.py b/tests_python/resources/_debugger_case_frame_eval.py new file mode 100644 index 0000000..945355f --- /dev/null +++ b/tests_python/resources/_debugger_case_frame_eval.py @@ -0,0 +1,70 @@ +''' +Things this test checks: + +- frame.f_trace is None when there are only regular breakpoints. + +- The no-op tracing function is set by default (otherwise when set tracing functions have no effect). + +- When stepping in, frame.f_trace must be set by the frame eval. + +- When stepping over/return, the frame.f_trace must not be set on intermediate callers. + +TODO: + +- When frame.f_trace is set to the default tracing function, it'll become None again in frame + eval mode if not stepping (if breakpoints weren't changed). + +- The tracing function in the frames that deal with unhandled exceptions must be set when dealing + with unhandled exceptions. + +- The tracing function in the frames that deal with unhandled exceptions must NOT be set when + NOT dealing with unhandled exceptions. + +- If handled exceptions should be dealt with, the proper tracing should be set in frame.f_trace. +''' + +import sys +from _pydevd_frame_eval import pydevd_frame_tracing + + +def check_with_no_trace(): + if False: + print('break on check_with_trace') + frame = sys._getframe() + if frame.f_trace is not None: + raise AssertionError('Expected %s to be None' % (frame.f_trace,)) + + if sys.gettrace() is not pydevd_frame_tracing.dummy_tracing_holder.dummy_trace_func: + raise AssertionError('Expected %s to be dummy_trace_func' % (sys.gettrace(),)) + + +def check_step_in_then_step_return(): + frame = sys._getframe() + f_trace = frame.f_trace + if f_trace.__class__.__name__ != 'SafeCallWrapper': + raise AssertionError('Expected %s to be SafeCallWrapper' % (f_trace.__class__.__name__,)) + + check_with_no_trace() + + +def check_revert_to_dummy(): + check_with_no_trace() + + +if __name__ == '__main__': + # Check how frame eval works. + if sys.version_info[0:2] < (3, 6): + raise AssertionError('Only available for Python 3.6 onwards. Found: %s' % (sys.version_info[0:1],)) + + check_with_no_trace() # break on global (step over) + + check_step_in_then_step_return() + + import pydevd_tracing + import pydevd + + # This is what a remote attach would do (should revert to the frame eval mode). + pydevd_tracing.SetTrace(pydevd.get_global_debugger().trace_dispatch) + check_revert_to_dummy() + + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_generator.py b/tests_python/resources/_debugger_case_generator.py new file mode 100644 index 0000000..694baca --- /dev/null +++ b/tests_python/resources/_debugger_case_generator.py @@ -0,0 +1,18 @@ + + +def generator2(): + for i in range(5): + yield i + + +def generator(): + print('start') # break here + yield from generator2() # step 1 + print('end') # step 2 + + +if __name__ == '__main__': + for i in generator(): # generator return + print(i) + + print('TEST SUCEEDED!') # step 3 diff --git a/tests_python/resources/_debugger_case_generator2.py b/tests_python/resources/_debugger_case_generator2.py new file mode 100644 index 0000000..59c6ee8 --- /dev/null +++ b/tests_python/resources/_debugger_case_generator2.py @@ -0,0 +1,17 @@ +def get_return(): + return 10 + + +def generator(): + print('start') # break here + yield 10 # step 1 + + return \ + get_return() # step 2 + + +if __name__ == '__main__': + for i in generator(): # generator return + print(i) + + print('TEST SUCEEDED!') # step 3 diff --git a/tests_python/resources/_debugger_case_generator3.py b/tests_python/resources/_debugger_case_generator3.py new file mode 100644 index 0000000..9910ba0 --- /dev/null +++ b/tests_python/resources/_debugger_case_generator3.py @@ -0,0 +1,13 @@ + + +def generator(): + print('start') # break here + yield 10 # step 1 + print('end') # step 2 + + +if __name__ == '__main__': + for i in generator(): # generator return + print(i) + + print('TEST SUCEEDED!') # step 3 diff --git a/tests_python/resources/_debugger_case_generator_py2.py b/tests_python/resources/_debugger_case_generator_py2.py new file mode 100644 index 0000000..956190c --- /dev/null +++ b/tests_python/resources/_debugger_case_generator_py2.py @@ -0,0 +1,16 @@ +def generator2(): + for i in range(4): + yield i + + +def generator(): + a = 42 # break here + for x in generator2(): + yield x + + +sum = 0 +for i in generator(): + sum += i + +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_generator_py3.py b/tests_python/resources/_debugger_case_generator_py3.py new file mode 100644 index 0000000..f8cf55a --- /dev/null +++ b/tests_python/resources/_debugger_case_generator_py3.py @@ -0,0 +1,14 @@ +def generator2(): + yield from range(4) + + +def generator(): + a = 42 # break here + yield from generator2() + + +sum = 0 +for i in generator(): + sum += i + +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_generator_step_in.py b/tests_python/resources/_debugger_case_generator_step_in.py new file mode 100644 index 0000000..8e379de --- /dev/null +++ b/tests_python/resources/_debugger_case_generator_step_in.py @@ -0,0 +1,13 @@ +def generator(): + yield 1 # stop 1 + yield 2 # stop 4 + + +def main(): + for i in generator(): # stop 3 + print(i) # stop 2 + + +if __name__ == '__main__': + main() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_get_next_statement_targets.py b/tests_python/resources/_debugger_case_get_next_statement_targets.py new file mode 100644 index 0000000..e258a95 --- /dev/null +++ b/tests_python/resources/_debugger_case_get_next_statement_targets.py @@ -0,0 +1,26 @@ +def method(): + a = 1 + print('call %s' % (a,)) + + def method2(): + print('call %s' % (a,)) + + while a < 10: + a += 1 + print('call %s' % (a,)) + + try: + if a < 0: + print('call %s' % (a,)) + raise ValueError + else: + method2() + except ValueError: + pass + + print('call %s' % (a,)) + + +if __name__ == '__main__': + method() + print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_get_thread_stack.py b/tests_python/resources/_debugger_case_get_thread_stack.py new file mode 100644 index 0000000..2ed3bc7 --- /dev/null +++ b/tests_python/resources/_debugger_case_get_thread_stack.py @@ -0,0 +1,21 @@ +import threading +event_set = False +inner_started = False + +def method(): + global inner_started + inner_started = True + while not event_set: + import time + time.sleep(.1) + +t = threading.Thread(target=method) +t.start() +while not inner_started: + import time + time.sleep(.1) + +print('break here') +event_set = True +t.join() +print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_gevent.py b/tests_python/resources/_debugger_case_gevent.py new file mode 100644 index 0000000..1dab1c4 --- /dev/null +++ b/tests_python/resources/_debugger_case_gevent.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +from gevent import monkey, sleep, threading as gevent_threading +import sys + +if 'remote' in sys.argv: + import pydevd + port = int(sys.argv[1]) + print('before pydevd.settrace') + pydevd.settrace(host=('' if 'as-server' in sys.argv else '127.0.0.1'), port=port, suspend=False) + print('after pydevd.settrace') + +monkey.patch_all() +import threading + +called = [] + + +class MyGreenThread2(threading.Thread): + + def run(self): + for _i in range(3): + sleep() + + +class MyGreenletThread(threading.Thread): + + def run(self): + for _i in range(5): + called.append(self.name) # break here + t1 = MyGreenThread2() + t1.start() + sleep() + + +if __name__ == '__main__': + t1 = MyGreenletThread() + t1.name = 't1' + t2 = MyGreenletThread() + t2.name = 't2' + + if hasattr(gevent_threading, 'Thread'): + # Only available in newer versions of gevent. + assert isinstance(t1, gevent_threading.Thread) + assert isinstance(t2, gevent_threading.Thread) + + t1.start() + t2.start() + + for t1 in (t1, t2): + t1.join() + + # With gevent it's always the same (gevent coroutine support makes thread + # switching serial). + expected = ['t1', 't2', 't1', 't2', 't1', 't2', 't1', 't2', 't1', 't2'] + if called != expected: + raise AssertionError("Expected:\n%s\nFound:\n%s" % (expected, called)) + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_gevent_simple.py b/tests_python/resources/_debugger_case_gevent_simple.py new file mode 100644 index 0000000..79785cf --- /dev/null +++ b/tests_python/resources/_debugger_case_gevent_simple.py @@ -0,0 +1,21 @@ +import gevent + + +def foo(): + print('Running in foo') + gevent.sleep(0) + print('Explicit context switch to foo again') + + +def bar(): + print('Explicit context to bar') + gevent.sleep(0) # break here + print('Implicit context switch back to bar') + + +if __name__ == '__main__': + gevent.joinall([ + gevent.spawn(foo), + gevent.spawn(bar), + ]) + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_gevent_subprocess.py b/tests_python/resources/_debugger_case_gevent_subprocess.py new file mode 100644 index 0000000..1c6192b --- /dev/null +++ b/tests_python/resources/_debugger_case_gevent_subprocess.py @@ -0,0 +1,16 @@ +from gevent import monkey +monkey.patch_all() + +import subprocess +import sys +import os + +if __name__ == "__main__": + if '-foo' in sys.argv: + print('foo called') + else: + if os.environ.get('CALL_PYTHON_SUB') == '1': + assert 'foo called' in subprocess.check_output([sys.executable, __file__, '-foo']).decode('utf-8') + else: + subprocess.check_output("tput -T xterm-256color bold".split()) + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_globals.py b/tests_python/resources/_debugger_case_globals.py new file mode 100644 index 0000000..17bf0b1 --- /dev/null +++ b/tests_python/resources/_debugger_case_globals.py @@ -0,0 +1,12 @@ +in_global_scope = 'in_global_scope_value' + + +class SomeClass(object): + + def method(self): + print('breakpoint here') + + +if __name__ == '__main__': + SomeClass().method() + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_gui_event_loop.py b/tests_python/resources/_debugger_case_gui_event_loop.py new file mode 100644 index 0000000..5b0c5d2 --- /dev/null +++ b/tests_python/resources/_debugger_case_gui_event_loop.py @@ -0,0 +1,26 @@ +class LoopHolder: + + @staticmethod + def gui_loop(): + print('gui_loop() called') + + +def call_method(): + from _pydevd_bundle.pydevd_constants import get_global_debugger + py_db = get_global_debugger() + + # Check state prior to breaking + assert not py_db.gui_in_use + assert py_db._installed_gui_support + assert py_db._gui_event_loop == '__main__.LoopHolder.gui_loop' + + print('break here') + + assert py_db.gui_in_use + assert py_db._installed_gui_support + assert py_db._gui_event_loop == '__main__.LoopHolder.gui_loop' + + +if __name__ == '__main__': + call_method() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_gui_event_loop_qt5.py b/tests_python/resources/_debugger_case_gui_event_loop_qt5.py new file mode 100644 index 0000000..c9d3871 --- /dev/null +++ b/tests_python/resources/_debugger_case_gui_event_loop_qt5.py @@ -0,0 +1,51 @@ +def call_method(): + + from _pydevd_bundle.pydevd_constants import get_global_debugger + py_db = get_global_debugger() + + # Check state prior to breaking + assert not py_db.gui_in_use + assert py_db._installed_gui_support + assert py_db._gui_event_loop == 'qt5' + + import os + import PySide2 + from PySide2.QtCore import QTimer + + dirname = os.path.dirname(PySide2.__file__) + plugin_path = os.path.join(dirname, 'plugins', 'platforms') + if os.path.exists(plugin_path): + os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path + + from PySide2 import QtWidgets + + app = QtWidgets.QApplication([]) + + def on_timeout(): + print('on_timeout() called') + + print_timer = QTimer() + print_timer.timeout.connect(on_timeout) + print_timer.setInterval(100) + print_timer.start() + + def on_break(): + print('break here') + app.quit() + + break_on_timer = QTimer() + break_on_timer.timeout.connect(on_break) + break_on_timer.setSingleShot(True) + break_on_timer.setInterval(50) + break_on_timer.start() + + app.exec_() # Run forever until app.quit() + + assert py_db.gui_in_use + assert py_db._installed_gui_support + assert py_db._gui_event_loop == 'qt5' + + +if __name__ == '__main__': + call_method() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_hasattr_crash.py b/tests_python/resources/_debugger_case_hasattr_crash.py new file mode 100644 index 0000000..c71df62 --- /dev/null +++ b/tests_python/resources/_debugger_case_hasattr_crash.py @@ -0,0 +1,10 @@ +class MyClass(object): + + def __getattribute__(self, attr): + raise RuntimeError() + + +obj = MyClass() + +if __name__ == '__main__': + print('TEST SUCEEDED') # break here diff --git a/tests_python/resources/_debugger_case_hit_count.py b/tests_python/resources/_debugger_case_hit_count.py new file mode 100644 index 0000000..e250ddf --- /dev/null +++ b/tests_python/resources/_debugger_case_hit_count.py @@ -0,0 +1,6 @@ +if __name__ == '__main__': + x = 0 # before loop line + for i in range(10): # for line + print(i) # print line + + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_ignore_exceptions.py b/tests_python/resources/_debugger_case_ignore_exceptions.py new file mode 100644 index 0000000..9628f4d --- /dev/null +++ b/tests_python/resources/_debugger_case_ignore_exceptions.py @@ -0,0 +1,25 @@ +import sys +if __name__ == '__main__': + + a = [1, 2, 3, 4] + b = [2, 7] + + assert any(x in a for x in b) + + def gen(): + yield 1 + + for i in gen(): + pass + + def gen2(): + yield 2 + if sys.version_info[:2] < (3, 7): + # On Python 3.7 onwards this will generate an unhandled exception, which + # is not what we want. + raise StopIteration() + + for i in gen2(): + pass + + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_import_imported.py b/tests_python/resources/_debugger_case_import_imported.py new file mode 100644 index 0000000..bc66192 --- /dev/null +++ b/tests_python/resources/_debugger_case_import_imported.py @@ -0,0 +1,2 @@ +print('text 1') +print('text 2') diff --git a/tests_python/resources/_debugger_case_import_main.py b/tests_python/resources/_debugger_case_import_main.py new file mode 100644 index 0000000..92e8676 --- /dev/null +++ b/tests_python/resources/_debugger_case_import_main.py @@ -0,0 +1,3 @@ +import _debugger_case_import_imported # break here + +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_lambda_multiline.py b/tests_python/resources/_debugger_case_lambda_multiline.py new file mode 100644 index 0000000..da692f7 --- /dev/null +++ b/tests_python/resources/_debugger_case_lambda_multiline.py @@ -0,0 +1,8 @@ +call = lambda b:( + b, + 1, # Break here + ) +call(1) +call(2) + +print('TEST SUCEEDED') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_lamda.py b/tests_python/resources/_debugger_case_lamda.py new file mode 100644 index 0000000..c039e4c --- /dev/null +++ b/tests_python/resources/_debugger_case_lamda.py @@ -0,0 +1,5 @@ +call = lambda b:b # Break here will hit once at creation time and then at each call. +call(1) +call(2) + +print('TEST SUCEEDED') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_large_exception_stack.py b/tests_python/resources/_debugger_case_large_exception_stack.py new file mode 100644 index 0000000..7fa3704 --- /dev/null +++ b/tests_python/resources/_debugger_case_large_exception_stack.py @@ -0,0 +1,16 @@ +def method1(n): + if n <= 0: + raise IndexError('foo') + method2(n - 1) + + +def method2(n): + method1(n - 1) + + +if __name__ == '__main__': + try: + method1(100) + except: + pass # Don't let it print the exception (just deal with caught exceptions). + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_linecache.py b/tests_python/resources/_debugger_case_linecache.py new file mode 100644 index 0000000..e02d01a --- /dev/null +++ b/tests_python/resources/_debugger_case_linecache.py @@ -0,0 +1,26 @@ +import linecache + +unique_filename = "" + + +def foo(): + print("on foo") # breakpoint + + +script = """ +def somemethod(): + foo() +somemethod() +[x for x in range(10)] +""" + +linecache.cache[unique_filename] = ( + len(script), + None, + script.splitlines(True), + unique_filename, +) + +obj = compile(script, unique_filename, "exec") +exec(obj) +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_linecache_existing_file.py b/tests_python/resources/_debugger_case_linecache_existing_file.py new file mode 100644 index 0000000..5824df2 --- /dev/null +++ b/tests_python/resources/_debugger_case_linecache_existing_file.py @@ -0,0 +1,12 @@ +import linecache +import sys +import os +sys.path.append(os.path.dirname(os.path.abspath(__file__))) + +import _debugger_case_stepping + +linecache.updatecache(_debugger_case_stepping.__file__) +assert linecache.getline(_debugger_case_stepping.__file__, 1) +_debugger_case_stepping.Call() + +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_listen_dap_messages.py b/tests_python/resources/_debugger_case_listen_dap_messages.py new file mode 100644 index 0000000..d160d52 --- /dev/null +++ b/tests_python/resources/_debugger_case_listen_dap_messages.py @@ -0,0 +1,59 @@ +import time + + +def check_output_command(messages_sent): + for _i in range(50): + for msg in messages_sent: + if msg.get('type') == 'event' and msg.get('event') == 'output' and 'Something' in msg['body']['output']: + return True + time.sleep(.1) + return False + + +def check_continue_request(messages_received): + for _i in range(50): + for msg in messages_received: + if msg.get('type') == 'request' and msg.get('command') == 'continue': + return True + time.sleep(.1) + return False + + +def main(): + ''' + In this test we'll check that pydevd sends an output event and receives a continue request in + the dap messages listener. + ''' + messages_sent = [] + messages_received = [] + + import pydevd + + class Listener(pydevd.IDAPMessagesListener): + + def before_send(self, message_as_dict): + messages_sent.append(message_as_dict) + + def after_receive(self, message_as_dict): + messages_received.append(message_as_dict) + + pydevd.add_dap_messages_listener(Listener()) + + print('Something') # Break here + + # Note that the message is only received in a thread, so, we have to + # wait for it to be received. + if not check_output_command(messages_sent): + print('Output not received!') + return False + + if not check_continue_request(messages_received): + print('Continue not received!') + return False + + print('TEST SUCEEDED!') + return True + + +if __name__ == '__main__': + assert main() diff --git a/tests_python/resources/_debugger_case_local_variables.py b/tests_python/resources/_debugger_case_local_variables.py new file mode 100644 index 0000000..47f8f16 --- /dev/null +++ b/tests_python/resources/_debugger_case_local_variables.py @@ -0,0 +1,14 @@ + + +def Call(): + variable_for_test_1 = 10 # Break here + variable_for_test_2 = 20 + variable_for_test_3 = {'a':30, 'b':20} + locals()[u'\u16A0'] = u'\u16A1' # unicode variable (would be syntax error on py2). + + all_vars_set = True # Break 2 here + + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_local_variables2.py b/tests_python/resources/_debugger_case_local_variables2.py new file mode 100644 index 0000000..988c97d --- /dev/null +++ b/tests_python/resources/_debugger_case_local_variables2.py @@ -0,0 +1,12 @@ + + +def Call(): + variable_for_test_1 = ['a', 'b'] + variable_for_test_2 = set(['a']) + + all_vars_set = True # Break here + + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_local_variables3.py b/tests_python/resources/_debugger_case_local_variables3.py new file mode 100644 index 0000000..7161353 --- /dev/null +++ b/tests_python/resources/_debugger_case_local_variables3.py @@ -0,0 +1,82 @@ +class MyDictSubclass(dict): + + def __init__(self): + dict.__init__(self) + self.var1 = 10 + self['in_dct'] = 20 + + def __str__(self): + ret = [] + for key, val in sorted(self.items()): + ret.append('%s: %s' % (key, val)) + ret.append('self.var1: %s' % (self.var1,)) + return '{' + '; '.join(ret) + '}' + + __repr__ = __str__ + + +class MyListSubclass(list): + + def __init__(self): + list.__init__(self) + self.var1 = 11 + self.append('a') + self.append('b') + + def __str__(self): + ret = [] + for obj in self: + ret.append(repr(obj)) + ret.append('self.var1: %s' % (self.var1,)) + return '[' + ', '.join(ret) + ']' + + __repr__ = __str__ + + +class MySetSubclass(set): + + def __init__(self): + set.__init__(self) + self.var1 = 12 + self.add('a') + + def __str__(self): + ret = [] + for obj in sorted(self): + ret.append(repr(obj)) + ret.append('self.var1: %s' % (self.var1,)) + return 'set([' + ', '.join(ret) + '])' + + __repr__ = __str__ + + +class MyTupleSubclass(tuple): + + def __new__ (cls): + return super(MyTupleSubclass, cls).__new__(cls, tuple(['a', 1])) + + def __init__(self): + self.var1 = 13 + + def __str__(self): + ret = [] + for obj in self: + ret.append(repr(obj)) + ret.append('self.var1: %s' % (self.var1,)) + return 'tuple(' + ', '.join(ret) + ')' + + __repr__ = __str__ + + +def Call(): + variable_for_test_1 = MyListSubclass() + variable_for_test_2 = MySetSubclass() + variable_for_test_3 = MyDictSubclass() + variable_for_test_4 = MyTupleSubclass() + + all_vars_set = True # Break here + + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_local_variables_hex.py b/tests_python/resources/_debugger_case_local_variables_hex.py new file mode 100644 index 0000000..07e2637 --- /dev/null +++ b/tests_python/resources/_debugger_case_local_variables_hex.py @@ -0,0 +1,12 @@ +def Call(): + variables_for_test_1 = 100 + variables_for_test_2 = [1, 10, 100] + variables_for_test_3 = {10: 10, 100: 100, 1000: 1000} + variables_for_test_4 = {(1, 10, 100): (10000, 100000, 100000)} + + all_vars_set = True # Break here + + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_logging.py b/tests_python/resources/_debugger_case_logging.py new file mode 100644 index 0000000..b6355b8 --- /dev/null +++ b/tests_python/resources/_debugger_case_logging.py @@ -0,0 +1,63 @@ +import subprocess +import sys +import json +from _pydev_bundle import pydev_log +import os +import io + + +def gen_debug_info(): + from _pydevd_bundle.pydevd_constants import DebugInfoHolder + dct = {} + for name in ( + 'PYDEVD_DEBUG_FILE', + 'DEBUG_TRACE_LEVEL', + ): + dct[name] = getattr(DebugInfoHolder, name) + + return dct + + +if __name__ == "__main__": + if '-print-debug' in sys.argv: + info = gen_debug_info() # break on 2nd process + pydev_log.info('Something in print-debug') + + print('>>> print-debug pid: %s' % os.getpid()) + print(json.dumps(info)) + + else: + # Note: when running tests we usually have logging setup, + # so, we create a context so that our changes are restored + # when it finishes (as the `log_to` function will just reset + # whatever is there). + s = io.StringIO() + with pydev_log.log_context(trace_level=3, stream=s): + target_log_file = os.getenv('TARGET_LOG_FILE') + + pydev_log.log_to(target_log_file, 1) + new_debug_info = gen_debug_info() + subprocess_pid = None + with subprocess.Popen( + [sys.executable, __file__, '-print-debug'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) as process: + subprocess_pid = process.pid + stdout, stderr = process.communicate(input) + + output = stdout.decode('utf-8') + pydev_log.info('Something in initial') + + log_contents = open(pydev_log._compute_filename_with_pid(target_log_file)).read() + assert 'Something in initial' in log_contents, 'Did not find "Something in initial" in %s' % (log_contents,) + + log_contents = open(pydev_log._compute_filename_with_pid(target_log_file, pid=subprocess_pid)).read() + assert 'Something in print-debug' in log_contents, 'Did not find "Something in print-debug" in %s' % (log_contents,) + + output = ''.join(output.splitlines(keepends=True)[1:]) # Remove the first line + loaded_debug_info = json.loads(output) + assert loaded_debug_info == new_debug_info, 'Expected %s. Found: %s' % (new_debug_info, loaded_debug_info) + print('>>> Initial pid: %s' % os.getpid()) + print(output) + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_m_switch.py b/tests_python/resources/_debugger_case_m_switch.py new file mode 100644 index 0000000..a5b3706 --- /dev/null +++ b/tests_python/resources/_debugger_case_m_switch.py @@ -0,0 +1,3 @@ +from . import _debugger_case_m_switch_2 +print(_debugger_case_m_switch_2.ClassToBeImported) +print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_m_switch_2.py b/tests_python/resources/_debugger_case_m_switch_2.py new file mode 100644 index 0000000..99c9f4c --- /dev/null +++ b/tests_python/resources/_debugger_case_m_switch_2.py @@ -0,0 +1,2 @@ +class ClassToBeImported(object): + pass \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_matplotlib.py b/tests_python/resources/_debugger_case_matplotlib.py new file mode 100644 index 0000000..b973347 --- /dev/null +++ b/tests_python/resources/_debugger_case_matplotlib.py @@ -0,0 +1,23 @@ +from concurrent.futures import ThreadPoolExecutor +import matplotlib +import matplotlib.pyplot as plt + +processed = [] + + +def double(nmbr): + doubled = nmbr * 2 # break here + processed.append(1) + return doubled + + +with ThreadPoolExecutor(max_workers=2) as pool: + futures = [] + + for number in range(3): + future = pool.submit(double, number) + futures.append(future) + +pool.shutdown() +assert len(processed) == 3 +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_method_single_line.py b/tests_python/resources/_debugger_case_method_single_line.py new file mode 100644 index 0000000..8caee59 --- /dev/null +++ b/tests_python/resources/_debugger_case_method_single_line.py @@ -0,0 +1,5 @@ +def call(b): return b # Break here will hit once at creation time and then at each call. +call(1) +call(2) + +print('TEST SUCEEDED') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_module.py b/tests_python/resources/_debugger_case_module.py new file mode 100644 index 0000000..e98b830 --- /dev/null +++ b/tests_python/resources/_debugger_case_module.py @@ -0,0 +1,17 @@ +class MyVersion(object): + pass + + +class MyPackage(object): + pass + + +class MyName(object): + pass + + +__version__ = MyVersion() +__package__ = MyPackage() +__name__ = MyName() + +print('TEST SUCEEDED') # Break here diff --git a/tests_python/resources/_debugger_case_module_entry_point.py b/tests_python/resources/_debugger_case_module_entry_point.py new file mode 100644 index 0000000..a69ce52 --- /dev/null +++ b/tests_python/resources/_debugger_case_module_entry_point.py @@ -0,0 +1,2 @@ +def main(): + print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_multi_threads_stepping.py b/tests_python/resources/_debugger_case_multi_threads_stepping.py new file mode 100644 index 0000000..be1eeb3 --- /dev/null +++ b/tests_python/resources/_debugger_case_multi_threads_stepping.py @@ -0,0 +1,55 @@ +''' +After breaking on the thread 1, thread 2 should pause waiting for the event1 to be set, +so, when we step return on thread 1, the program should finish if all threads are resumed +or should keep waiting for the thread 2 to run if only thread 1 is resumed. +''' + +import threading + +event0 = threading.Event() +event1 = threading.Event() +event2 = threading.Event() +event3 = threading.Event() + + +def _thread1(): + _event1_set = False + _event2_set = False + + while not event0.is_set(): + event0.wait(timeout=.001) + + event1.set() # Break thread 1 + _event1_set = True + + while not event2.is_set(): + event2.wait(timeout=.001) + _event2_set = True # Note: we can only get here if thread 2 is also released. + + event3.set() + + +def _thread2(): + event0.set() + + while not event1.is_set(): + event1.wait(timeout=.001) + + event2.set() + + while not event3.is_set(): + event3.wait(timeout=.001) + + +if __name__ == '__main__': + threads = [ + threading.Thread(target=_thread1, name='thread1'), + threading.Thread(target=_thread2, name='thread2'), + ] + for t in threads: + t.start() + + for t in threads: + t.join() + + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_multiple_threads.py b/tests_python/resources/_debugger_case_multiple_threads.py new file mode 100644 index 0000000..64296a8 --- /dev/null +++ b/tests_python/resources/_debugger_case_multiple_threads.py @@ -0,0 +1,32 @@ +import threading + + +class KeepInLoop(object): + keep_in_loop = True # Debugger should change to False to break. + + +def stop_loop(): + KeepInLoop.keep_in_loop = False + return 'stopped_loop' + + +def double_number(number): + while KeepInLoop.keep_in_loop: + doubled = number * 2 + print(doubled) + import time + time.sleep(.5) + return doubled + + +if __name__ == '__main__': + threads = [] + for num in range(2): + thread = threading.Thread(target=double_number, args=(num,)) + thread.start() + threads.append(thread) + + for thread in threads: + thread.join() + + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_multiprocessing.py b/tests_python/resources/_debugger_case_multiprocessing.py new file mode 100644 index 0000000..cee09e9 --- /dev/null +++ b/tests_python/resources/_debugger_case_multiprocessing.py @@ -0,0 +1,15 @@ +import multiprocessing +import sys + + +def run(name): + print("argument: ", name) # break 1 here + + +if __name__ == '__main__': + if sys.version_info[0] >= 3 and sys.platform != 'win32': + multiprocessing.set_start_method('fork') + p = multiprocessing.Process(target=run, args=("argument to run method",)) + p.start() + print('TEST SUCEEDED!') # break 2 here + p.join() diff --git a/tests_python/resources/_debugger_case_multiprocessing_2.py b/tests_python/resources/_debugger_case_multiprocessing_2.py new file mode 100644 index 0000000..ff29e93 --- /dev/null +++ b/tests_python/resources/_debugger_case_multiprocessing_2.py @@ -0,0 +1,20 @@ +from multiprocessing import Process, Queue + + +class Foo: + + def __init__(self, value): + self.value = value # break 2 here + + +def f(q): + q.put(Foo(1)) + + +if __name__ == '__main__': + q = Queue() + p = Process(target=f, args=(q,)) + p.start() + print(q.get().value) # break 1 here + print('TEST SUCEEDED!') + p.join() diff --git a/tests_python/resources/_debugger_case_multiprocessing_pool.py b/tests_python/resources/_debugger_case_multiprocessing_pool.py new file mode 100644 index 0000000..d83fb04 --- /dev/null +++ b/tests_python/resources/_debugger_case_multiprocessing_pool.py @@ -0,0 +1,17 @@ +from __future__ import print_function +from multiprocessing import Pool +from time import sleep + + +def call(arg): + if arg == '2': + print("called") # break 1 here + + +if __name__ == '__main__': + pool = Pool(1) + pool.map(call, ['1', '2', '3']) + pool.close() + pool.join() + sleep(1) + print('TEST SUCEEDED!') # break 2 here diff --git a/tests_python/resources/_debugger_case_multiprocessing_stopped_threads.py b/tests_python/resources/_debugger_case_multiprocessing_stopped_threads.py new file mode 100644 index 0000000..3d73078 --- /dev/null +++ b/tests_python/resources/_debugger_case_multiprocessing_stopped_threads.py @@ -0,0 +1,32 @@ +import time +import multiprocessing +import threading +import sys +import os + +event = threading.Event() + + +class MyThread(threading.Thread): + + def run(self): + _a = 10 + _b = 20 # break in thread here + event.set() + _c = 20 + + +def run_in_multiprocess(): + _a = 30 + _b = 40 # break in process here + + +if __name__ == '__main__': + MyThread().start() + event.wait() + if sys.version_info[0] >= 3 and sys.platform != 'win32': + multiprocessing.set_start_method('fork') + p = multiprocessing.Process(target=run_in_multiprocess, args=()) + p.start() + print('TEST SUCEEDED!') # break in main here + p.join() diff --git a/tests_python/resources/_debugger_case_namedtuple.py b/tests_python/resources/_debugger_case_namedtuple.py new file mode 100644 index 0000000..e871b0e --- /dev/null +++ b/tests_python/resources/_debugger_case_namedtuple.py @@ -0,0 +1,6 @@ +from collections import namedtuple +MyTup = namedtuple('MyTup', 'a, b, c') +tup = MyTup(1, 2, 3) # break here +assert tup.a == 1 +assert tup.b == 2 +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_no_subprocess_patching.py b/tests_python/resources/_debugger_case_no_subprocess_patching.py new file mode 100644 index 0000000..a327adf --- /dev/null +++ b/tests_python/resources/_debugger_case_no_subprocess_patching.py @@ -0,0 +1,35 @@ +import subprocess +import sys +import os +from contextlib import contextmanager +env = os.environ.copy() +pythonpath = env.get('PYTHONPATH', '') +env['PYTHONPATH'] = os.path.dirname(__file__) + + +def call(): + print("called") # break 1 here + + +@contextmanager +def dummy_context_manager(): + yield + + +if __name__ == '__main__': + if 'apply-multiprocessing-patch' in sys.argv: + context_manager = dummy_context_manager # It's applied by default. + else: + import pydevd + context_manager = pydevd.skip_subprocess_arg_patch + + with context_manager(): + p = subprocess.Popen( + [sys.executable, '-c', 'import _debugger_case_no_subprocess_patching;_debugger_case_no_subprocess_patching.call()'], + stdout=subprocess.PIPE, + env=env, + ) + + stdout, stderr = p.communicate() + assert b'called' in stdout, 'Did not find b"called" in: %s' % (stdout,) + print('TEST SUCEEDED!') # break 2 here diff --git a/tests_python/resources/_debugger_case_odict.py b/tests_python/resources/_debugger_case_odict.py new file mode 100644 index 0000000..dadbf02 --- /dev/null +++ b/tests_python/resources/_debugger_case_odict.py @@ -0,0 +1,14 @@ +def check(): + from collections import OrderedDict + import sys + # On 3.6 onwards, use a regular dict. + odict = OrderedDict() if sys.version_info[:2] < (3, 6) else {} + odict[4] = 'first' + odict[3] = 'second' + odict[2] = 'last' + print('break here') + + +if __name__ == '__main__': + check() +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_path_translation.py b/tests_python/resources/_debugger_case_path_translation.py new file mode 100644 index 0000000..3127821 --- /dev/null +++ b/tests_python/resources/_debugger_case_path_translation.py @@ -0,0 +1,14 @@ +from tests_python.resource_path_translation import other + + +def call_this(): + print('break here') + + +def main(): + other.call_me_back1(call_this) + print('TEST SUCEEDED!') + + +if __name__ == '__main__': + main() diff --git a/tests_python/resources/_debugger_case_pause_continue.py b/tests_python/resources/_debugger_case_pause_continue.py new file mode 100644 index 0000000..c37de64 --- /dev/null +++ b/tests_python/resources/_debugger_case_pause_continue.py @@ -0,0 +1,13 @@ +import time +def Call(): + loop = True # Break here + + count = 0 + while(loop and (count < 200)): + time.sleep(0.1) + count += 1 # Pause here and change loop to False + + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_print.py b/tests_python/resources/_debugger_case_print.py new file mode 100644 index 0000000..e012ee8 --- /dev/null +++ b/tests_python/resources/_debugger_case_print.py @@ -0,0 +1 @@ +print('TEST SUCEEDED') # Break here should only hit once. \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_pydevd_customization.py b/tests_python/resources/_debugger_case_pydevd_customization.py new file mode 100644 index 0000000..bac506a --- /dev/null +++ b/tests_python/resources/_debugger_case_pydevd_customization.py @@ -0,0 +1,63 @@ +import sys +import os + + +def main(): + env = os.environ.copy() + pythonpath = env.get('PYTHONPATH', '') + env['PYTHONPATH'] = os.path.dirname(__file__) + os.pathsep + \ + os.path.dirname(os.path.dirname(os.path.dirname(__file__))) + + from _pydevd_bundle.pydevd_constants import HTTP_JSON_PROTOCOL + from _pydevd_bundle.pydevd_defaults import PydevdCustomization + PydevdCustomization.DEFAULT_PROTOCOL = HTTP_JSON_PROTOCOL + + import pydevd + from _pydev_bundle import pydev_log + pydev_log.debug('Argv received: %s', sys.argv) + port = int(sys.argv[1]) + print('before pydevd.settrace') + pydevd.settrace(port=port, patch_multiprocessing=True, suspend=True) + print('after pydevd.settrace') + + import subprocess + if '--use-c-switch' in sys.argv: + child_process = subprocess.Popen( + [sys.executable, '-u', '-c', 'import _debugger_case_pydevd_customization;_debugger_case_pydevd_customization.call()'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env, + ) + elif '--posix-spawn' in sys.argv: + env = os.environ.copy() + args = ['-u', '_debugger_case_pydevd_customization.py', '--simple-call'] + pid = os.posix_spawn(sys.executable, args, env) + os.waitpid(pid, 0) + child_process = None # We don't really have a subprocess.Popen instance in this case. + else: + child_process = subprocess.Popen( + [sys.executable, '-u', '_debugger_case_pydevd_customization.py', '--simple-call'], + cwd=os.path.dirname(__file__), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env, + ) + + if child_process: + stdout, stderr = child_process.communicate() + assert b'called' in stdout, 'Did not find b"called" in stdout:\n>>%s<<\nstderr:\n>>%s<<\n' % (stdout, stderr) + print('TEST SUCEEDED!') # break 2 here + + +def call(): + import pydevd + from _pydevd_bundle.pydevd_api import PyDevdAPI + assert pydevd.get_global_debugger().get_arg_ppid() == PyDevdAPI().get_ppid() + print("called") # break 1 here + + +if __name__ == '__main__': + if '--simple-call' in sys.argv: + call() + else: + main() diff --git a/tests_python/resources/_debugger_case_python_c.py b/tests_python/resources/_debugger_case_python_c.py new file mode 100644 index 0000000..21db960 --- /dev/null +++ b/tests_python/resources/_debugger_case_python_c.py @@ -0,0 +1,21 @@ +import subprocess +import sys +import os +env = os.environ.copy() +pythonpath = env.get('PYTHONPATH', '') +env['PYTHONPATH'] = os.path.dirname(__file__) + + +def call(): + print("called") # break 1 here + + +if __name__ == '__main__': + p = subprocess.Popen( + [sys.executable, '-c', 'import _debugger_case_python_c;_debugger_case_python_c.call()'], + stdout=subprocess.PIPE, + env=env, + ) + stdout, stderr = p.communicate() + assert b'called' in stdout, 'Did not find b"called" in: %s' % (stdout,) + print('TEST SUCEEDED!') # break 2 here diff --git a/tests_python/resources/_debugger_case_qthread1.py b/tests_python/resources/_debugger_case_qthread1.py new file mode 100644 index 0000000..b77a45b --- /dev/null +++ b/tests_python/resources/_debugger_case_qthread1.py @@ -0,0 +1,31 @@ +import time +import sys + +try: + try: + from PySide import QtCore # @UnresolvedImport + except: + from PySide2 import QtCore # @UnresolvedImport +except: + try: + from PyQt4 import QtCore + except: + from PyQt5 import QtCore + +# Subclassing QThread +# http://doc.qt.nokia.com/latest/qthread.html +class AThread(QtCore.QThread): + + def run(self): + count = 0 + while count < 5: + print("Increasing", count) # break here + sys.stdout.flush() + count += 1 + +app = QtCore.QCoreApplication([]) +thread = AThread() +thread.finished.connect(app.exit) +thread.start() +app.exec_() +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_qthread2.py b/tests_python/resources/_debugger_case_qthread2.py new file mode 100644 index 0000000..feddd72 --- /dev/null +++ b/tests_python/resources/_debugger_case_qthread2.py @@ -0,0 +1,40 @@ +import time +import sys + +try: + try: + from PySide import QtCore # @UnresolvedImport + except: + from PySide2 import QtCore # @UnresolvedImport +except: + try: + from PyQt4 import QtCore + except: + from PyQt5 import QtCore + +# Subclassing QObject and using moveToThread +# http://labs.qt.nokia.com/2007/07/05/qthreads-no-longer-abstract/ +class SomeObject(QtCore.QObject): + + try: + finished = QtCore.Signal() # @UndefinedVariable + except: + finished = QtCore.pyqtSignal() # @UndefinedVariable + + def long_running(self): + count = 0 + while count < 5: + print("Increasing") # break here + count += 1 + self.finished.emit() + +app = QtCore.QCoreApplication([]) +objThread = QtCore.QThread() +obj = SomeObject() +obj.moveToThread(objThread) +obj.finished.connect(objThread.quit) +objThread.started.connect(obj.long_running) +objThread.finished.connect(app.exit) +objThread.start() +app.exec_() +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_qthread3.py b/tests_python/resources/_debugger_case_qthread3.py new file mode 100644 index 0000000..5bc0470 --- /dev/null +++ b/tests_python/resources/_debugger_case_qthread3.py @@ -0,0 +1,35 @@ +import time +import sys + +try: + try: + from PySide import QtCore # @UnresolvedImport + except: + from PySide2 import QtCore # @UnresolvedImport +except: + try: + from PyQt4 import QtCore + except: + from PyQt5 import QtCore + +# Using a QRunnable +# http://doc.qt.nokia.com/latest/qthreadpool.html +# Note that a QRunnable isn't a subclass of QObject and therefore does +# not provide signals and slots. +class Runnable(QtCore.QRunnable): + + def run(self): + count = 0 + app = QtCore.QCoreApplication.instance() + while count < 5: + print("Increasing") # break here + count += 1 + app.quit() + + +app = QtCore.QCoreApplication([]) +runnable = Runnable() +QtCore.QThreadPool.globalInstance().start(runnable) +app.exec_() +QtCore.QThreadPool.globalInstance().waitForDone() +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_qthread4.py b/tests_python/resources/_debugger_case_qthread4.py new file mode 100644 index 0000000..c137f05 --- /dev/null +++ b/tests_python/resources/_debugger_case_qthread4.py @@ -0,0 +1,47 @@ +try: + from PySide import QtCore +except: + try: + from PySide2 import QtCore + except: + try: + from PyQt4 import QtCore + except: + from PyQt5 import QtCore + + +class TestObject(QtCore.QObject): + """ + Test class providing some non-argument signal + """ + + try: + testSignal = QtCore.Signal() # @UndefinedVariable + except: + testSignal = QtCore.pyqtSignal() # @UndefinedVariable + + +class TestThread(QtCore.QThread): + + def run(self): + QtCore.QThread.sleep(4) + print('Done sleeping') + + +def on_start(): + print('On start called1') + print('On start called2') + + +app = QtCore.QCoreApplication([]) +some_thread = TestThread() +some_object = TestObject() + +# connect QThread.started to the signal +some_thread.started.connect(some_object.testSignal) +some_object.testSignal.connect(on_start) +some_thread.finished.connect(app.quit) + +some_thread.start() +app.exec_() +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_quoting.py b/tests_python/resources/_debugger_case_quoting.py new file mode 100644 index 0000000..e9220ba --- /dev/null +++ b/tests_python/resources/_debugger_case_quoting.py @@ -0,0 +1,26 @@ +import subprocess +import sys + +args = [ + 'connect(\\"127 . 0.0.1\\")', + '"', + '', + '\\', + '\\"', + '""', +] + + +def main(): + retcode = subprocess.call([sys.executable, __file__] + args) + assert retcode == 0 + + +if __name__ == '__main__': + sys_args = sys.argv[1:] + if sys_args: + assert sys_args == args, 'Expected that %r == %r' % (sys_args, args) + print('break here') + print('TEST SUCEEDED!') + else: + main() diff --git a/tests_python/resources/_debugger_case_raise_with_cause.py b/tests_python/resources/_debugger_case_raise_with_cause.py new file mode 100644 index 0000000..51c5e60 --- /dev/null +++ b/tests_python/resources/_debugger_case_raise_with_cause.py @@ -0,0 +1,23 @@ +def method2(): + raise RuntimeError('TEST SUCEEDED') + + +def method(): + method2() + + +def handle(e): + raise Exception('another while handling') + + +def foobar(): + try: + try: + method() + except Exception as e: + handle(e) + except Exception as e: + raise RuntimeError from e + + +foobar() diff --git a/tests_python/resources/_debugger_case_redirect.py b/tests_python/resources/_debugger_case_redirect.py new file mode 100644 index 0000000..3f54547 --- /dev/null +++ b/tests_python/resources/_debugger_case_redirect.py @@ -0,0 +1,26 @@ +# coding:utf-8 +if __name__ == '__main__': + import sys + for stream_name in ('stdout', 'stderr'): + stream = getattr(sys, stream_name) + stream.write('text\n') + stream.write('binary or text\n') + stream.write('ação1\n') + + if sys.version_info[0] >= 3: + # sys.stdout.buffer is only available on py3. + stream.buffer.write(b'binary\n') + # Note: this will be giberish on the receiving side because when writing bytes + # we can't be sure what's the encoding and will treat it as utf-8 (i.e.: + # uses PYTHONIOENCODING). + stream.buffer.write('ação2\n'.encode(encoding='latin1')) + + # This will be ok + stream.buffer.write('ação3\n'.encode(encoding='utf-8')) + + if sys.version_info[0] >= 3: + stream.buffer.write(b'\xe8\xF0\x80\x80\x80\n\n') + else: + stream.write(b'\xe8\xF0\x80\x80\x80\n\n') + + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_remote.py b/tests_python/resources/_debugger_case_remote.py new file mode 100644 index 0000000..82deefa --- /dev/null +++ b/tests_python/resources/_debugger_case_remote.py @@ -0,0 +1,16 @@ +if __name__ == '__main__': + import os + import sys + port = int(sys.argv[1]) + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + if root_dirname not in sys.path: + sys.path.append(root_dirname) + + del sys.argv + + import pydevd + print('before pydevd.settrace') + pydevd.settrace(port=port) + print('after pydevd.settrace') + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_remote_1.py b/tests_python/resources/_debugger_case_remote_1.py new file mode 100644 index 0000000..04b389a --- /dev/null +++ b/tests_python/resources/_debugger_case_remote_1.py @@ -0,0 +1,47 @@ +if __name__ == '__main__': + import subprocess + import sys + import os + import _debugger_case_remote_2 + args = sys.argv[1:] + port = int(args.pop(0)) + + access_token = None + client_access_token = None + while args: + if args[0] == '--access-token': + access_token = args[1] + args = args[2:] + elif args[0] == '--client-access-token': + client_access_token = args[1] + args = args[2:] + else: + raise AssertionError('Unable to handle args: %s' % (sys.argv[1:])) + + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + if root_dirname not in sys.path: + sys.path.append(root_dirname) + + import pydevd + + print('before pydevd.settrace') + sys.stdout.flush() + pydevd.settrace( + port=port, + patch_multiprocessing=True, + access_token=access_token, + client_access_token=client_access_token, + ) + print('after pydevd.settrace') + sys.stdout.flush() + f = _debugger_case_remote_2.__file__ + if f.endswith('.pyc'): + f = f[:-1] + elif f.endswith('$py.class'): + f = f[:-len('$py.class')] + '.py' + print('before call') + sys.stdout.flush() + subprocess.check_call([sys.executable, '-u', f]) + print('after call') + sys.stdout.flush() diff --git a/tests_python/resources/_debugger_case_remote_2.py b/tests_python/resources/_debugger_case_remote_2.py new file mode 100644 index 0000000..d25bb77 --- /dev/null +++ b/tests_python/resources/_debugger_case_remote_2.py @@ -0,0 +1,11 @@ +if __name__ == '__main__': + print('Run as main: %s' % (__file__,)) + import sys + sys.stdout.flush() + import pydevd + # Just check that we're already connected + assert pydevd.GetGlobalDebugger() is not None + print('finish') + sys.stdout.flush() + print('TEST SUCEEDED!') + sys.stdout.flush() \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_remote_threads.py b/tests_python/resources/_debugger_case_remote_threads.py new file mode 100644 index 0000000..7192a19 --- /dev/null +++ b/tests_python/resources/_debugger_case_remote_threads.py @@ -0,0 +1,31 @@ +import threading +if __name__ == '__main__': + import os + import sys + port = int(sys.argv[1]) + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + if root_dirname not in sys.path: + sys.path.append(root_dirname) + + def method(i): + import time + wait = True + while wait: + time.sleep(.1) # break here + + threads = [threading.Thread(target=method, args=(i,)) for i in range(2)] + for t in threads: + t.start() + + import pydevd + assert pydevd.get_global_debugger() is None + + print('before pydevd.settrace') + pydevd.settrace(port=port) + print('after pydevd.settrace') + + for t in threads: + t.join() + + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_remote_unhandled_exceptions.py b/tests_python/resources/_debugger_case_remote_unhandled_exceptions.py new file mode 100644 index 0000000..f0d9363 --- /dev/null +++ b/tests_python/resources/_debugger_case_remote_unhandled_exceptions.py @@ -0,0 +1,15 @@ +if __name__ == '__main__': + import os + import sys + port = int(sys.argv[1]) + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + if root_dirname not in sys.path: + sys.path.append(root_dirname) + + import pydevd + print('before pydevd.settrace') + pydevd.settrace(port=port) + print('after pydevd.settrace') + raise ValueError('TEST SUCEEDED!') + \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_remote_unhandled_exceptions2.py b/tests_python/resources/_debugger_case_remote_unhandled_exceptions2.py new file mode 100644 index 0000000..9e7fd29 --- /dev/null +++ b/tests_python/resources/_debugger_case_remote_unhandled_exceptions2.py @@ -0,0 +1,21 @@ +if __name__ == '__main__': + import os + import sys + port = int(sys.argv[1]) + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + if root_dirname not in sys.path: + sys.path.append(root_dirname) + + import pydevd + print('before pydevd.settrace') + pydevd.settrace(port=port) + print('after pydevd.settrace') + for i in range(2): + try: + raise ValueError('not finished') + except: + pass + + raise ValueError('TEST SUCEEDED!') + \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_remove_breakpoint.py b/tests_python/resources/_debugger_case_remove_breakpoint.py new file mode 100644 index 0000000..6681b42 --- /dev/null +++ b/tests_python/resources/_debugger_case_remove_breakpoint.py @@ -0,0 +1,14 @@ + + +def check(): + import pydevd + py_db = pydevd.get_global_debugger() + assert len(py_db.api_received_breakpoints) == 1 + _a = 10 # break here + # should remove the breakpoints when stopped on the previous line + assert len(py_db.api_received_breakpoints) == 0 + + +if __name__ == '__main__': + check() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_replace_process.py b/tests_python/resources/_debugger_case_replace_process.py new file mode 100644 index 0000000..bdee695 --- /dev/null +++ b/tests_python/resources/_debugger_case_replace_process.py @@ -0,0 +1,18 @@ +import sys + +if __name__ == '__main__': + if 'in-sub' not in sys.argv: + import os + # These functions all execute a new program, replacing the current process; they do not return. + # os.execl(path, arg0, arg1, ...) + # os.execle(path, arg0, arg1, ..., env) + # os.execlp(file, arg0, arg1, ...) + # os.execlpe(file, arg0, arg1, ..., env)¶ + # os.execv(path, args) + # os.execve(path, args, env) + # os.execvp(file, args) + # os.execvpe(file, args, env) + os.execvp(sys.executable, [sys.executable, __file__, 'in-sub']) + else: + print('In sub') + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_return_value.py b/tests_python/resources/_debugger_case_return_value.py new file mode 100644 index 0000000..20f6334 --- /dev/null +++ b/tests_python/resources/_debugger_case_return_value.py @@ -0,0 +1,16 @@ +def method1(): + return 1 + + +def method2(): + return 2 + + +def main(): + method1() # break here + method2() + print('TEST SUCEEDED!') + + +if __name__ == '__main__': + main() diff --git a/tests_python/resources/_debugger_case_return_value_asyncio.py b/tests_python/resources/_debugger_case_return_value_asyncio.py new file mode 100644 index 0000000..84f5cca --- /dev/null +++ b/tests_python/resources/_debugger_case_return_value_asyncio.py @@ -0,0 +1,26 @@ +import asyncio + + +async def method1(): + return 1 + + +async def method2(): + return 2 + + +async def main(): + await method1() # break here + await method2() + print('TEST SUCEEDED!') + + +if __name__ == '__main__': + if hasattr(asyncio, 'run'): + print('using asyncio.run') + asyncio.run(main()) + else: + print('using loop.run_until_complete') + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) + loop.close() diff --git a/tests_python/resources/_debugger_case_scapy.py b/tests_python/resources/_debugger_case_scapy.py new file mode 100644 index 0000000..c2a51f6 --- /dev/null +++ b/tests_python/resources/_debugger_case_scapy.py @@ -0,0 +1,2 @@ +from scapy import all as scapy +print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_scoped_stepping.py b/tests_python/resources/_debugger_case_scoped_stepping.py new file mode 100644 index 0000000..62390f0 --- /dev/null +++ b/tests_python/resources/_debugger_case_scoped_stepping.py @@ -0,0 +1,145 @@ +from ast import Module +from ast import stmt +from typing import List as ListType + +import ast +import inspect +from ast import PyCF_ONLY_AST, PyCF_ALLOW_TOP_LEVEL_AWAIT +import types +import os +from contextlib import contextmanager +PyCF_DONT_IMPLY_DEDENT = 0x200 # Matches pythonrun.h + +_assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign) +_single_targets_nodes = (ast.AugAssign, ast.AnnAssign) + +user_module = types.ModuleType("__main__", + doc="Automatically created module for IPython interactive environment") + +stored = [] + + +def tracefunc(frame, event, arg): + if '_debugger_case_scoped_stepping_target' not in frame.f_code.co_filename: + return None + stored.append(frame) + print('\n---') + print(event, id(frame), os.path.basename(frame.f_code.co_filename), frame.f_lineno, arg, frame.f_code.co_name) + assert frame.f_back.f_code.co_name == 'run_code' + return None + + +@contextmanager +def tracing_info(): + import sys + sys.settrace(tracefunc) + try: + yield + finally: + sys.settrace(None) + + +# Note: this is roughly what IPython itself does at: +# https://github.com/ipython/ipython/blob/master/IPython/core/interactiveshell.py +class Runner: + + async def run_ast_nodes( + self, + nodelist: ListType[stmt], + cell_name: str, + interactivity="last_expr", + compiler=compile, + ): + if not nodelist: + return + + if interactivity == 'last_expr_or_assign': + if isinstance(nodelist[-1], _assign_nodes): + asg = nodelist[-1] + if isinstance(asg, ast.Assign) and len(asg.targets) == 1: + target = asg.targets[0] + elif isinstance(asg, _single_targets_nodes): + target = asg.target + else: + target = None + if isinstance(target, ast.Name): + nnode = ast.Expr(ast.Name(target.id, ast.Load())) + ast.fix_missing_locations(nnode) + nodelist.append(nnode) + interactivity = 'last_expr' + + _async = False + if interactivity == 'last_expr': + if isinstance(nodelist[-1], ast.Expr): + interactivity = "last" + else: + interactivity = "none" + + if interactivity == 'none': + to_run_exec, to_run_interactive = nodelist, [] + elif interactivity == 'last': + to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:] + elif interactivity == 'all': + to_run_exec, to_run_interactive = [], nodelist + else: + raise ValueError("Interactivity was %r" % interactivity) + + def compare(code): + is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE + return is_async + + # Refactor that to just change the mod constructor. + to_run = [] + for node in to_run_exec: + to_run.append((node, "exec")) + + for node in to_run_interactive: + to_run.append((node, "single")) + + for node, mode in to_run: + if mode == "exec": + mod = Module([node], []) + elif mode == "single": + mod = ast.Interactive([node]) + code = compiler(mod, cell_name, mode, PyCF_DONT_IMPLY_DEDENT | + PyCF_ALLOW_TOP_LEVEL_AWAIT) + asy = compare(code) + if await self.run_code(code, async_=asy): + return True + + async def run_code(self, code_obj, *, async_=False): + if async_: + await eval(code_obj, self.user_global_ns, self.user_ns) + else: + exec(code_obj, self.user_global_ns, self.user_ns) + + @property + def user_global_ns(self): + return user_module.__dict__ + + @property + def user_ns(self): + return user_module.__dict__ + + +async def main(): + SCOPED_STEPPING_TARGET = os.getenv('SCOPED_STEPPING_TARGET', '_debugger_case_scoped_stepping_target.py') + filename = os.path.join(os.path.dirname(__file__), SCOPED_STEPPING_TARGET) + assert os.path.exists(filename), '%s does not exist.' % (filename,) + with open(filename, 'r') as stream: + source = stream.read() + code_ast = compile( + source, + filename, + 'exec', + PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST | PyCF_ALLOW_TOP_LEVEL_AWAIT, + 1) + + runner = Runner() + await runner.run_ast_nodes(code_ast.body, filename) + + +if __name__ == '__main__': + import asyncio + asyncio.run(main()) + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_scoped_stepping_target.py b/tests_python/resources/_debugger_case_scoped_stepping_target.py new file mode 100644 index 0000000..a9aeef0 --- /dev/null +++ b/tests_python/resources/_debugger_case_scoped_stepping_target.py @@ -0,0 +1,3 @@ +a = 1 +b = 2 +c = 3 diff --git a/tests_python/resources/_debugger_case_scoped_stepping_target2.py b/tests_python/resources/_debugger_case_scoped_stepping_target2.py new file mode 100644 index 0000000..4dd4af9 --- /dev/null +++ b/tests_python/resources/_debugger_case_scoped_stepping_target2.py @@ -0,0 +1,9 @@ +a = 1 + + +def method(): + b = 2 + + +method() # break here +c = 3 diff --git a/tests_python/resources/_debugger_case_scoped_stepping_target_async.py b/tests_python/resources/_debugger_case_scoped_stepping_target_async.py new file mode 100644 index 0000000..d7bbcfe --- /dev/null +++ b/tests_python/resources/_debugger_case_scoped_stepping_target_async.py @@ -0,0 +1,9 @@ +# Note that await in the top-level isn't valid in general, but we compile +# it specifically accepting it, so, that's ok. +import asyncio + +await asyncio.sleep(.01) +a = 1 # Break here +await asyncio.sleep(.01) +b = 2 +await asyncio.sleep(.01) diff --git a/tests_python/resources/_debugger_case_set_next_statement.py b/tests_python/resources/_debugger_case_set_next_statement.py new file mode 100644 index 0000000..dcbd1af --- /dev/null +++ b/tests_python/resources/_debugger_case_set_next_statement.py @@ -0,0 +1,10 @@ +def method(): + a = 1 # Step here + print('call %s' % (a,)) + a = 2 + print('call %s' % (a,)) + a = 3 # Break here + +if __name__ == '__main__': + method() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_settrace.py b/tests_python/resources/_debugger_case_settrace.py new file mode 100644 index 0000000..6090089 --- /dev/null +++ b/tests_python/resources/_debugger_case_settrace.py @@ -0,0 +1,26 @@ +def ask_for_stop(use_back): + import pydevd + if use_back: + pydevd.settrace(stop_at_frame=sys._getframe().f_back) + else: + pydevd.settrace() + print('Will stop here if use_back==False.') + + +def outer_method(): + ask_for_stop(True) + print('will stop here.') + ask_for_stop(False) + + +if __name__ == '__main__': + import os + import sys + root_dirname = os.path.dirname(os.path.dirname(__file__)) + + if root_dirname not in sys.path: + sys.path.append(root_dirname) + + outer_method() + print('TEST SUCEEDED!') + diff --git a/tests_python/resources/_debugger_case_show_bytecode.py b/tests_python/resources/_debugger_case_show_bytecode.py new file mode 100644 index 0000000..1373822 --- /dev/null +++ b/tests_python/resources/_debugger_case_show_bytecode.py @@ -0,0 +1,25 @@ +def foo(): + return 1 # breakpoint + + +def main(): + + code = ''' + +class MyClass(object): + def method(self): + if True: + foo() + +MyClass().method() +''' + + co = compile(code, '', 'exec') + + # Intermediate stack frame will have source. + eval(co) + + +if __name__ == '__main__': + main() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_simple_calls.py b/tests_python/resources/_debugger_case_simple_calls.py new file mode 100644 index 0000000..323deda --- /dev/null +++ b/tests_python/resources/_debugger_case_simple_calls.py @@ -0,0 +1,18 @@ +def Method1(): + print('m1') + print('m1') + +def Method1a(): + print('m1a') + print('m1a') + +def Method2(): + print('m2 before') + Method1() + Method1a() + print('m2 after') + + +if __name__ == '__main__': + Method2() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_skip_breakpoint_in_exceptions.py b/tests_python/resources/_debugger_case_skip_breakpoint_in_exceptions.py new file mode 100644 index 0000000..fca9a9e --- /dev/null +++ b/tests_python/resources/_debugger_case_skip_breakpoint_in_exceptions.py @@ -0,0 +1,8 @@ +if __name__ == '__main__': + for i in range(2): + print("one") + try: + raise AttributeError() # Breakpoint here + except: + pass + print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_smart_step_into.py b/tests_python/resources/_debugger_case_smart_step_into.py new file mode 100644 index 0000000..84d4b18 --- /dev/null +++ b/tests_python/resources/_debugger_case_smart_step_into.py @@ -0,0 +1,20 @@ +def bar(): + print('on bar mark') + + +def call_outer(*args): + print('on outer mark') + + +def foo(*args): + print('on foo mark') + + +def main(): + call_outer(foo(bar())) # break here + + +if __name__ == '__main__': + main() + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_smart_step_into2.py b/tests_python/resources/_debugger_case_smart_step_into2.py new file mode 100644 index 0000000..d805b5f --- /dev/null +++ b/tests_python/resources/_debugger_case_smart_step_into2.py @@ -0,0 +1,17 @@ + + +def foo(arg): + print('on foo mark', arg) + return arg + 1 + + +def main(): + # Note that we have multiple foo calls and we have to differentiate and stop at the + # proper one. + foo(foo(foo(foo(1)))) # break here + + +if __name__ == '__main__': + main() + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_smart_step_into3.py b/tests_python/resources/_debugger_case_smart_step_into3.py new file mode 100644 index 0000000..1215d12 --- /dev/null +++ b/tests_python/resources/_debugger_case_smart_step_into3.py @@ -0,0 +1,21 @@ +def foo(arg): + print('on foo mark', arg) + return arg + 1 + + +def main(): + items = [1] # break here + gen = (foo(arg) for arg in items) + list(gen) + +# import dis +# print('-------- main ------------') +# dis.dis(main) +# print('-------- foo ------------') +# dis.dis(foo) + + +if __name__ == '__main__': + main() + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_source_map_goto_target.py b/tests_python/resources/_debugger_case_source_map_goto_target.py new file mode 100644 index 0000000..11619b0 --- /dev/null +++ b/tests_python/resources/_debugger_case_source_map_goto_target.py @@ -0,0 +1,24 @@ +# Some comment lines to move the function below +# Some comment lines to move the function below +# Some comment lines to move the function below +# Some comment lines to move the function below + + +def full_function(): + # Note that this function is not called, it's there just to make the mapping explicit. + # The test case should stop at `a = 1` and then skip the `print('Skip this print')`. + # map to Cell1, line 1 + a = 1 # map to Cell1, line 2 + print('Skip this print') # map to Cell1, line 3 + print('TEST SUCEEDED') # map to Cell1, line 4 + b = 2 # map to Cell1, line 5 + + +if __name__ == '__main__': + code = compile('''# line 1 +a = 1 # line 2 +print('Skip this print') # line 3 +print('TEST SUCEEDED') # line 4 +b = 2 # line 5 +''', '', 'exec') + exec(code) diff --git a/tests_python/resources/_debugger_case_source_mapping.py b/tests_python/resources/_debugger_case_source_mapping.py new file mode 100644 index 0000000..ceb4f1d --- /dev/null +++ b/tests_python/resources/_debugger_case_source_mapping.py @@ -0,0 +1,31 @@ +def full_function(): + # Note that this function is not called, it's there just to make the mapping explicit. + a = 1 # map to cEll1, line 2 + b = 2 # map to cEll1, line 3 + + c = 3 # map to cEll2, line 2 + d = 4 # map to cEll2, line 3 + + +def create_code(): + cell1_code = compile(''' # line 1 +a = 1 # line 2 +b = 2 # line 3 +''', '', 'exec') + + cell2_code = compile('''# line 1 +c = 3 # line 2 +d = 4 # line 3 +''', '', 'exec') + + return {'cEll1': cell1_code, 'cEll2': cell2_code} + + +if __name__ == '__main__': + code = create_code() + exec(code['cEll1']) + exec(code['cEll1']) + + exec(code['cEll2']) + exec(code['cEll2']) + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_source_mapping_and_reference.py b/tests_python/resources/_debugger_case_source_mapping_and_reference.py new file mode 100644 index 0000000..d977f5a --- /dev/null +++ b/tests_python/resources/_debugger_case_source_mapping_and_reference.py @@ -0,0 +1,57 @@ +def full_function(): + # Note that this function is not called, it's there just to make the mapping explicit. + a = 1 # map to cEll1, line 2 + b = 2 # map to cEll1, line 3 + + c = 3 # map to cEll2, line 2 + d = 4 # map to cEll2, line 3 + + +def create_code(): + cell1_code = compile(''' # line 1 +a = 1 # line 2 +b = 2 # line 3 +''', '', 'exec') + + cell2_code = compile('''# line 1 +c = 3 # line 2 +d = 4 # line 3 +''', '', 'exec') + + # Set up the source in linecache. Python doesn't have a public API for + # this, so we have to hack around it, similar to what IPython does. + import linecache + import time + code = ''' # line 1 +a = 1 # line 2 +b = 2 # line 3 +''' + linecache.cache[''] = ( + len(code), + time.time(), + [line + '\n' for line in code.splitlines()], + '', + ) + + code = '''# line 1 +c = 3 # line 2 +d = 4 # line 3 +''' + linecache.cache[''] = ( + len(code), + time.time(), + [line + '\n' for line in code.splitlines()], + '', + ) + + return {'cEll1': cell1_code, 'cEll2': cell2_code} + + +if __name__ == '__main__': + code = create_code() + exec(code['cEll1']) + exec(code['cEll1']) + + exec(code['cEll2']) + exec(code['cEll2']) + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_source_mapping_jmc.py b/tests_python/resources/_debugger_case_source_mapping_jmc.py new file mode 100644 index 0000000..594fe5e --- /dev/null +++ b/tests_python/resources/_debugger_case_source_mapping_jmc.py @@ -0,0 +1,35 @@ +def full_function(): + # Note that this function is not called, it's there just to make the mapping explicit. # map to cEll1, line 1 + import sys # map to cEll1, line 2 + frame = sys._getframe() # map to cEll1, line 3 + if py_db.in_project_scope(frame, '') != expect_in_project_scope: # map to cEll1, line 4 + raise AssertionError('Expected to be in project scope: %s' % (expect_in_project_scope,)) # map to cEll1, line 5 + a = 1 # map to cEll1, line 6 + b = 2 # map to cEll1, line 7 + + +def create_code(): + cEll1_code = compile(''' # line 1 +import sys # line 2 +frame = sys._getframe() # line 3 +if py_db.in_project_scope(frame, '') != expect_in_project_scope: # line 4 + raise AssertionError('Expected to be in project scope: %s' % (expect_in_project_scope,)) # line 5 +a = 1 # line 6 +b = 2 # line 7 +''', '', 'exec') + + return {'cEll1': cEll1_code} + + +if __name__ == '__main__': + code = create_code() + import pydevd + py_db = pydevd.get_global_debugger() + + expect_in_project_scope = True + exec(code['cEll1']) # When executing, stop at breakpoint and then remove the source mapping. + + expect_in_project_scope = False + exec(code['cEll1']) # Should no longer stop. + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_source_reference.py b/tests_python/resources/_debugger_case_source_reference.py new file mode 100644 index 0000000..84ba89b --- /dev/null +++ b/tests_python/resources/_debugger_case_source_reference.py @@ -0,0 +1,32 @@ +def foo(): + return 1 # breakpoint + + +def main(): + import linecache + import time + + code = 'foo()' + + # Intermediate stack frame will have no source. + eval(code) + + co_filename = '' + co = compile(code, co_filename, 'exec') + + # Set up the source in linecache. Python doesn't have a public API for + # this, so we have to hack around it, similar to what IPython does. + linecache.cache[co_filename] = ( + len(code), + time.time(), + [line + '\n' for line in code.splitlines()], + co_filename, + ) + + # Intermediate stack frame will have source. + eval(co) + + +if __name__ == '__main__': + main() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_stepping.py b/tests_python/resources/_debugger_case_stepping.py new file mode 100644 index 0000000..2abfbea --- /dev/null +++ b/tests_python/resources/_debugger_case_stepping.py @@ -0,0 +1,19 @@ +def step_over(): + print("don't step here") + +def step_into(): + print('step into') + +def step_out(): + print('step out') # Break here 1 + print("don't step here") + +def Call(): + step_over() # Break here 2 + step_into() + step_out() + print('stepped out') + +if __name__ == '__main__': + Call() + print('TEST SUCEEDED!') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_stop_async_iteration.py b/tests_python/resources/_debugger_case_stop_async_iteration.py new file mode 100644 index 0000000..fe54132 --- /dev/null +++ b/tests_python/resources/_debugger_case_stop_async_iteration.py @@ -0,0 +1,14 @@ +import asyncio + +async def gen(): + for i in range(10): + yield i + +async def run(): + async for p in gen(): + print(p) + +if __name__ == "__main__": + loop = asyncio.get_event_loop_policy().get_event_loop() + loop.run_until_complete(run()) + print('TEST SUCEEDED') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_subprocess_and_fork.py b/tests_python/resources/_debugger_case_subprocess_and_fork.py new file mode 100644 index 0000000..5bcb88b --- /dev/null +++ b/tests_python/resources/_debugger_case_subprocess_and_fork.py @@ -0,0 +1,47 @@ +import os +import sys +import subprocess + + +def breaknow(): + print('break here') + + +if '--fork-in-subprocess' in sys.argv: + popen = None + if sys.platform == 'win32': + popen = subprocess.Popen([sys.executable, __file__, '--forked']) + pid = popen.pid + else: + pid = os.fork() + try: + ppid = os.getppid() + except: + ppid = '' + print('currently in pid: %s, ppid: %s' % (os.getpid(), ppid)) + print('os.fork returned', pid) + breaknow() + # i.e.: wait so that we check for the retcode so that we don't get a traceback such as the one + # below (as that code in __del__ will only be called if returncode is None). + # Traceback (most recent call last): + # File "C:\hostedtoolcache\windows\Python\3.9.13\x64\lib\subprocess.py", line 1055, in __del__ + # self._internal_poll(_deadstate=_maxsize) + # File "C:\hostedtoolcache\windows\Python\3.9.13\x64\lib\subprocess.py", line 1457, in _internal_poll + # if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0: + # OSError: [WinError 6] The handle is invalid + if popen is not None: + popen.wait(20) + +elif '--forked' in sys.argv: + try: + ppid = os.getppid() + except: + ppid = '' + print('currently in pid: %s, ppid: %s' % (os.getpid(), ppid)) + breaknow() + +elif '--fork-in-subprocess' not in sys.argv: + out = subprocess.check_output([sys.executable, __file__, '--fork-in-subprocess']) + breaknow() + print('\n\nin pid %s, output from subprocess.run:\n%s' % (os.getpid(), out.decode('utf-8'))) + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_subprocess_target.zip b/tests_python/resources/_debugger_case_subprocess_target.zip new file mode 100644 index 0000000000000000000000000000000000000000..d9f9c61df2e84f35fa1f0cf04e683c23012f4601 GIT binary patch literal 177 zcmWIWW@Zs#U|`^2=&LytvSg<2OG_Xx1ch-NZrSssB_Uh?#W=s~IA2ww^_oK{=B1VP)Z$>5& f2HbW4tpS4uMi7N$V}Lg+8%T%|2tkfY0&y4s=ua&F literal 0 HcmV?d00001 diff --git a/tests_python/resources/_debugger_case_subprocess_zip.py b/tests_python/resources/_debugger_case_subprocess_zip.py new file mode 100644 index 0000000..e6a26fc --- /dev/null +++ b/tests_python/resources/_debugger_case_subprocess_zip.py @@ -0,0 +1,34 @@ +import subprocess +import sys +import os + +target_zip = os.path.join(os.path.dirname(__file__), '_debugger_case_subprocess_target.zip') + + +def create_zip(): + import zipfile + z = zipfile.ZipFile(target_zip, 'w', zipfile.ZIP_DEFLATED) + z.writestr('__main__.py', ''' +import _debugger_case_subprocess_zip +_debugger_case_subprocess_zip.call_from_zip() +''') + + +def call_from_zip(): + print('Called from zip') # break here + + +def main(): + env = os.environ.copy() + env['PYTHONPATH'] = os.path.dirname(__file__) + result = subprocess.check_output([sys.executable, target_zip], env=env).decode('utf-8') + assert 'Called from zip' in result + print('TEST SUCEEDED!') + + +if __name__ == '__main__': + if not os.path.exists(target_zip): + create_zip() + assert os.path.exists(target_zip) + + main() diff --git a/tests_python/resources/_debugger_case_suspend_all.py b/tests_python/resources/_debugger_case_suspend_all.py new file mode 100644 index 0000000..f02ce7a --- /dev/null +++ b/tests_python/resources/_debugger_case_suspend_all.py @@ -0,0 +1,33 @@ +import time +import threading + + +class ProceedContainer: + tid_to_proceed = { + 1: False, + 2: False, + } + + +def exit_while_loop(tid): + ProceedContainer.tid_to_proceed[tid] = True + return 'ok' + + +def thread_func(tid): + while not ProceedContainer.tid_to_proceed[tid]: # The debugger should change the proceed to True to exit the loop. + time.sleep(.1) + + +if __name__ == '__main__': + threads = [ + threading.Thread(target=thread_func, args=(1,)), + threading.Thread(target=thread_func, args=(2,)), + ] + for t in threads: + t.start() + + for t in threads: + t.join() + + print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_suspend_policy.py b/tests_python/resources/_debugger_case_suspend_policy.py new file mode 100644 index 0000000..dfb5ed3 --- /dev/null +++ b/tests_python/resources/_debugger_case_suspend_policy.py @@ -0,0 +1,29 @@ +import threading + +semaphore1 = threading.Semaphore(0) +proceed = False + + +def thread_target(): + semaphore1.release() + import time + + while True: + if proceed: + break + time.sleep(1 / 30.) + + +for i in range(2): + t = threading.Thread(target=thread_target) + t.start() + +semaphore1.acquire() # let first thread run +semaphore1.acquire() # let second thread run + +# At this point we know both other threads are already running. +print('break here') + +proceed = True + +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_sysexit.py b/tests_python/resources/_debugger_case_sysexit.py new file mode 100644 index 0000000..53738bd --- /dev/null +++ b/tests_python/resources/_debugger_case_sysexit.py @@ -0,0 +1,9 @@ +import sys + + +def main(): + print('TEST SUCEEDED!') + sys.exit(1) + + +main() diff --git a/tests_python/resources/_debugger_case_sysexit_0.py b/tests_python/resources/_debugger_case_sysexit_0.py new file mode 100644 index 0000000..61f11c7 --- /dev/null +++ b/tests_python/resources/_debugger_case_sysexit_0.py @@ -0,0 +1,9 @@ +import sys + + +def main(): + print('TEST SUCEEDED!') + sys.exit(0) + + +main() # call_main_line diff --git a/tests_python/resources/_debugger_case_sysexit_none.py b/tests_python/resources/_debugger_case_sysexit_none.py new file mode 100644 index 0000000..1d0d524 --- /dev/null +++ b/tests_python/resources/_debugger_case_sysexit_none.py @@ -0,0 +1,9 @@ +import sys + + +def main(): + print('TEST SUCEEDED!') + sys.exit() + + +main() # call_main_line diff --git a/tests_python/resources/_debugger_case_terminate.py b/tests_python/resources/_debugger_case_terminate.py new file mode 100644 index 0000000..d241d9e --- /dev/null +++ b/tests_python/resources/_debugger_case_terminate.py @@ -0,0 +1,37 @@ +import time +import subprocess +import sys +import os + +if __name__ == '__main__': + if 'launch-subprocesses' in sys.argv: + n = int(sys.argv[-1]) + if n != 0: + subprocess.Popen([sys.executable, __file__, 'launch-subprocesses', str(n - 1)]) + if hasattr(os, 'getppid'): + print('%screated %s (child of %s)' % ('\t' * (4 - n), os.getpid(), os.getppid())) + else: + print('%screated %s' % ('\t' * (4 - n), os.getpid())) + + elif 'check-subprocesses' in sys.argv or 'check-subprocesses-ignore-pid' in sys.argv: + # Recursively create a process tree such as: + # - parent (this process) + # - p3 + # - p2 + # - p1 + # - p0 + # - p3 + # - p2 + # - p1 + # - p0 + p0 = subprocess.Popen([sys.executable, __file__, 'launch-subprocesses', '3']) + p1 = subprocess.Popen([sys.executable, __file__, 'launch-subprocesses', '3']) + + if 'check-subprocesses-ignore-pid' in sys.argv: + import pydevd + pydevd.add_dont_terminate_child_pid(p0.pid) + + print('created', os.getpid()) + + while True: + time.sleep(.1) diff --git a/tests_python/resources/_debugger_case_thread_creation_deadlock.py b/tests_python/resources/_debugger_case_thread_creation_deadlock.py new file mode 100644 index 0000000..b437d9c --- /dev/null +++ b/tests_python/resources/_debugger_case_thread_creation_deadlock.py @@ -0,0 +1,26 @@ +from threading import Thread, Event + + +def create_thread(): + event = Event() + event_set = [False] + + def run_thread(): + event_set[0] = True + event.set() + + t = Thread(target=run_thread) + t.start() + + try: + event.wait(5) + + # note: not using `assert event.wait(5)` for py2.6 compatibility. + assert event_set[0] + print('TEST SUCEEDED!') + return 'create_thread:ok' + except: + import traceback;traceback.print_exc() + + +a = 10 # Add breakpoint here and evaluate create_thread() diff --git a/tests_python/resources/_debugger_case_thread_started_exited.py b/tests_python/resources/_debugger_case_thread_started_exited.py new file mode 100644 index 0000000..7c89502 --- /dev/null +++ b/tests_python/resources/_debugger_case_thread_started_exited.py @@ -0,0 +1,18 @@ +import threading + + +class MyThread(threading.Thread): + + def run(self): + pass + + +threads = [MyThread() for i in range(3)] + +for t in threads: + t.start() + +for t in threads: + t.join() + +print('TEST SUCEEDED!') # Break here diff --git a/tests_python/resources/_debugger_case_trace_dispatch.py b/tests_python/resources/_debugger_case_trace_dispatch.py new file mode 100644 index 0000000..6a89f0d --- /dev/null +++ b/tests_python/resources/_debugger_case_trace_dispatch.py @@ -0,0 +1,18 @@ +import sys + + +def method(): + a = 10 # add breakpoint + b = 20 + c = 30 + d = 40 + f_trace = sys._getframe().f_trace + if sys.version_info[:2] == (2,6) and f_trace.__name__ == 'NO_FTRACE': + print('TEST SUCEEDED') + elif f_trace is None: + print('TEST SUCEEDED') + else: + raise AssertionError('frame.f_trace is expected to be None at this point. Found: %s' % (f_trace,)) + + +method() diff --git a/tests_python/resources/_debugger_case_tracing.py b/tests_python/resources/_debugger_case_tracing.py new file mode 100644 index 0000000..ab9dc89 --- /dev/null +++ b/tests_python/resources/_debugger_case_tracing.py @@ -0,0 +1,14 @@ + +a = 1 +b = 2 +c = 3 + + +def foo(): + a = 1 + b = 2 + c = 3 + + +foo() +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_trio.py b/tests_python/resources/_debugger_case_trio.py new file mode 100644 index 0000000..ec150ad --- /dev/null +++ b/tests_python/resources/_debugger_case_trio.py @@ -0,0 +1,30 @@ +import trio + + +async def count(): + print('enter count') + await trio.sleep(.001) # break count 1 + await trio.sleep(.001) # break count 2 + + +async def count2(): + print('enter count 2') + await trio.sleep(.001) + await trio.sleep(.001) + + +async def count3(): + print('enter count 3') + await trio.sleep(.001) + await trio.sleep(.001) + + +async def main(): + await count() # break main + await count2() # step main + await count3() + + +if __name__ == '__main__': + trio.run(main) + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_type_ext.py b/tests_python/resources/_debugger_case_type_ext.py new file mode 100644 index 0000000..4a9b694 --- /dev/null +++ b/tests_python/resources/_debugger_case_type_ext.py @@ -0,0 +1,8 @@ +class Rect(object): + def __init__(self, l, w): + super(Rect, self).__init__() + self.length = l + self.width = w +my_rect=Rect(5, 10) +print('TEST SUCEEDED!') + diff --git a/tests_python/resources/_debugger_case_unhandled_exception_get_stack.py b/tests_python/resources/_debugger_case_unhandled_exception_get_stack.py new file mode 100644 index 0000000..e013693 --- /dev/null +++ b/tests_python/resources/_debugger_case_unhandled_exception_get_stack.py @@ -0,0 +1,12 @@ +from contextlib import contextmanager + + +@contextmanager +def something(): + yield + + +with something(): + raise ValueError('TEST SUCEEDED') # break line on unhandled exception + print('a') + print('b') diff --git a/tests_python/resources/_debugger_case_unhandled_exceptions.py b/tests_python/resources/_debugger_case_unhandled_exceptions.py new file mode 100644 index 0000000..f08e1d7 --- /dev/null +++ b/tests_python/resources/_debugger_case_unhandled_exceptions.py @@ -0,0 +1,47 @@ +import threading, atexit, sys +import time + +try: + from thread import start_new_thread +except: + from _thread import start_new_thread + + +def _atexit(): + print('TEST SUCEEDED') + sys.stderr.write('TEST SUCEEDED\n') + sys.stderr.flush() + sys.stdout.flush() + + +# Register the TEST SUCEEDED msg to the exit of the process. +atexit.register(_atexit) + + +def thread_func(): + raise Exception('in thread 1') + + +start_new_thread(thread_func, ()) + +# Wait for the first to be handled... otherwise, tests can become flaky if +# both stop at the same time only 1 notification may be given for both, whereas +# the test expects 2 notifications. +time.sleep(.5) + + +def thread_func2(n): + raise ValueError('in thread 2') + + +th = threading.Thread(target=lambda: thread_func2(1)) +th.daemon = True +th.start() + +th.join() + +# This is a bit tricky: although we waited on the event, there's a slight chance +# that we didn't get the notification because the thread could've stopped executing, +# so, sleep a bit so that the test does not become flaky. +time.sleep(.5) +raise IndexError('in main') diff --git a/tests_python/resources/_debugger_case_unhandled_exceptions_custom.py b/tests_python/resources/_debugger_case_unhandled_exceptions_custom.py new file mode 100644 index 0000000..6065110 --- /dev/null +++ b/tests_python/resources/_debugger_case_unhandled_exceptions_custom.py @@ -0,0 +1,53 @@ +import threading, atexit, sys +import time + +try: + from thread import start_new_thread +except: + from _thread import start_new_thread + + +class MyError(Exception): + + def __init__(self, msg): + return Exception.__init__(self) + + +def _atexit(): + print('TEST SUCEEDED') + sys.stderr.write('TEST SUCEEDED\n') + sys.stderr.flush() + sys.stdout.flush() + + +# Register the TEST SUCEEDED msg to the exit of the process. +atexit.register(_atexit) + + +def thread_func(): + raise MyError('in thread 1') + + +start_new_thread(thread_func, ()) + +# Wait for the first to be handled... otherwise, tests can become flaky if +# both stop at the same time only 1 notification may be given for both, whereas +# the test expects 2 notifications. +time.sleep(.5) + + +def thread_func2(n): + raise MyError('in thread 2') + + +th = threading.Thread(target=lambda: thread_func2(1)) +th.daemon = True +th.start() + +th.join() + +# This is a bit tricky: although we waited on the event, there's a slight chance +# that we didn't get the notification because the thread could've stopped executing, +# so, sleep a bit so that the test does not become flaky. +time.sleep(.5) +raise MyError('in main') diff --git a/tests_python/resources/_debugger_case_unhandled_exceptions_generator.py b/tests_python/resources/_debugger_case_unhandled_exceptions_generator.py new file mode 100644 index 0000000..1e354b2 --- /dev/null +++ b/tests_python/resources/_debugger_case_unhandled_exceptions_generator.py @@ -0,0 +1,19 @@ +import atexit, sys + + +def _atexit(): + print('TEST SUCEEDED') + sys.stderr.write('TEST SUCEEDED\n') + sys.stderr.flush() + sys.stdout.flush() + + +# Register the TEST SUCEEDED msg to the exit of the process. +atexit.register(_atexit) + + +def f(): + return list(1 / 0 for _ in '123') # exc line + + +f() # call exc diff --git a/tests_python/resources/_debugger_case_unhandled_exceptions_listcomp.py b/tests_python/resources/_debugger_case_unhandled_exceptions_listcomp.py new file mode 100644 index 0000000..a700c6e --- /dev/null +++ b/tests_python/resources/_debugger_case_unhandled_exceptions_listcomp.py @@ -0,0 +1,19 @@ +import atexit, sys + + +def _atexit(): + print('TEST SUCEEDED') + sys.stderr.write('TEST SUCEEDED\n') + sys.stderr.flush() + sys.stdout.flush() + + +# Register the TEST SUCEEDED msg to the exit of the process. +atexit.register(_atexit) + + +def f(): + return [1 / 0 for _ in '123'] # exc line + + +f() # call exc diff --git a/tests_python/resources/_debugger_case_unhandled_exceptions_on_top_level.py b/tests_python/resources/_debugger_case_unhandled_exceptions_on_top_level.py new file mode 100644 index 0000000..14ca964 --- /dev/null +++ b/tests_python/resources/_debugger_case_unhandled_exceptions_on_top_level.py @@ -0,0 +1 @@ +raise ValueError('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_unhandled_exceptions_on_top_level2.py b/tests_python/resources/_debugger_case_unhandled_exceptions_on_top_level2.py new file mode 100644 index 0000000..68b40cc --- /dev/null +++ b/tests_python/resources/_debugger_case_unhandled_exceptions_on_top_level2.py @@ -0,0 +1,6 @@ +try: + raise ValueError('foobar') +except ValueError: + pass + +raise ValueError('TEST SUCEEDED') \ No newline at end of file diff --git a/tests_python/resources/_debugger_case_unhandled_just_my_code.py b/tests_python/resources/_debugger_case_unhandled_just_my_code.py new file mode 100644 index 0000000..e300302 --- /dev/null +++ b/tests_python/resources/_debugger_case_unhandled_just_my_code.py @@ -0,0 +1,13 @@ +import sys + +filename = sys.argv[1] + +obj = compile(''' +def call_exception_in_exec(): + a = 10 + b = 20 + raise Exception('TEST SUCEEDED') +''', filename, 'exec') + +exec(obj) +call_exception_in_exec() # @UndefinedVariable diff --git a/tests_python/resources/_debugger_case_user_unhandled.py b/tests_python/resources/_debugger_case_user_unhandled.py new file mode 100644 index 0000000..ae46c90 --- /dev/null +++ b/tests_python/resources/_debugger_case_user_unhandled.py @@ -0,0 +1,14 @@ +import pytest + + +def some_call(): + assert 0 # raise here + + +def test_example(): + some_call() # stop here + + +if __name__ == '__main__': + pytest.main([__file__, '--capture=no', '--noconftest']) + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_user_unhandled2.py b/tests_python/resources/_debugger_case_user_unhandled2.py new file mode 100644 index 0000000..f1ec9e5 --- /dev/null +++ b/tests_python/resources/_debugger_case_user_unhandled2.py @@ -0,0 +1,5 @@ +if __name__ == '__main__': + try: + raise RuntimeError() + except: + print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_variables_with_same_name.py b/tests_python/resources/_debugger_case_variables_with_same_name.py new file mode 100644 index 0000000..196f15e --- /dev/null +++ b/tests_python/resources/_debugger_case_variables_with_same_name.py @@ -0,0 +1,15 @@ +class T: + + def __init__(self, name, value): + self.name = name + self.value = value + + def __repr__(self): + return self.name + + +td = {T("foo", 24): "bar", + T("gad", 42): "zooks", + T("foo", 12): "bur"} + +print('TEST SUCEEDED!') # Break here diff --git a/tests_python/resources/_debugger_case_wait_for_attach.py b/tests_python/resources/_debugger_case_wait_for_attach.py new file mode 100644 index 0000000..75f2252 --- /dev/null +++ b/tests_python/resources/_debugger_case_wait_for_attach.py @@ -0,0 +1,3 @@ +if __name__ == '__main__': + # We want to call _enable_attach inside an import to make sure that it works properly that way. + import _debugger_case_wait_for_attach_impl diff --git a/tests_python/resources/_debugger_case_wait_for_attach_impl.py b/tests_python/resources/_debugger_case_wait_for_attach_impl.py new file mode 100644 index 0000000..61e0ebd --- /dev/null +++ b/tests_python/resources/_debugger_case_wait_for_attach_impl.py @@ -0,0 +1,49 @@ +import os +import sys +import time +port = int(sys.argv[1]) +root_dirname = os.path.dirname(os.path.dirname(__file__)) + +if root_dirname not in sys.path: + sys.path.append(root_dirname) + +import pydevd +try: + pydevd._wait_for_attach() # Cannot be called before _enable_attach. +except AssertionError: + pass +else: + raise AssertionError('Expected _wait_for_attach to raise exception.') + +assert sys.gettrace() is None +print('enable attach to port: %s' % (port,)) +pydevd._enable_attach(('127.0.0.1', port)) +pydevd._enable_attach(('127.0.0.1', port)) # no-op in practice + +try: + pydevd._enable_attach(('127.0.0.1', port + 15)) # different port: raise error. +except AssertionError: + pass +else: + raise AssertionError('Expected _enable_attach to raise exception (because it is already hearing in another port).') + +assert pydevd.get_global_debugger() is not None +assert sys.gettrace() is not None + +a = 10 # Break 1 +print('wait for attach') +pydevd._wait_for_attach() +print('finished wait for attach') +pydevd._wait_for_attach() # Should promptly return (already connected). + +a = 20 # Break 2 + +pydevd._wait_for_attach() # As we disconnected on the 2nd break, this one should wait until a new configurationDone. + +a = 20 # Break 3 + +while a == 20: # Pause 1 + # The debugger should disconnect/reconnect, pause and then change 'a' to another value. + time.sleep(1 / 20.) # Pause 2 + +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_debugger_case_warnings.py b/tests_python/resources/_debugger_case_warnings.py new file mode 100644 index 0000000..4817b1a --- /dev/null +++ b/tests_python/resources/_debugger_case_warnings.py @@ -0,0 +1,22 @@ +import warnings + + +class MyClass(object): + + def __getattribute__(self, attr): + warnings.warn( + "Deprecation Warning", + DeprecationWarning + ) + + warnings.warn( + "Future Warning!", + FutureWarning, + ) + return 1 + + +obj = MyClass() + +if __name__ == '__main__': + print('TEST SUCEEDED') # break here diff --git a/tests_python/resources/_debugger_case_yield_from.py b/tests_python/resources/_debugger_case_yield_from.py new file mode 100644 index 0000000..5bacd2a --- /dev/null +++ b/tests_python/resources/_debugger_case_yield_from.py @@ -0,0 +1,12 @@ +def method(): + a = [1, 2] + + def b(): # break1 + yield from [j for j in a if j % 2 == 0] # break2 + + for j in b(): + print(j) + + +method() +print('TEST SUCEEDED') diff --git a/tests_python/resources/_debugger_case_zip_files.py b/tests_python/resources/_debugger_case_zip_files.py new file mode 100644 index 0000000..8445684 --- /dev/null +++ b/tests_python/resources/_debugger_case_zip_files.py @@ -0,0 +1,17 @@ +from zipped import zipped_contents +try: + code = zipped_contents.call_in_zip.__code__ +except AttributeError: + code = zipped_contents.call_in_zip.func_code +assert 'myzip.zip' in code.co_filename +zipped_contents.call_in_zip() + +from zipped2 import zipped_contents2 +try: + code = zipped_contents2.call_in_zip2.__code__ +except AttributeError: + code = zipped_contents2.call_in_zip2.func_code +assert 'myzip2.egg!' in code.co_filename +zipped_contents2.call_in_zip2() + +print('TEST SUCEEDED!') diff --git a/tests_python/resources/_performance_1.py b/tests_python/resources/_performance_1.py new file mode 100644 index 0000000..0aaa5f5 --- /dev/null +++ b/tests_python/resources/_performance_1.py @@ -0,0 +1,34 @@ +import time + + +def method2(): + i = 1 + + +def method(): + + for i in range(200000): + method2() + + if False: + # Unreachable breakpoint here + pass + + +def caller(): + start_time = time.time() + method() + print('TotalTime>>%s<<' % (time.time() - start_time,)) + + +if __name__ == '__main__': + import sys + if '--regular-trace' in sys.argv: + + def trace_dispatch(frame, event, arg): + return trace_dispatch + + sys.settrace(trace_dispatch) + + caller() # Initial breakpoint for a step-over here + print('TEST SUCEEDED') diff --git a/tests_python/resources/_performance_2.py b/tests_python/resources/_performance_2.py new file mode 100644 index 0000000..574fcb0 --- /dev/null +++ b/tests_python/resources/_performance_2.py @@ -0,0 +1,25 @@ +import time +import sys +import itertools + +from itertools import groupby +count = itertools.count(0) + + +def next_val(): + return next(count) % 25 + + +start_time = time.time() +letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + +# create an array of random strings of 40 characters each +l = sorted([''.join([letters[next_val()] for _ in range(40)]) for _ in range(10000)]) +# group by the first two characters +g = {k: list(v) for k, v in groupby(l, lambda x: x[:2])} + +if False: + pass # Breakpoint here + +print('TotalTime>>%s<<' % (time.time() - start_time,)) +print('TEST SUCEEDED') diff --git a/tests_python/resources/_performance_3.py b/tests_python/resources/_performance_3.py new file mode 100644 index 0000000..7903bcf --- /dev/null +++ b/tests_python/resources/_performance_3.py @@ -0,0 +1,15 @@ +import time +start_time = time.time() + +# do some busy work in parallel +print("Started main task") +x = 0 +for i in range(1000000): + x += 1 +print("Completed main task") + +if False: + pass # Breakpoint here + +print('TotalTime>>%s<<' % (time.time() - start_time,)) +print('TEST SUCEEDED') diff --git a/tests_python/resources/_pydev_coverage_cyrillic_encoding_py2.py b/tests_python/resources/_pydev_coverage_cyrillic_encoding_py2.py new file mode 100644 index 0000000..e56d5d0 --- /dev/null +++ b/tests_python/resources/_pydev_coverage_cyrillic_encoding_py2.py @@ -0,0 +1,8 @@ +# -*- coding: iso-8859-5 -*- + +# Ʋ³´µ¶ +class Dummy(object): + def Print(self): + print ('Ʋ³´µ¶') + +Dummy().Print() diff --git a/tests_python/resources/_pydev_coverage_cyrillic_encoding_py3.py b/tests_python/resources/_pydev_coverage_cyrillic_encoding_py3.py new file mode 100644 index 0000000..f099c53 --- /dev/null +++ b/tests_python/resources/_pydev_coverage_cyrillic_encoding_py3.py @@ -0,0 +1,8 @@ +# -*- coding: iso-8859-5 -*- + +# Ʋ³´µ¶ +class DummyƲ³´µ¶(object): + def Print(self): + print ('Ʋ³´µ¶') + +DummyƲ³´µ¶().Print() diff --git a/tests_python/resources/_pydev_coverage_syntax_error.py b/tests_python/resources/_pydev_coverage_syntax_error.py new file mode 100644 index 0000000..6faf573 --- /dev/null +++ b/tests_python/resources/_pydev_coverage_syntax_error.py @@ -0,0 +1,8 @@ +# -*- coding: iso-8859-5 -*- + +# Ʋ³´µ¶ +class Dummy(object): + def Print(self) + print ('Ʋ³´µ¶') + +Dummy().Print() diff --git a/tests_python/resources/_pydevd_test_find_main_thread_id.py b/tests_python/resources/_pydevd_test_find_main_thread_id.py new file mode 100644 index 0000000..f78454f --- /dev/null +++ b/tests_python/resources/_pydevd_test_find_main_thread_id.py @@ -0,0 +1,159 @@ +# Note: this module should be self-contained to run tests (as it relies on `threading` not being +# imported and having no other threads running). + + +def wait_for_condition(condition, msg=None, timeout=5, sleep=.05): + import time + curtime = time.time() + while True: + if condition(): + break + if time.time() - curtime > timeout: + error_msg = 'Condition not reached in %s seconds' % (timeout,) + if msg is not None: + error_msg += '\n' + if callable(msg): + error_msg += msg() + else: + error_msg += str(msg) + + raise AssertionError('Timeout: %s' % (error_msg,)) + time.sleep(sleep) + + +def check_main_thread_id_simple(): + import attach_script + import sys + assert 'threading' not in sys.modules + try: + import thread + except ImportError: + import _thread as thread + + main_thread_id, log_msg = attach_script.get_main_thread_id(None) + assert main_thread_id == thread.get_ident(), 'Found: %s, Expected: %s' % (main_thread_id, thread.get_ident()) + assert not log_msg + assert 'threading' not in sys.modules + wait_for_condition(lambda: len(sys._current_frames()) == 1) + + +def check_main_thread_id_multiple_threads(): + import attach_script + import sys + import time + assert 'threading' not in sys.modules + try: + import thread + except ImportError: + import _thread as thread + + lock = thread.allocate_lock() + lock2 = thread.allocate_lock() + + def method(): + lock2.acquire() + with lock: + pass # Will only finish when lock is released. + + with lock: + thread.start_new_thread(method, ()) + while not lock2.locked(): + time.sleep(.1) + + wait_for_condition(lambda: len(sys._current_frames()) == 2) + + main_thread_id, log_msg = attach_script.get_main_thread_id(None) + assert main_thread_id == thread.get_ident(), 'Found: %s, Expected: %s' % (main_thread_id, thread.get_ident()) + assert not log_msg + assert 'threading' not in sys.modules + wait_for_condition(lambda: len(sys._current_frames()) == 1) + + +def check_fix_main_thread_id_multiple_threads(): + import attach_script + import sys + import time + assert 'threading' not in sys.modules + try: + import thread + except ImportError: + import _thread as thread + + lock = thread.allocate_lock() + lock2 = thread.allocate_lock() + + def method(): + lock2.acquire() + import threading # Note: imported on wrong thread + assert threading.current_thread().ident == thread.get_ident() + assert threading.current_thread() is attach_script.get_main_thread_instance(threading) + + attach_script.fix_main_thread_id() + + assert threading.current_thread().ident == thread.get_ident() + assert threading.current_thread() is not attach_script.get_main_thread_instance(threading) + + with lock: + pass # Will only finish when lock is released. + + with lock: + thread.start_new_thread(method, ()) + while not lock2.locked(): + time.sleep(.1) + + wait_for_condition(lambda: len(sys._current_frames()) == 2) + + main_thread_id, log_msg = attach_script.get_main_thread_id(None) + assert main_thread_id == thread.get_ident(), 'Found: %s, Expected: %s' % (main_thread_id, thread.get_ident()) + assert not log_msg + assert 'threading' in sys.modules + import threading + assert threading.current_thread().ident == main_thread_id + wait_for_condition(lambda: len(sys._current_frames()) == 1) + + +def check_win_threads(): + import sys + if sys.platform != 'win32': + return + + import attach_script + import time + assert 'threading' not in sys.modules + try: + import thread + except ImportError: + import _thread as thread + from ctypes import windll, WINFUNCTYPE, c_uint32, c_void_p, c_size_t + + ThreadProc = WINFUNCTYPE(c_uint32, c_void_p) + + lock = thread.allocate_lock() + lock2 = thread.allocate_lock() + + @ThreadProc + def method(_): + lock2.acquire() + with lock: + pass # Will only finish when lock is released. + return 0 + + with lock: + windll.kernel32.CreateThread(None, c_size_t(0), method, None, c_uint32(0), None) + while not lock2.locked(): + time.sleep(.1) + + wait_for_condition(lambda: len(sys._current_frames()) == 2) + + main_thread_id, log_msg = attach_script.get_main_thread_id(None) + assert main_thread_id == thread.get_ident(), 'Found: %s, Expected: %s' % (main_thread_id, thread.get_ident()) + assert not log_msg + assert 'threading' not in sys.modules + wait_for_condition(lambda: len(sys._current_frames()) == 1) + + +if __name__ == '__main__': + check_main_thread_id_simple() + check_main_thread_id_multiple_threads() + check_win_threads() + check_fix_main_thread_id_multiple_threads() # Important: must be the last test checked! diff --git a/tests_python/resources/launch/foo/__main__.py b/tests_python/resources/launch/foo/__main__.py new file mode 100644 index 0000000..f29131e --- /dev/null +++ b/tests_python/resources/launch/foo/__main__.py @@ -0,0 +1,6 @@ +import sys +if '--as-module' in sys.argv: + from . import bar +else: + import bar +print('Worked') diff --git a/tests_python/resources/launch/foo/bar.py b/tests_python/resources/launch/foo/bar.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resources/launch_py2/__init__.py b/tests_python/resources/launch_py2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resources/launch_py2/foo/__init__.py b/tests_python/resources/launch_py2/foo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resources/launch_py2/foo/__main__.py b/tests_python/resources/launch_py2/foo/__main__.py new file mode 100644 index 0000000..f29131e --- /dev/null +++ b/tests_python/resources/launch_py2/foo/__main__.py @@ -0,0 +1,6 @@ +import sys +if '--as-module' in sys.argv: + from . import bar +else: + import bar +print('Worked') diff --git a/tests_python/resources/launch_py2/foo/bar.py b/tests_python/resources/launch_py2/foo/bar.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resources/my_code/__init__.py b/tests_python/resources/my_code/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resources/my_code/my_code.py b/tests_python/resources/my_code/my_code.py new file mode 100644 index 0000000..8d0e8f7 --- /dev/null +++ b/tests_python/resources/my_code/my_code.py @@ -0,0 +1,15 @@ +if __name__ == '__main__': + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from not_my_code import other + + def callback2(): + return 'my code2' + + def callback1(): + other.call_me_back2(callback2) # first step into my code + + other.call_me_back1(callback1) # break here + print('TEST SUCEEDED!') diff --git a/tests_python/resources/my_code/my_code_coroutine.py b/tests_python/resources/my_code/my_code_coroutine.py new file mode 100644 index 0000000..d1bd070 --- /dev/null +++ b/tests_python/resources/my_code/my_code_coroutine.py @@ -0,0 +1,27 @@ +import asyncio + + +async def main(): + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from not_my_code import not_my_coroutine + await not_my_coroutine.call1(call2) + print('finish main') + + +async def call2(): + print('on call2') # break here + + +if __name__ == '__main__': + if hasattr(asyncio, 'run'): + print('using asyncio.run') + asyncio.run(main()) + else: + print('using loop.run_until_complete') + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) + loop.close() + print('TEST SUCEEDED!') diff --git a/tests_python/resources/my_code/my_code_coroutine_user_unhandled.py b/tests_python/resources/my_code/my_code_coroutine_user_unhandled.py new file mode 100644 index 0000000..330e5e4 --- /dev/null +++ b/tests_python/resources/my_code/my_code_coroutine_user_unhandled.py @@ -0,0 +1,34 @@ +import asyncio + + +async def main(): + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from not_my_code import not_my_coroutine + try: + await not_my_coroutine.call1(call2) # stop here 2 + finally: + print('finish main') + + +async def call2(): + try: + raise RuntimeError() # stop here 1 + except AssertionError: + pass + + +if __name__ == '__main__': + try: + if hasattr(asyncio, 'run'): + print('using asyncio.run') + asyncio.run(main()) # stop here 3a + else: + print('using loop.run_until_complete') + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) # stop here 3b + loop.close() + finally: + print('TEST SUCEEDED!') diff --git a/tests_python/resources/my_code/my_code_coroutine_user_unhandled_no_stop.py b/tests_python/resources/my_code/my_code_coroutine_user_unhandled_no_stop.py new file mode 100644 index 0000000..312aa3a --- /dev/null +++ b/tests_python/resources/my_code/my_code_coroutine_user_unhandled_no_stop.py @@ -0,0 +1,34 @@ +import asyncio + + +async def main(): + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from not_my_code import not_my_coroutine + try: + await not_my_coroutine.call1(call2) # stop here 2 + finally: + print('finish main') + + +async def call2(): + try: + raise RuntimeError() # stop here 1 + except RuntimeError: + pass + + +if __name__ == '__main__': + try: + if hasattr(asyncio, 'run'): + print('using asyncio.run') + asyncio.run(main()) # stop here 3a + else: + print('using loop.run_until_complete') + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) # stop here 3b + loop.close() + finally: + print('TEST SUCEEDED!') diff --git a/tests_python/resources/my_code/my_code_double_step.py b/tests_python/resources/my_code/my_code_double_step.py new file mode 100644 index 0000000..1915fd4 --- /dev/null +++ b/tests_python/resources/my_code/my_code_double_step.py @@ -0,0 +1,8 @@ +if __name__ == '__main__': + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from not_my_code import other_noop + other_noop.call_noop() # break here + print('TEST SUCEEDED!') diff --git a/tests_python/resources/my_code/my_code_exception.py b/tests_python/resources/my_code/my_code_exception.py new file mode 100644 index 0000000..7ec8013 --- /dev/null +++ b/tests_python/resources/my_code/my_code_exception.py @@ -0,0 +1,14 @@ +if __name__ == '__main__': + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from not_my_code import other + + def callback2(): + raise RuntimeError('TEST SUCEEDED!') + + def callback1(): + other.call_me_back2(callback2) + + other.call_me_back1(callback1) # break here diff --git a/tests_python/resources/my_code/my_code_exception_on_other.py b/tests_python/resources/my_code/my_code_exception_on_other.py new file mode 100644 index 0000000..0d82dc9 --- /dev/null +++ b/tests_python/resources/my_code/my_code_exception_on_other.py @@ -0,0 +1,14 @@ +if __name__ == '__main__': + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from not_my_code import other + + def callback2(): + other.raise_exception() + + def callback1(): + other.call_me_back2(callback2) + + other.call_me_back1(callback1) # break here diff --git a/tests_python/resources/my_code/my_code_exception_user_unhandled.py b/tests_python/resources/my_code/my_code_exception_user_unhandled.py new file mode 100644 index 0000000..5a6344d --- /dev/null +++ b/tests_python/resources/my_code/my_code_exception_user_unhandled.py @@ -0,0 +1,22 @@ +def main(): + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from not_my_code import other + + def callback2(): + try:raise AssertionError() + except:return False + + return True + + def callback1(): + other.call_me_back2(callback2) + + other.call_me_back1(callback1) + print('TEST SUCEEDED!') + + +if __name__ == '__main__': + main() diff --git a/tests_python/resources/my_code/my_code_on_entry.py b/tests_python/resources/my_code/my_code_on_entry.py new file mode 100644 index 0000000..ebfaa1b --- /dev/null +++ b/tests_python/resources/my_code/my_code_on_entry.py @@ -0,0 +1 @@ +print('my code on entry') diff --git a/tests_python/resources/not_my_code/__init__.py b/tests_python/resources/not_my_code/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resources/not_my_code/empty_file.py b/tests_python/resources/not_my_code/empty_file.py new file mode 100644 index 0000000..e69de29 diff --git a/tests_python/resources/not_my_code/main_on_entry.py b/tests_python/resources/not_my_code/main_on_entry.py new file mode 100644 index 0000000..1edcc1b --- /dev/null +++ b/tests_python/resources/not_my_code/main_on_entry.py @@ -0,0 +1,7 @@ +if __name__ == '__main__': + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + from my_code import my_code_on_entry + print('TEST SUCEEDED') diff --git a/tests_python/resources/not_my_code/main_on_entry2.py b/tests_python/resources/not_my_code/main_on_entry2.py new file mode 100644 index 0000000..79c9ee3 --- /dev/null +++ b/tests_python/resources/not_my_code/main_on_entry2.py @@ -0,0 +1,24 @@ +if __name__ == '__main__': + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + + def call(): + return 1 + + call() + # Check that we're not setting return values here. + assert '__pydevd_ret_val_dict' not in sys._getframe().f_locals + + try: + import enum + except ImportError: + pass + else: + + # i.e.: this could fail if a return value was traced + class MyCode(enum.IntEnum): + A = 10 + + import empty_file + print('TEST SUCEEDED') diff --git a/tests_python/resources/not_my_code/not_my_coroutine.py b/tests_python/resources/not_my_code/not_my_coroutine.py new file mode 100644 index 0000000..b3d16df --- /dev/null +++ b/tests_python/resources/not_my_code/not_my_coroutine.py @@ -0,0 +1,5 @@ + + +async def call1(callback): + await callback() + diff --git a/tests_python/resources/not_my_code/other.py b/tests_python/resources/not_my_code/other.py new file mode 100644 index 0000000..431b634 --- /dev/null +++ b/tests_python/resources/not_my_code/other.py @@ -0,0 +1,15 @@ +def call_me_back2(callback): + a = 'other' + callback() + return a + + +def call_me_back1(callback): + a = 'other' + callback() + return a + + +def raise_exception(): + raise RuntimeError('TEST SUCEEDED') + diff --git a/tests_python/resources/not_my_code/other_noop.py b/tests_python/resources/not_my_code/other_noop.py new file mode 100644 index 0000000..5fa9664 --- /dev/null +++ b/tests_python/resources/not_my_code/other_noop.py @@ -0,0 +1,2 @@ +def call_noop(): + return None diff --git a/tests_python/resources/wrong_bytecode/_debugger_case_wrong_bytecode.py b/tests_python/resources/wrong_bytecode/_debugger_case_wrong_bytecode.py new file mode 100644 index 0000000..5d8f49f --- /dev/null +++ b/tests_python/resources/wrong_bytecode/_debugger_case_wrong_bytecode.py @@ -0,0 +1,47 @@ +import helper +import sys +import helper +import helper +import helper +import helper +from helper import helper as sa +from helper.helper.helper import NULL +from helper.helper import NULL + +Base = NULL() + +def MyFunction(): + pass + +class MyClassA(object): + __tablename__ = 'tableA' + n = sa.NULL(sa.NULL, primary_key=True) + +class MyClassB(object): + __tablename__ = 'tableB' + n = sa.NULL(sa.NULL, primary_key=True) + +class MyClassC(object): + def __init__(self): + pass + +class MyClassD(object): + def __init__(self): + pass + +if __name__ == "__main__": + N = len(sys.argv) # break here + + if N >= 2: # step 1 + arg1 = sys.argv[1] # the debugger gets here even though N=1 + print(arg1) + else: + arg1 = 'MyString' # step 2 + + if N >= 3: # step 3 + arg2 = int(sys.argv[2]) # the debugger gets here even though N=1 + else: + arg2 = int(0) # step 4 + + print(N) # still N=1 step 5 + # print(arg1) # if you print this then it changes the debugger behavior above \ No newline at end of file diff --git a/tests_python/resources/wrong_bytecode/helper/__init__.py b/tests_python/resources/wrong_bytecode/helper/__init__.py new file mode 100644 index 0000000..65192b0 --- /dev/null +++ b/tests_python/resources/wrong_bytecode/helper/__init__.py @@ -0,0 +1,58 @@ +print('TEST SUCEEDED!') + +class Null: + """ + Gotten from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205 + """ + + def __init__(self, *args, **kwargs): + return None + + def __call__(self, *args, **kwargs): + return self + + def __enter__(self, *args, **kwargs): + return self + + def __exit__(self, *args, **kwargs): + return self + + def __getattr__(self, mname): + if len(mname) > 4 and mname[:2] == '__' and mname[-2:] == '__': + # Don't pretend to implement special method names. + raise AttributeError(mname) + return self + + def __setattr__(self, name, value): + return self + + def __delattr__(self, name): + return self + + def __repr__(self): + return "" + + def __str__(self): + return "Null" + + def __len__(self): + return 0 + + def __getitem__(self): + return self + + def __setitem__(self, *args, **kwargs): + pass + + def write(self, *args, **kwargs): + pass + + def __nonzero__(self): + return 0 + + def __iter__(self): + return iter(()) + + +# Default instance +NULL = Null() diff --git a/tests_python/resources/wrong_bytecode/helper/helper/__init__.py b/tests_python/resources/wrong_bytecode/helper/helper/__init__.py new file mode 100644 index 0000000..9ee7074 --- /dev/null +++ b/tests_python/resources/wrong_bytecode/helper/helper/__init__.py @@ -0,0 +1,56 @@ +class Null: + """ + Gotten from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205 + """ + + def __init__(self, *args, **kwargs): + return None + + def __call__(self, *args, **kwargs): + return self + + def __enter__(self, *args, **kwargs): + return self + + def __exit__(self, *args, **kwargs): + return self + + def __getattr__(self, mname): + if len(mname) > 4 and mname[:2] == '__' and mname[-2:] == '__': + # Don't pretend to implement special method names. + raise AttributeError(mname) + return self + + def __setattr__(self, name, value): + return self + + def __delattr__(self, name): + return self + + def __repr__(self): + return "" + + def __str__(self): + return "Null" + + def __len__(self): + return 0 + + def __getitem__(self): + return self + + def __setitem__(self, *args, **kwargs): + pass + + def write(self, *args, **kwargs): + pass + + def __nonzero__(self): + return 0 + + def __iter__(self): + return iter(()) + + +# Default instance +NULL = Null() diff --git a/tests_python/resources/wrong_bytecode/helper/helper/helper/__init__.py b/tests_python/resources/wrong_bytecode/helper/helper/helper/__init__.py new file mode 100644 index 0000000..9ee7074 --- /dev/null +++ b/tests_python/resources/wrong_bytecode/helper/helper/helper/__init__.py @@ -0,0 +1,56 @@ +class Null: + """ + Gotten from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205 + """ + + def __init__(self, *args, **kwargs): + return None + + def __call__(self, *args, **kwargs): + return self + + def __enter__(self, *args, **kwargs): + return self + + def __exit__(self, *args, **kwargs): + return self + + def __getattr__(self, mname): + if len(mname) > 4 and mname[:2] == '__' and mname[-2:] == '__': + # Don't pretend to implement special method names. + raise AttributeError(mname) + return self + + def __setattr__(self, name, value): + return self + + def __delattr__(self, name): + return self + + def __repr__(self): + return "" + + def __str__(self): + return "Null" + + def __len__(self): + return 0 + + def __getitem__(self): + return self + + def __setitem__(self, *args, **kwargs): + pass + + def write(self, *args, **kwargs): + pass + + def __nonzero__(self): + return 0 + + def __iter__(self): + return iter(()) + + +# Default instance +NULL = Null() diff --git a/tests_python/test_additional_thread_info.py b/tests_python/test_additional_thread_info.py new file mode 100644 index 0000000..7852b8f --- /dev/null +++ b/tests_python/test_additional_thread_info.py @@ -0,0 +1,82 @@ +import sys +import os +from _pydev_bundle import pydev_monkey +sys.path.insert(0, os.path.split(os.path.split(__file__)[0])[0]) + +import unittest + +try: + import thread +except: + import _thread as thread # @UnresolvedImport + + +#======================================================================================================================= +# TestCase +#======================================================================================================================= +class TestCase(unittest.TestCase): + + def test_start_new_thread(self): + pydev_monkey.patch_thread_modules() + try: + found = {} + + def function(a, b, *args, **kwargs): + found['a'] = a + found['b'] = b + found['args'] = args + found['kwargs'] = kwargs + + thread.start_new_thread(function, (1, 2, 3, 4), {'d':1, 'e':2}) + import time + for _i in range(20): + if len(found) == 4: + break + time.sleep(.1) + else: + raise AssertionError('Could not get to condition before 2 seconds') + + self.assertEqual({'a': 1, 'b': 2, 'args': (3, 4), 'kwargs': {'e': 2, 'd': 1}}, found) + finally: + pydev_monkey.undo_patch_thread_modules() + + def test_start_new_thread2(self): + pydev_monkey.patch_thread_modules() + try: + found = {} + + class F(object): + start_new_thread = thread.start_new_thread + + def start_it(self): + try: + self.start_new_thread(self.function, (1, 2, 3, 4), {'d':1, 'e':2}) + except: + import traceback;traceback.print_exc() + + def function(self, a, b, *args, **kwargs): + found['a'] = a + found['b'] = b + found['args'] = args + found['kwargs'] = kwargs + + f = F() + f.start_it() + import time + for _i in range(20): + if len(found) == 4: + break + time.sleep(.1) + else: + raise AssertionError('Could not get to condition before 2 seconds') + + self.assertEqual({'a': 1, 'b': 2, 'args': (3, 4), 'kwargs': {'e': 2, 'd': 1}}, found) + finally: + pydev_monkey.undo_patch_thread_modules() + + +#======================================================================================================================= +# main +#======================================================================================================================= +if __name__ == '__main__': + unittest.main() diff --git a/tests_python/test_bytecode_manipulation.py b/tests_python/test_bytecode_manipulation.py new file mode 100644 index 0000000..6a3bc2a --- /dev/null +++ b/tests_python/test_bytecode_manipulation.py @@ -0,0 +1,279 @@ +from io import StringIO +import os +import sys +import traceback + +import pytest + +from tests_python.debug_constants import IS_PY36_OR_GREATER, IS_CPYTHON, TEST_CYTHON, TODO_PY311 +import dis + +pytestmark = pytest.mark.skipif( + not IS_PY36_OR_GREATER or + TODO_PY311 or + not IS_CPYTHON or + not TEST_CYTHON, reason='Requires CPython >= 3.6 < 3.11') + + +class _Tracer(object): + + def __init__(self): + self.stream = StringIO() + self._in_print = False + self.accept_frame = None # Can be set to a callable + self.lines_executed = set() + + def tracer_printer(self, frame, event, arg): + if self._in_print: + return None + self._in_print = True + try: + if self.accept_frame is None or self.accept_frame(frame): + if arg is not None: + if event == 'exception': + arg = arg[0].__name__ + elif arg is not None: + arg = str(arg) + if arg is None: + arg = '' + + self.lines_executed.add(frame.f_lineno) + + s = ' '.join(( + str(frame.f_lineno), + frame.f_code.co_name, + os.path.basename(frame.f_code.co_filename), + event.upper() if event != 'line' else event, + arg, + )) + self.writeln(s) + except: + traceback.print_exc() + self._in_print = False + return self.tracer_printer + + def writeln(self, s): + self.write(s) + self.write('\n') + + def write(self, s): + if isinstance(s, bytes): + s = s.decode('utf-8') + self.stream.write(s) + + def call(self, c): + sys.settrace(self.tracer_printer) + c() + sys.settrace(None) + return self.stream.getvalue() + + +def check( + filename, + method, + method_kwargs=None, + skip_breaks_at_lines=None, + method_to_change=None, + stop_at_all_lines=False, + has_line_event_optimized_in_original_case=False, + ): + ''' + :param has_line_event_optimized_in_original_case: + If True, we're handling a case where we have a double jump, i.e.: some case + where there's a JUMP_FORWARD which points to a JUMP_ABSOLUTE and this is + optimized so that the JUMP_FORWARD is changed directly to a JUMP_ABSOLUTE and + we end up skipping one line event which is supposed to be there but isn't in + the initial case but appears when we run after modifying the bytecode in memory. + + See: https://github.com/microsoft/debugpy/issues/973#issuecomment-1178090731 + ''' + from _pydevd_frame_eval.pydevd_modify_bytecode import _get_code_line_info + from _pydevd_frame_eval import pydevd_modify_bytecode + + if method_to_change is None: + method_to_change = method + + if method_kwargs is None: + method_kwargs = {} + if skip_breaks_at_lines is None: + skip_breaks_at_lines = set() + + pydev_break_stops = [] + + def _pydev_needs_stop_at_break(line): + pydev_break_stops.append(line) + return False + + tracer = _Tracer() + + def accept_frame(f): + return filename in f.f_code.co_filename + + code = method_to_change.__code__ + code_line_info = _get_code_line_info(code) + + try: + tracer.accept_frame = accept_frame + + def call(): + method(**method_kwargs) + + tracer.call(call) + breakpoint_hit_at_least_once = False + + # Ok, we just ran the tracer once without any breakpoints. + # + # Gather its tracing profile: this will be our baseline for further tests (it should contain + # the events and the order in which the were executed). + # + # Note: methods cannot have random elements when executing (otherwise + # the order would be different and the test would be expected to fail). + baseline = tracer.stream.getvalue() + + for line in sorted(code_line_info.line_to_offset): + if line in skip_breaks_at_lines: + continue + # Now, for each valid line, add a breakpoint and check if the tracing profile is exactly + # the same (and if the line where we added the breakpoint was executed, see if our + # callback got called). + success, new_code = pydevd_modify_bytecode.insert_pydevd_breaks(code, set([line]), _pydev_needs_stop_at_break=_pydev_needs_stop_at_break) + + assert success + method_to_change.__code__ = new_code + + tracer = _Tracer() + tracer.accept_frame = accept_frame + tracer.call(call) + contents = tracer.stream.getvalue() + + assert tracer.lines_executed + if has_line_event_optimized_in_original_case: + lines = sorted(set(x[1] for x in dis.findlinestarts(new_code))) + new_line_contents = [] + last_line = str(max(lines)) + ' ' + for l in contents.splitlines(keepends=True): + if not l.strip().startswith(last_line): + new_line_contents.append(l) + contents = ''.join(new_line_contents) + + if line in tracer.lines_executed: + assert set([line]) == set(pydev_break_stops) + breakpoint_hit_at_least_once = True + else: + if stop_at_all_lines: + raise AssertionError('Expected the debugger to stop at all lines. Did not stop at line: %s' % (line,)) + del pydev_break_stops[:] + + if baseline != contents: + print('------- replacement at line: %s ---------' % (line,)) + print('------- baseline ---------') + print(baseline) + print('------- contents ---------') + print(contents) + print('-------- error -----------') + assert baseline == contents + + # We must have found a break at least once! + assert breakpoint_hit_at_least_once + finally: + method_to_change.__code__ = code + + +def test_set_pydevd_break_01(): + from tests_python.resources import _bytecode_overflow_example + + check('_bytecode_overflow_example.py', _bytecode_overflow_example.Dummy.fun, method_kwargs={'text': 'ing'}, has_line_event_optimized_in_original_case=True) + + +def test_set_pydevd_break_01a(): + from tests_python.resources import _bytecode_overflow_example + + check('_bytecode_overflow_example.py', _bytecode_overflow_example.check_backtrack, method_kwargs={'x': 'f'}) + + +def test_set_pydevd_break_02(): + from tests_python.resources import _bytecode_many_names_example + + check('_bytecode_many_names_example.py', _bytecode_many_names_example.foo) + + +def test_set_pydevd_break_03(): + from tests_python.resources import _bytecode_big_method + + check('_bytecode_big_method.py', _bytecode_big_method.foo) + + +def test_set_pydevd_break_04(): + from tests_python.resources import _debugger_case_yield_from + + check('_debugger_case_yield_from.py', _debugger_case_yield_from.method) + + +def test_set_pydevd_break_05(): + from tests_python import debugger_unittest + add_to_pythonpath = debugger_unittest._get_debugger_test_file('wrong_bytecode') + sys.path.append(add_to_pythonpath) + + try: + with open(debugger_unittest._get_debugger_test_file('wrong_bytecode/_debugger_case_wrong_bytecode.py'), 'r') as stream: + contents = stream.read() + + code = compile(contents, '_my_file_debugger_case_wrong_bytecode.py', 'exec') + + def method(): + pass + + method.__code__ = code + + check('_my_file_debugger_case_wrong_bytecode.py', method, skip_breaks_at_lines=set([1])) + finally: + sys.path.remove(add_to_pythonpath) + + +def test_set_pydevd_break_06(pyfile): + from tests_python.resources import _bytecode_super + + check('_bytecode_super.py', _bytecode_super.B, method_to_change=_bytecode_super.B.__init__, stop_at_all_lines=True) + + +def test_set_pydevd_break_07(): + from tests_python.resources import _bytecode_overflow_example + + check('_bytecode_overflow_example.py', _bytecode_overflow_example.offset_overflow, method_kwargs={'stream': StringIO()}) + + +def test_set_pydevd_break_08(): + from tests_python.resources import _bytecode_overflow_example + + check('_bytecode_overflow_example.py', _bytecode_overflow_example.long_lines, stop_at_all_lines=True) + + +def test_internal_double_linked_list(): + from _pydevd_frame_eval.pydevd_modify_bytecode import _HelperBytecodeList + lst = _HelperBytecodeList() + node1 = lst.append(1) + assert list(lst) == [1] + node2 = lst.append(2) + assert list(lst) == [1, 2] + + node15 = node1.append(1.5) + assert list(lst) == [1, 1.5, 2] + + node12 = node15.prepend(1.2) + assert list(lst) == [1, 1.2, 1.5, 2] + + node12.prepend(1.1) + assert list(lst) == [1, 1.1, 1.2, 1.5, 2] + + node1.prepend(0) + assert list(lst) == [0, 1, 1.1, 1.2, 1.5, 2] + + node2.append(3) + assert list(lst) == [0, 1, 1.1, 1.2, 1.5, 2, 3] + + assert lst.head.data == 0 + assert lst.tail.data == 3 + + lst = _HelperBytecodeList([1, 2, 3, 4, 5]) + assert lst.head.data == 1 + assert lst.tail.data == 5 diff --git a/tests_python/test_code_obj_to_source_code.py b/tests_python/test_code_obj_to_source_code.py new file mode 100644 index 0000000..7516cbf --- /dev/null +++ b/tests_python/test_code_obj_to_source_code.py @@ -0,0 +1,95 @@ +from _pydevd_bundle.pydevd_code_to_source import code_obj_to_source +import pytest + +# i.e.: Skip these tests (this is a work in progress / proof of concept / not ready to be used). +pytestmark = pytest.mark.skip + + +def check(obtained, expected, strip_return_none=True): + keepends = False + obtained_lines = list(obtained.rstrip().splitlines(keepends)) + if strip_return_none: + obtained_lines = [x.replace('return None', '') for x in obtained_lines] + + expected_lines = list(expected.rstrip().splitlines(keepends)) + + assert obtained_lines == expected_lines + + +def test_code_obj_to_source_make_class_and_func(): + code = ''' +class MyClass(object, other_class): + def my_func(self): + print(self) +''' + expected = ''' +__module__=__name____qualname__=MyClassMyClass=(def MyClass():MyClass,object,other_class,) + def MyClass.my_func(self): + print(self) +''' + + co = compile(code, '', 'exec') + + contents = code_obj_to_source(co) + check(contents, expected) + + +def test_code_obj_to_source_lambda(): + code = 'my_func = lambda arg: (2,)' + + co = compile(code, '', 'exec') + + contents = code_obj_to_source(co) + check(contents, 'my_func=(arg):return return (2,)None') + + +def test_code_obj_to_source_make_func(): + code = ''' + +def my_func(arg1, arg2=2, arg3=3): + some_call(arg1) +''' + + co = compile(code, '', 'exec') + + contents = code_obj_to_source(co) + check(contents, code) + + +def test_code_obj_to_source_call_func(): + code = 'a=call1(call2(arg1))' + + co = compile(code, '', 'exec') + + contents = code_obj_to_source(co) + check(contents, code) + + +def test_for_list_comp(): + code = '[x for x in range(10)]' + + co = compile(code, '', 'exec') + + contents = code_obj_to_source(co) + check(contents, code) + + +def test_code_obj_to_source_for(): + code = 'for i in range(10):\n print(i)' + + co = compile(code, '', 'exec') + + contents = code_obj_to_source(co) + check(contents, code) + + +def test_code_obj_to_source_call_func2(): + code = '''a=call1( +call2( +arg1)) +''' + + co = compile(code, '', 'exec') + + contents = code_obj_to_source(co) + check(contents, code) diff --git a/tests_python/test_collect_bytecode_info.py b/tests_python/test_collect_bytecode_info.py new file mode 100644 index 0000000..c3e8b39 --- /dev/null +++ b/tests_python/test_collect_bytecode_info.py @@ -0,0 +1,698 @@ +# coding: utf-8 +from io import StringIO +import os.path +import sys +import traceback + +from _pydevd_bundle.pydevd_collect_bytecode_info import collect_try_except_info, \ + collect_return_info, code_to_bytecode_representation +from tests_python.debugger_unittest import IS_CPYTHON, IS_PYPY +from _pydevd_bundle.pydevd_constants import IS_PY38_OR_GREATER, IS_JYTHON +from tests_python.debug_constants import IS_PY311_OR_GREATER + + +def _method_call_with_error(): + try: + _method_reraise() + except: + raise + + +def _method_except_local(): + Foo = AssertionError + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except Foo as exc: + # DUP_TOP, LOAD_FAST (x), COMPARE_OP (exception match), POP_JUMP_IF_FALSE + pass + + +def _method_reraise(): + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except AssertionError as e: # POP_TOP + raise e + + +def _method_return_with_error(): + _method_call_with_error() + + +def _method_return_with_error2(): + try: + _method_call_with_error() + except: + return + + +def _method_simple_raise_any_except(): + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except: # POP_TOP + pass + + +def _method_simple_raise_any_except_return_on_raise(): + # Note how the tracing the debugger has is equal to the tracing from _method_simple_raise_any_except + # but this one resulted in an unhandled exception while the other one didn't. + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except: # POP_TOP + raise # RAISE_VARARGS + + +def _method_simple_raise_local_load(): + x = AssertionError + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except x as exc: + # DUP_TOP, LOAD_GLOBAL (NameError), LOAD_GLOBAL(AssertionError), BUILD_TUPLE, + # COMPARE_OP (exception match), POP_JUMP_IF_FALSE + pass + + +def _method_simple_raise_multi_except(): + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except (NameError, AssertionError) as exc: + # DUP_TOP, LOAD_FAST (x), COMPARE_OP (exception match), POP_JUMP_IF_FALSE + pass + + +def _method_simple_raise_unmatched_except(): + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except NameError: # DUP_TOP, LOAD_GLOBAL (NameError), COMPARE_OP (exception match), POP_JUMP_IF_FALSE + pass + + +class _Tracer(object): + + def __init__(self, partial_info=False): + self.partial_info = partial_info + self.stream = StringIO() + self._in_print = False + + def tracer_printer(self, frame, event, arg): + if self._in_print: + return None + self._in_print = True + try: + if arg is not None: + if event == 'exception': + arg = arg[0].__name__ + elif arg is not None: + arg = str(arg) + if arg is None: + arg = '' + + if self.partial_info: + s = ' '.join(( + os.path.basename(frame.f_code.co_filename), + event.upper() if event != 'line' else event, + arg, + )) + else: + s = ' '.join(( + str(frame.f_lineno), + frame.f_code.co_name, + os.path.basename(frame.f_code.co_filename), + event.upper() if event != 'line' else event, + arg, + )) + self.writeln(s) + except: + traceback.print_exc() + self._in_print = False + return self.tracer_printer + + def writeln(self, s): + self.write(s) + self.write('\n') + + def write(self, s): + if isinstance(s, bytes): + s = s.decode('utf-8') + self.stream.write(s) + + def call(self, c): + sys.settrace(self.tracer_printer) + try: + c() + except: + pass + sys.settrace(None) + return self.stream.getvalue() + + +import pytest + + +class _ExcVerifier(object): + + def __init__(self, pyfile): + self.pyfile = pyfile + + def check(self, method, expected_as_str, expected_as_str_source_version=None, update_try_except_infos=None): + code = method.__code__ + + try_except_infos = sorted(collect_try_except_info(code, use_func_first_line=True), key=lambda t:t.try_line) + if IS_CPYTHON or IS_PYPY: + if update_try_except_infos is not None: + update_try_except_infos(try_except_infos) + + if sys.version_info[:2] not in ((3, 10), (3, 11)): + assert str(try_except_infos) == expected_as_str + from _pydevd_bundle.pydevd_collect_bytecode_info import collect_try_except_info_from_source + + expected_as_str_source_version = expected_as_str_source_version or expected_as_str + try_except_infos = collect_try_except_info_from_source(self.pyfile(method)) + if update_try_except_infos is not None: + update_try_except_infos(try_except_infos) + assert str(try_except_infos) == expected_as_str_source_version + else: + assert try_except_infos == [] + + +@pytest.fixture +def exc_verifier(pyfile): + return _ExcVerifier(pyfile) + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +def test_collect_try_except_info(data_regression, pyfile): + from _pydevd_bundle.pydevd_collect_bytecode_info import collect_try_except_info_from_source + method_to_info = {} + method_to_info_from_source = {} + for key, method in sorted(dict(globals()).items()): + if key.startswith('_method'): + + info = collect_try_except_info_from_source(pyfile(method)) + method_to_info_from_source[key] = sorted(str(x) for x in info) + + info = collect_try_except_info(method.__code__, use_func_first_line=True) + method_to_info[key] = sorted(str(x) for x in info) + + if sys.version_info[:2] not in ((3, 10), (3, 11)): + data_regression.check(method_to_info) + + data_regression.check(method_to_info_from_source) + + +def test_collect_try_except_info2(exc_verifier): + + def method(): + try: + raise AssertionError + except: + _a = 10 + raise + finally: + _b = 20 + _c = 20 + + exc_verifier.check(method, '[{try:1 except 3 end block 5 raises: 5}]') + + +def test_collect_try_except_info3(exc_verifier): + + def method(): + get_exc_class = lambda:AssertionError + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except get_exc_class() \ + as e: # POP_TOP + raise e + + exc_verifier.check(method, '[{try:2 except 4 end block 6}]') + + +def test_collect_try_except_info4(exc_verifier): + + def method(): + for i in range(2): + try: + raise AssertionError() + except AssertionError: + if i == 1: + try: + raise + except: + pass + + _foo = 10 + + exc_verifier.check( + method, + '[{try:2 except 4 end block 9 raises: 7}, {try:6 except 8 end block 9 raises: 7}]', + '[{try:2 except 4 end block 9 raises: 7}, {try:6 except 8 end block 9}]', + ) + + +def test_collect_try_except_info4a(exc_verifier): + + def method(): + for i in range(2): + try: + raise AssertionError() + except: + if i == 1: + try: + raise + except: + pass + + _foo = 10 + + exc_verifier.check(method, + '[{try:2 except 4 end block 9 raises: 7}, {try:6 except 8 end block 9 raises: 7}]', + '[{try:2 except 4 end block 9 raises: 7}, {try:6 except 8 end block 9}]', + ) + + +def test_collect_try_except_info_raise_unhandled7(exc_verifier): + + def raise_unhandled7(): + try: + raise AssertionError() + except AssertionError: + try: + raise AssertionError() + except RuntimeError: + pass + + exc_verifier.check(raise_unhandled7, '[{try:1 except 3 end block 7}, {try:4 except 6 end block 7}]') + + +def test_collect_try_except_info_raise_unhandled10(exc_verifier): + + def raise_unhandled10(): + for i in range(2): + try: + raise AssertionError() + except AssertionError: + if i == 1: + try: + raise + except RuntimeError: + pass + + exc_verifier.check( + raise_unhandled10, + '[{try:2 except 4 end block 9 raises: 7}, {try:6 except 8 end block 9 raises: 7}]', + '[{try:2 except 4 end block 9 raises: 7}, {try:6 except 8 end block 9}]', + ) + + +def test_collect_try_except_info_return_on_except(exc_verifier): + + def method(): + try: # SETUP_EXCEPT (to except line) + try: # SETUP_EXCEPT (to except line) + raise AssertionError() + except: # POP_TOP + raise + except: # POP_TOP + return ( + 1, + 2 + ) + + def update_try_except_infos(try_except_infos): + for try_except_info in try_except_infos: + # On 3.7/3.8 the last bytecode actually has a different start line. + if try_except_info.except_end_line in (7, 8): + try_except_info.except_end_line = 9 + + try_except_info_for_source = '[{try:1 except 6 end block 10}, {try:2 except 4 end block 5 raises: 5}]' + if sys.version_info[:2] <= (3, 7): + # The ast doesn't have end_lineno, so, the end block must be calculated based on children lineno (and thus is a bit different). + try_except_info_for_source = '[{try:1 except 6 end block 9}, {try:2 except 4 end block 5 raises: 5}]' + + exc_verifier.check( + method, + '[{try:1 except 6 end block 9 raises: 5}, {try:2 except 4 end block 5 raises: 5}]', + try_except_info_for_source, + update_try_except_infos=update_try_except_infos + ) + + +def test_collect_try_except_info_with(exc_verifier): + + def try_except_with(): + try: + with object(): + pass + except AssertionError: + pass + + exc_verifier.check(try_except_with, '[{try:1 except 4 end block 5}]') + + +def test_collect_try_except_info_in_single_line_1(exc_verifier): + + def try_except_single_line(): + try:range() + except: + return False + return True + + exc_verifier.check(try_except_single_line, '[{try:1 except 2 end block 3}]') + + +def test_collect_try_except_info_in_single_line_2(exc_verifier): + + def try_except_single_line(): + try:range() + except: return False + return True + + exc_verifier.check(try_except_single_line, '[{try:1 except 2 end block 2}]') + + +def test_collect_try_except_info_multiple_except(exc_verifier): + + def try_except_with(): + try: + pass + except AssertionError: + a = 1 + except RuntimeError: + a = 2 + except: + a = 3 + + exc_verifier.check(try_except_with, '[{try:1 except 3 end block 8}]') + + +def test_collect_try_except_info_async_for(): + if IS_PY311_OR_GREATER: + pytest.skip('On Python 3.11 we just support collecting info from the AST.') + + # Not valid on Python 2. + code_str = ''' +async def try_except_with(): + try: + async for a in object(): + b = 10 + else: + b = 20 + except AssertionError: + pass +''' + + namespace = {} + exec(code_str, namespace, namespace) + code = namespace['try_except_with'].__code__ + + lst = sorted(collect_try_except_info(code, use_func_first_line=True), key=lambda t:t.try_line) + if IS_CPYTHON or IS_PYPY: + if IS_PY38_OR_GREATER: + assert str(lst) == '[{try:1 except 6 end block 7}]' + else: + # Before Python 3.8 the async for does a try..except StopAsyncIteration internally. + assert str(lst) in ( + '[{try:1 except 6 end block 7}, {try:2 except 2 end block 7}]', + '[{try:1 except 6 end block 7}, {try:2 except 2 end block 2}]' + ) + + # The version from the contents should always be correct. + from _pydevd_bundle.pydevd_collect_bytecode_info import collect_try_except_info_from_contents + assert str(collect_try_except_info_from_contents(code_str)) == '[{try:3 except 8 end block 9}]' + + else: + assert lst == [] + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_collect_return_info(): + + def method(): + return 1 + + assert str(collect_return_info(method.__code__, use_func_first_line=True)) == '[{return: 1}]' + + def method2(): + pass + + assert str(collect_return_info(method2.__code__, use_func_first_line=True)) == '[{return: 1}]' + + def method3(): + yield 1 + yield 2 + + assert str(collect_return_info(method3.__code__, use_func_first_line=True)) == '[{return: 2}]' + + def method4(): + return (1, + 2, + 3, + 4) + + assert str(collect_return_info(method4.__code__, use_func_first_line=True)) == \ + '[{return: 1}]' if IS_PY38_OR_GREATER else '[{return: 4}]' + + def method5(): + return \ + \ + 1 + + assert str(collect_return_info(method5.__code__, use_func_first_line=True)) == \ + '[{return: 1}]' if IS_PY38_OR_GREATER else '[{return: 3}]' + + code = ''' +def method(): + if a: + yield 1 + yield 2 + return 1 + else: + pass +''' + + scope = {} + exec(code, scope) + assert str(collect_return_info(scope['method'].__code__, use_func_first_line=True)) == \ + '[{return: 4}, {return: 6}]' + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr(): + + def method4(): + return (1, + 2, + 3, + call('tnh %s' % 1)) + + contents = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert contents.count('\n') == 4, 'Found:%s' % (contents,) + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr_many(): + + def method4(): + a = call() + if a == 20: + [x for x in call()] + + def method2(): + for x in y: + yield x + raise AssertionError + + return (1, + 2, + 3, + call('tnh 1' % 1)) + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + # print(new_repr) + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr2(): + + def method(): + print(10) + + def method4(a, b): + return (1, + 2, + 3, + call('somestr %s' % 1)) + + print(20) + + s = code_to_bytecode_representation(method.__code__, use_func_first_line=True) + assert s.count('\n') == 9, 'Expected 9 lines. Found: %s in:>>\n%s\n<<' % (s.count('\n'), s) + assert 'somestr' in s # i.e.: the contents of the inner code have been added too + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr_simple_method_calls(): + + def method4(): + call() + a = 10 + call(1, 2, 3, a, b, "x") + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert 'call()' in new_repr + assert 'call(1, 2, 3, a, b, \'x\')' in new_repr + assert 'NULL' not in new_repr + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr_assign(): + + def method4(): + a = call() + return call() + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert 'a = call()' in new_repr + assert 'return call()' in new_repr + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr_tuple(): + + def method4(): + return (1, 2, call(3, 4)) + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert 'return (1, 2, call(3, 4))' in new_repr + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_build_tuple(): + + def method4(): + return call(1, (call2(), 2)) + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert 'return call(1, (call2(), 2))' in new_repr + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr_return_tuple(): + + def method4(): + return (1, 2, 3, a) + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert 'return (1, 2, 3, a)' in new_repr + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr_return_tuple_with_call(): + + def method4(): + return (1, 2, 3, a()) + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert 'return (1, 2, 3, a())' in new_repr + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr_attr(): + + def method4(): + call(a.b.c) + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert 'call(a.b.c)' in new_repr + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_cls_method(): + + def method4(): + + class B: + + def method(self): + self.a.b.c + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert 'self.a.b.c' in new_repr + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not have bytecode support.') +def test_simple_code_to_bytecode_repr_unicode(): + + def method4(): + return 'áéíóú' + + new_repr = code_to_bytecode_representation(method4.__code__, use_func_first_line=True) + assert repr('áéíóú') in new_repr + + +def _create_entry(instruction): + argval = instruction.argval + return dict( + opname=instruction.opname, + argval=argval, + starts_line=instruction.starts_line, + is_jump_target=instruction.is_jump_target, + ) + + +def debug_test_iter_bytecode(data_regression): + # Note: not run by default, only to help visualizing bytecode and comparing differences among versions. + import dis + + basename = 'test_iter_bytecode.py%s%s' % (sys.version_info[:2]) + method_to_info = {} + for key, method in sorted(dict(globals()).items()): + if key.startswith('_method'): + info = [] + + if sys.version_info[0] < 3: + from _pydevd_bundle.pydevd_collect_bytecode_info import _iter_as_bytecode_as_instructions_py2 + iter_in = _iter_as_bytecode_as_instructions_py2(method.__code__) + else: + iter_in = dis.Bytecode(method) + + for instruction in iter_in: + info.append(_create_entry(instruction)) + + msg = [] + for d in info: + line = [] + for k, v in sorted(d.items()): + line.append(u'%s=%s' % (k, v)) + msg.append(u' '.join(line)) + if isinstance(key, bytes): + key = key.decode('utf-8') + method_to_info[key] = msg + + data_regression.check(method_to_info, basename=basename) + + +def debug_test_tracing_output(): # Note: not run by default, only to debug tracing. + from collections import defaultdict + output_to_method_names = defaultdict(list) + for key, val in sorted(dict(globals()).items()): + if key.startswith('_method'): + tracer = _Tracer(partial_info=False) + output_to_method_names[tracer.call(val)].append(val.__name__) + + # Notes: + # + # Seen as the same by the tracing (so, we inspect the bytecode to disambiguate). + # _method_simple_raise_any_except + # _method_simple_raise_any_except_return_on_raise + # _method_simple_raise_multi_except + # + # The return with an exception is always None + # + # It's not possible to disambiguate from a return None, pass or raise just with the tracing + # (only a raise with an exception is gotten by the debugger). + for output, method_names in sorted(output_to_method_names.items(), key=lambda x:(-len(x[1]), ''.join(x[1]))): + print('=' * 80) + print(' %s ' % (', '.join(method_names),)) + print('=' * 80) + print(output) diff --git a/tests_python/test_collect_bytecode_info/test_collect_try_except_info.json b/tests_python/test_collect_bytecode_info/test_collect_try_except_info.json new file mode 100644 index 0000000..3f4039d --- /dev/null +++ b/tests_python/test_collect_bytecode_info/test_collect_try_except_info.json @@ -0,0 +1,30 @@ +{ + "_method_call_with_error": [ + "{try:1 except 3 end block 4 raises: 4}" + ], + "_method_except_local": [ + "{try:2 except 4 end block 6}" + ], + "_method_reraise": [ + "{try:1 except 3 end block 4}" + ], + "_method_return_with_error": [], + "_method_return_with_error2": [ + "{try:1 except 3 end block 4}" + ], + "_method_simple_raise_any_except": [ + "{try:1 except 3 end block 4}" + ], + "_method_simple_raise_any_except_return_on_raise": [ + "{try:3 except 5 end block 6 raises: 6}" + ], + "_method_simple_raise_local_load": [ + "{try:2 except 4 end block 7}" + ], + "_method_simple_raise_multi_except": [ + "{try:1 except 3 end block 5}" + ], + "_method_simple_raise_unmatched_except": [ + "{try:1 except 3 end block 4}" + ] +} \ No newline at end of file diff --git a/tests_python/test_collect_bytecode_info/test_iter_bytecode.py26.json b/tests_python/test_collect_bytecode_info/test_iter_bytecode.py26.json new file mode 100644 index 0000000..7013d74 --- /dev/null +++ b/tests_python/test_collect_bytecode_info/test_iter_bytecode.py26.json @@ -0,0 +1,210 @@ +{ + "_method_call_with_error": [ + "argval=14 is_jump_target=False opname=SETUP_EXCEPT starts_line=11", + "argval=_method_reraise is_jump_target=False opname=LOAD_GLOBAL starts_line=12", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=24 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=13", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=14", + "argval=24 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_except_local": [ + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=18", + "argval=Foo is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=22 is_jump_target=False opname=SETUP_EXCEPT starts_line=19", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=20", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=43 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=21", + "argval=Foo is_jump_target=False opname=LOAD_FAST starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=43 is_jump_target=False opname=JUMP_FORWARD starts_line=23", + "argval=None is_jump_target=True opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_reraise": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=27", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=28", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=43 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=29", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=e is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=e is_jump_target=False opname=LOAD_FAST starts_line=30", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=43 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_return_with_error": [ + "argval=_method_call_with_error is_jump_target=False opname=LOAD_GLOBAL starts_line=34", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_return_with_error2": [ + "argval=14 is_jump_target=False opname=SETUP_EXCEPT starts_line=38", + "argval=_method_call_with_error is_jump_target=False opname=LOAD_GLOBAL starts_line=39", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=22 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=40", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=41", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_any_except": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=45", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=46", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=23 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=47", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=23 is_jump_target=False opname=JUMP_FORWARD starts_line=48", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_any_except_return_on_raise": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=54", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=55", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=56", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=57", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_local_load": [ + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=61", + "argval=x is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=22 is_jump_target=False opname=SETUP_EXCEPT starts_line=62", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=63", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=43 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=64", + "argval=x is_jump_target=False opname=LOAD_FAST starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=43 is_jump_target=False opname=JUMP_FORWARD starts_line=67", + "argval=None is_jump_target=True opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_multi_except": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=71", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=72", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=43 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=73", + "argval=NameError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=2 is_jump_target=False opname=BUILD_TUPLE starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=43 is_jump_target=False opname=JUMP_FORWARD starts_line=75", + "argval=None is_jump_target=True opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_unmatched_except": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=79", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=80", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=35 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=81", + "argval=NameError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=33 is_jump_target=False opname=JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=35 is_jump_target=False opname=JUMP_FORWARD starts_line=82", + "argval=None is_jump_target=True opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_try_except": [ + "argval=33 is_jump_target=False opname=SETUP_EXCEPT starts_line=86", + "argval=19 is_jump_target=False opname=SETUP_EXCEPT starts_line=87", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=88", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=29 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=89", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=90", + "argval=29 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=POP_BLOCK starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=91", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=(1, 2) is_jump_target=False opname=LOAD_CONST starts_line=94", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ] +} \ No newline at end of file diff --git a/tests_python/test_collect_bytecode_info/test_iter_bytecode.py27.json b/tests_python/test_collect_bytecode_info/test_iter_bytecode.py27.json new file mode 100644 index 0000000..f4657b1 --- /dev/null +++ b/tests_python/test_collect_bytecode_info/test_iter_bytecode.py27.json @@ -0,0 +1,200 @@ +{ + "_method_call_with_error": [ + "argval=14 is_jump_target=False opname=SETUP_EXCEPT starts_line=11", + "argval=_method_reraise is_jump_target=False opname=LOAD_GLOBAL starts_line=12", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=24 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=13", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=14", + "argval=24 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_except_local": [ + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=18", + "argval=Foo is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=22 is_jump_target=False opname=SETUP_EXCEPT starts_line=19", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=20", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=21", + "argval=Foo is_jump_target=False opname=LOAD_FAST starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=40 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=23", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_reraise": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=27", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=28", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=29", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=40 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=e is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=e is_jump_target=False opname=LOAD_FAST starts_line=30", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_return_with_error": [ + "argval=_method_call_with_error is_jump_target=False opname=LOAD_GLOBAL starts_line=34", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_return_with_error2": [ + "argval=14 is_jump_target=False opname=SETUP_EXCEPT starts_line=38", + "argval=_method_call_with_error is_jump_target=False opname=LOAD_GLOBAL starts_line=39", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=22 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=40", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=41", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_any_except": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=45", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=46", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=23 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=47", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=23 is_jump_target=False opname=JUMP_FORWARD starts_line=48", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_any_except_return_on_raise": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=54", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=55", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=56", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=57", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_local_load": [ + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=61", + "argval=x is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=22 is_jump_target=False opname=SETUP_EXCEPT starts_line=62", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=63", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=64", + "argval=x is_jump_target=False opname=LOAD_FAST starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=40 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=67", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_multi_except": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=71", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=72", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=73", + "argval=NameError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=2 is_jump_target=False opname=BUILD_TUPLE starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=40 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=75", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_unmatched_except": [ + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=79", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=80", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=33 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=81", + "argval=NameError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=32 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=33 is_jump_target=False opname=JUMP_FORWARD starts_line=82", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_try_except": [ + "argval=33 is_jump_target=False opname=SETUP_EXCEPT starts_line=86", + "argval=19 is_jump_target=False opname=SETUP_EXCEPT starts_line=87", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=88", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=29 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=89", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=90", + "argval=29 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=POP_BLOCK starts_line=None", + "argval=41 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=91", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=(1, 2) is_jump_target=False opname=LOAD_CONST starts_line=94", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ] +} \ No newline at end of file diff --git a/tests_python/test_collect_bytecode_info/test_iter_bytecode.py36.json b/tests_python/test_collect_bytecode_info/test_iter_bytecode.py36.json new file mode 100644 index 0000000..9e6aea6 --- /dev/null +++ b/tests_python/test_collect_bytecode_info/test_iter_bytecode.py36.json @@ -0,0 +1,235 @@ +{ + "_method_call_with_error": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=11", + "argval=_method_reraise is_jump_target=False opname=LOAD_GLOBAL starts_line=12", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=13", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=14", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_except_local": [ + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=18", + "argval=Foo is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=19", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=20", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=21", + "argval=Foo is_jump_target=False opname=LOAD_FAST starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=48 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=38 is_jump_target=False opname=SETUP_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=23", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=exc is_jump_target=False opname=DELETE_FAST starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_reraise": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=27", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=28", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=29", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=48 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=e is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=38 is_jump_target=False opname=SETUP_FINALLY starts_line=None", + "argval=e is_jump_target=False opname=LOAD_FAST starts_line=30", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=e is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=e is_jump_target=False opname=DELETE_FAST starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_return_with_error": [ + "argval=_method_call_with_error is_jump_target=False opname=LOAD_GLOBAL starts_line=34", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_return_with_error2": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=38", + "argval=_method_call_with_error is_jump_target=False opname=LOAD_GLOBAL starts_line=39", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=22 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=40", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=41", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_any_except": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=45", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=46", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=24 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=47", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=48", + "argval=24 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_any_except_return_on_raise": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=54", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=55", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=56", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=57", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_local_load": [ + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=61", + "argval=x is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=62", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=63", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=64", + "argval=x is_jump_target=False opname=LOAD_FAST starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=48 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=38 is_jump_target=False opname=SETUP_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=67", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=exc is_jump_target=False opname=DELETE_FAST starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_multi_except": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=71", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=72", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=73", + "argval=NameError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=2 is_jump_target=False opname=BUILD_TUPLE starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=48 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=38 is_jump_target=False opname=SETUP_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=75", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=exc is_jump_target=False opname=DELETE_FAST starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_unmatched_except": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=79", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=80", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=32 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=81", + "argval=NameError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=30 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=82", + "argval=32 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_try_except": [ + "argval=32 is_jump_target=False opname=SETUP_EXCEPT starts_line=86", + "argval=14 is_jump_target=False opname=SETUP_EXCEPT starts_line=87", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=88", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=28 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=89", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=90", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=28 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=POP_BLOCK starts_line=None", + "argval=42 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=91", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=(1, 2) is_jump_target=False opname=LOAD_CONST starts_line=94", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ] +} \ No newline at end of file diff --git a/tests_python/test_collect_bytecode_info/test_iter_bytecode.py37.json b/tests_python/test_collect_bytecode_info/test_iter_bytecode.py37.json new file mode 100644 index 0000000..bef46a7 --- /dev/null +++ b/tests_python/test_collect_bytecode_info/test_iter_bytecode.py37.json @@ -0,0 +1,235 @@ +{ + "_method_call_with_error": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=11", + "argval=_method_reraise is_jump_target=False opname=LOAD_GLOBAL starts_line=12", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=13", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=14", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_except_local": [ + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=18", + "argval=Foo is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=19", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=20", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=21", + "argval=Foo is_jump_target=False opname=LOAD_FAST starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=48 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=36 is_jump_target=False opname=SETUP_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=23", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=exc is_jump_target=False opname=DELETE_FAST starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_reraise": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=27", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=28", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=29", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=48 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=e is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=36 is_jump_target=False opname=SETUP_FINALLY starts_line=None", + "argval=e is_jump_target=False opname=LOAD_FAST starts_line=30", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=e is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=e is_jump_target=False opname=DELETE_FAST starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_return_with_error": [ + "argval=_method_call_with_error is_jump_target=False opname=LOAD_GLOBAL starts_line=34", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_return_with_error2": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=38", + "argval=_method_call_with_error is_jump_target=False opname=LOAD_GLOBAL starts_line=39", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=22 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=40", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=41", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_any_except": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=45", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=46", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=24 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=47", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=48", + "argval=24 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_any_except_return_on_raise": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=54", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=55", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=56", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=57", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=26 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_local_load": [ + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=61", + "argval=x is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=16 is_jump_target=False opname=SETUP_EXCEPT starts_line=62", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=63", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=64", + "argval=x is_jump_target=False opname=LOAD_FAST starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=48 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=36 is_jump_target=False opname=SETUP_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=67", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=exc is_jump_target=False opname=DELETE_FAST starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_multi_except": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=71", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=72", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=73", + "argval=NameError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=2 is_jump_target=False opname=BUILD_TUPLE starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=48 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=36 is_jump_target=False opname=SETUP_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=75", + "argval=None is_jump_target=False opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=exc is_jump_target=False opname=STORE_FAST starts_line=None", + "argval=exc is_jump_target=False opname=DELETE_FAST starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=50 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_simple_raise_unmatched_except": [ + "argval=12 is_jump_target=False opname=SETUP_EXCEPT starts_line=79", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=80", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=32 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=DUP_TOP starts_line=81", + "argval=NameError is_jump_target=False opname=LOAD_GLOBAL starts_line=None", + "argval=exception match is_jump_target=False opname=COMPARE_OP starts_line=None", + "argval=30 is_jump_target=False opname=POP_JUMP_IF_FALSE starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=82", + "argval=32 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ], + "_method_try_except": [ + "argval=32 is_jump_target=False opname=SETUP_EXCEPT starts_line=86", + "argval=14 is_jump_target=False opname=SETUP_EXCEPT starts_line=87", + "argval=AssertionError is_jump_target=False opname=LOAD_GLOBAL starts_line=88", + "argval=0 is_jump_target=False opname=CALL_FUNCTION starts_line=None", + "argval=1 is_jump_target=False opname=RAISE_VARARGS starts_line=None", + "argval=None is_jump_target=False opname=POP_BLOCK starts_line=None", + "argval=28 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=89", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=0 is_jump_target=False opname=RAISE_VARARGS starts_line=90", + "argval=None is_jump_target=False opname=POP_EXCEPT starts_line=None", + "argval=28 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=False opname=END_FINALLY starts_line=None", + "argval=None is_jump_target=True opname=POP_BLOCK starts_line=None", + "argval=42 is_jump_target=False opname=JUMP_FORWARD starts_line=None", + "argval=None is_jump_target=True opname=POP_TOP starts_line=91", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=None is_jump_target=False opname=POP_TOP starts_line=None", + "argval=(1, 2) is_jump_target=False opname=LOAD_CONST starts_line=93", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None", + "argval=None is_jump_target=True opname=LOAD_CONST starts_line=None", + "argval=None is_jump_target=False opname=RETURN_VALUE starts_line=None" + ] +} \ No newline at end of file diff --git a/tests_python/test_console.py b/tests_python/test_console.py new file mode 100644 index 0000000..c1d0f84 --- /dev/null +++ b/tests_python/test_console.py @@ -0,0 +1,201 @@ +from contextlib import contextmanager + +import pytest + +from _pydev_bundle.pydev_override import overrides +from tests_python.debugger_fixtures import DebuggerRunnerSimple, debugger_runner_simple +from tests_python.debugger_unittest import AbstractWriterThread, SHOW_OTHER_DEBUG_INFO, \ + start_in_daemon_thread, wait_for_condition, IS_JYTHON +from _pydev_bundle.pydev_localhost import get_socket_names, get_socket_name +from _pydev_bundle.pydev_imports import xmlrpclib +from _pydev_bundle.pydev_imports import _queue as queue +from _pydev_bundle.pydev_imports import SimpleXMLRPCServer +import time +import socket + +builtin_qualifier = "builtins" + + +@pytest.fixture +def console_setup(tmpdir): + + server_queue = queue.Queue() + + def notify_finished(more): + server_queue.put(('notify_finished', more)) + return '' + + class ConsoleRunner(DebuggerRunnerSimple): + + @overrides(DebuggerRunnerSimple.add_command_line_args) + def add_command_line_args(self, args): + port, client_port = get_socket_names(2, close=True) + args.extend(( + writer.get_pydevconsole_file(), + str(port[1]), + str(client_port[1]) + )) + self.port = port + self.client_port = client_port + + server = SimpleXMLRPCServer(client_port) + server.register_function(notify_finished, "NotifyFinished") + start_in_daemon_thread(server.serve_forever, []) + + self.proxy = xmlrpclib.ServerProxy("http://%s:%s/" % port) + + return args + + class WriterThread(AbstractWriterThread): + + if IS_JYTHON: + EXPECTED_RETURNCODE = 'any' + + @overrides(AbstractWriterThread.additional_output_checks) + def additional_output_checks(self, stdout, stderr): + print('output found: %s - %s' % (stdout, stderr)) + + @overrides(AbstractWriterThread.write_dump_threads) + def write_dump_threads(self): + pass # no-op (may be called on timeout). + + def execute_line(self, command, more=False): + runner.proxy.execLine(command) + assert server_queue.get(timeout=5.) == ('notify_finished', more) + + def hello(self): + + def _hello(): + try: + msg = runner.proxy.hello('ignored') + if msg is not None: + if isinstance(msg, (list, tuple)): + msg = next(iter(msg)) + if msg.lower().startswith('hello'): + return True + except: + # That's ok, communication still not ready. + pass + + return False + + wait_for_condition(_hello) + + def close(self): + try: + runner.proxy.close() + except: + # Ignore any errors on close. + pass + + def connect_to_debugger(self, debugger_port): + runner.proxy.connectToDebugger(debugger_port) + + runner = ConsoleRunner(tmpdir) + writer = WriterThread() + + class CaseSetup(object): + + @contextmanager + def check_console( + self, + **kwargs + ): + for key, value in kwargs.items(): + assert hasattr(WriterThread, key) + setattr(WriterThread, key, value) + + self.writer = writer + + args = runner.get_command_line() + + args = runner.add_command_line_args(args) + + if SHOW_OTHER_DEBUG_INFO: + print('executing: %s' % (' '.join(args),)) + try: + with runner.run_process(args, writer) as dct_with_stdout_stder: + writer.get_stdout = lambda: ''.join(dct_with_stdout_stder['stdout']) + writer.get_stderr = lambda: ''.join(dct_with_stdout_stder['stderr']) + + # Make sure communication is setup. + writer.hello() + yield writer + finally: + writer.log = [] + + stdout = dct_with_stdout_stder['stdout'] + stderr = dct_with_stdout_stder['stderr'] + writer.additional_output_checks(''.join(stdout), ''.join(stderr)) + + return CaseSetup() + + +def test_console_simple(console_setup): + with console_setup.check_console() as writer: + writer.execute_line('a = 10') + writer.execute_line('print("TEST SUCEEDED")') + writer.close() + writer.finished_ok = True + + +def test_console_debugger_connected(console_setup): + + class _DebuggerWriterThread(AbstractWriterThread): + + FORCE_KILL_PROCESS_WHEN_FINISHED_OK = True + + def __init__(self): + AbstractWriterThread.__init__(self) + socket_name = get_socket_name(close=True) + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server_socket.bind(socket_name) + server_socket.listen(1) + self.port = socket_name[1] + self.__server_socket = server_socket + + def run(self): + print('waiting for second process') + self.sock, addr = self.__server_socket.accept() + print('accepted second process') + + from tests_python.debugger_unittest import ReaderThread + self.reader_thread = ReaderThread(self.sock) + self.reader_thread.start() + + self._sequence = -1 + # initial command is always the version + self.write_version() + self.log.append('start_socket') + self.write_make_initial_run() + time.sleep(1) + + seq = self.write_list_threads() + msg = self.wait_for_list_threads(seq) + assert msg.thread['name'] == 'MainThread' + assert msg.thread['id'] == 'console_main' + + self.write_get_frame('console_main', '1') + self.wait_for_vars([ + [ + '') == '' + real_case = pydevd_file_utils.get_path_with_real_case(normalized) + assert isinstance(real_case, str) + # Note test_dir itself cannot be compared with because pytest may + # have passed the case normalized. + assert real_case.endswith("Test_Convert_Utilities") + + if i == 2: + # Check that we have the expected paths in the cache. + assert pydevd_file_utils._listdir_cache[os.path.dirname(normalized).lower()] == ['Test_Convert_Utilities'] + assert pydevd_file_utils._listdir_cache[(os.path.dirname(normalized).lower(), 'Test_Convert_Utilities'.lower())] == real_case + + # Check that it works with a shortened path. + shortened = pydevd_file_utils.convert_to_short_pathname(normalized) + assert '~' in shortened + with_real_case = pydevd_file_utils.get_path_with_real_case(shortened) + assert with_real_case.endswith('Test_Convert_Utilities') + assert '~' not in with_real_case + + else: + # On other platforms, nothing should change + assert pydevd_file_utils.normcase(test_dir) == test_dir + assert pydevd_file_utils.get_path_with_real_case(test_dir) == test_dir + + +def test_source_reference(tmpdir): + import pydevd_file_utils + + pydevd_file_utils.set_ide_os('WINDOWS') + if IS_WINDOWS: + # Client and server are on windows. + pydevd_file_utils.setup_client_server_paths([('c:\\foo', 'c:\\bar')]) + + assert pydevd_file_utils.map_file_to_client('c:\\bar\\my') == ('c:\\foo\\my', True) + assert pydevd_file_utils.get_client_filename_source_reference('c:\\foo\\my') == 0 + + assert pydevd_file_utils.map_file_to_client('c:\\another\\my') == ('c:\\another\\my', False) + source_reference = pydevd_file_utils.get_client_filename_source_reference('c:\\another\\my') + assert source_reference != 0 + assert pydevd_file_utils.get_server_filename_from_source_reference(source_reference) == 'c:\\another\\my' + + else: + # Client on windows and server on unix + pydevd_file_utils.set_ide_os('WINDOWS') + + pydevd_file_utils.setup_client_server_paths([('c:\\foo', '/bar')]) + + assert pydevd_file_utils.map_file_to_client('/bar/my') == ('c:\\foo\\my', True) + assert pydevd_file_utils.get_client_filename_source_reference('c:\\foo\\my') == 0 + + assert pydevd_file_utils.map_file_to_client('/another/my') == ('\\another\\my', False) + source_reference = pydevd_file_utils.get_client_filename_source_reference('\\another\\my') + assert source_reference != 0 + assert pydevd_file_utils.get_server_filename_from_source_reference(source_reference) == '/another/my' + + +@pytest.mark.skipif(sys.platform != 'win32', reason='Windows-only test.') +def test_translate_only_drive(): + import pydevd_file_utils + assert pydevd_file_utils.get_path_with_real_case('c:\\') == 'C:\\' + + +def test_to_server_and_to_client(tmpdir): + try: + + def check(obtained, expected): + assert obtained == expected, '%s (%s) != %s (%s)' % (obtained, type(obtained), expected, type(expected)) + if isinstance(obtained, tuple): + assert isinstance(obtained[0], str) + else: + assert isinstance(obtained, str) + + if isinstance(expected, tuple): + assert isinstance(expected[0], str) + else: + assert isinstance(expected, str) + + import pydevd_file_utils + if IS_WINDOWS: + # Check with made-up files + + pydevd_file_utils.setup_client_server_paths([('c:\\foo', 'c:\\bar'), ('c:\\foo2', 'c:\\bar2')]) + + stream = io.StringIO() + with log_context(0, stream=stream): + pydevd_file_utils.map_file_to_server('y:\\only_exists_in_client_not_in_server') + assert r'pydev debugger: unable to find translation for: "y:\only_exists_in_client_not_in_server" in ["c:\foo\", "c:\foo2\", "c:\foo", "c:\foo2"] (please revise your path mappings).' in stream.getvalue() + + # Client and server are on windows. + pydevd_file_utils.set_ide_os('WINDOWS') + for in_eclipse, in_python in ([ + ('c:\\foo', 'c:\\bar'), + ('c:/foo', 'c:\\bar'), + ('c:\\foo', 'c:/bar'), + ('c:\\foo', 'c:\\bar\\'), + ('c:/foo', 'c:\\bar\\'), + ('c:\\foo', 'c:/bar/'), + ('c:\\foo\\', 'c:\\bar'), + ('c:/foo/', 'c:\\bar'), + ('c:\\foo\\', 'c:/bar'), + + ]): + PATHS_FROM_ECLIPSE_TO_PYTHON = [ + (in_eclipse, in_python) + ] + pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON) + check(pydevd_file_utils.map_file_to_server('c:\\foo\\my'), 'c:\\bar\\my') + check(pydevd_file_utils.map_file_to_server('c:/foo/my'), 'c:\\bar\\my') + check(pydevd_file_utils.map_file_to_server('c:/foo/my/'), 'c:\\bar\\my') + check(pydevd_file_utils.map_file_to_server('c:\\foo\\áéíóú'.upper()), 'c:\\bar' + '\\áéíóú'.upper()) + check(pydevd_file_utils.map_file_to_client('c:\\bar\\my'), ('c:\\foo\\my', True)) + + # Client on unix and server on windows + pydevd_file_utils.set_ide_os('UNIX') + for in_eclipse, in_python in ([ + ('/foo', 'c:\\bar'), + ('/foo', 'c:/bar'), + ('/foo', 'c:\\bar\\'), + ('/foo', 'c:/bar/'), + ('/foo/', 'c:\\bar'), + ('/foo/', 'c:\\bar\\'), + ]): + + PATHS_FROM_ECLIPSE_TO_PYTHON = [ + (in_eclipse, in_python) + ] + pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON) + check(pydevd_file_utils.map_file_to_server('/foo/my'), 'c:\\bar\\my') + check(pydevd_file_utils.map_file_to_client('c:\\bar\\my'), ('/foo/my', True)) + check(pydevd_file_utils.map_file_to_client('c:\\bar\\my\\'), ('/foo/my', True)) + check(pydevd_file_utils.map_file_to_client('c:/bar/my'), ('/foo/my', True)) + check(pydevd_file_utils.map_file_to_client('c:/bar/my/'), ('/foo/my', True)) + + # Test with 'real' files + # Client and server are on windows. + pydevd_file_utils.set_ide_os('WINDOWS') + + test_dir = pydevd_file_utils.get_path_with_real_case(str(tmpdir.mkdir("Foo"))) + os.makedirs(os.path.join(test_dir, "Another")) + + in_eclipse = os.path.join(os.path.dirname(test_dir), 'Bar') + in_python = test_dir + PATHS_FROM_ECLIPSE_TO_PYTHON = [ + (in_eclipse, in_python) + ] + pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON) + + if pydevd_file_utils.map_file_to_server(in_eclipse) != in_python.lower(): + raise AssertionError('%s != %s\ntmpdir:%s\nin_eclipse: %s\nin_python: %s\ntest_dir: %s' % ( + pydevd_file_utils.map_file_to_server(in_eclipse), in_python.lower(), tmpdir, in_eclipse, in_python, test_dir)) + + found_in_eclipse = pydevd_file_utils.map_file_to_client(in_python)[0] + assert found_in_eclipse.endswith('Bar') + + assert pydevd_file_utils.map_file_to_server( + os.path.join(in_eclipse, 'another')) == os.path.join(in_python, 'another').lower() + found_in_eclipse = pydevd_file_utils.map_file_to_client( + os.path.join(in_python, 'another'))[0] + assert found_in_eclipse.endswith('Bar\\Another') + + # Client on unix and server on windows + pydevd_file_utils.set_ide_os('UNIX') + in_eclipse = '/foo' + in_python = test_dir + PATHS_FROM_ECLIPSE_TO_PYTHON = [ + (in_eclipse, in_python) + ] + pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON) + assert pydevd_file_utils.map_file_to_server('/foo').lower() == in_python.lower() + assert pydevd_file_utils.map_file_to_client(in_python) == (in_eclipse, True) + + # Test without translation in place (still needs to fix case and separators) + pydevd_file_utils.set_ide_os('WINDOWS') + PATHS_FROM_ECLIPSE_TO_PYTHON = [] + pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON) + assert pydevd_file_utils.map_file_to_server(test_dir) == test_dir + assert pydevd_file_utils.map_file_to_client(test_dir.lower())[0].endswith('\\Foo') + else: + # Client on windows and server on unix + pydevd_file_utils.set_ide_os('WINDOWS') + + PATHS_FROM_ECLIPSE_TO_PYTHON = [ + ('c:\\BAR', '/bar') + ] + + pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON) + assert pydevd_file_utils.map_file_to_server('c:\\bar\\my') == '/bar/my' + assert pydevd_file_utils.map_file_to_client('/bar/my') == ('c:\\BAR\\my', True) + + for in_eclipse, in_python in ([ + ('c:\\foo', '/báéíóúr'), + ('c:/foo', '/báéíóúr'), + ('c:/foo/', '/báéíóúr'), + ('c:/foo/', '/báéíóúr/'), + ('c:\\foo\\', '/báéíóúr/'), + ]): + + PATHS_FROM_ECLIPSE_TO_PYTHON = [ + (in_eclipse, in_python) + ] + + pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON) + assert pydevd_file_utils.map_file_to_server('c:\\foo\\my') == '/báéíóúr/my' + assert pydevd_file_utils.map_file_to_server('C:\\foo\\my') == '/báéíóúr/my' + assert pydevd_file_utils.map_file_to_server('C:\\foo\\MY') == '/báéíóúr/MY' + assert pydevd_file_utils.map_file_to_server('C:\\foo\\MY\\') == '/báéíóúr/MY' + assert pydevd_file_utils.map_file_to_server('c:\\foo\\my\\file.py') == '/báéíóúr/my/file.py' + assert pydevd_file_utils.map_file_to_server('c:\\foo\\my\\other\\file.py') == '/báéíóúr/my/other/file.py' + assert pydevd_file_utils.map_file_to_server('c:/foo/my') == '/báéíóúr/my' + assert pydevd_file_utils.map_file_to_server('c:\\foo\\my\\') == '/báéíóúr/my' + assert pydevd_file_utils.map_file_to_server('c:/foo/my/') == '/báéíóúr/my' + + assert pydevd_file_utils.map_file_to_client('/báéíóúr/my') == ('c:\\foo\\my', True) + assert pydevd_file_utils.map_file_to_client('/báéíóúr/my/') == ('c:\\foo\\my', True) + + # Files for which there's no translation have only their separators updated. + assert pydevd_file_utils.map_file_to_client('/usr/bin/x.py') == ('\\usr\\bin\\x.py', False) + assert pydevd_file_utils.map_file_to_client('/usr/bin') == ('\\usr\\bin', False) + assert pydevd_file_utils.map_file_to_client('/usr/bin/') == ('\\usr\\bin', False) + assert pydevd_file_utils.map_file_to_server('\\usr\\bin') == '/usr/bin' + assert pydevd_file_utils.map_file_to_server('\\usr\\bin\\') == '/usr/bin' + + # When we have a client file and there'd be no translation, and making it absolute would + # do something as '$cwd/$file_received' (i.e.: $cwd/c:/another in the case below), + # warn the user that it's not correct and the path that should be translated instead + # and don't make it absolute. + assert pydevd_file_utils.map_file_to_server('c:\\Another') == 'c:/Another' + + assert pydevd_file_utils.map_file_to_server('c:/FoO/my/BAR') == '/báéíóúr/my/BAR' + assert pydevd_file_utils.map_file_to_client('/báéíóúr/my/BAR') == ('c:\\foo\\my\\BAR', True) + + # Client and server on unix + pydevd_file_utils.set_ide_os('UNIX') + in_eclipse = '/foo' + in_python = '/báéíóúr' + PATHS_FROM_ECLIPSE_TO_PYTHON = [ + (in_eclipse, in_python) + ] + pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON) + assert pydevd_file_utils.map_file_to_server('/foo/my') == '/báéíóúr/my' + assert pydevd_file_utils.map_file_to_client('/báéíóúr/my') == ('/foo/my', True) + finally: + pydevd_file_utils.setup_client_server_paths([]) + + +def test_relative_paths(tmpdir): + ''' + We need to check that we can deal with relative paths. + + Use cases: + - Relative path of file that does not exist: + Use case is a cython-generated module which is generated from a .pyx which + is not distributed. In this case we need to resolve the file to a library path file. + + - Relative path of a file that exists but not when resolved from the working directory: + Use case is a cython-generated module which is generated from a .pyx which is + distributed. In this case we need to resolve to the real file based on the sys.path + entries. + ''' + import pydevd_file_utils + import sys + sys.path.append(str(tmpdir)) + try: + pydevd_file_utils.NORM_PATHS_AND_BASE_CONTAINER.clear() + pydevd_file_utils.NORM_PATHS_CONTAINER.clear() + abs_path = pydevd_file_utils.get_abs_path_real_path_and_base_from_file('my_dir/my_file.pyx')[0] + assert 'site-packages' in abs_path + assert os.path.normcase(str(tmpdir)) not in abs_path + assert not pydevd_file_utils.exists('my_dir/my_file.pyx') + + # If the relative file exists when joined with some entry in the PYTHONPATH we'll consider + # that the relative path points to that absolute path. + target_dir = os.path.join(str(tmpdir), 'my_dir') + os.makedirs(target_dir) + with open(os.path.join(target_dir, 'my_file.pyx'), 'w') as stream: + stream.write('empty') + + pydevd_file_utils.NORM_PATHS_AND_BASE_CONTAINER.clear() + pydevd_file_utils.NORM_PATHS_CONTAINER.clear() + abs_path = pydevd_file_utils.get_abs_path_real_path_and_base_from_file('my_dir/my_file.pyx')[0] + assert 'site-packages' not in abs_path + assert str(tmpdir) in abs_path + assert pydevd_file_utils.exists('my_dir/my_file.pyx') + finally: + sys.path.remove(str(tmpdir)) + + +def test_zip_paths(tmpdir): + import pydevd_file_utils + import sys + import zipfile + + for i, zip_basename in enumerate(('MY1.zip', 'my2.egg!')): + zipfile_path = str(tmpdir.join(zip_basename)) + zip_file = zipfile.ZipFile(zipfile_path, 'w') + zip_file.writestr('zipped%s/__init__.py' % (i,), '') + zip_file.writestr('zipped%s/zipped_contents.py' % (i,), 'def call_in_zip():\n return 1') + zip_file.close() + + sys.path.append(zipfile_path) + try: + import importlib + except ImportError: + __import__('zipped%s' % (i,)) # Py2.6 does not have importlib + else: + importlib.import_module('zipped%s' % (i,)) # Check that it's importable. + + # Check that we can deal with the zip path. + assert pydevd_file_utils.exists(zipfile_path) + abspath, realpath, basename = pydevd_file_utils.get_abs_path_real_path_and_base_from_file(zipfile_path) + if IS_WINDOWS: + assert abspath == zipfile_path + assert basename == zip_basename.lower() + else: + assert abspath == zipfile_path + assert basename == zip_basename + + # Check that we can deal with zip contents. + for path in [ + zipfile_path + '/zipped%s/__init__.py' % (i,), + zipfile_path + '/zipped%s/zipped_contents.py' % (i,), + zipfile_path + '\\zipped%s\\__init__.py' % (i,), + zipfile_path + '\\zipped%s\\zipped_contents.py' % (i,), + ]: + assert pydevd_file_utils.exists(path), 'Expected exists to return True for path:\n%s' % (path,) + abspath, realpath, basename = pydevd_file_utils.get_abs_path_real_path_and_base_from_file(path) + assert pydevd_file_utils.exists(abspath), 'Expected exists to return True for path:\n%s' % (abspath,) + assert pydevd_file_utils.exists(realpath), 'Expected exists to return True for path:\n%s' % (realpath,) + + assert zipfile_path in pydevd_file_utils._ZIP_SEARCH_CACHE, '%s not in %s' % ( + zipfile_path, '\n'.join(sorted(pydevd_file_utils._ZIP_SEARCH_CACHE.keys()))) + + +def test_source_mapping(): + + from _pydevd_bundle.pydevd_source_mapping import SourceMapping, SourceMappingEntry + from _pydevd_bundle import pydevd_api + + class _DummyPyDB(object): + source_mapping = SourceMapping() + api_received_breakpoints = {} + file_to_id_to_line_breakpoint = {} + file_to_id_to_plugin_breakpoint = {} + breakpoints = {} + + source_mapping = _DummyPyDB.source_mapping + + mapping = [ + SourceMappingEntry(line=3, end_line=6, runtime_line=5, runtime_source=''), + SourceMappingEntry(line=10, end_line=11, runtime_line=1, runtime_source=''), + ] + + api = pydevd_api.PyDevdAPI() + py_db = _DummyPyDB() + filename = 'c:\\temp\\bar.py' if IS_WINDOWS else '/temp/bar.py' + api.set_source_mapping(py_db, filename, mapping) + + # Map to server + assert source_mapping.map_to_server(filename, 1) == (filename, 1, False) + assert source_mapping.map_to_server(filename, 2) == (filename, 2, False) + + assert source_mapping.map_to_server(filename, 3) == ('', 5, True) + assert source_mapping.map_to_server(filename, 4) == ('', 6, True) + assert source_mapping.map_to_server(filename, 5) == ('', 7, True) + assert source_mapping.map_to_server(filename, 6) == ('', 8, True) + + assert source_mapping.map_to_server(filename, 7) == (filename, 7, False) + + assert source_mapping.map_to_server(filename, 10) == ('', 1, True) + assert source_mapping.map_to_server(filename, 11) == ('', 2, True) + + assert source_mapping.map_to_server(filename, 12) == (filename, 12, False) + + # Map to client + assert source_mapping.map_to_client(filename, 1) == (filename, 1, False) + assert source_mapping.map_to_client(filename, 2) == (filename, 2, False) + + assert source_mapping.map_to_client('', 5) == (filename, 3, True) + assert source_mapping.map_to_client('', 6) == (filename, 4, True) + assert source_mapping.map_to_client('', 7) == (filename, 5, True) + assert source_mapping.map_to_client('', 8) == (filename, 6, True) + + assert source_mapping.map_to_client(filename, 7) == (filename, 7, False) + + assert source_mapping.map_to_client('', 1) == (filename, 10, True) + assert source_mapping.map_to_client('', 2) == (filename, 11, True) + + assert source_mapping.map_to_client(filename, 12) == (filename, 12, False) + + +@pytest.mark.skipif(IS_WINDOWS, reason='Linux-only test') +def test_mapping_conflict_to_client(): + import pydevd_file_utils + + path_mappings = [] + for pathMapping in _MAPPING_CONFLICT: + localRoot = pathMapping.get('localRoot', '') + remoteRoot = pathMapping.get('remoteRoot', '') + if (localRoot != '') and (remoteRoot != ''): + path_mappings.append((localRoot, remoteRoot)) + + pydevd_file_utils.setup_client_server_paths(path_mappings) + + assert pydevd_file_utils.map_file_to_client('/opt/pathsomething/foo.py') == \ + ('/var/home/p2/foo.py', True) + + assert pydevd_file_utils.map_file_to_client('/opt/v2/pathsomething/foo.py') == \ + ('/var/home/p4/foo.py', True) + + # This is an odd case, but the user didn't really put a slash in the end, + # so, it's possible that this is what the user actually wants. + assert pydevd_file_utils.map_file_to_client('/opt/v2/path_r1/foo.py') == \ + ('/var/home/p3_r1/foo.py', True) + + # The client said both local and remote end with a slash, so, we can only + # match it with the slash in the end. + assert pydevd_file_utils.map_file_to_client('/opt/pathsomething_foo.py') == \ + ('/opt/pathsomething_foo.py', False) + + +_MAPPING_CONFLICT = [ + { + "localRoot": "/var/home/p1/", + "remoteRoot": "/opt/path/" + }, + { + "localRoot": "/var/home/p2/", + "remoteRoot": "/opt/pathsomething/" + }, + { + "localRoot": "/var/home/p3", + "remoteRoot": "/opt/v2/path" + }, + { + "localRoot": "/var/home/p4", + "remoteRoot": "/opt/v2/pathsomething" + }, +] + + +@pytest.mark.skipif(IS_WINDOWS, reason='Linux-only test') +def test_mapping_conflict_to_server(): + import pydevd_file_utils + + path_mappings = [] + for pathMapping in _MAPPING_CONFLICT_TO_SERVER: + localRoot = pathMapping.get('localRoot', '') + remoteRoot = pathMapping.get('remoteRoot', '') + if (localRoot != '') and (remoteRoot != ''): + path_mappings.append((localRoot, remoteRoot)) + + pydevd_file_utils.setup_client_server_paths(path_mappings) + + assert pydevd_file_utils.map_file_to_server('/opt/pathsomething/foo.py') == '/var/home/p2/foo.py' + + assert pydevd_file_utils.map_file_to_server('/opt/v2/pathsomething/foo.py') == '/var/home/p4/foo.py' + + # This is an odd case, but the user didn't really put a slash in the end, + # so, it's possible that this is what the user actually wants. + assert pydevd_file_utils.map_file_to_server('/opt/v2/path_r1/foo.py') == '/var/home/p3_r1/foo.py' + + # The client said both local and remote end with a slash, so, we can only + # match it with the slash in the end. + assert pydevd_file_utils.map_file_to_server('/opt/pathsomething_foo.py') == '/opt/pathsomething_foo.py' + + +_MAPPING_CONFLICT_TO_SERVER = [ + { + "remoteRoot": "/var/home/p1/", + "localRoot": "/opt/path/" + }, + { + "remoteRoot": "/var/home/p2/", + "localRoot": "/opt/pathsomething/" + }, + { + "remoteRoot": "/var/home/p3", + "localRoot": "/opt/v2/path" + }, + { + "remoteRoot": "/var/home/p4", + "localRoot": "/opt/v2/pathsomething" + }, +] + diff --git a/tests_python/test_debugger.py b/tests_python/test_debugger.py new file mode 100644 index 0000000..9262185 --- /dev/null +++ b/tests_python/test_debugger.py @@ -0,0 +1,4405 @@ +# coding: utf-8 +''' + The idea is that we record the commands sent to the debugger and reproduce them from this script + (so, this works as the client, which spawns the debugger as a separate process and communicates + to it as if it was run from the outside) + + Note that it's a python script but it'll spawn a process to run as jython, ironpython and as python. +''' +import time + +import pytest + +from tests_python import debugger_unittest +from tests_python.debugger_unittest import (CMD_SET_PROPERTY_TRACE, REASON_CAUGHT_EXCEPTION, + REASON_UNCAUGHT_EXCEPTION, REASON_STOP_ON_BREAKPOINT, REASON_THREAD_SUSPEND, overrides, CMD_THREAD_CREATE, + CMD_GET_THREAD_STACK, REASON_STEP_INTO_MY_CODE, CMD_GET_EXCEPTION_DETAILS, IS_IRONPYTHON, IS_JYTHON, IS_CPYTHON, + IS_APPVEYOR, wait_for_condition, CMD_GET_FRAME, CMD_GET_BREAKPOINT_EXCEPTION, + CMD_THREAD_SUSPEND, CMD_STEP_OVER, REASON_STEP_OVER, CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, + CMD_THREAD_RESUME_SINGLE_NOTIFICATION, REASON_STEP_RETURN, REASON_STEP_RETURN_MY_CODE, + REASON_STEP_OVER_MY_CODE, REASON_STEP_INTO, CMD_THREAD_KILL, IS_PYPY, REASON_STOP_ON_START, + CMD_SMART_STEP_INTO) +from _pydevd_bundle.pydevd_constants import IS_WINDOWS, IS_PY38_OR_GREATER, \ + IS_MAC +from _pydevd_bundle.pydevd_comm_constants import CMD_RELOAD_CODE, CMD_INPUT_REQUESTED +import json +import pydevd_file_utils +import subprocess +import threading +from _pydev_bundle import pydev_log +from urllib.parse import unquote + +from tests_python.debug_constants import * # noqa + +pytest_plugins = [ + str('tests_python.debugger_fixtures'), +] + +builtin_qualifier = "builtins" + + +@pytest.mark.skipif(not IS_CPYTHON, reason='Test needs gc.get_referrers/reference counting to really check anything.') +def test_case_referrers(case_setup): + with case_setup.test_file('_debugger_case1.py') as writer: + writer.log.append('writing add breakpoint') + writer.write_add_breakpoint(6, 'set_up') + + writer.log.append('making initial run') + writer.write_make_initial_run() + + writer.log.append('waiting for breakpoint hit') + hit = writer.wait_for_breakpoint_hit() + thread_id = hit.thread_id + frame_id = hit.frame_id + + writer.log.append('get frame') + writer.write_get_frame(thread_id, frame_id) + + writer.log.append('step over') + writer.write_step_over(thread_id) + + writer.log.append('get frame') + writer.write_get_frame(thread_id, frame_id) + + writer.log.append('run thread') + writer.write_run_thread(thread_id) + + writer.log.append('asserting') + try: + assert 13 == writer._sequence, 'Expected 13. Had: %s' % writer._sequence + except: + writer.log.append('assert failed!') + raise + writer.log.append('asserted') + + writer.finished_ok = True + + +def test_case_2(case_setup): + with case_setup.test_file('_debugger_case2.py') as writer: + writer.write_add_breakpoint(3, 'Call4') # seq = 3 + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + thread_id = hit.thread_id + frame_id = hit.frame_id + + writer.write_get_frame(thread_id, frame_id) # Note: write get frame but not waiting for it to be gotten. + + writer.write_add_breakpoint(14, 'Call2') + + writer.write_run_thread(thread_id) + + hit = writer.wait_for_breakpoint_hit() + thread_id = hit.thread_id + frame_id = hit.frame_id + + writer.write_get_frame(thread_id, frame_id) # Note: write get frame but not waiting for it to be gotten. + + writer.write_run_thread(thread_id) + + writer.log.append('Checking sequence. Found: %s' % (writer._sequence)) + assert 15 == writer._sequence, 'Expected 15. Had: %s' % writer._sequence + + writer.log.append('Marking finished ok.') + writer.finished_ok = True + + +@pytest.mark.parametrize( + 'skip_suspend_on_breakpoint_exception, skip_print_breakpoint_exception', + ( + [['NameError'], []], + [['NameError'], ['NameError']], + [[], []], # Empty means it'll suspend/print in any exception + [[], ['NameError']], + [['ValueError'], ['Exception']], + [['Exception'], ['ValueError']], # ValueError will also suspend/print since we're dealing with a NameError + ) +) +def test_case_breakpoint_condition_exc(case_setup, skip_suspend_on_breakpoint_exception, skip_print_breakpoint_exception): + + msgs_in_stderr = ( + 'Error while evaluating expression in conditional breakpoint: i > 5', + 'Traceback (most recent call last):', + 'File "", line 1, in ', + ) + + # It could be one or the other in PyPy depending on the version. + msgs_one_in_stderr = ( + "NameError: name 'i' is not defined", + "global name 'i' is not defined", + ) + + def _ignore_stderr_line(line): + if original_ignore_stderr_line(line): + return True + + for msg in msgs_in_stderr + msgs_one_in_stderr: + if msg in line: + return True + + return False + + with case_setup.test_file('_debugger_case_breakpoint_condition_exc.py') as writer: + + original_ignore_stderr_line = writer._ignore_stderr_line + writer._ignore_stderr_line = _ignore_stderr_line + + writer.write_suspend_on_breakpoint_exception(skip_suspend_on_breakpoint_exception, skip_print_breakpoint_exception) + + expect_print = skip_print_breakpoint_exception in ([], ['ValueError']) + expect_suspend = skip_suspend_on_breakpoint_exception in ([], ['ValueError']) + + breakpoint_id = writer.write_add_breakpoint( + writer.get_line_index_with_content('break here'), 'Call', condition='i > 5') + + if not expect_print: + _original = writer.reader_thread.on_message_found + + def on_message_found(found_msg): + for msg in msgs_in_stderr + msgs_one_in_stderr: + assert msg not in found_msg + + writer.reader_thread.on_message_found = on_message_found + + writer.write_make_initial_run() + + def check_error_msg(stderr): + for msg in msgs_in_stderr: + assert msg in stderr + + for msg in msgs_one_in_stderr: + if msg in stderr: + break + else: + raise AssertionError('Did not find any of: %s in stderr: %s' % ( + msgs_one_in_stderr, stderr)) + + if expect_print: + msg, ctx = writer.wait_for_output() + check_error_msg(msg.replace('>', '>')) + + if expect_suspend: + writer.wait_for_message(CMD_GET_BREAKPOINT_EXCEPTION) + hit = writer.wait_for_breakpoint_hit() + writer.write_run_thread(hit.thread_id) + + if IS_JYTHON: + # Jython will break twice. + if expect_suspend: + writer.wait_for_message(CMD_GET_BREAKPOINT_EXCEPTION) + hit = writer.wait_for_breakpoint_hit() + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit() + thread_id = hit.thread_id + frame_id = hit.frame_id + + writer.write_get_frame(thread_id, frame_id) + msg = writer.wait_for_message(CMD_GET_FRAME) + name_to_value = {} + for var in msg.var: + name_to_value[var['name']] = var['value'] + assert name_to_value == {'i': 'int: 6', 'last_i': 'int: 6'} + + writer.write_remove_breakpoint(breakpoint_id) + + writer.write_run_thread(thread_id) + + writer.finished_ok = True + + +def test_case_remove_breakpoint(case_setup): + with case_setup.test_file('_debugger_case_remove_breakpoint.py') as writer: + breakpoint_id = writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + writer.write_remove_breakpoint(breakpoint_id) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_case_double_remove_breakpoint(case_setup): + + with case_setup.test_file('_debugger_case_remove_breakpoint.py') as writer: + breakpoint_id = writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + writer.write_remove_breakpoint(breakpoint_id) + writer.write_remove_breakpoint(breakpoint_id) # Double-remove (just check that we don't have an error). + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_IRONPYTHON, reason='This test fails once in a while due to timing issues on IronPython, so, skipping it.') +def test_case_3(case_setup): + with case_setup.test_file('_debugger_case3.py') as writer: + writer.write_make_initial_run() + time.sleep(.5) + breakpoint_id = writer.write_add_breakpoint(4, '') + + hit = writer.wait_for_breakpoint_hit() + thread_id = hit.thread_id + frame_id = hit.frame_id + + writer.write_get_frame(thread_id, frame_id) + + writer.write_run_thread(thread_id) + + hit = writer.wait_for_breakpoint_hit() + thread_id = hit.thread_id + frame_id = hit.frame_id + + writer.write_get_frame(thread_id, frame_id) + + writer.write_remove_breakpoint(breakpoint_id) + + writer.write_run_thread(thread_id) + + writer.finished_ok = True + + +def test_case_suspend_thread(case_setup): + with case_setup.test_file('_debugger_case4.py') as writer: + writer.write_make_initial_run() + + thread_id = writer.wait_for_new_thread() + + writer.write_suspend_thread(thread_id) + + while True: + hit = writer.wait_for_breakpoint_hit((REASON_THREAD_SUSPEND, REASON_STOP_ON_BREAKPOINT)) + if hit.name == 'sleep': + break # Ok, broke on 'sleep'. + else: + # i.e.: if it doesn't hit on 'sleep', release and pause again. + writer.write_run_thread(thread_id) + time.sleep(.1) + writer.write_suspend_thread(thread_id) + + assert hit.thread_id == thread_id + + writer.write_evaluate_expression('%s\t%s\t%s' % (hit.thread_id, hit.frame_id, 'LOCAL'), 'exit_while_loop()') + writer.wait_for_evaluation([ + [ + '%0A
'.format(builtin_qualifier), + '%0A%0A
'.format(builtin_qualifier), + '%0A%0A', # jython + ] + ]) + + writer.write_run_thread(hit.thread_id) + + assert 17 == writer._sequence, 'Expected 17. Had: %s' % writer._sequence + + writer.finished_ok = True + + +def test_case_8(case_setup): + with case_setup.test_file('_debugger_case89.py') as writer: + writer.write_add_breakpoint(10, 'Method3') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit('111') + + writer.write_step_return(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit('109', line=15) + + writer.write_run_thread(hit.thread_id) + + assert 9 == writer._sequence, 'Expected 9. Had: %s' % writer._sequence + + writer.finished_ok = True + + +def test_case_9(case_setup): + with case_setup.test_file('_debugger_case89.py') as writer: + writer.write_add_breakpoint(10, 'Method3') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit('111') + + # Note: no active exception (should not give an error and should return no + # exception details as there's no exception). + writer.write_get_current_exception(hit.thread_id) + + msg = writer.wait_for_message(CMD_GET_EXCEPTION_DETAILS) + assert msg.thread['id'] == hit.thread_id + assert not hasattr(msg.thread, 'frames') # No frames should be found. + + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit('108', line=11) + + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit('108', line=12) + + writer.write_run_thread(hit.thread_id) + + assert 13 == writer._sequence, 'Expected 13. Had: %s' % writer._sequence + + writer.finished_ok = True + + +def test_case_10(case_setup): + with case_setup.test_file('_debugger_case_simple_calls.py') as writer: + writer.write_add_breakpoint(2, 'None') # None or Method should make hit. + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit('111') + + writer.write_step_return(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit('109', line=11) + + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit('108', line=12) + + writer.write_run_thread(hit.thread_id) + + assert 11 == writer._sequence, 'Expected 11. Had: %s' % writer._sequence + + writer.finished_ok = True + + +def test_case_11(case_setup): + with case_setup.test_file('_debugger_case_simple_calls.py') as writer: + writer.write_add_breakpoint(2, 'Method1') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT, line=2) + assert hit.name == 'Method1' + + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, line=3) + assert hit.name == 'Method1' + + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, line=12) # Reverts to step in + assert hit.name == 'Method2' + + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, line=13) + assert hit.name == 'Method2' + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, line=18) # Reverts to step in + assert hit.name == '' + + # Finish with a step over + writer.write_step_over(hit.thread_id) + + if IS_JYTHON: + writer.write_run_thread(hit.thread_id) + else: + # Finish with a step over + writer.write_step_over(hit.thread_id) + + writer.finished_ok = True + + +def test_case_12(case_setup): + # Note: In CPython we now ignore the function names, so, we'll stop at the breakpoint in line 2 + # regardless of the function name (we decide whether to stop in a line or not through the function + # lines). + with case_setup.test_file('_debugger_case_simple_calls.py') as writer: + writer.write_add_breakpoint(2, '') # Should not be hit: setting empty function (not None) should only hit global. + writer.write_add_breakpoint(6, 'Method1a') + writer.write_add_breakpoint(11, 'Method2') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit('111', line=11) + + writer.write_step_return(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit('111', line=6 if IS_JYTHON else 2) # not a return (it stopped in the other breakpoint) + + writer.write_run_thread(hit.thread_id) + + if not IS_JYTHON: + hit = writer.wait_for_breakpoint_hit('111', line=6) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_IRONPYTHON, reason='Failing on IronPython (needs to be investigated).') +def test_case_13(case_setup): + with case_setup.test_file('_debugger_case13.py') as writer: + + def _ignore_stderr_line(line): + if original_ignore_stderr_line(line): + return True + + if IS_JYTHON: + for expected in ( + "RuntimeWarning: Parent module '_pydevd_bundle' not found while handling absolute import", + "import __builtin__"): + if expected in line: + return True + + return False + + original_ignore_stderr_line = writer._ignore_stderr_line + writer._ignore_stderr_line = _ignore_stderr_line + + writer.write_add_breakpoint(35, 'main') + writer.write("%s\t%s\t%s" % (CMD_SET_PROPERTY_TRACE, writer.next_seq(), "true;false;false;true")) + writer.write_make_initial_run() + hit = writer.wait_for_breakpoint_hit('111') + + writer.write_get_frame(hit.thread_id, hit.frame_id) + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit('107', line=25) + # Should go inside setter method + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit('107', line=36) + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit('107', line=21) + # Should go inside getter method + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit('107') + + # Disable property tracing + writer.write("%s\t%s\t%s" % (CMD_SET_PROPERTY_TRACE, writer.next_seq(), "true;true;true;true")) + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit('107', line=39) + # Should Skip step into properties setter + + # Enable property tracing + writer.write("%s\t%s\t%s" % (CMD_SET_PROPERTY_TRACE, writer.next_seq(), "true;false;false;true")) + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit('107', line=8) + # Should go inside getter method + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_case_14(case_setup): + # Interactive Debug Console + with case_setup.test_file('_debugger_case14.py') as writer: + writer.write_add_breakpoint(22, 'main') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit('111') + assert hit.thread_id, '%s not valid.' % hit.thread_id + assert hit.frame_id, '%s not valid.' % hit.frame_id + + # Access some variable + writer.write_debug_console_expression("%s\t%s\tEVALUATE\tcarObj.color" % (hit.thread_id, hit.frame_id)) + writer.wait_for_var(['False', '%27Black%27']) + assert 7 == writer._sequence, 'Expected 9. Had: %s' % writer._sequence + + # Change some variable + writer.write_debug_console_expression("%s\t%s\tEVALUATE\tcarObj.color='Red'" % (hit.thread_id, hit.frame_id)) + writer.write_debug_console_expression("%s\t%s\tEVALUATE\tcarObj.color" % (hit.thread_id, hit.frame_id)) + writer.wait_for_var(['False', '%27Red%27']) + assert 11 == writer._sequence, 'Expected 13. Had: %s' % writer._sequence + + # Iterate some loop + writer.write_debug_console_expression("%s\t%s\tEVALUATE\tfor i in range(3):" % (hit.thread_id, hit.frame_id)) + writer.wait_for_var(['True']) + writer.write_debug_console_expression("%s\t%s\tEVALUATE\t print(i)" % (hit.thread_id, hit.frame_id)) + writer.wait_for_var(['True']) + writer.write_debug_console_expression("%s\t%s\tEVALUATE\t" % (hit.thread_id, hit.frame_id)) + writer.wait_for_var( + [ + 'False' ] + ) + assert 17 == writer._sequence, 'Expected 19. Had: %s' % writer._sequence + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +def test_case_15(case_setup): + with case_setup.test_file('_debugger_case15.py') as writer: + writer.write_add_breakpoint(22, 'main') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT) + + # Access some variable + writer.write_custom_operation("%s\t%s\tEXPRESSION\tcarObj.color" % (hit.thread_id, hit.frame_id), "EXEC", "f=lambda x: 'val=%s' % x", "f") + writer.wait_for_custom_operation('val=Black') + assert 7 == writer._sequence, 'Expected 7. Had: %s' % writer._sequence + + writer.write_custom_operation("%s\t%s\tEXPRESSION\tcarObj.color" % (hit.thread_id, hit.frame_id), "EXECFILE", debugger_unittest._get_debugger_test_file('_debugger_case15_execfile.py'), "f") + writer.wait_for_custom_operation('val=Black') + assert 9 == writer._sequence, 'Expected 9. Had: %s' % writer._sequence + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +def test_case_16_resolve_numpy_array(case_setup): + # numpy.ndarray resolver + try: + import numpy + except ImportError: + pytest.skip('numpy not available') + with case_setup.test_file('_debugger_case16.py') as writer: + writer.write_add_breakpoint(9, 'main') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT) + + # In this test we check that the three arrays of different shapes, sizes and types + # are all resolved properly as ndarrays. + + # First pass check is that we have all three expected variables defined + writer.write_get_frame(hit.thread_id, hit.frame_id) + writer.wait_for_multiple_vars(( + ( + '', + '' + ), + + ( + '', + '' + ), + + # Any of the ones below will do. + ( + '', + '' + ) + )) + + # For each variable, check each of the resolved (meta data) attributes... + writer.write_get_variable(hit.thread_id, hit.frame_id, 'smallarray') + writer.wait_for_multiple_vars(( + ''.format(builtin_qualifier), + ''.format(builtin_qualifier), + ''.format(builtin_qualifier), + ''.format(builtin_qualifier), + ], + [ + ''.format(builtin_qualifier), + ''.format(builtin_qualifier), + ''.format(builtin_qualifier), + ''.format(builtin_qualifier), + ], + '%0A'.format(builtin_qualifier,)) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_case_19(case_setup): + # Check evaluate '__' attributes + with case_setup.test_file('_debugger_case19.py') as writer: + writer.write_add_breakpoint(8, None) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT, line=8) + + writer.write_evaluate_expression('%s\t%s\t%s' % (hit.thread_id, hit.frame_id, 'LOCAL'), 'a.__var') + writer.wait_for_evaluation([ + [ + 'Hello' in contents + assert 'Flask-Jinja-Test' in contents + + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_DJANGO, reason='No django available') +def test_case_django_a(case_setup_django): + + def get_environ(writer): + env = os.environ.copy() + env.update({ + 'PYDEVD_FILTER_LIBRARIES': '1', # Global setting for in project or not + }) + return env + + with case_setup_django.test_file(EXPECTED_RETURNCODE='any', get_environ=get_environ) as writer: + writer.write_add_breakpoint_django(5, None, 'index.html') + writer.write_make_initial_run() + + t = writer.create_request_thread('my_app') + time.sleep(5) # Give django some time to get to startup before requesting the page + t.start() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT, line=5) + writer.write_get_variable(hit.thread_id, hit.frame_id, 'entry') + writer.wait_for_vars([ + '
  • v1:v1
  • v2:v2
  • ' % (contents,)) + + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_DJANGO, reason='No django available') +def test_case_django_b(case_setup_django): + with case_setup_django.test_file(EXPECTED_RETURNCODE='any') as writer: + writer.write_add_breakpoint_django(4, None, 'name.html') + writer.write_add_exception_breakpoint_django() + writer.write_remove_exception_breakpoint_django() + writer.write_make_initial_run() + + t = writer.create_request_thread('my_app/name') + time.sleep(5) # Give django some time to get to startup before requesting the page + t.start() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT, line=4) + + writer.write_get_frame(hit.thread_id, hit.frame_id) + writer.wait_for_var('', 'f', ''] + else: + expected_frame_names = ['', 'f', ''] + + writer.write_get_current_exception(hit.thread_id) + msg = writer.wait_for_message(accept_message=lambda msg:'exc_type="' in msg and 'exc_desc="' in msg, unquote_msg=False) + + frame_names = [unquote(f['name']).replace('<', '<').replace('>', '>') for f in msg.thread.frame] + assert frame_names == expected_frame_names + + writer.write_run_thread(hit.thread_id) + + if not unhandled: + expected_lines = [ + writer.get_line_index_with_content('# exc line'), + writer.get_line_index_with_content('# call exc'), + ] + + for expected_line in expected_lines: + hit = writer.wait_for_breakpoint_hit(REASON_CAUGHT_EXCEPTION) + assert hit.line == expected_line + + writer.write_get_current_exception(hit.thread_id) + msg = writer.wait_for_message(accept_message=lambda msg:'exc_type="' in msg and 'exc_desc="' in msg, unquote_msg=False) + + frame_names = [unquote(f['name']).replace('<', '<').replace('>', '>') for f in msg.thread.frame] + assert frame_names == expected_frame_names + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).') +def test_unhandled_exceptions_basic(case_setup): + + def check_test_suceeded_msg(writer, stdout, stderr): + # Don't call super (we have an unhandled exception in the stack trace). + return 'TEST SUCEEDED' in ''.join(stdout) and 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + if 'raise Exception' not in stderr: + raise AssertionError('Expected test to have an unhandled exception.\nstdout:\n%s\n\nstderr:\n%s' % ( + stdout, stderr)) + + with case_setup.test_file( + '_debugger_case_unhandled_exceptions.py', + check_test_suceeded_msg=check_test_suceeded_msg, + additional_output_checks=additional_output_checks, + EXPECTED_RETURNCODE=1, + ) as writer: + + writer.write_add_exception_breakpoint_with_policy('Exception', "0", "1", "0") + writer.write_make_initial_run() + + def check(hit, exc_type, exc_desc): + writer.write_get_current_exception(hit.thread_id) + msg = writer.wait_for_message(accept_message=lambda msg:exc_type in msg and 'exc_type="' in msg and 'exc_desc="' in msg, unquote_msg=False) + assert unquote(msg.thread['exc_desc']) == exc_desc + assert unquote(msg.thread['exc_type']) in ( + "<type 'exceptions.%s'>" % (exc_type,), # py2 + "<class '%s'>" % (exc_type,) # py3 + ) + if len(msg.thread.frame) == 0: + assert unquote(unquote(msg.thread.frame['file'])).endswith('_debugger_case_unhandled_exceptions.py') + else: + assert unquote(unquote(msg.thread.frame[0]['file'])).endswith('_debugger_case_unhandled_exceptions.py') + writer.write_run_thread(hit.thread_id) + + # Will stop in 2 background threads + hit0 = writer.wait_for_breakpoint_hit(REASON_UNCAUGHT_EXCEPTION) + thread_id1 = hit0.thread_id + + hit1 = writer.wait_for_breakpoint_hit(REASON_UNCAUGHT_EXCEPTION) + thread_id2 = hit1.thread_id + + if hit0.name == 'thread_func2': + check(hit0, 'ValueError', 'in thread 2') + check(hit1, 'Exception', 'in thread 1') + else: + check(hit0, 'Exception', 'in thread 1') + check(hit1, 'ValueError', 'in thread 2') + + writer.write_run_thread(thread_id1) + writer.write_run_thread(thread_id2) + + # Will stop in main thread + hit = writer.wait_for_breakpoint_hit(REASON_UNCAUGHT_EXCEPTION) + assert hit.name == '' + thread_id3 = hit.thread_id + + # Requesting the stack in an unhandled exception should provide the stack of the exception, + # not the current location of the program. + writer.write_get_thread_stack(thread_id3) + msg = writer.wait_for_message(CMD_GET_THREAD_STACK) + assert len(msg.thread.frame) == 0 # In main thread (must have no back frames). + assert msg.thread.frame['name'] == '' + check(hit, 'IndexError', 'in main') + + writer.log.append('Marking finished ok.') + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).') +def test_unhandled_exceptions_in_top_level1(case_setup_unhandled_exceptions): + + with case_setup_unhandled_exceptions.test_file( + '_debugger_case_unhandled_exceptions_on_top_level.py', + EXPECTED_RETURNCODE=1, + ) as writer: + + writer.write_add_exception_breakpoint_with_policy('Exception', "0", "1", "0") + writer.write_make_initial_run() + + # Will stop in main thread + hit = writer.wait_for_breakpoint_hit(REASON_UNCAUGHT_EXCEPTION) + writer.write_run_thread(hit.thread_id) + + writer.log.append('Marking finished ok.') + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).') +def test_unhandled_exceptions_in_top_level2(case_setup_unhandled_exceptions): + # Note: expecting unhandled exception to be printed to stderr. + + def get_environ(writer): + env = os.environ.copy() + curr_pythonpath = env.get('PYTHONPATH', '') + + pydevd_dirname = os.path.dirname(writer.get_pydevd_file()) + + curr_pythonpath = pydevd_dirname + os.pathsep + curr_pythonpath + env['PYTHONPATH'] = curr_pythonpath + return env + + def update_command_line_args(writer, args): + # Start pydevd with '-m' to see how it deal with being called with + # runpy at the start. + assert args[0].endswith('pydevd.py') + args = ['-m', 'pydevd'] + args[1:] + return args + + with case_setup_unhandled_exceptions.test_file( + '_debugger_case_unhandled_exceptions_on_top_level.py', + get_environ=get_environ, + update_command_line_args=update_command_line_args, + EXPECTED_RETURNCODE='any', + ) as writer: + + writer.write_add_exception_breakpoint_with_policy('Exception', "0", "1", "0") + writer.write_make_initial_run() + + # Should stop (only once) in the main thread. + hit = writer.wait_for_breakpoint_hit(REASON_UNCAUGHT_EXCEPTION) + writer.write_run_thread(hit.thread_id) + + writer.log.append('Marking finished ok.') + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).') +def test_unhandled_exceptions_in_top_level3(case_setup_unhandled_exceptions): + + with case_setup_unhandled_exceptions.test_file( + '_debugger_case_unhandled_exceptions_on_top_level.py', + EXPECTED_RETURNCODE=1 + ) as writer: + + # Handled and unhandled + # PySide2 has a bug in shibokensupport which will try to do: sys._getframe(1). + # during the teardown (which will fail as there's no back frame in this case). + # So, mark ignore libraries in this case. + writer.write_add_exception_breakpoint_with_policy('Exception', "1", "1", ignore_libraries="1") + writer.write_make_initial_run() + + # Will stop in main thread twice: once one we find that the exception is being + # thrown and another in postmortem mode when we discover it's uncaught. + hit = writer.wait_for_breakpoint_hit(REASON_CAUGHT_EXCEPTION) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(REASON_UNCAUGHT_EXCEPTION) + writer.write_run_thread(hit.thread_id) + + writer.log.append('Marking finished ok.') + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).') +def test_unhandled_exceptions_in_top_level4(case_setup_unhandled_exceptions): + + # Note: expecting unhandled exception to be printed to stderr. + with case_setup_unhandled_exceptions.test_file( + '_debugger_case_unhandled_exceptions_on_top_level2.py', + EXPECTED_RETURNCODE=1, + ) as writer: + + # Handled and unhandled + writer.write_add_exception_breakpoint_with_policy('Exception', "1", "1", "0") + writer.write_make_initial_run() + + # We have an exception thrown and handled and another which is thrown and is then unhandled. + hit = writer.wait_for_breakpoint_hit(REASON_CAUGHT_EXCEPTION) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(REASON_CAUGHT_EXCEPTION) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(REASON_UNCAUGHT_EXCEPTION) + writer.write_run_thread(hit.thread_id) + + writer.log.append('Marking finished ok.') + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='Only for Python.') +def test_case_set_next_statement(case_setup): + + with case_setup.test_file('_debugger_case_set_next_statement.py') as writer: + breakpoint_id = writer.write_add_breakpoint(6, None) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT, line=6) # Stop in line a=3 (before setting it) + + writer.write_evaluate_expression('%s\t%s\t%s' % (hit.thread_id, hit.frame_id, 'LOCAL'), 'a') + writer.wait_for_evaluation('' + assert msg.thread.frame['line'] == str(writer.get_line_index_with_content('break line on unhandled exception')) + + writer.write_run_thread(hit.thread_id) + + writer.log.append('Marking finished ok.') + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Requires Python 3.') +def test_case_throw_exc_reason_xml(case_setup): + + def check_test_suceeded_msg(self, stdout, stderr): + return 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + assert "raise RuntimeError('TEST SUCEEDED')" in stderr + assert "raise RuntimeError from e" in stderr + assert "raise Exception('another while handling')" in stderr + + with case_setup.test_file( + '_debugger_case_raise_with_cause.py', + EXPECTED_RETURNCODE=1, + check_test_suceeded_msg=check_test_suceeded_msg, + additional_output_checks=additional_output_checks + ) as writer: + + writer.write_add_exception_breakpoint_with_policy('Exception', "0", "1", "0") + writer.write_make_initial_run() + + el = writer.wait_for_curr_exc_stack() + name_and_lines = [] + for frame in el.thread.frame: + name_and_lines.append((frame['name'], frame['line'])) + + assert name_and_lines == [ + ('method2', '2'), + ('method', '6'), + ('foobar', '16'), + ('handle', '10'), + ('foobar', '18'), + ('foobar', '20'), + ('', '23'), + ] + + hit = writer.wait_for_breakpoint_hit(REASON_UNCAUGHT_EXCEPTION) + writer.write_get_thread_stack(hit.thread_id) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='Only for Python.') +def test_case_get_next_statement_targets(case_setup): + with case_setup.test_file('_debugger_case_get_next_statement_targets.py') as writer: + breakpoint_id = writer.write_add_breakpoint(21, None) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT, line=21) + + writer.write_get_next_statement_targets(hit.thread_id, hit.frame_id) + targets = writer.wait_for_get_next_statement_targets() + # Note: 20 may appear as a side-effect of the frame eval + # mode (so, we have to ignore it here) -- this isn't ideal, but + # it's also not that bad (that line has no code in the source and + # executing it will just set the tracing for the method). + targets.discard(20) + # On Python 3.11 there's now a line 1 (which should be harmless). + targets.discard(1) + expected = set((2, 3, 5, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, 21)) + assert targets == expected, 'Expected targets to be %s, was: %s' % (expected, targets) + + writer.write_remove_breakpoint(breakpoint_id) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_IRONPYTHON or IS_JYTHON, reason='Failing on IronPython and Jython (needs to be investigated).') +def test_case_type_ext(case_setup): + # Custom type presentation extensions + + def get_environ(self): + env = os.environ.copy() + + python_path = env.get("PYTHONPATH", "") + ext_base = debugger_unittest._get_debugger_test_file('my_extensions') + env['PYTHONPATH'] = ext_base + os.pathsep + python_path if python_path else ext_base + return env + + with case_setup.test_file('_debugger_case_type_ext.py', get_environ=get_environ) as writer: + writer.get_environ = get_environ + + writer.write_add_breakpoint(7, None) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit('111') + writer.write_get_frame(hit.thread_id, hit.frame_id) + assert writer.wait_for_var([ + [ + r'', + r''.format(builtin_qualifier)) + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +@pytest.mark.skipif(IS_IRONPYTHON or IS_JYTHON, reason='Failing on IronPython and Jython (needs to be investigated).') +def test_case_event_ext(case_setup): + + def get_environ(self): + env = os.environ.copy() + + python_path = env.get("PYTHONPATH", "") + ext_base = debugger_unittest._get_debugger_test_file('my_extensions') + env['PYTHONPATH'] = ext_base + os.pathsep + python_path if python_path else ext_base + env["VERIFY_EVENT_TEST"] = "1" + return env + + # Test initialize event for extensions + with case_setup.test_file('_debugger_case_event_ext.py', get_environ=get_environ) as writer: + + original_additional_output_checks = writer.additional_output_checks + + @overrides(writer.additional_output_checks) + def additional_output_checks(stdout, stderr): + original_additional_output_checks(stdout, stderr) + if 'INITIALIZE EVENT RECEIVED' not in stdout: + raise AssertionError('No initialize event received') + + writer.additional_output_checks = additional_output_checks + + writer.write_make_initial_run() + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Jython does not seem to be creating thread started inside tracing (investigate).') +def test_case_writer_creation_deadlock(case_setup): + # check case where there was a deadlock evaluating expressions + with case_setup.test_file('_debugger_case_thread_creation_deadlock.py') as writer: + writer.write_add_breakpoint(26, None) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit('111') + + assert hit.line == 26, 'Expected return to be in line 26, was: %s' % (hit.line,) + + writer.write_evaluate_expression('%s\t%s\t%s' % (hit.thread_id, hit.frame_id, 'LOCAL'), 'create_thread()') + writer.wait_for_evaluation('= 3: + binary_junk = binary_junk.decode('utf-8', 'replace') + + return line.startswith(( + 'text', + 'binary', + 'a', + binary_junk, + )) + + writer._ignore_stderr_line = _ignore_stderr_line + + # Note: writes to stdout and stderr are now synchronous (so, the order + # must always be consistent and there's a message for each write). + expected = [ + 'text\n', + 'binary or text\n', + 'ação1\n', + ] + + if sys.version_info[0] >= 3: + expected.extend(( + 'binary\n', + 'ação2\n'.encode(encoding='latin1').decode('utf-8', 'replace'), + 'ação3\n', + )) + + binary_junk = '\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\n\n' + if sys.version_info[0] >= 3: + binary_junk = "\ufffd\ufffd\ufffd\ufffd\ufffd\n\n" + expected.append(binary_junk) + + new_expected = [(x, 'stdout') for x in expected] + new_expected.extend([(x, 'stderr') for x in expected]) + + writer.write_start_redirect() + + writer.write_make_initial_run() + msgs = [] + ignored = [] + while len(msgs) < len(new_expected): + try: + msg = writer.wait_for_output() + except AssertionError: + for msg in msgs: + sys.stderr.write('Found: %s\n' % (msg,)) + for msg in new_expected: + sys.stderr.write('Expected: %s\n' % (msg,)) + for msg in ignored: + sys.stderr.write('Ignored: %s\n' % (msg,)) + raise + if msg not in new_expected: + ignored.append(msg) + continue + msgs.append(msg) + + if msgs != new_expected: + print(msgs) + print(new_expected) + assert msgs == new_expected + writer.finished_ok = True + + +def _path_equals(path1, path2): + path1 = pydevd_file_utils.normcase(path1) + path2 = pydevd_file_utils.normcase(path2) + return path1 == path2 + + +@pytest.mark.parametrize('mixed_case', [True, False] if sys.platform == 'win32' else [False]) +def test_path_translation(case_setup, mixed_case): + + def get_file_in_client(writer): + # Instead of using: test_python/_debugger_case_path_translation.py + # we'll set the breakpoints at foo/_debugger_case_path_translation.py + file_in_client = os.path.dirname(os.path.dirname(writer.TEST_FILE)) + return os.path.join(os.path.dirname(file_in_client), 'foo', '_debugger_case_path_translation.py') + + def get_environ(writer): + import json + env = os.environ.copy() + + env["PYTHONIOENCODING"] = 'utf-8' + + assert writer.TEST_FILE.endswith('_debugger_case_path_translation.py') + file_in_client = get_file_in_client(writer) + if mixed_case: + new_file_in_client = ''.join([file_in_client[i].upper() if i % 2 == 0 else file_in_client[i].lower() for i in range(len(file_in_client))]) + assert _path_equals(file_in_client, new_file_in_client) + env["PATHS_FROM_ECLIPSE_TO_PYTHON"] = json.dumps([ + ( + os.path.dirname(file_in_client), + os.path.dirname(writer.TEST_FILE) + ) + ]) + return env + + with case_setup.test_file('_debugger_case_path_translation.py', get_environ=get_environ) as writer: + from tests_python.debugger_unittest import CMD_LOAD_SOURCE + writer.write_start_redirect() + + file_in_client = get_file_in_client(writer) + assert 'tests_python' not in file_in_client + writer.write_add_breakpoint( + writer.get_line_index_with_content('break here'), 'call_this', filename=file_in_client) + writer.write_make_initial_run() + + xml = writer.wait_for_message(lambda msg:'stop_reason="111"' in msg) + assert xml.thread.frame[0]['file'] == file_in_client + thread_id = xml.thread['id'] + + # Request a file that exists + files_to_match = [file_in_client] + if IS_WINDOWS: + files_to_match.append(file_in_client.upper()) + for f in files_to_match: + writer.write_load_source(f) + writer.wait_for_message( + lambda msg: + '%s\t' % CMD_LOAD_SOURCE in msg and \ + "def main():" in msg and \ + "print('break here')" in msg and \ + "print('TEST SUCEEDED!')" in msg + , expect_xml=False) + + # Request a file that does not exist + writer.write_load_source(file_in_client + 'not_existent.py') + writer.wait_for_message( + lambda msg:'901\t' in msg and ('FileNotFoundError' in msg or 'IOError' in msg), + expect_xml=False) + + writer.write_run_thread(thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +def test_linecache_xml(case_setup, tmpdir): + from _pydevd_bundle.pydevd_comm_constants import CMD_LOAD_SOURCE_FROM_FRAME_ID + + with case_setup.test_file('_debugger_case_linecache.py') as writer: + writer.write_add_breakpoint(writer.get_line_index_with_content('breakpoint')) + writer.write_make_initial_run() + + # First hit is for breakpoint reached via a stack frame that doesn't have source. + hit = writer.wait_for_breakpoint_hit() + + writer.write_get_thread_stack(hit.thread_id) + msg = writer.wait_for_get_thread_stack_message() + frame_ids = set() + for frame in msg.thread.frame: + if frame['file'] == '': + frame_ids.add(frame['id']) + + assert len(frame_ids) == 2 + + for frame_id in frame_ids: + writer.write_load_source_from_frame_id(frame_id) + writer.wait_for_message( + lambda msg: + '%s\t' % CMD_LOAD_SOURCE_FROM_FRAME_ID in msg and ( + "[x for x in range(10)]" in msg and "def somemethod():" in msg + ) + , expect_xml=False) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +def test_show_bytecode_xml(case_setup, tmpdir): + from _pydevd_bundle.pydevd_comm_constants import CMD_LOAD_SOURCE_FROM_FRAME_ID + + with case_setup.test_file('_debugger_case_show_bytecode.py') as writer: + writer.write_add_breakpoint(writer.get_line_index_with_content('breakpoint')) + writer.write_make_initial_run() + + # First hit is for breakpoint reached via a stack frame that doesn't have source. + hit = writer.wait_for_breakpoint_hit() + + writer.write_get_thread_stack(hit.thread_id) + msg = writer.wait_for_get_thread_stack_message() + frame_ids = set() + for frame in msg.thread.frame: + if frame['file'] == '': + frame_ids.add(frame['id']) + + assert len(frame_ids) == 2 + + for frame_id in frame_ids: + writer.write_load_source_from_frame_id(frame_id) + writer.wait_for_message( + lambda msg: + '%s\t' % CMD_LOAD_SOURCE_FROM_FRAME_ID in msg and ( + "MyClass" in msg or "foo()" in msg + ) + , expect_xml=False) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_evaluate_errors(case_setup): + with case_setup.test_file('_debugger_case_local_variables.py') as writer: + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here'), 'Call') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + thread_id = hit.thread_id + frame_id = hit.frame_id + + writer.write_evaluate_expression('%s\t%s\t%s' % (thread_id, frame_id, 'LOCAL'), 'name_error') + writer.wait_for_evaluation('' + else: + assert len(msg.thread.frame) > 1 # Stopped in threading (must have back frames). + assert msg.thread.frame[0]['name'] == 'method' + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_case_dump_threads_to_stderr(case_setup): + + from tests_python.debugger_unittest import wait_for_condition + + def additional_output_checks(writer, stdout, stderr): + assert is_stderr_ok(stderr), make_error_msg(stderr) + + def make_error_msg(stderr): + return 'Did not find thread dump in stderr. stderr:\n%s' % (stderr,) + + def is_stderr_ok(stderr): + return 'Thread Dump' in stderr and 'Thread pydevd.CommandThread (daemon: True, pydevd thread: True)' in stderr + + with case_setup.test_file( + '_debugger_case_get_thread_stack.py', additional_output_checks=additional_output_checks) as writer: + writer.write_add_breakpoint(12, None) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT) + + writer.write_dump_threads() + wait_for_condition( + lambda: is_stderr_ok(writer.get_stderr()), + lambda: make_error_msg(writer.get_stderr()) + ) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_stop_on_start_regular(case_setup): + + with case_setup.test_file('_debugger_case_simple_calls.py') as writer: + writer.write_stop_on_start() + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_START, file='_debugger_case_simple_calls.py', line=1) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def _get_breakpoint_cases(): + if sys.version_info >= (3, 7): + # Just check breakpoint() + return ('_debugger_case_breakpoint.py',) + else: + # Check breakpoint() and sys.__breakpointhook__ replacement. + return ('_debugger_case_breakpoint.py', '_debugger_case_breakpoint2.py') + + +@pytest.mark.parametrize("filename", _get_breakpoint_cases()) +def test_py_37_breakpoint(case_setup, filename): + with case_setup.test_file(filename) as writer: + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(file=filename, line=3) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def _get_generator_cases(): + # On py3 we should check both versions. + return ( + '_debugger_case_generator_py2.py', + '_debugger_case_generator_py3.py', + ) + + +@pytest.mark.parametrize("filename", _get_generator_cases()) +def test_generator_cases(case_setup, filename): + with case_setup.test_file(filename) as writer: + writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_stop_on_start_m_switch(case_setup_m_switch): + + with case_setup_m_switch.test_file() as writer: + writer.write_stop_on_start() + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_START, file='_debugger_case_m_switch.py', line=1) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_stop_on_start_entry_point(case_setup_m_switch_entry_point): + + with case_setup_m_switch_entry_point.test_file() as writer: + writer.write_stop_on_start() + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_START, file='_debugger_case_module_entry_point.py', line=1) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Not working properly on Jython (needs investigation).') +def test_debug_zip_files(case_setup, tmpdir): + + def get_environ(writer): + env = os.environ.copy() + curr_pythonpath = env.get('PYTHONPATH', '') + + curr_pythonpath = str(tmpdir.join('myzip.zip')) + os.pathsep + curr_pythonpath + curr_pythonpath = str(tmpdir.join('myzip2.egg!')) + os.pathsep + curr_pythonpath + env['PYTHONPATH'] = curr_pythonpath + + env["IDE_PROJECT_ROOTS"] = str(tmpdir.join('myzip.zip')) + return env + + import zipfile + zip_file = zipfile.ZipFile( + str(tmpdir.join('myzip.zip')), 'w') + zip_file.writestr('zipped/__init__.py', '') + zip_file.writestr('zipped/zipped_contents.py', 'def call_in_zip():\n return 1') + zip_file.close() + + zip_file = zipfile.ZipFile( + str(tmpdir.join('myzip2.egg!')), 'w') + zip_file.writestr('zipped2/__init__.py', '') + zip_file.writestr('zipped2/zipped_contents2.py', 'def call_in_zip2():\n return 1') + zip_file.close() + + with case_setup.test_file('_debugger_case_zip_files.py', get_environ=get_environ) as writer: + writer.write_add_breakpoint( + 2, + 'None', + filename=os.path.join(str(tmpdir.join('myzip.zip')), 'zipped', 'zipped_contents.py') + ) + + writer.write_add_breakpoint( + 2, + 'None', + filename=os.path.join(str(tmpdir.join('myzip2.egg!')), 'zipped2', 'zipped_contents2.py') + ) + + writer.write_make_initial_run() + hit = writer.wait_for_breakpoint_hit() + assert hit.name == 'call_in_zip' + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit() + assert hit.name == 'call_in_zip2' + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +@pytest.mark.parametrize('file_to_check', [ + '_debugger_case_multiprocessing_2.py', + '_debugger_case_multiprocessing.py', + '_debugger_case_python_c.py', + '_debugger_case_multiprocessing_pool.py' +]) +def test_multiprocessing_simple(case_setup_multiprocessing, file_to_check): + import threading + from tests_python.debugger_unittest import AbstractWriterThread + with case_setup_multiprocessing.test_file(file_to_check) as writer: + break1_line = writer.get_line_index_with_content('break 1 here') + break2_line = writer.get_line_index_with_content('break 2 here') + + writer.write_add_breakpoint(break1_line) + writer.write_add_breakpoint(break2_line) + + server_socket = writer.server_socket + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + expected_connections = 1 + + for _ in range(expected_connections): + server_socket.listen(1) + self.server_socket = server_socket + new_sock, addr = server_socket.accept() + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + + writer2 = SecondaryProcessWriterThread() + + writer2.reader_thread = reader_thread + writer2.sock = new_sock + + writer2.write_version() + writer2.write_add_breakpoint(break1_line) + writer2.write_add_breakpoint(break2_line) + writer2.write_make_initial_run() + + hit = writer2.wait_for_breakpoint_hit() + writer2.write_run_thread(hit.thread_id) + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + writer.write_make_initial_run() + hit2 = writer.wait_for_breakpoint_hit() + secondary_process_thread_communication.join(10) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + writer.write_run_thread(hit2.thread_id) + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +@pytest.mark.parametrize('count', range(5)) # Call multiple times to exercise timing issues. +def test_multiprocessing_with_stopped_breakpoints(case_setup_multiprocessing, count, debugger_runner_simple): + import threading + from tests_python.debugger_unittest import AbstractWriterThread + with case_setup_multiprocessing.test_file('_debugger_case_multiprocessing_stopped_threads.py') as writer: + break_main_line = writer.get_line_index_with_content('break in main here') + break_thread_line = writer.get_line_index_with_content('break in thread here') + break_process_line = writer.get_line_index_with_content('break in process here') + + writer.write_add_breakpoint(break_main_line) + writer.write_add_breakpoint(break_thread_line) + writer.write_add_breakpoint(break_process_line) + + server_socket = writer.server_socket + listening_event = threading.Event() + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + server_socket.listen(1) + self.server_socket = server_socket + listening_event.set() + writer.log.append(' *** Multiprocess waiting on server_socket.accept()') + new_sock, addr = server_socket.accept() + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + writer.log.append(' *** Multiprocess started ReaderThread') + + writer2 = SecondaryProcessWriterThread() + writer2._WRITE_LOG_PREFIX = ' *** Multiprocess write: ' + writer2.log = writer.log + + writer2.reader_thread = reader_thread + writer2.sock = new_sock + + writer2.write_version() + writer2.write_add_breakpoint(break_main_line) + writer2.write_add_breakpoint(break_thread_line) + writer2.write_add_breakpoint(break_process_line) + writer2.write_make_initial_run() + hit = writer2.wait_for_breakpoint_hit() + writer2.write_run_thread(hit.thread_id) + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + + ok = listening_event.wait(timeout=10) + assert ok + writer.write_make_initial_run() + hit2 = writer.wait_for_breakpoint_hit() # Breaks in thread. + writer.write_step_over(hit2.thread_id) + + hit2 = writer.wait_for_breakpoint_hit(REASON_STEP_OVER) # line == event.set() + + # paused on breakpoint, will start process and pause on main thread + # in the main process too. + writer.write_step_over(hit2.thread_id) + + # Note: ignore the step over hit (go only for the breakpoint hit). + main_hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT) + + secondary_process_thread_communication.join(10) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + + writer.write_run_thread(hit2.thread_id) + writer.write_run_thread(main_hit.thread_id) + + # We must have found at least 2 debug files when doing multiprocessing (one for + # each pid). + assert len(pydev_log.list_log_files(debugger_runner_simple.pydevd_debug_file)) == 2 + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +@pytest.mark.parametrize('target', [ + '_debugger_case_quoting.py', + '_debugger_case_subprocess_zip.py' +]) +def test_subprocess_quoted_args(case_setup_multiprocessing, target): + from tests_python.debugger_unittest import AbstractWriterThread + with case_setup_multiprocessing.test_file(target) as writer: + break_subprocess_line = writer.get_line_index_with_content('break here') + + writer.write_add_breakpoint(break_subprocess_line) + + server_socket = writer.server_socket + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + # Note: on linux on Python 2 because on Python 2 CPython subprocess.call will actually + # create a fork first (at which point it'll connect) and then, later on it'll + # call the main (as if it was a clean process as if PyDB wasn't created + # the first time -- the debugger will still work, but it'll do an additional + # connection. + + expected_connections = 1 + + for _ in range(expected_connections): + server_socket.listen(1) + self.server_socket = server_socket + new_sock, addr = server_socket.accept() + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + + writer2 = SecondaryProcessWriterThread() + + writer2.reader_thread = reader_thread + writer2.sock = new_sock + + writer2.write_version() + writer2.write_add_breakpoint(break_subprocess_line) + writer2.write_make_initial_run() + hit = writer2.wait_for_breakpoint_hit() + writer2.write_run_thread(hit.thread_id) + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + writer.write_make_initial_run() + + secondary_process_thread_communication.join(10) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + + writer.finished_ok = True + + +def _attach_to_writer_pid(writer): + import pydevd + assert writer.process is not None + + def attach(): + attach_pydevd_file = os.path.join(os.path.dirname(pydevd.__file__), 'pydevd_attach_to_process', 'attach_pydevd.py') + subprocess.call([sys.executable, attach_pydevd_file, '--pid', str(writer.process.pid), '--port', str(writer.port)]) + + threading.Thread(target=attach).start() + + wait_for_condition(lambda: writer.finished_initialization) + + +@pytest.mark.skipif(not IS_CPYTHON or IS_MAC, reason='CPython only test (brittle on Mac).') +@pytest.mark.parametrize('reattach', [True, False]) +def test_attach_to_pid_no_threads(case_setup_remote, reattach): + with case_setup_remote.test_file('_debugger_case_attach_to_pid_simple.py', wait_for_port=False) as writer: + time.sleep(1) # Give it some time to initialize to get to the while loop. + _attach_to_writer_pid(writer) + + bp_line = writer.get_line_index_with_content('break here') + bp_id = writer.write_add_breakpoint(bp_line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=bp_line) + + if reattach: + # This would be the same as a second attach to pid, so, the idea is closing the current + # connection and then doing a new attach to pid. + writer.write_remove_breakpoint(bp_id) + writer.write_run_thread(hit.thread_id) + + writer.do_kill() # This will simply close the open sockets without doing anything else. + time.sleep(1) + + t = threading.Thread(target=writer.start_socket) + t.start() + wait_for_condition(lambda: hasattr(writer, 'port')) + time.sleep(1) + writer.process = writer.process + _attach_to_writer_pid(writer) + wait_for_condition(lambda: hasattr(writer, 'reader_thread')) + time.sleep(1) + + bp_id = writer.write_add_breakpoint(bp_line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=bp_line) + + writer.write_change_variable(hit.thread_id, hit.frame_id, 'wait', 'False') + writer.wait_for_var(' 1 + else: + assert len(msg) == 1 + + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_GEVENT, reason='Gevent not installed.') +def test_gevent_remote(case_setup_remote): + + def get_environ(writer): + env = os.environ.copy() + env['GEVENT_SUPPORT'] = 'True' + return env + + with case_setup_remote.test_file('_debugger_case_gevent.py', get_environ=get_environ, append_command_line_args=['remote']) as writer: + writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + writer.write_make_initial_run() + for _i in range(10): + hit = writer.wait_for_breakpoint_hit(name='run') + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +def test_return_value(case_setup): + with case_setup.test_file('_debugger_case_return_value.py') as writer: + break_line = writer.get_line_index_with_content('break here') + writer.write_add_breakpoint(break_line) + writer.write_show_return_vars() + writer.write_make_initial_run() + hit = writer.wait_for_breakpoint_hit(name='main', line=break_line) + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, name='main', line=break_line + 1) + writer.write_get_frame(hit.thread_id, hit.frame_id) + writer.wait_for_vars([ + [ + '' + + writer.write_step_over_my_code(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_OVER_MY_CODE) + assert hit.name == '' + + writer.write_step_over_my_code(hit.thread_id) + writer.finished_ok = True + + +@pytest.fixture( + params=[ + 'step_over', + 'step_return', + 'step_in', + ] +) +def step_method(request): + return request.param + + +def test_sysexit_on_filtered_file(case_setup): + + def get_environ(writer): + env = os.environ.copy() + env.update({'PYDEVD_FILTERS': json.dumps({'**/_debugger_case_sysexit.py': True})}) + return env + + with case_setup.test_file('_debugger_case_sysexit.py', get_environ=get_environ, EXPECTED_RETURNCODE=1) as writer: + writer.write_add_exception_breakpoint_with_policy( + 'SystemExit', + notify_on_handled_exceptions=1, # Notify multiple times + notify_on_unhandled_exceptions=1, + ignore_libraries=0 + ) + + writer.write_make_initial_run() + writer.finished_ok = True + + +@pytest.mark.parametrize("scenario", [ + 'handled_once', + 'handled_multiple', + 'unhandled', +]) +def test_exception_not_on_filtered_file(case_setup, scenario): + + def get_environ(writer): + env = os.environ.copy() + env.update({'PYDEVD_FILTERS': json.dumps({'**/other.py': True})}) + return env + + def check_test_suceeded_msg(writer, stdout, stderr): + return 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + if 'raise RuntimeError' not in stderr: + raise AssertionError('Expected test to have an unhandled exception.\nstdout:\n%s\n\nstderr:\n%s' % ( + stdout, stderr)) + + with case_setup.test_file( + 'my_code/my_code_exception.py', + get_environ=get_environ, + EXPECTED_RETURNCODE='any', + check_test_suceeded_msg=check_test_suceeded_msg, + additional_output_checks=additional_output_checks, + ) as writer: + + if scenario == 'handled_once': + writer.write_add_exception_breakpoint_with_policy( + 'RuntimeError', + notify_on_handled_exceptions=2, # Notify only once + notify_on_unhandled_exceptions=0, + ignore_libraries=0 + ) + elif scenario == 'handled_multiple': + writer.write_add_exception_breakpoint_with_policy( + 'RuntimeError', + notify_on_handled_exceptions=1, # Notify multiple times + notify_on_unhandled_exceptions=0, + ignore_libraries=0 + ) + elif scenario == 'unhandled': + writer.write_add_exception_breakpoint_with_policy( + 'RuntimeError', + notify_on_handled_exceptions=0, + notify_on_unhandled_exceptions=1, + ignore_libraries=0 + ) + + writer.write_make_initial_run() + for _i in range(3 if scenario == 'handled_multiple' else 1): + hit = writer.wait_for_breakpoint_hit( + REASON_UNCAUGHT_EXCEPTION if scenario == 'unhandled' else REASON_CAUGHT_EXCEPTION) + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +def test_exception_on_filtered_file(case_setup): + + def get_environ(writer): + env = os.environ.copy() + env.update({'PYDEVD_FILTERS': json.dumps({'**/other.py': True})}) + return env + + def check_test_suceeded_msg(writer, stdout, stderr): + return 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + if 'raise RuntimeError' not in stderr: + raise AssertionError('Expected test to have an unhandled exception.\nstdout:\n%s\n\nstderr:\n%s' % ( + stdout, stderr)) + + with case_setup.test_file( + 'my_code/my_code_exception_on_other.py', + get_environ=get_environ, + EXPECTED_RETURNCODE='any', + check_test_suceeded_msg=check_test_suceeded_msg, + additional_output_checks=additional_output_checks, + ) as writer: + writer.write_add_exception_breakpoint_with_policy( + 'RuntimeError', + notify_on_handled_exceptions=2, # Notify only once + notify_on_unhandled_exceptions=1, + ignore_libraries=0 + ) + + writer.write_make_initial_run() + + # Note: the unhandled exception was initially raised in a file which is filtered out, but we + # should be able to see the frames which are part of the project. + hit = writer.wait_for_breakpoint_hit( + REASON_UNCAUGHT_EXCEPTION, + file='my_code_exception_on_other.py', + line=writer.get_line_index_with_content('other.raise_exception()') + ) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.parametrize("environ", [ + {'PYDEVD_FILTER_LIBRARIES': '1'}, # Global setting for step over + {'PYDEVD_FILTERS': json.dumps({'**/other.py': True})}, # specify as json + {'PYDEVD_FILTERS': '**/other.py'}, # specify ';' separated list +]) +@pytest.mark.skipif(IS_JYTHON, reason='Flaky on Jython.') +def test_step_over_my_code_global_settings(case_setup, environ, step_method): + + def get_environ(writer): + env = os.environ.copy() + env.update(environ) + return env + + def do_step(): + if step_method == 'step_over': + writer.write_step_over(hit.thread_id) + return REASON_STEP_OVER # Note: goes from step over to step into + elif step_method == 'step_return': + writer.write_step_return(hit.thread_id) + return REASON_STEP_RETURN + else: + assert step_method == 'step_in' + writer.write_step_in(hit.thread_id) + return REASON_STEP_INTO + + with case_setup.test_file('my_code/my_code.py', get_environ=get_environ) as writer: + writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('my_code')]) + writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + writer.write_make_initial_run() + hit = writer.wait_for_breakpoint_hit() + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO) + assert hit.name == 'callback1' + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO) + assert hit.name == 'callback2' + + stop_reason = do_step() + hit = writer.wait_for_breakpoint_hit(reason=stop_reason) + assert hit.name == 'callback1' + + stop_reason = do_step() + hit = writer.wait_for_breakpoint_hit(reason=stop_reason) + assert hit.name == '' + + if IS_JYTHON: + # Jython may get to exit functions, so, just resume the thread. + writer.write_run_thread(hit.thread_id) + + else: + stop_reason = do_step() + + if step_method != 'step_return': + stop_reason = do_step() + if step_method == 'step_over': + stop_reason = REASON_STEP_OVER + + hit = writer.wait_for_breakpoint_hit(reason=stop_reason) + assert hit.name == '' + + writer.write_step_over(hit.thread_id) + + writer.finished_ok = True + + +def test_step_over_my_code_global_setting_and_explicit_include(case_setup): + + def get_environ(writer): + env = os.environ.copy() + env.update({ + 'PYDEVD_FILTER_LIBRARIES': '1', # Global setting for in project or not + # specify as json (force include). + 'PYDEVD_FILTERS': json.dumps({'**/other.py': False}) + }) + return env + + with case_setup.test_file('my_code/my_code.py', get_environ=get_environ) as writer: + writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('my_code')]) + writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + writer.write_make_initial_run() + hit = writer.wait_for_breakpoint_hit() + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO) + + # Although we filtered out non-project files, other.py is explicitly included. + assert hit.name == 'call_me_back1' + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +def test_access_token(case_setup): + + def update_command_line_args(self, args): + i = args.index('--client') + assert i > 0 + args.insert(i, '--access-token') + args.insert(i + 1, 'bar123') + args.insert(i, '--client-access-token') + args.insert(i + 1, 'foo234') + return args + + with case_setup.test_file('_debugger_case_print.py', update_command_line_args=update_command_line_args) as writer: + writer.write_add_breakpoint(1, 'None') # I.e.: should not work (not authenticated). + + writer.wait_for_message(lambda msg:'Client not authenticated.' in msg, expect_xml=False) + + writer.write_authenticate(access_token='bar123', client_access_token='foo234') + + writer.write_version() + + writer.write_make_initial_run() + + writer.finished_ok = True + + +def test_namedtuple(case_setup): + ''' + Check that we don't step into in the namedtuple constructor. + ''' + with case_setup.test_file('_debugger_case_namedtuple.py') as writer: + line = writer.get_line_index_with_content('break here') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + expected_line = line + + for _ in range(2): + expected_line += 1 + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_INTO, file='_debugger_case_namedtuple.py', line=expected_line) + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +def test_matplotlib_activation(case_setup): + try: + import matplotlib + except ImportError: + return + + def get_environ(writer): + env = os.environ.copy() + env.update({ + 'IPYTHONENABLE': 'True', + }) + return env + + with case_setup.test_file('_debugger_case_matplotlib.py', get_environ=get_environ) as writer: + writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + writer.write_make_initial_run() + for _ in range(3): + hit = writer.wait_for_breakpoint_hit() + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +_GENERATOR_FILES = [ + '_debugger_case_generator3.py', + '_debugger_case_generator.py', + '_debugger_case_generator2.py', +] + + +@pytest.mark.parametrize('target_filename', _GENERATOR_FILES) +@pytest.mark.skipif(IS_JYTHON, reason='We do not detect generator returns on Jython.') +def test_generator_step_over_basic(case_setup, target_filename): + with case_setup.test_file(target_filename) as writer: + line = writer.get_line_index_with_content('break here') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + # Note: not using for so that we know which step failed in the ci if it fails. + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_OVER, + file=target_filename, + line=writer.get_line_index_with_content('step 1') + ) + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_OVER, + file=target_filename, + line=writer.get_line_index_with_content('step 2') + ) + + if IS_PY38_OR_GREATER and target_filename == '_debugger_case_generator2.py': + # On py 3.8 it goes back to the return line. + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_OVER, + file=target_filename, + line=writer.get_line_index_with_content('return \\') + ) + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_OVER, + file=target_filename, + line=writer.get_line_index_with_content('step 3') + ) + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +@pytest.mark.parametrize('target_filename', _GENERATOR_FILES) +@pytest.mark.skipif(IS_JYTHON, reason='We do not detect generator returns on Jython.') +def test_generator_step_return(case_setup, target_filename): + with case_setup.test_file(target_filename) as writer: + line = writer.get_line_index_with_content('break here') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + # Note: not using for so that we know which step failed in the ci if it fails. + writer.write_step_return(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_RETURN, + file=target_filename, + line=writer.get_line_index_with_content('generator return') + ) + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_OVER, + file=target_filename, + line=writer.get_line_index_with_content('step 3') + ) + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +def test_stepin_not_my_code_coroutine(case_setup): + + def get_environ(writer): + environ = {'PYDEVD_FILTERS': '{"**/not_my_coroutine.py": true}'} + env = os.environ.copy() + env.update(environ) + return env + + with case_setup.test_file('my_code/my_code_coroutine.py', get_environ=get_environ) as writer: + writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('my_code')]) + writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + writer.write_make_initial_run() + hit = writer.wait_for_breakpoint_hit() + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO) + assert hit.name == 'main' + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Flaky on Jython') +def test_generator_step_in(case_setup): + with case_setup.test_file('_debugger_case_generator_step_in.py') as writer: + line = writer.get_line_index_with_content('stop 1') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + for i in range(2, 5): + writer.write_step_in(hit.thread_id) + kwargs = {} + if not IS_JYTHON: + kwargs['line'] = writer.get_line_index_with_content('stop %s' % (i,)) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_INTO, + file='_debugger_case_generator_step_in.py', + **kwargs + ) + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +@pytest.mark.parametrize( + 'target_filename', + [ + '_debugger_case_asyncio.py', + '_debugger_case_trio.py', + ] +) +@pytest.mark.skipif(not IS_CPYTHON or not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +def test_asyncio_step_over_basic(case_setup, target_filename): + with case_setup.test_file(target_filename) as writer: + line = writer.get_line_index_with_content('break main') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_OVER, + file=target_filename, + line=writer.get_line_index_with_content('step main') + ) + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +@pytest.mark.parametrize( + 'target_filename', + [ + '_debugger_case_asyncio.py', + '_debugger_case_trio.py', + ] +) +@pytest.mark.skipif(not IS_CPYTHON or not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +def test_asyncio_step_over_end_of_function(case_setup, target_filename): + with case_setup.test_file(target_filename) as writer: + line = writer.get_line_index_with_content('break count 2') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_OVER, + name=('sleep', 'wait_task_rescheduled'), + ) + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +@pytest.mark.parametrize( + 'target_filename', + [ + '_debugger_case_asyncio.py', + '_debugger_case_trio.py', + ] +) +@pytest.mark.skipif(not IS_CPYTHON or not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +def test_asyncio_step_in(case_setup, target_filename): + with case_setup.test_file(target_filename) as writer: + line = writer.get_line_index_with_content('break count 1') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + writer.write_step_return(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_RETURN, + file=target_filename, + line=writer.get_line_index_with_content('break main') + ) + + writer.write_step_in(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_INTO, + name=('sleep', 'wait_task_rescheduled'), + ) + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +@pytest.mark.parametrize( + 'target_filename', + [ + '_debugger_case_asyncio.py', + '_debugger_case_trio.py', + ] +) +@pytest.mark.skipif(not IS_CPYTHON or not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +def test_asyncio_step_return(case_setup, target_filename): + with case_setup.test_file(target_filename) as writer: + line = writer.get_line_index_with_content('break count 1') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + + writer.write_step_return(hit.thread_id) + hit = writer.wait_for_breakpoint_hit( + reason=REASON_STEP_RETURN, + file=target_filename, + line=writer.get_line_index_with_content('break main') + ) + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + +def test_notify_stdin(case_setup, pyfile): + + @pyfile + def case_stdin(): + import sys + print('Write something:') + contents = sys.stdin.readline() + print('Found: ' + contents) + + print('TEST SUCEEDED') + + def additional_output_checks(writer, stdout, stderr): + assert 'Found: foo' in stdout + + with case_setup.test_file( + case_stdin, + additional_output_checks=additional_output_checks, + ) as writer: + writer.write_make_initial_run() + msg = writer.wait_for_message(CMD_INPUT_REQUESTED, expect_xml=False) + assert msg.split('\t')[-1] == 'True' + process = writer.process + process.stdin.write(b'foo\n') + process.stdin.flush() + msg = writer.wait_for_message(CMD_INPUT_REQUESTED, expect_xml=False) + assert msg.split('\t')[-1] == 'False' + + writer.finished_ok = True + + +def test_frame_eval_mode_corner_case_01(case_setup): + + with case_setup.test_file( + 'wrong_bytecode/_debugger_case_wrong_bytecode.py', + ) as writer: + line = writer.get_line_index_with_content('break here') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + hit = writer.wait_for_breakpoint_hit(line=writer.get_line_index_with_content('break here'), file='_debugger_case_wrong_bytecode.py') + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=writer.get_line_index_with_content('step 1'), file='_debugger_case_wrong_bytecode.py', reason=REASON_STEP_OVER) + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=writer.get_line_index_with_content('step 2'), file='_debugger_case_wrong_bytecode.py', reason=REASON_STEP_OVER) + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=writer.get_line_index_with_content('step 3'), file='_debugger_case_wrong_bytecode.py', reason=REASON_STEP_OVER) + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=writer.get_line_index_with_content('step 4'), file='_debugger_case_wrong_bytecode.py', reason=REASON_STEP_OVER) + writer.write_step_over(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=writer.get_line_index_with_content('step 5'), file='_debugger_case_wrong_bytecode.py', reason=REASON_STEP_OVER) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +def test_frame_eval_mode_corner_case_02(case_setup): + + with case_setup.test_file( + '_bytecode_super.py', + ) as writer: + line = writer.get_line_index_with_content('break here') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=line, file='_bytecode_super.py') + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +def test_frame_eval_mode_corner_case_03(case_setup): + + with case_setup.test_file( + '_bytecode_constructs.py', + ) as writer: + line = writer.get_line_index_with_content('break while') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=line) + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(line=line + 1, reason=REASON_STEP_OVER) + + writer.write_step_over(hit.thread_id) # i.e.: check that the jump target is still ok. + hit = writer.wait_for_breakpoint_hit(line=line, reason=REASON_STEP_OVER) + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(line=line + 1, reason=REASON_STEP_OVER) + + writer.write_step_over(hit.thread_id) + hit = writer.wait_for_breakpoint_hit(line=line, reason=REASON_STEP_OVER) + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +def test_frame_eval_mode_corner_case_04(case_setup): + + with case_setup.test_file( + '_bytecode_constructs.py', + ) as writer: + line = writer.get_line_index_with_content('break for') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=line) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=line) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=line) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +@pytest.mark.parametrize( + 'break_name', + [ + 'break except', + 'break with', + 'break try 1', + 'break try 2', + 'break finally 1', + 'break except 2', + 'break finally 2', + 'break finally 3', + 'break finally 4', + 'break in dict', + 'break else', + ] +) +def test_frame_eval_mode_corner_case_many(case_setup, break_name): + if break_name == 'break finally 4' and sys.version_info[:2] == (3, 9): + # This case is currently failing in Python 3.9 + return + + # Check the constructs where we stop only once and proceed. + with case_setup.test_file( + '_bytecode_constructs.py', + ) as writer: + line = writer.get_line_index_with_content(break_name) + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=line) + writer.write_run_thread(hit.thread_id) + + if break_name == 'break with': + if sys.version_info[:2] >= (3, 10): + # On Python 3.10 it'll actually backtrack for the + # with and thus will execute the line where the + # 'with' statement was started again. + hit = writer.wait_for_breakpoint_hit(line=line) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +check_shadowed = [ + ( + u''' +if __name__ == '__main__': + import queue + print(queue) +''', + 'queue.py', + u'shadowed = True\n' + ), + + ( + u''' +if __name__ == '__main__': + import queue + print(queue) +''', + 'queue.py', + u'raise AssertionError("error on import")' + ) +] + + +@pytest.mark.parametrize('module_name_and_content', check_shadowed) +def test_debugger_shadowed_imports(case_setup, tmpdir, module_name_and_content): + main_content, module_name, content = module_name_and_content + target = tmpdir.join('main.py') + shadowed = tmpdir.join(module_name) + + target.write_text(main_content, encoding='utf-8') + + shadowed.write_text(content, encoding='utf-8') + + def get_environ(writer): + env = os.environ.copy() + env.update({ + 'PYTHONPATH': str(tmpdir), + }) + return env + + try: + with case_setup.test_file( + str(target), + get_environ=get_environ, + wait_for_initialization=False, + ) as writer: + writer.write_make_initial_run() + except AssertionError: + pass # This is expected as pydevd didn't start-up. + + assert ('the module "%s" could not be imported because it is shadowed by:' % (module_name.split('.')[0])) in writer.get_stderr() + + +def test_debugger_hide_pydevd_threads(case_setup, pyfile): + + @pyfile + def target_file(): + import threading + from _pydevd_bundle import pydevd_constants + found_pydevd_thread = False + for t in threading.enumerate(): + if getattr(t, 'is_pydev_daemon_thread', False): + found_pydevd_thread = True + + if pydevd_constants.IS_CPYTHON: + assert not found_pydevd_thread + else: + assert found_pydevd_thread + print('TEST SUCEEDED') + + with case_setup.test_file(target_file) as writer: + line = writer.get_line_index_with_content('TEST SUCEEDED') + writer.write_add_breakpoint(line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=line) + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + +# Jython needs some vars to be set locally. +# set JAVA_HOME=c:\bin\jdk1.8.0_172 +# set PATH=%PATH%;C:\bin\jython2.7.0\bin +# set PATH=%PATH%;%JAVA_HOME%\bin +# c:\bin\jython2.7.0\bin\jython.exe -m py.test tests_python + + +if __name__ == '__main__': + pytest.main(['-k', 'test_case_12']) diff --git a/tests_python/test_debugger_json.py b/tests_python/test_debugger_json.py new file mode 100644 index 0000000..73ea325 --- /dev/null +++ b/tests_python/test_debugger_json.py @@ -0,0 +1,6375 @@ +# coding: utf-8 +from collections import namedtuple +import json +from os.path import normcase +import os.path +import sys +import time + +import pytest + +from _pydev_bundle.pydev_localhost import get_socket_name +from _pydevd_bundle._debug_adapter import pydevd_schema, pydevd_base_schema +from _pydevd_bundle._debug_adapter.pydevd_base_schema import from_json +from _pydevd_bundle._debug_adapter.pydevd_schema import (ThreadEvent, ModuleEvent, OutputEvent, + ExceptionOptions, Response, StoppedEvent, ContinuedEvent, ProcessEvent, InitializeRequest, + InitializeRequestArguments, TerminateArguments, TerminateRequest, TerminatedEvent, + FunctionBreakpoint, SetFunctionBreakpointsRequest, SetFunctionBreakpointsArguments, + BreakpointEvent) +from _pydevd_bundle.pydevd_comm_constants import file_system_encoding +from _pydevd_bundle.pydevd_constants import (int_types, IS_64BIT_PROCESS, + PY_VERSION_STR, PY_IMPL_VERSION_STR, PY_IMPL_NAME, IS_PY36_OR_GREATER, + IS_PYPY, GENERATED_LEN_ATTR_NAME, IS_WINDOWS, IS_LINUX, IS_MAC, IS_PY38_OR_GREATER) +from tests_python import debugger_unittest +from tests_python.debug_constants import TEST_CHERRYPY, TEST_DJANGO, TEST_FLASK, \ + IS_CPYTHON, TEST_GEVENT, TEST_CYTHON, TODO_PY311 +from tests_python.debugger_unittest import (IS_JYTHON, IS_APPVEYOR, overrides, + get_free_port, wait_for_condition) +from _pydevd_bundle.pydevd_utils import DAPGrouper +import pydevd_file_utils +from _pydevd_bundle import pydevd_constants + +pytest_plugins = [ + str('tests_python.debugger_fixtures'), +] + +_JsonHit = namedtuple('_JsonHit', 'thread_id, frame_id, stack_trace_response') + +pytestmark = pytest.mark.skipif(IS_JYTHON, reason='Single notification is not OK in Jython (investigate).') + +# Note: in reality must be < int32, but as it's created sequentially this should be +# a reasonable number for tests. +MAX_EXPECTED_ID = 10000 + + +class _MessageWithMark(object): + + def __init__(self, msg): + self.msg = msg + self.marked = False + + +class JsonFacade(object): + + def __init__(self, writer, send_json_startup_messages=True): + self.writer = writer + writer.reader_thread.accept_xml_messages = False + if send_json_startup_messages: + writer.write_set_protocol('http_json') + writer.write_multi_threads_single_notification(True) + self._all_json_messages_found = [] + self._sent_launch_or_attach = False + + def mark_messages(self, expected_class, accept_message=lambda obj:True): + ret = [] + for message_with_mark in self._all_json_messages_found: + if not message_with_mark.marked: + if isinstance(message_with_mark.msg, expected_class): + if accept_message(message_with_mark.msg): + message_with_mark.marked = True + ret.append(message_with_mark.msg) + return ret + + def wait_for_json_message(self, expected_class, accept_message=lambda obj:True): + + def accept_json_message(msg): + if msg.startswith('{'): + decoded_msg = from_json(msg) + + self._all_json_messages_found.append(_MessageWithMark(decoded_msg)) + + if isinstance(decoded_msg, expected_class): + if accept_message(decoded_msg): + return True + return False + + msg = self.writer.wait_for_message(accept_json_message, unquote_msg=False, expect_xml=False) + return from_json(msg) + + def wait_for_response(self, request, response_class=None): + if response_class is None: + response_class = pydevd_base_schema.get_response_class(request) + + def accept_message(response): + if isinstance(request, dict): + if response.request_seq == request['seq']: + return True + else: + if response.request_seq == request.seq: + return True + return False + + return self.wait_for_json_message((response_class, Response), accept_message) + + def write_request(self, request): + seq = self.writer.next_seq() + if isinstance(request, dict): + request['seq'] = seq + self.writer.write_with_content_len(json.dumps(request)) + else: + request.seq = seq + self.writer.write_with_content_len(request.to_json()) + return request + + def write_make_initial_run(self): + if not self._sent_launch_or_attach: + self._auto_write_launch() + + configuration_done_request = self.write_request(pydevd_schema.ConfigurationDoneRequest()) + return self.wait_for_response(configuration_done_request) + + def write_list_threads(self): + return self.wait_for_response(self.write_request(pydevd_schema.ThreadsRequest())) + + def wait_for_terminated(self): + return self.wait_for_json_message(TerminatedEvent) + + def wait_for_thread_stopped(self, reason='breakpoint', line=None, file=None, name=None, preserve_focus_hint=None): + ''' + :param file: + utf-8 bytes encoded file or unicode + ''' + stopped_event = self.wait_for_json_message(StoppedEvent) + assert stopped_event.body.reason == reason + if preserve_focus_hint is not None: + assert stopped_event.body.preserveFocusHint == preserve_focus_hint + json_hit = self.get_stack_as_json_hit(stopped_event.body.threadId) + if file is not None: + path = json_hit.stack_trace_response.body.stackFrames[0]['source']['path'] + + if not path.endswith(file): + # pytest may give a lowercase tempdir, so, also check with + # the real case if possible + file = pydevd_file_utils.get_path_with_real_case(file) + if not path.endswith(file): + raise AssertionError('Expected path: %s to end with: %s' % (path, file)) + if name is not None: + assert json_hit.stack_trace_response.body.stackFrames[0]['name'] == name + if line is not None: + found_line = json_hit.stack_trace_response.body.stackFrames[0]['line'] + path = json_hit.stack_trace_response.body.stackFrames[0]['source']['path'] + if not isinstance(line, (tuple, list)): + line = [line] + assert found_line in line, 'Expect to break at line: %s. Found: %s (file: %s)' % (line, found_line, path) + return json_hit + + def write_set_function_breakpoints( + self, function_names): + function_breakpoints = [FunctionBreakpoint(name,) for name in function_names] + arguments = SetFunctionBreakpointsArguments(function_breakpoints) + request = SetFunctionBreakpointsRequest(arguments) + response = self.wait_for_response(self.write_request(request)) + assert response.success + + def write_set_breakpoints( + self, + lines, + filename=None, + line_to_info=None, + success=True, + verified=True, + send_launch_if_needed=True, + expected_lines_in_response=None, + ): + ''' + Adds a breakpoint. + ''' + if send_launch_if_needed and not self._sent_launch_or_attach: + self._auto_write_launch() + + if isinstance(lines, int): + lines = [lines] + + if line_to_info is None: + line_to_info = {} + + if filename is None: + filename = self.writer.get_main_filename() + + if isinstance(filename, bytes): + filename = filename.decode(file_system_encoding) # file is in the filesystem encoding but protocol needs it in utf-8 + filename = filename.encode('utf-8') + + source = pydevd_schema.Source(path=filename) + breakpoints = [] + for line in lines: + condition = None + hit_condition = None + log_message = None + + if line in line_to_info: + line_info = line_to_info.get(line) + condition = line_info.get('condition') + hit_condition = line_info.get('hit_condition') + log_message = line_info.get('log_message') + + breakpoints.append(pydevd_schema.SourceBreakpoint( + line, condition=condition, hitCondition=hit_condition, logMessage=log_message).to_dict()) + + arguments = pydevd_schema.SetBreakpointsArguments(source, breakpoints) + request = pydevd_schema.SetBreakpointsRequest(arguments) + + # : :type response: SetBreakpointsResponse + response = self.wait_for_response(self.write_request(request)) + body = response.body + + assert response.success == success + + if success: + # : :type body: SetBreakpointsResponseBody + assert len(body.breakpoints) == len(lines) + lines_in_response = [b['line'] for b in body.breakpoints] + + if expected_lines_in_response is None: + expected_lines_in_response = lines + assert set(lines_in_response) == set(expected_lines_in_response) + + for b in body.breakpoints: + if isinstance(verified, dict): + if b['verified'] != verified[b['id']]: + raise AssertionError('Expected verified breakpoint to be: %s. Found: %s.\nBreakpoint: %s' % ( + verified, verified[b['id']], b)) + + elif b['verified'] != verified: + raise AssertionError('Expected verified breakpoint to be: %s. Found: %s.\nBreakpoint: %s' % ( + verified, b['verified'], b)) + return response + + def write_set_exception_breakpoints(self, filters=None, exception_options=None): + ''' + :param list(str) filters: + A list with 'raised' or 'uncaught' entries. + + :param list(ExceptionOptions) exception_options: + + ''' + filters = filters or [] + assert set(filters).issubset(set(('raised', 'uncaught', 'userUnhandled'))) + + exception_options = exception_options or [] + exception_options = [exception_option.to_dict() for exception_option in exception_options] + + arguments = pydevd_schema.SetExceptionBreakpointsArguments(filters=filters, exceptionOptions=exception_options) + request = pydevd_schema.SetExceptionBreakpointsRequest(arguments) + # : :type response: SetExceptionBreakpointsResponse + response = self.wait_for_response(self.write_request(request)) + assert response.success + + def reset_sent_launch_or_attach(self): + self._sent_launch_or_attach = False + + def _write_launch_or_attach(self, command, **arguments): + assert not self._sent_launch_or_attach + self._sent_launch_or_attach = True + arguments['noDebug'] = False + request = {'type': 'request', 'command': command, 'arguments': arguments, 'seq':-1} + self.wait_for_response(self.write_request(request)) + + def _auto_write_launch(self): + self.write_launch(variablePresentation={ + "all": "hide", + "protected": "inline", + }) + + def write_launch(self, **arguments): + return self._write_launch_or_attach('launch', **arguments) + + def write_attach(self, **arguments): + return self._write_launch_or_attach('attach', **arguments) + + def write_disconnect(self, wait_for_response=True, terminate_debugee=False): + assert self._sent_launch_or_attach + self._sent_launch_or_attach = False + arguments = pydevd_schema.DisconnectArguments(terminateDebuggee=terminate_debugee) + request = pydevd_schema.DisconnectRequest(arguments=arguments) + self.write_request(request) + if wait_for_response: + self.wait_for_response(request) + + def get_stack_as_json_hit(self, thread_id, no_stack_frame=False): + stack_trace_request = self.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=thread_id))) + + # : :type stack_trace_response: StackTraceResponse + # : :type stack_trace_response_body: StackTraceResponseBody + # : :type stack_frame: StackFrame + stack_trace_response = self.wait_for_response(stack_trace_request) + stack_trace_response_body = stack_trace_response.body + if no_stack_frame: + assert len(stack_trace_response_body.stackFrames) == 0 + frame_id = None + else: + assert len(stack_trace_response_body.stackFrames) > 0 + for stack_frame in stack_trace_response_body.stackFrames: + assert stack_frame['id'] < MAX_EXPECTED_ID + + stack_frame = next(iter(stack_trace_response_body.stackFrames)) + frame_id = stack_frame['id'] + + return _JsonHit( + thread_id=thread_id, frame_id=frame_id, stack_trace_response=stack_trace_response) + + def get_variables_response(self, variables_reference, fmt=None, success=True): + assert variables_reference < MAX_EXPECTED_ID + variables_request = self.write_request( + pydevd_schema.VariablesRequest(pydevd_schema.VariablesArguments(variables_reference, format=fmt))) + variables_response = self.wait_for_response(variables_request) + assert variables_response.success == success + return variables_response + + def filter_return_variables(self, variables): + ret = [] + for variable in variables: + if variable['name'].startswith('(return)'): + ret.append(variable) + return ret + + def pop_variables_reference(self, lst): + ''' + Modifies dicts in-place to remove the variablesReference and returns those (in the same order + in which they were received). + ''' + references = [] + for dct in lst: + reference = dct.pop('variablesReference', None) + if reference is not None: + assert isinstance(reference, int_types) + assert reference < MAX_EXPECTED_ID + references.append(reference) + return references + + def wait_for_continued_event(self): + assert self.wait_for_json_message(ContinuedEvent).body.allThreadsContinued + + def write_continue(self, wait_for_response=True): + continue_request = self.write_request( + pydevd_schema.ContinueRequest(pydevd_schema.ContinueArguments('*'))) + + if wait_for_response: + # The continued event is received before the response. + self.wait_for_continued_event() + + continue_response = self.wait_for_response(continue_request) + assert continue_response.body.allThreadsContinued + + def write_pause(self): + pause_request = self.write_request( + pydevd_schema.PauseRequest(pydevd_schema.PauseArguments('*'))) + pause_response = self.wait_for_response(pause_request) + assert pause_response.success + + def write_step_in(self, thread_id, target_id=None): + arguments = pydevd_schema.StepInArguments(threadId=thread_id, targetId=target_id) + self.wait_for_response(self.write_request(pydevd_schema.StepInRequest(arguments))) + + def write_step_next(self, thread_id, wait_for_response=True): + next_request = self.write_request( + pydevd_schema.NextRequest(pydevd_schema.NextArguments(thread_id))) + if wait_for_response: + self.wait_for_response(next_request) + + def write_step_out(self, thread_id, wait_for_response=True): + stepout_request = self.write_request( + pydevd_schema.StepOutRequest(pydevd_schema.StepOutArguments(thread_id))) + if wait_for_response: + self.wait_for_response(stepout_request) + + def write_set_variable(self, frame_variables_reference, name, value, success=True): + set_variable_request = self.write_request( + pydevd_schema.SetVariableRequest(pydevd_schema.SetVariableArguments( + frame_variables_reference, name, value, + ))) + set_variable_response = self.wait_for_response(set_variable_request) + if set_variable_response.success != success: + raise AssertionError( + 'Expected %s. Found: %s\nResponse: %s\n' % ( + success, set_variable_response.success, set_variable_response.to_json())) + return set_variable_response + + def get_name_to_scope(self, frame_id): + scopes_request = self.write_request(pydevd_schema.ScopesRequest( + pydevd_schema.ScopesArguments(frame_id))) + + scopes_response = self.wait_for_response(scopes_request) + + scopes = scopes_response.body.scopes + name_to_scopes = dict((scope['name'], pydevd_schema.Scope(**scope)) for scope in scopes) + + assert len(scopes) == 2 + assert sorted(name_to_scopes.keys()) == ['Globals', 'Locals'] + assert not name_to_scopes['Locals'].expensive + assert name_to_scopes['Locals'].presentationHint == 'locals' + + return name_to_scopes + + def get_step_in_targets(self, frame_id): + request = self.write_request(pydevd_schema.StepInTargetsRequest( + pydevd_schema.StepInTargetsArguments(frame_id))) + + # : :type response: StepInTargetsResponse + response = self.wait_for_response(request) + + # : :type body: StepInTargetsResponseBody + body = response.body + targets = body.targets + # : :type targets: List[StepInTarget] + return targets + + def get_name_to_var(self, variables_reference): + variables_response = self.get_variables_response(variables_reference) + return dict((variable['name'], pydevd_schema.Variable(**variable)) for variable in variables_response.body.variables) + + def get_locals_name_to_var(self, frame_id): + name_to_scope = self.get_name_to_scope(frame_id) + + return self.get_name_to_var(name_to_scope['Locals'].variablesReference) + + def get_globals_name_to_var(self, frame_id): + name_to_scope = self.get_name_to_scope(frame_id) + + return self.get_name_to_var(name_to_scope['Globals'].variablesReference) + + def get_local_var(self, frame_id, var_name): + ret = self.get_locals_name_to_var(frame_id)[var_name] + assert ret.name == var_name + return ret + + def get_global_var(self, frame_id, var_name): + ret = self.get_globals_name_to_var(frame_id)[var_name] + assert ret.name == var_name + return ret + + def get_var(self, variables_reference, var_name=None, index=None): + if var_name is not None: + return self.get_name_to_var(variables_reference)[var_name] + else: + assert index is not None, 'Either var_name or index must be passed.' + variables_response = self.get_variables_response(variables_reference) + return pydevd_schema.Variable(**variables_response.body.variables[index]) + + def write_set_debugger_property( + self, + dont_trace_start_patterns=None, + dont_trace_end_patterns=None, + multi_threads_single_notification=None, + success=True + ): + dbg_request = self.write_request( + pydevd_schema.SetDebuggerPropertyRequest(pydevd_schema.SetDebuggerPropertyArguments( + dontTraceStartPatterns=dont_trace_start_patterns, + dontTraceEndPatterns=dont_trace_end_patterns, + multiThreadsSingleNotification=multi_threads_single_notification, + ))) + response = self.wait_for_response(dbg_request) + assert response.success == success + return response + + def write_set_pydevd_source_map(self, source, pydevd_source_maps, success=True): + dbg_request = self.write_request( + pydevd_schema.SetPydevdSourceMapRequest(pydevd_schema.SetPydevdSourceMapArguments( + source=source, + pydevdSourceMaps=pydevd_source_maps, + ))) + response = self.wait_for_response(dbg_request) + assert response.success == success + return response + + def write_initialize(self, success=True): + arguments = InitializeRequestArguments( + adapterID='pydevd_test_case', + ) + response = self.wait_for_response(self.write_request(InitializeRequest(arguments))) + assert response.success == success + if success: + process_id = response.body.kwargs['pydevd']['processId'] + assert isinstance(process_id, int) + return response + + def write_authorize(self, access_token, success=True): + from _pydevd_bundle._debug_adapter.pydevd_schema import PydevdAuthorizeArguments + from _pydevd_bundle._debug_adapter.pydevd_schema import PydevdAuthorizeRequest + arguments = PydevdAuthorizeArguments( + debugServerAccessToken=access_token, + ) + response = self.wait_for_response(self.write_request(PydevdAuthorizeRequest(arguments))) + assert response.success == success + return response + + def evaluate(self, expression, frameId=None, context=None, fmt=None, success=True, wait_for_response=True): + ''' + :param wait_for_response: + If True returns the response, otherwise returns the request. + + :returns EvaluateResponse + ''' + eval_request = self.write_request( + pydevd_schema.EvaluateRequest(pydevd_schema.EvaluateArguments( + expression, frameId=frameId, context=context, format=fmt))) + if wait_for_response: + eval_response = self.wait_for_response(eval_request) + assert eval_response.success == success + return eval_response + else: + return eval_request + + def write_terminate(self): + # Note: this currently terminates promptly, so, no answer is given. + self.write_request(TerminateRequest(arguments=TerminateArguments())) + + def write_get_source(self, source_reference, success=True): + response = self.wait_for_response(self.write_request( + pydevd_schema.SourceRequest(pydevd_schema.SourceArguments(source_reference)))) + assert response.success == success + return response + + +def test_case_json_logpoints(case_setup): + with case_setup.test_file('_debugger_case_change_breaks.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + break_2 = writer.get_line_index_with_content('break 2') + break_3 = writer.get_line_index_with_content('break 3') + json_facade.write_set_breakpoints( + [break_2, break_3], + line_to_info={ + break_2: {'log_message': 'var {repr("_a")} is {_a}'} + }) + json_facade.write_make_initial_run() + + # Should only print, not stop on logpoints. + messages = [] + while True: + output_event = json_facade.wait_for_json_message(OutputEvent) + msg = output_event.body.output + ctx = output_event.body.category + + if ctx == 'stdout': + msg = msg.strip() + if msg == "var '_a' is 2": + messages.append(msg) + + if len(messages) == 2: + break + + # Just one hit at the end (break 3). + json_facade.wait_for_thread_stopped(line=break_3) + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_json_logpoint_and_step_failure_ok(case_setup): + with case_setup.test_file('_debugger_case_hit_count.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + before_loop_line = writer.get_line_index_with_content('before loop line') + for_line = writer.get_line_index_with_content('for line') + print_line = writer.get_line_index_with_content('print line') + json_facade.write_set_breakpoints( + [before_loop_line, print_line], + line_to_info={ + print_line: {'log_message': 'var {repr("_a")} is {_a}'} + }) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=before_loop_line) + + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', line=for_line) + + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', line=print_line) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_json_logpoint_and_step_still_prints(case_setup): + with case_setup.test_file('_debugger_case_hit_count.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + before_loop_line = writer.get_line_index_with_content('before loop line') + print_line = writer.get_line_index_with_content('print line') + json_facade.write_set_breakpoints( + [before_loop_line, print_line], + line_to_info={ + print_line: {'log_message': 'var {repr("i")} is {i}'} + }) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=before_loop_line) + + for _i in range(4): + # I.e.: even when stepping we should have the messages. + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step') + + json_facade.write_continue() + + def accept_last_output_message(output_event): + return output_event.body.output.startswith("var 'i' is 9") + + json_facade.wait_for_json_message(OutputEvent, accept_last_output_message) + + def accept_message(output_event): + return output_event.body.output.startswith("var 'i' is ") + + assert len(json_facade.mark_messages(OutputEvent, accept_message)) == 10 + + writer.finished_ok = True + + +def test_case_json_hit_count_and_step(case_setup): + with case_setup.test_file('_debugger_case_hit_count.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + for_line = writer.get_line_index_with_content('for line') + print_line = writer.get_line_index_with_content('print line') + json_facade.write_set_breakpoints( + [print_line], + line_to_info={ + print_line: {'hit_condition': '5'} + }) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=print_line) + i_local_var = json_facade.get_local_var(json_hit.frame_id, 'i') # : :type i_local_var: pydevd_schema.Variable + assert i_local_var.value == '4' + + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', line=for_line) + + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', line=print_line) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_json_hit_condition_error(case_setup): + with case_setup.test_file('_debugger_case_hit_count.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + bp = writer.get_line_index_with_content('before loop line') + json_facade.write_set_breakpoints( + [bp], + line_to_info={ + bp: {'condition': 'range.range.range'} + }) + json_facade.write_make_initial_run() + + def accept_message(msg): + if msg.body.category == 'important': + if 'Error while evaluating expression in conditional breakpoint' in msg.body.output: + return True + return False + + json_facade.wait_for_json_message(OutputEvent, accept_message=accept_message) + + json_facade.wait_for_thread_stopped(line=bp) + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_process_event(case_setup): + with case_setup.test_file('_debugger_case_change_breaks.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + assert len(json_facade.mark_messages(ProcessEvent)) == 1 + json_facade.write_make_initial_run() + writer.finished_ok = True + + +def test_case_json_change_breaks(case_setup): + with case_setup.test_file('_debugger_case_change_breaks.py') as writer: + json_facade = JsonFacade(writer) + + break1_line = writer.get_line_index_with_content('break 1') + # Note: we can only write breakpoints after the launch is received. + json_facade.write_set_breakpoints(break1_line, success=False, send_launch_if_needed=False) + + json_facade.write_launch() + json_facade.write_set_breakpoints(break1_line) + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped(line=break1_line) + json_facade.write_set_breakpoints([]) + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_handled_exception_no_break_on_generator(case_setup): + with case_setup.test_file('_debugger_case_ignore_exceptions.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + json_facade.write_set_exception_breakpoints(['raised']) + json_facade.write_make_initial_run() + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Requires Python 3.') +def test_case_throw_exc_reason(case_setup): + + def check_test_suceeded_msg(self, stdout, stderr): + return 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + assert "raise RuntimeError('TEST SUCEEDED')" in stderr + assert "raise RuntimeError from e" in stderr + assert "raise Exception('another while handling')" in stderr + + with case_setup.test_file( + '_debugger_case_raise_with_cause.py', + EXPECTED_RETURNCODE=1, + check_test_suceeded_msg=check_test_suceeded_msg, + additional_output_checks=additional_output_checks + ) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=False) + json_facade.write_set_exception_breakpoints(['uncaught']) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped( + reason='exception', line=writer.get_line_index_with_content('raise RuntimeError from e')) + + exc_info_request = json_facade.write_request( + pydevd_schema.ExceptionInfoRequest(pydevd_schema.ExceptionInfoArguments(json_hit.thread_id))) + exc_info_response = json_facade.wait_for_response(exc_info_request) + + stack_frames = json_hit.stack_trace_response.body.stackFrames + # Note that the additional context doesn't really appear in the stack + # frames, only in the details. + assert [x['name'] for x in stack_frames] == ['foobar', ''] + + body = exc_info_response.body + assert body.exceptionId.endswith('RuntimeError') + assert body.description == 'another while handling' + assert normcase(body.details.kwargs['source']) == normcase(writer.TEST_FILE) + + # Check that we have all the lines (including the cause/context) in the stack trace. + import re + lines_and_names = re.findall(r',\sline\s(\d+),\sin\s([\w|<|>]+)', body.details.stackTrace) + assert lines_and_names == [ + ('16', 'foobar'), ('6', 'method'), ('2', 'method2'), ('18', 'foobar'), ('10', 'handle'), ('20', 'foobar'), ('23', '') + ] + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_handled_exception_breaks(case_setup): + with case_setup.test_file('_debugger_case_exceptions.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + json_facade.write_set_exception_breakpoints(['raised']) + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped( + reason='exception', line=writer.get_line_index_with_content('raise indexerror line')) + json_facade.write_continue() + + json_facade.wait_for_thread_stopped( + reason='exception', line=writer.get_line_index_with_content('reraise on method2')) + + # Clear so that the last one is not hit. + json_facade.write_set_exception_breakpoints([]) + json_facade.write_continue() + + writer.finished_ok = True + + +def _check_current_line(json_hit, current_line): + if not isinstance(current_line, (list, tuple)): + current_line = (current_line,) + for frame in json_hit.stack_trace_response.body.stackFrames: + if '(Current frame)' in frame['name']: + if frame['line'] not in current_line: + rep = json.dumps(json_hit.stack_trace_response.body.stackFrames, indent=4) + raise AssertionError('Expected: %s to be one of: %s\nFrames:\n%s.' % ( + frame['line'], + current_line, + rep + )) + + break + else: + rep = json.dumps(json_hit.stack_trace_response.body.stackFrames, indent=4) + raise AssertionError('Could not find (Current frame) in any frame name in: %s.' % ( + rep)) + + +@pytest.mark.parametrize('stop', [False, True]) +def test_case_user_unhandled_exception(case_setup, stop): + + def get_environ(self): + env = os.environ.copy() + + # Note that we put the working directory in the project roots to check that when expanded + # the relative file that doesn't exist is still considered a library file. + env["IDE_PROJECT_ROOTS"] = os.path.dirname(self.TEST_FILE) + os.pathsep + os.path.abspath('.') + return env + + if stop: + target = '_debugger_case_user_unhandled.py' + else: + target = '_debugger_case_user_unhandled2.py' + with case_setup.test_file(target, get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + json_facade.write_set_exception_breakpoints(['userUnhandled']) + json_facade.write_make_initial_run() + + if stop: + json_hit = json_facade.wait_for_thread_stopped( + reason='exception', line=writer.get_line_index_with_content('raise here'), file=target) + _check_current_line(json_hit, writer.get_line_index_with_content('stop here')) + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Only CPython 3.6 onwards') +@pytest.mark.parametrize('stop', [False, True]) +def test_case_user_unhandled_exception_coroutine(case_setup, stop): + if stop: + target = 'my_code/my_code_coroutine_user_unhandled.py' + else: + target = 'my_code/my_code_coroutine_user_unhandled_no_stop.py' + basename = os.path.basename(target) + + def additional_output_checks(writer, stdout, stderr): + if stop: + assert 'raise RuntimeError' in stderr + else: + assert 'raise RuntimeError' not in stderr + + with case_setup.test_file( + target, + EXPECTED_RETURNCODE=1 if stop else 0, + additional_output_checks=additional_output_checks + ) as writer: + json_facade = JsonFacade(writer) + + not_my_code_dir = debugger_unittest._get_debugger_test_file('not_my_code') + json_facade.write_launch( + rules=[ + {'path': not_my_code_dir, 'include':False}, + ] + ) + json_facade.write_set_exception_breakpoints(['userUnhandled']) + json_facade.write_make_initial_run() + + if stop: + stop_line = writer.get_line_index_with_content('stop here 1') + current_line = stop_line + + json_hit = json_facade.wait_for_thread_stopped( + reason='exception', line=stop_line, file=basename) + _check_current_line(json_hit, current_line) + + json_facade.write_continue() + + current_line = writer.get_line_index_with_content('stop here 2') + json_hit = json_facade.wait_for_thread_stopped( + reason='exception', line=stop_line, file=basename) + _check_current_line(json_hit, current_line) + + json_facade.write_continue() + + current_line = ( + writer.get_line_index_with_content('stop here 3a'), + writer.get_line_index_with_content('stop here 3b'), + ) + + json_hit = json_facade.wait_for_thread_stopped( + reason='exception', line=stop_line, file=basename) + _check_current_line(json_hit, current_line) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_user_unhandled_exception_dont_stop(case_setup): + + with case_setup.test_file( + 'my_code/my_code_exception_user_unhandled.py',) as writer: + json_facade = JsonFacade(writer) + + not_my_code_dir = debugger_unittest._get_debugger_test_file('not_my_code') + json_facade.write_launch( + debugStdLib=True, + rules=[ + {'path': not_my_code_dir, 'include':False}, + ] + ) + + json_facade.write_set_exception_breakpoints(['userUnhandled']) + json_facade.write_make_initial_run() + + writer.finished_ok = True + + +def test_case_user_unhandled_exception_stop_on_yield(case_setup, pyfile): + + @pyfile + def case_error_on_yield(): + + def on_yield(): + yield + raise AssertionError() # raise here + + try: + for _ in on_yield(): # stop here + pass + except: + print('TEST SUCEEDED!') + raise + + def get_environ(self): + env = os.environ.copy() + + # Note that we put the working directory in the project roots to check that when expanded + # the relative file that doesn't exist is still considered a library file. + env["IDE_PROJECT_ROOTS"] = os.path.dirname(self.TEST_FILE) + os.pathsep + os.path.abspath('.') + return env + + def additional_output_checks(writer, stdout, stderr): + assert 'raise AssertionError' in stderr + + with case_setup.test_file( + case_error_on_yield, + get_environ=get_environ, + EXPECTED_RETURNCODE=1, + additional_output_checks=additional_output_checks) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + json_facade.write_set_exception_breakpoints(['userUnhandled']) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped( + reason='exception', line=writer.get_line_index_with_content('raise here'), file=case_error_on_yield) + _check_current_line(json_hit, writer.get_line_index_with_content('stop here')) + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.parametrize('target', [ + 'absolute', + 'relative', + ]) +@pytest.mark.parametrize('just_my_code', [ + True, + False, + ]) +def test_case_unhandled_exception_just_my_code(case_setup, target, just_my_code): + + def check_test_suceeded_msg(writer, stdout, stderr): + # Don't call super (we have an unhandled exception in the stack trace). + return 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + if 'call_exception_in_exec()' not in stderr: + raise AssertionError('Expected test to have an unhandled exception.\nstdout:\n%s\n\nstderr:\n%s' % ( + stdout, stderr)) + + def get_environ(self): + env = os.environ.copy() + + # Note that we put the working directory in the project roots to check that when expanded + # the relative file that doesn't exist is still considered a library file. + env["IDE_PROJECT_ROOTS"] = os.path.dirname(self.TEST_FILE) + os.pathsep + os.path.abspath('.') + return env + + def update_command_line_args(writer, args): + ret = debugger_unittest.AbstractWriterThread.update_command_line_args(writer, args) + if target == 'absolute': + if sys.platform == 'win32': + ret.append('c:/temp/folder/my_filename.pyx') + else: + ret.append('/temp/folder/my_filename.pyx') + + elif target == 'relative': + ret.append('folder/my_filename.pyx') + + else: + raise AssertionError('Unhandled case: %s' % (target,)) + return args + + target_filename = '_debugger_case_unhandled_just_my_code.py' + with case_setup.test_file( + target_filename, + check_test_suceeded_msg=check_test_suceeded_msg, + additional_output_checks=additional_output_checks, + update_command_line_args=update_command_line_args, + get_environ=get_environ, + EXPECTED_RETURNCODE=1, + ) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=just_my_code) + json_facade.write_set_exception_breakpoints(['uncaught']) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(reason='exception') + frames = json_hit.stack_trace_response.body.stackFrames + if just_my_code: + assert len(frames) == 1 + assert frames[0]['source']['path'].endswith(target_filename) + else: + assert len(frames) > 1 + assert frames[0]['source']['path'].endswith('my_filename.pyx') + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Python 3.6 onwards required for test.') +def test_case_stop_async_iteration_exception(case_setup): + + def get_environ(self): + env = os.environ.copy() + env["IDE_PROJECT_ROOTS"] = os.path.dirname(self.TEST_FILE) + os.pathsep + os.path.abspath('.') + return env + + with case_setup.test_file( + '_debugger_case_stop_async_iteration.py', + get_environ=get_environ, + ) as writer: + json_facade = JsonFacade(writer) + + # We don't want to hit common library exceptions here. + json_facade.write_launch(justMyCode=True) + + json_facade.write_set_exception_breakpoints(['raised']) + json_facade.write_make_initial_run() + + # Just making sure that no exception breakpoints are hit. + + writer.finished_ok = True + + +@pytest.mark.parametrize('target_file', [ + '_debugger_case_unhandled_exceptions.py', + '_debugger_case_unhandled_exceptions_custom.py', + ]) +def test_case_unhandled_exception(case_setup, target_file): + + def check_test_suceeded_msg(writer, stdout, stderr): + # Don't call super (we have an unhandled exception in the stack trace). + return 'TEST SUCEEDED' in ''.join(stdout) and 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + if 'raise MyError' not in stderr and 'raise Exception' not in stderr: + raise AssertionError('Expected test to have an unhandled exception.\nstdout:\n%s\n\nstderr:\n%s' % ( + stdout, stderr)) + + with case_setup.test_file( + target_file, + check_test_suceeded_msg=check_test_suceeded_msg, + additional_output_checks=additional_output_checks, + EXPECTED_RETURNCODE=1, + ) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + json_facade.write_set_exception_breakpoints(['uncaught']) + json_facade.write_make_initial_run() + + line_in_thread1 = writer.get_line_index_with_content('in thread 1') + line_in_thread2 = writer.get_line_index_with_content('in thread 2') + line_in_main = writer.get_line_index_with_content('in main') + json_facade.wait_for_thread_stopped( + reason='exception', line=(line_in_thread1, line_in_thread2), file=target_file) + json_facade.write_continue() + + json_facade.wait_for_thread_stopped( + reason='exception', line=(line_in_thread1, line_in_thread2), file=target_file) + json_facade.write_continue() + + json_facade.wait_for_thread_stopped( + reason='exception', line=line_in_main, file=target_file) + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('target_file', [ + '_debugger_case_unhandled_exceptions_generator.py', + '_debugger_case_unhandled_exceptions_listcomp.py', + ]) +def test_case_unhandled_exception_generator(case_setup, target_file): + + def check_test_suceeded_msg(writer, stdout, stderr): + # Don't call super (we have an unhandled exception in the stack trace). + return 'TEST SUCEEDED' in ''.join(stdout) and 'TEST SUCEEDED' in ''.join(stderr) + + def additional_output_checks(writer, stdout, stderr): + if 'ZeroDivisionError' not in stderr: + raise AssertionError('Expected test to have an unhandled exception.\nstdout:\n%s\n\nstderr:\n%s' % ( + stdout, stderr)) + + with case_setup.test_file( + target_file, + check_test_suceeded_msg=check_test_suceeded_msg, + additional_output_checks=additional_output_checks, + EXPECTED_RETURNCODE=1, + ) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + json_facade.write_set_exception_breakpoints(['uncaught']) + json_facade.write_make_initial_run() + + line_in_main = writer.get_line_index_with_content('exc line') + + json_hit = json_facade.wait_for_thread_stopped( + reason='exception', line=line_in_main, file=target_file) + frames = json_hit.stack_trace_response.body.stackFrames + json_facade.write_continue() + + if 'generator' in target_file: + expected_frame_names = ['', 'f', ''] + else: + expected_frame_names = ['', 'f', ''] + + frame_names = [f['name'] for f in frames] + assert frame_names == expected_frame_names + + writer.finished_ok = True + + +def test_case_sys_exit_unhandled_exception(case_setup): + + with case_setup.test_file('_debugger_case_sysexit.py', EXPECTED_RETURNCODE=1) as writer: + json_facade = JsonFacade(writer) + json_facade.write_set_exception_breakpoints(['uncaught']) + json_facade.write_make_initial_run() + + break_line = writer.get_line_index_with_content('sys.exit(1)') + json_facade.wait_for_thread_stopped( + reason='exception', line=break_line) + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('break_on_system_exit_zero', [True, False]) +@pytest.mark.parametrize('target', ['_debugger_case_sysexit_0.py', '_debugger_case_sysexit_none.py']) +def test_case_sys_exit_0_unhandled_exception(case_setup, break_on_system_exit_zero, target): + + with case_setup.test_file(target, EXPECTED_RETURNCODE=0) as writer: + json_facade = JsonFacade(writer) + kwargs = {} + if break_on_system_exit_zero: + kwargs = {'breakOnSystemExitZero': True} + json_facade.write_launch(**kwargs) + json_facade.write_set_exception_breakpoints(['uncaught']) + json_facade.write_make_initial_run() + + break_line = writer.get_line_index_with_content('sys.exit(') + if break_on_system_exit_zero: + json_facade.wait_for_thread_stopped( + reason='exception', line=break_line) + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('break_on_system_exit_zero', [True, False]) +def test_case_sys_exit_0_handled_exception(case_setup, break_on_system_exit_zero): + + with case_setup.test_file('_debugger_case_sysexit_0.py', EXPECTED_RETURNCODE=0) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch( + debugOptions=['BreakOnSystemExitZero'] if break_on_system_exit_zero else [], + ) + json_facade.write_set_exception_breakpoints(['raised']) + json_facade.write_make_initial_run() + + break_line = writer.get_line_index_with_content('sys.exit(0)') + break_main_line = writer.get_line_index_with_content('call_main_line') + if break_on_system_exit_zero: + json_facade.wait_for_thread_stopped( + reason='exception', line=break_line) + json_facade.write_continue() + + json_facade.wait_for_thread_stopped( + reason='exception', line=break_main_line) + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_handled_exception_breaks_by_type(case_setup): + with case_setup.test_file('_debugger_case_exceptions.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + json_facade.write_set_exception_breakpoints(exception_options=[ + ExceptionOptions(breakMode='always', path=[ + {'names': ['Python Exceptions']}, + {'names': ['IndexError']}, + ]) + ]) + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped( + reason='exception', line=writer.get_line_index_with_content('raise indexerror line')) + + # Deal only with RuntimeErorr now. + json_facade.write_set_exception_breakpoints(exception_options=[ + ExceptionOptions(breakMode='always', path=[ + {'names': ['Python Exceptions']}, + {'names': ['RuntimeError']}, + ]) + ]) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_json_protocol(case_setup): + with case_setup.test_file('_debugger_case_print.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + break_line = writer.get_line_index_with_content('Break here') + json_facade.write_set_breakpoints(break_line) + json_facade.write_make_initial_run() + + json_facade.wait_for_json_message(ThreadEvent, lambda event: event.body.reason == 'started') + + json_facade.wait_for_thread_stopped(line=break_line) + + # : :type response: ThreadsResponse + response = json_facade.write_list_threads() + assert len(response.body.threads) == 1 + assert next(iter(response.body.threads))['name'] == 'MainThread' + + # Removes breakpoints and proceeds running. + json_facade.write_disconnect() + + writer.finished_ok = True + + +def test_case_started_exited_threads_protocol(case_setup): + with case_setup.test_file('_debugger_case_thread_started_exited.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + break_line = writer.get_line_index_with_content('Break here') + json_facade.write_set_breakpoints(break_line) + + json_facade.write_make_initial_run() + + _stopped_event = json_facade.wait_for_json_message(StoppedEvent) + started_events = json_facade.mark_messages(ThreadEvent, lambda x: x.body.reason == 'started') + exited_events = json_facade.mark_messages(ThreadEvent, lambda x: x.body.reason == 'exited') + assert len(started_events) == 4 + assert len(exited_events) == 3 # Main is still running. + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_path_translation_not_skipped(case_setup): + import site + sys_folder = None + if hasattr(site, 'getusersitepackages'): + sys_folder = site.getusersitepackages() + + if not sys_folder and hasattr(site, 'getsitepackages'): + sys_folder = site.getsitepackages() + + if not sys_folder: + sys_folder = sys.prefix + + if isinstance(sys_folder, (list, tuple)): + sys_folder = next(iter(sys_folder)) + + with case_setup.test_file('my_code/my_code.py') as writer: + json_facade = JsonFacade(writer) + + # We need to set up path mapping to enable source references. + my_code = debugger_unittest._get_debugger_test_file('my_code') + + json_facade.write_launch( + justMyCode=False, + pathMappings=[{ + 'localRoot': sys_folder, + 'remoteRoot': my_code, + }] + ) + + bp_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints( + bp_line, + filename=os.path.join(sys_folder, 'my_code.py'), + ) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=bp_line) + + stack_frame = json_hit.stack_trace_response.body.stackFrames[-1] + assert stack_frame['source']['path'] == os.path.join(sys_folder, 'my_code.py') + for stack_frame in json_hit.stack_trace_response.body.stackFrames: + assert stack_frame['source']['sourceReference'] == 0 + json_facade.write_continue() + + writer.finished_ok = True + + +def test_case_exclude_double_step(case_setup): + with case_setup.test_file('my_code/my_code_double_step.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch( + justMyCode=False, # i.e.: exclude through rules and not my code + rules=[ + {'path': '**/other_noop.py', 'include':False}, + ] + ) + + break_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(break_line) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=break_line) + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', file='my_code_double_step.py', line=break_line + 1) + + json_facade.write_continue() + writer.finished_ok = True + + +def test_case_update_rules(case_setup): + with case_setup.test_file('my_code/my_code.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch( + rules=[ + {'path': '**/other.py', 'include':False}, + ] + ) + + break_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(break_line) + json_facade.write_make_initial_run() + + json_facade.wait_for_json_message(ThreadEvent, lambda event: event.body.reason == 'started') + + json_hit = json_facade.wait_for_thread_stopped(line=break_line) + json_facade.reset_sent_launch_or_attach() + json_facade.write_launch( + rules=[ + {'path': '**/other.py', 'include':True}, + ] + ) + json_facade.write_step_in(json_hit.thread_id) + # Not how we stoppen in the file that wasn't initially included. + json_hit = json_facade.wait_for_thread_stopped('step', name='call_me_back1') + + json_facade.reset_sent_launch_or_attach() + json_facade.write_launch( + rules=[ + {'path': '**/other.py', 'include':False}, + ] + ) + json_facade.write_step_in(json_hit.thread_id) + # Not how we go back to the callback and not to the `call_me_back1` because + # `call_me_back1` is now excluded again. + json_hit = json_facade.wait_for_thread_stopped('step', name='callback1') + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.parametrize("custom_setup", [ + 'set_exclude_launch_module_full', + 'set_exclude_launch_module_prefix', + 'set_exclude_launch_path_match_filename', + 'set_exclude_launch_path_match_folder', + 'set_just_my_code', + 'set_just_my_code_and_include', +]) +def test_case_skipping_filters(case_setup, custom_setup): + with case_setup.test_file('my_code/my_code.py') as writer: + json_facade = JsonFacade(writer) + + expect_just_my_code = False + if custom_setup == 'set_exclude_launch_path_match_filename': + json_facade.write_launch( + justMyCode=False, + rules=[ + {'path': '**/other.py', 'include':False}, + ] + ) + + elif custom_setup == 'set_exclude_launch_path_match_folder': + not_my_code_dir = debugger_unittest._get_debugger_test_file('not_my_code') + json_facade.write_launch( + debugStdLib=True, + rules=[ + {'path': not_my_code_dir, 'include':False}, + ] + ) + + other_filename = os.path.join(not_my_code_dir, 'other.py') + response = json_facade.write_set_breakpoints(1, filename=other_filename, verified=False) + assert response.body.breakpoints == [ + {'verified': False, 'id': 0, 'message': 'Breakpoint in file excluded by filters.', 'source': {'path': other_filename}, 'line': 1}] + # Note: there's actually a use-case where we'd hit that breakpoint even if it was excluded + # by filters, so, we must actually clear it afterwards (the use-case is that when we're + # stepping into the context with the breakpoint we wouldn't skip it). + json_facade.write_set_breakpoints([], filename=other_filename) + + other_filename = os.path.join(not_my_code_dir, 'file_that_does_not_exist.py') + response = json_facade.write_set_breakpoints(1, filename=other_filename, verified=False) + assert response.body.breakpoints == [ + {'verified': False, 'id': 1, 'message': 'Breakpoint in file that does not exist.', 'source': {'path': other_filename}, 'line': 1}] + + elif custom_setup == 'set_exclude_launch_module_full': + json_facade.write_launch( + debugOptions=['DebugStdLib'], + rules=[ + {'module': 'not_my_code.other', 'include':False}, + ] + ) + + elif custom_setup == 'set_exclude_launch_module_prefix': + json_facade.write_launch( + debugOptions=['DebugStdLib'], + rules=[ + {'module': 'not_my_code', 'include':False}, + ] + ) + + elif custom_setup == 'set_just_my_code': + expect_just_my_code = True + writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('my_code')]) + json_facade.write_launch(debugOptions=[]) + + not_my_code_dir = debugger_unittest._get_debugger_test_file('not_my_code') + other_filename = os.path.join(not_my_code_dir, 'other.py') + response = json_facade.write_set_breakpoints( + 33, filename=other_filename, verified=False, expected_lines_in_response=[14]) + assert response.body.breakpoints == [{ + 'verified': False, + 'id': 0, + 'message': 'Breakpoint in file excluded by filters.\nNote: may be excluded because of \"justMyCode\" option (default == true).Try setting \"justMyCode\": false in the debug configuration (e.g., launch.json).\n', + 'source': {'path': other_filename}, + 'line': 14 + }] + elif custom_setup == 'set_just_my_code_and_include': + expect_just_my_code = True + # I.e.: nothing in my_code (add it with rule). + writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('launch')]) + json_facade.write_launch( + debugOptions=[], + rules=[ + {'module': '__main__', 'include':True}, + ] + ) + + else: + raise AssertionError('Unhandled: %s' % (custom_setup,)) + + break_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(break_line) + json_facade.write_make_initial_run() + + json_facade.wait_for_json_message(ThreadEvent, lambda event: event.body.reason == 'started') + + json_hit = json_facade.wait_for_thread_stopped(line=break_line) + + json_facade.write_step_in(json_hit.thread_id) + + json_hit = json_facade.wait_for_thread_stopped('step', name='callback1') + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: 'Frame skipped from debugging during step-in.' in output_event.body.output) + assert len(messages) == 1 + body = next(iter(messages)).body + found_just_my_code = 'Note: may have been skipped because of \"justMyCode\" option (default == true)' in body.output + + assert found_just_my_code == expect_just_my_code + assert body.category == 'important' + + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='callback2') + + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='callback1') + + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='') + + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='') + + json_facade.write_step_next(json_hit.thread_id) + + if IS_JYTHON: + json_facade.write_continue() + + # Check that it's sent only once. + assert len(json_facade.mark_messages( + OutputEvent, lambda output_event: 'Frame skipped from debugging during step-in.' in output_event.body.output)) == 0 + + writer.finished_ok = True + + +def test_case_completions_json(case_setup): + with case_setup.test_file('_debugger_case_completions.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + first_hit = None + for i in range(2): + json_hit = json_facade.wait_for_thread_stopped() + + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + if i == 0: + first_hit = json_hit + + completions_arguments = pydevd_schema.CompletionsArguments( + 'dict.', 6, frameId=json_hit.frame_id, line=0) + completions_request = json_facade.write_request( + pydevd_schema.CompletionsRequest(completions_arguments)) + + response = json_facade.wait_for_response(completions_request) + assert response.success + labels = [x['label'] for x in response.body.targets] + assert set(labels).issuperset(set(['__contains__', 'items', 'keys', 'values'])) + + completions_arguments = pydevd_schema.CompletionsArguments( + 'dict.item', 10, frameId=json_hit.frame_id) + completions_request = json_facade.write_request( + pydevd_schema.CompletionsRequest(completions_arguments)) + + response = json_facade.wait_for_response(completions_request) + assert response.success + if IS_JYTHON: + assert response.body.targets == [ + {'start': 5, 'length': 4, 'type': 'keyword', 'label': 'items'}] + else: + assert response.body.targets == [ + {'start': 5, 'length': 4, 'type': 'function', 'label': 'items'}] + + if i == 1: + # Check with a previously existing frameId. + assert first_hit.frame_id != json_hit.frame_id + completions_arguments = pydevd_schema.CompletionsArguments( + 'dict.item', 10, frameId=first_hit.frame_id) + completions_request = json_facade.write_request( + pydevd_schema.CompletionsRequest(completions_arguments)) + + response = json_facade.wait_for_response(completions_request) + assert not response.success + assert response.message == 'Thread to get completions seems to have resumed already.' + + # Check with a never frameId which never existed. + completions_arguments = pydevd_schema.CompletionsArguments( + 'dict.item', 10, frameId=99999) + completions_request = json_facade.write_request( + pydevd_schema.CompletionsRequest(completions_arguments)) + + response = json_facade.wait_for_response(completions_request) + assert not response.success + assert response.message.startswith('Wrong ID sent from the client:') + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_modules(case_setup): + with case_setup.test_file('_debugger_case_local_variables.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break 2 here')) + json_facade.write_make_initial_run() + + stopped_event = json_facade.wait_for_json_message(StoppedEvent) + thread_id = stopped_event.body.threadId + + json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=thread_id))) + + json_facade.wait_for_json_message(ModuleEvent) + + # : :type response: ModulesResponse + # : :type modules_response_body: ModulesResponseBody + response = json_facade.wait_for_response(json_facade.write_request( + pydevd_schema.ModulesRequest(pydevd_schema.ModulesArguments()))) + modules_response_body = response.body + assert len(modules_response_body.modules) == 1 + module = next(iter(modules_response_body.modules)) + assert module['name'] == '__main__' + assert module['path'].endswith('_debugger_case_local_variables.py') + + json_facade.write_continue() + writer.finished_ok = True + + +def test_dict_ordered(case_setup): + with case_setup.test_file('_debugger_case_odict.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + + variables_references = variables_response.body.variables + for dct in variables_references: + if dct['name'] == 'odict': + break + else: + raise AssertionError('Expected to find "odict".') + ref = dct['variablesReference'] + + assert isinstance(ref, int_types) + # : :type variables_response: VariablesResponse + + variables_response = json_facade.get_variables_response(ref) + assert [(d['name'], d['value']) for d in variables_response.body.variables if (not d['name'].startswith('_OrderedDict')) and (d['name'] not in DAPGrouper.SCOPES_SORTED)] == [ + ('4', "'first'"), ('3', "'second'"), ('2', "'last'"), (GENERATED_LEN_ATTR_NAME, '3')] + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Putting unicode on frame vars does not work on Jython.') +def test_stack_and_variables_dict(case_setup): + with case_setup.test_file('_debugger_case_local_variables.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break 2 here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + + variables_references = json_facade.pop_variables_reference(variables_response.body.variables) + dict_variable_reference = variables_references[2] + assert isinstance(dict_variable_reference, int_types) + # : :type variables_response: VariablesResponse + + expected_unicode = { + 'name': u'\u16A0', + 'value': "'\u16a1'", + 'type': 'str', + 'presentationHint': {'attributes': ['rawString']}, + 'evaluateName': u'\u16A0', + } + assert variables_response.body.variables == [ + {'name': 'variable_for_test_1', 'value': '10', 'type': 'int', 'evaluateName': 'variable_for_test_1'}, + {'name': 'variable_for_test_2', 'value': '20', 'type': 'int', 'evaluateName': 'variable_for_test_2'}, + {'name': 'variable_for_test_3', 'value': "{'a': 30, 'b': 20}", 'type': 'dict', 'evaluateName': 'variable_for_test_3'}, + expected_unicode + ] + + variables_response = json_facade.get_variables_response(dict_variable_reference) + check = [x for x in variables_response.body.variables if x['name'] not in DAPGrouper.SCOPES_SORTED] + assert check == [ + {'name': "'a'", 'value': '30', 'type': 'int', 'evaluateName': "variable_for_test_3['a']", 'variablesReference': 0 }, + {'name': "'b'", 'value': '20', 'type': 'int', 'evaluateName': "variable_for_test_3['b']", 'variablesReference': 0}, + {'name': GENERATED_LEN_ATTR_NAME, 'value': '2', 'type': 'int', 'evaluateName': 'len(variable_for_test_3)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}} + ] + + json_facade.write_continue() + writer.finished_ok = True + + +def test_variables_with_same_name(case_setup): + with case_setup.test_file('_debugger_case_variables_with_same_name.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + + variables_references = json_facade.pop_variables_reference(variables_response.body.variables) + dict_variable_reference = variables_references[0] + assert isinstance(dict_variable_reference, int_types) + # : :type variables_response: VariablesResponse + + assert variables_response.body.variables == [ + {'name': 'td', 'value': "{foo: 'bar', gad: 'zooks', foo: 'bur'}", 'type': 'dict', 'evaluateName': 'td'} + ] + + dict_variables_response = json_facade.get_variables_response(dict_variable_reference) + # Note that we don't have the evaluateName because it's not possible to create a key + # from the user object to actually get its value from the dict in this case. + variables = dict_variables_response.body.variables[:] + + found_foo = False + found_foo_with_id = False + for v in variables: + if v['name'].startswith('foo'): + if not found_foo: + assert v['name'] == 'foo' + found_foo = True + else: + assert v['name'].startswith('foo (id: ') + v['name'] = 'foo' + found_foo_with_id = True + + assert found_foo + assert found_foo_with_id + + def compute_key(entry): + return (entry['name'], entry['value']) + + # Sort because the order may be different on Py2/Py3. + assert sorted(variables, key=compute_key) == sorted([ + { + 'name': 'foo', + 'value': "'bar'", + 'type': 'str', + 'variablesReference': 0, + 'presentationHint': {'attributes': ['rawString']} + }, + + { + # 'name': 'foo (id: 2699272929584)', In the code above we changed this + # to 'name': 'foo' for the comparisson. + 'name': 'foo', + 'value': "'bur'", + 'type': 'str', + 'variablesReference': 0, + 'presentationHint': {'attributes': ['rawString']} + }, + + { + 'name': 'gad', + 'value': "'zooks'", + 'type': 'str', + 'variablesReference': 0, + 'presentationHint': {'attributes': ['rawString']} + }, + + { + 'name': 'len()', + 'value': '3', + 'type': 'int', + 'evaluateName': 'len(td)', + 'variablesReference': 0, + 'presentationHint': {'attributes': ['readOnly']} + }, + ], key=compute_key) + + json_facade.write_continue() + writer.finished_ok = True + + +def test_hasattr_failure(case_setup): + with case_setup.test_file('_debugger_case_hasattr_crash.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + + for variable in variables_response.body.variables: + if variable['evaluateName'] == 'obj': + break + else: + raise AssertionError('Did not find "obj" in %s' % (variables_response.body.variables,)) + + evaluate_response = json_facade.evaluate('obj', json_hit.frame_id, context='hover') + evaluate_response_body = evaluate_response.body.to_dict() + assert evaluate_response_body['result'] == 'An exception was raised: RuntimeError()' + + json_facade.evaluate('not_there', json_hit.frame_id, context='hover', success=False) + json_facade.evaluate('not_there', json_hit.frame_id, context='watch', success=False) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_getattr_warning(case_setup): + with case_setup.test_file('_debugger_case_warnings.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + + for variable in variables_response.body.variables: + if variable['evaluateName'] == 'obj': + break + else: + raise AssertionError('Did not find "obj" in %s' % (variables_response.body.variables,)) + + json_facade.evaluate('obj', json_hit.frame_id, context='hover') + json_facade.evaluate('not_there', json_hit.frame_id, context='hover', success=False) + json_facade.evaluate('not_there', json_hit.frame_id, context='watch', success=False) + + json_facade.write_continue() + + # i.e.: the test will fail if anything is printed to stderr! + writer.finished_ok = True + + +def test_warning_on_repl(case_setup): + + def additional_output_checks(writer, stdout, stderr): + assert "WarningCalledOnRepl" in stderr + + with case_setup.test_file( + '_debugger_case_evaluate.py', + additional_output_checks=additional_output_checks + ) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + # We want warnings from the in evaluate in the repl (but not hover/watch). + json_facade.evaluate( + 'import warnings; warnings.warn("WarningCalledOnRepl")', json_hit.frame_id, context='repl') + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_evaluate_numpy(case_setup, pyfile): + try: + import numpy + except ImportError: + pytest.skip('numpy not available') + + @pyfile + def numpy_small_array_file(): + import numpy + + test_array = numpy.array(2) + + print('TEST SUCEEDED') # break here + + with case_setup.test_file(numpy_small_array_file) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=False) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + + for variable in variables_response.body.variables: + if variable['evaluateName'] == 'test_array': + break + else: + raise AssertionError('Did not find "test_array" in %s' % (variables_response.body.variables,)) + + evaluate_response = json_facade.evaluate('test_array', json_hit.frame_id, context='repl') + + variables_response = json_facade.get_variables_response(evaluate_response.body.variablesReference) + + check = [dict([(variable['name'], variable['value'])]) for variable in variables_response.body.variables] + assert check in ( + [ + {'special variables': ''}, + {'dtype': "dtype('int32')"}, + {'max': '2'}, + {'min': '2'}, + {'shape': '()'}, + {'size': '1'} + ], + [ + {'special variables': ''}, + {'dtype': "dtype('int64')"}, + {'max': '2'}, + {'min': '2'}, + {'shape': '()'}, + {'size': '1'} + ], + ) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_evaluate_name_mangling(case_setup, pyfile): + + @pyfile + def target(): + + class SomeObj(object): + + def __init__(self): + self.__value = 10 + print('here') # Break here + + SomeObj() + + print('TEST SUCEEDED') + + with case_setup.test_file(target) as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_launch(justMyCode=False) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + # Check eval with a properly indented block + evaluate_response = json_facade.evaluate( + 'self.__value', + frameId=json_hit.frame_id, + context="repl", + ) + + assert evaluate_response.body.result == '10' + json_facade.write_continue() + writer.finished_ok = True + + +def test_evaluate_no_name_mangling(case_setup): + + with case_setup.test_file('_debugger_case_local_variables2.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + # Check eval with a properly indented block + evaluate_response = json_facade.evaluate( + 'x = "_"', frameId=json_hit.frame_id, context="repl") + assert not evaluate_response.body.result + + evaluate_response = json_facade.evaluate( + 'x', frameId=json_hit.frame_id, context="repl") + assert evaluate_response.body.result == "'_'" + + evaluate_response = json_facade.evaluate( + 'y = "__"', frameId=json_hit.frame_id, context="repl") + assert not evaluate_response.body.result + + evaluate_response = json_facade.evaluate( + 'y', frameId=json_hit.frame_id, context="repl") + assert evaluate_response.body.result == "'__'" + + evaluate_response = json_facade.evaluate( + 'None', json_hit.frame_id, context='repl') + assert not evaluate_response.body.result + + json_facade.write_continue() + writer.finished_ok = True + + +def test_evaluate_block_repl(case_setup): + + with case_setup.test_file('_debugger_case_local_variables2.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + # Check eval with a properly indented block + json_facade.evaluate( + "for i in range(2):\n print('var%s' % i)", + frameId=json_hit.frame_id, + context="repl", + ) + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: u'var0' in output_event.body.output) + assert len(messages) == 1 + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: u'var1' in output_event.body.output) + assert len(messages) == 1 + + # Check eval with a block that needs to be dedented + json_facade.evaluate( + " for i in range(2):\n print('foo%s' % i)", + frameId=json_hit.frame_id, + context="repl", + ) + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: u'foo0' in output_event.body.output) + assert len(messages) == 1 + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: u'foo1' in output_event.body.output) + assert len(messages) == 1 + + json_facade.write_continue() + writer.finished_ok = True + + +def test_evaluate_block_clipboard(case_setup, pyfile): + + @pyfile + def target(): + MAX_LIMIT = 65538 + + class SomeObj(object): + + def __str__(self): + return var1 + + __repr__ = __str__ + + var1 = 'a' * 80000 + var2 = 20000 + var3 = SomeObj() + + print('TEST SUCEEDED') # Break here + + def verify(evaluate_response): + # : :type evaluate_response: EvaluateResponse + assert len(evaluate_response.body.result) >= 80000 + assert '...' not in evaluate_response.body.result + assert set(evaluate_response.body.result).issubset(set(['a', "'"])) + + with case_setup.test_file(target) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + evaluate_response = json_facade.evaluate( + 'var1', + frameId=json_hit.frame_id, + context='clipboard', + ) + verify(evaluate_response) + + evaluate_response = json_facade.evaluate( + 'var2', + frameId=json_hit.frame_id, + context='clipboard', + fmt={'hex': True} + ) + assert evaluate_response.body.result == "0x4e20" + + evaluate_response = json_facade.evaluate( + 'var3', + frameId=json_hit.frame_id, + context='clipboard', + ) + verify(evaluate_response) + + json_facade.write_continue() + writer.finished_ok = True + + +def test_exception_on_dir(case_setup): + with case_setup.test_file('_debugger_case_dir_exception.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + + variables_references = json_facade.pop_variables_reference(variables_response.body.variables) + variables_response = json_facade.get_variables_response(variables_references[0]) + assert variables_response.body.variables == [ + {'variablesReference': 0, 'type': 'int', 'evaluateName': 'self.__dict__[var1]', 'name': 'var1', 'value': '10'}] + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.parametrize('scenario', [ + 'step_in', + 'step_next', + 'step_out', +]) +@pytest.mark.parametrize('asyncio', [True, False]) +def test_return_value_regular(case_setup, scenario, asyncio): + with case_setup.test_file('_debugger_case_return_value.py' if not asyncio else '_debugger_case_return_value_asyncio.py') as writer: + json_facade = JsonFacade(writer) + + break_line = writer.get_line_index_with_content('break here') + json_facade.write_launch(debugOptions=['ShowReturnValue']) + json_facade.write_set_breakpoints(break_line) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + if scenario == 'step_next': + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='main', line=break_line + 1) + + elif scenario == 'step_in': + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='method1') + + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='main') + + elif scenario == 'step_out': + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='method1') + + json_facade.write_step_out(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='main') + + else: + raise AssertionError('unhandled scenario: %s' % (scenario,)) + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + return_variables = json_facade.filter_return_variables(variables_response.body.variables) + assert return_variables == [{ + 'name': '(return) method1', + 'value': '1', + 'type': 'int', + 'evaluateName': "__pydevd_ret_val_dict['method1']", + 'presentationHint': {'attributes': ['readOnly']}, + 'variablesReference': 0, + }] + + json_facade.write_continue() + writer.finished_ok = True + + +def test_stack_and_variables_set_and_list(case_setup): + with case_setup.test_file('_debugger_case_local_variables2.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + variables_response = json_facade.get_variables_response(json_hit.frame_id) + + variables_references = json_facade.pop_variables_reference(variables_response.body.variables) + expected_set = "{'a'}" + assert variables_response.body.variables == [ + {'type': 'list', 'evaluateName': 'variable_for_test_1', 'name': 'variable_for_test_1', 'value': "['a', 'b']"}, + {'type': 'set', 'evaluateName': 'variable_for_test_2', 'name': 'variable_for_test_2', 'value': expected_set} + ] + + variables_response = json_facade.get_variables_response(variables_references[0]) + cleaned_vars = _clear_groups(variables_response.body.variables) + if IS_PYPY: + # Functions are not found in PyPy. + assert cleaned_vars.groups_found == set([DAPGrouper.SCOPE_SPECIAL_VARS]) + else: + assert cleaned_vars.groups_found == set([DAPGrouper.SCOPE_SPECIAL_VARS, DAPGrouper.SCOPE_FUNCTION_VARS]) + assert cleaned_vars.variables == [{ + u'name': u'0', + u'type': u'str', + u'value': u"'a'", + u'presentationHint': {u'attributes': [u'rawString']}, + u'evaluateName': u'variable_for_test_1[0]', + u'variablesReference': 0, + }, + { + u'name': u'1', + u'type': u'str', + u'value': u"'b'", + u'presentationHint': {u'attributes': [u'rawString']}, + u'evaluateName': u'variable_for_test_1[1]', + u'variablesReference': 0, + }, + { + u'name': GENERATED_LEN_ATTR_NAME, + u'type': u'int', + u'value': u'2', + u'evaluateName': u'len(variable_for_test_1)', + u'variablesReference': 0, + u'presentationHint': {'attributes': ['readOnly']}, + }] + + json_facade.write_continue() + writer.finished_ok = True + + +_CleanedVars = namedtuple('_CleanedVars', 'variables, groups_found') + + +def _clear_groups(variables): + groups_found = set() + new_variables = [] + for v in variables: + if v['name'] in DAPGrouper.SCOPES_SORTED: + groups_found.add(v['name']) + assert not v['type'] + continue + + else: + new_variables.append(v) + + return _CleanedVars(new_variables, groups_found) + + +@pytest.mark.skipif(IS_JYTHON, reason='Putting unicode on frame vars does not work on Jython.') +def test_evaluate_unicode(case_setup): + with case_setup.test_file('_debugger_case_local_variables.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break 2 here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + evaluate_response = json_facade.evaluate(u'\u16A0', json_hit.frame_id) + + evaluate_response_body = evaluate_response.body.to_dict() + + assert evaluate_response_body == { + 'result': "'\u16a1'", + 'type': 'str', + 'variablesReference': 0, + 'presentationHint': {'attributes': ['rawString']}, + } + + json_facade.write_continue() + writer.finished_ok = True + + +def test_evaluate_exec_unicode(case_setup): + + def get_environ(writer): + env = os.environ.copy() + + env["PYTHONIOENCODING"] = 'utf-8' + return env + + with case_setup.test_file('_debugger_case_local_variables2.py', get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + writer.write_start_redirect() + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + # Check eval + json_facade.evaluate( + "print(u'中')", + frameId=json_hit.frame_id, + context="repl", + ) + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: (u'中' in output_event.body.output) and ('pydevd warning' not in output_event.body.output)) + assert len(messages) == 1 + + # Check exec + json_facade.evaluate( + "a=10;print(u'中')", + frameId=json_hit.frame_id, + context="repl", + ) + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: (u'中' in output_event.body.output) and ('pydevd warning' not in output_event.body.output)) + assert len(messages) == 1 + + response = json_facade.evaluate( + "u'中'", + frameId=json_hit.frame_id, + context="repl", + ) + assert response.body.result in ("u'\\u4e2d'", "'\u4e2d'") # py2 or py3 + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: (u'中' in output_event.body.output) and ('pydevd warning' not in output_event.body.output)) + assert len(messages) == 0 # i.e.: we don't print in this case. + + json_facade.write_continue() + writer.finished_ok = True + + +def test_evaluate_repl_redirect(case_setup): + + with case_setup.test_file('_debugger_case_local_variables2.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + # Check eval + json_facade.evaluate( + "print('var')", + frameId=json_hit.frame_id, + context="repl", + ) + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: u'var' in output_event.body.output) + assert len(messages) == 1 + + json_facade.write_continue() + writer.finished_ok = True + + +def test_evaluate_no_double_exec(case_setup, pyfile): + + @pyfile + def exec_code(): + + def print_and_raise(): + print('Something') + raise RuntimeError() + + print('Break here') + print('TEST SUCEEDED!') + + with case_setup.test_file(exec_code) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + json_facade.evaluate( + "print_and_raise()", + frameId=json_hit.frame_id, + context="repl", + success=False, + ) + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: u'Something' in output_event.body.output) + assert len(messages) == 1 + + json_facade.write_continue() + writer.finished_ok = True + + +def test_evaluate_variable_references(case_setup): + from _pydevd_bundle._debug_adapter.pydevd_schema import EvaluateRequest + from _pydevd_bundle._debug_adapter.pydevd_schema import EvaluateArguments + with case_setup.test_file('_debugger_case_local_variables2.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + evaluate_response = json_facade.wait_for_response( + json_facade.write_request(EvaluateRequest(EvaluateArguments('variable_for_test_2', json_hit.frame_id)))) + + evaluate_response_body = evaluate_response.body.to_dict() + + variables_reference = json_facade.pop_variables_reference([evaluate_response_body]) + + assert evaluate_response_body == { + 'type': 'set', + 'result': "{'a'}", + 'presentationHint': {}, + } + assert len(variables_reference) == 1 + reference = variables_reference[0] + assert reference > 0 + variables_response = json_facade.get_variables_response(reference) + child_variables = variables_response.to_dict()['body']['variables'] + + # The name for a reference in a set is the id() of the variable and can change at each run. + del child_variables[0]['name'] + + assert child_variables == [ + { + 'type': 'str', + 'value': "'a'", + 'presentationHint': {'attributes': ['rawString']}, + 'variablesReference': 0, + }, + { + 'name': GENERATED_LEN_ATTR_NAME, + 'type': 'int', + 'value': '1', + 'presentationHint': {'attributes': ['readOnly']}, + 'evaluateName': 'len(variable_for_test_2)', + 'variablesReference': 0, + } + ] + + json_facade.write_continue() + writer.finished_ok = True + + +def test_set_expression(case_setup): + from _pydevd_bundle._debug_adapter.pydevd_schema import SetExpressionRequest + from _pydevd_bundle._debug_adapter.pydevd_schema import SetExpressionArguments + with case_setup.test_file('_debugger_case_local_variables2.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + set_expression_response = json_facade.wait_for_response( + json_facade.write_request(SetExpressionRequest( + SetExpressionArguments('bb', '20', frameId=json_hit.frame_id)))) + assert set_expression_response.to_dict()['body'] == { + 'value': '20', 'type': 'int', 'presentationHint': {}, 'variablesReference': 0} + + variables_response = json_facade.get_variables_response(json_hit.frame_id) + assert {'name': 'bb', 'value': '20', 'type': 'int', 'evaluateName': 'bb', 'variablesReference': 0} in \ + variables_response.to_dict()['body']['variables'] + + json_facade.write_continue() + writer.finished_ok = True + + +def test_set_expression_failures(case_setup): + from _pydevd_bundle._debug_adapter.pydevd_schema import SetExpressionRequest + from _pydevd_bundle._debug_adapter.pydevd_schema import SetExpressionArguments + + with case_setup.test_file('_debugger_case_local_variables2.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + + set_expression_response = json_facade.wait_for_response( + json_facade.write_request(SetExpressionRequest( + SetExpressionArguments('frame_not_there', '10', frameId=0)))) + assert not set_expression_response.success + assert set_expression_response.message == 'Unable to find thread to set expression.' + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_get_variable_errors(case_setup): + with case_setup.test_file('_debugger_case_completions.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + # First, try with wrong id. + response = json_facade.get_variables_response(9999, success=False) + assert response.message == 'Wrong ID sent from the client: 9999' + + first_hit = None + for i in range(2): + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + if i == 0: + first_hit = json_hit + + if i == 1: + # Now, check with a previously existing frameId. + response = json_facade.get_variables_response(first_hit.frame_id, success=False) + assert response.message == 'Unable to find thread to evaluate variable reference.' + + json_facade.write_continue(wait_for_response=i == 0) + if i == 0: + json_hit = json_facade.wait_for_thread_stopped() + + writer.finished_ok = True + + +def test_set_variable_failure(case_setup): + with case_setup.test_file('_debugger_case_local_variables2.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped() + + # Wrong frame + set_variable_response = json_facade.write_set_variable(0, 'invalid_reference', 'invalid_reference', success=False) + assert not set_variable_response.success + assert set_variable_response.message == 'Unable to find thread to evaluate variable reference.' + + json_facade.write_continue() + + writer.finished_ok = True + + +def _check_list(json_facade, json_hit): + + variable = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_1') + assert variable.value == "['a', 'b', self.var1: 11]" + + var0 = json_facade.get_var(variable.variablesReference, '0') + + json_facade.write_set_variable(variable.variablesReference, var0.name, '1') + + # Check that it was actually changed. + variable = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_1') + assert variable.value == "[1, 'b', self.var1: 11]" + + var1 = json_facade.get_var(variable.variablesReference, 'var1') + + json_facade.write_set_variable(variable.variablesReference, var1.name, '2') + + variable = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_1') + assert variable.value == "[1, 'b', self.var1: 2]" + + +def _check_tuple(json_facade, json_hit): + + variable = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_4') + assert variable.value == "tuple('a', 1, self.var1: 13)" + + var0 = json_facade.get_var(variable.variablesReference, '0') + + response = json_facade.write_set_variable(variable.variablesReference, var0.name, '1', success=False) + assert response.message.startswith("Unable to change: ") + + var1 = json_facade.get_var(variable.variablesReference, 'var1') + json_facade.write_set_variable(variable.variablesReference, var1.name, '2') + + variable = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_4') + assert variable.value == "tuple('a', 1, self.var1: 2)" + + +def _check_dict_subclass(json_facade, json_hit): + variable = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_3') + assert variable.value == "{in_dct: 20; self.var1: 10}" + + var1 = json_facade.get_var(variable.variablesReference, 'var1') + + json_facade.write_set_variable(variable.variablesReference, var1.name, '2') + + # Check that it was actually changed. + variable = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_3') + assert variable.value == "{in_dct: 20; self.var1: 2}" + + var_in_dct = json_facade.get_var(variable.variablesReference, "'in_dct'") + + json_facade.write_set_variable(variable.variablesReference, var_in_dct.name, '5') + + # Check that it was actually changed. + variable = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_3') + assert variable.value == "{in_dct: 5; self.var1: 2}" + + +def _check_set(json_facade, json_hit): + set_var = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_2') + + assert set_var.value == "set(['a', self.var1: 12])" + + var_in_set = json_facade.get_var(set_var.variablesReference, index=1) + assert var_in_set.name != 'var1' + + set_variables_response = json_facade.write_set_variable(set_var.variablesReference, var_in_set.name, '1') + assert set_variables_response.body.type == "int" + assert set_variables_response.body.value == "1" + + # Check that it was actually changed (which for a set means removing the existing entry + # and adding a new one). + set_var = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_2') + assert set_var.value == "set([1, self.var1: 12])" + + # Check that it can be changed again. + var_in_set = json_facade.get_var(set_var.variablesReference, index=1) + + # Check that adding a mutable object to the set does not work. + response = json_facade.write_set_variable(set_var.variablesReference, var_in_set.name, '[22]', success=False) + assert response.message.startswith('Unable to change: ') + + # Check that it's still the same (the existing entry was not removed). + assert json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_2').value == "set([1, self.var1: 12])" + + set_variables_response = json_facade.write_set_variable(set_var.variablesReference, var_in_set.name, '(22,)') + assert set_variables_response.body.type == "tuple" + assert set_variables_response.body.value == "(22,)" + + # Check that the tuple created can be accessed and is correct in the response. + var_in_tuple_in_set = json_facade.get_var(set_variables_response.body.variablesReference, '0') + assert var_in_tuple_in_set.name == '0' + assert var_in_tuple_in_set.value == '22' + + # Check that we can change the variable in the instance. + var1 = json_facade.get_var(set_var.variablesReference, 'var1') + + json_facade.write_set_variable(set_var.variablesReference, var1.name, '2') + + # Check that it was actually changed. + set_var = json_facade.get_local_var(json_hit.frame_id, 'variable_for_test_2') + assert set_var.value == "set([(22,), self.var1: 2])" + + +@pytest.mark.parametrize('_check_func', [ + _check_tuple, + _check_set, + _check_list, + _check_dict_subclass, +]) +def test_set_variable_multiple_cases(case_setup, _check_func): + with case_setup.test_file('_debugger_case_local_variables3.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + _check_func(json_facade, json_hit) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_get_variables_corner_case(case_setup, pyfile): + + @pyfile + def case_with_class_as_object(): + + class ClassField(object): + __name__ = 'name?' + + def __hash__(self): + raise RuntimeError() + + class SomeClass(object): + __class__ = ClassField() + + some_class = SomeClass() + print('TEST SUCEEDED') # Break here + + with case_setup.test_file(case_with_class_as_object) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + set_var = json_facade.get_local_var(json_hit.frame_id, 'some_class') + assert '__main__.SomeClass' in set_var.value + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Putting unicode on frame vars does not work on Jython.') +def test_stack_and_variables(case_setup): + + with case_setup.test_file('_debugger_case_local_variables.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + # : :type stack_trace_response: StackTraceResponse + # : :type stack_trace_response_body: StackTraceResponseBody + # : :type stack_frame: StackFrame + + # Check stack trace format. + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments( + threadId=json_hit.thread_id, + format={'module': True, 'line': True} + ))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_trace_response_body = stack_trace_response.body + stack_frame = next(iter(stack_trace_response_body.stackFrames)) + assert stack_frame['name'] == '__main__.Call : 4' + + # Regular stack trace request (no format). + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + stack_trace_response = json_hit.stack_trace_response + stack_trace_response_body = stack_trace_response.body + assert len(stack_trace_response_body.stackFrames) == 2 + stack_frame = next(iter(stack_trace_response_body.stackFrames)) + assert stack_frame['name'] == 'Call' + assert stack_frame['source']['path'].endswith('_debugger_case_local_variables.py') + + name_to_scope = json_facade.get_name_to_scope(stack_frame['id']) + scope = name_to_scope['Locals'] + frame_variables_reference = scope.variablesReference + assert isinstance(frame_variables_reference, int) + + variables_response = json_facade.get_variables_response(frame_variables_reference) + # : :type variables_response: VariablesResponse + assert len(variables_response.body.variables) == 0 # No variables expected here + + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step') + + variables_response = json_facade.get_variables_response(frame_variables_reference) + # : :type variables_response: VariablesResponse + assert variables_response.body.variables == [{ + 'name': 'variable_for_test_1', + 'value': '10', + 'type': 'int', + 'evaluateName': 'variable_for_test_1', + 'variablesReference': 0, + }] + + # Same thing with hex format + variables_response = json_facade.get_variables_response(frame_variables_reference, fmt={'hex': True}) + # : :type variables_response: VariablesResponse + assert variables_response.body.variables == [{ + 'name': 'variable_for_test_1', + 'value': '0xa', + 'type': 'int', + 'evaluateName': 'variable_for_test_1', + 'variablesReference': 0, + }] + + # Note: besides the scope/stack/variables we can also have references when: + # - setting variable + # * If the variable was changed to a container, the new reference should be returned. + # - evaluate expression + # * Currently ptvsd returns a None value in on_setExpression, so, skip this for now. + # - output + # * Currently not handled by ptvsd, so, skip for now. + + # Reference is for parent (in this case the frame). + # We'll change `variable_for_test_1` from 10 to [1]. + set_variable_response = json_facade.write_set_variable( + frame_variables_reference, 'variable_for_test_1', '[1]') + set_variable_response_as_dict = set_variable_response.to_dict()['body'] + if not IS_JYTHON: + # Not properly changing var on Jython. + assert isinstance(set_variable_response_as_dict.pop('variablesReference'), int) + assert set_variable_response_as_dict == {'value': "[1]", 'type': 'list'} + + variables_response = json_facade.get_variables_response(frame_variables_reference) + # : :type variables_response: VariablesResponse + variables = variables_response.body.variables + assert len(variables) == 1 + var_as_dict = next(iter(variables)) + if not IS_JYTHON: + # Not properly changing var on Jython. + assert isinstance(var_as_dict.pop('variablesReference'), int) + assert var_as_dict == { + 'name': 'variable_for_test_1', + 'value': "[1]", + 'type': 'list', + 'evaluateName': 'variable_for_test_1', + } + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_hex_variables(case_setup): + with case_setup.test_file('_debugger_case_local_variables_hex.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + # : :type stack_trace_response: StackTraceResponse + # : :type stack_trace_response_body: StackTraceResponseBody + # : :type stack_frame: StackFrame + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=json_hit.thread_id))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_trace_response_body = stack_trace_response.body + assert len(stack_trace_response_body.stackFrames) == 2 + stack_frame = next(iter(stack_trace_response_body.stackFrames)) + assert stack_frame['name'] == 'Call' + assert stack_frame['source']['path'].endswith('_debugger_case_local_variables_hex.py') + + name_to_scope = json_facade.get_name_to_scope(stack_frame['id']) + + scope = name_to_scope['Locals'] + frame_variables_reference = scope.variablesReference + assert isinstance(frame_variables_reference, int) + + fmt = {'hex': True} + variables_request = json_facade.write_request( + pydevd_schema.VariablesRequest(pydevd_schema.VariablesArguments(frame_variables_reference, format=fmt))) + variables_response = json_facade.wait_for_response(variables_request) + + # : :type variables_response: VariablesResponse + variable_for_test_1, variable_for_test_2, variable_for_test_3, variable_for_test_4 = sorted(list( + v for v in variables_response.body.variables if v['name'].startswith('variables_for_test') + ), key=lambda v: v['name']) + assert variable_for_test_1 == { + 'name': 'variables_for_test_1', + 'value': "0x64", + 'type': 'int', + 'evaluateName': 'variables_for_test_1', + 'variablesReference': 0, + } + + assert isinstance(variable_for_test_2.pop('variablesReference'), int) + assert variable_for_test_2 == { + 'name': 'variables_for_test_2', + 'value': "[0x1, 0xa, 0x64]", + 'type': 'list', + 'evaluateName': 'variables_for_test_2' + } + + assert isinstance(variable_for_test_3.pop('variablesReference'), int) + assert variable_for_test_3 == { + 'name': 'variables_for_test_3', + 'value': '{0xa: 0xa, 0x64: 0x64, 0x3e8: 0x3e8}', + 'type': 'dict', + 'evaluateName': 'variables_for_test_3' + } + + assert isinstance(variable_for_test_4.pop('variablesReference'), int) + assert variable_for_test_4 == { + 'name': 'variables_for_test_4', + 'value': '{(0x1, 0xa, 0x64): (0x2710, 0x186a0, 0x186a0)}', + 'type': 'dict', + 'evaluateName': 'variables_for_test_4' + } + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_stopped_event(case_setup): + with case_setup.test_file('_debugger_case_print.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + assert json_hit.thread_id + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Not Jython compatible (fails on set variable).') +def test_pause_and_continue(case_setup): + with case_setup.test_file('_debugger_case_pause_continue.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped() + + json_facade.write_continue() + + json_facade.write_pause() + + json_hit = json_facade.wait_for_thread_stopped(reason="pause") + + stack_frame = next(iter(json_hit.stack_trace_response.body.stackFrames)) + + name_to_scope = json_facade.get_name_to_scope(stack_frame['id']) + frame_variables_reference = name_to_scope['Locals'].variablesReference + + set_variable_response = json_facade.write_set_variable(frame_variables_reference, 'loop', 'False') + set_variable_response_as_dict = set_variable_response.to_dict()['body'] + assert set_variable_response_as_dict == {'value': "False", 'type': 'bool', 'variablesReference': 0} + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('stepping_resumes_all_threads', [False, True]) +def test_step_out_multi_threads(case_setup, stepping_resumes_all_threads): + with case_setup.test_file('_debugger_case_multi_threads_stepping.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(steppingResumesAllThreads=stepping_resumes_all_threads) + json_facade.write_set_breakpoints([ + writer.get_line_index_with_content('Break thread 1'), + ]) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + response = json_facade.write_list_threads() + assert len(response.body.threads) == 3 + + thread_name_to_id = dict((t['name'], t['id']) for t in response.body.threads) + assert json_hit.thread_id == thread_name_to_id['thread1'] + + if stepping_resumes_all_threads: + # If we're stepping with multiple threads, we'll exit here. + json_facade.write_step_out(thread_name_to_id['thread1']) + else: + json_facade.write_step_out(thread_name_to_id['thread1']) + + # Timeout is expected... make it shorter. + writer.reader_thread.set_messages_timeout(2) + try: + json_hit = json_facade.wait_for_thread_stopped('step') + raise AssertionError('Expected timeout!') + except debugger_unittest.TimeoutError: + pass + + json_facade.write_step_out(thread_name_to_id['thread2']) + json_facade.write_step_next(thread_name_to_id['MainThread']) + json_hit = json_facade.wait_for_thread_stopped('step') + assert json_hit.thread_id == thread_name_to_id['MainThread'] + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('stepping_resumes_all_threads', [True, False]) +@pytest.mark.parametrize('step_mode', ['step_next', 'step_in']) +def test_step_next_step_in_multi_threads(case_setup, stepping_resumes_all_threads, step_mode): + with case_setup.test_file('_debugger_case_multi_threads_stepping.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(steppingResumesAllThreads=stepping_resumes_all_threads) + json_facade.write_set_breakpoints([ + writer.get_line_index_with_content('Break thread 1'), + ]) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + response = json_facade.write_list_threads() + assert len(response.body.threads) == 3 + + thread_name_to_id = dict((t['name'], t['id']) for t in response.body.threads) + assert json_hit.thread_id == thread_name_to_id['thread1'] + + for _i in range(20): + if step_mode == 'step_next': + json_facade.write_step_next(thread_name_to_id['thread1']) + + elif step_mode == 'step_in': + json_facade.write_step_in(thread_name_to_id['thread1']) + + else: + raise AssertionError('Unexpected step_mode: %s' % (step_mode,)) + + json_hit = json_facade.wait_for_thread_stopped('step') + assert json_hit.thread_id == thread_name_to_id['thread1'] + local_var = json_facade.get_local_var(json_hit.frame_id, '_event2_set') + + # We're stepping in a single thread which depends on events being set in + # another thread, so, we can only get here if the other thread was also released. + if local_var.value == 'True': + if stepping_resumes_all_threads: + break + else: + raise AssertionError('Did not expect _event2_set to be set when not resuming other threads on step.') + + time.sleep(.01) + else: + if stepping_resumes_all_threads: + raise AssertionError('Expected _event2_set to be set already.') + else: + # That's correct, we should never reach the condition where _event2_set is set if + # we're not resuming other threads on step. + pass + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_stepping(case_setup): + with case_setup.test_file('_debugger_case_stepping.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=False) + json_facade.write_set_breakpoints([ + writer.get_line_index_with_content('Break here 1'), + writer.get_line_index_with_content('Break here 2') + ]) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + # Test Step-Over or 'next' + stack_trace_response = json_hit.stack_trace_response + for stack_frame in stack_trace_response.body.stackFrames: + assert stack_frame['source']['sourceReference'] == 0 + + stack_frame = next(iter(stack_trace_response.body.stackFrames)) + before_step_over_line = stack_frame['line'] + + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', line=before_step_over_line + 1) + + # Test step into or 'stepIn' + json_facade.write_step_in(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='step_into') + + # Test step return or 'stepOut' + json_facade.write_continue() + json_hit = json_facade.wait_for_thread_stopped(name='step_out') + + json_facade.write_step_out(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', name='Call') + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_evaluate(case_setup): + with case_setup.test_file('_debugger_case_evaluate.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=json_hit.thread_id))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_frame = next(iter(stack_trace_response.body.stackFrames)) + stack_frame_id = stack_frame['id'] + + # Check that evaluating variable that does not exist in hover returns success == False. + json_facade.evaluate( + 'var_does_not_exist', frameId=stack_frame_id, context='hover', success=False) + + # Test evaluate request that results in 'eval' + eval_response = json_facade.evaluate('var_1', frameId=stack_frame_id, context='repl') + assert eval_response.body.result == '5' + assert eval_response.body.type == 'int' + + # Test evaluate request that results in 'exec' + exec_response = json_facade.evaluate('var_1 = 6', frameId=stack_frame_id, context='repl') + assert exec_response.body.result == '' + + # Test evaluate request that results in 'exec' but fails + exec_response = json_facade.evaluate( + 'var_1 = "abc"/6', frameId=stack_frame_id, context='repl', success=False) + assert 'TypeError' in exec_response.body.result + assert 'TypeError' in exec_response.message + + # Evaluate without a frameId. + + # Error because 'foo_value' is not set in 'sys'. + exec_response = json_facade.evaluate('import email;email.foo_value', success=False) + assert 'AttributeError' in exec_response.body.result + assert 'AttributeError' in exec_response.message + + # Reading foo_value didn't work, but 'email' should be in the namespace now. + json_facade.evaluate('email.foo_value=True') + + # Ok, 'foo_value' is now set in 'email' module. + exec_response = json_facade.evaluate('email.foo_value') + + # We don't actually get variables without a frameId, we can just evaluate and observe side effects + # (so, the result is always empty -- or an error). + assert exec_response.body.result == '' + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_evaluate_failures(case_setup): + with case_setup.test_file('_debugger_case_completions.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + # First, try with wrong id. + exec_request = json_facade.write_request( + pydevd_schema.EvaluateRequest(pydevd_schema.EvaluateArguments('a = 10', frameId=9999, context='repl'))) + exec_response = json_facade.wait_for_response(exec_request) + assert exec_response.success == False + assert exec_response.message == 'Wrong ID sent from the client: 9999' + + first_hit = None + for i in range(2): + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + if i == 0: + first_hit = json_hit + # Check that watch exceptions are shown as string/failure. + response = json_facade.evaluate( + 'invalid_var', frameId=first_hit.frame_id, context='watch', success=False) + assert response.body.result == "NameError: name 'invalid_var' is not defined" + if i == 1: + # Now, check with a previously existing frameId. + exec_request = json_facade.write_request( + pydevd_schema.EvaluateRequest(pydevd_schema.EvaluateArguments('a = 10', frameId=first_hit.frame_id, context='repl'))) + exec_response = json_facade.wait_for_response(exec_request) + assert exec_response.success == False + assert exec_response.message == 'Unable to find thread for evaluation.' + + json_facade.write_continue(wait_for_response=i == 0) + if i == 0: + json_hit = json_facade.wait_for_thread_stopped() + + writer.finished_ok = True + + +def test_evaluate_exception_trace(case_setup, pyfile): + + @pyfile + def exception_trace_file(): + + class A(object): + + def __init__(self, a): + pass + + def method(): + A() + + def method2(): + method() + + def method3(): + method2() + + print('TEST SUCEEDED') # Break here + + with case_setup.test_file(exception_trace_file) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + exec_response = json_facade.evaluate('method3()', json_hit.frame_id, 'repl', success=False) + assert 'pydevd' not in exec_response.message # i.e.: don't show pydevd in the trace + assert 'method3' in exec_response.message + assert 'method2' in exec_response.message + + exec_response = json_facade.evaluate('method2()', json_hit.frame_id, 'repl', success=False) + assert 'pydevd' not in exec_response.message + assert 'method3' not in exec_response.message + assert 'method2' in exec_response.message + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('max_frames', ['default', 'all', 10]) # -1 = default, 0 = all, 10 = 10 frames +def test_exception_details(case_setup, max_frames): + with case_setup.test_file('_debugger_case_large_exception_stack.py') as writer: + json_facade = JsonFacade(writer) + + if max_frames == 'all': + json_facade.write_launch(maxExceptionStackFrames=0) + # trace back compresses repeated text + min_expected_lines = 100 + max_expected_lines = 220 + elif max_frames == 'default': + json_facade.write_launch() + # default is all frames + # trace back compresses repeated text + min_expected_lines = 100 + max_expected_lines = 220 + else: + json_facade.write_launch(maxExceptionStackFrames=max_frames) + min_expected_lines = 10 + max_expected_lines = 21 + + json_facade.write_set_exception_breakpoints(['raised']) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped('exception') + + exc_info_request = json_facade.write_request( + pydevd_schema.ExceptionInfoRequest(pydevd_schema.ExceptionInfoArguments(json_hit.thread_id))) + exc_info_response = json_facade.wait_for_response(exc_info_request) + + stack_frames = json_hit.stack_trace_response.body.stackFrames + assert 100 <= len(stack_frames) <= 104 + assert stack_frames[-1]['name'] == '' + assert stack_frames[0]['name'] == 'method1' + + body = exc_info_response.body + assert body.exceptionId.endswith('IndexError') + assert body.description == 'foo' + assert normcase(body.details.kwargs['source']) == normcase(writer.TEST_FILE) + stack_line_count = len(body.details.stackTrace.split('\n')) + assert min_expected_lines <= stack_line_count <= max_expected_lines + + json_facade.write_set_exception_breakpoints([]) # Don't stop on reraises. + json_facade.write_continue() + + writer.finished_ok = True + + +def test_stack_levels(case_setup): + with case_setup.test_file('_debugger_case_deep_stacks.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped() + + # get full stack + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=json_hit.thread_id))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + full_stack_frames = stack_trace_response.body.stackFrames + total_frames = stack_trace_response.body.totalFrames + + startFrame = 0 + levels = 20 + received_frames = [] + while startFrame < total_frames: + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments( + threadId=json_hit.thread_id, + startFrame=startFrame, + levels=20))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + received_frames += stack_trace_response.body.stackFrames + startFrame += levels + + assert full_stack_frames == received_frames + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_breakpoint_adjustment(case_setup): + with case_setup.test_file('_debugger_case_adjust_breakpoint.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + + bp_requested = writer.get_line_index_with_content('requested') + bp_expected = writer.get_line_index_with_content('expected') + + set_bp_request = json_facade.write_request( + pydevd_schema.SetBreakpointsRequest(pydevd_schema.SetBreakpointsArguments( + source=pydevd_schema.Source(path=writer.TEST_FILE, sourceReference=0), + breakpoints=[pydevd_schema.SourceBreakpoint(bp_requested).to_dict()])) + ) + set_bp_response = json_facade.wait_for_response(set_bp_request) + assert set_bp_response.success + assert set_bp_response.body.breakpoints[0]['line'] == bp_expected + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=json_hit.thread_id))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_frame = next(iter(stack_trace_response.body.stackFrames)) + assert stack_frame['line'] == bp_expected + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='No goto on Jython.') +def test_goto(case_setup): + with case_setup.test_file('_debugger_case_set_next_statement.py') as writer: + json_facade = JsonFacade(writer) + + break_line = writer.get_line_index_with_content('Break here') + step_line = writer.get_line_index_with_content('Step here') + json_facade.write_set_breakpoints(break_line) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=json_hit.thread_id))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_frame = next(iter(stack_trace_response.body.stackFrames)) + assert stack_frame['line'] == break_line + + goto_targets_request = json_facade.write_request( + pydevd_schema.GotoTargetsRequest(pydevd_schema.GotoTargetsArguments( + source=pydevd_schema.Source(path=writer.TEST_FILE, sourceReference=0), + line=step_line))) + goto_targets_response = json_facade.wait_for_response(goto_targets_request) + target_id = goto_targets_response.body.targets[0]['id'] + + goto_request = json_facade.write_request( + pydevd_schema.GotoRequest(pydevd_schema.GotoArguments( + threadId=json_hit.thread_id, + targetId=12345))) + goto_response = json_facade.wait_for_response(goto_request) + assert not goto_response.success + + goto_request = json_facade.write_request( + pydevd_schema.GotoRequest(pydevd_schema.GotoArguments( + threadId=json_hit.thread_id, + targetId=target_id))) + goto_response = json_facade.wait_for_response(goto_request) + + json_hit = json_facade.wait_for_thread_stopped('goto') + + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=json_hit.thread_id))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_frame = next(iter(stack_trace_response.body.stackFrames)) + assert stack_frame['line'] == step_line + + json_facade.write_continue() + + # we hit the breakpoint again. Since we moved back + json_facade.wait_for_thread_stopped() + json_facade.write_continue() + + writer.finished_ok = True + + +def _collect_stack_frames_ending_with(json_hit, end_with_pattern): + stack_trace_response = json_hit.stack_trace_response + dont_trace_frames = list(frame for frame in stack_trace_response.body.stackFrames + if frame['source']['path'].endswith(end_with_pattern)) + return dont_trace_frames + + +def _check_dont_trace_filtered_out(json_hit): + assert _collect_stack_frames_ending_with(json_hit, 'dont_trace.py') == [] + + +def _check_dont_trace_not_filtered_out(json_hit): + assert len(_collect_stack_frames_ending_with(json_hit, 'dont_trace.py')) == 1 + + +@pytest.mark.parametrize('dbg_property', [ + 'dont_trace', + 'trace', + 'change_pattern', + 'dont_trace_after_start' +]) +def test_set_debugger_property(case_setup, dbg_property): + + kwargs = {} + + with case_setup.test_file('_debugger_case_dont_trace_test.py', **kwargs) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + if dbg_property in ('dont_trace', 'change_pattern', 'dont_trace_after_start'): + json_facade.write_set_debugger_property([], ['dont_trace.py'] if not IS_WINDOWS else ['Dont_Trace.py']) + + if dbg_property == 'change_pattern': + json_facade.write_set_debugger_property([], ['something_else.py']) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + if dbg_property in ('dont_trace', 'dont_trace_after_start'): + _check_dont_trace_filtered_out(json_hit) + + elif dbg_property in ('change_pattern', 'trace'): + _check_dont_trace_not_filtered_out(json_hit) + + else: + raise AssertionError('Unexpected: %s' % (dbg_property,)) + + if dbg_property == 'dont_trace_after_start': + json_facade.write_set_debugger_property([], ['something_else.py']) + + json_facade.write_continue() + json_hit = json_facade.wait_for_thread_stopped() + + if dbg_property in ('dont_trace',): + _check_dont_trace_filtered_out(json_hit) + + elif dbg_property in ('change_pattern', 'trace', 'dont_trace_after_start'): + _check_dont_trace_not_filtered_out(json_hit) + + else: + raise AssertionError('Unexpected: %s' % (dbg_property,)) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_source_mapping_errors(case_setup): + from _pydevd_bundle._debug_adapter.pydevd_schema import Source + from _pydevd_bundle._debug_adapter.pydevd_schema import PydevdSourceMap + + with case_setup.test_file('_debugger_case_source_mapping.py') as writer: + json_facade = JsonFacade(writer) + + map_to_cell_1_line2 = writer.get_line_index_with_content('map to cEll1, line 2') + map_to_cell_2_line2 = writer.get_line_index_with_content('map to cEll2, line 2') + + cell1_map = PydevdSourceMap(map_to_cell_1_line2, map_to_cell_1_line2 + 1, Source(path=''), 2) + cell2_map = PydevdSourceMap(map_to_cell_2_line2, map_to_cell_2_line2 + 1, Source(path=''), 2) + pydevd_source_maps = [ + cell1_map, cell2_map + ] + + json_facade.write_set_pydevd_source_map( + Source(path=writer.TEST_FILE), + pydevd_source_maps=pydevd_source_maps, + ) + # This will fail because file mappings must be 1:N, not M:N (i.e.: if there's a mapping from file1.py to , + # there can be no other mapping from any other file to ). + # This is a limitation to make it easier to remove existing breakpoints when new breakpoints are + # set to a file (so, any file matching that breakpoint can be removed instead of needing to check + # which lines are corresponding to that file). + json_facade.write_set_pydevd_source_map( + Source(path=os.path.join(os.path.dirname(writer.TEST_FILE), 'foo.py')), + pydevd_source_maps=pydevd_source_maps, + success=False, + ) + json_facade.write_make_initial_run() + + writer.finished_ok = True + + +@pytest.mark.parametrize( + 'target', + ['_debugger_case_source_mapping.py', '_debugger_case_source_mapping_and_reference.py'] +) +@pytest.mark.parametrize('jmc', [True, False]) +def test_source_mapping_base(case_setup, target, jmc): + from _pydevd_bundle._debug_adapter.pydevd_schema import Source + from _pydevd_bundle._debug_adapter.pydevd_schema import PydevdSourceMap + + case_setup.check_non_ascii = True + + with case_setup.test_file(target) as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=jmc) + + map_to_cell_1_line2 = writer.get_line_index_with_content('map to cEll1, line 2') + map_to_cell_2_line2 = writer.get_line_index_with_content('map to cEll2, line 2') + + cell1_map = PydevdSourceMap(map_to_cell_1_line2, map_to_cell_1_line2 + 1, Source(path=''), 2) + cell2_map = PydevdSourceMap(map_to_cell_2_line2, map_to_cell_2_line2 + 1, Source(path=''), 2) + pydevd_source_maps = [ + cell1_map, cell2_map, cell2_map, # The one repeated should be ignored. + ] + + # Set breakpoints before setting the source map (check that we reapply them). + json_facade.write_set_breakpoints(map_to_cell_1_line2) + + test_file = writer.TEST_FILE + if isinstance(test_file, bytes): + # file is in the filesystem encoding (needed for launch) but protocol needs it in utf-8 + test_file = test_file.decode(file_system_encoding) + test_file = test_file.encode('utf-8') + + json_facade.write_set_pydevd_source_map( + Source(path=test_file), + pydevd_source_maps=pydevd_source_maps, + ) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=map_to_cell_1_line2, file=os.path.basename(test_file)) + for stack_frame in json_hit.stack_trace_response.body.stackFrames: + assert stack_frame['source']['sourceReference'] == 0 + + # Check that we no longer stop at the cEll1 breakpoint (its mapping should be removed when + # the new one is added and we should only stop at cEll2). + json_facade.write_set_breakpoints(map_to_cell_2_line2) + for stack_frame in json_hit.stack_trace_response.body.stackFrames: + assert stack_frame['source']['sourceReference'] == 0 + json_facade.write_continue() + + json_hit = json_facade.wait_for_thread_stopped(line=map_to_cell_2_line2, file=os.path.basename(test_file)) + json_facade.write_set_breakpoints([]) # Clears breakpoints + json_facade.write_continue() + + writer.finished_ok = True + + +def test_source_mapping_just_my_code(case_setup): + from _pydevd_bundle._debug_adapter.pydevd_schema import Source + from _pydevd_bundle._debug_adapter.pydevd_schema import PydevdSourceMap + + case_setup.check_non_ascii = True + + with case_setup.test_file('_debugger_case_source_mapping_jmc.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=True) + + map_to_cell_1_line1 = writer.get_line_index_with_content('map to cEll1, line 1') + map_to_cell_1_line6 = writer.get_line_index_with_content('map to cEll1, line 6') + map_to_cell_1_line7 = writer.get_line_index_with_content('map to cEll1, line 7') + + cell1_map = PydevdSourceMap(map_to_cell_1_line1, map_to_cell_1_line7, Source(path=''), 1) + pydevd_source_maps = [cell1_map] + + # Set breakpoints before setting the source map (check that we reapply them). + json_facade.write_set_breakpoints(map_to_cell_1_line6) + + test_file = writer.TEST_FILE + if isinstance(test_file, bytes): + # file is in the filesystem encoding (needed for launch) but protocol needs it in utf-8 + test_file = test_file.decode(file_system_encoding) + test_file = test_file.encode('utf-8') + + json_facade.write_set_pydevd_source_map( + Source(path=test_file), + pydevd_source_maps=pydevd_source_maps, + ) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=map_to_cell_1_line6, file=os.path.basename(test_file)) + for stack_frame in json_hit.stack_trace_response.body.stackFrames: + assert stack_frame['source']['sourceReference'] == 0 + + # i.e.: Remove the source maps + json_facade.write_set_pydevd_source_map( + Source(path=test_file), + pydevd_source_maps=[], + ) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_source_mapping_goto_target(case_setup): + from _pydevd_bundle._debug_adapter.pydevd_schema import Source + from _pydevd_bundle._debug_adapter.pydevd_schema import PydevdSourceMap + + def additional_output_checks(writer, stdout, stderr): + assert 'Skip this print' not in stdout + assert 'TEST SUCEEDED' in stdout + + with case_setup.test_file('_debugger_case_source_map_goto_target.py', additional_output_checks=additional_output_checks) as writer: + test_file = writer.TEST_FILE + if isinstance(test_file, bytes): + # file is in the filesystem encoding (needed for launch) but protocol needs it in utf-8 + test_file = test_file.decode(file_system_encoding) + test_file = test_file.encode('utf-8') + + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + + map_to_cell_1_line1 = writer.get_line_index_with_content('map to Cell1, line 1') + map_to_cell_1_line2 = writer.get_line_index_with_content('map to Cell1, line 2') + map_to_cell_1_line4 = writer.get_line_index_with_content('map to Cell1, line 4') + map_to_cell_1_line5 = writer.get_line_index_with_content('map to Cell1, line 5') + + cell1_map = PydevdSourceMap(map_to_cell_1_line1, map_to_cell_1_line5, Source(path=''), 1) + pydevd_source_maps = [cell1_map] + json_facade.write_set_pydevd_source_map( + Source(path=test_file), + pydevd_source_maps=pydevd_source_maps, + ) + json_facade.write_set_breakpoints(map_to_cell_1_line2) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=map_to_cell_1_line2, file=os.path.basename(test_file)) + for stack_frame in json_hit.stack_trace_response.body.stackFrames: + assert stack_frame['source']['sourceReference'] == 0 + + goto_targets_request = json_facade.write_request( + pydevd_schema.GotoTargetsRequest(pydevd_schema.GotoTargetsArguments( + source=pydevd_schema.Source(path=writer.TEST_FILE, sourceReference=0), + line=map_to_cell_1_line4))) + goto_targets_response = json_facade.wait_for_response(goto_targets_request) + target_id = goto_targets_response.body.targets[0]['id'] + + goto_request = json_facade.write_request( + pydevd_schema.GotoRequest(pydevd_schema.GotoArguments( + threadId=json_hit.thread_id, + targetId=target_id))) + goto_response = json_facade.wait_for_response(goto_request) + assert goto_response.success + + json_hit = json_facade.wait_for_thread_stopped('goto') + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_CHERRYPY or IS_WINDOWS, reason='No CherryPy available / not ok in Windows.') +def test_process_autoreload_cherrypy(case_setup_multiprocessing, tmpdir): + ''' + CherryPy does an os.execv(...) which will kill the running process and replace + it with a new process when a reload takes place, so, it mostly works as + a new process connection (everything is the same except that the + existing process is stopped). + ''' + port = get_free_port() + # We write a temp file because we'll change it to autoreload later on. + f = tmpdir.join('_debugger_case_cherrypy.py') + + tmplt = ''' +import cherrypy +cherrypy.config.update({ + 'engine.autoreload.on': True, + 'checker.on': False, + 'server.socket_port': %(port)s, +}) +class HelloWorld(object): + + @cherrypy.expose + def index(self): + print('TEST SUCEEDED') + return "Hello World %(str)s!" # break here + @cherrypy.expose('/exit') + def exit(self): + cherrypy.engine.exit() + +cherrypy.quickstart(HelloWorld()) +''' + + f.write(tmplt % dict(port=port, str='INITIAL')) + + file_to_check = str(f) + + def get_environ(writer): + env = os.environ.copy() + + env["PYTHONIOENCODING"] = 'utf-8' + env["PYTHONPATH"] = str(tmpdir) + return env + + import threading + from tests_python.debugger_unittest import AbstractWriterThread + with case_setup_multiprocessing.test_file(file_to_check, get_environ=get_environ) as writer: + + original_ignore_stderr_line = writer._ignore_stderr_line + + @overrides(writer._ignore_stderr_line) + def _ignore_stderr_line(line): + if original_ignore_stderr_line(line): + return True + return 'ENGINE ' in line or 'CherryPy Checker' in line or 'has an empty config' in line + + writer._ignore_stderr_line = _ignore_stderr_line + + json_facade = JsonFacade(writer) + json_facade.write_launch(debugOptions=['DebugStdLib']) + + break1_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(break1_line) + + server_socket = writer.server_socket + + secondary_thread_log = [] + secondary_thread_errors = [] + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + try: + from tests_python.debugger_unittest import ReaderThread + expected_connections = 1 + for _ in range(expected_connections): + server_socket.listen(1) + self.server_socket = server_socket + new_sock, addr = server_socket.accept() + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + + writer2 = SecondaryProcessWriterThread() + + writer2.reader_thread = reader_thread + writer2.sock = new_sock + + writer2.write_version() + writer2.write_add_breakpoint(break1_line) + writer2.write_make_initial_run() + + secondary_thread_log.append('Initial run') + + # Give it some time to startup + time.sleep(2) + t = writer.create_request_thread('http://127.0.0.1:%s/' % (port,)) + t.start() + + secondary_thread_log.append('Waiting for first breakpoint') + hit = writer2.wait_for_breakpoint_hit() + secondary_thread_log.append('Hit first breakpoint') + writer2.write_run_thread(hit.thread_id) + + contents = t.wait_for_contents() + assert 'Hello World NEW!' in contents + + secondary_thread_log.append('Requesting exit.') + t = writer.create_request_thread('http://127.0.0.1:%s/exit' % (port,)) + t.start() + except Exception as e: + secondary_thread_errors.append('Error from secondary thread: %s' % (e,)) + raise + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + json_facade.write_make_initial_run() + + # Give it some time to startup + time.sleep(2) + + t = writer.create_request_thread('http://127.0.0.1:%s/' % (port,)) + t.start() + json_facade.wait_for_thread_stopped() + json_facade.write_continue() + + contents = t.wait_for_contents() + assert 'Hello World INITIAL!' in contents + + # Sleep a bit more to make sure that the initial timestamp was gotten in the + # CherryPy background thread. + time.sleep(2) + f.write(tmplt % dict(port=port, str='NEW')) + + def check_condition(): + return not secondary_process_thread_communication.is_alive() + + def create_msg(): + return 'Expected secondary thread to finish before timeout.\nSecondary thread log:\n%s\nSecondary thread errors:\n%s\n' % ( + '\n'.join(secondary_thread_log), '\n'.join(secondary_thread_errors)) + + wait_for_condition(check_condition, msg=create_msg) + + if secondary_thread_errors: + raise AssertionError('Found errors in secondary thread: %s' % (secondary_thread_errors,)) + + writer.finished_ok = True + + +def test_wait_for_attach(case_setup_remote_attach_to): + host_port = get_socket_name(close=True) + + def check_thread_events(json_facade): + json_facade.write_list_threads() + # Check that we have the started thread event (whenever we reconnect). + started_events = json_facade.mark_messages(ThreadEvent, lambda x: x.body.reason == 'started') + assert len(started_events) == 1 + + def check_process_event(json_facade, start_method): + if start_method == 'attach': + json_facade.write_attach() + + elif start_method == 'launch': + json_facade.write_launch() + + else: + raise AssertionError('Unexpected: %s' % (start_method,)) + + process_events = json_facade.mark_messages(ProcessEvent) + assert len(process_events) == 1 + assert next(iter(process_events)).body.startMethod == start_method + + with case_setup_remote_attach_to.test_file('_debugger_case_wait_for_attach.py', host_port[1]) as writer: + writer.TEST_FILE = debugger_unittest._get_debugger_test_file('_debugger_case_wait_for_attach_impl.py') + time.sleep(1) # Give some time for it to pass the first breakpoint and wait in 'wait_for_attach'. + writer.start_socket_client(*host_port) + + json_facade = JsonFacade(writer) + check_thread_events(json_facade) + + break1_line = writer.get_line_index_with_content('Break 1') + break2_line = writer.get_line_index_with_content('Break 2') + break3_line = writer.get_line_index_with_content('Break 3') + + pause1_line = writer.get_line_index_with_content('Pause 1') + pause2_line = writer.get_line_index_with_content('Pause 2') + + check_process_event(json_facade, start_method='launch') + json_facade.write_set_breakpoints([break1_line, break2_line, break3_line]) + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped(line=break2_line) + + # Upon disconnect, all threads should be running again. + json_facade.write_disconnect() + + # Connect back (socket should remain open). + writer.start_socket_client(*host_port) + json_facade = JsonFacade(writer) + check_thread_events(json_facade) + check_process_event(json_facade, start_method='attach') + json_facade.write_set_breakpoints([break1_line, break2_line, break3_line]) + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped(line=break3_line) + + # Upon disconnect, all threads should be running again. + json_facade.write_disconnect() + + # Connect back (socket should remain open). + writer.start_socket_client(*host_port) + json_facade = JsonFacade(writer) + check_thread_events(json_facade) + check_process_event(json_facade, start_method='attach') + json_facade.write_make_initial_run() + + # Connect back without a disconnect (auto-disconnects previous and connects new client). + writer.start_socket_client(*host_port) + json_facade = JsonFacade(writer) + check_thread_events(json_facade) + check_process_event(json_facade, start_method='attach') + json_facade.write_make_initial_run() + + json_facade.write_pause() + json_hit = json_facade.wait_for_thread_stopped(reason='pause', line=[pause1_line, pause2_line]) + + # Change value of 'a' for test to finish. + json_facade.write_set_variable(json_hit.frame_id, 'a', '10') + + json_facade.write_disconnect() + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_GEVENT, reason='Gevent not installed.') +def test_wait_for_attach_gevent(case_setup_remote_attach_to): + host_port = get_socket_name(close=True) + + def get_environ(writer): + env = os.environ.copy() + env['GEVENT_SUPPORT'] = 'True' + return env + + def check_thread_events(json_facade): + json_facade.write_list_threads() + # Check that we have the started thread event (whenever we reconnect). + started_events = json_facade.mark_messages(ThreadEvent, lambda x: x.body.reason == 'started') + assert len(started_events) == 1 + + with case_setup_remote_attach_to.test_file('_debugger_case_gevent.py', host_port[1], additional_args=['remote', 'as-server'], get_environ=get_environ) as writer: + writer.TEST_FILE = debugger_unittest._get_debugger_test_file('_debugger_case_gevent.py') + time.sleep(.5) # Give some time for it to pass the first breakpoint and wait. + writer.start_socket_client(*host_port) + + json_facade = JsonFacade(writer) + check_thread_events(json_facade) + + break1_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(break1_line) + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped(line=break1_line) + + json_facade.write_disconnect() + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_GEVENT, reason='Gevent not installed.') +@pytest.mark.parametrize('show', [True, False]) +def test_gevent_show_paused_greenlets(case_setup, show): + + def get_environ(writer): + env = os.environ.copy() + env['GEVENT_SUPPORT'] = 'True' + if show: + env['GEVENT_SHOW_PAUSED_GREENLETS'] = 'True' + else: + env['GEVENT_SHOW_PAUSED_GREENLETS'] = 'False' + return env + + with case_setup.test_file('_debugger_case_gevent_simple.py', get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + + break1_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(break1_line) + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped(line=break1_line) + + response = json_facade.write_list_threads() + if show: + assert len(response.body.threads) > 1 + + thread_name_to_id = dict((t['name'], t['id']) for t in response.body.threads) + assert set(thread_name_to_id.keys()) == set(( + 'MainThread', + 'greenlet: - _debugger_case_gevent_simple.py', + 'Greenlet: foo - _debugger_case_gevent_simple.py', + 'Hub: run - hub.py' + )) + + for tname, tid in thread_name_to_id.items(): + stack = json_facade.get_stack_as_json_hit( + tid, + no_stack_frame=tname == 'Hub: run - hub.py' + ) + assert stack + + else: + assert len(response.body.threads) == 1 + + json_facade.write_continue(wait_for_response=False) + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_GEVENT, reason='Gevent not installed.') +def test_gevent_subprocess_not_python(case_setup): + + def get_environ(writer): + env = os.environ.copy() + env['GEVENT_SUPPORT'] = 'True' + env['CALL_PYTHON_SUB'] = '0' + return env + + with case_setup.test_file('_debugger_case_gevent_subprocess.py', get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + + break1_line = writer.get_line_index_with_content("print('TEST SUCEEDED')") + json_facade.write_set_breakpoints(break1_line) + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped(line=break1_line) + + json_facade.write_continue(wait_for_response=False) + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_GEVENT, reason='Gevent not installed.') +def test_gevent_subprocess_python(case_setup_multiprocessing): + import threading + from tests_python.debugger_unittest import AbstractWriterThread + + def get_environ(writer): + env = os.environ.copy() + env['GEVENT_SUPPORT'] = 'True' + env['CALL_PYTHON_SUB'] = '1' + return env + + with case_setup_multiprocessing.test_file( + '_debugger_case_gevent_subprocess.py', + get_environ=get_environ, + ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + + break1_line = writer.get_line_index_with_content("print('foo called')") + json_facade.write_set_breakpoints([break1_line]) + + server_socket = writer.server_socket + secondary_finished_ok = [False] + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + server_socket.listen(1) + self.server_socket = server_socket + new_sock, addr = server_socket.accept() + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + + writer2 = SecondaryProcessWriterThread() + writer2.reader_thread = reader_thread + writer2.sock = new_sock + json_facade2 = JsonFacade(writer2) + + json_facade2.write_set_breakpoints([break1_line, ]) + json_facade2.write_make_initial_run() + + json_facade2.wait_for_thread_stopped() + json_facade2.write_continue() + secondary_finished_ok[0] = True + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + time.sleep(.1) + + json_facade.write_make_initial_run() + secondary_process_thread_communication.join(10) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + + assert secondary_finished_ok[0] + writer.finished_ok = True + + +@pytest.mark.skipif( + not TEST_GEVENT or IS_WINDOWS, + reason='Gevent not installed / Sometimes the debugger crashes on Windows as the compiled extensions conflict with gevent.' +) +def test_notify_gevent(case_setup, pyfile): + + def get_environ(writer): + # I.e.: Make sure that gevent support is disabled + env = os.environ.copy() + env['GEVENT_SUPPORT'] = '' + return env + + @pyfile + def case_gevent(): + from gevent import monkey + import os + monkey.patch_all() + print('TEST SUCEEDED') # Break here + os._exit(0) + + def additional_output_checks(writer, stdout, stderr): + assert 'environment variable' in stderr + assert 'GEVENT_SUPPORT=True' in stderr + + with case_setup.test_file( + case_gevent, + get_environ=get_environ, + additional_output_checks=additional_output_checks, + EXPECTED_RETURNCODE='any', + FORCE_KILL_PROCESS_WHEN_FINISHED_OK=True + ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped() + json_facade.write_continue(wait_for_response=False) + + wait_for_condition(lambda: 'GEVENT_SUPPORT=True' in writer.get_stderr()) + + writer.finished_ok = True + + +def test_ppid(case_setup, pyfile): + + @pyfile + def case_ppid(): + from pydevd import get_global_debugger + assert get_global_debugger().get_arg_ppid() == 22 + print('TEST SUCEEDED') + + def update_command_line_args(writer, args): + ret = debugger_unittest.AbstractWriterThread.update_command_line_args(writer, args) + ret.insert(ret.index('--client'), '--ppid') + ret.insert(ret.index('--client'), '22') + return ret + + with case_setup.test_file( + case_ppid, + update_command_line_args=update_command_line_args, + ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + json_facade.write_make_initial_run() + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Flaky on Jython.') +def test_path_translation_and_source_reference(case_setup): + + translated_dir_not_ascii = u'áéíóú汉字' + + def get_file_in_client(writer): + # Instead of using: test_python/_debugger_case_path_translation.py + # we'll set the breakpoints at foo/_debugger_case_path_translation.py + file_in_client = os.path.dirname(os.path.dirname(writer.TEST_FILE)) + return os.path.join(os.path.dirname(file_in_client), translated_dir_not_ascii, '_debugger_case_path_translation.py') + + def get_environ(writer): + env = os.environ.copy() + + env["PYTHONIOENCODING"] = 'utf-8' + return env + + with case_setup.test_file('_debugger_case_path_translation.py', get_environ=get_environ) as writer: + file_in_client = get_file_in_client(writer) + assert 'tests_python' not in file_in_client + assert translated_dir_not_ascii in file_in_client + + json_facade = JsonFacade(writer) + + bp_line = writer.get_line_index_with_content('break here') + assert writer.TEST_FILE.endswith('_debugger_case_path_translation.py') + local_root = os.path.dirname(get_file_in_client(writer)) + json_facade.write_launch(pathMappings=[{ + 'localRoot': local_root, + 'remoteRoot': os.path.dirname(writer.TEST_FILE), + }]) + json_facade.write_set_breakpoints(bp_line, filename=file_in_client) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + + # : :type stack_trace_response: StackTraceResponse + # : :type stack_trace_response_body: StackTraceResponseBody + # : :type stack_frame: StackFrame + + # Check stack trace format. + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments( + threadId=json_hit.thread_id, + format={'module': True, 'line': True} + ))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_trace_response_body = stack_trace_response.body + stack_frame = stack_trace_response_body.stackFrames[0] + assert stack_frame['name'] == '__main__.call_this : %s' % (bp_line,) + + path = stack_frame['source']['path'] + file_in_client_unicode = file_in_client + + assert path == file_in_client_unicode + source_reference = stack_frame['source']['sourceReference'] + assert source_reference == 0 # When it's translated the source reference must be == 0 + + stack_frame_not_path_translated = stack_trace_response_body.stackFrames[1] + if not stack_frame_not_path_translated['name'].startswith( + 'tests_python.resource_path_translation.other.call_me_back1 :'): + raise AssertionError('Error. Found: >>%s<<.' % (stack_frame_not_path_translated['name'],)) + + assert stack_frame_not_path_translated['source']['path'].endswith('other.py') + source_reference = stack_frame_not_path_translated['source']['sourceReference'] + assert source_reference != 0 # Not translated + + response = json_facade.write_get_source(source_reference) + assert "def call_me_back1(callback):" in response.body.content + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_JYTHON, reason='Flaky on Jython.') +def test_source_reference_no_file(case_setup, tmpdir): + + with case_setup.test_file('_debugger_case_source_reference.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch( + debugOptions=['DebugStdLib'], + pathMappings=[{ + 'localRoot': os.path.dirname(writer.TEST_FILE), + 'remoteRoot': os.path.dirname(writer.TEST_FILE), + }]) + + writer.write_add_breakpoint(writer.get_line_index_with_content('breakpoint')) + json_facade.write_make_initial_run() + + # First hit is for breakpoint reached via a stack frame that doesn't have source. + + json_hit = json_facade.wait_for_thread_stopped() + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments( + threadId=json_hit.thread_id, + format={'module': True, 'line': True} + ))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_trace_response_body = stack_trace_response.body + stack_frame = stack_trace_response_body.stackFrames[1] + assert stack_frame['source']['path'] == '' + source_reference = stack_frame['source']['sourceReference'] + assert source_reference != 0 + + json_facade.write_get_source(source_reference, success=False) + + json_facade.write_continue() + + # First hit is for breakpoint reached via a stack frame that doesn't have source + # on disk, but which can be retrieved via linecache. + + json_hit = json_facade.wait_for_thread_stopped() + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments( + threadId=json_hit.thread_id, + format={'module': True, 'line': True} + ))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_trace_response_body = stack_trace_response.body + stack_frame = stack_trace_response_body.stackFrames[1] + print(stack_frame['source']['path']) + assert stack_frame['source']['path'] == '' + source_reference = stack_frame['source']['sourceReference'] + assert source_reference != 0 + + response = json_facade.write_get_source(source_reference) + assert response.body.content == 'foo()\n' + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +def test_linecache_json_existing_file(case_setup, tmpdir): + + with case_setup.test_file('_debugger_case_linecache_existing_file.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=False) + + debugger_case_stepping_filename = debugger_unittest._get_debugger_test_file('_debugger_case_stepping.py') + bp_line = writer.get_line_index_with_content('Break here 1', filename=debugger_case_stepping_filename) + json_facade.write_set_breakpoints(bp_line, filename=debugger_case_stepping_filename) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + stack_trace_response_body = json_hit.stack_trace_response.body + for stack_frame in stack_trace_response_body.stackFrames: + source_reference = stack_frame['source']['sourceReference'] + assert source_reference == 0 + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +def test_linecache_json(case_setup, tmpdir): + + with case_setup.test_file('_debugger_case_linecache.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=False) + + writer.write_add_breakpoint(writer.get_line_index_with_content('breakpoint')) + json_facade.write_make_initial_run() + + # First hit is for breakpoint reached via a stack frame that doesn't have source. + + json_hit = json_facade.wait_for_thread_stopped() + stack_trace_response_body = json_hit.stack_trace_response.body + source_references = [] + for stack_frame in stack_trace_response_body.stackFrames: + if stack_frame['source']['path'] == '': + source_reference = stack_frame['source']['sourceReference'] + assert source_reference != 0 + source_references.append(source_reference) + + # Each frame gets its own source reference. + assert len(set(source_references)) == 2 + + for source_reference in source_references: + response = json_facade.write_get_source(source_reference) + assert 'def somemethod():' in response.body.content + assert ' foo()' in response.body.content + assert '[x for x in range(10)]' in response.body.content + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.') +def test_show_bytecode_json(case_setup, tmpdir): + + with case_setup.test_file('_debugger_case_show_bytecode.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(justMyCode=False) + + writer.write_add_breakpoint(writer.get_line_index_with_content('breakpoint')) + json_facade.write_make_initial_run() + + # First hit is for breakpoint reached via a stack frame that doesn't have source. + + json_hit = json_facade.wait_for_thread_stopped() + stack_trace_response_body = json_hit.stack_trace_response.body + source_references = [] + for stack_frame in stack_trace_response_body.stackFrames: + if stack_frame['source']['path'] == '': + source_reference = stack_frame['source']['sourceReference'] + assert source_reference != 0 + source_references.append(source_reference) + + # Each frame gets its own source reference. + assert len(set(source_references)) == 2 + + for source_reference in source_references: + response = json_facade.write_get_source(source_reference) + assert 'MyClass' in response.body.content or 'foo()' in response.body.content + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_DJANGO, reason='No django available') +@pytest.mark.parametrize("jmc", [False, True]) +def test_case_django_no_attribute_exception_breakpoint(case_setup_django, jmc): + import django # noqa (may not be there if TEST_DJANGO == False) + django_version = [int(x) for x in django.get_version().split('.')][:2] + + if django_version < [2, 1]: + pytest.skip('Template exceptions only supporting Django 2.1 onwards.') + + with case_setup_django.test_file(EXPECTED_RETURNCODE='any') as writer: + json_facade = JsonFacade(writer) + + if jmc: + writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('my_code')]) + json_facade.write_launch(debugOptions=['Django'], variablePresentation={ + "all": "hide", + "protected": "inline", + }) + json_facade.write_set_exception_breakpoints(['raised']) + else: + json_facade.write_launch(debugOptions=['DebugStdLib', 'Django'], variablePresentation={ + "all": "hide", + "protected": "inline", + }) + # Don't set to all 'raised' because we'd stop on standard library exceptions here + # (which is not something we want). + json_facade.write_set_exception_breakpoints(exception_options=[ + ExceptionOptions(breakMode='always', path=[ + {'names': ['Python Exceptions']}, + {'names': ['AssertionError']}, + ]) + ]) + + writer.write_make_initial_run() + + t = writer.create_request_thread('my_app/template_error') + time.sleep(5) # Give django some time to get to startup before requesting the page + t.start() + + json_hit = json_facade.wait_for_thread_stopped('exception', line=7, file='template_error.html') + + stack_trace_request = json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments( + threadId=json_hit.thread_id, + format={'module': True, 'line': True} + ))) + stack_trace_response = json_facade.wait_for_response(stack_trace_request) + stack_trace_response_body = stack_trace_response.body + stack_frame = next(iter(stack_trace_response_body.stackFrames)) + assert stack_frame['source']['path'].endswith('template_error.html') + + json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + variables_response = json_facade.get_variables_response(json_hit.frame_id) + entries = [x for x in variables_response.to_dict()['body']['variables'] if x['name'] == 'entry'] + assert len(entries) == 1 + variables_response = json_facade.get_variables_response(entries[0]['variablesReference']) + assert variables_response.to_dict()['body']['variables'] == [ + {'name': 'key', 'value': "'v1'", 'type': 'str', 'evaluateName': 'entry.key', 'presentationHint': {'attributes': ['rawString']}, 'variablesReference': 0}, + {'name': 'val', 'value': "'v1'", 'type': 'str', 'evaluateName': 'entry.val', 'presentationHint': {'attributes': ['rawString']}, 'variablesReference': 0} + ] + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_DJANGO, reason='No django available') +def test_case_django_line_validation(case_setup_django): + import django # noqa (may not be there if TEST_DJANGO == False) + django_version = [int(x) for x in django.get_version().split('.')][:2] + + support_lazy_line_validation = django_version >= [1, 9] + + import django # noqa (may not be there if TEST_DJANGO == False) + + with case_setup_django.test_file(EXPECTED_RETURNCODE='any') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch(debugOptions=['DebugStdLib', 'Django']) + template_file = debugger_unittest._get_debugger_test_file(os.path.join(writer.DJANGO_FOLDER, 'my_app', 'templates', 'my_app', 'index.html')) + file_doesnt_exist = os.path.join(os.path.dirname(template_file), 'this_does_not_exist.html') + + # At this point, breakpoints will still not be verified (that'll happen when we + # actually load the template). + if support_lazy_line_validation: + json_facade.write_set_breakpoints([1, 2, 4], template_file, verified=False) + else: + json_facade.write_set_breakpoints([1, 2, 4], template_file, verified=True) + + writer.write_make_initial_run() + + t = writer.create_request_thread('my_app') + time.sleep(5) # Give django some time to get to startup before requesting the page + t.start() + + json_facade.wait_for_thread_stopped(line=1) + breakpoint_events = json_facade.mark_messages(BreakpointEvent) + + found = {} + for breakpoint_event in breakpoint_events: + bp = breakpoint_event.body.breakpoint + found[bp.id] = (bp.verified, bp.line) + + if support_lazy_line_validation: + # At this point breakpoints were added. + # id=0 / Line 1 is ok + # id=1 / Line 2 will be disabled (because line 1 is already taken) + # id=2 / Line 4 will be moved to line 3 + assert found == { + 0: (True, 1), + 1: (False, 2), + 2: (True, 3), + } + else: + assert found == {} + + # Now, after the template was loaded, when setting the breakpoints we can already + # know about the template validation. + if support_lazy_line_validation: + json_facade.write_set_breakpoints( + [1, 2, 8], template_file, expected_lines_in_response=set((1, 2, 7)), + # i.e.: breakpoint id to whether it's verified. + verified={3: True, 4: False, 5: True}) + else: + json_facade.write_set_breakpoints( + [1, 2, 7], template_file, verified=True) + + json_facade.write_continue() + json_facade.wait_for_thread_stopped(line=7) + + json_facade.write_continue() + json_facade.wait_for_thread_stopped(line=7) + + # To finish, check that setting on a file that doesn't exist is not verified. + response = json_facade.write_set_breakpoints([1], file_doesnt_exist, verified=False) + for bp in response.body.breakpoints: + assert 'Breakpoint in file that does not exist' in bp['message'] + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_FLASK, reason='No flask available') +def test_case_flask_line_validation(case_setup_flask): + with case_setup_flask.test_file(EXPECTED_RETURNCODE='any') as writer: + json_facade = JsonFacade(writer) + writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('flask1')]) + json_facade.write_launch(debugOptions=['Jinja']) + json_facade.write_make_initial_run() + + template_file = debugger_unittest._get_debugger_test_file(os.path.join('flask1', 'templates', 'hello.html')) + + # At this point, breakpoints will still not be verified (that'll happen when we + # actually load the template). + json_facade.write_set_breakpoints([1, 5, 6, 10], template_file, verified=False) + + writer.write_make_initial_run() + + t = writer.create_request_thread() + time.sleep(2) # Give flask some time to get to startup before requesting the page + t.start() + + json_facade.wait_for_thread_stopped(line=5) + breakpoint_events = json_facade.mark_messages(BreakpointEvent) + + found = {} + for breakpoint_event in breakpoint_events: + bp = breakpoint_event.body.breakpoint + found[bp.id] = (bp.verified, bp.line) + + # At this point breakpoints were added. + # id=0 / Line 1 will be disabled + # id=1 / Line 5 is correct + # id=2 / Line 6 will be disabled (because line 5 is already taken) + # id=3 / Line 10 will be moved to line 8 + assert found == { + 0: (False, 1), + 1: (True, 5), + 2: (False, 6), + 3: (True, 8), + } + + json_facade.write_continue() + + json_facade.wait_for_thread_stopped(line=8) + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not TEST_FLASK, reason='No flask available') +@pytest.mark.parametrize("jmc", [False, True]) +def test_case_flask_exceptions(case_setup_flask, jmc): + with case_setup_flask.test_file(EXPECTED_RETURNCODE='any') as writer: + json_facade = JsonFacade(writer) + + if jmc: + ignore_py_exceptions = False + writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('my_code')]) + json_facade.write_launch(debugOptions=['Jinja']) + json_facade.write_set_exception_breakpoints(['raised']) + else: + ignore_py_exceptions = True + json_facade.write_launch(debugOptions=['DebugStdLib', 'Jinja']) + # Don't set to all 'raised' because we'd stop on standard library exceptions here + # (which is not something we want). + json_facade.write_set_exception_breakpoints(exception_options=[ + ExceptionOptions(breakMode='always', path=[ + {'names': ['Python Exceptions']}, + {'names': ['IndexError']}, + ]) + ]) + json_facade.write_make_initial_run() + + t = writer.create_request_thread('/bad_template') + time.sleep(2) # Give flask some time to get to startup before requesting the page + t.start() + + while True: + json_hit = json_facade.wait_for_thread_stopped('exception') + path = json_hit.stack_trace_response.body.stackFrames[0]['source']['path'] + found_line = json_hit.stack_trace_response.body.stackFrames[0]['line'] + if path.endswith('bad.html'): + assert found_line == 8 + json_facade.write_continue() + break + + if ignore_py_exceptions and path.endswith('.py'): + json_facade.write_continue() + continue + + raise AssertionError('Unexpected thread stop: at %s, %s' % (path, found_line)) + + writer.finished_ok = True + + +@pytest.mark.skipif(IS_APPVEYOR or IS_JYTHON, reason='Flaky on appveyor / Jython encoding issues (needs investigation).') +def test_redirect_output(case_setup): + + def get_environ(writer): + env = os.environ.copy() + + env["PYTHONIOENCODING"] = 'utf-8' + return env + + with case_setup.test_file('_debugger_case_redirect.py', get_environ=get_environ) as writer: + original_ignore_stderr_line = writer._ignore_stderr_line + + json_facade = JsonFacade(writer) + + @overrides(writer._ignore_stderr_line) + def _ignore_stderr_line(line): + if original_ignore_stderr_line(line): + return True + + binary_junk = b'\xe8\xF0\x80\x80\x80' + if sys.version_info[0] >= 3: + binary_junk = binary_junk.decode('utf-8', 'replace') + + return line.startswith(( + 'text', + 'binary', + 'a', + binary_junk, + )) + + writer._ignore_stderr_line = _ignore_stderr_line + + # Note: writes to stdout and stderr are now synchronous (so, the order + # must always be consistent and there's a message for each write). + + expected = [ + 'text\n', + 'binary or text\n', + 'ação1\n', + ] + + if sys.version_info[0] >= 3: + expected.extend(( + 'binary\n', + 'ação2\n'.encode(encoding='latin1').decode('utf-8', 'replace'), + 'ação3\n', + )) + + binary_junk = '\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\n\n' + if sys.version_info[0] >= 3: + binary_junk = "\ufffd\ufffd\ufffd\ufffd\ufffd\n\n" + expected.append(binary_junk) + + new_expected = [(x, 'stdout') for x in expected] + new_expected.extend([(x, 'stderr') for x in expected]) + + writer.write_start_redirect() + + writer.write_make_initial_run() + msgs = [] + ignored = [] + while len(msgs) < len(new_expected): + try: + output_event = json_facade.wait_for_json_message(OutputEvent) + output = output_event.body.output + category = output_event.body.category + msg = (output, category) + except Exception: + for msg in msgs: + sys.stderr.write('Found: %s\n' % (msg,)) + for msg in new_expected: + sys.stderr.write('Expected: %s\n' % (msg,)) + for msg in ignored: + sys.stderr.write('Ignored: %s\n' % (msg,)) + raise + if msg not in new_expected: + ignored.append(msg) + continue + msgs.append(msg) + + if msgs != new_expected: + print(msgs) + print(new_expected) + assert msgs == new_expected + writer.finished_ok = True + + +def test_listen_dap_messages(case_setup): + + with case_setup.test_file('_debugger_case_listen_dap_messages.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(debugOptions=['RedirectOutput'],) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped() + json_facade.write_continue() + + writer.finished_ok = True + + +def _attach_to_writer_pid(writer): + import pydevd + import threading + import subprocess + + assert writer.process is not None + + def attach(): + attach_pydevd_file = os.path.join(os.path.dirname(pydevd.__file__), 'pydevd_attach_to_process', 'attach_pydevd.py') + subprocess.call([sys.executable, attach_pydevd_file, '--pid', str(writer.process.pid), '--port', str(writer.port), '--protocol', 'http_json']) + + threading.Thread(target=attach).start() + + wait_for_condition(lambda: writer.finished_initialization) + + +@pytest.mark.parametrize('reattach', [True, False]) +@pytest.mark.skipif(not IS_CPYTHON or IS_MAC, reason='Attach to pid only available in CPython (brittle on Mac).') +def test_attach_to_pid(case_setup_remote, reattach): + import threading + + with case_setup_remote.test_file('_debugger_case_attach_to_pid_simple.py', wait_for_port=False) as writer: + time.sleep(1) # Give it some time to initialize to get to the while loop. + _attach_to_writer_pid(writer) + json_facade = JsonFacade(writer) + + bp_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(bp_line) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=bp_line) + + if reattach: + # This would be the same as a second attach to pid, so, the idea is closing the current + # connection and then doing a new attach to pid. + json_facade.write_set_breakpoints([]) + json_facade.write_continue() + + writer.do_kill() # This will simply close the open sockets without doing anything else. + time.sleep(1) + + t = threading.Thread(target=writer.start_socket) + t.start() + wait_for_condition(lambda: hasattr(writer, 'port')) + time.sleep(1) + writer.process = writer.process + _attach_to_writer_pid(writer) + wait_for_condition(lambda: hasattr(writer, 'reader_thread')) + time.sleep(1) + + json_facade = JsonFacade(writer) + json_facade.write_set_breakpoints(bp_line) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped(line=bp_line) + + json_facade.write_set_variable(json_hit.frame_id, 'wait', '0') + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_remote_debugger_basic(case_setup_remote): + with case_setup_remote.test_file('_debugger_case_remote.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped() + json_facade.write_continue() + + writer.finished_ok = True + + +PYDEVD_CUSTOMIZATION_COMMAND_LINE_ARGS = ['', '--use-c-switch'] +if hasattr(os, 'posix_spawn'): + PYDEVD_CUSTOMIZATION_COMMAND_LINE_ARGS.append('--posix-spawn') + + +@pytest.mark.parametrize('command_line_args', PYDEVD_CUSTOMIZATION_COMMAND_LINE_ARGS) +def test_subprocess_pydevd_customization(case_setup_remote, command_line_args): + import threading + from tests_python.debugger_unittest import AbstractWriterThread + + with case_setup_remote.test_file( + '_debugger_case_pydevd_customization.py', + append_command_line_args=command_line_args if command_line_args else [], + ) as writer: + json_facade = JsonFacade(writer, send_json_startup_messages=False) + json_facade.writer.write_multi_threads_single_notification(True) + json_facade.write_launch() + + break1_line = writer.get_line_index_with_content('break 1 here') + break2_line = writer.get_line_index_with_content('break 2 here') + json_facade.write_set_breakpoints([break1_line, break2_line]) + + server_socket = writer.server_socket + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + expected_connections = 1 + + for _ in range(expected_connections): + server_socket.listen(1) + self.server_socket = server_socket + writer.log.append(' *** Multiprocess waiting on server_socket.accept()') + new_sock, addr = server_socket.accept() + writer.log.append(' *** Multiprocess completed server_socket.accept()') + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + writer.log.append(' *** Multiprocess started ReaderThread') + + writer2 = SecondaryProcessWriterThread() + writer2._WRITE_LOG_PREFIX = ' *** Multiprocess write: ' + writer2.reader_thread = reader_thread + writer2.sock = new_sock + json_facade2 = JsonFacade(writer2, send_json_startup_messages=False) + json_facade2.writer.write_multi_threads_single_notification(True) + + json_facade2.write_set_breakpoints([break1_line, break2_line]) + json_facade2.write_make_initial_run() + + json_facade2.wait_for_thread_stopped() + json_facade2.write_continue() + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + time.sleep(.1) + + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped() + + json_facade.write_continue() + json_facade.wait_for_thread_stopped() + json_facade.write_continue() + + secondary_process_thread_communication.join(5) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + writer.finished_ok = True + + +def test_subprocess_then_fork(case_setup_multiprocessing): + import threading + from tests_python.debugger_unittest import AbstractWriterThread + + with case_setup_multiprocessing.test_file('_debugger_case_subprocess_and_fork.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + + break_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints([break_line]) + + server_socket = writer.server_socket + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + + # Note that we accept 2 connections and then we proceed to receive the breakpoints. + json_facades = [] + for i in range(2): + server_socket.listen(1) + self.server_socket = server_socket + writer.log.append(' *** Multiprocess %s waiting on server_socket.accept()' % (i,)) + new_sock, addr = server_socket.accept() + writer.log.append(' *** Multiprocess %s completed server_socket.accept()' % (i,)) + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess %s Reader Thread' % i + reader_thread.start() + writer.log.append(' *** Multiprocess %s started ReaderThread' % (i,)) + + writer2 = SecondaryProcessWriterThread() + writer2._WRITE_LOG_PREFIX = ' *** Multiprocess %s write: ' % i + writer2.reader_thread = reader_thread + writer2.sock = new_sock + json_facade2 = JsonFacade(writer2, send_json_startup_messages=False) + json_facade2.writer.write_multi_threads_single_notification(True) + writer.log.append(' *** Multiprocess %s write attachThread' % (i,)) + json_facade2.write_attach(justMyCode=False) + + writer.log.append(' *** Multiprocess %s write set breakpoints' % (i,)) + json_facade2.write_set_breakpoints([break_line]) + writer.log.append(' *** Multiprocess %s write make initial run' % (i,)) + json_facade2.write_make_initial_run() + json_facades.append(json_facade2) + + for i, json_facade3 in enumerate(json_facades): + writer.log.append(' *** Multiprocess %s wait for thread stopped' % (i,)) + json_facade3.wait_for_thread_stopped(line=break_line) + writer.log.append(' *** Multiprocess %s continue' % (i,)) + json_facade3.write_continue() + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + time.sleep(.1) + json_facade.write_make_initial_run() + + secondary_process_thread_communication.join(20) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + + json_facade.wait_for_thread_stopped(line=break_line) + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('apply_multiprocessing_patch', [True, False]) +def test_no_subprocess_patching(case_setup_multiprocessing, apply_multiprocessing_patch): + import threading + from tests_python.debugger_unittest import AbstractWriterThread + + def update_command_line_args(writer, args): + ret = debugger_unittest.AbstractWriterThread.update_command_line_args(writer, args) + ret.insert(ret.index('--client'), '--multiprocess') + if apply_multiprocessing_patch: + ret.append('apply-multiprocessing-patch') + return ret + + with case_setup_multiprocessing.test_file( + '_debugger_case_no_subprocess_patching.py', + update_command_line_args=update_command_line_args + ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + + break1_line = writer.get_line_index_with_content('break 1 here') + break2_line = writer.get_line_index_with_content('break 2 here') + json_facade.write_set_breakpoints([break1_line, break2_line]) + + server_socket = writer.server_socket + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + expected_connections = 1 + + for _ in range(expected_connections): + server_socket.listen(1) + self.server_socket = server_socket + new_sock, addr = server_socket.accept() + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + + writer2 = SecondaryProcessWriterThread() + writer2.reader_thread = reader_thread + writer2.sock = new_sock + json_facade2 = JsonFacade(writer2) + + json_facade2.write_set_breakpoints([break1_line, break2_line]) + json_facade2.write_make_initial_run() + + json_facade2.wait_for_thread_stopped() + json_facade2.write_continue() + + if apply_multiprocessing_patch: + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + time.sleep(.1) + + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped() + json_facade.write_continue() + + if apply_multiprocessing_patch: + secondary_process_thread_communication.join(10) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + writer.finished_ok = True + + +def test_module_crash(case_setup): + with case_setup.test_file('_debugger_case_module.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + stopped_event = json_facade.wait_for_json_message(StoppedEvent) + thread_id = stopped_event.body.threadId + + json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=thread_id))) + + module_event = json_facade.wait_for_json_message(ModuleEvent) # : :type module_event: ModuleEvent + assert 'MyName' in module_event.body.module.name + assert 'MyVersion' in module_event.body.module.version + assert 'MyPackage' in module_event.body.module.kwargs['package'] + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_pydevd_systeminfo(case_setup): + with case_setup.test_file('_debugger_case_print.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + assert json_hit.thread_id + + info_request = json_facade.write_request( + pydevd_schema.PydevdSystemInfoRequest( + pydevd_schema.PydevdSystemInfoArguments() + ) + ) + info_response = json_facade.wait_for_response(info_request) + body = info_response.to_dict()['body'] + + assert body['python']['version'] == PY_VERSION_STR + assert body['python']['implementation']['name'] == PY_IMPL_NAME + assert body['python']['implementation']['version'] == PY_IMPL_VERSION_STR + assert 'description' in body['python']['implementation'] + + assert body['platform'] == {'name': sys.platform} + + assert 'pid' in body['process'] + assert 'ppid' in body['process'] + assert body['process']['executable'] == sys.executable + assert body['process']['bitness'] == 64 if IS_64BIT_PROCESS else 32 + + assert 'usingCython' in body['pydevd'] + assert 'usingFrameEval' in body['pydevd'] + + use_cython = os.getenv('PYDEVD_USE_CYTHON') + if use_cython is not None: + using_cython = use_cython == 'YES' + assert body['pydevd']['usingCython'] == using_cython + assert body['pydevd']['usingFrameEval'] == (using_cython and IS_PY36_OR_GREATER and not TODO_PY311) + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('scenario', [ + 'terminate_request', + 'terminate_debugee' +]) +@pytest.mark.parametrize('check_subprocesses', [ + 'no_subprocesses', + 'kill_subprocesses', + 'kill_subprocesses_ignore_pid', + 'dont_kill_subprocesses', +]) +def test_terminate(case_setup, scenario, check_subprocesses): + import psutil + + def check_test_suceeded_msg(writer, stdout, stderr): + return 'TEST SUCEEDED' not in ''.join(stdout) + + def update_command_line_args(writer, args): + ret = debugger_unittest.AbstractWriterThread.update_command_line_args(writer, args) + if check_subprocesses in ('kill_subprocesses', 'dont_kill_subprocesses'): + ret.append('check-subprocesses') + if check_subprocesses in ('kill_subprocesses_ignore_pid',): + ret.append('check-subprocesses-ignore-pid') + return ret + + with case_setup.test_file( + '_debugger_case_terminate.py', + check_test_suceeded_msg=check_test_suceeded_msg, + update_command_line_args=update_command_line_args, + EXPECTED_RETURNCODE='any' if check_subprocesses == 'kill_subprocesses_ignore_pid' else 0, + ) as writer: + json_facade = JsonFacade(writer) + if check_subprocesses == 'dont_kill_subprocesses': + json_facade.write_launch(terminateChildProcesses=False) + + json_facade.write_make_initial_run() + response = json_facade.write_initialize() + pid = response.to_dict()['body']['pydevd']['processId'] + + if check_subprocesses in ('kill_subprocesses', 'dont_kill_subprocesses', 'kill_subprocesses_ignore_pid'): + process_ids_to_check = [pid] + p = psutil.Process(pid) + + def wait_for_child_processes(): + children = p.children(recursive=True) + found = len(children) + if found == 8: + process_ids_to_check.extend([x.pid for x in children]) + return True + return False + + wait_for_condition(wait_for_child_processes) + + if scenario == 'terminate_request': + json_facade.write_terminate() + elif scenario == 'terminate_debugee': + json_facade.write_disconnect(terminate_debugee=True) + else: + raise AssertionError('Unexpected: %s' % (scenario,)) + json_facade.wait_for_terminated() + + if check_subprocesses in ('kill_subprocesses', 'dont_kill_subprocesses', 'kill_subprocesses_ignore_pid'): + + def is_pid_alive(pid): + # Note: the process may be a zombie process in Linux + # (althought it's killed it remains in that state + # because we're monitoring it). + try: + proc = psutil.Process(pid) + if proc.status() == psutil.STATUS_ZOMBIE: + return False + except psutil.NoSuchProcess: + return False + return True + + def get_live_pids(): + return [pid for pid in process_ids_to_check if is_pid_alive(pid)] + + if check_subprocesses == 'kill_subprocesses': + + def all_pids_exited(): + live_pids = get_live_pids() + if live_pids: + return False + + return True + + wait_for_condition(all_pids_exited) + + elif check_subprocesses == 'kill_subprocesses_ignore_pid': + + def all_pids_exited(): + live_pids = get_live_pids() + if len(live_pids) == 1: + return False + + return True + + wait_for_condition(all_pids_exited) + + # Now, let's kill the remaining process ourselves. + for pid in get_live_pids(): + proc = psutil.Process(pid) + proc.kill() + + else: # 'dont_kill_subprocesses' + time.sleep(1) + + def only_main_pid_exited(): + live_pids = get_live_pids() + if len(live_pids) == len(process_ids_to_check) - 1: + return True + + return False + + wait_for_condition(only_main_pid_exited) + + # Now, let's kill the remaining processes ourselves. + for pid in get_live_pids(): + proc = psutil.Process(pid) + proc.kill() + + writer.finished_ok = True + + +def test_access_token(case_setup): + + def update_command_line_args(self, args): + args.insert(1, '--json-dap-http') + args.insert(2, '--access-token') + args.insert(3, 'bar123') + args.insert(4, '--client-access-token') + args.insert(5, 'foo321') + return args + + with case_setup.test_file('_debugger_case_pause_continue.py', update_command_line_args=update_command_line_args) as writer: + json_facade = JsonFacade(writer, send_json_startup_messages=False) + + response = json_facade.write_set_debugger_property(multi_threads_single_notification=True, success=False) + assert response.message == "Client not authenticated." + + response = json_facade.write_authorize(access_token='wrong', success=False) + assert response.message == "Client not authenticated." + + response = json_facade.write_set_debugger_property(multi_threads_single_notification=True, success=False) + assert response.message == "Client not authenticated." + + authorize_response = json_facade.write_authorize(access_token='bar123', success=True) + # : :type authorize_response:PydevdAuthorizeResponse + assert authorize_response.body.clientAccessToken == 'foo321' + + json_facade.write_set_debugger_property(multi_threads_single_notification=True) + json_facade.write_launch() + + break_line = writer.get_line_index_with_content('Pause here and change loop to False') + json_facade.write_set_breakpoints(break_line) + json_facade.write_make_initial_run() + + json_facade.wait_for_json_message(ThreadEvent, lambda event: event.body.reason == 'started') + json_facade.wait_for_thread_stopped(line=break_line) + + # : :type response: ThreadsResponse + response = json_facade.write_list_threads() + assert len(response.body.threads) == 1 + assert next(iter(response.body.threads))['name'] == 'MainThread' + + json_facade.write_disconnect() + + response = json_facade.write_authorize(access_token='wrong', success=False) + assert response.message == "Client not authenticated." + + authorize_response = json_facade.write_authorize(access_token='bar123') + assert authorize_response.body.clientAccessToken == 'foo321' + + json_facade.write_set_breakpoints(break_line) + json_hit = json_facade.wait_for_thread_stopped(line=break_line) + json_facade.write_set_variable(json_hit.frame_id, 'loop', 'False') + json_facade.write_continue() + json_facade.wait_for_terminated() + + writer.finished_ok = True + + +def test_stop_on_entry(case_setup): + with case_setup.test_file('not_my_code/main_on_entry.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch( + justMyCode=False, + stopOnEntry=True, + rules=[ + {'path': '**/not_my_code/**', 'include':False}, + ] + ) + + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped( + 'entry', + file=( + # We need to match the end with the proper slash. + 'my_code/__init__.py', + 'my_code\\__init__.py' + ) + ) + json_facade.write_continue() + writer.finished_ok = True + + +def test_stop_on_entry2(case_setup): + with case_setup.test_file('not_my_code/main_on_entry2.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch( + justMyCode=False, + stopOnEntry=True, + showReturnValue=True, + rules=[ + {'path': '**/main_on_entry2.py', 'include':False}, + ] + ) + + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped( + 'entry', + file='empty_file.py' + ) + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.parametrize('val', [True, False]) +def test_debug_options(case_setup, val): + with case_setup.test_file('_debugger_case_debug_options.py') as writer: + json_facade = JsonFacade(writer) + gui_event_loop = 'matplotlib' + if val: + try: + import PySide2.QtCore + except ImportError: + pass + else: + gui_event_loop = 'qt5' + args = dict( + justMyCode=val, + redirectOutput=True, # Always redirect the output regardless of other values. + showReturnValue=val, + breakOnSystemExitZero=val, + django=val, + flask=val, + stopOnEntry=val, + maxExceptionStackFrames=4 if val else 5, + guiEventLoop=gui_event_loop, + ) + json_facade.write_launch(**args) + + json_facade.write_make_initial_run() + if args['stopOnEntry']: + json_facade.wait_for_thread_stopped('entry') + json_facade.write_continue() + + output = json_facade.wait_for_json_message( + OutputEvent, lambda msg: msg.body.category == 'stdout' and msg.body.output.startswith('{')and msg.body.output.endswith('}')) + + # The values printed are internal values from _pydevd_bundle.pydevd_json_debug_options.DebugOptions, + # not the parameters we passed. + translation = { + 'django': 'django_debug', + 'flask': 'flask_debug', + 'justMyCode': 'just_my_code', + 'redirectOutput': 'redirect_output', + 'showReturnValue': 'show_return_value', + 'breakOnSystemExitZero': 'break_system_exit_zero', + 'stopOnEntry': 'stop_on_entry', + 'maxExceptionStackFrames': 'max_exception_stack_frames', + 'guiEventLoop': 'gui_event_loop', + } + + assert json.loads(output.body.output) == dict((translation[key], val) for key, val in args.items()) + json_facade.wait_for_terminated() + writer.finished_ok = True + + +def test_gui_event_loop_custom(case_setup): + with case_setup.test_file('_debugger_case_gui_event_loop.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(guiEventLoop='__main__.LoopHolder.gui_loop', redirectOutput=True) + break_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(break_line) + + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped() + + json_facade.wait_for_json_message( + OutputEvent, lambda msg: msg.body.category == 'stdout' and 'gui_loop() called' in msg.body.output) + + json_facade.write_continue() + json_facade.wait_for_terminated() + writer.finished_ok = True + + +def test_gui_event_loop_qt5(case_setup): + try: + from PySide2 import QtCore + except ImportError: + pytest.skip('PySide2 not available') + + with case_setup.test_file('_debugger_case_gui_event_loop_qt5.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(guiEventLoop='qt5', redirectOutput=True) + break_line = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints(break_line) + + json_facade.write_make_initial_run() + json_facade.wait_for_thread_stopped() + + # i.e.: if we don't have the event loop running in this test, this + # output is not shown (as the QTimer timeout wouldn't be executed). + for _i in range(3): + json_facade.wait_for_json_message( + OutputEvent, lambda msg: msg.body.category == 'stdout' and 'on_timeout() called' in msg.body.output) + + json_facade.write_continue() + json_facade.wait_for_terminated() + writer.finished_ok = True + + +@pytest.mark.parametrize('debug_stdlib', [True, False]) +def test_just_my_code_debug_option_deprecated(case_setup, debug_stdlib, debugger_runner_simple): + from _pydev_bundle import pydev_log + with case_setup.test_file('_debugger_case_debug_options.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch( + redirectOutput=True, # Always redirect the output regardless of other values. + debugStdLib=debug_stdlib + ) + json_facade.write_make_initial_run() + output = json_facade.wait_for_json_message( + OutputEvent, lambda msg: msg.body.category == 'stdout' and msg.body.output.startswith('{')and msg.body.output.endswith('}')) + + settings = json.loads(output.body.output) + # Note: the internal attribute is just_my_code. + assert settings['just_my_code'] == (not debug_stdlib) + json_facade.wait_for_terminated() + + contents = [] + for f in pydev_log.list_log_files(debugger_runner_simple.pydevd_debug_file): + if os.path.exists(f): + with open(f, 'r') as stream: + contents.append(stream.read()) + + writer.finished_ok = True + + +def test_send_invalid_messages(case_setup): + with case_setup.test_file('_debugger_case_local_variables.py') as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break 2 here')) + json_facade.write_make_initial_run() + + stopped_event = json_facade.wait_for_json_message(StoppedEvent) + thread_id = stopped_event.body.threadId + + json_facade.write_request( + pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=thread_id))) + + # : :type response: ModulesResponse + # : :type modules_response_body: ModulesResponseBody + + # *** Check that we accept an invalid modules request (i.e.: without arguments). + response = json_facade.wait_for_response(json_facade.write_request( + {'type': 'request', 'command': 'modules'})) + + modules_response_body = response.body + assert len(modules_response_body.modules) == 1 + module = next(iter(modules_response_body.modules)) + assert module['name'] == '__main__' + assert module['path'].endswith('_debugger_case_local_variables.py') + + # *** Check that we don't fail on request without command. + request = json_facade.write_request({'type': 'request'}) + response = json_facade.wait_for_response(request, Response) + assert not response.success + assert response.command == '' + + # *** Check that we don't crash if we can't decode message. + json_facade.writer.write_with_content_len('invalid json here') + + # *** Check that we get a failure from a completions without arguments. + response = json_facade.wait_for_response(json_facade.write_request( + {'type': 'request', 'command': 'completions'})) + assert not response.success + + json_facade.write_continue() + writer.finished_ok = True + + +def test_send_json_message(case_setup): + + with case_setup.test_file('_debugger_case_custom_message.py') as writer: + json_facade = JsonFacade(writer) + + json_facade.write_launch() + + json_facade.write_make_initial_run() + + json_facade.wait_for_json_message( + OutputEvent, lambda msg: msg.body.category == 'my_category' and msg.body.output == 'some output') + + json_facade.wait_for_json_message( + OutputEvent, lambda msg: msg.body.category == 'my_category2' and msg.body.output == 'some output 2') + + writer.finished_ok = True + + +def test_global_scope(case_setup): + with case_setup.test_file('_debugger_case_globals.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_set_breakpoints(writer.get_line_index_with_content('breakpoint here')) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped() + + local_var = json_facade.get_global_var(json_hit.frame_id, 'in_global_scope') + assert local_var.value == "'in_global_scope_value'" + json_facade.write_continue() + + writer.finished_ok = True + + +def _check_inline_var_presentation(json_facade, json_hit, variables_response): + var_names = [v['name'] for v in variables_response.body.variables] + assert var_names[:3] == ['SomeClass', 'in_global_scope', '__builtins__'] + + +def _check_hide_var_presentation(json_facade, json_hit, variables_response): + var_names = [v['name'] for v in variables_response.body.variables] + assert var_names == ['in_global_scope'] + + +def _check_class_group_special_inline_presentation(json_facade, json_hit, variables_response): + var_names = [v['name'] for v in variables_response.body.variables] + assert var_names[:3] == ['class variables', 'in_global_scope', '__builtins__'] + + variables_response = json_facade.get_variables_response(variables_response.body.variables[0]['variablesReference']) + var_names = [v['name'] for v in variables_response.body.variables] + assert var_names == ['SomeClass'] + + +@pytest.mark.parametrize('var_presentation, check_func', [ + ({"all": "inline"}, _check_inline_var_presentation), + ({"all": "hide"}, _check_hide_var_presentation), + ({"class": "group", "special": "inline"}, _check_class_group_special_inline_presentation), +]) +def test_variable_presentation(case_setup, var_presentation, check_func): + with case_setup.test_file('_debugger_case_globals.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(variablePresentation=var_presentation) + json_facade.write_set_breakpoints(writer.get_line_index_with_content('breakpoint here')) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped() + name_to_scope = json_facade.get_name_to_scope(json_hit.frame_id) + + variables_response = json_facade.get_variables_response(name_to_scope['Globals'].variablesReference) + check_func(json_facade, json_hit, variables_response) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_debugger_case_deadlock_thread_eval(case_setup): + + def get_environ(self): + env = os.environ.copy() + env['PYDEVD_UNBLOCK_THREADS_TIMEOUT'] = '0.5' + return env + + with case_setup.test_file('_debugger_case_deadlock_thread_eval.py', get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here 1')) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped() + + # If threads aren't resumed, this will deadlock. + json_facade.evaluate('processor.process("process in evaluate")', json_hit.frame_id) + + json_facade.write_continue() + + writer.finished_ok = True + + +def test_debugger_case_breakpoint_on_unblock_thread_eval(case_setup): + + from _pydevd_bundle._debug_adapter.pydevd_schema import EvaluateResponse + + def get_environ(self): + env = os.environ.copy() + env['PYDEVD_UNBLOCK_THREADS_TIMEOUT'] = '0.5' + return env + + with case_setup.test_file('_debugger_case_deadlock_thread_eval.py', get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + break1 = writer.get_line_index_with_content('Break here 1') + break2 = writer.get_line_index_with_content('Break here 2') + json_facade.write_set_breakpoints([break1, break2]) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped(line=break1) + + # If threads aren't resumed, this will deadlock. + evaluate_request = json_facade.evaluate( + 'processor.process("process in evaluate")', json_hit.frame_id, wait_for_response=False) + + # We'll hit another breakpoint during that evaluation. + json_hit = json_facade.wait_for_thread_stopped(line=break2) + json_facade.write_set_breakpoints([]) + json_facade.write_continue() + + json_hit = json_facade.wait_for_thread_stopped(line=break1) + json_facade.write_continue() + + # Check that we got the evaluate responses. + messages = json_facade.mark_messages( + EvaluateResponse, lambda evaluate_response: evaluate_response.request_seq == evaluate_request.seq) + assert len(messages) == 1 + + writer.finished_ok = True + + +def test_debugger_case_unblock_manually(case_setup): + + from _pydevd_bundle._debug_adapter.pydevd_schema import EvaluateResponse + + def get_environ(self): + env = os.environ.copy() + env['PYDEVD_WARN_EVALUATION_TIMEOUT'] = '0.5' + return env + + with case_setup.test_file('_debugger_case_deadlock_thread_eval.py', get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + break1 = writer.get_line_index_with_content('Break here 1') + json_facade.write_set_breakpoints([break1]) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped(line=break1) + + # If threads aren't resumed, this will deadlock. + evaluate_request = json_facade.evaluate( + 'processor.process("process in evaluate")', json_hit.frame_id, wait_for_response=False) + + json_facade.wait_for_json_message( + OutputEvent, lambda output_event: 'did not finish after' in output_event.body.output) + + # User may manually resume it. + json_facade.write_continue() + + # Check that we got the evaluate responses. + json_facade.wait_for_json_message( + EvaluateResponse, lambda evaluate_response: evaluate_response.request_seq == evaluate_request.seq) + + writer.finished_ok = True + + +def test_debugger_case_deadlock_notify_evaluate_timeout(case_setup, pyfile): + + @pyfile + def case_slow_evaluate(): + + def slow_evaluate(): + import time + time.sleep(2) + + print('TEST SUCEEDED!') # Break here + + def get_environ(self): + env = os.environ.copy() + env['PYDEVD_WARN_EVALUATION_TIMEOUT'] = '0.5' + return env + + with case_setup.test_file(case_slow_evaluate, get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped() + + # If threads aren't resumed, this will deadlock. + json_facade.evaluate('slow_evaluate()', json_hit.frame_id) + + json_facade.write_continue() + + messages = json_facade.mark_messages( + OutputEvent, lambda output_event: 'did not finish after' in output_event.body.output) + assert len(messages) == 1 + + writer.finished_ok = True + + +def test_debugger_case_deadlock_interrupt_thread(case_setup, pyfile): + + @pyfile + def case_infinite_evaluate(): + + def infinite_evaluate(): + import time + while True: + time.sleep(.1) + + print('TEST SUCEEDED!') # Break here + + def get_environ(self): + env = os.environ.copy() + env['PYDEVD_INTERRUPT_THREAD_TIMEOUT'] = '0.5' + return env + + # Sometimes we end up with a different return code on Linux when interrupting (even + # though we go through completion and print the 'TEST SUCEEDED' msg). + with case_setup.test_file( + case_infinite_evaluate, get_environ=get_environ, EXPECTED_RETURNCODE='any') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped() + + # If threads aren't resumed, this will deadlock. + json_facade.evaluate('infinite_evaluate()', json_hit.frame_id, wait_for_response=False) + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.parametrize('launch_through_link', [True, False]) +@pytest.mark.parametrize('breakpoints_through_link', [True, False]) +def test_debugger_case_symlink(case_setup, tmpdir, launch_through_link, breakpoints_through_link): + ''' + Test that even if we resolve links internally, externally the contents will be + related to the version launched. + ''' + + from tests_python.debugger_unittest import _get_debugger_test_file + original_filename = _get_debugger_test_file('_debugger_case2.py') + + target_link = str(tmpdir.join('resources_link')) + if pydevd_constants.IS_WINDOWS and not pydevd_constants.IS_PY38_OR_GREATER: + pytest.skip('Symlink support not available.') + + try: + os.symlink(os.path.dirname(original_filename), target_link, target_is_directory=True) + except (OSError, TypeError, AttributeError): + pytest.skip('Symlink support not available.') + + try: + target_filename_in_link = os.path.join(target_link, '_debugger_case2.py') + + with case_setup.test_file(target_filename_in_link if launch_through_link else original_filename) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + + # Note that internally links are resolved to match the breakpoint, so, + # it doesn't matter if the breakpoint was added as viewed through the + # link or the real path. + json_facade.write_set_breakpoints( + writer.get_line_index_with_content("print('Start Call1')"), + filename=target_filename_in_link if breakpoints_through_link else original_filename + ) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped() + path = json_hit.stack_trace_response.body.stackFrames[0]['source']['path'] + + # Regardless of how it was hit, what's shown is what was launched. + assert path == target_filename_in_link if launch_through_link else original_filename + + json_facade.write_continue() + + writer.finished_ok = True + finally: + # We must remove the link, otherwise pytest can end up removing things under that + # directory when collecting temporary files. + os.unlink(target_link) + + +@pytest.mark.skipif(not IS_LINUX, reason='Linux only test.') +def test_debugger_case_sensitive(case_setup, tmpdir): + path = os.path.abspath(str(tmpdir.join('Path1').join('PaTh2'))) + os.makedirs(path) + target = os.path.join(path, 'myFile.py') + with open(target, 'w') as stream: + stream.write(''' +print('current file', __file__) # Break here +print('TEST SUCEEDED') +''') + assert not os.path.exists(target.lower()) + assert os.path.exists(target) + + def get_environ(self): + env = os.environ.copy() + # Force to normalize by doing filename.lower(). + env['PYDEVD_FILENAME_NORMALIZATION'] = 'lower' + return env + + # Sometimes we end up with a different return code on Linux when interrupting (even + # though we go through completion and print the 'TEST SUCEEDED' msg). + with case_setup.test_file(target, get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + json_facade.write_set_breakpoints(writer.get_line_index_with_content('Break here')) + + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped() + path = json_hit.stack_trace_response.body.stackFrames[0]['source']['path'] + assert path == target + + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif( + not IS_WINDOWS or + not IS_PY36_OR_GREATER or + not IS_CPYTHON or + not TEST_CYTHON or + TODO_PY311, # Requires frame-eval mode (still not available for Python 3.11). + reason='Windows only test and only Python 3.6 onwards.') +def test_native_threads(case_setup, pyfile): + + @pyfile + def case_native_thread(): + from ctypes import windll, WINFUNCTYPE, c_uint32, c_void_p, c_size_t + import time + + ThreadProc = WINFUNCTYPE(c_uint32, c_void_p) + + entered_thread = [False] + + @ThreadProc + def method(_): + entered_thread[0] = True # Break here + return 0 + + windll.kernel32.CreateThread(None, c_size_t(0), method, None, c_uint32(0), None) + while not entered_thread[0]: + time.sleep(.1) + + print('TEST SUCEEDED') + + with case_setup.test_file(case_native_thread) as writer: + json_facade = JsonFacade(writer) + + line = writer.get_line_index_with_content('Break here') + json_facade.write_launch(justMyCode=False) + json_facade.write_set_breakpoints(line) + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped(line=line) + + json_facade.write_continue() + writer.finished_ok = True + + +def test_code_reload(case_setup, pyfile): + + @pyfile + def mod1(): + import mod2 + import time + finish = False + for _ in range(50): + finish = mod2.do_something() + if finish: + break + time.sleep(.1) # Break 1 + else: + raise AssertionError('It seems the reload was not done in the available amount of time.') + + print('TEST SUCEEDED') # Break 2 + + @pyfile + def mod2(): + + def do_something(): + return False + + with case_setup.test_file(mod1) as writer: + json_facade = JsonFacade(writer) + + line1 = writer.get_line_index_with_content('Break 1') + line2 = writer.get_line_index_with_content('Break 2') + json_facade.write_launch(justMyCode=False, autoReload={'pollingInterval': 0, 'enable': True}) + json_facade.write_set_breakpoints([line1, line2]) + json_facade.write_make_initial_run() + + # At this point we know that 'do_something' was called at least once. + json_facade.wait_for_thread_stopped(line=line1) + json_facade.write_set_breakpoints(line2) + + with open(mod2, 'w') as stream: + stream.write(''' +def do_something(): + return True +''') + + json_facade.write_continue() + json_facade.wait_for_thread_stopped(line=line2) + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(TODO_PY311, reason='Needs bytecode support in Python 3.11') +def test_step_into_target_basic(case_setup): + with case_setup.test_file('_debugger_case_smart_step_into.py') as writer: + json_facade = JsonFacade(writer) + + bp = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints([bp]) + json_facade.write_make_initial_run() + + # At this point we know that 'do_something' was called at least once. + hit = json_facade.wait_for_thread_stopped(line=bp) + + # : :type step_in_targets: List[StepInTarget] + step_in_targets = json_facade.get_step_in_targets(hit.frame_id) + label_to_id = dict((target['label'], target['id']) for target in step_in_targets) + assert set(label_to_id.keys()) == {'bar', 'foo', 'call_outer'} + json_facade.write_step_in(hit.thread_id, target_id=label_to_id['foo']) + + on_foo_mark_line = writer.get_line_index_with_content('on foo mark') + hit = json_facade.wait_for_thread_stopped(reason='step', line=on_foo_mark_line) + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(TODO_PY311, reason='Needs bytecode support in Python 3.11') +def test_step_into_target_multiple(case_setup): + with case_setup.test_file('_debugger_case_smart_step_into2.py') as writer: + json_facade = JsonFacade(writer) + + bp = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints([bp]) + json_facade.write_make_initial_run() + + # At this point we know that 'do_something' was called at least once. + hit = json_facade.wait_for_thread_stopped(line=bp) + + # : :type step_in_targets: List[StepInTarget] + step_in_targets = json_facade.get_step_in_targets(hit.frame_id) + label_to_id = dict((target['label'], target['id']) for target in step_in_targets) + assert set(label_to_id.keys()) == {'foo', 'foo (call 2)', 'foo (call 3)', 'foo (call 4)'} + json_facade.write_step_in(hit.thread_id, target_id=label_to_id['foo (call 2)']) + + on_foo_mark_line = writer.get_line_index_with_content('on foo mark') + hit = json_facade.wait_for_thread_stopped(reason='step', line=on_foo_mark_line) + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(TODO_PY311, reason='Needs bytecode support in Python 3.11') +def test_step_into_target_genexpr(case_setup): + with case_setup.test_file('_debugger_case_smart_step_into3.py') as writer: + json_facade = JsonFacade(writer) + + bp = writer.get_line_index_with_content('break here') + json_facade.write_set_breakpoints([bp]) + json_facade.write_make_initial_run() + + # At this point we know that 'do_something' was called at least once. + hit = json_facade.wait_for_thread_stopped(line=bp) + + # : :type step_in_targets: List[StepInTarget] + step_in_targets = json_facade.get_step_in_targets(hit.frame_id) + label_to_id = dict((target['label'], target['id']) for target in step_in_targets) + json_facade.write_step_in(hit.thread_id, target_id=label_to_id['foo']) + + on_foo_mark_line = writer.get_line_index_with_content('on foo mark') + hit = json_facade.wait_for_thread_stopped(reason='step', line=on_foo_mark_line) + json_facade.write_continue() + + writer.finished_ok = True + + +def test_function_breakpoints_basic(case_setup, pyfile): + + @pyfile + def module(): + + def do_something(): # break here + print('TEST SUCEEDED') + + if __name__ == '__main__': + do_something() + + with case_setup.test_file(module) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + bp = writer.get_line_index_with_content('break here') + json_facade.write_set_function_breakpoints(['do_something']) + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped( + 'function breakpoint', line=bp, preserve_focus_hint=False) + json_facade.write_continue() + + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY36_OR_GREATER, reason='Python 3.6 onwards required for test.') +def test_function_breakpoints_async(case_setup): + + with case_setup.test_file('_debugger_case_stop_async_iteration.py') as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + bp = writer.get_line_index_with_content('async def gen():') + json_facade.write_set_function_breakpoints(['gen']) + json_facade.write_make_initial_run() + + json_facade.wait_for_thread_stopped( + 'function breakpoint', line=bp, preserve_focus_hint=False) + json_facade.write_continue() + + writer.finished_ok = True + + +try: + import pandas +except: + pandas = None + + +@pytest.mark.skipif(pandas is None, reason='Pandas not installed.') +def test_pandas(case_setup, pyfile): + + @pyfile + def pandas_mod(): + import pandas as pd + import numpy as np + + rows = 5000 + cols = 50 + + # i.e.: even with these setting our repr will print at most 300 lines/cols by default. + pd.set_option('display.max_columns', None) + pd.set_option('display.max_rows', None) + + items = rows * cols + df = pd.DataFrame(np.arange(items).reshape(rows, cols)).applymap(lambda x: 'Test String') + series = df._series[0] + styler = df.style + + print('TEST SUCEEDED') # Break here + + with case_setup.test_file(pandas_mod) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + + bp = writer.get_line_index_with_content('Break here') + json_facade.write_set_breakpoints([bp]) + + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + # json_hit = json_facade.get_stack_as_json_hit(json_hit.thread_id) + name_to_var = json_facade.get_locals_name_to_var(json_hit.frame_id) + + # Check the custom repr(DataFrame) + assert name_to_var['df'].value.count('\n') <= 63 + assert '...' in name_to_var['df'].value + + # Check the custom repr(Series) + assert name_to_var['series'].value.count('\n') <= 60 + assert '...' in name_to_var['series'].value + + # Check custom listing (DataFrame) + df_variables_response = json_facade.get_variables_response(name_to_var['df'].variablesReference) + for v in df_variables_response.body.variables: + if v['name'] == 'T': + assert v['value'] == "''" + break + else: + raise AssertionError('Did not find variable "T".') + + # Check custom listing (Series) + df_variables_response = json_facade.get_variables_response(name_to_var['series'].variablesReference) + for v in df_variables_response.body.variables: + if v['name'] == 'T': + assert v['value'] == "''" + break + else: + raise AssertionError('Did not find variable "T".') + + # Check custom listing (Styler) + df_variables_response = json_facade.get_variables_response(name_to_var['styler'].variablesReference) + for v in df_variables_response.body.variables: + if v['name'] == 'data': + assert v['value'] == "''" + break + else: + raise AssertionError('Did not find variable "data".') + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not IS_PY38_OR_GREATER, reason='Python 3.8 onwards required for test.') +def test_same_lineno_and_filename(case_setup, pyfile): + + @pyfile + def target(): + + def some_code(): + print('1') # Break here + + code_obj = compile(''' + func() + ''', __file__, 'exec') + + code_obj = code_obj.replace(co_name=some_code.__code__.co_name, co_firstlineno=some_code.__code__.co_firstlineno) + exec(code_obj, {'func': some_code}) + + print('TEST SUCEEDED') + + with case_setup.test_file(target) as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here')) + json_facade.write_launch(justMyCode=False) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + json_facade.write_continue() + + if sys.version_info[:2] >= (3, 10): + # On Python 3.10 we'll stop twice in this specific case + # because the line actually matches in the caller (so + # this is correct based on what the debugger is seeing...) + json_hit = json_facade.wait_for_thread_stopped() + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(sys.platform == 'win32', reason='Windows does not have execvp.') +def test_replace_process(case_setup_multiprocessing): + import threading + from tests_python.debugger_unittest import AbstractWriterThread + from _pydevd_bundle._debug_adapter.pydevd_schema import ExitedEvent + + with case_setup_multiprocessing.test_file( + '_debugger_case_replace_process.py', + ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + + break1_line = writer.get_line_index_with_content("print('In sub')") + json_facade.write_set_breakpoints([break1_line]) + + server_socket = writer.server_socket + secondary_finished_ok = [False] + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + server_socket.listen(1) + self.server_socket = server_socket + new_sock, addr = server_socket.accept() + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + + writer2 = SecondaryProcessWriterThread() + writer2.reader_thread = reader_thread + writer2.sock = new_sock + json_facade2 = JsonFacade(writer2) + + json_facade2.write_set_breakpoints([break1_line, ]) + json_facade2.write_make_initial_run() + + json_facade2.wait_for_thread_stopped() + json_facade2.write_continue() + secondary_finished_ok[0] = True + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + time.sleep(.1) + + json_facade.write_make_initial_run() + exited_event = json_facade.wait_for_json_message(ExitedEvent) + assert exited_event.body.kwargs['pydevdReason'] == "processReplaced" + + secondary_process_thread_communication.join(10) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + + assert secondary_finished_ok[0] + writer.finished_ok = True + + +@pytest.mark.parametrize('resolve_symlinks', [True, False]) +def test_use_real_path_and_not_links(case_setup, tmpdir, resolve_symlinks): + dira = tmpdir.join('dira') + dira.mkdir() + + dirb = tmpdir.join('dirb') + dirb.mkdir() + + original_file = dira.join('test.py') + original_file.write(''' +print('p1') # Break here +print('p2') +print('TEST SUCEEDED') +''') + + symlinked_file = dirb.join('testit.py') + os.symlink(str(original_file), str(symlinked_file)) + + # I.e.: we're launching the symlinked file but we're actually + # working with the original file afterwards. + with case_setup.test_file(str(symlinked_file)) as writer: + json_facade = JsonFacade(writer) + + writer.write_add_breakpoint(writer.get_line_index_with_content('Break here'), filename=str(original_file)) + json_facade.write_launch(justMyCode=False, resolveSymlinks=resolve_symlinks) + json_facade.write_make_initial_run() + + json_hit = json_facade.wait_for_thread_stopped() + filename = json_hit.stack_trace_response.body.stackFrames[0]['source']['path'] + if resolve_symlinks: + assert filename == str(original_file) + else: + assert filename == str(symlinked_file) + json_facade.write_continue() + writer.finished_ok = True + + +_TOP_LEVEL_AWAIT_AVAILABLE = False +try: + from ast import PyCF_ONLY_AST, PyCF_ALLOW_TOP_LEVEL_AWAIT + _TOP_LEVEL_AWAIT_AVAILABLE = True +except ImportError: + pass + + +@pytest.mark.skipif(not _TOP_LEVEL_AWAIT_AVAILABLE, reason="Top-level await required.") +def test_ipython_stepping_basic(case_setup): + + def get_environ(self): + env = os.environ.copy() + + # Test setup + env["SCOPED_STEPPING_TARGET"] = '_debugger_case_scoped_stepping_target.py' + + # Actually setup the debugging + env["PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING"] = "1" + env["PYDEVD_IPYTHON_CONTEXT"] = '_debugger_case_scoped_stepping.py, run_code, run_ast_nodes' + return env + + with case_setup.test_file('_debugger_case_scoped_stepping.py', get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + + target_file = debugger_unittest._get_debugger_test_file('_debugger_case_scoped_stepping_target.py') + break_line = writer.get_line_index_with_content('a = 1', filename=target_file) + assert break_line == 1 + json_facade.write_set_breakpoints(break_line, filename=target_file) + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped(line=break_line, file='_debugger_case_scoped_stepping_target.py') + + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', line=break_line + 1, file='_debugger_case_scoped_stepping_target.py') + + json_facade.write_step_next(json_hit.thread_id) + json_hit = json_facade.wait_for_thread_stopped('step', line=break_line + 2, file='_debugger_case_scoped_stepping_target.py') + + json_facade.write_continue() + writer.finished_ok = True + + +@pytest.mark.skipif(not _TOP_LEVEL_AWAIT_AVAILABLE, reason="Top-level await required.") +def test_ipython_stepping_step_in(case_setup): + + def get_environ(self): + env = os.environ.copy() + + # Test setup + env["SCOPED_STEPPING_TARGET"] = '_debugger_case_scoped_stepping_target2.py' + + # Actually setup the debugging + env["PYDEVD_IPYTHON_COMPATIBLE_DEBUGGING"] = "1" + env["PYDEVD_IPYTHON_CONTEXT"] = '_debugger_case_scoped_stepping.py, run_code, run_ast_nodes' + return env + + with case_setup.test_file('_debugger_case_scoped_stepping.py', get_environ=get_environ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch(justMyCode=False) + + target_file = debugger_unittest._get_debugger_test_file('_debugger_case_scoped_stepping_target2.py') + break_line = writer.get_line_index_with_content('break here', filename=target_file) + json_facade.write_set_breakpoints(break_line, filename=target_file) + json_facade.write_make_initial_run() + json_hit = json_facade.wait_for_thread_stopped(line=break_line, file='_debugger_case_scoped_stepping_target2.py') + + json_facade.write_step_in(json_hit.thread_id) + stop_at = writer.get_line_index_with_content('b = 2', filename=target_file) + json_hit = json_facade.wait_for_thread_stopped('step', line=stop_at, file='_debugger_case_scoped_stepping_target2.py') + + json_facade.write_step_in(json_hit.thread_id) + stop_at = writer.get_line_index_with_content('method() # break here', filename=target_file) + json_hit = json_facade.wait_for_thread_stopped('step', line=stop_at, file='_debugger_case_scoped_stepping_target2.py') + + json_facade.write_step_in(json_hit.thread_id) + stop_at = writer.get_line_index_with_content('c = 3', filename=target_file) + json_hit = json_facade.wait_for_thread_stopped('step', line=stop_at, file='_debugger_case_scoped_stepping_target2.py') + + json_facade.write_continue() + writer.finished_ok = True + + +def test_logging_api(case_setup_multiprocessing, tmpdir): + import threading + from tests_python.debugger_unittest import AbstractWriterThread + + log_file = str(tmpdir.join('pydevd_in_test_logging.log')) + + def get_environ(self): + env = os.environ.copy() + env["TARGET_LOG_FILE"] = log_file + return env + + with case_setup_multiprocessing.test_file( + '_debugger_case_logging.py', + get_environ=get_environ + ) as writer: + json_facade = JsonFacade(writer) + json_facade.write_launch() + + break1_line = writer.get_line_index_with_content("break on 2nd process") + json_facade.write_set_breakpoints([break1_line]) + + server_socket = writer.server_socket + secondary_finished_ok = [False] + + class SecondaryProcessWriterThread(AbstractWriterThread): + + TEST_FILE = writer.get_main_filename() + _sequence = -1 + + class SecondaryProcessThreadCommunication(threading.Thread): + + def run(self): + from tests_python.debugger_unittest import ReaderThread + server_socket.listen(1) + self.server_socket = server_socket + new_sock, addr = server_socket.accept() + + reader_thread = ReaderThread(new_sock) + reader_thread.name = ' *** Multiprocess Reader Thread' + reader_thread.start() + + writer2 = SecondaryProcessWriterThread() + writer2.reader_thread = reader_thread + writer2.sock = new_sock + json_facade2 = JsonFacade(writer2) + + json_facade2.write_set_breakpoints([break1_line, ]) + json_facade2.write_make_initial_run() + + json_facade2.wait_for_thread_stopped() + json_facade2.write_continue() + secondary_finished_ok[0] = True + + secondary_process_thread_communication = SecondaryProcessThreadCommunication() + secondary_process_thread_communication.start() + time.sleep(.1) + + json_facade.write_make_initial_run() + secondary_process_thread_communication.join(10) + if secondary_process_thread_communication.is_alive(): + raise AssertionError('The SecondaryProcessThreadCommunication did not finish') + + assert secondary_finished_ok[0] + writer.finished_ok = True + + +if __name__ == '__main__': + pytest.main(['-k', 'test_replace_process', '-s']) + diff --git a/tests_python/test_dump_threads.py b/tests_python/test_dump_threads.py new file mode 100644 index 0000000..b619f61 --- /dev/null +++ b/tests_python/test_dump_threads.py @@ -0,0 +1,8 @@ +def test_dump_threads(): + import pydevd + from io import StringIO + stream = StringIO() + pydevd.dump_threads(stream=stream) + contents = stream.getvalue() + assert 'Thread MainThread (daemon: False, pydevd thread: False)' in contents + assert 'test_dump_threads' in contents diff --git a/tests_python/test_evaluate_expression.py b/tests_python/test_evaluate_expression.py new file mode 100644 index 0000000..adc4ba2 --- /dev/null +++ b/tests_python/test_evaluate_expression.py @@ -0,0 +1,280 @@ +from _pydevd_bundle.pydevd_constants import IS_PY38_OR_GREATER, NULL +from _pydevd_bundle.pydevd_xml import ExceptionOnEvaluate + +import sys +import pytest + +SOME_LST = ["foo", "bar"] +BAR = "bar" +FOO = "foo" +global_frame = sys._getframe() + + +def obtain_frame(): + A = 1 + B = 2 + yield sys._getframe() + + +@pytest.fixture +def disable_critical_log(): + # We want to hide the logging related to _evaluate_with_timeouts not receiving the py_db. + from _pydev_bundle.pydev_log import log_context + import io + stream = io.StringIO() + with log_context(0, stream): + yield + + +def test_evaluate_expression_basic(disable_critical_log): + from _pydevd_bundle.pydevd_vars import evaluate_expression + + def check(frame): + evaluate_expression(None, frame, 'some_var = 1', is_exec=True) + + assert frame.f_locals['some_var'] == 1 + + check(next(iter(obtain_frame()))) + assert 'some_var' not in sys._getframe().f_globals + + # as locals == globals, this will also change the current globals + check(global_frame) + assert 'some_var' in sys._getframe().f_globals + del sys._getframe().f_globals['some_var'] + assert 'some_var' not in sys._getframe().f_globals + + +def test_evaluate_expression_1(disable_critical_log): + from _pydevd_bundle.pydevd_vars import evaluate_expression + + def check(frame): + eval_txt = ''' +container = ["abc","efg"] +results = [] +for s in container: + result = [s[i] for i in range(3)] + results.append(result) +''' + evaluate_expression(None, frame, eval_txt, is_exec=True) + assert frame.f_locals['results'] == [['a', 'b', 'c'], ['e', 'f', 'g']] + assert frame.f_locals['s'] == "efg" + + check(next(iter(obtain_frame()))) + + for varname in ['container', 'results', 's']: + assert varname not in sys._getframe().f_globals + + check(global_frame) + for varname in ['container', 'results', 's']: + assert varname in sys._getframe().f_globals + + for varname in ['container', 'results', 's']: + del sys._getframe().f_globals[varname] + + +def test_evaluate_expression_2(disable_critical_log): + from _pydevd_bundle.pydevd_vars import evaluate_expression + + def check(frame): + eval_txt = 'all((x in (BAR, FOO) for x in SOME_LST))' + assert evaluate_expression(None, frame, eval_txt, is_exec=False) + + check(next(iter(obtain_frame()))) + check(global_frame) + + +def test_evaluate_expression_3(disable_critical_log): + if not IS_PY38_OR_GREATER: + return + + from _pydevd_bundle.pydevd_vars import evaluate_expression + + def check(frame): + eval_txt = '''11 if (some_var := 22) else 33''' + assert evaluate_expression(None, frame, eval_txt, is_exec=False) == 11 + + check(next(iter(obtain_frame()))) + assert 'some_var' not in sys._getframe().f_globals + + # as locals == globals, this will also change the current globals + check(global_frame) + assert 'some_var' in sys._getframe().f_globals + del sys._getframe().f_globals['some_var'] + assert 'some_var' not in sys._getframe().f_globals + + +def test_evaluate_expression_4(disable_critical_log): + from _pydevd_bundle.pydevd_vars import evaluate_expression + + def check(frame): + eval_txt = '''import email;email.foo_value''' + with pytest.raises(AttributeError): + evaluate_expression(None, frame, eval_txt, is_exec=True) + assert 'email' in frame.f_locals + + check(next(iter(obtain_frame()))) + assert 'email' not in sys._getframe().f_globals + + # as locals == globals, this will also change the current globals + check(global_frame) + assert 'email' in sys._getframe().f_globals + del sys._getframe().f_globals['email'] + assert 'email' not in sys._getframe().f_globals + + +def test_evaluate_expression_5(disable_critical_log): + from _pydevd_bundle.pydevd_vars import evaluate_expression + + def check(frame): + eval_txt = 'A, B = 5, 6' + evaluate_expression(None, frame, eval_txt, is_exec=True) + assert frame.f_locals['A'] == 5 + assert frame.f_locals['B'] == 6 + + check(next(iter(obtain_frame()))) + + +class _DummyPyDB(object): + + def __init__(self): + self.created_pydb_daemon_threads = {} + self.timeout_tracker = NULL + self.multi_threads_single_notification = False + + +try: + from ast import PyCF_ALLOW_TOP_LEVEL_AWAIT # @UnusedImport + CAN_EVALUATE_TOP_LEVEL_ASYNC = True +except: + CAN_EVALUATE_TOP_LEVEL_ASYNC = False + + +@pytest.mark.skipif(not CAN_EVALUATE_TOP_LEVEL_ASYNC, reason='Requires top-level async evaluation.') +def test_evaluate_expression_async_exec(disable_critical_log): + py_db = _DummyPyDB() + + async def async_call(a): + return a + + async def main(): + from _pydevd_bundle.pydevd_vars import evaluate_expression + a = 10 + assert async_call is not None # Make sure it's in the locals. + frame = sys._getframe() + eval_txt = 'y = await async_call(a)' + evaluate_expression(py_db, frame, eval_txt, is_exec=True) + assert frame.f_locals['y'] == a + + import asyncio + asyncio.run(main()) + + +@pytest.mark.skipif(not CAN_EVALUATE_TOP_LEVEL_ASYNC, reason='Requires top-level async evaluation.') +def test_evaluate_expression_async_exec_as_eval(disable_critical_log): + py_db = _DummyPyDB() + + async def async_call(a): + return a + + async def main(): + from _pydevd_bundle.pydevd_vars import evaluate_expression + assert async_call is not None # Make sure it's in the locals. + frame = sys._getframe() + eval_txt = 'await async_call(10)' + from io import StringIO + _original_stdout = sys.stdout + try: + stringio = sys.stdout = StringIO() + evaluate_expression(py_db, frame, eval_txt, is_exec=True) + finally: + sys.stdout = _original_stdout + + # I.e.: Check that we printed the value obtained in the exec. + assert '10\n' in stringio.getvalue() + + import asyncio + asyncio.run(main()) + + +@pytest.mark.skipif(not CAN_EVALUATE_TOP_LEVEL_ASYNC, reason='Requires top-level async evaluation.') +def test_evaluate_expression_async_exec_error(disable_critical_log): + py_db = _DummyPyDB() + + async def async_call(a): + raise RuntimeError('foobar') + + async def main(): + from _pydevd_bundle.pydevd_vars import evaluate_expression + assert async_call is not None # Make sure it's in the locals. + frame = sys._getframe() + eval_txt = 'y = await async_call(10)' + with pytest.raises(RuntimeError) as e: + evaluate_expression(py_db, frame, eval_txt, is_exec=True) + assert 'foobar' in str(e) + assert 'y' not in frame.f_locals + + import asyncio + asyncio.run(main()) + + +@pytest.mark.skipif(not CAN_EVALUATE_TOP_LEVEL_ASYNC, reason='Requires top-level async evaluation.') +def test_evaluate_expression_async_eval(disable_critical_log): + py_db = _DummyPyDB() + + async def async_call(a): + return a + + async def main(): + from _pydevd_bundle.pydevd_vars import evaluate_expression + a = 10 + assert async_call is not None # Make sure it's in the locals. + frame = sys._getframe() + eval_txt = 'await async_call(a)' + v = evaluate_expression(py_db, frame, eval_txt, is_exec=False) + if isinstance(v, ExceptionOnEvaluate): + raise v.result.with_traceback(v.tb) + assert v == a + + import asyncio + asyncio.run(main()) + + +@pytest.mark.skipif(not CAN_EVALUATE_TOP_LEVEL_ASYNC, reason='Requires top-level async evaluation.') +def test_evaluate_expression_async_eval_error(disable_critical_log): + py_db = _DummyPyDB() + + async def async_call(a): + raise RuntimeError('foobar') + + async def main(): + from _pydevd_bundle.pydevd_vars import evaluate_expression + a = 10 + assert async_call is not None # Make sure it's in the locals. + frame = sys._getframe() + eval_txt = 'await async_call(a)' + v = evaluate_expression(py_db, frame, eval_txt, is_exec=False) + assert isinstance(v, ExceptionOnEvaluate) + assert 'foobar' in str(v.result) + + import asyncio + asyncio.run(main()) + + +def test_evaluate_expression_name_mangling(disable_critical_log): + from _pydevd_bundle.pydevd_vars import evaluate_expression + + class SomeObj(object): + + def __init__(self): + self.__value = 10 + self.frame = sys._getframe() + + obj = SomeObj() + frame = obj.frame + + eval_txt = '''self.__value''' + v = evaluate_expression(None, frame, eval_txt, is_exec=False) + if isinstance(v, ExceptionOnEvaluate): + raise v.result.with_traceback(v.tb) + + assert v == 10 diff --git a/tests_python/test_extract_token.py b/tests_python/test_extract_token.py new file mode 100644 index 0000000..94ca727 --- /dev/null +++ b/tests_python/test_extract_token.py @@ -0,0 +1,49 @@ +# coding: utf-8 +from __future__ import unicode_literals +from _pydev_bundle._pydev_completer import (isidentifier, extract_token_and_qualifier, + TokenAndQualifier) + + +def test_isidentifier(): + assert isidentifier('abc') + assert not isidentifier('<') + assert not isidentifier('') + assert isidentifier('áéíóú') + + +def test_extract_token_and_qualifier(): + + assert extract_token_and_qualifier('tok', 0, 0) == TokenAndQualifier('', '') + assert extract_token_and_qualifier('tok', 0, 1) == TokenAndQualifier('', 't') + assert extract_token_and_qualifier('tok', 0, 2) == TokenAndQualifier('', 'to') + assert extract_token_and_qualifier('tok', 0, 3) == TokenAndQualifier('', 'tok') + assert extract_token_and_qualifier('tok', 0, 4) == TokenAndQualifier('', 'tok') + + assert extract_token_and_qualifier('tok.qual', 0, 0) == TokenAndQualifier('', '') + assert extract_token_and_qualifier('tok.qual', 0, 1) == TokenAndQualifier('', 't') + assert extract_token_and_qualifier('tok.qual', 0, 2) == TokenAndQualifier('', 'to') + assert extract_token_and_qualifier('tok.qual', 0, 3) == TokenAndQualifier('', 'tok') + + assert extract_token_and_qualifier('tok.qual', 0, 4) == TokenAndQualifier('tok', '') + assert extract_token_and_qualifier('tok.qual', 0, 5) == TokenAndQualifier('tok', 'q') + assert extract_token_and_qualifier('tok.qual', 0, 6) == TokenAndQualifier('tok', 'qu') + assert extract_token_and_qualifier('tok.qual', 0, 7) == TokenAndQualifier('tok', 'qua') + assert extract_token_and_qualifier('tok.qual', 0, 8) == TokenAndQualifier('tok', 'qual') + + # out of range (column) + assert extract_token_and_qualifier('tok.qual.qual2', 0, 100) == TokenAndQualifier('tok.qual', 'qual2') + + assert extract_token_and_qualifier('t' + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_frame_eval_change_breakpoints(case_setup_force_frame_eval): + with case_setup_force_frame_eval.test_file('_debugger_case_change_breaks.py') as writer: + break1_line = writer.get_line_index_with_content('break 1') + break2_line = writer.get_line_index_with_content('break 2') + + break2_id = writer.write_add_breakpoint(break2_line, 'None') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=break2_line) + assert hit.suspend_type == "frame_eval" + + writer.write_remove_breakpoint(break2_id) + writer.write_add_breakpoint(break1_line, 'None') + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=break1_line) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_generator_code_cache(case_setup_force_frame_eval): + + with case_setup_force_frame_eval.test_file('_debugger_case_yield_from.py') as writer: + break1_line = writer.get_line_index_with_content('break1') + writer.write_add_breakpoint(break1_line) + break2_line = writer.get_line_index_with_content('break2') + writer.write_add_breakpoint(break2_line) + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=break1_line) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=break2_line) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=break2_line) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=break2_line) + writer.write_run_thread(hit.thread_id) + + hit = writer.wait_for_breakpoint_hit(line=break2_line) + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True + + +def test_break_line_1(case_setup_force_frame_eval): + with case_setup_force_frame_eval.test_file('_debugger_case_yield_from.py') as writer: + break1_line = 1 + break1_id = writer.write_add_breakpoint(break1_line, 'None') + writer.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit(line=break1_line) + assert hit.suspend_type == "frame_eval" + + writer.write_run_thread(hit.thread_id) + + writer.finished_ok = True diff --git a/tests_python/test_frame_evaluator.py b/tests_python/test_frame_evaluator.py new file mode 100644 index 0000000..ca0b809 --- /dev/null +++ b/tests_python/test_frame_evaluator.py @@ -0,0 +1,131 @@ +import sys +import threading +import pytest +from tests_python.debugger_unittest import IS_PY36_OR_GREATER, IS_CPYTHON +from tests_python.debug_constants import TEST_CYTHON, TODO_PY311 + +pytestmark = pytest.mark.skipif(not IS_PY36_OR_GREATER or not IS_CPYTHON or not TEST_CYTHON or TODO_PY311, reason='Requires CPython >= 3.6') + + +def get_foo_frame(): + frame = sys._getframe() + return frame + + +class CheckClass(object): + + def collect_info(self): + from _pydevd_frame_eval import pydevd_frame_evaluator + thread_info = pydevd_frame_evaluator.get_thread_info_py() + self.thread_info = thread_info + + +@pytest.mark.parametrize('_times', range(2)) +def test_thread_info(_times): + obj = CheckClass() + obj.collect_info() + assert obj.thread_info.additional_info is not None + assert not obj.thread_info.is_pydevd_thread + thread_info = obj.thread_info + obj.collect_info() + assert obj.thread_info is thread_info + + obj = CheckClass() + t = threading.Thread(target=obj.collect_info) + t.is_pydev_daemon_thread = True + t.start() + t.join() + + assert obj.thread_info.additional_info is None + assert obj.thread_info.is_pydevd_thread + + +def method(): + return sys._getframe() + + +@pytest.fixture +def _custom_global_dbg(): + from _pydevd_bundle.pydevd_constants import GlobalDebuggerHolder + from pydevd import PyDB + curr = GlobalDebuggerHolder.global_dbg + PyDB() # Will make itself current + yield + GlobalDebuggerHolder.global_dbg = curr + + +@pytest.mark.parametrize('_times', range(2)) +def test_func_code_info(_times, _custom_global_dbg): + from _pydevd_frame_eval import pydevd_frame_evaluator + # Must be called before get_func_code_info_py to initialize the _code_extra_index. + thread_info = pydevd_frame_evaluator.get_thread_info_py() + + func_info = pydevd_frame_evaluator.get_func_code_info_py(thread_info, method(), method.__code__) + assert func_info.co_filename is method.__code__.co_filename + func_info2 = pydevd_frame_evaluator.get_func_code_info_py(thread_info, method(), method.__code__) + assert func_info is func_info2 + + some_func = eval('lambda:sys._getframe()') + func_info3 = pydevd_frame_evaluator.get_func_code_info_py(thread_info, some_func(), some_func.__code__) + del some_func + del func_info3 + + some_func = eval('lambda:sys._getframe()') + pydevd_frame_evaluator.get_func_code_info_py(thread_info, some_func(), some_func.__code__) + func_info = pydevd_frame_evaluator.get_func_code_info_py(thread_info, some_func(), some_func.__code__) + assert pydevd_frame_evaluator.get_func_code_info_py(thread_info, some_func(), some_func.__code__) is func_info + + +def test_generate_code_with_breakpoints(): + from _pydevd_frame_eval.pydevd_frame_evaluator import generate_code_with_breakpoints_py + from _pydevd_frame_eval.pydevd_frame_evaluator import get_cached_code_obj_info_py + + def create_breakpoints_dict(lines): + return dict((line, None) for line in lines) + + def method(): + a = 1 + a = 2 + a = 3 + + breakpoint_found, new_code = generate_code_with_breakpoints_py( + method.__code__, + create_breakpoints_dict([method.__code__.co_firstlineno + 1, method.__code__.co_firstlineno + 2]) + ) + + assert breakpoint_found + with pytest.raises(AssertionError): + # We must use the cached one directly (in the real-world, this would indicate a reuse + # of the code object -- which is related to generator handling). + generate_code_with_breakpoints_py( + new_code, + create_breakpoints_dict([method.__code__.co_firstlineno + 1]) + ) + + cached_value = get_cached_code_obj_info_py(new_code) + breakpoint_found, force_stay_in_untraced_mode = cached_value.compute_force_stay_in_untraced_mode( + create_breakpoints_dict([method.__code__.co_firstlineno + 1])) + + assert breakpoint_found + assert force_stay_in_untraced_mode + + # i.e.: no breakpoints match (stay in untraced mode) + breakpoint_found, force_stay_in_untraced_mode = cached_value.compute_force_stay_in_untraced_mode( + create_breakpoints_dict([method.__code__.co_firstlineno + 10])) + + assert not breakpoint_found + assert force_stay_in_untraced_mode + + # i.e.: one of the breakpoints match (stay in untraced mode) + breakpoint_found, force_stay_in_untraced_mode = cached_value.compute_force_stay_in_untraced_mode( + create_breakpoints_dict([method.__code__.co_firstlineno + 2])) + + assert breakpoint_found + assert force_stay_in_untraced_mode + + # i.e.: one of the breakpoints doesn't match (leave untraced mode) + breakpoint_found, force_stay_in_untraced_mode = cached_value.compute_force_stay_in_untraced_mode( + create_breakpoints_dict([method.__code__.co_firstlineno + 3])) + + assert breakpoint_found + assert not force_stay_in_untraced_mode diff --git a/tests_python/test_null.py b/tests_python/test_null.py new file mode 100644 index 0000000..f09da7b --- /dev/null +++ b/tests_python/test_null.py @@ -0,0 +1,8 @@ +def test_null(): + from _pydevd_bundle.pydevd_constants import Null + null = Null() + assert not null + assert len(null) == 0 + + with null as n: + n.write('foo') \ No newline at end of file diff --git a/tests_python/test_process_command_line.py b/tests_python/test_process_command_line.py new file mode 100644 index 0000000..8932630 --- /dev/null +++ b/tests_python/test_process_command_line.py @@ -0,0 +1,28 @@ +import unittest + +class Test(unittest.TestCase): + + def testProcessCommandLine(self): + from _pydevd_bundle.pydevd_command_line_handling import process_command_line, setup_to_argv + setup = process_command_line(['pydevd.py', '--port', '1', '--save-threading']) + assert setup['save-threading'] + assert setup['port'] == 1 + assert not setup['qt-support'] + + argv = setup_to_argv(setup) + assert argv[0].endswith('pydevd.py') or argv[0].endswith('pydevd$py.class'), 'Expected: %s to end with pydevd.py' % (argv[0],) + argv = argv[1:] + assert argv == ['--port', '1', '--save-threading'] + + def testProcessCommandLine2(self): + from _pydevd_bundle.pydevd_command_line_handling import process_command_line, setup_to_argv + setup = process_command_line(['pydevd.py', '--port', '1', '--qt-support=auto']) + assert setup['qt-support'] == 'auto' + + setup = process_command_line(['pydevd.py', '--port', '1', '--qt-support']) + assert setup['qt-support'] == 'auto' + + setup = process_command_line(['pydevd.py', '--port', '1', '--qt-support=pyqt4']) + assert setup['qt-support'] == 'pyqt4' + + self.assertRaises(ValueError, process_command_line, ['pydevd.py', '--port', '1', '--qt-support=wrong']) diff --git a/tests_python/test_pydev_monkey.py b/tests_python/test_pydev_monkey.py new file mode 100644 index 0000000..2681fe2 --- /dev/null +++ b/tests_python/test_pydev_monkey.py @@ -0,0 +1,526 @@ +# coding: utf-8 +import os +import sys + +import pytest + +from _pydev_bundle.pydev_monkey import pydev_src_dir +from _pydevd_bundle.pydevd_constants import sorted_dict_repr +from pydevd import SetupHolder + +try: + from _pydev_bundle import pydev_monkey +except: + sys.path.append(os.path.dirname(os.path.dirname(__file__))) + from _pydev_bundle import pydev_monkey + + +@pytest.fixture(autouse=True) +def save_setup_holder(): + original = SetupHolder.setup + yield + SetupHolder.setup = original + + +def test_monkey(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True} + check = '''C:\\bin\\python.exe -u -c connect(\\"127.0.0.1\\")''' + debug_command = ( + 'import sys; ' + 'sys.path.insert(0, r\'%s\'); ' + "import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + "pydevd.settrace(host='127.0.0.1', port=0, suspend=False, " + 'trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + + assert 'C:\\bin\\python.exe -u -c %s' % debug_command == pydev_monkey.patch_arg_str_win(check) + + +def test_str_to_args_windows(): + assert ['a', 'b'] == pydev_monkey.str_to_args_windows('a "b"') + + +def test_monkey_patch_return_original_args(): + check = ['echo', '"my"', '"args"'] + res = pydev_monkey.patch_args(check[:]) + assert res == check + + +def test_monkey_patch_pathlib_args(): + try: + import pathlib + except ImportError: + pytest.skip('pathlib not available.') + + check = [pathlib.Path('echo'), '"my"', '"args"'] + res = pydev_monkey.patch_args(check[:]) + assert res == check + + +def test_monkey_patch_wrong_object_type(): + check = [1, 22, '"my"', '"args"'] + res = pydev_monkey.patch_args(check[:]) + assert res == check + + +def test_monkey_patch_wrong_object_type_2(): + check = ['C:\\bin\\python.exe', '-u', 1, '-qcconnect("127.0.0.1")'] + res = pydev_monkey.patch_args(check[:]) + assert res == check + + +def test_monkey_patch_args_module_subprocess_pathlib(): + try: + import pathlib + except ImportError: + pytest.skip('pathlib not available.') + + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'multiprocess': True} + if sys.platform == 'win32': + python_path = 'C:\\bin\\python.exe' + else: + python_path = '/bin/python' + check = [pathlib.Path(python_path), '-mtest', pathlib.Path('bar')] + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + assert pydev_monkey.patch_args(check) == [ + python_path, + get_pydevd_file(), + '--module', + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--multiprocess', + '--protocol-quoted-line', + '--file', + 'test', + 'bar', + ] + + +def test_monkey_patch_args_indc(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-u', '-c', 'connect("127.0.0.1")'] + debug_command = ( + "import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-u', + '-c', + debug_command + ] + + +def test_separate_future_imports(): + found = pydev_monkey._separate_future_imports('''from __future__ import print_function\nprint(1)''') + assert found == ('from __future__ import print_function;', '\nprint(1)') + + found = pydev_monkey._separate_future_imports('''from __future__ import print_function;print(1)''') + assert found == ('from __future__ import print_function;', 'print(1)') + + found = pydev_monkey._separate_future_imports('''from __future__ import (\nprint_function);print(1)''') + assert found == ('from __future__ import (\nprint_function);', 'print(1)') + + found = pydev_monkey._separate_future_imports('''"line";from __future__ import (\n\nprint_function, absolute_imports\n);print(1)''') + assert found == ('"line";from __future__ import (\n\nprint_function, absolute_imports\n);', 'print(1)') + + found = pydev_monkey._separate_future_imports('''from __future__ import bar\nfrom __future__ import (\n\nprint_function, absolute_imports\n);print(1)''') + assert found == ('from __future__ import bar\nfrom __future__ import (\n\nprint_function, absolute_imports\n);', 'print(1)') + + +def test_monkey_patch_args_indc_future_import(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-u', '-c', 'from __future__ import print_function;connect("127.0.0.1")'] + debug_command = ( + "from __future__ import print_function;import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-u', + '-c', + debug_command + ] + + +def test_monkey_patch_args_indc_future_import2(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-u', '-c', 'from __future__ import print_function\nconnect("127.0.0.1")'] + debug_command = ( + "from __future__ import print_function;import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + '\nconnect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-u', + '-c', + debug_command + ] + + +def test_monkey_patch_args_indc2(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-u', '-qcconnect("127.0.0.1")'] + debug_command = ( + "import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-u', + '-qc', + debug_command + ] + + +def test_monkey_patch_args_x_flag(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-X', 'faulthandler', '-c', 'connect("127.0.0.1")'] + debug_command = ( + "import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-X', + 'faulthandler', + '-c', + debug_command + ] + + +def test_monkey_patch_args_flag_in_single_arg_1(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-qX', 'faulthandler', '-c', 'connect("127.0.0.1")'] + debug_command = ( + "import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-qX', + 'faulthandler', + '-c', + debug_command + ] + + +def test_monkey_patch_args_flag_in_single_arg_2(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-qX', 'faulthandler', '-c', 'connect("127.0.0.1")'] + debug_command = ( + "import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-qX', + 'faulthandler', + '-c', + debug_command + ] + + +def test_monkey_patch_args_flag_in_single_arg_3(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-qc', 'connect("127.0.0.1")'] + debug_command = ( + "import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-qc', + debug_command + ] + + +def test_monkey_patch_args_x_flag_inline(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-Xfaulthandler', '-c', 'connect("127.0.0.1")', 'arg1'] + debug_command = ( + "import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-Xfaulthandler', + '-c', + debug_command, + 'arg1' + ] + + +def test_monkey_patch_args_c_flag_inline(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'ppid': os.getpid(), 'protocol-quoted-line': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-X', 'faulthandler', '-cconnect("127.0.0.1")', 'arg1'] + debug_command = ( + "import sys; sys.path.insert(0, r\'%s\'); import pydevd; pydevd.PydevdCustomization.DEFAULT_PROTOCOL='quoted-line'; " + 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True, access_token=None, client_access_token=None, __setup_holder__=%s); ' + '' + 'connect("127.0.0.1")') % (pydev_src_dir, sorted_dict_repr(SetupHolder.setup)) + if sys.platform == "win32": + debug_command = debug_command.replace('"', '\\"') + debug_command = '"%s"' % debug_command + res = pydev_monkey.patch_args(check) + assert res == [ + 'C:\\bin\\python.exe', + '-X', + 'faulthandler', + '-c', + debug_command, + 'arg1' + ] + + +def test_monkey_patch_args_module(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'multiprocess': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-m', 'test'] + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + assert pydev_monkey.patch_args(check) == [ + 'C:\\bin\\python.exe', + get_pydevd_file(), + '--module', + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--multiprocess', + '--skip-notify-stdin', + '--protocol-quoted-line', + '--file', + 'test', + ] + + +def test_monkey_patch_args_unbuffered_module(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'multiprocess': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-u', '-m', 'test'] + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + assert pydev_monkey.patch_args(check) == [ + 'C:\\bin\\python.exe', + '-u', + get_pydevd_file(), + '--module', + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--multiprocess', + '--skip-notify-stdin', + '--protocol-quoted-line', + '--file', + 'test', + ] + + +def test_monkey_patch_args_module_inline(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'multiprocess': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-qOmtest'] + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + assert pydev_monkey.patch_args(check) == [ + 'C:\\bin\\python.exe', + '-qO', + get_pydevd_file(), + '--module', + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--multiprocess', + '--skip-notify-stdin', + '--protocol-quoted-line', + '--file', + 'test', + ] + + +def test_monkey_patch_args_module_inline2(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'multiprocess': True, 'skip-notify-stdin': True} + check = ['C:\\bin\\python.exe', '-qOm', 'test'] + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + assert pydev_monkey.patch_args(check) == [ + 'C:\\bin\\python.exe', + '-qO', + get_pydevd_file(), + '--module', + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--multiprocess', + '--skip-notify-stdin', + '--protocol-quoted-line', + '--file', + 'test', + ] + + +def test_monkey_patch_args_no_indc(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0'} + check = ['C:\\bin\\python.exe', 'connect(\\"127.0.0.1\\")', 'with spaces'] + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + assert pydev_monkey.patch_args(check) == [ + 'C:\\bin\\python.exe', + get_pydevd_file(), + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--protocol-quoted-line', + '--file', + '"connect(\\\\\\"127.0.0.1\\\\\\")"' if sys.platform == 'win32' else 'connect(\\"127.0.0.1\\")', + '"with spaces"' if sys.platform == 'win32' else 'with spaces', + ] + + +def test_monkey_patch_args_no_indc_with_pydevd(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0'} + check = ['C:\\bin\\python.exe', 'pydevd.py', 'connect(\\"127.0.0.1\\")', 'bar'] + + assert pydev_monkey.patch_args(check) == [ + 'C:\\bin\\python.exe', 'pydevd.py', 'connect(\\"127.0.0.1\\")', 'bar'] + + +def test_monkey_patch_args_no_indc_without_pydevd(): + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0'} + check = ['C:\\bin\\python.exe', 'target.py', 'connect(\\"127.0.0.1\\")', 'bar'] + assert pydev_monkey.patch_args(check) == [ + 'C:\\bin\\python.exe', + get_pydevd_file(), + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--protocol-quoted-line', + '--file', + 'target.py', + '"connect(\\\\\\"127.0.0.1\\\\\\")"' if sys.platform == 'win32' else 'connect(\\"127.0.0.1\\")', + 'bar', + ] + + +@pytest.mark.parametrize('use_bytes', [True, False]) +def test_monkey_patch_c_program_arg(use_bytes): + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'module': 'ignore.this'} + check = ['C:\\bin\\python.exe', '-u', 'target.py', '-c', '-áéíóú'] + + encode = lambda s:s + if use_bytes: + check = [c.encode('utf-8') for c in check] + encode = lambda s:s.encode('utf-8') + + assert pydev_monkey.patch_args(check) == [ + encode('C:\\bin\\python.exe'), + encode('-u'), + get_pydevd_file(), + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--protocol-quoted-line', + '--file', + encode('target.py'), + encode('-c'), + encode('-áéíóú') + ] + + +def test_monkey_patch_args_module_single_arg(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'multiprocess': True, 'module': 'ignore.this'} + check = ['C:\\bin\\python.exe', '-mtest', 'bar'] + from _pydevd_bundle.pydevd_command_line_handling import get_pydevd_file + assert pydev_monkey.patch_args(check) == [ + 'C:\\bin\\python.exe', + get_pydevd_file(), + '--module', + '--port', + '0', + '--ppid', + str(os.getpid()), + '--client', + '127.0.0.1', + '--multiprocess', + '--protocol-quoted-line', + '--file', + 'test', + 'bar', + ] + + +def test_monkey_patch_args_stdin(): + SetupHolder.setup = {'client': '127.0.0.1', 'port': '0', 'multiprocess': True, 'module': 'ignore.this'} + check = ['C:\\bin\\python.exe', '-Xfaulthandler' , '-'] + # i.e.: we don't deal with the stdin. + assert pydev_monkey.patch_args(check) == check diff --git a/tests_python/test_pydevcoverage.py b/tests_python/test_pydevcoverage.py new file mode 100644 index 0000000..353027d --- /dev/null +++ b/tests_python/test_pydevcoverage.py @@ -0,0 +1,68 @@ +import os +import re +import sys +import subprocess +import tempfile +import unittest + + +#======================================================================================================================= +# Test +#======================================================================================================================= +class Test(unittest.TestCase): + """ + Unittest for pydev_coverage.py. + TODO: + - 'combine' in arguments + - no 'combine' and no 'pydev-analyze' in arguments + """ + + def setUp(self): + unittest.TestCase.setUp(self) + project_path = os.path.dirname(os.path.dirname(__file__)) + self._resources_path = os.path.join(project_path, "tests_python", "resources") + self._coverage_file = os.path.join(project_path, "pydev_coverage.py") + + def _do_analyze(self, files): + invalid_files = [] + + p = subprocess.Popen([sys.executable, self._coverage_file, "--pydev-analyze"], + stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + __, stderrdata = p.communicate("|".join(files).encode()) + + if stderrdata: + match = re.search("Invalid files not passed to coverage: (.*?)$", + stderrdata.decode(), re.M) # @UndefinedVariable + if match: + invalid_files = [f.strip() for f in match.group(1).split(",")] + return invalid_files + + def test_pydev_analyze_ok(self): + ref_valid_files = [__file__, + os.path.join(self._resources_path, "_debugger_case18.py")] + ref_invalid_files = [] + + invalid_files = self._do_analyze(ref_valid_files) + + self.assertEqual(ref_invalid_files, invalid_files) + + def test_pydev_analyse_non_standard_encoding(self): + ref_valid_files = [os.path.join(self._resources_path, + "_pydev_coverage_cyrillic_encoding_py%i.py" + % sys.version_info[0])] + ref_invalid_files = [] + + invalid_files = self._do_analyze(ref_valid_files + ref_invalid_files) + + self.assertEqual(ref_invalid_files, invalid_files) + + def test_pydev_analyse_invalid_files(self): + with tempfile.NamedTemporaryFile(suffix=".pyx") as pyx_file: + ref_valid_files = [] + ref_invalid_files = [os.path.join(self._resources_path, + "_pydev_coverage_syntax_error.py"), + pyx_file.name] + + invalid_files = self._do_analyze(ref_valid_files + ref_invalid_files) + + self.assertEqual(ref_invalid_files, invalid_files) diff --git a/tests_python/test_pydevd_api.py b/tests_python/test_pydevd_api.py new file mode 100644 index 0000000..2f27530 --- /dev/null +++ b/tests_python/test_pydevd_api.py @@ -0,0 +1,43 @@ +import pytest +import sys + + +@pytest.mark.skipif(sys.platform != 'win32', reason='Windows-only test.') +def test_pydevd_api_breakpoints(tmpdir): + from _pydevd_bundle.pydevd_api import PyDevdAPI + from pydevd import PyDB + import pydevd_file_utils + api = PyDevdAPI() + + py_db = PyDB(set_as_global=False) + + dira = tmpdir.join('DirA') + dira.mkdir() + + f = dira.join('filE.py') + f.write_text(''' +a = 1 +b = 2 +c = 3 +''', 'utf-8') + filename = str(f) + + result = api.add_breakpoint( + py_db, filename, breakpoint_type='python-line', breakpoint_id=0, line=1, condition=None, func_name='None', + expression=None, suspend_policy="NONE", hit_condition='', is_logpoint=False) + assert not result.error_code + + result = api.add_breakpoint( + py_db, filename, breakpoint_type='python-line', breakpoint_id=1, line=2, condition=None, func_name='None', + expression=None, suspend_policy="NONE", hit_condition='', is_logpoint=False) + assert not result.error_code + + canonical_path = pydevd_file_utils.canonical_normalized_path(filename) + + assert len(py_db.breakpoints[canonical_path]) == 2 + assert len(py_db.file_to_id_to_line_breakpoint[canonical_path]) == 2 + + filename_replaced = filename.replace('DirA', 'dira') + api.remove_all_breakpoints(py_db, filename_replaced) + assert not py_db.breakpoints + assert not py_db.file_to_id_to_line_breakpoint diff --git a/tests_python/test_pydevd_filtering.py b/tests_python/test_pydevd_filtering.py new file mode 100644 index 0000000..f1c3d7b --- /dev/null +++ b/tests_python/test_pydevd_filtering.py @@ -0,0 +1,258 @@ +from _pydevd_bundle.pydevd_constants import IS_WINDOWS + + +def test_in_project_roots_prefix_01(tmpdir): + from _pydevd_bundle.pydevd_filtering import FilesFiltering + files_filtering = FilesFiltering() + + another = str(tmpdir.join('another')) + assert not another.endswith('/') and not another.endswith('\\') + + files_filtering.set_library_roots([another]) + files_filtering.set_project_roots([]) + assert not files_filtering.in_project_roots(another + '/f.py') + if IS_WINDOWS: + assert not files_filtering.in_project_roots(another + '\\f.py') + else: + assert files_filtering.in_project_roots(another + '\\f.py') + + assert files_filtering.in_project_roots(another + 'f.py') + + +def test_in_project_roots_prefix_02(tmpdir): + from _pydevd_bundle.pydevd_filtering import FilesFiltering + files_filtering = FilesFiltering() + + another = str(tmpdir.join('another')) + assert not another.endswith('/') and not another.endswith('\\') + + files_filtering.set_library_roots([]) + files_filtering.set_project_roots([another]) + assert files_filtering.in_project_roots(another + '/f.py') + if IS_WINDOWS: + assert files_filtering.in_project_roots(another + '\\f.py') + else: + assert not files_filtering.in_project_roots(another + '\\f.py') + + assert not files_filtering.in_project_roots(another + 'f.py') + + +def test_in_project_roots(tmpdir): + from _pydevd_bundle.pydevd_filtering import FilesFiltering + files_filtering = FilesFiltering() + + import os.path + import sys + assert files_filtering._get_library_roots() == [ + os.path.normcase(x) + ('\\' if IS_WINDOWS else '/') for x in files_filtering._get_default_library_roots()] + + site_packages = tmpdir.mkdir('site-packages') + project_dir = tmpdir.mkdir('project') + + project_dir_inside_site_packages = str(site_packages.mkdir('project')) + site_packages_inside_project_dir = str(project_dir.mkdir('site-packages')) + + # Convert from pytest paths to str. + site_packages = str(site_packages) + project_dir = str(project_dir) + tmpdir = str(tmpdir) + + # Test permutations of project dir inside site packages and vice-versa. + files_filtering.set_project_roots([project_dir, project_dir_inside_site_packages]) + files_filtering.set_library_roots([site_packages, site_packages_inside_project_dir]) + + check = [ + (tmpdir, False), + (site_packages, False), + (site_packages_inside_project_dir, False), + (project_dir, True), + (project_dir_inside_site_packages, True), + ] + for (check_path, find) in check[:]: + filename_inside = os.path.join(check_path, 'a.py') + with open(filename_inside, 'w') as stream: + # Note: on Github actions, tmpdir may be something as: + # c:\\users\\runner~1\\appdata\\local\\temp\\pytest-of-runneradmin\\pytest-0\\test_in_project_roots0 + # internally this may be set as: + # c:\\users\\runneradmin\\appdata\\local\\temp\\pytest-of-runneradmin\\pytest-0\\test_in_project_roots0 + # So, when getting the absolute path, `runner~1` will be properly expanded to `runneradmin` if the + # file exists, but if it doesn't it's not (which may make the test fail), so, make sure + # that we actually create the file so that things work as expected. + stream.write('...') + check.append((filename_inside, find)) + + for check_path, find in check: + if files_filtering.in_project_roots(check_path) != find: + if find: + msg = 'Expected %s to be in the project roots.\nProject roots: %s\nLibrary roots: %s\n' + else: + msg = 'Expected %s NOT to be in the project roots.\nProject roots: %s\nLibrary roots: %s\n' + + raise AssertionError(msg % ( + check_path, + files_filtering._get_project_roots(), + files_filtering._get_library_roots(), + ) + ) + + files_filtering.set_project_roots([]) + files_filtering.set_library_roots([site_packages, site_packages_inside_project_dir]) + + # If the IDE did not set the project roots, consider anything not in the site + # packages as being in a project root (i.e.: we can calculate default values for + # site-packages but not for project roots). + check = [ + (tmpdir, True), + (site_packages, False), + (site_packages_inside_project_dir, False), + (project_dir, True), + (project_dir_inside_site_packages, False), + ('', False), + ('', True), + ('', False), + ] + + for check_path, find in check: + assert files_filtering.in_project_roots(check_path) == find, \ + 'Expected: %s to be a part of the project: %s' % (check_path, find) + + sys.path.append(str(site_packages)) + try: + default_library_roots = files_filtering._get_default_library_roots() + assert len(set(default_library_roots)) == len(default_library_roots), \ + 'Duplicated library roots found in: %s' % (default_library_roots,) + + assert str(site_packages) in default_library_roots + for path in sys.path: + if os.path.exists(path) and path.endswith('site-packages'): + assert path in default_library_roots + finally: + sys.path.remove(str(site_packages)) + + +def test_filtering(tmpdir): + from _pydevd_bundle.pydevd_filtering import FilesFiltering + from _pydevd_bundle.pydevd_filtering import ExcludeFilter + files_filtering = FilesFiltering() + + site_packages = tmpdir.mkdir('site-packages') + project_dir = tmpdir.mkdir('project') + + project_dir_inside_site_packages = str(site_packages.mkdir('project')) + site_packages_inside_project_dir = str(project_dir.mkdir('site-packages')) + + files_filtering.set_exclude_filters([ + ExcludeFilter('**/project*', True, True), + ExcludeFilter('**/bar*', False, True), + ]) + assert files_filtering.exclude_by_filter('/foo/project', None) is True + assert files_filtering.exclude_by_filter('/foo/unmatched', None) is None + assert files_filtering.exclude_by_filter('/foo/bar', None) is False + + +def test_glob_matching(): + from _pydevd_bundle.pydevd_filtering import glob_matches_path + + # Linux + for sep, altsep in (('\\', '/'), ('/', None)): + + def build(path): + if sep == '/': + return path + else: + return ('c:' + path).replace('/', '\\') + + assert glob_matches_path(build('/a'), r'*', sep, altsep) + + assert not glob_matches_path(build('/a/b/c/some.py'), '/a/**/c/so?.py', sep, altsep) + + assert glob_matches_path('/a/b/c', '/a/b/*') + assert not glob_matches_path('/a/b', '/*') + assert glob_matches_path('/a/b', '/*/b') + assert glob_matches_path('/a/b', '**/*') + assert not glob_matches_path('/a/b', '**/a') + + assert glob_matches_path(build('/a/b/c/d'), '**/d', sep, altsep) + assert not glob_matches_path(build('/a/b/c/d'), '**/c', sep, altsep) + assert glob_matches_path(build('/a/b/c/d'), '**/c/d', sep, altsep) + assert glob_matches_path(build('/a/b/c/d'), '**/b/c/d', sep, altsep) + assert glob_matches_path(build('/a/b/c/d'), '/*/b/*/d', sep, altsep) + assert glob_matches_path(build('/a/b/c/d'), '**/c/*', sep, altsep) + assert glob_matches_path(build('/a/b/c/d'), '/a/**/c/*', sep, altsep) + + # I.e. directories are expected to end with '/', so, it'll match + # something as **/directory/** + assert glob_matches_path(build('/a/b/c/'), '**/c/**', sep, altsep) + assert glob_matches_path(build('/a/b/c/'), '**/c/', sep, altsep) + # But not something as **/directory (that'd be a file match). + assert not glob_matches_path(build('/a/b/c/'), '**/c', sep, altsep) + assert not glob_matches_path(build('/a/b/c'), '**/c/', sep, altsep) + + assert glob_matches_path(build('/a/b/c/d.py'), '/a/**/c/*', sep, altsep) + assert glob_matches_path(build('/a/b/c/d.py'), '/a/**/c/*.py', sep, altsep) + assert glob_matches_path(build('/a/b/c/some.py'), '/a/**/c/so*.py', sep, altsep) + assert glob_matches_path(build('/a/b/c/some.py'), '/a/**/c/som?.py', sep, altsep) + assert glob_matches_path(build('/a/b/c/d'), '/**', sep, altsep) + assert glob_matches_path(build('/a/b/c/d'), '/**/d', sep, altsep) + assert glob_matches_path(build('/a/b/c/d.py'), '/**/*.py', sep, altsep) + assert glob_matches_path(build('/a/b/c/d.py'), '**/c/*.py', sep, altsep) + + if IS_WINDOWS: + assert glob_matches_path(build('/a/b/c/d.py'), '**/C/*.py', sep, altsep) + assert glob_matches_path(build('/a/b/C/d.py'), '**/c/*.py', sep, altsep) + + # Expected not to match. + assert not glob_matches_path(build('/a/b/c/d'), '/**/d.py', sep, altsep) + assert not glob_matches_path(build('/a/b/c/d.pyx'), '/a/**/c/*.py', sep, altsep) + assert not glob_matches_path(build('/a/b/c/d'), '/*/d', sep, altsep) + + if sep == '/': + assert not glob_matches_path(build('/a/b/c/d'), r'**\d', sep, altsep) # Match with \ doesn't work on linux... + assert not glob_matches_path(build('/a/b/c/d'), r'c:\**\d', sep, altsep) # Match with drive doesn't work on linux... + else: + # Works in Windows. + assert glob_matches_path(build('/a/b/c/d'), r'**\d', sep, altsep) + assert glob_matches_path(build('/a/b/c/d'), r'c:\**\d', sep, altsep) + + # Corner cases + assert not glob_matches_path(build('/'), r'', sep, altsep) + assert glob_matches_path(build(''), r'', sep, altsep) + assert not glob_matches_path(build(''), r'**', sep, altsep) + assert glob_matches_path(build('/'), r'**', sep, altsep) + assert glob_matches_path(build('/'), r'*', sep, altsep) + + +def test_rules_to_exclude_filter(tmpdir): + from _pydevd_bundle.pydevd_process_net_command_json import _convert_rules_to_exclude_filters + from _pydevd_bundle.pydevd_filtering import ExcludeFilter + from random import shuffle + dira = tmpdir.mkdir('a') + dirb = dira.mkdir('b') + fileb = dirb.join('fileb.py') + fileb2 = dirb.join('fileb2.py') + with fileb.open('w') as stream: + stream.write('') + + def on_error(msg): + raise AssertionError(msg) + + rules = [ + {'path': str(dira), 'include': False}, + {'path': str(dirb), 'include': True}, + {'path': str(fileb), 'include': True}, + {'path': str(fileb2), 'include': True}, + {'path': '**/foo/*.py', 'include': True}, + {'module': 'bar', 'include': False}, + {'module': 'bar.foo', 'include': True}, + ] + shuffle(rules) + exclude_filters = _convert_rules_to_exclude_filters(rules, on_error) + assert exclude_filters == [ + ExcludeFilter(name=str(fileb2), exclude=False, is_path=True), + ExcludeFilter(name=str(fileb), exclude=False, is_path=True), + ExcludeFilter(name=str(dirb) + '/**', exclude=False, is_path=True), + ExcludeFilter(name=str(dira) + '/**', exclude=True, is_path=True), + ExcludeFilter(name='**/foo/*.py', exclude=False, is_path=True), + ExcludeFilter(name='bar.foo', exclude=False, is_path=False), + ExcludeFilter(name='bar', exclude=True, is_path=False), + ] diff --git a/tests_python/test_pydevd_io.py b/tests_python/test_pydevd_io.py new file mode 100644 index 0000000..b8608ef --- /dev/null +++ b/tests_python/test_pydevd_io.py @@ -0,0 +1,225 @@ +from _pydevd_bundle.pydevd_io import IORedirector +from _pydevd_bundle.pydevd_net_command_factory_xml import NetCommandFactory +import pytest +import sys + + +def test_io_redirector(): + + class MyRedirection1(object): + encoding = 'foo' + + class MyRedirection2(object): + pass + + my_redirector = IORedirector(MyRedirection1(), MyRedirection2(), wrap_buffer=True) + none_redirector = IORedirector(None, None, wrap_buffer=True) + + assert my_redirector.encoding == 'foo' + with pytest.raises(AttributeError): + none_redirector.encoding + + # Check that we don't fail creating the IORedirector if the original + # doesn't have a 'buffer'. + for redirector in ( + my_redirector, + none_redirector, + ): + redirector.write('test') + redirector.flush() + + assert not redirector.isatty() + + +class _DummyWriter(object): + + __slots__ = ['commands', 'command_meanings'] + + def __init__(self): + self.commands = [] + self.command_meanings = [] + + def add_command(self, cmd): + from _pydevd_bundle.pydevd_comm import ID_TO_MEANING + meaning = ID_TO_MEANING[str(cmd.id)] + self.command_meanings.append(meaning) + self.commands.append(cmd) + + +class _DummyPyDb(object): + + def __init__(self): + self.cmd_factory = NetCommandFactory() + self.writer = _DummyWriter() + + +def test_patch_stdin(): + from pydevd import _internal_patch_stdin + + py_db = _DummyPyDb() + + class _Stub(object): + pass + + actions = [] + + class OriginalStdin(object): + + def readline(self): + # On a readline we keep the patched version. + assert sys_mod.stdin is not original_stdin + actions.append('readline') + return 'read' + + def getpass_stub(*args, **kwargs): + # On getpass we need to revert to the original version. + actions.append('getpass') + assert sys_mod.stdin is original_stdin + return 'pass' + + sys_mod = _Stub() + original_stdin = sys_mod.stdin = OriginalStdin() + + getpass_mod = _Stub() + getpass_mod.getpass = getpass_stub + + _internal_patch_stdin(py_db, sys_mod, getpass_mod) + + assert sys_mod.stdin.readline() == 'read' + + assert py_db.writer.command_meanings == ['CMD_INPUT_REQUESTED', 'CMD_INPUT_REQUESTED'] + del py_db.writer.command_meanings[:] + assert actions == ['readline'] + del actions[:] + + assert getpass_mod.getpass() == 'pass' + assert py_db.writer.command_meanings == ['CMD_INPUT_REQUESTED', 'CMD_INPUT_REQUESTED'] + del py_db.writer.command_meanings[:] + + +def test_debug_console(): + from _pydev_bundle.pydev_console_utils import DebugConsoleStdIn + + class OriginalStdin(object): + + def readline(self): + return 'read' + + original_stdin = OriginalStdin() + + py_db = _DummyPyDb() + debug_console_std_in = DebugConsoleStdIn(py_db, original_stdin) + assert debug_console_std_in.readline() == 'read' + + assert py_db.writer.command_meanings == ['CMD_INPUT_REQUESTED', 'CMD_INPUT_REQUESTED'] + del py_db.writer.command_meanings[:] + + with debug_console_std_in.notify_input_requested(): + with debug_console_std_in.notify_input_requested(): + pass + assert py_db.writer.command_meanings == ['CMD_INPUT_REQUESTED', 'CMD_INPUT_REQUESTED'] + + +@pytest.yield_fixture +def _redirect_context(): + from _pydevd_bundle.pydevd_io import RedirectToPyDBIoMessages + from _pydevd_bundle.pydevd_io import _RedirectionsHolder + py_db = _DummyPyDb() + + _original_get_pydb = RedirectToPyDBIoMessages.get_pydb + _original_stack_stdout = _RedirectionsHolder._stack_stdout + _original_stack_stderr = _RedirectionsHolder._stack_stderr + _original_stdout_redirect = _RedirectionsHolder._pydevd_stdout_redirect_ + _original_stderr_redirect = _RedirectionsHolder._pydevd_stderr_redirect_ + + RedirectToPyDBIoMessages.get_pydb = lambda *args, **kwargs: py_db + _RedirectionsHolder._stack_stdout = [] + _RedirectionsHolder._stack_stderr = [] + _RedirectionsHolder._pydevd_stdout_redirect_ = None + _RedirectionsHolder._pydevd_stderr_redirect_ = None + + original_stdout = sys.stdout + original_stderr = sys.stderr + + yield {'py_db': py_db} + + sys.stdout = original_stdout + sys.stderr = original_stderr + + RedirectToPyDBIoMessages.get_pydb = _original_get_pydb + _RedirectionsHolder._stack_stdout = _original_stack_stdout + _RedirectionsHolder._stack_stderr = _original_stack_stderr + _RedirectionsHolder._pydevd_stdout_redirect_ = _original_stdout_redirect + _RedirectionsHolder._pydevd_stderr_redirect_ = _original_stderr_redirect + + +def test_redirect_to_pyd_io_messages_basic(_redirect_context): + from _pydevd_bundle.pydevd_io import redirect_stream_to_pydb_io_messages + from _pydevd_bundle.pydevd_io import redirect_stream_to_pydb_io_messages_context + from _pydevd_bundle.pydevd_io import stop_redirect_stream_to_pydb_io_messages + from _pydevd_bundle.pydevd_io import _RedirectionsHolder + + py_db = _redirect_context['py_db'] + + redirect_stream_to_pydb_io_messages(std='stdout') + assert len(_RedirectionsHolder._stack_stdout) == 1 + assert _RedirectionsHolder._pydevd_stdout_redirect_ is not None + sys.stdout.write('aaa') + assert py_db.writer.command_meanings == ['CMD_WRITE_TO_CONSOLE'] + + with redirect_stream_to_pydb_io_messages_context(): + assert len(_RedirectionsHolder._stack_stdout) == 1 + assert _RedirectionsHolder._pydevd_stdout_redirect_ is not None + sys.stdout.write('bbb') + + assert py_db.writer.command_meanings == ['CMD_WRITE_TO_CONSOLE', 'CMD_WRITE_TO_CONSOLE'] + + assert len(_RedirectionsHolder._stack_stdout) == 1 + assert _RedirectionsHolder._pydevd_stdout_redirect_ is not None + sys.stdout.write('ccc') + assert py_db.writer.command_meanings == ['CMD_WRITE_TO_CONSOLE', 'CMD_WRITE_TO_CONSOLE', 'CMD_WRITE_TO_CONSOLE'] + + stop_redirect_stream_to_pydb_io_messages(std='stdout') + assert len(_RedirectionsHolder._stack_stdout) == 0 + assert _RedirectionsHolder._pydevd_stdout_redirect_ is None + sys.stdout.write('ddd') + assert py_db.writer.command_meanings == ['CMD_WRITE_TO_CONSOLE', 'CMD_WRITE_TO_CONSOLE', 'CMD_WRITE_TO_CONSOLE'] + + +@pytest.mark.parametrize('std', ['stderr', 'stdout']) +def test_redirect_to_pyd_io_messages_user_change_stdout(_redirect_context, std): + from _pydevd_bundle.pydevd_io import redirect_stream_to_pydb_io_messages + from _pydevd_bundle.pydevd_io import stop_redirect_stream_to_pydb_io_messages + from _pydevd_bundle.pydevd_io import _RedirectionsHolder + + py_db = _redirect_context['py_db'] + stack = getattr(_RedirectionsHolder, '_stack_%s' % (std,)) + + def get_redirect(): + return getattr(_RedirectionsHolder, '_pydevd_%s_redirect_' % (std,)) + + def write(s): + getattr(sys, std).write(s) + + redirect_stream_to_pydb_io_messages(std=std) + assert len(stack) == 1 + assert get_redirect() is not None + write('aaa') + assert py_db.writer.command_meanings == ['CMD_WRITE_TO_CONSOLE'] + + from io import StringIO + stream = StringIO() + setattr(sys, std, stream) + + write(u'bbb') + assert py_db.writer.command_meanings == ['CMD_WRITE_TO_CONSOLE'] + assert stream.getvalue() == u'bbb' + + # i.e.: because the user changed the sys.stdout, we cannot change it to our previous version. + stop_redirect_stream_to_pydb_io_messages(std=std) + assert len(stack) == 0 + assert get_redirect() is None + write(u'ccc') + assert py_db.writer.command_meanings == ['CMD_WRITE_TO_CONSOLE'] + assert stream.getvalue() == u'bbbccc' + diff --git a/tests_python/test_resolvers.py b/tests_python/test_resolvers.py new file mode 100644 index 0000000..8e8cc49 --- /dev/null +++ b/tests_python/test_resolvers.py @@ -0,0 +1,323 @@ +from _pydevd_bundle.pydevd_constants import IS_PY36_OR_GREATER, GENERATED_LEN_ATTR_NAME + + +def check_len_entry(len_entry, first_2_params): + assert len_entry[:2] == first_2_params + assert callable(len_entry[2]) + assert len_entry[2]('check') == 'len(check)' + + +def test_dict_resolver(): + from _pydevd_bundle.pydevd_resolver import DictResolver + dict_resolver = DictResolver() + dct = {(1, 2): 2, u'22': 22} + contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(dict_resolver.get_contents_debug_adapter_protocol(dct)) + len_entry = contents_debug_adapter_protocol.pop(-1) + check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 2)) + if IS_PY36_OR_GREATER: + assert contents_debug_adapter_protocol == [ + ('(1, 2)', 2, '[(1, 2)]'), ("'22'", 22, "['22']")] + + else: + assert contents_debug_adapter_protocol == [ + ("'22'", 22, "['22']"), ('(1, 2)', 2, '[(1, 2)]')] + + +def test_dict_resolver_hex(): + from _pydevd_bundle.pydevd_resolver import DictResolver + dict_resolver = DictResolver() + dct = {(1, 10, 100): (10000, 100000, 100000)} + contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol( + dict_resolver.get_contents_debug_adapter_protocol(dct, fmt={'hex': True})) + len_entry = contents_debug_adapter_protocol.pop(-1) + check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 1)) + assert contents_debug_adapter_protocol == [ + ('(0x1, 0xa, 0x64)', (10000, 100000, 100000), '[(1, 10, 100)]'), ] + + +def test_object_resolver_simple(): + from _pydevd_bundle.pydevd_resolver import DefaultResolver + default_resolver = DefaultResolver() + + class MyObject(object): + + def __init__(self): + self.a = 10 + self.b = 20 + + obj = MyObject() + dictionary = clear_contents_dictionary(default_resolver.get_dictionary(obj)) + assert dictionary == {'a': 10, 'b': 20} + + contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(default_resolver.get_contents_debug_adapter_protocol(obj)) + assert contents_debug_adapter_protocol == [('a', 10, '.a'), ('b', 20, '.b')] + + +def test_object_resolver_error(): + from _pydevd_bundle.pydevd_resolver import DefaultResolver + default_resolver = DefaultResolver() + + class MyObject(object): + + def __init__(self): + self.a = 10 + + def __dir__(self): + return ['a', 'b'] + + def __getattribute__(self, attr_name): + if attr_name == 'b': + raise RuntimeError('unavailable') + return object.__getattribute__(self, attr_name) + + obj = MyObject() + dictionary = default_resolver.get_dictionary(obj) + b_value = dictionary.pop('b') + assert dictionary == {'a': 10} + assert "raise RuntimeError('unavailable')" in b_value + + contents_debug_adapter_protocol = default_resolver.get_contents_debug_adapter_protocol(obj) + b_value = contents_debug_adapter_protocol.pop(-1) + assert contents_debug_adapter_protocol == [('a', 10, '.a')] + assert b_value[0] == 'b' + assert "raise RuntimeError('unavailable')" in b_value[1] + assert b_value[2] == '.b' + + +def test_object_resolver_hasattr_error(): + from _pydevd_bundle.pydevd_resolver import DefaultResolver + from _pydevd_bundle.pydevd_xml import get_type + default_resolver = DefaultResolver() + + class MyObject(object): + + def __getattribute__(self, attr_name): + raise RuntimeError() + + obj = MyObject() + dictionary = default_resolver.get_dictionary(obj) + assert dictionary == {} + + _type_object, type_name, _resolver = get_type(obj) + assert type_name == 'MyObject' + + +def test_object_resolver__dict__non_strings(): + from _pydevd_bundle.pydevd_resolver import DefaultResolver + default_resolver = DefaultResolver() + + class MyObject(object): + + def __init__(self): + self.__dict__[(1, 2)] = (3, 4) + + obj = MyObject() + dictionary = clear_contents_dictionary(default_resolver.get_dictionary(obj)) + assert dictionary == {'(1, 2)': (3, 4)} + + contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol( + default_resolver.get_contents_debug_adapter_protocol(obj)) + assert contents_debug_adapter_protocol == [('(1, 2)', (3, 4), '.__dict__[(1, 2)]')] + + +def test_django_forms_resolver(): + from _pydevd_bundle.pydevd_resolver import DjangoFormResolver + django_form_resolver = DjangoFormResolver() + + class MyObject(object): + + def __init__(self): + self.__dict__[(1, 2)] = (3, 4) + self.__dict__['errors'] = 'foo' + + obj = MyObject() + + dictionary = clear_contents_dictionary(django_form_resolver.get_dictionary(obj)) + assert dictionary == {'(1, 2)': (3, 4), 'errors': None} + + obj._errors = 'bar' + dictionary = clear_contents_dictionary(django_form_resolver.get_dictionary(obj)) + assert dictionary == {'(1, 2)': (3, 4), 'errors': 'bar', '_errors': 'bar'} + + +def clear_contents_debug_adapter_protocol(contents_debug_adapter_protocol): + lst = [] + for x in contents_debug_adapter_protocol: + if not x[0].startswith('__'): + + if '= 7: + + @pytest.fixture + def testdir_or_pytester(pytester): + return pytester + +else: + + @pytest.fixture + def testdir_or_pytester(testdir): + return testdir + + +def test_run(testdir_or_pytester): + from tests_python import debugger_unittest + import sys + import os + + foo_dir = debugger_unittest._get_debugger_test_file(os.path.join('resources', 'launch', 'foo')) + foo_module = 'tests_python.resources.launch.foo' + + pydevd_dir = os.path.dirname(os.path.dirname(__file__)) + assert os.path.exists(os.path.join(pydevd_dir, 'pydevd.py')) + + _run_and_check(testdir_or_pytester, testdir_or_pytester.makepyfile(''' +import sys +sys.path.append(%(pydevd_dir)r) +import pydevd +py_db = pydevd.PyDB() +py_db.ready_to_run = True +py_db.run(%(foo_dir)r) +''' % locals())) + + _run_and_check(testdir_or_pytester, testdir_or_pytester.makepyfile(''' +import sys +sys.path.append(%(pydevd_dir)r) +import pydevd +py_db = pydevd.PyDB() +py_db.run(%(foo_dir)r, set_trace=False) +''' % locals())) + + if sys.version_info[0:2] == (2, 6): + # Not valid for Python 2.6 + return + + _run_and_check(testdir_or_pytester, testdir_or_pytester.makepyfile(''' +import sys +sys.path.append(%(pydevd_dir)r) +sys.argv.append('--as-module') +import pydevd +py_db = pydevd.PyDB() +py_db.ready_to_run = True +py_db.run(%(foo_module)r, is_module=True) +''' % locals())) + + _run_and_check(testdir_or_pytester, testdir_or_pytester.makepyfile(''' +import sys +sys.argv.append('--as-module') +sys.path.append(%(pydevd_dir)r) +import pydevd +py_db = pydevd.PyDB() +py_db.run(%(foo_module)r, is_module=True, set_trace=False) +''' % locals())) + + +def test_run_on_local_module_without_adding_to_pythonpath(testdir_or_pytester): + import sys + import os + + pydevd_dir = os.path.dirname(os.path.dirname(__file__)) + assert os.path.exists(os.path.join(pydevd_dir, 'pydevd.py')) + + foo_module = 'local_foo' + with open(os.path.join(os.getcwd(), 'local_foo.py'), 'w') as stream: + stream.write('print("WorkedLocalFoo")') + + _run_and_check(testdir_or_pytester, testdir_or_pytester.makepyfile(''' +import sys +import os +sys.path.append(%(pydevd_dir)r) +sys.argv.append('--as-module') +cwd = os.path.abspath(os.getcwd()) +while cwd in sys.path: + sys.path.remove(cwd) +import pydevd +py_db = pydevd.PyDB() +py_db.ready_to_run = True +py_db.run(%(foo_module)r, is_module=True) +''' % locals()), check_for='WorkedLocalFoo') + + _run_and_check(testdir_or_pytester, testdir_or_pytester.makepyfile(''' +import sys +import os +sys.argv.append('--as-module') +sys.path.append(%(pydevd_dir)r) +cwd = os.path.abspath(os.getcwd()) +while cwd in sys.path: + sys.path.remove(cwd) +import pydevd +py_db = pydevd.PyDB() +py_db.run(%(foo_module)r, is_module=True, set_trace=False) +''' % locals()), check_for='WorkedLocalFoo') diff --git a/tests_python/test_safe_repr.py b/tests_python/test_safe_repr.py new file mode 100644 index 0000000..9356e40 --- /dev/null +++ b/tests_python/test_safe_repr.py @@ -0,0 +1,690 @@ +# coding: utf-8 +import collections +import sys +import re +import pytest +from _pydevd_bundle.pydevd_safe_repr import SafeRepr +import json +from _pydevd_bundle.pydevd_constants import IS_PY36_OR_GREATER + +try: + import numpy as np +except ImportError: + np = None + +PY_VER = sys.version_info[0] +assert PY_VER <= 3 # Fix the code when Python 4 comes around. +PY3K = PY_VER == 3 + + +class SafeReprTestBase(object): + + saferepr = SafeRepr() + + def assert_saferepr(self, value, expected): + safe = self.saferepr(value) + + if len(safe) != len(expected): + raise AssertionError('Expected:\n%s\nFound:\n%s\n Expected len: %s Found len: %s' % ( + expected, safe, len(expected), len(safe),)) + assert safe == expected + return safe + + def assert_unchanged(self, value, expected): + actual = repr(value) + + safe = self.assert_saferepr(value, expected) + assert safe == actual + + def assert_shortened(self, value, expected): + actual = repr(value) + + safe = self.assert_saferepr(value, expected) + assert safe != actual + + def assert_saferepr_regex(self, s, r): + safe = self.saferepr(s) + + assert re.search(r, safe) is not None + return safe + + def assert_unchanged_regex(self, value, expected): + actual = repr(value) + + safe = self.assert_saferepr_regex(value, expected) + assert safe == actual + + def assert_shortened_regex(self, value, expected): + actual = repr(value) + + safe = self.assert_saferepr_regex(value, expected) + assert safe != actual + + +class TestSafeRepr(SafeReprTestBase): + + def test_collection_types(self): + colltypes = [t for t, _, _, _ in SafeRepr.collection_types] + + assert colltypes == [ + tuple, + list, + frozenset, + set, + collections.deque, + ] + + def test_largest_repr(self): + # Find the largest possible repr and ensure it is below our arbitrary + # limit (8KB). + coll = '-' * (SafeRepr.maxstring_outer * 2) + for limit in reversed(SafeRepr.maxcollection[1:]): + coll = [coll] * (limit * 2) + dcoll = {} + for i in range(SafeRepr.maxcollection[0]): + dcoll[str(i) * SafeRepr.maxstring_outer] = coll + text = self.saferepr(dcoll) + # try: + # text_repr = repr(dcoll) + # except MemoryError: + # print('Memory error raised while creating repr of test data') + # text_repr = '' + # print('len(SafeRepr()(dcoll)) = ' + str(len(text)) + + # ', len(repr(coll)) = ' + str(len(text_repr))) + + assert len(text) < 8192 + + +class TestStrings(SafeReprTestBase): + + def test_str_small(self): + value = 'A' * 5 + + self.assert_unchanged(value, "'AAAAA'") + self.assert_unchanged([value], "['AAAAA']") + + def test_str_large(self): + value = 'A' * (SafeRepr.maxstring_outer + 10) + + self.assert_shortened(value, + "'" + 'A' * 43690 + "..." + 'A' * 21845 + "'") + self.assert_shortened([value], "['AAAAAAAAAAAAAAAAAAAA...AAAAAAAAAA']") + + def test_str_largest_unchanged(self): + value = 'A' * (SafeRepr.maxstring_outer) + + self.assert_unchanged(value, "'" + 'A' * 65536 + "'") + + def test_str_smallest_changed(self): + value = 'A' * (SafeRepr.maxstring_outer + 1) + + self.assert_shortened(value, + "'" + 'A' * 43690 + "..." + 'A' * 21845 + "'") + + def test_str_list_largest_unchanged(self): + value = 'A' * (SafeRepr.maxstring_inner) + + self.assert_unchanged([value], "['AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA']") + + def test_str_list_smallest_changed(self): + value = 'A' * (SafeRepr.maxstring_inner + 1) + + self.assert_shortened([value], "['AAAAAAAAAAAAAAAAAAAA...AAAAAAAAAA']") + + @pytest.mark.skipif(sys.version_info > (3, 0), reason='Py2 specific test') + def test_unicode_small(self): + value = u'A' * 5 + + self.assert_unchanged(value, "u'AAAAA'") + self.assert_unchanged([value], "[u'AAAAA']") + + @pytest.mark.skipif(sys.version_info > (3, 0), reason='Py2 specific test') + def test_unicode_large(self): + value = u'A' * (SafeRepr.maxstring_outer + 10) + + self.assert_shortened(value, + "u'" + 'A' * 43690 + "..." + 'A' * 21845 + "'") + self.assert_shortened([value], "[u'AAAAAAAAAAAAAAAAAAAA...AAAAAAAAAA']") + + @pytest.mark.skipif(sys.version_info < (3, 0), reason='Py3 specific test') + def test_bytes_small(self): + value = b'A' * 5 + + self.assert_unchanged(value, "b'AAAAA'") + self.assert_unchanged([value], "[b'AAAAA']") + + @pytest.mark.skipif(sys.version_info < (3, 0), reason='Py3 specific test') + def test_bytes_large(self): + value = b'A' * (SafeRepr.maxstring_outer + 10) + + self.assert_shortened(value, + "b'" + 'A' * 43690 + "..." + 'A' * 21845 + "'") + self.assert_shortened([value], "[b'AAAAAAAAAAAAAAAAAAAA...AAAAAAAAAA']") + + # @pytest.mark.skip(reason='not written') # TODO: finish! + # def test_bytearray_small(self): + # raise NotImplementedError + # + # @pytest.mark.skip(reason='not written') # TODO: finish! + # def test_bytearray_large(self): + # raise NotImplementedError + + +class RawValueTests(SafeReprTestBase): + + def setUp(self): + super(RawValueTests, self).setUp() + self.saferepr.raw_value = True + + def test_unicode_raw(self): + value = u'A\u2000' * 10000 + self.assert_saferepr(value, value) + + def test_bytes_raw(self): + value = b'A' * 10000 + self.assert_saferepr(value, value.decode('ascii')) + + def test_bytearray_raw(self): + value = bytearray(b'A' * 5) + self.assert_saferepr(value, value.decode('ascii')) + +# class TestNumbers(SafeReprTestBase): +# +# @pytest.mark.skip(reason='not written') # TODO: finish! +# def test_int(self): +# raise NotImplementedError +# +# @pytest.mark.skip(reason='not written') # TODO: finish! +# def test_float(self): +# raise NotImplementedError +# +# @pytest.mark.skip(reason='not written') # TODO: finish! +# def test_complex(self): +# raise NotImplementedError + + +class ContainerBase(object): + + CLASS = None + LEFT = None + RIGHT = None + + @property + def info(self): + try: + return self._info + except AttributeError: + for info in SafeRepr.collection_types: + ctype, _, _, _ = info + if self.CLASS is ctype: + type(self)._info = info + return info + else: + raise TypeError('unsupported') + + def _combine(self, items, prefix, suffix, large): + contents = ', '.join(str(item) for item in items) + if large: + contents += ', ...' + return prefix + contents + suffix + + def combine(self, items, large=False): + if self.LEFT is None: + pytest.skip('unsupported') + return self._combine(items, self.LEFT, self.RIGHT, large=large) + + def combine_nested(self, depth, items, large=False): + _, _prefix, _suffix, comma = self.info + prefix = _prefix * (depth + 1) + if comma: + suffix = _suffix + ("," + _suffix) * depth + else: + suffix = _suffix * (depth + 1) + # print("ctype = " + ctype.__name__ + ", maxcollection[" + + # str(i) + "] == " + str(SafeRepr.maxcollection[i])) + return self._combine(items, prefix, suffix, large=large) + + def test_large_flat(self): + c1 = self.CLASS(range(SafeRepr.maxcollection[0] * 2)) + items = range(SafeRepr.maxcollection[0] - 1) + c1_expect = self.combine(items, large=True) + + self.assert_shortened(c1, c1_expect) + + def test_large_nested(self): + c1 = self.CLASS(range(SafeRepr.maxcollection[0] * 2)) + c1_items = range(SafeRepr.maxcollection[1] - 1) + c1_expect = self.combine(c1_items, large=True) + + c2 = self.CLASS(c1 for _ in range(SafeRepr.maxcollection[0] * 2)) + items = (c1_expect for _ in range(SafeRepr.maxcollection[0] - 1)) + c2_expect = self.combine(items, large=True) + + self.assert_shortened(c2, c2_expect) + + # @pytest.mark.skip(reason='not written') # TODO: finish! + # def test_empty(self): + # raise NotImplementedError + # + # @pytest.mark.skip(reason='not written') # TODO: finish! + # def test_subclass(self): + # raise NotImplementedError + + def test_boundary(self): + items1 = range(SafeRepr.maxcollection[0] - 1) + items2 = range(SafeRepr.maxcollection[0]) + items3 = range(SafeRepr.maxcollection[0] + 1) + c1 = self.CLASS(items1) + c2 = self.CLASS(items2) + c3 = self.CLASS(items3) + expected1 = self.combine(items1) + expected2 = self.combine(items2[:-1], large=True) + expected3 = self.combine(items3[:-2], large=True) + + self.assert_unchanged(c1, expected1) + self.assert_shortened(c2, expected2) + self.assert_shortened(c3, expected3) + + def test_nested(self): + ctype = self.CLASS + for i in range(1, len(SafeRepr.maxcollection)): + items1 = range(SafeRepr.maxcollection[i] - 1) + items2 = range(SafeRepr.maxcollection[i]) + items3 = range(SafeRepr.maxcollection[i] + 1) + c1 = self.CLASS(items1) + c2 = self.CLASS(items2) + c3 = self.CLASS(items3) + for _j in range(i): + c1, c2, c3 = ctype((c1,)), ctype((c2,)), ctype((c3,)) + expected1 = self.combine_nested(i, items1) + expected2 = self.combine_nested(i, items2[:-1], large=True) + expected3 = self.combine_nested(i, items3[:-2], large=True) + + self.assert_unchanged(c1, expected1) + self.assert_shortened(c2, expected2) + self.assert_shortened(c3, expected3) + + +class TestTuples(ContainerBase, SafeReprTestBase): + + CLASS = tuple + LEFT = '(' + RIGHT = ')' + + +class TestLists(ContainerBase, SafeReprTestBase): + + CLASS = list + LEFT = '[' + RIGHT = ']' + + def test_directly_recursive(self): + value = [1, 2] + value.append(value) + + self.assert_unchanged(value, '[1, 2, [...]]') + + def test_indirectly_recursive(self): + value = [1, 2] + value.append([value]) + + self.assert_unchanged(value, '[1, 2, [[...]]]') + + +class TestFrozensets(ContainerBase, SafeReprTestBase): + + CLASS = frozenset + + +class TestSets(ContainerBase, SafeReprTestBase): + + CLASS = set + if PY_VER != 2: + LEFT = '{' + RIGHT = '}' + + def test_nested(self): + pytest.skip('unsupported') + + def test_large_nested(self): + pytest.skip('unsupported') + + +class TestDicts(SafeReprTestBase): + + def test_large_key(self): + value = { + 'a' * SafeRepr.maxstring_inner * 3: '', + } + + self.assert_shortened_regex(value, r"{'a+\.\.\.a+': ''}") + + def test_large_value(self): + value = { + '': 'a' * SafeRepr.maxstring_inner * 2, + } + + self.assert_shortened_regex(value, r"{'': 'a+\.\.\.a+'}") + + def test_large_both(self): + value = {} + key = 'a' * SafeRepr.maxstring_inner * 2 + value[key] = key + + self.assert_shortened_regex(value, r"{'a+\.\.\.a+': 'a+\.\.\.a+'}") + + def test_nested_value(self): + d1 = {} + d1_key = 'a' * SafeRepr.maxstring_inner * 2 + d1[d1_key] = d1_key + d2 = {d1_key: d1} + d3 = {d1_key: d2} + + self.assert_shortened_regex(d2, r"{'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}") # noqa + if len(SafeRepr.maxcollection) == 2: + self.assert_shortened_regex(d3, r"{'a+\.\.\.a+': {'a+\.\.\.a+': {\.\.\.}}}") # noqa + else: + self.assert_shortened_regex(d3, r"{'a+\.\.\.a+': {'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}}") # noqa + + def test_empty(self): + # Ensure empty dicts work + self.assert_unchanged({}, '{}') + + def test_sorted(self): + # Ensure dict keys are sorted + d1 = {} + d1['c'] = None + d1['b'] = None + d1['a'] = None + if IS_PY36_OR_GREATER: + self.assert_saferepr(d1, "{'c': None, 'b': None, 'a': None}") + else: + self.assert_saferepr(d1, "{'a': None, 'b': None, 'c': None}") + + @pytest.mark.skipif(sys.version_info < (3, 0), reason='Py3 specific test') + def test_unsortable_keys(self): + # Ensure dicts with unsortable keys do not crash + d1 = {} + for _ in range(100): + d1[object()] = None + with pytest.raises(TypeError): + list(sorted(d1)) + self.saferepr(d1) + + def test_directly_recursive(self): + value = {1: None} + value[2] = value + + self.assert_unchanged(value, '{1: None, 2: {...}}') + + def test_indirectly_recursive(self): + value = {1: None} + value[2] = {3: value} + + self.assert_unchanged(value, '{1: None, 2: {3: {...}}}') + + +class TestOtherPythonTypes(SafeReprTestBase): + # not critical to test: + # singletons + # + # + # + # memoryview + # classmethod + # staticmethod + # property + # enumerate + # reversed + # object + # type + # super + + # @pytest.mark.skip(reason='not written') # TODO: finish! + # def test_file(self): + # raise NotImplementedError + + def test_range_small(self): + range_name = range.__name__ + value = range(1, 42) + + self.assert_unchanged(value, '%s(1, 42)' % (range_name,)) + + @pytest.mark.skipif(sys.version_info < (3, 0), reason='Py3 specific test') + def test_range_large_stop_only(self): + range_name = range.__name__ + stop = SafeRepr.maxcollection[0] + value = range(stop) + + self.assert_unchanged(value, + '%s(0, %s)' % (range_name, stop)) + + def test_range_large_with_start(self): + range_name = range.__name__ + stop = SafeRepr.maxcollection[0] + 1 + value = range(1, stop) + + self.assert_unchanged(value, + '%s(1, %s)' % (range_name, stop)) + + # @pytest.mark.skip(reason='not written') # TODO: finish! + # def test_named_struct(self): + # # e.g. sys.version_info + # raise NotImplementedError + # + # @pytest.mark.skip(reason='not written') # TODO: finish! + # def test_namedtuple(self): + # raise NotImplementedError + # + # @pytest.mark.skip(reason='not written') # TODO: finish! + # @pytest.mark.skipif(sys.version_info < (3, 0), reason='Py3 specific test') + # def test_SimpleNamespace(self): + # raise NotImplementedError + + +class TestUserDefinedObjects(SafeReprTestBase): + + def test_broken_repr(self): + + class TestClass(object): + + def __repr__(self): + raise NameError + + value = TestClass() + + with pytest.raises(NameError): + repr(TestClass()) + self.assert_saferepr(value, object.__repr__(value)) + + def test_large(self): + + class TestClass(object): + + def __repr__(self): + return '<' + 'A' * SafeRepr.maxother_outer * 2 + '>' + + value = TestClass() + + self.assert_shortened_regex(value, r'\') + + def test_inherit_repr(self): + + class TestClass(dict): + pass + + value_dict = TestClass() + + class TestClass2(list): + pass + + value_list = TestClass2() + + self.assert_unchanged(value_dict, '{}') + self.assert_unchanged(value_list, '[]') + + def test_custom_repr(self): + + class TestClass(dict): + + def __repr__(self): + return 'MyRepr' + + value1 = TestClass() + + class TestClass2(list): + + def __repr__(self): + return 'MyRepr' + + value2 = TestClass2() + + self.assert_unchanged(value1, 'MyRepr') + self.assert_unchanged(value2, 'MyRepr') + + def test_custom_repr_many_items(self): + + class TestClass(list): + + def __init__(self, it=()): + list.__init__(self, it) + + def __repr__(self): + return 'MyRepr' + + value1 = TestClass(range(0, 15)) + value2 = TestClass(range(0, 16)) + value3 = TestClass([TestClass(range(0, 10))]) + value4 = TestClass([TestClass(range(0, 11))]) + + self.assert_unchanged(value1, 'MyRepr') + self.assert_shortened(value2, '') + self.assert_unchanged(value3, 'MyRepr') + self.assert_shortened(value4, '') + + def test_custom_repr_large_item(self): + + class TestClass(list): + + def __init__(self, it=()): + list.__init__(self, it) + + def __repr__(self): + return 'MyRepr' + + value1 = TestClass(['a' * (SafeRepr.maxcollection[1] + 1)]) + value2 = TestClass(['a' * (SafeRepr.maxstring_inner + 1)]) + + self.assert_unchanged(value1, 'MyRepr') + self.assert_shortened(value2, '') + + +@pytest.mark.skipif(np is None, reason='could not import numpy') +class TestNumpy(SafeReprTestBase): + # numpy types should all use their native reprs, even arrays + # exceeding limits. + + def test_int32(self): + value = np.int32(123) + + self.assert_unchanged(value, repr(value)) + + def test_float32(self): + value = np.float32(123.456) + + self.assert_unchanged(value, repr(value)) + + def test_zeros(self): + value = np.zeros(SafeRepr.maxcollection[0] + 1) + + self.assert_unchanged(value, repr(value)) + + +@pytest.mark.parametrize('params', [ + {'maxother_outer': 20, 'input': "😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄FFFFFFFF", 'output': '😄😄😄😄😄😄😄😄😄😄😄😄😄...FFFFFF'}, + {'maxother_outer': 10, 'input': "😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄FFFFFFFF", 'output': '😄😄😄😄😄😄...FFF'}, + {'maxother_outer': 10, 'input': u"������������FFFFFFFF", 'output': u"������...FFF"}, + + # Because we can't return bytes, byte-related tests aren't needed (and str works as it should). +]) +@pytest.mark.parametrize('use_str', [True, False]) +def test_py3_str_slicing(params, use_str): + # Note: much simpler in python because __repr__ is required to return str + safe_repr = SafeRepr() + safe_repr.locale_preferred_encoding = 'ascii' + safe_repr.sys_stdout_encoding = params.get('sys_stdout_encoding', 'ascii') + + safe_repr.maxother_outer = params['maxother_outer'] + + if not use_str: + + class MyObj(object): + + def __repr__(self): + return params['input'] + + safe_repr_input = MyObj() + else: + safe_repr_input = params['input'] + expected_output = params['output'] + computed = safe_repr(safe_repr_input) + expected = repr(expected_output) + if use_str: + expected = repr(expected) + assert repr(computed) == expected + + # Check that we can json-encode the return. + assert json.dumps(computed) + + +def test_raw_bytes(): + safe_repr = SafeRepr() + safe_repr.raw_value = True + obj = b'\xed\xbd\xbf\xff\xfe\xfa\xfd' + raw_value_repr = safe_repr(obj) + assert isinstance(raw_value_repr, str) # bytes on py2, str on py3 + assert raw_value_repr == obj.decode('latin1') + + +def test_raw_unicode(): + safe_repr = SafeRepr() + safe_repr.raw_value = True + obj = u'\xed\xbd\xbf\xff\xfe\xfa\xfd' + raw_value_repr = safe_repr(obj) + assert isinstance(raw_value_repr, str) # bytes on py2, str on py3 + assert raw_value_repr == obj + + +def test_no_repr(): + + class MyBytes(object): + + def __init__(self, contents): + self.contents = contents + self.errored = None + + def __iter__(self): + return iter(self.contents) + + def decode(self, encoding): + self.errored = 'decode called' + raise RuntimeError('Should not be called.') + + def __repr__(self): + self.errored = '__repr__ called' + raise RuntimeError('Should not be called.') + + def __getitem__(self, *args): + return self.contents.__getitem__(*args) + + def __len__(self): + return len(self.contents) + + safe_repr = SafeRepr() + safe_repr.string_types = (MyBytes,) + safe_repr.bytes = MyBytes + obj = b'f' * (safe_repr.maxstring_outer * 10) + my_bytes = MyBytes(obj) + raw_value_repr = safe_repr(my_bytes) + assert not my_bytes.errored + diff --git a/tests_python/test_save_locals.py b/tests_python/test_save_locals.py new file mode 100644 index 0000000..ed4bd2c --- /dev/null +++ b/tests_python/test_save_locals.py @@ -0,0 +1,101 @@ +import inspect +import sys +import unittest + +from _pydevd_bundle.pydevd_save_locals import save_locals +from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_IRONPYTHON +import pytest + + +def use_save_locals(name, value): + """ + Attempt to set the local of the given name to value, using locals_to_fast. + """ + frame = inspect.currentframe().f_back + locals_dict = frame.f_locals + locals_dict[name] = value + + save_locals(frame) + + +def check_method(fn): + """ + A harness for testing methods that attempt to modify the values of locals on the stack. + """ + x = 1 + + # The method 'fn' should attempt to set x = 2 in the current frame. + fn('x', 2) + + return x + + + +@pytest.mark.skipif(IS_JYTHON or IS_IRONPYTHON, reason='CPython/pypy only') +class TestSetLocals(unittest.TestCase): + """ + Test setting locals in one function from another function using several approaches. + """ + + def test_set_locals_using_save_locals(self): + x = check_method(use_save_locals) + self.assertEqual(x, 2) # Expected to succeed + + + def test_frame_simple_change(self): + frame = sys._getframe() + a = 20 + frame.f_locals['a'] = 50 + save_locals(frame) + self.assertEqual(50, a) + + + def test_frame_co_freevars(self): + + outer_var = 20 + + def func(): + frame = sys._getframe() + frame.f_locals['outer_var'] = 50 + save_locals(frame) + self.assertEqual(50, outer_var) + + func() + + def test_frame_co_cellvars(self): + + def check_co_vars(a): + frame = sys._getframe() + def function2(): + print(a) + + assert 'a' in frame.f_code.co_cellvars + frame = sys._getframe() + frame.f_locals['a'] = 50 + save_locals(frame) + self.assertEqual(50, a) + + check_co_vars(1) + + + def test_frame_change_in_inner_frame(self): + def change(f): + self.assertTrue(f is not sys._getframe()) + f.f_locals['a']= 50 + save_locals(f) + + + frame = sys._getframe() + a = 20 + change(frame) + self.assertEqual(50, a) + + +if __name__ == '__main__': + suite = unittest.TestSuite() +# suite.addTest(TestSetLocals('test_set_locals_using_dict')) +# #suite.addTest(Test('testCase10a')) +# unittest.TextTestRunner(verbosity=3).run(suite) + + suite = unittest.makeSuite(TestSetLocals) + unittest.TextTestRunner(verbosity=3).run(suite) diff --git a/tests_python/test_schema.py b/tests_python/test_schema.py new file mode 100644 index 0000000..5470076 --- /dev/null +++ b/tests_python/test_schema.py @@ -0,0 +1,142 @@ +from _pydevd_bundle._debug_adapter.pydevd_schema import InitializeRequest, \ + InitializeRequestArguments, InitializeResponse, Capabilities +from _pydevd_bundle._debug_adapter import pydevd_schema, pydevd_base_schema +from _pydevd_bundle._debug_adapter.pydevd_schema import ThreadsResponse + + +def test_schema(): + + json_msg = ''' +{ + "arguments": { + "adapterID": "pydevd", + "clientID": "vscode", + "clientName": "Visual Studio Code", + "columnsStartAt1": true, + "linesStartAt1": true, + "locale": "en-us", + "pathFormat": "path", + "supportsRunInTerminalRequest": true, + "supportsVariablePaging": true, + "supportsVariableType": true + }, + "command": "initialize", + "seq": 1, + "type": "request" +}''' + + initialize_request = pydevd_base_schema.from_json(json_msg) + assert initialize_request.__class__ == InitializeRequest + assert initialize_request.arguments.__class__ == InitializeRequestArguments + assert initialize_request.arguments.adapterID == 'pydevd' + assert initialize_request.command == 'initialize' + assert initialize_request.type == 'request' + assert initialize_request.seq == 1 + + response = pydevd_base_schema.build_response(initialize_request) + assert response.__class__ == InitializeResponse + assert response.seq == -1 # Must be set before sending + assert response.command == 'initialize' + assert response.type == 'response' + assert response.body.__class__ == Capabilities + + assert response.to_dict() == { + "seq":-1, + "type": "response", + "request_seq": 1, + "success": True, + "command": "initialize", + "body": {} + } + + capabilities = response.body # : :type capabilities: Capabilities + capabilities.supportsCompletionsRequest = True + assert response.to_dict() == { + "seq":-1, + "type": "response", + "request_seq": 1, + "success": True, + "command": "initialize", + "body": {'supportsCompletionsRequest':True} + } + + initialize_event = pydevd_schema.InitializedEvent() + assert initialize_event.to_dict() == { + "seq":-1, + "type": "event", + "event": "initialized" + } + + +def test_schema_translation_frame(): + pydevd_base_schema.BaseSchema.initialize_ids_translation() + stack_trace_arguments = pydevd_schema.StackTraceArguments(threadId=1) + stack_trace_request = pydevd_schema.StackTraceRequest(stack_trace_arguments) + + stackFrames = [ + pydevd_schema.StackFrame(id=2 ** 45, name='foo', line=1, column=1).to_dict(), + pydevd_schema.StackFrame(id=2 ** 46, name='bar', line=1, column=1).to_dict(), + ] + body = pydevd_schema.StackTraceResponseBody(stackFrames) + stack_trace_response = pydevd_base_schema.build_response(stack_trace_request, kwargs=dict(body=body)) + as_dict = stack_trace_response.to_dict(update_ids_to_dap=True) + assert as_dict == { + 'type': 'response', + 'request_seq':-1, + 'success': True, + 'command': 'stackTrace', + 'body': {'stackFrames': [ + {'id': 1, 'name': 'foo', 'line': 1, 'column': 1, 'source': {}}, + {'id': 2, 'name': 'bar', 'line': 1, 'column': 1, 'source': {}}, + ]}, + 'seq':-1} + + reconstructed = pydevd_base_schema.from_dict(as_dict, update_ids_from_dap=True) + assert reconstructed.to_dict() == { + 'type': 'response', + 'request_seq':-1, + 'success': True, + 'command': 'stackTrace', + 'body': {'stackFrames': [ + {'id': 2 ** 45, 'name': 'foo', 'line': 1, 'column': 1, 'source': {}}, + {'id': 2 ** 46, 'name': 'bar', 'line': 1, 'column': 1, 'source': {}} + ]}, + 'seq':-1 + } + + +def test_schema_translation_thread(): + from _pydevd_bundle._debug_adapter.pydevd_schema import ThreadsRequest + pydevd_base_schema.BaseSchema.initialize_ids_translation() + + threads = [ + pydevd_schema.Thread(id=2 ** 45, name='foo').to_dict(), + pydevd_schema.Thread(id=2 ** 46, name='bar').to_dict(), + ] + body = pydevd_schema.ThreadsResponseBody(threads) + threads_request = ThreadsRequest() + threads_response = pydevd_base_schema.build_response(threads_request, kwargs=dict(body=body)) + as_dict = threads_response.to_dict(update_ids_to_dap=True) + assert as_dict == { + 'type': 'response', + 'request_seq':-1, + 'success': True, + 'command': 'threads', + 'body': {'threads': [ + {'id': 1, 'name': 'foo'}, + {'id': 2, 'name': 'bar'}, + ]}, + 'seq':-1} + + reconstructed = pydevd_base_schema.from_dict(as_dict, update_ids_from_dap=True) + assert reconstructed.to_dict() == { + 'type': 'response', + 'request_seq':-1, + 'success': True, + 'command': 'threads', + 'body': {'threads': [ + {'id': 2 ** 45, 'name': 'foo'}, + {'id': 2 ** 46, 'name': 'bar'} + ]}, + 'seq':-1 + } diff --git a/tests_python/test_smart_step_into_bytecode.py b/tests_python/test_smart_step_into_bytecode.py new file mode 100644 index 0000000..0a4cd4c --- /dev/null +++ b/tests_python/test_smart_step_into_bytecode.py @@ -0,0 +1,1132 @@ +import sys +from tests_python.debug_constants import TODO_PY311 +try: + from _pydevd_bundle import pydevd_bytecode_utils +except ImportError: + pass +import pytest + +pytestmark = pytest.mark.skipif( + sys.version_info[0] < 3 or + TODO_PY311, reason='Only available for Python 3. / Requires bytecode support in Python 3.11') + + +@pytest.fixture(autouse=True, scope='function') +def enable_strict(): + # In tests enable strict mode (in regular operation it'll be False and will just ignore + # bytecodes we still don't handle as if it didn't change the stack). + pydevd_bytecode_utils.STRICT_MODE = True + yield + pydevd_bytecode_utils.STRICT_MODE = False + + +def check(found, expected): + assert len(found) == len(expected), '%s != %s' % (found, expected) + + last_offset = -1 + for f, e in zip(found, expected): + try: + if isinstance(e.name, (list, tuple, set)): + assert f.name in e.name + else: + assert f.name == e.name + assert f.is_visited == e.is_visited + assert f.line == e.line + assert f.call_order == e.call_order + except AssertionError as exc: + raise AssertionError('%s\nError with: %s - %s' % (exc, f, e)) + + # We can't check the offset because it may be different among different python versions + # so, just check that it's always in order. + assert f.offset > last_offset + last_offset = f.offset + + +def collect_smart_step_into_variants(*args, **kwargs): + try: + return pydevd_bytecode_utils.calculate_smart_step_into_variants(*args, **kwargs) + except: + pass + + # In a failure, rerun with DEBUG! + debug = pydevd_bytecode_utils.DEBUG + pydevd_bytecode_utils.DEBUG = True + try: + return pydevd_bytecode_utils.calculate_smart_step_into_variants(*args, **kwargs) + finally: + pydevd_bytecode_utils.DEBUG = debug + + +def check_names_from_func_str(func_str, expected): + locs = {} + exec(func_str, globals(), locs) + + function = locs['function'] + + class Frame: + f_code = function.__code__ + f_lasti = 0 + + found = collect_smart_step_into_variants( + Frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, expected) + + +def test_smart_step_into_bytecode_info(): + from _pydevd_bundle.pydevd_bytecode_utils import Variant + + def function(): + + def some(arg): + pass + + def call(arg): + pass + + yield sys._getframe() + call(some(call(some()))) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check(found, [ + Variant(name=('_getframe', 'sys'), is_visited=True, line=8, offset=20, call_order=1), + Variant(name='some', is_visited=False, line=9, offset=34, call_order=1), + Variant(name='call', is_visited=False, line=9, offset=36, call_order=1), + Variant(name='some', is_visited=False, line=9, offset=38, call_order=2), + Variant(name='call', is_visited=False, line=9, offset=40, call_order=2), + ]) + + +def check_name_and_line(found, expected): + names_and_lines = set() + for variant in found: + if variant.children_variants: + for v in variant.children_variants: + names_and_lines.add((v.name + (' (in %s)' % variant.name), v.line)) + else: + names_and_lines.add((variant.name, variant.line)) + + if names_and_lines != set(expected): + raise AssertionError('Found: %s' % (sorted(names_and_lines, key=lambda tup:tuple(reversed(tup))),)) + + +def test_smart_step_into_bytecode_info_002(): + + def function(): + yield sys._getframe() + completions = foo.bar( + Something(param1, param2=xxx.yyy), + ) + call() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 5)]) + + +def test_smart_step_into_bytecode_info_003(): + + def function(): + yield sys._getframe() + bbb = foo.bar( + Something(param1, param2=xxx.yyy), {} + ) + call() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 5)]) + + +def test_smart_step_into_bytecode_info_004(): + + def function(): + yield sys._getframe() + bbb = foo.bar( + Something(param1, param2=xxx.yyy), {1: 1} # BUILD_MAP + ) + call() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 5)]) + + +def test_smart_step_into_bytecode_info_005(): + + def function(): + yield sys._getframe() + bbb = foo.bar( + Something(param1, param2=xxx.yyy), {1: 1, 2:2} # BUILD_CONST_KEY_MAP + ) + call() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [ + ('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 5)]) + + +def test_smart_step_into_bytecode_info_006(): + + def function(): + yield sys._getframe() + foo.bar( + Something(), + { + 1: 1, + 2:[ + x for x + in call() + ] + } + ) + call2() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [ + ('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 8), ('call2', 12)]) + + +def test_smart_step_into_bytecode_info_007(): + + def function(): + yield sys._getframe() + a[0] + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('__getitem__', 2)]) + + +def test_smart_step_into_bytecode_info_008(): + + def function(): + yield sys._getframe() + call( + [1, 2, 3]) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('call', 2)]) + + +def test_smart_step_into_bytecode_info_009(): + + def function(): + yield sys._getframe() + [1, 2, 3][0]() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('__getitem__', 2), ('__getitem__().__call__', 2)]) + + +def test_smart_step_into_bytecode_info_011(): + + def function(): + yield sys._getframe() + [1, 2, 3][0]()() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('__getitem__', 2), ('__getitem__().__call__', 2)]) + + +def test_smart_step_into_bytecode_info_012(): + + def function(): + yield sys._getframe() + (lambda a:a)(1) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('', 2)]) + + +def test_smart_step_into_bytecode_info_013(): + + def function(): + yield sys._getframe() + (lambda a:a,)[0](1) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('__getitem__().__call__', 2), ('__getitem__', 2)]) + + +def test_smart_step_into_bytecode_info_014(): + + def function(): + yield sys._getframe() + try: + raise RuntimeError() + except Exception: + call2() + finally: + call3() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('RuntimeError', 3), ('call2', 5), ('call3', 7)]) + + +def test_smart_step_into_bytecode_info_015(): + + def function(): + yield sys._getframe() + with call(): + call2() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('call', 2), ('call2', 3)]) + + +def test_smart_step_into_bytecode_info_016(): + + def function(): + yield sys._getframe() + call2( + 1, + 2, + a=3, + *args, + **kwargs + ) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('call2', 2)]) + + +def test_smart_step_into_bytecode_info_017(): + + def function(): + yield sys._getframe() + call([ + x for x in y + if x == call2() + ]) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, + [('_getframe', 1), ('call', 2), ('__eq__ (in )', 4), ('call2 (in )', 4)] + ) + + +def test_smart_step_into_bytecode_info_018(): + + def function(): + yield sys._getframe() + + class Foo(object): + + def __init__(self): + pass + + f = Foo() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('Foo', 8)]) + + +def test_smart_step_into_bytecode_info_019(): + + def function(): + yield sys._getframe() + + class Foo(object): + + def __init__(self): + pass + + f = Foo() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('Foo', 8)]) + + +def test_smart_step_into_bytecode_info_020(): + + def function(): + yield sys._getframe() + for a in call(): + if a != 1: + a() + break + elif a != 2: + b() + break + else: + continue + else: + raise RuntimeError() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [ + ('_getframe', 1), ('call', 2), ('__ne__', 3), ('a', 4), ('__ne__', 6), ('b', 7), ('RuntimeError', 12)]) + + +def test_smart_step_into_bytecode_info_021(): + + def function(): + yield sys._getframe() + a, b = b, a + a, b, c = c, a, b + a, b, c, d = d, c, a, b + a() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('a', 5)]) + + +def test_smart_step_into_bytecode_info_022(): + + def function(): + yield sys._getframe() + a( + *{1, 2}, + **{ + 1:('1' + '2'), + 2: tuple( + x for x in c() + if x == d()) + } + ) + b() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [ + ('_getframe', 1), ('a', 2), ('tuple', 6), ('c', 7), ('__eq__ (in )', 8), ('d (in )', 8), ('b', 11)]) + + +def test_smart_step_into_bytecode_info_023(): + + def function(): + yield sys._getframe() + tuple( + x for x in + c() + if x == d() + ) + tuple( + x for x in + c() + if x == d() + ) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [ + ('_getframe', 1), ('tuple', 2), ('c', 4), ('__eq__ (in )', 5), ('d (in )', 5), ('tuple', 7), ('c', 9), ('__eq__ (in )', 10), ('d (in )', 10)]) + + +def test_smart_step_into_bytecode_info_024(): + + func = '''def function(): + yield sys._getframe() + call(a ** b) + call(a * b) + call(a @ b) + call(a / b) + call(a // b) + call(a % b) + call(a + b) + call(a - b) + call(a >> b) + call(a << b) + call(a & b) + call(a | b) + call(a ^ b) +''' + locs = {} + exec(func, globals(), locs) + + function = locs['function'] + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [ + ('_getframe', 1), + ('__pow__', 2), + ('call', 2), + + ('__mul__', 3), + ('call', 3), + + ('__matmul__', 4), + ('call', 4), + + ('__div__', 5), + ('call', 5), + + ('__floordiv__', 6), + ('call', 6), + + ('__mod__', 7), + ('call', 7), + + ('__add__', 8), + ('call', 8), + + ('__sub__', 9), + ('call', 9), + + ('__rshift__', 10), + ('call', 10), + + ('__lshift__', 11), + ('call', 11), + + ('__and__', 12), + ('call', 12), + + ('__or__', 13), + ('call', 13), + + ('__xor__', 14), + ('call', 14)], + ) + + +def test_smart_step_into_bytecode_info_025(): + + func = '''def function(): + yield sys._getframe() + a **= b + a *= b + a @= b + a /= b + a //= b + a %= b + a += b + a -= b + a >>= b + a <<= b + a &= b + a |= b + a ^= b + call() +''' + locs = {} + exec(func, globals(), locs) + + function = locs['function'] + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('call', 15)]) + + +@pytest.mark.skipif(sys.version_info[0:2] < (3, 8), reason='Walrus operator only available for Python 3.8 onwards.') +def test_smart_step_into_bytecode_info_026(): + + func = '''def function(): + yield sys._getframe() + call((a:=1)) +''' + locs = {} + exec(func, globals(), locs) + + function = locs['function'] + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('call', 2)]) + + +def test_smart_step_into_bytecode_info_027(): + + def function(): + yield sys._getframe() + + def call(): + pass + + a = [1, call] + a[:1] = [] + x = a[0]() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('__getitem__', 8), ('__getitem__().__call__', 8)]) + + +def test_smart_step_into_bytecode_info_028(): + + def function(): + yield sys._getframe() + + def call(): + pass + + a = [1, call] + a[:1] += [] + x = a[0]() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('__getitem__', 7), ('__getitem__', 8), ('__getitem__().__call__', 8)]) + + +def test_smart_step_into_bytecode_info_029(): + + def function(): + yield sys._getframe() + + call((+b) + (-b) - (not b) * (~b)) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('__add__', 3), ('__mul__', 3), ('__sub__', 3), ('call', 3)]) + + +def test_smart_step_into_bytecode_info_030(): + + def function(): + yield sys._getframe() + + call({a for a in b}) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('call', 3)]) + + +def test_smart_step_into_bytecode_info_031(): + + def function(): + yield sys._getframe() + + call({a: b for a in b}) + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('call', 3)]) + + +def test_smart_step_into_bytecode_info_032(): + + def function(): + yield sys._getframe() + + del a[:2] + call() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 1), ('call', 4)]) + + +def test_smart_step_into_bytecode_info_033(): + + check_names_from_func_str('''def function(): + yield sys._getframe() + + raise call() + ''', [('_getframe', 1), ('call', 3)]) + + +@pytest.mark.skipif(sys.version_info[0:2] < (3, 6), reason='Async only available for Python 3.6 onwards.') +def test_smart_step_into_bytecode_info_034(): + + check_names_from_func_str('''async def function(): + await a() + async for b in c(): + await d() +''', [('a', 1), ('c', 2), ('d', 3)]) + + +def test_smart_step_into_bytecode_info_035(): + + check_names_from_func_str('''def function(): + assert 0, 'Foo' +''', [('AssertionError', 1)]) + + +def test_smart_step_into_bytecode_info_036(): + + check_names_from_func_str('''def function(a): + global some_name + some_name = a + some_name() +''', [('some_name', 3)]) + + +def test_smart_step_into_bytecode_info_037(): + + func = '''def function(): + some_name = 10 + def another(): + nonlocal some_name + some_name = a + some_name() + return another +''' + locs = {} + exec(func, globals(), locs) + + function = locs['function']() + + class Frame: + f_code = function.__code__ + f_lasti = 0 + + found = collect_smart_step_into_variants( + Frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('some_name', 3)]) + + +def test_smart_step_into_bytecode_info_038(): + check_names_from_func_str('''def function(): + try: + call() + finally: + call2() +''', [('call', 2), ('call2', 4)]) + + +def test_smart_step_into_bytecode_info_039(): + check_names_from_func_str('''def function(): + try: + call() + except: + return call2() + finally: + return call3() +''', [('call', 2), ('call2', 4), ('call3', 6)]) + + +def test_smart_step_into_bytecode_info_040(): + check_names_from_func_str('''def function(): + a.call = foo() + a.call() +''', [('foo', 1), ('call', 2)]) + + +def test_smart_step_into_bytecode_info_041(): + check_names_from_func_str('''def function(): + foo = 10 + del foo + foo = method + foo() +''', [('foo', 4)]) + + +def test_smart_step_into_bytecode_info_042(): + check_names_from_func_str(''' +foo = 10 +def function(): + global foo + foo() +''', [('foo', 2)]) + + +def test_smart_step_into_bytecode_info_043(): + + def function(call): + + def another_function(): + yield sys._getframe() + + call() + + for frame in another_function(): + yield frame + + generator = iter(function(lambda: None)) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('_getframe', 3), ('call', 5)]) + + +def test_smart_step_into_bytecode_info_044(): + check_names_from_func_str(''' +def function(args): + call, *c = args + call(*c) +''', [('call', 2)]) + + +def test_smart_step_into_bytecode_info_045(): + check_names_from_func_str(''' +def function(): + x.foo = 10 + del x.foo + x.foo = lambda:None + x.foo() +''', [('foo', 4)]) + + +def test_smart_step_into_bytecode_info_046(): + check_names_from_func_str(''' +a = 10 +def function(args): + global a + del a + a() +''', [('a', 3)]) + + +def test_smart_step_into_bytecode_info_047(): + check_names_from_func_str(''' +def function(): + call(a, b=1, *c, **kw) +''', [('call', 1)]) + + +def test_smart_step_into_bytecode_info_048(): + check_names_from_func_str(''' +def function(fn): + fn = call(fn) + + def pa(): + fn() + + return pa() + +''', [('call', 1), ('pa', 6)]) + + +def test_smart_step_into_bytecode_info_049(): + + def function(foo): + + class SomeClass(object): + implementation = foo + + implementation() + f = sys._getframe() + + return SomeClass.f + + frame = function(object) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + check_name_and_line(found, [('implementation', 5), ('_getframe', 6)]) + + +def test_smart_step_into_bytecode_info_050(): + check_names_from_func_str(''' +def function(): + ('a' 'b').index('x') + +''', [('index', 1)]) + + +def test_smart_step_into_bytecode_info_051(): + check_names_from_func_str(''' +def function(): + v = 1 + v2 = 2 + call((f'a{v()!r}' f'b{v2()}')) + +''', [('call', 3), ('v', 3), ('v2', 3)]) + + +def test_smart_step_into_bytecode_info_052(): + check_names_from_func_str(''' +def function(): + v = 1 + v2 = 2 + call({*v(), *v2()}) + +''', [('call', 3), ('v', 3), ('v2', 3)]) + + +def test_smart_step_into_bytecode_info_053(): + check_names_from_func_str(''' +def function(): + v = 1 + v2 = 2 + call({**v(), **v2()}) + +''', [('call', 3), ('v', 3), ('v2', 3)]) + + +def test_smart_step_into_bytecode_info_054(): + check_names_from_func_str(''' +def function(): + import a + from a import b + call() + +''', [('call', 3)]) + + +def test_smart_step_into_bytecode_info_055(): + check_names_from_func_str(''' +async def function(): + async with lock() as foo: + await foo() + +''', [('lock', 1), ('foo', 2)]) + + +def test_smart_step_into_bytecode_info_056(): + check_names_from_func_str(''' +def function(mask_path): + wc = some_func( + parsed_content, + np.array( + Image.open(mask_path) + ) + ) + +''', [('some_func', 1), ('array', 3), ('open', 4)]) + + +def test_smart_step_into_bytecode_info_057(): + check_names_from_func_str(''' +def function(mask_path): + wc = some_func( + parsed_content, + np.array( + my.pack.Image.open(mask_path) + ) + ) + +''', [('some_func', 1), ('array', 3), ('open', 4)]) + + +def test_get_smart_step_into_variant_from_frame_offset(): + from _pydevd_bundle.pydevd_bytecode_utils import Variant + + found = [ + Variant(name='_getframe', is_visited=True, line=8, offset=20, call_order=1), + Variant(name='some', is_visited=False, line=9, offset=34, call_order=1), + Variant(name='call', is_visited=False, line=9, offset=36, call_order=1), + Variant(name='some', is_visited=False, line=9, offset=38, call_order=2), + Variant(name='call', is_visited=False, line=9, offset=40, call_order=2), + ] + assert pydevd_bytecode_utils.get_smart_step_into_variant_from_frame_offset(19, found) is None + assert pydevd_bytecode_utils.get_smart_step_into_variant_from_frame_offset(20, found).offset == 20 + + assert pydevd_bytecode_utils.get_smart_step_into_variant_from_frame_offset(33, found).offset == 20 + + assert pydevd_bytecode_utils.get_smart_step_into_variant_from_frame_offset(34, found).offset == 34 + assert pydevd_bytecode_utils.get_smart_step_into_variant_from_frame_offset(35, found).offset == 34 + + assert pydevd_bytecode_utils.get_smart_step_into_variant_from_frame_offset(36, found).offset == 36 + + assert pydevd_bytecode_utils.get_smart_step_into_variant_from_frame_offset(44, found).offset == 40 + + +def test_smart_step_into_bytecode_info_00eq(): + from _pydevd_bundle.pydevd_bytecode_utils import Variant + + def function(): + a = 1 + b = 1 + if a == b: + pass + if a != b: + pass + if a > b: + pass + if a >= b: + pass + if a < b: + pass + if a <= b: + pass + if a is b: + pass + + yield sys._getframe() + + generator = iter(function()) + frame = next(generator) + + found = collect_smart_step_into_variants( + frame, 0, 99999, base=function.__code__.co_firstlineno) + + if sys.version_info[:2] < (3, 9): + check(found, [ + Variant(name='__eq__', is_visited=True, line=3, offset=18, call_order=1), + Variant(name='__ne__', is_visited=True, line=5, offset=33, call_order=1), + Variant(name='__gt__', is_visited=True, line=7, offset=48, call_order=1), + Variant(name='__ge__', is_visited=True, line=9, offset=63, call_order=1), + Variant(name='__lt__', is_visited=True, line=11, offset=78, call_order=1), + Variant(name='__le__', is_visited=True, line=13, offset=93, call_order=1), + Variant(name='is', is_visited=True, line=15, offset=108, call_order=1), + Variant(name=('_getframe', 'sys'), is_visited=True, line=18, offset=123, call_order=1), + ]) + else: + check(found, [ + Variant(name='__eq__', is_visited=True, line=3, offset=18, call_order=1), + Variant(name='__ne__', is_visited=True, line=5, offset=33, call_order=1), + Variant(name='__gt__', is_visited=True, line=7, offset=48, call_order=1), + Variant(name='__ge__', is_visited=True, line=9, offset=63, call_order=1), + Variant(name='__lt__', is_visited=True, line=11, offset=78, call_order=1), + Variant(name='__le__', is_visited=True, line=13, offset=93, call_order=1), + Variant(name=('_getframe', 'sys'), is_visited=True, line=18, offset=123, call_order=1), + ]) + + +def _test_find_bytecode(): + import glob + import dis + from io import StringIO + root_dir = 'C:\\bin\\Python310\\Lib\\site-packages\\' + + i = 0 + for filename in glob.iglob(root_dir + '**/*.py', recursive=True): + print(filename) + with open(filename, 'r', encoding='utf-8') as stream: + try: + contents = stream.read() + except: + sys.stderr.write('Unable to read file: %s' % (filename,)) + continue + + code_obj = compile(contents, filename, 'exec') + s = StringIO() + dis.dis(code_obj, file=s) + # https://docs.python.org/3.10/library/dis.html has references to the new opcodes added. + if 'COPY_DICT_WITHOUT_KEYS' in s.getvalue(): + dis.dis(code_obj) + raise AssertionError('Found bytecode in: %s' % filename) + + # i += 1 + # if i == 1000: + # break + diff --git a/tests_python/test_suspended_frames_manager.py b/tests_python/test_suspended_frames_manager.py new file mode 100644 index 0000000..6c89b17 --- /dev/null +++ b/tests_python/test_suspended_frames_manager.py @@ -0,0 +1,142 @@ +import sys +from _pydevd_bundle.pydevd_constants import int_types, GENERATED_LEN_ATTR_NAME +from _pydevd_bundle.pydevd_resolver import MAX_ITEMS_TO_HANDLE, TOO_LARGE_ATTR +from _pydevd_bundle import pydevd_frame_utils + + +def get_frame(): + var1 = 1 + var2 = [var1] + var3 = {33: [var1]} + return sys._getframe() + + +def check_vars_dict_expected(as_dict, expected): + assert as_dict == expected + + +class _DummyPyDB(object): + + def __init__(self): + from _pydevd_bundle.pydevd_api import PyDevdAPI + self.variable_presentation = PyDevdAPI.VariablePresentation() + + +def test_suspended_frames_manager(): + from _pydevd_bundle.pydevd_suspended_frames import SuspendedFramesManager + from _pydevd_bundle.pydevd_utils import DAPGrouper + suspended_frames_manager = SuspendedFramesManager() + py_db = _DummyPyDB() + with suspended_frames_manager.track_frames(py_db) as tracker: + # : :type tracker: _FramesTracker + thread_id = 'thread1' + frame = get_frame() + tracker.track(thread_id, pydevd_frame_utils.create_frames_list_from_frame(frame)) + + assert suspended_frames_manager.get_thread_id_for_variable_reference(id(frame)) == thread_id + + variable = suspended_frames_manager.get_variable(id(frame)) + + # Should be properly sorted. + assert ['var1', 'var2', 'var3'] == [x.get_name()for x in variable.get_children_variables()] + + as_dict = dict((x.get_name(), x.get_var_data()) for x in variable.get_children_variables()) + var_reference = as_dict['var2'].pop('variablesReference') + assert isinstance(var_reference, int_types) # The variable reference is always a new int. + assert isinstance(as_dict['var3'].pop('variablesReference'), int_types) # The variable reference is always a new int. + + check_vars_dict_expected(as_dict, { + 'var1': {'name': 'var1', 'value': '1', 'type': 'int', 'evaluateName': 'var1', 'variablesReference': 0}, + 'var2': {'name': 'var2', 'value': '[1]', 'type': 'list', 'evaluateName': 'var2'}, + 'var3': {'name': 'var3', 'value': '{33: [1]}', 'type': 'dict', 'evaluateName': 'var3'} + }) + + # Now, same thing with a different format. + as_dict = dict((x.get_name(), x.get_var_data(fmt={'hex': True})) for x in variable.get_children_variables()) + var_reference = as_dict['var2'].pop('variablesReference') + assert isinstance(var_reference, int_types) # The variable reference is always a new int. + assert isinstance(as_dict['var3'].pop('variablesReference'), int_types) # The variable reference is always a new int. + + check_vars_dict_expected(as_dict, { + 'var1': {'name': 'var1', 'value': '0x1', 'type': 'int', 'evaluateName': 'var1', 'variablesReference': 0}, + 'var2': {'name': 'var2', 'value': '[0x1]', 'type': 'list', 'evaluateName': 'var2'}, + 'var3': {'name': 'var3', 'value': '{0x21: [0x1]}', 'type': 'dict', 'evaluateName': 'var3'} + }) + + var2 = dict((x.get_name(), x) for x in variable.get_children_variables())['var2'] + children_vars = var2.get_children_variables() + as_dict = (dict([x.get_name(), x.get_var_data()] for x in children_vars if x.get_name() not in DAPGrouper.SCOPES_SORTED)) + assert as_dict == { + '0': {'name': '0', 'value': '1', 'type': 'int', 'evaluateName': 'var2[0]', 'variablesReference': 0 }, + GENERATED_LEN_ATTR_NAME: {'name': GENERATED_LEN_ATTR_NAME, 'value': '1', 'type': 'int', 'evaluateName': 'len(var2)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}, }, + } + + var3 = dict((x.get_name(), x) for x in variable.get_children_variables())['var3'] + children_vars = var3.get_children_variables() + as_dict = (dict([x.get_name(), x.get_var_data()] for x in children_vars if x.get_name() not in DAPGrouper.SCOPES_SORTED)) + assert isinstance(as_dict['33'].pop('variablesReference'), int_types) # The variable reference is always a new int. + + check_vars_dict_expected(as_dict, { + '33': {'name': '33', 'value': "[1]", 'type': 'list', 'evaluateName': 'var3[33]'}, + GENERATED_LEN_ATTR_NAME: {'name': GENERATED_LEN_ATTR_NAME, 'value': '1', 'type': 'int', 'evaluateName': 'len(var3)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}, } + }) + + +_NUMBER_OF_ITEMS_TO_CREATE = MAX_ITEMS_TO_HANDLE + 300 + + +def get_dict_large_frame(): + obj = {} + for idx in range(_NUMBER_OF_ITEMS_TO_CREATE): + obj[idx] = (1) + return sys._getframe() + + +def get_set_large_frame(): + obj = set() + for idx in range(_NUMBER_OF_ITEMS_TO_CREATE): + obj.add(idx) + return sys._getframe() + + +def get_tuple_large_frame(): + obj = tuple(range(_NUMBER_OF_ITEMS_TO_CREATE)) + return sys._getframe() + + +def test_get_child_variables(): + from _pydevd_bundle.pydevd_suspended_frames import SuspendedFramesManager + suspended_frames_manager = SuspendedFramesManager() + py_db = _DummyPyDB() + for frame in ( + get_dict_large_frame(), + get_set_large_frame(), + get_tuple_large_frame(), + ): + with suspended_frames_manager.track_frames(py_db) as tracker: + # : :type tracker: _FramesTracker + thread_id = 'thread1' + tracker.track(thread_id, pydevd_frame_utils.create_frames_list_from_frame(frame)) + + assert suspended_frames_manager.get_thread_id_for_variable_reference(id(frame)) == thread_id + + variable = suspended_frames_manager.get_variable(id(frame)) + + children_variables = variable.get_child_variable_named('obj').get_children_variables() + assert len(children_variables) < _NUMBER_OF_ITEMS_TO_CREATE + + found_too_large = False + found_len = False + for x in children_variables: + if x.name == TOO_LARGE_ATTR: + var_data = x.get_var_data() + assert 'readOnly' in var_data['presentationHint']['attributes'] + found_too_large = True + elif x.name == GENERATED_LEN_ATTR_NAME: + found_len = True + + if not found_too_large: + raise AssertionError('Expected to find variable named: %s' % (TOO_LARGE_ATTR,)) + if not found_len: + raise AssertionError('Expected to find variable named: len()') + diff --git a/tests_python/test_timeout_tracker.py b/tests_python/test_timeout_tracker.py new file mode 100644 index 0000000..388f119 --- /dev/null +++ b/tests_python/test_timeout_tracker.py @@ -0,0 +1,128 @@ +from _pydevd_bundle import pydevd_timeout +from _pydevd_bundle.pydevd_constants import IS_PYPY, IS_CPYTHON +from _pydevd_bundle.pydevd_timeout import create_interrupt_this_thread_callback +from tests_python.debugger_unittest import wait_for_condition +import pytest +import threading +import time + + +@pytest.yield_fixture(autouse=True) +def _enable_debug_msgs(): + original = pydevd_timeout._DEBUG + pydevd_timeout._DEBUG = True + yield + pydevd_timeout._DEBUG = original + + +def test_timeout(): + + class _DummyPyDb(object): + + def __init__(self): + self.created_pydb_daemon_threads = {} + + raise_timeout = pydevd_timeout.create_interrupt_this_thread_callback() + + def on_timeout(arg): + assert arg == 1 + raise_timeout() + + py_db = _DummyPyDb() + timeout_tracker = pydevd_timeout.TimeoutTracker(py_db) + try: + if IS_PYPY: + timeout = 2 + else: + timeout = 20 + with timeout_tracker.call_on_timeout(1, on_timeout, kwargs={'arg': 1}): + time.sleep(timeout) + except KeyboardInterrupt: + pass + + +def test_timeout_0_time(): + + class _DummyPyDb(object): + + def __init__(self): + self.created_pydb_daemon_threads = {} + + raise_timeout = pydevd_timeout.create_interrupt_this_thread_callback() + + def on_timeout(arg): + assert arg == 1 + raise_timeout() + + py_db = _DummyPyDb() + timeout_tracker = pydevd_timeout.TimeoutTracker(py_db) + try: + with timeout_tracker.call_on_timeout(0, on_timeout, kwargs={'arg': 1}): + time.sleep(1) + except KeyboardInterrupt: + pass + + +@pytest.mark.skipif(not IS_CPYTHON, reason='This only works in CPython.') +def test_create_interrupt_this_thread_callback(): + + class MyThread(threading.Thread): + + def __init__(self): + threading.Thread.__init__(self) + self.finished = False + self.daemon = True + self.interrupt_thread = None + self.interrupted = False + + def run(self): + try: + self.interrupt_thread = create_interrupt_this_thread_callback() + while True: + time.sleep(.2) + except KeyboardInterrupt: + self.interrupted = True + finally: + self.finished = True + + t = MyThread() + t.start() + wait_for_condition(lambda: t.interrupt_thread is not None) + + t.interrupt_thread() + + wait_for_condition(lambda: t.finished) + + assert t.interrupted + + +@pytest.mark.skipif(True, reason='Skipping because running this test can interrupt the test suite execution.') +def test_interrupt_main_thread(): + + from _pydevd_bundle.pydevd_constants import IS_PY39_OR_GREATER + + class MyThread(threading.Thread): + + def __init__(self, interrupt_thread_callback): + threading.Thread.__init__(self) + self.interrupt_thread_callback = interrupt_thread_callback + + def run(self): + time.sleep(.5) + self.interrupt_thread_callback() + + initial_time = time.time() + interrupt_only_on_callback = IS_PYPY or IS_PY39_OR_GREATER + if interrupt_only_on_callback: + timeout = 2 + else: + timeout = 20 + try: + t = MyThread(create_interrupt_this_thread_callback()) + t.start() + time.sleep(timeout) + except KeyboardInterrupt: + if not interrupt_only_on_callback: + assert time.time() - initial_time < timeout + else: + raise AssertionError('Expected main thread to be interrupted.') diff --git a/tests_python/test_tracing_gotchas.py b/tests_python/test_tracing_gotchas.py new file mode 100644 index 0000000..6620402 --- /dev/null +++ b/tests_python/test_tracing_gotchas.py @@ -0,0 +1,101 @@ +import pytest +import sys +from _pydevd_bundle.pydevd_constants import NO_FTRACE +from tests_python.debugger_unittest import IS_JYTHON + + +class Tracer(object): + + def __init__(self): + self.call_calls = 0 + self.line_calls = 0 + + def trace_func(self, frame, event, arg): + if event == 'call': + self.call_calls += 1 + return self.on_call() + + elif event == 'line': + self.line_calls += 1 + # Should disable tracing when None is returned (but doesn't). + return self.on_line(frame, event, arg) + + else: + return self.trace_func + + def on_call(self): + return self.trace_func + + def on_line(self, frame, event, arg): + return None + + +class TracerSettingNone(Tracer): + + def on_line(self, frame, event, arg): + frame.f_trace = NO_FTRACE + return NO_FTRACE + + +class TracerChangeToOtherTracing(Tracer): + + def on_line(self, frame, event, arg): + return self._no_trace + + def _no_trace(self, frame, event, arg): + return self._no_trace + + +class TracerDisableOnCall(Tracer): + + def on_call(self): + return None + + +def test_tracing_gotchas(): + ''' + Summary of the gotchas tested: + + If 'call' is used, a None return value is used for the tracing. Afterwards the return may or may + not be ignored depending on the Python version. + + Also, on Python 2.6, the trace function may not be set to None as it'll give an error + afterwards (it needs to be set to an empty tracing function). + + All of the versions seem to work when the return value is a new callable though. + + Note: according to: https://docs.python.org/3/library/sys.html#sys.settrace the behavior + does not follow the spec (but we have to work with it nonetheless). + + Note: Jython seems to do what's written in the docs. + ''' + + def method(): + _a = 1 + _b = 1 + _c = 1 + _d = 1 + + for tracer, line_events in ( + (Tracer(), 1 if IS_JYTHON else 4), + (TracerSettingNone(), 1), + (TracerChangeToOtherTracing(), 1), + (TracerDisableOnCall(), 0), + ): + curr_trace_func = sys.gettrace() + try: + sys.settrace(tracer.trace_func) + + method() + + if tracer.call_calls != 1: + pytest.fail('Expected a single call event. Found: %s' % (tracer.call_calls)) + + if tracer.line_calls != line_events: + pytest.fail('Expected %s line events. Found: %s. Tracer: %s' % (line_events, tracer.line_calls, tracer)) + finally: + sys.settrace(curr_trace_func) + + +if __name__ == '__main__': + pytest.main(['-k', 'test_tracing_gotchas']) diff --git a/tests_python/test_tracing_on_top_level.py b/tests_python/test_tracing_on_top_level.py new file mode 100644 index 0000000..fa53ad4 --- /dev/null +++ b/tests_python/test_tracing_on_top_level.py @@ -0,0 +1,485 @@ +from pydevd import PyDB +import pytest +from tests_python.debugger_unittest import IS_CPYTHON +import threading + +DEBUG = False + + +class DummyTopLevelFrame(object): + + __slots__ = ['f_code', 'f_back', 'f_lineno', 'f_trace'] + + def __init__(self, method): + self.f_code = method.__code__ + self.f_back = None + self.f_lineno = method.__code__.co_firstlineno + + +class DummyWriter(object): + + __slots__ = ['commands', 'command_meanings'] + + def __init__(self): + self.commands = [] + self.command_meanings = [] + + def add_command(self, cmd): + from _pydevd_bundle.pydevd_comm import ID_TO_MEANING + meaning = ID_TO_MEANING[str(cmd.id)] + if DEBUG: + print(meaning) + self.command_meanings.append(meaning) + if DEBUG: + print(cmd._as_bytes.decode('utf-8')) + self.commands.append(cmd) + + +class DummyPyDb(PyDB): + + def __init__(self): + PyDB.__init__(self, set_as_global=False) + + def do_wait_suspend( + self, thread, frame, event, arg, *args, **kwargs): + from _pydevd_bundle.pydevd_constants import STATE_RUN + info = thread.additional_info + info.pydev_original_step_cmd = -1 + info.pydev_step_cmd = -1 + info.pydev_step_stop = None + info.pydev_state = STATE_RUN + + return PyDB.do_wait_suspend(self, thread, frame, event, arg, *args, **kwargs) + + +class _TraceTopLevel(object): + + def __init__(self): + self.py_db = DummyPyDb() + self.py_db.writer = DummyWriter() + + def set_target_func(self, target_func): + self.frame = DummyTopLevelFrame(target_func) + self.target_func = target_func + + def get_exception_arg(self): + import sys + try: + raise AssertionError() + except: + arg = sys.exc_info() + return arg + + def create_add_exception_breakpoint_with_policy( + self, exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries): + return '\t'.join(str(x) for x in [ + exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries]) + + def add_unhandled_exception_breakpoint(self): + from _pydevd_bundle.pydevd_process_net_command import process_net_command + from tests_python.debugger_unittest import CMD_ADD_EXCEPTION_BREAK + for exc_name in ('AssertionError', 'RuntimeError'): + process_net_command( + self.py_db, + CMD_ADD_EXCEPTION_BREAK, + 1, + self.create_add_exception_breakpoint_with_policy(exc_name, '0', '1', '0'), + ) + + def assert_last_commands(self, *commands): + assert self.py_db.writer.command_meanings[-len(commands):] == list(commands) + + def assert_no_commands(self, *commands): + for command in commands: + assert command not in self.py_db.writer.command_meanings + + def trace_dispatch(self, event, arg): + from _pydevd_bundle import pydevd_trace_dispatch_regular + + self.new_trace_func = pydevd_trace_dispatch_regular.trace_dispatch(self.py_db, self.frame, event, arg) + return self.new_trace_func + + def call_trace_dispatch(self, line): + self.frame.f_lineno = line + return self.trace_dispatch('call', None) + + def exception_trace_dispatch(self, line, arg): + self.frame.f_lineno = line + self.new_trace_func = self.new_trace_func(self.frame, 'exception', arg) + + def return_trace_dispatch(self, line): + self.frame.f_lineno = line + self.new_trace_func = self.new_trace_func(self.frame, 'return', None) + + def assert_paused(self): + self.assert_last_commands('CMD_THREAD_SUSPEND', 'CMD_THREAD_RUN') + + def assert_not_paused(self): + self.assert_no_commands('CMD_THREAD_SUSPEND', 'CMD_THREAD_RUN') + + +@pytest.yield_fixture +def trace_top_level(): + # Note: we trace with a dummy frame with no f_back to simulate the issue in a remote attach. + yield _TraceTopLevel() + threading.current_thread().additional_info = None + + +@pytest.fixture +def trace_top_level_unhandled(trace_top_level): + trace_top_level.add_unhandled_exception_breakpoint() + return trace_top_level + + +_expected_functions_to_test = 0 + + +def mark_handled(func): + global _expected_functions_to_test + _expected_functions_to_test += 1 + func.__handled__ = True + return func + + +def mark_unhandled(func): + global _expected_functions_to_test + _expected_functions_to_test += 1 + func.__handled__ = False + return func + + +#------------------------------------------------------------------------------------------- Handled +@mark_handled +def raise_handled_exception(): + try: + raise AssertionError() + except: + pass + + +@mark_handled +def raise_handled_exception2(): + try: + raise AssertionError() + except AssertionError: + pass + + +@mark_handled +def raise_handled_exception3(): + try: + try: + raise AssertionError() + except RuntimeError: + pass + except AssertionError: + pass + + +@mark_handled +def raise_handled_exception3a(): + try: + try: + raise AssertionError() + except AssertionError: + pass + except RuntimeError: + pass + + +@mark_handled +def raise_handled_exception4(): + try: + try: + raise AssertionError() + except RuntimeError: + pass + except ( + RuntimeError, + AssertionError): + pass + + +@mark_handled +def raise_handled(): + try: + try: + raise AssertionError() + except RuntimeError: + pass + except ( + RuntimeError, + AssertionError): + pass + + +@mark_handled +def raise_handled2(): + try: + raise AssertionError() + except ( + RuntimeError, + AssertionError): + pass + + try: + raise RuntimeError() + except ( + RuntimeError, + AssertionError): + pass + + +@mark_handled +def raise_handled9(): + for i in range(2): + try: + raise AssertionError() + except AssertionError: + if i == 1: + try: + raise + except: + pass + + +@mark_handled +def raise_handled10(): + for i in range(2): + try: + raise AssertionError() + except AssertionError: + if i == 1: + try: + raise + except: + pass + + _foo = 10 + +#----------------------------------------------------------------------------------------- Unhandled + + +@mark_unhandled +def raise_unhandled_exception(): + raise AssertionError() + + +@mark_unhandled +def raise_unhandled_exception_not_in_except_clause(): + try: + raise AssertionError() + except RuntimeError: + pass + + +@mark_unhandled +def raise_unhandled(): + try: + try: + raise AssertionError() + except RuntimeError: + pass + except ( + RuntimeError, + AssertionError): + raise + + +@mark_unhandled +def raise_unhandled2(): + try: + raise AssertionError() + except AssertionError: + pass + + raise AssertionError() + + +@mark_unhandled +def raise_unhandled3(): + try: + raise AssertionError() + except AssertionError: + raise AssertionError() + + +@mark_unhandled +def raise_unhandled4(): + try: + raise AssertionError() + finally: + _a = 10 + + +@mark_unhandled +def raise_unhandled5(): + try: + raise AssertionError() + finally: + raise RuntimeError() + + +@mark_unhandled +def raise_unhandled6(): + try: + raise AssertionError() + finally: + raise RuntimeError( + 'in another' + 'line' + ) + + +@mark_unhandled +def raise_unhandled7(): + try: + raise AssertionError() + except AssertionError: + try: + raise AssertionError() + except RuntimeError: + pass + + +@mark_unhandled +def raise_unhandled8(): + for i in range(2): + + def get_exc_to_treat(): + if i == 0: + return AssertionError + return RuntimeError + + try: + raise AssertionError() + except get_exc_to_treat(): + pass + + +@mark_unhandled +def raise_unhandled9(): + for i in range(2): + + def get_exc_to_treat(): + if i == 0: + return AssertionError + return RuntimeError + + try: + raise AssertionError() + except get_exc_to_treat(): + try: + raise + except: + pass + + +@mark_unhandled +def raise_unhandled10(): + for i in range(2): + try: + raise AssertionError() + except AssertionError: + if i == 1: + try: + raise + except RuntimeError: + pass + + +@mark_unhandled +def raise_unhandled11(): + try: + raise_unhandled10() + finally: + if True: + pass + + +@mark_unhandled +def raise_unhandled12(): + try: + raise AssertionError() + except: + pass + try: + raise AssertionError() + finally: + if True: + pass + + +@mark_unhandled +def reraise_handled_exception(): + try: + raise AssertionError() # Should be considered unhandled (because it's reraised). + except: + raise + + +def _collect_events(func): + collected = [] + + def events_collector(frame, event, arg): + if frame.f_code.co_name == func.__name__: + collected.append((event, frame.f_lineno, arg)) + return events_collector + + import sys + sys.settrace(events_collector) + try: + func() + except: + import traceback;traceback.print_exc() + finally: + sys.settrace(None) + return collected + + +def _replay_events(collected, trace_top_level_unhandled): + for event, lineno, arg in collected: + if event == 'call': + # Notify only unhandled + new_trace_func = trace_top_level_unhandled.call_trace_dispatch(lineno) + # Check that it's dealing with the top-level event. + if hasattr(new_trace_func, 'get_method_object'): + new_trace_func = new_trace_func.get_method_object() + assert new_trace_func.__name__ == 'trace_dispatch_and_unhandled_exceptions' + elif event == 'exception': + trace_top_level_unhandled.exception_trace_dispatch(lineno, arg) + + elif event == 'return': + trace_top_level_unhandled.return_trace_dispatch(lineno) + + elif event == 'line': + pass + + else: + raise AssertionError('Unexpected: %s' % (event,)) + + +def _collect_target_functions(): +# return [raise_unhandled10] + ret = [] + for _key, method in sorted(dict(globals()).items()): + if hasattr(method, '__handled__'): + ret.append(method) + + assert len(ret) == _expected_functions_to_test + return ret + + +@pytest.mark.skipif(not IS_CPYTHON, reason='try..except info only available on CPython') +@pytest.mark.parametrize("func", _collect_target_functions()) +def test_tracing_on_top_level_unhandled(trace_top_level_unhandled, func): + trace_top_level_unhandled.set_target_func(func) + + collected_events = _collect_events(func) + # print([(x[0], x[1], x[2].__class__.__name__) for x in collected_events]) + _replay_events(collected_events, trace_top_level_unhandled) + + if func.__handled__: + trace_top_level_unhandled.assert_not_paused() # handled exception + else: + trace_top_level_unhandled.assert_paused() diff --git a/tests_python/test_utilities.py b/tests_python/test_utilities.py new file mode 100644 index 0000000..09b8b19 --- /dev/null +++ b/tests_python/test_utilities.py @@ -0,0 +1,550 @@ +import threading + +from _pydevd_bundle.pydevd_utils import convert_dap_log_message_to_expression +from tests_python.debug_constants import TEST_GEVENT, IS_CPYTHON +import sys +from _pydevd_bundle.pydevd_constants import IS_WINDOWS, IS_PYPY, IS_JYTHON +import pytest +import os +from _pydevd_bundle.pydevd_thread_lifecycle import pydevd_find_thread_by_id + + +def test_expression_to_evaluate(): + from _pydevd_bundle.pydevd_vars import _expression_to_evaluate + assert _expression_to_evaluate(b'expr') == b'expr' + assert _expression_to_evaluate(b' expr') == b'expr' + assert _expression_to_evaluate(b'for a in b:\n foo') == b'for a in b:\n foo' + assert _expression_to_evaluate(b' for a in b:\n foo') == b'for a in b:\nfoo' + assert _expression_to_evaluate(b' for a in b:\nfoo') == b' for a in b:\nfoo' + assert _expression_to_evaluate(b'\tfor a in b:\n\t\tfoo') == b'for a in b:\n\tfoo' + + assert _expression_to_evaluate(u' expr') == u'expr' + assert _expression_to_evaluate(u' for a in expr:\n pass') == u'for a in expr:\npass' + + +@pytest.mark.skipif(IS_WINDOWS, reason='Brittle on Windows.') +def test_is_main_thread(): + ''' + This is now skipped due to it failing sometimes (only on Windows). + + I (fabioz) am not 100% sure on why this happens, but when this happens the initial thread for + the tests seems to be a non main thread. + + i.e.: With an autouse fixture with a scope='session' with the code and error message below, it's + possible to see that at even at the `conftest` import (where indent_at_import is assigned) the + current thread is already not the main thread. + + As far as I know this seems to be an issue in how pytest-xdist is running the tests (i.e.: + I couldn't reproduce this without running with `python -m pytest -n 0 ...`). + + -------- Code to check error / error output ---------- + + from _pydevd_bundle.pydevd_utils import is_current_thread_main_thread + import threading + indent_at_import = threading.get_ident() + + @pytest.yield_fixture(autouse=True, scope='session') + def check_main_thread_session(request): + if not is_current_thread_main_thread(): + error_msg = 'Current thread does not seem to be a main thread at the start of the session. Details:\n' + current_thread = threading.current_thread() + error_msg += 'Current thread: %s\n' % (current_thread,) + error_msg += 'Current thread ident: %s\n' % (current_thread.ident,) + error_msg += 'ident at import: %s\n' % (indent_at_import,) + error_msg += 'curr ident: %s\n' % (threading.get_ident(),) + + if hasattr(threading, 'main_thread'): + error_msg += 'Main thread found: %s\n' % (threading.main_thread(),) + error_msg += 'Main thread id: %s\n' % (threading.main_thread().ident,) + else: + error_msg += 'Current main thread not instance of: %s (%s)\n' % ( + threading._MainThread, current_thread.__class__.__mro__,) + +> raise AssertionError(error_msg) +E AssertionError: Current thread does not seem to be a main thread at the start of the session. Details: +E Current thread: <_DummyThread(Dummy-2, started daemon 7072)> +E Current thread ident: 7072 +E ident at import: 7072 +E curr ident: 7072 +E Main thread found: <_MainThread(MainThread, started 5924)> +E Main thread id: 5924 + +conftest.py:67: AssertionError + ''' + from _pydevd_bundle.pydevd_utils import is_current_thread_main_thread + from _pydevd_bundle.pydevd_utils import dump_threads + if not is_current_thread_main_thread(): + error_msg = 'Current thread does not seem to be a main thread. Details:\n' + current_thread = threading.current_thread() + error_msg += 'Current thread: %s\n' % (current_thread,) + + if hasattr(threading, 'main_thread'): + error_msg += 'Main thread found: %s\n' % (threading.main_thread(),) + else: + error_msg += 'Current main thread not instance of: %s (%s)' % ( + threading._MainThread, current_thread.__class__.__mro__,) + + from io import StringIO + + stream = StringIO() + dump_threads(stream=stream) + error_msg += '\n\n' + stream.getvalue() + raise AssertionError(error_msg) + + class NonMainThread(threading.Thread): + + def run(self): + self.is_main_thread = is_current_thread_main_thread() + + non_main_thread = NonMainThread() + non_main_thread.start() + non_main_thread.join() + assert not non_main_thread.is_main_thread + + +def test_find_thread(): + from _pydevd_bundle.pydevd_constants import get_current_thread_id + assert pydevd_find_thread_by_id('123') is None + + assert pydevd_find_thread_by_id( + get_current_thread_id(threading.current_thread())) is threading.current_thread() + + +def check_dap_log_message(log_message, expected, evaluated, eval_locals=None): + ret = convert_dap_log_message_to_expression(log_message) + assert ret == expected + assert (eval(ret, eval_locals)) == evaluated + return ret + + +def test_convert_dap_log_message_to_expression(): + assert check_dap_log_message( + 'a', + "'a'", + 'a', + ) + assert check_dap_log_message( + 'a {a}', + "'a %s' % (a,)", + 'a value', + {'a': 'value'} + ) + assert check_dap_log_message( + 'a {1}', + "'a %s' % (1,)", + 'a 1' + ) + assert check_dap_log_message( + 'a { }', + "'a '", + 'a ' + ) + assert check_dap_log_message( + 'a {1} {2}', + "'a %s %s' % (1, 2,)", + 'a 1 2', + ) + assert check_dap_log_message( + 'a {{22:22}} {2}', + "'a %s %s' % ({22:22}, 2,)", + 'a {22: 22} 2' + ) + assert check_dap_log_message( + 'a {(22,33)}} {2}', + "'a %s} %s' % ((22,33), 2,)", + 'a (22, 33)} 2' + ) + + assert check_dap_log_message( + 'a {{1: {1}}}', + "'a %s' % ({1: {1}},)", + 'a {1: {1}}' + ) + + # Error condition. + assert check_dap_log_message( + 'a {{22:22} {2}', + "'Unbalanced braces in: a {{22:22} {2}'", + 'Unbalanced braces in: a {{22:22} {2}' + ) + + +def test_pydevd_log(): + from _pydev_bundle import pydev_log + import io + from _pydev_bundle.pydev_log import log_context + + stream = io.StringIO() + with log_context(0, stream=stream): + pydev_log.critical('always') + pydev_log.info('never') + + assert stream.getvalue().endswith('always\n') + + stream = io.StringIO() + with log_context(1, stream=stream): + pydev_log.critical('always') + pydev_log.info('this too') + assert stream.getvalue().endswith('always\n0.00s - this too\n') + + stream = io.StringIO() + with log_context(0, stream=stream): + pydev_log.critical('always %s', 1) + + assert stream.getvalue().endswith('always 1\n') + + stream = io.StringIO() + with log_context(0, stream=stream): + pydev_log.critical('always %s %s', 1, 2) + + assert stream.getvalue().endswith('always 1 2\n') + + stream = io.StringIO() + with log_context(0, stream=stream): + pydev_log.critical('always %s %s', 1) + + # Even if there's an error in the formatting, don't fail, just print the message and args. + assert stream.getvalue().endswith('always %s %s - (1,)\n') + + stream = io.StringIO() + with log_context(0, stream=stream): + try: + raise RuntimeError() + except: + pydev_log.exception('foo') + + assert 'foo\n' in stream.getvalue() + assert 'raise RuntimeError()' in stream.getvalue() + + stream = io.StringIO() + with log_context(0, stream=stream): + pydev_log.error_once('always %s %s', 1) + + # Even if there's an error in the formatting, don't fail, just print the message and args. + assert stream.getvalue().endswith('always %s %s - (1,)\n') + + +def test_pydevd_logging_files(tmpdir): + from _pydev_bundle import pydev_log + from _pydevd_bundle.pydevd_constants import DebugInfoHolder + import os.path + from _pydev_bundle.pydev_log import _LoggingGlobals + + import io + from _pydev_bundle.pydev_log import log_context + + stream = io.StringIO() + with log_context(0, stream=stream): + d1 = str(tmpdir.join('d1')) + d2 = str(tmpdir.join('d2')) + + for d in (d1, d2): + DebugInfoHolder.PYDEVD_DEBUG_FILE = os.path.join(d, 'file.txt') + pydev_log.initialize_debug_stream(reinitialize=True) + + assert os.path.normpath(_LoggingGlobals._debug_stream_filename) == \ + os.path.normpath(os.path.join(d, 'file.%s.txt' % os.getpid())) + + assert os.path.exists(_LoggingGlobals._debug_stream_filename) + + assert pydev_log.list_log_files(DebugInfoHolder.PYDEVD_DEBUG_FILE) == [ + _LoggingGlobals._debug_stream_filename] + + +def _check_tracing_other_threads(): + import pydevd_tracing + import time + from tests_python.debugger_unittest import wait_for_condition + import _thread + + # This method is called in a subprocess, so, make sure we exit properly even if we somehow + # deadlock somewhere else. + def dump_threads_and_kill_on_timeout(): + time.sleep(10) + from _pydevd_bundle import pydevd_utils + pydevd_utils.dump_threads() + time.sleep(1) + import os + os._exit(77) + + _thread.start_new_thread(dump_threads_and_kill_on_timeout, ()) + + def method(): + while True: + trace_func = sys.gettrace() + if trace_func: + threading.current_thread().trace_func = trace_func + break + time.sleep(.01) + + def dummy_thread_method(): + threads.append(threading.current_thread()) + method() + + threads = [] + threads.append(threading.Thread(target=method)) + threads[-1].daemon = True + threads[-1].start() + _thread.start_new_thread(dummy_thread_method, ()) + + wait_for_condition(lambda: len(threads) == 2, msg=lambda:'Found threads: %s' % (threads,)) + + def tracing_func(frame, event, args): + return tracing_func + + assert pydevd_tracing.set_trace_to_threads(tracing_func) == 0 + + def check_threads_tracing_func(): + for t in threads: + if getattr(t, 'trace_func', None) != tracing_func: + return False + return True + + wait_for_condition(check_threads_tracing_func) + + assert tracing_func == sys.gettrace() + + +def _build_launch_env(): + import os + import pydevd + + environ = os.environ.copy() + cwd = os.path.abspath(os.path.dirname(__file__)) + assert os.path.isdir(cwd) + + resources_dir = os.path.join(os.path.dirname(pydevd.__file__), 'tests_python', 'resources') + assert os.path.isdir(resources_dir) + + attach_to_process_dir = os.path.join(os.path.dirname(pydevd.__file__), 'pydevd_attach_to_process') + assert os.path.isdir(attach_to_process_dir) + + pydevd_dir = os.path.dirname(pydevd.__file__) + assert os.path.isdir(pydevd_dir) + + environ['PYTHONPATH'] = ( + cwd + os.pathsep + + resources_dir + os.pathsep + + attach_to_process_dir + os.pathsep + + pydevd_dir + os.pathsep + + environ.get('PYTHONPATH', '') + ) + return cwd, environ + + +def _check_in_separate_process(method_name, module_name='test_utilities', update_env={}): + import subprocess + cwd, environ = _build_launch_env() + environ.update(update_env) + + subprocess.check_call( + [sys.executable, '-c', 'import %(module_name)s;%(module_name)s.%(method_name)s()' % dict( + method_name=method_name, module_name=module_name)], + env=environ, + cwd=cwd + ) + + +@pytest.mark.skipif(not IS_CPYTHON, reason='Functionality to trace other threads requires CPython.') +def test_tracing_other_threads(): + # Note: run this test in a separate process so that it doesn't mess with any current tracing + # in our current process. + _check_in_separate_process('_check_tracing_other_threads') + + +def _check_basic_tracing(): + import pydevd_tracing + + # Note: run this test in a separate process so that it doesn't mess with any current tracing + # in our current process. + called = [0] + + def tracing_func(frame, event, args): + called[0] = called[0] + 1 + return tracing_func + + assert pydevd_tracing.set_trace_to_threads(tracing_func) == 0 + + def foo(): + pass + + foo() + assert called[0] > 2 + + +@pytest.mark.skipif(not IS_CPYTHON, reason='Functionality to trace other threads requires CPython.') +def test_tracing_basic(): + _check_in_separate_process('_check_basic_tracing') + + +@pytest.mark.skipif(not IS_CPYTHON, reason='Functionality to trace other threads requires CPython.') +def test_find_main_thread_id(): + # Note: run the checks below in a separate process because they rely heavily on what's available + # in the env (such as threads or having threading imported). + _check_in_separate_process('check_main_thread_id_simple', '_pydevd_test_find_main_thread_id') + _check_in_separate_process('check_main_thread_id_multiple_threads', '_pydevd_test_find_main_thread_id') + _check_in_separate_process('check_win_threads', '_pydevd_test_find_main_thread_id') + _check_in_separate_process('check_fix_main_thread_id_multiple_threads', '_pydevd_test_find_main_thread_id') + + import subprocess + import pydevd + cwd, environ = _build_launch_env() + + subprocess.check_call( + [sys.executable, '-m', '_pydevd_test_find_main_thread_id'], + env=environ, + cwd=cwd + ) + + resources_dir = os.path.join(os.path.dirname(pydevd.__file__), 'tests_python', 'resources') + + subprocess.check_call( + [sys.executable, os.path.join(resources_dir, '_pydevd_test_find_main_thread_id.py') ], + env=environ, + cwd=cwd + ) + + +@pytest.mark.skipif(not IS_WINDOWS or IS_JYTHON, reason='Windows-only test.') +def test_get_ppid(): + from _pydevd_bundle.pydevd_api import PyDevdAPI + api = PyDevdAPI() + # On python 3 we can check that our internal api which is used for Python 2 gives the + # same result as os.getppid. + ppid = os.getppid() + assert api._get_windows_ppid() == ppid + + +def _check_gevent(expect_msg): + from _pydevd_bundle.pydevd_utils import notify_about_gevent_if_needed + assert not notify_about_gevent_if_needed() + import gevent + assert not notify_about_gevent_if_needed() + import gevent.monkey + assert not notify_about_gevent_if_needed() + gevent.monkey.patch_all() + assert notify_about_gevent_if_needed() == expect_msg + + +def check_notify_on_gevent_loaded(): + _check_gevent(True) + + +def check_dont_notify_on_gevent_loaded(): + _check_gevent(False) + + +@pytest.mark.skipif(not TEST_GEVENT, reason='Gevent not installed.') +def test_gevent_notify(): + _check_in_separate_process('check_notify_on_gevent_loaded', update_env={'GEVENT_SUPPORT': ''}) + _check_in_separate_process('check_dont_notify_on_gevent_loaded', update_env={'GEVENT_SUPPORT': 'True'}) + + +@pytest.mark.skipif(True, reason='Skipping because running this test can interrupt the test suite execution.') +def test_interrupt_main_thread(): + from _pydevd_bundle.pydevd_utils import interrupt_main_thread + import time + + main_thread = threading.current_thread() + + def interrupt(): + # sleep here so that the main thread in the test can get to the sleep too (otherwise + # if we interrupt too fast we won't really check that the sleep itself + # got interrupted -- although if that happens on some tests runs it's + # not really an issue either). + time.sleep(1) + interrupt_main_thread(main_thread) + + if IS_PYPY: + # On PyPy a time.sleep() is not being properly interrupted, + # so, let's just check that it throws the KeyboardInterrupt in the + # next instruction. + timeout = 2 + else: + timeout = 20 + initial_time = time.time() + try: + t = threading.Thread(target=interrupt) + t.start() + time.sleep(timeout) + except KeyboardInterrupt: + if not IS_PYPY: + actual_timeout = time.time() - initial_time + # If this fails it means that although we interrupted Python actually waited for the next + # instruction to send the event and didn't really interrupt the thread. + assert actual_timeout < timeout, 'Expected the actual timeout (%s) to be < than the timeout (%s)' % ( + actual_timeout, timeout) + else: + raise AssertionError('KeyboardInterrupt not generated in main thread.') + + +@pytest.mark.skipif(sys.version_info[0] < 3, reason='Only available for Python 3.') +def test_get_smart_step_into_variant_from_frame_offset(): + from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset + variants = [] + assert get_smart_step_into_variant_from_frame_offset(0, variants) is None + + class DummyVariant(object): + + def __init__(self, offset): + self.offset = offset + + variants.append(DummyVariant(1)) + assert get_smart_step_into_variant_from_frame_offset(0, variants) is None + assert get_smart_step_into_variant_from_frame_offset(1, variants) is variants[0] + assert get_smart_step_into_variant_from_frame_offset(2, variants) is variants[0] + + variants.append(DummyVariant(3)) + assert get_smart_step_into_variant_from_frame_offset(0, variants) is None + assert get_smart_step_into_variant_from_frame_offset(1, variants) is variants[0] + assert get_smart_step_into_variant_from_frame_offset(2, variants) is variants[0] + assert get_smart_step_into_variant_from_frame_offset(3, variants) is variants[1] + assert get_smart_step_into_variant_from_frame_offset(4, variants) is variants[1] + + +def test_threading_hide_pydevd(): + + class T(threading.Thread): + + def __init__(self, is_pydev_daemon_thread): + from _pydevd_bundle.pydevd_daemon_thread import mark_as_pydevd_daemon_thread + threading.Thread.__init__(self) + if is_pydev_daemon_thread: + mark_as_pydevd_daemon_thread(self) + else: + self.daemon = True + self.event = threading.Event() + + def run(self): + self.event.wait(10) + + current_count = threading.active_count() + t0 = T(True) + t1 = T(False) + t0.start() + t1.start() + + # i.e.: the patching doesn't work for other implementations. + if IS_CPYTHON: + assert threading.active_count() == current_count + 1 + assert t0 not in threading.enumerate() + else: + assert threading.active_count() == current_count + 2 + assert t0 in threading.enumerate() + + assert t1 in threading.enumerate() + t0.event.set() + t1.event.set() + + +def test_import_token_from_module(): + from _pydevd_bundle.pydevd_utils import import_attr_from_module + + with pytest.raises(ImportError): + import_attr_from_module('sys') + + with pytest.raises(ImportError): + import_attr_from_module('sys.settrace.foo') + + assert import_attr_from_module('sys.settrace') == sys.settrace + assert import_attr_from_module('threading.Thread.start') == threading.Thread.start diff --git a/tests_python/tests_single_notification.py b/tests_python/tests_single_notification.py new file mode 100644 index 0000000..fbbfbf9 --- /dev/null +++ b/tests_python/tests_single_notification.py @@ -0,0 +1,293 @@ +from functools import partial +import itertools +from pydevd import AbstractSingleNotificationBehavior +import time + +import pytest + +from _pydevd_bundle.pydevd_daemon_thread import run_as_pydevd_daemon_thread +from tests_python.debugger_unittest import CMD_THREAD_SUSPEND, CMD_STEP_OVER, CMD_SET_BREAK +from _pydev_bundle.pydev_override import overrides + +STATE_RUN = 1 +STATE_SUSPEND = 2 + + +class _ThreadInfo(object): + + next_thread_id = partial(next, itertools.count()) + + def __init__(self): + self.state = STATE_RUN + self.thread_id = self.next_thread_id() + + +class _CustomSingleNotificationBehavior(AbstractSingleNotificationBehavior): + + NOTIFY_OF_PAUSE_TIMEOUT = .01 + + __slots__ = AbstractSingleNotificationBehavior.__slots__ + ['notification_queue'] + + def __init__(self, py_db): + try: + from queue import Queue + except ImportError: + from Queue import Queue + super(_CustomSingleNotificationBehavior, self).__init__(py_db) + self.notification_queue = Queue() + + @overrides(AbstractSingleNotificationBehavior.send_resume_notification) + def send_resume_notification(self, *args, **kwargs): + # print('put resume', threading.current_thread()) + self.notification_queue.put('resume') + + @overrides(AbstractSingleNotificationBehavior.send_suspend_notification) + def send_suspend_notification(self, *args, **kwargs): + # print('put suspend', threading.current_thread()) + self.notification_queue.put('suspend') + + def do_wait_suspend(self, thread_info, stop_reason): + with self.notify_thread_suspended(thread_info.thread_id, stop_reason=stop_reason): + while thread_info.state == STATE_SUSPEND: + time.sleep(.1) + + +@pytest.fixture +def _dummy_pydb(): + return _DummyPyDB() + + +@pytest.fixture( + name='single_notification_behavior', +# params=range(50) # uncomment to run the tests many times. +) +def _single_notification_behavior(_dummy_pydb): + single_notification_behavior = _CustomSingleNotificationBehavior(_dummy_pydb) + return single_notification_behavior + + +@pytest.fixture(name='notification_queue') +def _notification_queue(single_notification_behavior): + return single_notification_behavior.notification_queue + + +def wait_for_notification(notification_queue, msg): + __tracebackhide__ = True + try: + from Queue import Empty + except ImportError: + from queue import Empty + try: + found = notification_queue.get(timeout=2) + assert found == msg + except Empty: + raise AssertionError('Timed out while waiting for %s notification.' % (msg,)) + + +def join_thread(t): + __tracebackhide__ = True + t.join(2) + assert not t.is_alive(), 'Thread still alive after timeout.s' + + +class _DummyPyDB(object): + + def __init__(self): + self.created_pydb_daemon_threads = {} + + +def test_single_notification_1(single_notification_behavior, notification_queue): + ''' + 1. Resume before pausing 2nd thread + + - user pauses all (2) threads + - break first -> send notification + - user presses continue all before second is paused + - 2nd should not pause nor send notification + - resume all notification should be sent + ''' + thread_info1 = _ThreadInfo() + thread_info2 = _ThreadInfo() + + # pause all = set_suspend both + single_notification_behavior.increment_suspend_time() + single_notification_behavior.on_pause() + thread_info1.state = STATE_SUSPEND + thread_info2.state = STATE_SUSPEND + + dummy_py_db = _DummyPyDB() + + t = run_as_pydevd_daemon_thread(dummy_py_db, single_notification_behavior.do_wait_suspend, thread_info1, CMD_THREAD_SUSPEND) + thread_info1.state = STATE_RUN + # Set 2 to run before it starts (should not send additional message). + thread_info2.state = STATE_RUN + t.join() + + assert notification_queue.qsize() == 2 + assert notification_queue.get() == 'suspend' + assert notification_queue.get() == 'resume' + assert notification_queue.qsize() == 0 + + # Run thread 2 only now (no additional notification). + t = run_as_pydevd_daemon_thread(dummy_py_db, single_notification_behavior.do_wait_suspend, thread_info1, CMD_THREAD_SUSPEND) + t.join() + + assert notification_queue.qsize() == 0 + + +def test_single_notification_2(single_notification_behavior, notification_queue): + ''' + 2. Pausing all then stepping + + - user pauses all (2) threads + - break first -> send notification + - break second (no notification) + - user steps in second + - suspend in second -> send resume/pause notification on step + ''' + thread_info1 = _ThreadInfo() + thread_info2 = _ThreadInfo() + + dummy_py_db = _DummyPyDB() + + # pause all = set_suspend both + single_notification_behavior.increment_suspend_time() + single_notification_behavior.on_pause() + thread_info1.state = STATE_SUSPEND + thread_info2.state = STATE_SUSPEND + + # Leave both in break mode + t1 = run_as_pydevd_daemon_thread(dummy_py_db, single_notification_behavior.do_wait_suspend, thread_info1, CMD_THREAD_SUSPEND) + wait_for_notification(notification_queue, 'suspend') + + t2 = run_as_pydevd_daemon_thread(dummy_py_db, single_notification_behavior.do_wait_suspend, thread_info2, CMD_THREAD_SUSPEND) + + # Step would actually be set state to STEP, which would result in resuming + # and then stopping again as if it was a SUSPEND (which calls a set_supend again with + # the step mode). + thread_info2.state = STATE_RUN + join_thread(t2) + wait_for_notification(notification_queue, 'resume') + + single_notification_behavior.increment_suspend_time() + thread_info2.state = STATE_SUSPEND + t2 = run_as_pydevd_daemon_thread(dummy_py_db, single_notification_behavior.do_wait_suspend, thread_info2, CMD_STEP_OVER) + wait_for_notification(notification_queue, 'suspend') + + thread_info1.state = STATE_RUN + thread_info2.state = STATE_RUN + # First does a resume notification, the other remains quiet. + wait_for_notification(notification_queue, 'resume') + + join_thread(t2) + join_thread(t1) + assert notification_queue.qsize() == 0 + + +def test_single_notification_3(single_notification_behavior, notification_queue, _dummy_pydb): + ''' + 3. Deadlocked thread + + - user adds breakpoint in thread.join() -- just before threads becomes deadlocked + - breakpoint hits -> send notification + - pauses 2nd thread (no notification) + - user steps over thead.join() -> never completes + - user presses pause + - second thread is already stopped + - send notification regarding 2nd thread (still stopped). + - leave both threads running: no suspend should be shown as there are no stopped threads + - when thread is paused, show suspend notification + ''' + + # i.e.: stopping at breakpoint + thread_info1 = _ThreadInfo() + single_notification_behavior.increment_suspend_time() + thread_info1.state = STATE_SUSPEND + t1 = run_as_pydevd_daemon_thread(_dummy_pydb, single_notification_behavior.do_wait_suspend, thread_info1, CMD_SET_BREAK) + + # i.e.: stop because of breakpoint + thread_info2 = _ThreadInfo() + thread_info2.state = STATE_SUSPEND + t2 = run_as_pydevd_daemon_thread(_dummy_pydb, single_notification_behavior.do_wait_suspend, thread_info2, CMD_SET_BREAK) + + wait_for_notification(notification_queue, 'suspend') + + # i.e.: step over (thread 2 is still suspended and this one never completes) + thread_info1.state = STATE_RUN + wait_for_notification(notification_queue, 'resume') + + join_thread(t1) + + # On pause we should notify that the thread 2 is suspended (after timeout if no other thread suspends first). + single_notification_behavior.increment_suspend_time() + single_notification_behavior.on_pause() + thread_info1.state = STATE_SUSPEND + thread_info2.state = STATE_SUSPEND + wait_for_notification(notification_queue, 'suspend') + + thread_info2.state = STATE_RUN + wait_for_notification(notification_queue, 'resume') + + join_thread(t2) + assert notification_queue.qsize() == 0 + assert not single_notification_behavior._suspended_thread_ids + + # Now, no threads are running and pause is pressed + # (maybe we could do a thread dump in this case as this + # means nothing is stopped after pause is requested and + # the timeout elapses). + single_notification_behavior.increment_suspend_time() + single_notification_behavior.on_pause() + thread_info1.state = STATE_SUSPEND + thread_info2.state = STATE_SUSPEND + + time.sleep(single_notification_behavior.NOTIFY_OF_PAUSE_TIMEOUT * 2) + assert notification_queue.qsize() == 0 + + t1 = run_as_pydevd_daemon_thread(_dummy_pydb, single_notification_behavior.do_wait_suspend, thread_info1, CMD_THREAD_SUSPEND) + wait_for_notification(notification_queue, 'suspend') + thread_info1.state = STATE_RUN + wait_for_notification(notification_queue, 'resume') + join_thread(t1) + assert notification_queue.qsize() == 0 + + +def test_single_notification_4(single_notification_behavior, notification_queue, _dummy_pydb): + ''' + 4. Delayed stop + + - user presses pause + - stops first (2nd keeps running) + - user steps on first + - 2nd hits before first ends step (should not send any notification) + - when step finishes send notification + ''' + thread_info1 = _ThreadInfo() + thread_info2 = _ThreadInfo() + + single_notification_behavior.increment_suspend_time() + single_notification_behavior.on_pause() + thread_info1.state = STATE_SUSPEND + thread_info2.state = STATE_SUSPEND + + t1 = run_as_pydevd_daemon_thread(_dummy_pydb, single_notification_behavior.do_wait_suspend, thread_info1, CMD_THREAD_SUSPEND) + wait_for_notification(notification_queue, 'suspend') + thread_info1.state = STATE_RUN + wait_for_notification(notification_queue, 'resume') + join_thread(t1) + + t2 = run_as_pydevd_daemon_thread(_dummy_pydb, single_notification_behavior.do_wait_suspend, thread_info1, CMD_THREAD_SUSPEND) + time.sleep(.1) + assert notification_queue.qsize() == 0 + + single_notification_behavior.increment_suspend_time() + thread_info1.state = STATE_SUSPEND + t1 = run_as_pydevd_daemon_thread(_dummy_pydb, single_notification_behavior.do_wait_suspend, thread_info1, CMD_STEP_OVER) + wait_for_notification(notification_queue, 'suspend') + thread_info2.state = STATE_RUN + thread_info1.state = STATE_RUN + join_thread(t1) + join_thread(t2) + wait_for_notification(notification_queue, 'resume') + assert notification_queue.qsize() == 0 + diff --git a/tests_runfiles/not_in_default_pythonpath.txt b/tests_runfiles/not_in_default_pythonpath.txt new file mode 100644 index 0000000..29cdc5b --- /dev/null +++ b/tests_runfiles/not_in_default_pythonpath.txt @@ -0,0 +1 @@ +(no __init__.py file) \ No newline at end of file diff --git a/tests_runfiles/samples/.cvsignore b/tests_runfiles/samples/.cvsignore new file mode 100644 index 0000000..d1c8995 --- /dev/null +++ b/tests_runfiles/samples/.cvsignore @@ -0,0 +1,2 @@ +*.class +*.pyc diff --git a/tests_runfiles/samples/nested_dir/.cvsignore b/tests_runfiles/samples/nested_dir/.cvsignore new file mode 100644 index 0000000..d1c8995 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/.cvsignore @@ -0,0 +1,2 @@ +*.class +*.pyc diff --git a/tests_runfiles/samples/nested_dir/__init__.py b/tests_runfiles/samples/nested_dir/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/__init__.py @@ -0,0 +1 @@ + diff --git a/tests_runfiles/samples/nested_dir/nested2/.cvsignore b/tests_runfiles/samples/nested_dir/nested2/.cvsignore new file mode 100644 index 0000000..d1c8995 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/nested2/.cvsignore @@ -0,0 +1,2 @@ +*.class +*.pyc diff --git a/tests_runfiles/samples/nested_dir/nested2/__init__.py b/tests_runfiles/samples/nested_dir/nested2/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/nested2/__init__.py @@ -0,0 +1 @@ + diff --git a/tests_runfiles/samples/nested_dir/nested2/deep_nest_test.py b/tests_runfiles/samples/nested_dir/nested2/deep_nest_test.py new file mode 100644 index 0000000..7b1972b --- /dev/null +++ b/tests_runfiles/samples/nested_dir/nested2/deep_nest_test.py @@ -0,0 +1,22 @@ +import unittest + +class SampleTest(unittest.TestCase): + + def setUp(self): + return + + def tearDown(self): + return + + def test_non_unique_name(self): + pass + + def test_asdf2(self): + pass + + def test_i_am_a_unique_test_name(self): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/tests_runfiles/samples/nested_dir/nested2/non_test_file.py b/tests_runfiles/samples/nested_dir/nested2/non_test_file.py new file mode 100644 index 0000000..470c650 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/nested2/non_test_file.py @@ -0,0 +1,3 @@ + +""" i am a python file with no tests """ +pass diff --git a/tests_runfiles/samples/nested_dir/nested3/.cvsignore b/tests_runfiles/samples/nested_dir/nested3/.cvsignore new file mode 100644 index 0000000..d1c8995 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/nested3/.cvsignore @@ -0,0 +1,2 @@ +*.class +*.pyc diff --git a/tests_runfiles/samples/nested_dir/nested3/__init__.py b/tests_runfiles/samples/nested_dir/nested3/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/nested3/__init__.py @@ -0,0 +1 @@ + diff --git a/tests_runfiles/samples/nested_dir/nested3/junk.txt b/tests_runfiles/samples/nested_dir/nested3/junk.txt new file mode 100644 index 0000000..14dd4dd --- /dev/null +++ b/tests_runfiles/samples/nested_dir/nested3/junk.txt @@ -0,0 +1 @@ +im a junk file diff --git a/tests_runfiles/samples/nested_dir/nested3/non_test_file.py b/tests_runfiles/samples/nested_dir/nested3/non_test_file.py new file mode 100644 index 0000000..470c650 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/nested3/non_test_file.py @@ -0,0 +1,3 @@ + +""" i am a python file with no tests """ +pass diff --git a/tests_runfiles/samples/nested_dir/non_test_file.py b/tests_runfiles/samples/nested_dir/non_test_file.py new file mode 100644 index 0000000..470c650 --- /dev/null +++ b/tests_runfiles/samples/nested_dir/non_test_file.py @@ -0,0 +1,3 @@ + +""" i am a python file with no tests """ +pass diff --git a/tests_runfiles/samples/nested_dir/simple4_test.py b/tests_runfiles/samples/nested_dir/simple4_test.py new file mode 100644 index 0000000..ba5d45f --- /dev/null +++ b/tests_runfiles/samples/nested_dir/simple4_test.py @@ -0,0 +1,16 @@ +import unittest + +class NestedSampleTest(unittest.TestCase): + + def setUp(self): + return + + def tearDown(self): + return + + def test_non_unique_name(self): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/tests_runfiles/samples/non_test_file.py b/tests_runfiles/samples/non_test_file.py new file mode 100644 index 0000000..470c650 --- /dev/null +++ b/tests_runfiles/samples/non_test_file.py @@ -0,0 +1,3 @@ + +""" i am a python file with no tests """ +pass diff --git a/tests_runfiles/samples/not_in_default_pythonpath.txt b/tests_runfiles/samples/not_in_default_pythonpath.txt new file mode 100644 index 0000000..29cdc5b --- /dev/null +++ b/tests_runfiles/samples/not_in_default_pythonpath.txt @@ -0,0 +1 @@ +(no __init__.py file) \ No newline at end of file diff --git a/tests_runfiles/samples/simple2_test.py b/tests_runfiles/samples/simple2_test.py new file mode 100644 index 0000000..d46468e --- /dev/null +++ b/tests_runfiles/samples/simple2_test.py @@ -0,0 +1,16 @@ +import unittest + +class YetAnotherSampleTest(unittest.TestCase): + + def setUp(self): + return + + def tearDown(self): + return + + def test_abc(self): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/tests_runfiles/samples/simple3_test.py b/tests_runfiles/samples/simple3_test.py new file mode 100644 index 0000000..da1ccbf --- /dev/null +++ b/tests_runfiles/samples/simple3_test.py @@ -0,0 +1,16 @@ +import unittest + +class StillYetAnotherSampleTest(unittest.TestCase): + + def setUp(self): + return + + def tearDown(self): + return + + def test_non_unique_name(self): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/tests_runfiles/samples/simpleClass_test.py b/tests_runfiles/samples/simpleClass_test.py new file mode 100644 index 0000000..3a9c900 --- /dev/null +++ b/tests_runfiles/samples/simpleClass_test.py @@ -0,0 +1,14 @@ +import unittest + +class SetUpClassTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + raise ValueError("This is an INTENTIONAL value error in setUpClass.") + + def test_blank(self): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/tests_runfiles/samples/simpleModule_test.py b/tests_runfiles/samples/simpleModule_test.py new file mode 100644 index 0000000..fdde67e --- /dev/null +++ b/tests_runfiles/samples/simpleModule_test.py @@ -0,0 +1,16 @@ +import unittest + +def setUpModule(): + raise ValueError("This is an INTENTIONAL value error in setUpModule.") + +class SetUpModuleTest(unittest.TestCase): + + def setUp(cls): + pass + + def test_blank(self): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/tests_runfiles/samples/simple_test.py b/tests_runfiles/samples/simple_test.py new file mode 100644 index 0000000..619df7c --- /dev/null +++ b/tests_runfiles/samples/simple_test.py @@ -0,0 +1,45 @@ +import unittest + +class SampleTest(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_xxxxxx1(self): + self.fail('Fail test 2') + def test_xxxxxx2(self): + pass + def test_xxxxxx3(self): + pass + def test_xxxxxx4(self): + pass + def test_non_unique_name(self): + print('non unique name ran') + + +class AnotherSampleTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + def test_1(self): + pass + def test_2(self): + """ im a doc string""" + pass + def todo_not_tested(self): + ''' + Not there by default! + ''' + + +if __name__ == '__main__': +# suite = unittest.makeSuite(SampleTest, 'test') +# runner = unittest.TextTestRunner( verbosity=3 ) +# runner.run(suite) + unittest.main() diff --git a/tests_runfiles/test_pydevd_property.py b/tests_runfiles/test_pydevd_property.py new file mode 100644 index 0000000..aa1d010 --- /dev/null +++ b/tests_runfiles/test_pydevd_property.py @@ -0,0 +1,124 @@ +''' +Created on Aug 22, 2011 + +@author: hussain.bohra +@author: fabioz +''' + +import os +import sys +import unittest + +#======================================================================================================================= +# Test +#======================================================================================================================= +class Test(unittest.TestCase): + """Test cases to validate custom property implementation in pydevd + """ + + def setUp(self, nused=None): + self.tempdir = os.path.join(os.path.dirname(os.path.dirname(__file__))) + sys.path.insert(0, self.tempdir) + from _pydevd_bundle import pydevd_traceproperty + self.old = pydevd_traceproperty.replace_builtin_property() + + + def tearDown(self, unused=None): + from _pydevd_bundle import pydevd_traceproperty + pydevd_traceproperty.replace_builtin_property(self.old) + sys.path.remove(self.tempdir) + + + def test_property(self): + """Test case to validate custom property + """ + + from _pydevd_bundle import pydevd_traceproperty + class TestProperty(object): + + def __init__(self): + self._get = 0 + self._set = 0 + self._del = 0 + + def get_name(self): + self._get += 1 + return self.__name + + def set_name(self, value): + self._set += 1 + self.__name = value + + def del_name(self): + self._del += 1 + del self.__name + name = property(get_name, set_name, del_name, "name's docstring") + self.assertEqual(name.__class__, pydevd_traceproperty.DebugProperty) + + testObj = TestProperty() + self._check(testObj) + + + def test_property2(self): + """Test case to validate custom property + """ + + class TestProperty(object): + + def __init__(self): + self._get = 0 + self._set = 0 + self._del = 0 + + def name(self): + self._get += 1 + return self.__name + name = property(name) + + def set_name(self, value): + self._set += 1 + self.__name = value + name.setter(set_name) + + def del_name(self): + self._del += 1 + del self.__name + name.deleter(del_name) + + testObj = TestProperty() + self._check(testObj) + + + def test_property3(self): + """Test case to validate custom property + """ + + class TestProperty(object): + + def __init__(self): + self._name = 'foo' + + def name(self): + return self._name + name = property(name) + + testObj = TestProperty() + self.assertRaises(AttributeError, setattr, testObj, 'name', 'bar') + self.assertRaises(AttributeError, delattr, testObj, 'name') + + + def _check(self, testObj): + testObj.name = "Custom" + self.assertEqual(1, testObj._set) + + self.assertEqual(testObj.name, "Custom") + self.assertEqual(1, testObj._get) + + self.assertTrue(hasattr(testObj, 'name')) + del testObj.name + self.assertEqual(1, testObj._del) + + self.assertTrue(not hasattr(testObj, 'name')) + testObj.name = "Custom2" + self.assertEqual(testObj.name, "Custom2") + diff --git a/tests_runfiles/test_pydevdio.py b/tests_runfiles/test_pydevdio.py new file mode 100644 index 0000000..3d0b007 --- /dev/null +++ b/tests_runfiles/test_pydevdio.py @@ -0,0 +1,36 @@ +import sys +import os + + +import unittest + +class Test(unittest.TestCase): + + def test_it(self): + #make it as if we were executing from the directory above this one (so that we can use jycompletionserver + #without the need for it being in the pythonpath) + #(twice the dirname to get the previous level from this file.) + import test_pydevdio #@UnresolvedImport - importing itself + ADD_TO_PYTHONPATH = os.path.join(os.path.dirname(os.path.dirname(test_pydevdio.__file__))) + sys.path.insert(0, ADD_TO_PYTHONPATH) + + try: + from _pydevd_bundle import pydevd_io + original = sys.stdout + + try: + sys.stdout = pydevd_io.IOBuf() + print('foo') + print('bar') + + self.assertEqual('foo\nbar\n', sys.stdout.getvalue()) #@UndefinedVariable + + print('ww') + print('xx') + self.assertEqual('ww\nxx\n', sys.stdout.getvalue()) #@UndefinedVariable + finally: + sys.stdout = original + finally: + #remove it to leave it ok for other tests + sys.path.remove(ADD_TO_PYTHONPATH) + diff --git a/tests_runfiles/test_runfiles.py b/tests_runfiles/test_runfiles.py new file mode 100644 index 0000000..d20b002 --- /dev/null +++ b/tests_runfiles/test_runfiles.py @@ -0,0 +1,437 @@ +import os.path +import sys + +IS_JYTHON = sys.platform.find('java') != -1 + +try: + this_file_name = __file__ +except NameError: + # stupid jython. plain old __file__ isnt working for some reason + import test_runfiles # @UnresolvedImport - importing the module itself + this_file_name = test_runfiles.__file__ + +desired_runfiles_path = os.path.normpath(os.path.dirname(this_file_name) + "/..") +sys.path.insert(0, desired_runfiles_path) + +from _pydev_runfiles import pydev_runfiles_unittest +from _pydev_runfiles import pydev_runfiles_xml_rpc +from _pydevd_bundle import pydevd_io + +# remove existing pydev_runfiles from modules (if any), so that we can be sure we have the correct version +if 'pydev_runfiles' in sys.modules: + del sys.modules['pydev_runfiles'] +if '_pydev_runfiles.pydev_runfiles' in sys.modules: + del sys.modules['_pydev_runfiles.pydev_runfiles'] + +from _pydev_runfiles import pydev_runfiles +import unittest +import tempfile +import re + +try: + set +except: + from sets import Set as set + +# this is an early test because it requires the sys.path changed +orig_syspath = sys.path +a_file = pydev_runfiles.__file__ +pydev_runfiles.PydevTestRunner(pydev_runfiles.Configuration(files_or_dirs=[a_file])) +file_dir = os.path.dirname(os.path.dirname(a_file)) +assert file_dir in sys.path +sys.path = orig_syspath[:] + +# remove it so that we leave it ok for other tests +sys.path.remove(desired_runfiles_path) + + +class RunfilesTest(unittest.TestCase): + + def _setup_scenario( + self, + path, + include_tests=None, + tests=None, + files_to_tests=None, + exclude_files=None, + exclude_tests=None, + include_files=None, + ): + self.MyTestRunner = pydev_runfiles.PydevTestRunner( + pydev_runfiles.Configuration( + files_or_dirs=path, + include_tests=include_tests, + verbosity=1, + tests=tests, + files_to_tests=files_to_tests, + exclude_files=exclude_files, + exclude_tests=exclude_tests, + include_files=include_files, + ) + ) + self.files = self.MyTestRunner.find_import_files() + self.modules = self.MyTestRunner.find_modules_from_files(self.files) + self.all_tests = self.MyTestRunner.find_tests_from_modules(self.modules) + self.filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + + def setUp(self): + self.file_dir = [os.path.abspath(os.path.join(desired_runfiles_path, 'tests_runfiles/samples'))] + self._setup_scenario(self.file_dir, None) + + def test_suite_used(self): + for suite in self.all_tests + self.filtered_tests: + self.assertTrue(isinstance(suite, pydev_runfiles_unittest.PydevTestSuite)) + + def test_parse_cmdline(self): + sys.argv = "pydev_runfiles.py ./".split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual([sys.argv[1]], configuration.files_or_dirs) + self.assertEqual(2, configuration.verbosity) # default value + self.assertEqual(None, configuration.include_tests) # default value + + sys.argv = "pydev_runfiles.py ../images c:/temp".split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual(sys.argv[1:3], configuration.files_or_dirs) + self.assertEqual(2, configuration.verbosity) + + sys.argv = "pydev_runfiles.py --verbosity 3 ../junk c:/asdf ".split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual(sys.argv[3:], configuration.files_or_dirs) + self.assertEqual(int(sys.argv[2]), configuration.verbosity) + + sys.argv = "pydev_runfiles.py --include_tests test_def ./".split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual([sys.argv[-1]], configuration.files_or_dirs) + self.assertEqual([sys.argv[2]], configuration.include_tests) + + sys.argv = "pydev_runfiles.py --include_tests Abc.test_def,Mod.test_abc c:/junk/".split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual([sys.argv[-1]], configuration.files_or_dirs) + self.assertEqual(sys.argv[2].split(','), configuration.include_tests) + + sys.argv = ('C:\\eclipse-SDK-3.2-win32\\eclipse\\plugins\\org.python.pydev.debug_1.2.2\\pysrc\\pydev_runfiles.py ' + + '--verbosity 1 ' + + 'C:\\workspace_eclipse\\fronttpa\\tests\\gui_tests\\calendar_popup_control_test.py ').split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual([sys.argv[-1]], configuration.files_or_dirs) + self.assertEqual(1, configuration.verbosity) + + sys.argv = "pydev_runfiles.py --verbosity 1 --include_tests Mod.test_abc c:/junk/ ./".split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual(sys.argv[5:], configuration.files_or_dirs) + self.assertEqual(int(sys.argv[2]), configuration.verbosity) + self.assertEqual([sys.argv[4]], configuration.include_tests) + + sys.argv = "pydev_runfiles.py --exclude_files=*.txt,a*.py".split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual(['*.txt', 'a*.py'], configuration.exclude_files) + + sys.argv = "pydev_runfiles.py --exclude_tests=*__todo,test*bar".split() + configuration = pydev_runfiles.parse_cmdline() + self.assertEqual(['*__todo', 'test*bar'], configuration.exclude_tests) + + def test___adjust_python_path_works_for_directories(self): + orig_syspath = sys.path + tempdir = tempfile.gettempdir() + pydev_runfiles.PydevTestRunner(pydev_runfiles.Configuration(files_or_dirs=[tempdir])) + self.assertEqual(1, tempdir in sys.path) + sys.path = orig_syspath[:] + + def test___is_valid_py_file(self): + isvalid = self.MyTestRunner._PydevTestRunner__is_valid_py_file + self.assertEqual(1, isvalid("test.py")) + self.assertEqual(0, isvalid("asdf.pyc")) + self.assertEqual(0, isvalid("__init__.py")) + self.assertEqual(0, isvalid("__init__.pyc")) + self.assertEqual(1, isvalid("asdf asdf.pyw")) + + def test___unixify(self): + unixify = self.MyTestRunner._PydevTestRunner__unixify + self.assertEqual("c:/temp/junk/asdf.py", unixify("c:SEPtempSEPjunkSEPasdf.py".replace('SEP', os.sep))) + + def test___importify(self): + importify = self.MyTestRunner._PydevTestRunner__importify + self.assertEqual("temp.junk.asdf", importify("temp/junk/asdf.py")) + self.assertEqual("asdf", importify("asdf.py")) + self.assertEqual("abc.def.hgi", importify("abc/def/hgi")) + + def test_finding_a_file_from_file_system(self): + test_file = "simple_test.py" + self.MyTestRunner.files_or_dirs = [self.file_dir[0] + test_file] + files = self.MyTestRunner.find_import_files() + self.assertEqual(1, len(files)) + self.assertEqual(files[0], self.file_dir[0] + test_file) + + def test_finding_files_in_dir_from_file_system(self): + self.assertEqual(1, len(self.files) > 0) + for import_file in self.files: + self.assertEqual(-1, import_file.find(".pyc")) + self.assertEqual(-1, import_file.find("__init__.py")) + self.assertEqual(-1, import_file.find("\\")) + self.assertEqual(-1, import_file.find(".txt")) + + def test___get_module_from_str(self): + my_importer = self.MyTestRunner._PydevTestRunner__get_module_from_str + my_os_path = my_importer("os.path", True, 'unused') + from os import path + import os.path as path2 + self.assertEqual(path, my_os_path) + self.assertEqual(path2, my_os_path) + self.assertNotEqual(__import__("os.path"), my_os_path) + self.assertNotEqual(__import__("os"), my_os_path) + + def test_finding_modules_from_import_strings(self): + self.assertEqual(1, len(self.modules) > 0) + + def test_finding_tests_when_no_filter(self): + # unittest.py will create a TestCase with 0 tests in it + # since it just imports what is given + self.assertEqual(1, len(self.all_tests) > 0) + files_with_tests = [1 for t in self.all_tests if len(t._tests) > 0] + self.assertNotEqual(len(self.files), len(files_with_tests)) + + def count_suite(self, tests=None): + total = 0 + for t in tests: + total += t.countTestCases() + return total + + def test_runfile_imports(self): + from _pydev_runfiles import pydev_runfiles_coverage + from _pydev_runfiles import pydev_runfiles_parallel_client + from _pydev_runfiles import pydev_runfiles_parallel + import pytest + from _pydev_runfiles import pydev_runfiles_pytest2 + from _pydev_runfiles import pydev_runfiles_unittest + from _pydev_runfiles import pydev_runfiles_xml_rpc + from _pydev_runfiles import pydev_runfiles + + def test___match(self): + matcher = self.MyTestRunner._PydevTestRunner__match + self.assertEqual(1, matcher(None, "aname")) + self.assertEqual(1, matcher([".*"], "aname")) + self.assertEqual(0, matcher(["^x$"], "aname")) + self.assertEqual(0, matcher(["abc"], "aname")) + self.assertEqual(1, matcher(["abc", "123"], "123")) + + def test_finding_tests_from_modules_with_bad_filter_returns_0_tests(self): + self._setup_scenario(self.file_dir, ["NO_TESTS_ARE_SURE_TO_HAVE_THIS_NAME"]) + self.assertEqual(0, self.count_suite(self.all_tests)) + + def test_finding_test_with_unique_name_returns_1_test(self): + self._setup_scenario(self.file_dir, include_tests=["test_i_am_a_unique_test_name"]) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(1, self.count_suite(filtered_tests)) + + def test_finding_test_with_non_unique_name(self): + self._setup_scenario(self.file_dir, include_tests=["test_non_unique_name"]) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(1, self.count_suite(filtered_tests) > 2) + + def test_finding_tests_with_regex_filters(self): + self._setup_scenario(self.file_dir, include_tests=["test_non*"]) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(1, self.count_suite(filtered_tests) > 2) + + self._setup_scenario(self.file_dir, ["^$"]) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(0, self.count_suite(filtered_tests)) + + self._setup_scenario(self.file_dir, None, exclude_tests=["*"]) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(0, self.count_suite(filtered_tests)) + + def test_matching_tests(self): + self._setup_scenario(self.file_dir, None, ['StillYetAnotherSampleTest']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(1, self.count_suite(filtered_tests)) + + self._setup_scenario(self.file_dir, None, ['SampleTest.test_xxxxxx1']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(1, self.count_suite(filtered_tests)) + + self._setup_scenario(self.file_dir, None, ['SampleTest']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(8, self.count_suite(filtered_tests)) + + self._setup_scenario(self.file_dir, None, ['AnotherSampleTest.todo_not_tested']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(1, self.count_suite(filtered_tests)) + + self._setup_scenario(self.file_dir, None, ['StillYetAnotherSampleTest', 'SampleTest.test_xxxxxx1']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(2, self.count_suite(filtered_tests)) + + self._setup_scenario(self.file_dir, None, exclude_tests=['*']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(self.count_suite(filtered_tests), 0) + + self._setup_scenario(self.file_dir, None, exclude_tests=['*a*']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(self.count_suite(filtered_tests), 6) + + self.assertEqual( + set(self.MyTestRunner.list_test_names(filtered_tests)), + set(['test_1', 'test_2', 'test_xxxxxx1', 'test_xxxxxx2', 'test_xxxxxx3', 'test_xxxxxx4']) + ) + + self._setup_scenario(self.file_dir, None, exclude_tests=['*a*', '*x*']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + self.assertEqual(self.count_suite(filtered_tests), 2) + + self.assertEqual( + set(self.MyTestRunner.list_test_names(filtered_tests)), + set(['test_1', 'test_2']) + ) + + self._setup_scenario(self.file_dir, None, exclude_files=['simple_test.py']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + names = self.MyTestRunner.list_test_names(filtered_tests) + self.assertTrue('test_xxxxxx1' not in names, 'Found: %s' % (names,)) + + self.assertEqual( + set(['test_abc', 'test_non_unique_name', 'test_non_unique_name', 'test_asdf2', 'test_i_am_a_unique_test_name', 'test_non_unique_name', 'test_blank']), + set(names) + ) + + self._setup_scenario(self.file_dir, None, include_files=['simple3_test.py']) + filtered_tests = self.MyTestRunner.filter_tests(self.all_tests) + names = self.MyTestRunner.list_test_names(filtered_tests) + self.assertTrue('test_xxxxxx1' not in names, 'Found: %s' % (names,)) + + self.assertEqual( + set(['test_non_unique_name']), + set(names) + ) + + def test_xml_rpc_communication(self): + import sys + sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'samples')) + notifications = [] + + class Server: + + def __init__(self, notifications): + self.notifications = notifications + + def notifyConnected(self): + # This method is called at the very start (in runfiles.py), and we do not check this here + raise AssertionError('Should not be called from the run tests.') + + def notifyTestsCollected(self, number_of_tests): + self.notifications.append(('notifyTestsCollected', number_of_tests)) + + def notifyStartTest(self, file, test): + pass + + def notifyTest(self, cond, captured_output, error_contents, file, test, time): + try: + # I.e.: when marked as Binary in xml-rpc + captured_output = captured_output.data + except: + pass + try: + # I.e.: when marked as Binary in xml-rpc + error_contents = error_contents.data + except: + pass + if error_contents: + error_contents = error_contents.splitlines()[-1].strip() + self.notifications.append(('notifyTest', cond, captured_output.strip(), error_contents, file, test)) + + def notifyTestRunFinished(self, total_time): + self.notifications.append(('notifyTestRunFinished',)) + + server = Server(notifications) + pydev_runfiles_xml_rpc.set_server(server) + simple_test = os.path.join(self.file_dir[0], 'simple_test.py') + simple_test2 = os.path.join(self.file_dir[0], 'simple2_test.py') + simpleClass_test = os.path.join(self.file_dir[0], 'simpleClass_test.py') + simpleModule_test = os.path.join(self.file_dir[0], 'simpleModule_test.py') + + files_to_tests = {} + files_to_tests.setdefault(simple_test , []).append('SampleTest.test_xxxxxx1') + files_to_tests.setdefault(simple_test , []).append('SampleTest.test_xxxxxx2') + files_to_tests.setdefault(simple_test , []).append('SampleTest.test_non_unique_name') + files_to_tests.setdefault(simple_test2, []).append('YetAnotherSampleTest.test_abc') + files_to_tests.setdefault(simpleClass_test, []).append('SetUpClassTest.test_blank') + files_to_tests.setdefault(simpleModule_test, []).append('SetUpModuleTest.test_blank') + + self._setup_scenario(None, files_to_tests=files_to_tests) + self.MyTestRunner.verbosity = 2 + + buf = pydevd_io.start_redirect(keep_original_redirection=False) + try: + self.MyTestRunner.run_tests() + self.assertEqual(8, len(notifications)) + if sys.version_info[:2] <= (2, 6): + # The setUpClass is not supported in Python 2.6 (thus we have no collection error). + expected = [ + ('notifyTest', 'fail', '', 'AssertionError: Fail test 2', simple_test, 'SampleTest.test_xxxxxx1'), + ('notifyTest', 'ok', '', '', simple_test2, 'YetAnotherSampleTest.test_abc'), + ('notifyTest', 'ok', '', '', simpleClass_test, 'SetUpClassTest.test_blank'), + ('notifyTest', 'ok', '', '', simpleModule_test, 'SetUpModuleTest.test_blank'), + ('notifyTest', 'ok', '', '', simple_test, 'SampleTest.test_xxxxxx2'), + ('notifyTest', 'ok', 'non unique name ran', '', simple_test, 'SampleTest.test_non_unique_name'), + ('notifyTestRunFinished',), + ('notifyTestsCollected', 6) + ] + else: + expected = [ + ('notifyTestsCollected', 6), + ('notifyTest', 'ok', 'non unique name ran', '', simple_test, 'SampleTest.test_non_unique_name'), + ('notifyTest', 'fail', '', 'AssertionError: Fail test 2', simple_test, 'SampleTest.test_xxxxxx1'), + ('notifyTest', 'ok', '', '', simple_test, 'SampleTest.test_xxxxxx2'), + ('notifyTest', 'ok', '', '', simple_test2, 'YetAnotherSampleTest.test_abc'), + ] + + if not IS_JYTHON: + if 'samples.simpleClass_test' in str(notifications): + expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpClass.', + simpleClass_test.replace('/', os.path.sep), 'samples.simpleClass_test.SetUpClassTest ')) + expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpModule.', + simpleModule_test.replace('/', os.path.sep), 'samples.simpleModule_test ')) + else: + expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpClass.', + simpleClass_test.replace('/', os.path.sep), 'simpleClass_test.SetUpClassTest ')) + expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpModule.', + simpleModule_test.replace('/', os.path.sep), 'simpleModule_test ')) + else: + expected.append(('notifyTest', 'ok', '', '', simpleClass_test, 'SetUpClassTest.test_blank')) + expected.append(('notifyTest', 'ok', '', '', simpleModule_test, 'SetUpModuleTest.test_blank')) + + expected.append(('notifyTestRunFinished',)) + + expected.sort() + new_notifications = [] + for notification in expected: + try: + if len(notification) == 6: + # Some are binary on Py3. + new_notifications.append(( + notification[0], + notification[1], + notification[2].encode('latin1'), + notification[3].encode('latin1'), + notification[4], + notification[5], + )) + else: + new_notifications.append(notification) + except: + raise + expected = new_notifications + + notifications.sort() + if not IS_JYTHON: + self.assertEqual( + expected, + notifications + ) + finally: + pydevd_io.end_redirect() + b = buf.getvalue() + if sys.version_info[:2] > (2, 6): + self.assertTrue(b.find('Ran 4 tests in ') != -1, 'Found: ' + b) + else: + self.assertTrue(b.find('Ran 6 tests in ') != -1, 'Found: ' + b) -- 2.30.2