From 3207466fc306e22f69abc1e94200b6ecaa524cec Mon Sep 17 00:00:00 2001 From: Fabio Zadrozny Date: Fri, 6 Aug 2021 07:18:09 -0300 Subject: [PATCH] Python 3.10 support (work in progress). Updated bytecode library (and other minors). --- cgmanifest.json | 2 +- .../pydevd/_pydev_bundle/pydev_monkey.py | 2 +- .../pydev_runfiles_parallel.py | 4 +- .../_pydevd_bundle/pydevd_bytecode_utils.py | 5 + .../pydevd/_pydevd_bundle/pydevd_constants.py | 2 + .../pydevd/_pydevd_bundle/pydevd_reload.py | 2 +- .../pydevd/_pydevd_bundle/pydevd_vars.py | 2 +- .../_pydevd_frame_eval/vendored/README.txt | 4 +- .../vendored/bytecode-0.12.0.dist-info/RECORD | 41 -- .../COPYING | 0 .../INSTALLER | 0 .../METADATA | 14 +- .../bytecode-0.13.0.dev0.dist-info/RECORD | 42 +++ .../REQUESTED | 0 .../WHEEL | 0 .../direct_url.json | 1 + .../top_level.txt | 0 .../vendored/bytecode/__init__.py | 2 +- .../vendored/bytecode/bytecode.py | 6 +- .../vendored/bytecode/cfg.py | 17 +- .../vendored/bytecode/concrete.py | 182 +++++---- .../vendored/bytecode/flags.py | 16 +- .../vendored/bytecode/instr.py | 16 +- .../vendored/bytecode/tests/__init__.py | 2 - .../vendored/bytecode/tests/sanitytest.py | 36 -- .../vendored/bytecode/tests/test_bytecode.py | 51 ++- .../vendored/bytecode/tests/test_cfg.py | 17 +- .../vendored/bytecode/tests/test_code.py | 20 + .../vendored/bytecode/tests/test_concrete.py | 353 ++++++++++-------- .../vendored/bytecode/tests/test_misc.py | 90 ++--- .../bytecode/tests/util_annotation.py | 17 + src/debugpy/_vendored/pydevd/conftest.py | 2 +- .../_vendored/pydevd/pydev_run_in_console.py | 2 +- src/debugpy/_vendored/pydevd/runfiles.py | 2 +- .../pydevd/tests/test_check_pydevconsole.py | 4 +- .../pydevd/tests/test_pydev_ipython_011.py | 2 +- .../pydevd/tests/test_pydevconsole.py | 6 +- .../pydevd/tests_python/debugger_unittest.py | 6 +- .../_debugger_case_adjust_breakpoint.py | 7 +- .../resources/_debugger_case_check_tracer.py | 2 +- .../_debugger_case_stop_async_iteration.py | 2 +- .../_debugger_case_unhandled_exceptions.py | 2 +- ...bugger_case_unhandled_exceptions_custom.py | 2 +- .../test_smart_step_into_bytecode.py | 28 +- 44 files changed, 559 insertions(+), 454 deletions(-) delete mode 100644 src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/RECORD rename src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/{bytecode-0.12.0.dist-info => bytecode-0.13.0.dev0.dist-info}/COPYING (100%) rename src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/{bytecode-0.12.0.dist-info => bytecode-0.13.0.dev0.dist-info}/INSTALLER (100%) rename src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/{bytecode-0.12.0.dist-info => bytecode-0.13.0.dev0.dist-info}/METADATA (85%) create mode 100644 src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/RECORD rename src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/{bytecode-0.12.0.dist-info => bytecode-0.13.0.dev0.dist-info}/REQUESTED (100%) rename src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/{bytecode-0.12.0.dist-info => bytecode-0.13.0.dev0.dist-info}/WHEEL (100%) create mode 100644 src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/direct_url.json rename src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/{bytecode-0.12.0.dist-info => bytecode-0.13.0.dev0.dist-info}/top_level.txt (100%) delete mode 100644 src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/sanitytest.py create mode 100644 src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/util_annotation.py diff --git a/cgmanifest.json b/cgmanifest.json index e305b20e..e3cca295 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -45,7 +45,7 @@ "git": { "Name": "bytecode", "RepositoryUrl": "https://github.com/MatthieuDartiailh/bytecode", - "CommitHash": "826344ec533643fad068754e0b9799bfeac46634" + "CommitHash": "ccb8a7b4bf12a85ff53c3c42517d2633c5225829" }, "DevelopmentDependency": false } diff --git a/src/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py b/src/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py index 0449ca8d..369051e7 100644 --- a/src/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py +++ b/src/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py @@ -1032,7 +1032,7 @@ class _NewThreadStartupWithTrace: # 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 - # current_thread() unless we're sure it's a dummy thread. + # 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 diff --git a/src/debugpy/_vendored/pydevd/_pydev_runfiles/pydev_runfiles_parallel.py b/src/debugpy/_vendored/pydevd/_pydev_runfiles/pydev_runfiles_parallel.py index 34009cae..15d188e3 100644 --- a/src/debugpy/_vendored/pydevd/_pydev_runfiles/pydev_runfiles_parallel.py +++ b/src/debugpy/_vendored/pydevd/_pydev_runfiles/pydev_runfiles_parallel.py @@ -155,7 +155,7 @@ class CommunicationThread(threading.Thread): def __init__(self, tests_queue): threading.Thread.__init__(self) - self.setDaemon(True) + self.daemon = True self.queue = tests_queue self.finished = False from _pydev_bundle.pydev_imports import SimpleXMLRPCServer @@ -243,7 +243,7 @@ class ClientThread(threading.Thread): def __init__(self, job_id, port, verbosity, coverage_output_file=None, coverage_include=None): threading.Thread.__init__(self) - self.setDaemon(True) + self.daemon = True self.port = port self.job_id = job_id self.verbosity = verbosity diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_bytecode_utils.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_bytecode_utils.py index e90d7c62..8f2f5dad 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_bytecode_utils.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_bytecode_utils.py @@ -194,6 +194,11 @@ class _StackInterpreter(object): 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) diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_constants.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_constants.py index 9421430b..85ea223c 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_constants.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_constants.py @@ -184,6 +184,7 @@ IS_PY36_OR_GREATER = False IS_PY37_OR_GREATER = False IS_PY38_OR_GREATER = False IS_PY39_OR_GREATER = False +IS_PY310_OR_GREATER = False IS_PY2 = True IS_PY27 = False IS_PY24 = False @@ -197,6 +198,7 @@ try: 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) elif sys.version_info[0] == 2 and sys.version_info[1] == 7: IS_PY27 = True elif sys.version_info[0] == 2 and sys.version_info[1] == 4: diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_reload.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_reload.py index b279eda2..c2c61bf0 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_reload.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_reload.py @@ -148,7 +148,7 @@ def notify_error(*args): #======================================================================================================================= def code_objects_equal(code0, code1): for d in dir(code0): - if d.startswith('_') or 'lineno' in d or d == 'replace': + if d.startswith('_') or 'line' in d or d == 'replace': continue if getattr(code0, d) != getattr(code1, d): return False diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_vars.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_vars.py index b3339761..d436386a 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_vars.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_vars.py @@ -65,7 +65,7 @@ def getVariable(dbg, thread_id, frame_id, scope, attrs): 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(current_thread()): + if thread_id != get_current_thread_id(threading.current_thread()): raise VariableError("getVariable: must execute on same thread") try: diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/README.txt b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/README.txt index 0c9de17c..d15aa209 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/README.txt +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/README.txt @@ -8,9 +8,11 @@ pip install bytecode --target . or from master (if needed for some early bugfix): -python -m pip install https://github.com/vstinner/bytecode/archive/master.zip --target . +python -m pip install https://github.com/MatthieuDartiailh/bytecode/archive/main.zip --target . Then run 'pydevd_fix_code.py' to fix the imports on the vendored file, run its tests (to see if things are still ok) and commit. +Then, to finish, apply the patch to add the offset to the instructions (bcb8a28669e9178f96f5d71af7259e0674acc47c) + Note: commit the egg-info as a note of the license (force if needed). \ No newline at end of file diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/RECORD b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/RECORD deleted file mode 100644 index 8b53879f..00000000 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/RECORD +++ /dev/null @@ -1,41 +0,0 @@ -bytecode-0.12.0.dist-info/COPYING,sha256=nPUTV23AcD5UZcc9EtVTBt-Igoyj7IIRw97xuOGVgq8,1095 -bytecode-0.12.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -bytecode-0.12.0.dist-info/METADATA,sha256=asu9c0mCLVYLxmfElINQCm0lAMBdVcgZqMIoCI1Zfnk,2589 -bytecode-0.12.0.dist-info/RECORD,, -bytecode-0.12.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -bytecode-0.12.0.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92 -bytecode-0.12.0.dist-info/top_level.txt,sha256=9BhdB7HqYZ-PvHNoWX6ilwLYWQqcgEOLwdb3aXm5Gys,9 -bytecode/__init__.py,sha256=8krUbp5Kcxe_oC3S5OXwB-VXoMP_V-13FV0eLLFPPs4,4011 -bytecode/__pycache__/__init__.cpython-38.pyc,, -bytecode/__pycache__/bytecode.cpython-38.pyc,, -bytecode/__pycache__/cfg.cpython-38.pyc,, -bytecode/__pycache__/concrete.cpython-38.pyc,, -bytecode/__pycache__/flags.cpython-38.pyc,, -bytecode/__pycache__/instr.cpython-38.pyc,, -bytecode/__pycache__/peephole_opt.cpython-38.pyc,, -bytecode/bytecode.py,sha256=8eZ6vZTfCFEB0lwupJZsZds5u6Is7wlX6IlR8olG7QQ,6897 -bytecode/cfg.py,sha256=NGBJ5lZuCQuAHvyWiyUHPXGBA_8ze3CzyXvJxmcYTWk,15239 -bytecode/concrete.py,sha256=0Ojd-mED2COoB_fzEHL6OcW7zqtb76k6lEbkvJPNCQY,21281 -bytecode/flags.py,sha256=opG0Yh8oQ0EUPIAA5S3TIHHaojYO_sV3RHc3WSFlopg,5956 -bytecode/instr.py,sha256=Zavx4BNwJfWLNZUIGXukGPInxTsflyZeZ6cAcqq1ggk,11832 -bytecode/peephole_opt.py,sha256=_XI45yErqZ4pGEUqRQVcMl5vS2IY4dqcrCGmHIHJdow,16203 -bytecode/tests/__init__.py,sha256=tpG_2bYVAAFqVQz2ZbkZ-XQAX8k8rQjBbAUVhZqMLkA,5163 -bytecode/tests/__pycache__/__init__.cpython-38.pyc,, -bytecode/tests/__pycache__/sanitytest.cpython-38.pyc,, -bytecode/tests/__pycache__/test_bytecode.cpython-38.pyc,, -bytecode/tests/__pycache__/test_cfg.cpython-38.pyc,, -bytecode/tests/__pycache__/test_code.cpython-38.pyc,, -bytecode/tests/__pycache__/test_concrete.cpython-38.pyc,, -bytecode/tests/__pycache__/test_flags.cpython-38.pyc,, -bytecode/tests/__pycache__/test_instr.cpython-38.pyc,, -bytecode/tests/__pycache__/test_misc.cpython-38.pyc,, -bytecode/tests/__pycache__/test_peephole_opt.cpython-38.pyc,, -bytecode/tests/sanitytest.py,sha256=-UiwWgJe9y6LC2Bim0ZdV6aKN47b3uJ_RWELbfzO_0g,711 -bytecode/tests/test_bytecode.py,sha256=3dH08nPMs_T6sZXHybS0beA8pTvBeyUqLIS5WaVx1VQ,15150 -bytecode/tests/test_cfg.py,sha256=h-Z7tZsWDqdW0BEzQBYmnKKlw2LqeeiKGpiUwPc4ADI,29056 -bytecode/tests/test_code.py,sha256=8wqx8uli3_UXewDeh6wt52oDZcRp3L7SXYoGkmIP1Zg,1697 -bytecode/tests/test_concrete.py,sha256=uamFKnciMljHHIL7U691KQemFE0EazvhSOV1ErcgUF4,49375 -bytecode/tests/test_flags.py,sha256=ve1FXkaXO9mBly4EO0vTySeWZC4x17yyBMdfvHNtWqc,5838 -bytecode/tests/test_instr.py,sha256=ucFNTYxuHN1S2-lIuIVl9QV0zL4DDnUGmcbz5Je2ONo,11652 -bytecode/tests/test_misc.py,sha256=l5WOEITwedUz_PbZu3Z1E5qk4lSDpEAeIRNGKHONTJE,7704 -bytecode/tests/test_peephole_opt.py,sha256=kPEUtsgpCkM889c1zV0GcaB1Iy3F75ypJMQYBpHQZdI,33620 diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/COPYING b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/COPYING similarity index 100% rename from src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/COPYING rename to src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/COPYING diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/INSTALLER b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/INSTALLER similarity index 100% rename from src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/INSTALLER rename to src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/INSTALLER diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/METADATA b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/METADATA similarity index 85% rename from src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/METADATA rename to src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/METADATA index 78142539..e1d5e012 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/METADATA +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: bytecode -Version: 0.12.0 +Version: 0.13.0.dev0 Summary: Python module to generate and modify bytecode Home-page: https://github.com/MatthieuDartiailh/bytecode Author: Victor Stinner @@ -15,8 +15,12 @@ Classifier: License :: OSI Approved :: MIT License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Dist: aenum (>=2.0) ; python_version < "3.6" +Requires-Python: >=3.6 ******** bytecode @@ -51,8 +55,10 @@ bytecode * `Download latest bytecode release at the Python Cheeseshop (PyPI) `_ -Install bytecode: ``python3 -m pip install bytecode``. It requires Python 3.5 -or newer. +Install bytecode: ``python3 -m pip install bytecode``. It requires Python 3.6 +or newer. The latest release that supports Python 3.5 is 0.12.0. For Python 2.7 +support, have a look at `dead-bytecode +`_ instead. Example executing ``print('Hello World!')``: diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/RECORD b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/RECORD new file mode 100644 index 00000000..3890ece1 --- /dev/null +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/RECORD @@ -0,0 +1,42 @@ +bytecode-0.13.0.dev0.dist-info/COPYING,sha256=baWkm-Te2LLURwK7TL0zOkMSVjVCU_ezvObHBo298Tk,1074 +bytecode-0.13.0.dev0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +bytecode-0.13.0.dev0.dist-info/METADATA,sha256=9XadDK6YTQ-FPowYI5DS4ieA7hRGnRP_fM5Z9ioPkEQ,2929 +bytecode-0.13.0.dev0.dist-info/RECORD,, +bytecode-0.13.0.dev0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +bytecode-0.13.0.dev0.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92 +bytecode-0.13.0.dev0.dist-info/direct_url.json,sha256=s58Rb4KXRlMKxk-mzpvr_tJRQ-Hx8-DHsU6NdohCnAg,93 +bytecode-0.13.0.dev0.dist-info/top_level.txt,sha256=9BhdB7HqYZ-PvHNoWX6ilwLYWQqcgEOLwdb3aXm5Gys,9 +bytecode/__init__.py,sha256=d-yk4Xh4SwOWq9NgoD2rmBLG6RhUFNljeqs-NjMNSYM,3885 +bytecode/__pycache__/__init__.cpython-38.pyc,, +bytecode/__pycache__/bytecode.cpython-38.pyc,, +bytecode/__pycache__/cfg.cpython-38.pyc,, +bytecode/__pycache__/concrete.cpython-38.pyc,, +bytecode/__pycache__/flags.cpython-38.pyc,, +bytecode/__pycache__/instr.cpython-38.pyc,, +bytecode/__pycache__/peephole_opt.cpython-38.pyc,, +bytecode/bytecode.py,sha256=IMCcatHMtQ7M31nwj4r3drcvQuGVJAOP0d7C0O8P_SE,6894 +bytecode/cfg.py,sha256=RmJGJqwCxR-XYaPH9YGY4wNDycdtLvIBJb1OGSmxcN0,15274 +bytecode/concrete.py,sha256=0eb6Yh_NDLmzJNcMs2TFom0EqFVSM1cO3inMH90YE-s,21683 +bytecode/flags.py,sha256=hAvM_B2yQKRw44leHP0oCae0aaJraAbDDTpqIf4I1CM,5987 +bytecode/instr.py,sha256=HYc65LjNSOB3GCWkNkCSkee1rRzUyr89rgdjbKBaTpE,11616 +bytecode/peephole_opt.py,sha256=W-cFVPOZN-JKfDV3aImsYenDSZkSNBDTVQqeMrGPU18,15712 +bytecode/tests/__init__.py,sha256=BAdOXXNRdMVX4D8TuRYPlG9PHU7Cb0bzvyfA9s435kM,4968 +bytecode/tests/__pycache__/__init__.cpython-38.pyc,, +bytecode/tests/__pycache__/test_bytecode.cpython-38.pyc,, +bytecode/tests/__pycache__/test_cfg.cpython-38.pyc,, +bytecode/tests/__pycache__/test_code.cpython-38.pyc,, +bytecode/tests/__pycache__/test_concrete.cpython-38.pyc,, +bytecode/tests/__pycache__/test_flags.cpython-38.pyc,, +bytecode/tests/__pycache__/test_instr.cpython-38.pyc,, +bytecode/tests/__pycache__/test_misc.cpython-38.pyc,, +bytecode/tests/__pycache__/test_peephole_opt.cpython-38.pyc,, +bytecode/tests/__pycache__/util_annotation.cpython-38.pyc,, +bytecode/tests/test_bytecode.py,sha256=buvtlDC0NwoQ3zuZ7OENIIDngSqtiO9WkAa2-UvxGkI,15584 +bytecode/tests/test_cfg.py,sha256=c0xT8OfV-mDHu-DIDWr6LVlZQyK4GfgLSmT5AsodbMk,28194 +bytecode/tests/test_code.py,sha256=XCOH29rOXSoQz130s-AIC62r23e9qNjk8Y2xDB2LmSc,2100 +bytecode/tests/test_concrete.py,sha256=qT2qvabkF0yC7inniNx53cMSDN-2Qi0IE3pwBZSzF8g,49253 +bytecode/tests/test_flags.py,sha256=DY9U3c6tJdxJFm0jEm_To1Cc0I99EidQv_0guud-4oE,5684 +bytecode/tests/test_instr.py,sha256=rYeF8u-L0aW8bLPBxTUSy_T7KP6SaXyJKv9OhC8k6aA,11295 +bytecode/tests/test_misc.py,sha256=wyK1wpVPHRfaXgo-EqUI-F1nyB9-UACerHsHbExAo1U,6758 +bytecode/tests/test_peephole_opt.py,sha256=niUfhgEbiFR7IAmdQ_N9Qgh7D3wdRQ_zS0V8mKC4EzI,32640 +bytecode/tests/util_annotation.py,sha256=wKq6yPWrzkNlholl5Y10b3VjuCkoiYVgvcIjk_8jzf8,485 diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/REQUESTED b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/REQUESTED similarity index 100% rename from src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/REQUESTED rename to src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/REQUESTED diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/WHEEL b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/WHEEL similarity index 100% rename from src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/WHEEL rename to src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/WHEEL diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/direct_url.json b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/direct_url.json new file mode 100644 index 00000000..3c32b571 --- /dev/null +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/direct_url.json @@ -0,0 +1 @@ +{"archive_info": {}, "url": "https://github.com/MatthieuDartiailh/bytecode/archive/main.zip"} \ No newline at end of file diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/top_level.txt b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/top_level.txt similarity index 100% rename from src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.12.0.dist-info/top_level.txt rename to src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode-0.13.0.dev0.dist-info/top_level.txt diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__init__.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__init__.py index 559903ea..9a5b91aa 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__init__.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.12.0" +__version__ = "0.13.0.dev" __all__ = [ "Label", diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/bytecode.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/bytecode.py index 927efd58..ca4d0ace 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/bytecode.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/bytecode.py @@ -198,8 +198,12 @@ class Bytecode(_InstrList, _BaseBytecodeList): def to_code( self, compute_jumps_passes=None, stacksize=None, *, check_pre_and_post=True ): + # Prevent reconverting the concrete bytecode to bytecode and cfg to do the + # calculation if we need to do it. + if stacksize is None: + stacksize = self.compute_stacksize(check_pre_and_post=check_pre_and_post) bc = self.to_concrete_bytecode(compute_jumps_passes=compute_jumps_passes) - return bc.to_code(stacksize=stacksize, check_pre_and_post=check_pre_and_post) + return bc.to_code(stacksize=stacksize) def to_concrete_bytecode(self, compute_jumps_passes=None): converter = _bytecode._ConvertBytecodeToConcrete(self) diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/cfg.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/cfg.py index bfe3ec33..5e2f3229 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/cfg.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/cfg.py @@ -1,6 +1,9 @@ +import sys + # alias to keep the 'bytecode' variable free from _pydevd_frame_eval.vendored import bytecode as _bytecode from _pydevd_frame_eval.vendored.bytecode.concrete import ConcreteInstr +from _pydevd_frame_eval.vendored.bytecode.flags import CompilerFlags from _pydevd_frame_eval.vendored.bytecode.instr import Label, SetLineno, Instr @@ -219,8 +222,20 @@ class ControlFlowGraph(_bytecode.BaseBytecode): block.seen = False block.startsize = -32768 # INT_MIN + # Starting with Python 3.10, generator and coroutines start with one object + # on the stack (None, anything is an error). + initial_stack_size = 0 + if sys.version_info >= (3, 10) and self.flags & ( + CompilerFlags.GENERATOR + | CompilerFlags.COROUTINE + | CompilerFlags.ASYNC_GENERATOR + ): + initial_stack_size = 1 + # Create a generator/coroutine responsible of dealing with the first block - coro = _compute_stack_size(self[0], 0, 0, check_pre_and_post=check_pre_and_post) + coro = _compute_stack_size( + self[0], initial_stack_size, 0, check_pre_and_post=check_pre_and_post + ) # Create a list of generator that have not yet been exhausted coroutines = [] diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/concrete.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/concrete.py index 7e9c1437..798b827e 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/concrete.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/concrete.py @@ -19,7 +19,11 @@ from _pydevd_frame_eval.vendored.bytecode.instr import ( _check_arg_int, ) -_WORDCODE = sys.version_info >= (3, 6) + +# - jumps use instruction +# - lineno use bytes (dis.findlinestarts(code)) +# - dis displays bytes +OFFSET_AS_INSTRUCTION = sys.version_info >= (3, 10) def _set_docstring(code, consts): @@ -60,22 +64,13 @@ class ConcreteInstr(Instr): def _set(self, name, arg, lineno): super()._set(name, arg, lineno) - if _WORDCODE: - size = 2 - if arg is not UNSET: - while arg > 0xFF: - size += 2 - arg >>= 8 - if self._extended_args is not None: - size = 2 + 2 * self._extended_args - else: - size = 1 - if arg is not UNSET: + size = 2 + if arg is not UNSET: + while arg > 0xFF: size += 2 - if arg > 0xFFFF: - size += 3 - if self._extended_args is not None: - size = 1 + 3 * self._extended_args + arg >>= 8 + if self._extended_args is not None: + size = 2 + 2 * self._extended_args self._size = size @property @@ -87,64 +82,41 @@ class ConcreteInstr(Instr): def get_jump_target(self, instr_offset): if self._opcode in _opcode.hasjrel: - return instr_offset + self._size + self._arg + s = (self._size // 2) if OFFSET_AS_INSTRUCTION else self._size + return instr_offset + s + self._arg if self._opcode in _opcode.hasjabs: return self._arg return None - if _WORDCODE: + def assemble(self): + if self._arg is UNSET: + return bytes((self._opcode, 0)) - def assemble(self): - if self._arg is UNSET: - return bytes((self._opcode, 0)) + arg = self._arg + b = [self._opcode, arg & 0xFF] + while arg > 0xFF: + arg >>= 8 + b[:0] = [_opcode.EXTENDED_ARG, arg & 0xFF] - arg = self._arg - b = [self._opcode, arg & 0xFF] - while arg > 0xFF: - arg >>= 8 - b[:0] = [_opcode.EXTENDED_ARG, arg & 0xFF] + if self._extended_args: + while len(b) < self._size: + b[:0] = [_opcode.EXTENDED_ARG, 0x00] - if self._extended_args: - while len(b) < self._size: - b[:0] = [_opcode.EXTENDED_ARG, 0x00] - - return bytes(b) - - else: - - def assemble(self): - if self._arg is UNSET: - return struct.pack(" 0xFFFF: - b = struct.pack( - "> 16, self._opcode, arg & 0xFFFF - ) - else: - b = struct.pack("= _opcode.HAVE_ARGUMENT: - if _WORDCODE: - arg = code[offset + 1] - else: - arg = code[offset + 1] + code[offset + 2] * 256 + arg = code[index + 1] else: arg = UNSET name = _opcode.opname[op] # fabioz: added offset to ConcreteBytecode # Need to keep an eye on https://github.com/MatthieuDartiailh/bytecode/issues/48 in # case the library decides to add this in some other way. - return cls(name, arg, lineno=lineno, offset=offset) + return cls(name, arg, lineno=lineno, offset=index) class ConcreteBytecode(_bytecode._BaseBytecodeList): @@ -205,14 +177,15 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): instructions = [] offset = 0 lineno = code.co_firstlineno - while offset < len(code.co_code): - if offset in line_starts: - lineno = line_starts[offset] + while offset < (len(code.co_code) // (2 if OFFSET_AS_INSTRUCTION else 1)): + lineno_off = (2 * offset) if OFFSET_AS_INSTRUCTION else offset + if lineno_off in line_starts: + lineno = line_starts[lineno_off] instr = ConcreteInstr.disassemble(lineno, code.co_code, offset) instructions.append(instr) - offset += instr.size + offset += (instr.size // 2) if OFFSET_AS_INSTRUCTION else instr.size bytecode = ConcreteBytecode() @@ -262,8 +235,11 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): linenos = [] for lineno, instr in self._normalize_lineno(self, self.first_lineno): code_str.append(instr.assemble()) - linenos.append((offset, lineno)) - offset += instr.size + i_size = instr.size + linenos.append( + ((offset * 2) if OFFSET_AS_INSTRUCTION else offset, i_size, lineno) + ) + offset += (i_size // 2) if OFFSET_AS_INSTRUCTION else i_size code_str = b"".join(code_str) return (code_str, linenos) @@ -272,7 +248,7 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): lnotab = [] old_offset = 0 old_lineno = first_lineno - for offset, lineno in linenos: + for offset, _, lineno in linenos: dlineno = lineno - old_lineno if dlineno == 0: continue @@ -291,11 +267,13 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): doff -= 255 while dlineno < -128: - lnotab.append(struct.pack("Bb", 0, -128)) + lnotab.append(struct.pack("Bb", doff, -128)) + doff = 0 dlineno -= -128 while dlineno > 127: - lnotab.append(struct.pack("Bb", 0, 127)) + lnotab.append(struct.pack("Bb", doff, 127)) + doff = 0 dlineno -= 127 assert 0 <= doff <= 255 @@ -305,6 +283,53 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): return b"".join(lnotab) + @staticmethod + def _pack_linetable(doff, dlineno): + linetable = [] + while doff > 254: + linetable.append(b"\xfe\x00") + doff -= 254 + + while dlineno < -127: + linetable.append(struct.pack("Bb", 0, -127)) + dlineno -= -127 + + while dlineno > 127: + linetable.append(struct.pack("Bb", 0, 127)) + dlineno -= 127 + + assert 0 <= doff <= 254 + assert -127 <= dlineno <= 127 + + linetable.append(struct.pack("Bb", doff, dlineno)) + return linetable + + def _assemble_linestable(self, first_lineno, linenos): + if not linenos: + return b"" + + linetable = [] + old_offset = 0 + offset, i_size, old_lineno = linenos[0] + old_dlineno = old_lineno - first_lineno + for offset, i_size, lineno in linenos[1:]: + dlineno = lineno - old_lineno + if dlineno == 0: + continue + old_lineno = lineno + + doff = offset - old_offset + old_offset = offset + + linetable.extend(self._pack_linetable(doff, old_dlineno)) + old_dlineno = dlineno + + # Pack the line of the last instruction. + doff = offset + i_size - old_offset + linetable.extend(self._pack_linetable(doff, old_dlineno)) + + return b"".join(linetable) + @staticmethod def _remove_extended_args(instructions): # replace jump targets with blocks @@ -327,8 +352,6 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): if instr.name == "EXTENDED_ARG": nb_extended_args += 1 if extended_arg is not None: - if not _WORDCODE: - raise ValueError("EXTENDED_ARG followed " "by EXTENDED_ARG") extended_arg = (extended_arg << 8) + instr.arg else: extended_arg = instr.arg @@ -337,10 +360,7 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): continue if extended_arg is not None: - if _WORDCODE: - arg = (extended_arg << 8) + instr.arg - else: - arg = (extended_arg << 16) + instr.arg + arg = (extended_arg << 8) + instr.arg extended_arg = None instr = ConcreteInstr( @@ -348,7 +368,7 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): arg, lineno=instr.lineno, extended_args=nb_extended_args, - offset=instr.offset + offset=instr.offset, ) instructions[index] = instr nb_extended_args = 0 @@ -365,7 +385,11 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): def to_code(self, stacksize=None, *, check_pre_and_post=True): code_str, linenos = self._assemble_code() - lnotab = self._assemble_lnotab(self.first_lineno, linenos) + lnotab = ( + self._assemble_linestable(self.first_lineno, linenos) + if sys.version_info >= (3, 10) + else self._assemble_lnotab(self.first_lineno, linenos) + ) nlocals = len(self.varnames) if stacksize is None: stacksize = self.compute_stacksize(check_pre_and_post=check_pre_and_post) @@ -423,7 +447,7 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): target = instr.get_jump_target(offset) if target is not None: jump_targets.add(target) - offset += instr.size + offset += (instr.size // 2) if OFFSET_AS_INSTRUCTION else instr.size # create labels jumps = [] @@ -464,7 +488,7 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList): else: instr_index = len(instructions) instructions.append(instr) - offset += size + offset += (size // 2) if OFFSET_AS_INSTRUCTION else size if jump_target is not None: jumps.append((instr_index, jump_target)) @@ -586,7 +610,7 @@ class _ConvertBytecodeToConcrete: offset = 0 for index, instr in enumerate(self.instructions): offsets.append(offset) - offset += instr.size + offset += instr.size // 2 if OFFSET_AS_INSTRUCTION else instr.size # needed if a label is at the end offsets.append(offset) @@ -598,7 +622,9 @@ class _ConvertBytecodeToConcrete: if instr.opcode in _opcode.hasjrel: instr_offset = offsets[index] - target_offset -= instr_offset + instr.size + target_offset -= instr_offset + ( + instr.size // 2 if OFFSET_AS_INSTRUCTION else instr.size + ) old_size = instr.size # FIXME: better error report if target_offset is negative diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/flags.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/flags.py index db722217..b0c5239c 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/flags.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/flags.py @@ -1,11 +1,8 @@ # alias to keep the 'bytecode' variable free +import sys +from enum import IntFlag from _pydevd_frame_eval.vendored import bytecode as _bytecode -try: - from enum import IntFlag -except ImportError: - from aenum import IntFlag - class CompilerFlags(IntFlag): """Possible values of the co_flags attribute of Code object. @@ -33,7 +30,14 @@ class CompilerFlags(IntFlag): ASYNC_GENERATOR = 0x00200 # noqa # __future__ flags - FUTURE_GENERATOR_STOP = 0x80000 # noqa + # future flags changed in Python 3.9 + if sys.version_info < (3, 9): + FUTURE_GENERATOR_STOP = 0x80000 # noqa + if sys.version_info > (3, 6): + FUTURE_ANNOTATIONS = 0x100000 + else: + FUTURE_GENERATOR_STOP = 0x800000 # noqa + FUTURE_ANNOTATIONS = 0x1000000 def infer_flags(bytecode, is_async=None): diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/instr.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/instr.py index 859ac6f6..9247a549 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/instr.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/instr.py @@ -42,6 +42,7 @@ def _pushes_back(opname): return ( opname.startswith("UNARY_") or opname.startswith("GET_") + # BUILD_XXX_UNPACK have been removed in 3.9 or opname.startswith("BINARY_") or opname.startswith("INPLACE_") or opname.startswith("BUILD_") @@ -318,14 +319,15 @@ class Instr: def pre_and_post_stack_effect(self, jump=None): _effect = self.stack_effect(jump=jump) - # To compute pre size and post size to avoid segfault cause by not enough stack element + # To compute pre size and post size to avoid segfault cause by not enough + # stack element _opname = _opcode.opname[self._opcode] if _opname.startswith("DUP_TOP"): return _effect * -1, _effect * 2 if _pushes_back(_opname): - # if the op pushes value back to the stack, then the stack effect given by dis.stack_effect - # actually equals pre + post effect, therefore we need -1 from the stack effect as a pre - # condition + # if the op pushes value back to the stack, then the stack effect given + # by dis.stack_effect actually equals pre + post effect, therefore we need + # -1 from the stack effect as a pre condition return _effect - 1, 1 if _opname.startswith("UNPACK_"): # Instr(UNPACK_* , n) pops 1 and pushes n @@ -333,8 +335,11 @@ class Instr: # hence we return -1, _effect + 1 return -1, _effect + 1 if _opname == "FOR_ITER" and not jump: - # Since FOR_ITER needs TOS to be an iterator, which basically means a prerequisite of 1 on the stack + # Since FOR_ITER needs TOS to be an iterator, which basically means + # a prerequisite of 1 on the stack return -1, 2 + if _opname == "ROT_N": + return (-self._arg, self._arg) return {"ROT_TWO": (-2, 2), "ROT_THREE": (-3, 3), "ROT_FOUR": (-4, 4)}.get( _opname, (_effect, 0) ) @@ -381,6 +386,7 @@ class Instr: if self._name in { "RETURN_VALUE", "RAISE_VARARGS", + "RERAISE", "BREAK_LOOP", "CONTINUE_LOOP", }: diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__init__.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__init__.py index 08f95e79..ee0f7d1b 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__init__.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__init__.py @@ -14,8 +14,6 @@ from _pydevd_frame_eval.vendored.bytecode import ( ConcreteBytecode, ) -WORDCODE = sys.version_info >= (3, 6) - def _format_instr_list(block, labels, lineno): instr_list = [] diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/sanitytest.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/sanitytest.py deleted file mode 100644 index 2ff34b35..00000000 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/sanitytest.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/python -#author: tobias mueller 13.6.13 -#byteplay test - -from sys import version_info -from dis import dis -from _pydevd_frame_eval.vendored.bytecode import Bytecode, ConcreteBytecode, dump_bytecode -from pprint import pprint - -def f(a, b): -# res = a + b - return - -def g(a, b): - res = a + b if a < b else b + a - r = 0 - for a in range(res): - r += 1 - return r or 2 - -for x in (f, g): - #get byte code for f - dis(x) - print(f.__code__.co_code) - c = Bytecode.from_code(x.__code__) - cc = ConcreteBytecode.from_code(x.__code__) - dump_bytecode(c) - dump_bytecode(cc) - - #generate byte code - cnew = c.to_code() - - x.__code__ = cnew - dis(x) - - print(x(3,5)) diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_bytecode.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_bytecode.py index 782a13a0..c629f75e 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_bytecode.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_bytecode.py @@ -138,22 +138,41 @@ class BytecodeTests(TestCase): bytecode = Bytecode.from_code(code) label_else = Label() label_exit = Label() - self.assertEqual( - bytecode, - [ - Instr("LOAD_NAME", "test", lineno=1), - Instr("POP_JUMP_IF_FALSE", label_else, lineno=1), - Instr("LOAD_CONST", 1, lineno=2), - Instr("STORE_NAME", "x", lineno=2), - Instr("JUMP_FORWARD", label_exit, lineno=2), - label_else, - Instr("LOAD_CONST", 2, lineno=4), - Instr("STORE_NAME", "x", lineno=4), - label_exit, - Instr("LOAD_CONST", None, lineno=4), - Instr("RETURN_VALUE", lineno=4), - ], - ) + if sys.version_info < (3, 10): + self.assertEqual( + bytecode, + [ + Instr("LOAD_NAME", "test", lineno=1), + Instr("POP_JUMP_IF_FALSE", label_else, lineno=1), + Instr("LOAD_CONST", 1, lineno=2), + Instr("STORE_NAME", "x", lineno=2), + Instr("JUMP_FORWARD", label_exit, lineno=2), + label_else, + Instr("LOAD_CONST", 2, lineno=4), + Instr("STORE_NAME", "x", lineno=4), + label_exit, + Instr("LOAD_CONST", None, lineno=4), + Instr("RETURN_VALUE", lineno=4), + ], + ) + # Control flow handling appears to have changed under Python 3.10 + else: + self.assertEqual( + bytecode, + [ + Instr("LOAD_NAME", "test", lineno=1), + Instr("POP_JUMP_IF_FALSE", label_else, lineno=1), + Instr("LOAD_CONST", 1, lineno=2), + Instr("STORE_NAME", "x", lineno=2), + Instr("LOAD_CONST", None, lineno=2), + Instr("RETURN_VALUE", lineno=2), + label_else, + Instr("LOAD_CONST", 2, lineno=4), + Instr("STORE_NAME", "x", lineno=4), + Instr("LOAD_CONST", None, lineno=4), + Instr("RETURN_VALUE", lineno=4), + ], + ) def test_from_code_freevars(self): ns = {} diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_cfg.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_cfg.py index 20ea1763..9b5b07b1 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_cfg.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_cfg.py @@ -17,7 +17,8 @@ from _pydevd_frame_eval.vendored.bytecode import ( BasicBlock, ControlFlowGraph, ) -from _pydevd_frame_eval.vendored.bytecode.tests import disassemble as _disassemble, TestCase, WORDCODE +from _pydevd_frame_eval.vendored.bytecode.concrete import OFFSET_AS_INSTRUCTION +from _pydevd_frame_eval.vendored.bytecode.tests import disassemble as _disassemble, TestCase def disassemble( @@ -566,20 +567,14 @@ class BytecodeBlocksFunctionalTests(TestCase): ] ) - if WORDCODE: + if OFFSET_AS_INSTRUCTION: + # The argument of the jump is divided by 2 expected = ( - b"|\x05" b"r\x08" b"|\x00" b"}\x05" b"d\x01" b"}\x05" b"|\x05" b"S\x00" + b"|\x05" b"r\x04" b"|\x00" b"}\x05" b"d\x01" b"}\x05" b"|\x05" b"S\x00" ) else: expected = ( - b"|\x05\x00" - b"r\x0c\x00" - b"|\x00\x00" - b"}\x05\x00" - b"d\x01\x00" - b"}\x05\x00" - b"|\x05\x00" - b"S" + b"|\x05" b"r\x08" b"|\x00" b"}\x05" b"d\x01" b"}\x05" b"|\x05" b"S\x00" ) code = bytecode.to_code() diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_code.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_code.py index ed3415fd..6938bd1b 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_code.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_code.py @@ -68,6 +68,26 @@ class CodeTests(unittest.TestCase): function=True, ) + # Added because Python 3.10 added some special beahavior with respect to + # generators in term of stack size + def test_generator_func(self): + self.check( + """ + def func(arg, arg2): + yield + """, + function=True, + ) + + def test_async_func(self): + self.check( + """ + async def func(arg, arg2): + pass + """, + function=True, + ) + if __name__ == "__main__": unittest.main() # pragma: no cover diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_concrete.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_concrete.py index e5467923..510f6cd5 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_concrete.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_concrete.py @@ -6,9 +6,10 @@ pytestmark = pytest.mark.skipif(not IS_PY36_OR_GREATER or not IS_CPYTHON or not #!/usr/bin/env python3 import opcode import sys +import textwrap import types import unittest -import textwrap + from _pydevd_frame_eval.vendored.bytecode import ( UNSET, Label, @@ -21,7 +22,8 @@ from _pydevd_frame_eval.vendored.bytecode import ( ConcreteInstr, ConcreteBytecode, ) -from _pydevd_frame_eval.vendored.bytecode.tests import get_code, TestCase, WORDCODE +from _pydevd_frame_eval.vendored.bytecode.concrete import OFFSET_AS_INSTRUCTION +from _pydevd_frame_eval.vendored.bytecode.tests import get_code, TestCase class ConcreteInstrTests(TestCase): @@ -62,7 +64,7 @@ class ConcreteInstrTests(TestCase): self.assertEqual(instr.opcode, 100) self.assertEqual(instr.arg, 5) self.assertEqual(instr.lineno, 12) - self.assertEqual(instr.size, 2 if WORDCODE else 3) + self.assertEqual(instr.size, 2) def test_set(self): instr = ConcreteInstr("LOAD_CONST", 5, lineno=3) @@ -103,12 +105,12 @@ class ConcreteInstrTests(TestCase): # extended argument instr.arg = 0x1234ABCD self.assertEqual(instr.arg, 0x1234ABCD) - self.assertEqual(instr.size, 8 if WORDCODE else 6) + self.assertEqual(instr.size, 8) # small argument instr.arg = 0 self.assertEqual(instr.arg, 0) - self.assertEqual(instr.size, 2 if WORDCODE else 3) + self.assertEqual(instr.size, 2) # invalid argument self.assertRaises(ValueError, setattr, instr, "arg", -1) @@ -124,44 +126,40 @@ class ConcreteInstrTests(TestCase): self.assertRaises(ValueError, setattr, instr, "lineno", -1) def test_size(self): - self.assertEqual(ConcreteInstr("ROT_TWO").size, 2 if WORDCODE else 1) - self.assertEqual(ConcreteInstr("LOAD_CONST", 3).size, 2 if WORDCODE else 3) - self.assertEqual( - ConcreteInstr("LOAD_CONST", 0x1234ABCD).size, 8 if WORDCODE else 6 - ) + self.assertEqual(ConcreteInstr("ROT_TWO").size, 2) + self.assertEqual(ConcreteInstr("LOAD_CONST", 3).size, 2) + self.assertEqual(ConcreteInstr("LOAD_CONST", 0x1234ABCD).size, 8) def test_disassemble(self): - code = b"\t\x00d\x03" if WORDCODE else b"\td\x03\x00" + code = b"\t\x00d\x03" instr = ConcreteInstr.disassemble(1, code, 0) self.assertEqual(instr, ConcreteInstr("NOP", lineno=1)) - instr = ConcreteInstr.disassemble(2, code, 2 if WORDCODE else 1) + instr = ConcreteInstr.disassemble(2, code, 1 if OFFSET_AS_INSTRUCTION else 2) self.assertEqual(instr, ConcreteInstr("LOAD_CONST", 3, lineno=2)) - code = b"\x90\x12\x904\x90\xabd\xcd" if WORDCODE else b"\x904\x12d\xcd\xab" + code = b"\x90\x12\x904\x90\xabd\xcd" instr = ConcreteInstr.disassemble(3, code, 0) - self.assertEqual( - instr, ConcreteInstr("EXTENDED_ARG", 0x12 if WORDCODE else 0x1234, lineno=3) - ) + self.assertEqual(instr, ConcreteInstr("EXTENDED_ARG", 0x12, lineno=3)) def test_assemble(self): instr = ConcreteInstr("NOP") - self.assertEqual(instr.assemble(), b"\t\x00" if WORDCODE else b"\t") + self.assertEqual(instr.assemble(), b"\t\x00") instr = ConcreteInstr("LOAD_CONST", 3) - self.assertEqual(instr.assemble(), b"d\x03" if WORDCODE else b"d\x03\x00") + self.assertEqual(instr.assemble(), b"d\x03") instr = ConcreteInstr("LOAD_CONST", 0x1234ABCD) self.assertEqual( instr.assemble(), - (b"\x90\x12\x904\x90\xabd\xcd" if WORDCODE else b"\x904\x12d\xcd\xab"), + (b"\x90\x12\x904\x90\xabd\xcd"), ) instr = ConcreteInstr("LOAD_CONST", 3, extended_args=1) self.assertEqual( instr.assemble(), - (b"\x90\x00d\x03" if WORDCODE else b"\x90\x00\x00d\x03\x00"), + (b"\x90\x00d\x03"), ) def test_get_jump_target(self): @@ -169,7 +167,9 @@ class ConcreteInstrTests(TestCase): self.assertEqual(jump_abs.get_jump_target(100), 3) jump_forward = ConcreteInstr("JUMP_FORWARD", 5) - self.assertEqual(jump_forward.get_jump_target(10), 17 if WORDCODE else 18) + self.assertEqual( + jump_forward.get_jump_target(10), 16 if OFFSET_AS_INSTRUCTION else 17 + ) class ConcreteBytecodeTests(TestCase): @@ -241,43 +241,42 @@ class ConcreteBytecodeTests(TestCase): ConcreteBytecode([Label()]) def test_to_code_lnotab(self): - # x = 7 - # y = 8 - # z = 9 + + # We use an actual function for the simple case to + # ensure we get lnotab right + def f(): + # + # + x = 7 # noqa + y = 8 # noqa + z = 9 # noqa + + fl = f.__code__.co_firstlineno concrete = ConcreteBytecode() - concrete.consts = [7, 8, 9] - concrete.names = ["x", "y", "z"] - concrete.first_lineno = 3 + concrete.consts = [None, 7, 8, 9] + concrete.varnames = ["x", "y", "z"] + concrete.first_lineno = fl concrete.extend( [ - ConcreteInstr("LOAD_CONST", 0), - ConcreteInstr("STORE_NAME", 0), - SetLineno(4), + SetLineno(fl + 3), ConcreteInstr("LOAD_CONST", 1), - ConcreteInstr("STORE_NAME", 1), - SetLineno(5), + ConcreteInstr("STORE_FAST", 0), + SetLineno(fl + 4), ConcreteInstr("LOAD_CONST", 2), - ConcreteInstr("STORE_NAME", 2), + ConcreteInstr("STORE_FAST", 1), + SetLineno(fl + 5), + ConcreteInstr("LOAD_CONST", 3), + ConcreteInstr("STORE_FAST", 2), + ConcreteInstr("LOAD_CONST", 0), + ConcreteInstr("RETURN_VALUE"), ] ) code = concrete.to_code() - if WORDCODE: - expected = b"d\x00Z\x00d\x01Z\x01d\x02Z\x02" - else: - expected = ( - b"d\x00\x00" - b"Z\x00\x00" - b"d\x01\x00" - b"Z\x01\x00" - b"d\x02\x00" - b"Z\x02\x00" - ) - self.assertEqual(code.co_code, expected) - self.assertEqual(code.co_firstlineno, 3) - self.assertEqual( - code.co_lnotab, b"\x04\x01\x04\x01" if WORDCODE else b"\x06\x01\x06\x01" - ) + self.assertEqual(code.co_code, f.__code__.co_code) + self.assertEqual(code.co_lnotab, f.__code__.co_lnotab) + if sys.version_info >= (3, 10): + self.assertEqual(code.co_linetable, f.__code__.co_linetable) def test_negative_lnotab(self): # x = 7 @@ -296,22 +295,15 @@ class ConcreteBytecodeTests(TestCase): concrete.names = ["x", "y"] concrete.first_lineno = 5 - if sys.version_info >= (3, 6): - code = concrete.to_code() - expected = b"d\x00Z\x00d\x01Z\x01" - self.assertEqual(code.co_code, expected) - self.assertEqual(code.co_firstlineno, 5) - self.assertEqual(code.co_lnotab, b"\x04\xfd") - else: - with self.assertRaises(ValueError) as cm: - code = concrete.to_code() - self.assertEqual( - str(cm.exception), - "negative line number delta is not supported " "on Python < 3.6", - ) + code = concrete.to_code() + expected = b"d\x00Z\x00d\x01Z\x01" + self.assertEqual(code.co_code, expected) + self.assertEqual(code.co_firstlineno, 5) + self.assertEqual(code.co_lnotab, b"\x04\xfd") def test_extended_lnotab(self): # x = 7 + # 200 blank lines # y = 8 concrete = ConcreteBytecode( [ @@ -329,21 +321,38 @@ class ConcreteBytecodeTests(TestCase): concrete.names = ["x", "y"] concrete.first_lineno = 1 - if sys.version_info >= (3, 6): - code = concrete.to_code() - expected = b"d\x00Z\x00d\x01Z\x01" - self.assertEqual(code.co_code, expected) - self.assertEqual(code.co_firstlineno, 1) - self.assertEqual( - code.co_lnotab, b"\x00\x7f\x02\x01\x02\x01\x00\x80\x02\xff" - ) - else: - with self.assertRaises(ValueError) as cm: - code = concrete.to_code() - self.assertEqual( - str(cm.exception), - "negative line number delta is not supported " "on Python < 3.6", - ) + code = concrete.to_code() + expected = b"d\x00Z\x00d\x01Z\x01" + self.assertEqual(code.co_code, expected) + self.assertEqual(code.co_firstlineno, 1) + self.assertEqual(code.co_lnotab, b"\x02\x7f\x00\x01\x02\x01\x02\x80\x00\xff") + + def test_extended_lnotab2(self): + # x = 7 + # 200 blank lines + # y = 8 + base_code = compile("x = 7" + "\n" * 200 + "y = 8", "", "exec") + concrete = ConcreteBytecode( + [ + ConcreteInstr("LOAD_CONST", 0), + ConcreteInstr("STORE_NAME", 0), + SetLineno(201), + ConcreteInstr("LOAD_CONST", 1), + ConcreteInstr("STORE_NAME", 1), + ConcreteInstr("LOAD_CONST", 2), + ConcreteInstr("RETURN_VALUE"), + ] + ) + concrete.consts = [None, 7, 8] + concrete.names = ["x", "y"] + concrete.first_lineno = 1 + + code = concrete.to_code() + self.assertEqual(code.co_code, base_code.co_code) + self.assertEqual(code.co_firstlineno, base_code.co_firstlineno) + self.assertEqual(code.co_lnotab, base_code.co_lnotab) + if sys.version_info >= (3, 10): + self.assertEqual(code.co_linetable, base_code.co_linetable) def test_to_bytecode_consts(self): # x = -0.0 @@ -476,7 +485,7 @@ class ConcreteBytecodeTests(TestCase): self.assertEqual(code.co_cellvars, ("__class__",)) self.assertEqual( code.co_code, - b"\x94\x01\x89\x01" if WORDCODE else b"\x94\x01\x00\x89\x01\x00", + b"\x94\x01\x89\x01", ) def test_explicit_stacksize(self): @@ -571,7 +580,7 @@ class ConcreteBytecodeTests(TestCase): class ConcreteFromCodeTests(TestCase): def test_extended_arg(self): # Create a code object from arbitrary bytecode - co_code = b"\x90\x12\x904\x90\xabd\xcd" if WORDCODE else b"\x904\x12d\xcd\xab" + co_code = b"\x90\x12\x904\x90\xabd\xcd" code = get_code("x=1") args = ( (code.co_argcount,) @@ -590,7 +599,7 @@ class ConcreteFromCodeTests(TestCase): code.co_filename, code.co_name, code.co_firstlineno, - code.co_lnotab, + code.co_linetable if sys.version_info >= (3, 10) else code.co_lnotab, code.co_freevars, code.co_cellvars, ) @@ -605,78 +614,106 @@ class ConcreteFromCodeTests(TestCase): # with EXTENDED_ARG opcode bytecode = ConcreteBytecode.from_code(code, extended_arg=True) - if WORDCODE: - expected = [ - ConcreteInstr("EXTENDED_ARG", 0x12, lineno=1), - ConcreteInstr("EXTENDED_ARG", 0x34, lineno=1), - ConcreteInstr("EXTENDED_ARG", 0xAB, lineno=1), - ConcreteInstr("LOAD_CONST", 0xCD, lineno=1), - ] - else: - expected = [ - ConcreteInstr("EXTENDED_ARG", 0x1234, lineno=1), - ConcreteInstr("LOAD_CONST", 0xABCD, lineno=1), - ] + expected = [ + ConcreteInstr("EXTENDED_ARG", 0x12, lineno=1), + ConcreteInstr("EXTENDED_ARG", 0x34, lineno=1), + ConcreteInstr("EXTENDED_ARG", 0xAB, lineno=1), + ConcreteInstr("LOAD_CONST", 0xCD, lineno=1), + ] self.assertListEqual(list(bytecode), expected) def test_extended_arg_make_function(self): - code_obj = get_code( - """ - def foo(x: int, y: int): - pass - """ - ) + if (3, 9) <= sys.version_info < (3, 10): + from _pydevd_frame_eval.vendored.bytecode.tests.util_annotation import get_code as get_code_future + + code_obj = get_code_future( + """ + def foo(x: int, y: int): + pass + """ + ) + else: + code_obj = get_code( + """ + def foo(x: int, y: int): + pass + """ + ) # without EXTENDED_ARG concrete = ConcreteBytecode.from_code(code_obj) - func_code = concrete.consts[1] - self.assertEqual(concrete.names, ["int", "foo"]) - self.assertEqual(concrete.consts, [("x", "y"), func_code, "foo", None]) - if WORDCODE: - expected = [ - ConcreteInstr("LOAD_NAME", 0, lineno=1), - ConcreteInstr("LOAD_NAME", 0, lineno=1), + if sys.version_info >= (3, 10): + func_code = concrete.consts[2] + names = ["int", "foo"] + consts = ["x", "y", func_code, "foo", None] + const_offset = 1 + name_offset = 1 + first_instrs = [ ConcreteInstr("LOAD_CONST", 0, lineno=1), - ConcreteInstr("BUILD_CONST_KEY_MAP", 2, lineno=1), + ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_CONST", 1, lineno=1), - ConcreteInstr("LOAD_CONST", 2, lineno=1), - ConcreteInstr("MAKE_FUNCTION", 4, lineno=1), - ConcreteInstr("STORE_NAME", 1, lineno=1), - ConcreteInstr("LOAD_CONST", 3, lineno=1), - ConcreteInstr("RETURN_VALUE", lineno=1), + ConcreteInstr("LOAD_NAME", 0, lineno=1), + ConcreteInstr("BUILD_TUPLE", 4, lineno=1), + ] + elif ( + sys.version_info >= (3, 7) + and concrete.flags & CompilerFlags.FUTURE_ANNOTATIONS + ): + func_code = concrete.consts[2] + names = ["foo"] + consts = ["int", ("x", "y"), func_code, "foo", None] + const_offset = 1 + name_offset = 0 + first_instrs = [ + ConcreteInstr("LOAD_CONST", 0, lineno=1), + ConcreteInstr("LOAD_CONST", 0, lineno=1), + ConcreteInstr("LOAD_CONST", 0 + const_offset, lineno=1), + ConcreteInstr("BUILD_CONST_KEY_MAP", 2, lineno=1), ] else: - expected = [ + func_code = concrete.consts[1] + names = ["int", "foo"] + consts = [("x", "y"), func_code, "foo", None] + const_offset = 0 + name_offset = 1 + first_instrs = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), ConcreteInstr("LOAD_NAME", 0, lineno=1), - ConcreteInstr("LOAD_CONST", 0, lineno=1), - ConcreteInstr("LOAD_CONST", 1, lineno=1), - ConcreteInstr("LOAD_CONST", 2, lineno=1), - ConcreteInstr("MAKE_FUNCTION", 3 << 16, lineno=1), - ConcreteInstr("STORE_NAME", 1, lineno=1), - ConcreteInstr("LOAD_CONST", 3, lineno=1), - ConcreteInstr("RETURN_VALUE", lineno=1), + ConcreteInstr("LOAD_CONST", 0 + const_offset, lineno=1), + ConcreteInstr("BUILD_CONST_KEY_MAP", 2, lineno=1), ] + + self.assertEqual(concrete.names, names) + self.assertEqual(concrete.consts, consts) + expected = first_instrs + [ + ConcreteInstr("LOAD_CONST", 1 + const_offset, lineno=1), + ConcreteInstr("LOAD_CONST", 2 + const_offset, lineno=1), + ConcreteInstr("MAKE_FUNCTION", 4, lineno=1), + ConcreteInstr("STORE_NAME", name_offset, lineno=1), + ConcreteInstr("LOAD_CONST", 3 + const_offset, lineno=1), + ConcreteInstr("RETURN_VALUE", lineno=1), + ] self.assertListEqual(list(concrete), expected) # with EXTENDED_ARG concrete = ConcreteBytecode.from_code(code_obj, extended_arg=True) - func_code = concrete.consts[1] - self.assertEqual(concrete.names, ["int", "foo"]) - self.assertEqual(concrete.consts, [("x", "y"), func_code, "foo", None]) - if not WORDCODE: - expected = [ - ConcreteInstr("LOAD_NAME", 0, lineno=1), - ConcreteInstr("LOAD_NAME", 0, lineno=1), - ConcreteInstr("LOAD_CONST", 0, lineno=1), - ConcreteInstr("LOAD_CONST", 1, lineno=1), - ConcreteInstr("LOAD_CONST", 2, lineno=1), - ConcreteInstr("EXTENDED_ARG", 3, lineno=1), - ConcreteInstr("MAKE_FUNCTION", 0, lineno=1), - ConcreteInstr("STORE_NAME", 1, lineno=1), - ConcreteInstr("LOAD_CONST", 3, lineno=1), - ConcreteInstr("RETURN_VALUE", lineno=1), - ] + # With future annotation the int annotation is stringified and + # stored as constant this the default behavior under Python 3.10 + if sys.version_info >= (3, 10): + func_code = concrete.consts[2] + names = ["int", "foo"] + consts = ["x", "y", func_code, "foo", None] + elif concrete.flags & CompilerFlags.FUTURE_ANNOTATIONS: + func_code = concrete.consts[2] + names = ["foo"] + consts = ["int", ("x", "y"), func_code, "foo", None] + else: + func_code = concrete.consts[1] + names = ["int", "foo"] + consts = [("x", "y"), func_code, "foo", None] + + self.assertEqual(concrete.names, names) + self.assertEqual(concrete.consts, consts) self.assertListEqual(list(concrete), expected) # The next three tests ensure we can round trip ConcreteBytecode generated @@ -1093,10 +1130,12 @@ class BytecodeToConcreteTests(TestCase): concrete = bytecode.to_concrete_bytecode() expected = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), - ConcreteInstr("POP_JUMP_IF_FALSE", 14 if WORDCODE else 21, lineno=1), + ConcreteInstr( + "POP_JUMP_IF_FALSE", 7 if OFFSET_AS_INSTRUCTION else 14, lineno=1 + ), ConcreteInstr("LOAD_CONST", 0, lineno=2), ConcreteInstr("STORE_NAME", 1, lineno=2), - ConcreteInstr("JUMP_FORWARD", 4 if WORDCODE else 6, lineno=2), + ConcreteInstr("JUMP_FORWARD", 2 if OFFSET_AS_INSTRUCTION else 4, lineno=2), ConcreteInstr("LOAD_CONST", 1, lineno=4), ConcreteInstr("STORE_NAME", 1, lineno=4), ConcreteInstr("LOAD_CONST", 2, lineno=4), @@ -1232,10 +1271,10 @@ class BytecodeToConcreteTests(TestCase): ) code_obj = code.to_code() - if WORDCODE: - expected = b"\x90\x01\x90\x00q\x06" + NOP * nb_nop + b"d\x00S\x00" + if OFFSET_AS_INSTRUCTION: + expected = b"\x90\x80q\x02" + NOP * nb_nop + b"d\x00S\x00" else: - expected = b"\x90\x01\x00q\x06\x00" + NOP * nb_nop + b"d\x00\x00S" + expected = b"\x90\x01\x90\x00q\x06" + NOP * nb_nop + b"d\x00S\x00" self.assertEqual(code_obj.co_code, expected) def test_jumps(self): @@ -1265,10 +1304,12 @@ class BytecodeToConcreteTests(TestCase): code = code.to_concrete_bytecode() expected = [ ConcreteInstr("LOAD_NAME", 0, lineno=1), - ConcreteInstr("POP_JUMP_IF_FALSE", 10 if WORDCODE else 15, lineno=1), + ConcreteInstr( + "POP_JUMP_IF_FALSE", 5 if OFFSET_AS_INSTRUCTION else 10, lineno=1 + ), ConcreteInstr("LOAD_CONST", 0, lineno=2), ConcreteInstr("STORE_NAME", 1, lineno=2), - ConcreteInstr("JUMP_FORWARD", 4 if WORDCODE else 6, lineno=2), + ConcreteInstr("JUMP_FORWARD", 2 if OFFSET_AS_INSTRUCTION else 4, lineno=2), ConcreteInstr("LOAD_CONST", 1, lineno=4), ConcreteInstr("STORE_NAME", 1, lineno=4), ConcreteInstr("LOAD_CONST", 2, lineno=4), @@ -1340,11 +1381,9 @@ class BytecodeToConcreteTests(TestCase): # # Thus we need to make an additional pass. This test only verifies # case where 2 passes is insufficient but three is enough. - - if not WORDCODE: - # Could be done pre-WORDCODE, but that requires 2**16 bytes of - # code. - return + # + # On Python > 3.10 we need to double the number since the offset is now + # in term of instructions and not bytes. # Create code from comment above. code = Bytecode() @@ -1353,11 +1392,17 @@ class BytecodeToConcreteTests(TestCase): nop = "NOP" code.append(Instr("JUMP_ABSOLUTE", label1)) code.append(Instr("JUMP_ABSOLUTE", label2)) - for x in range(4, 254, 2): + # Need 254 * 2 + 2 since the arg will change by 1 instruction rather than 2 + # bytes. + for x in range(4, 510 if OFFSET_AS_INSTRUCTION else 254, 2): code.append(Instr(nop)) code.append(label1) code.append(Instr(nop)) - for x in range(256, 300, 2): + for x in range( + 514 if OFFSET_AS_INSTRUCTION else 256, + 600 if OFFSET_AS_INSTRUCTION else 300, + 2, + ): code.append(Instr(nop)) code.append(label2) code.append(Instr(nop)) @@ -1381,18 +1426,20 @@ class BytecodeToConcreteTests(TestCase): instead generate a series of many jumps. Each pass of compute_jumps() extends one more instruction, which in turn causes the one behind it to be extended on the next pass. + """ - if not WORDCODE: - return # N: the number of unextended instructions that can be squeezed into a # set of bytes adressable by the arg of an unextended instruction. - # The answer is "128", but here's how we arrive at it (and it also - # hints at how to make this work for pre-WORDCODE). + # The answer is "128", but here's how we arrive at it. max_unextended_offset = 1 << 8 unextended_branch_instr_size = 2 N = max_unextended_offset // unextended_branch_instr_size + # When using instruction rather than bytes in the offset multiply by 2 + if OFFSET_AS_INSTRUCTION: + N *= 2 + nop = "UNARY_POSITIVE" # don't use NOP, dis.stack_effect will raise # The number of jumps will be equal to the number of labels. The diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_misc.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_misc.py index 58f313bb..5f4c0636 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_misc.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/test_misc.py @@ -6,12 +6,14 @@ pytestmark = pytest.mark.skipif(not IS_PY36_OR_GREATER or not IS_CPYTHON or not #!/usr/bin/env python3 import contextlib import io +import sys import textwrap import unittest from _pydevd_frame_eval.vendored import bytecode from _pydevd_frame_eval.vendored.bytecode import Label, Instr, Bytecode, BasicBlock, ControlFlowGraph -from _pydevd_frame_eval.vendored.bytecode.tests import disassemble, WORDCODE +from _pydevd_frame_eval.vendored.bytecode.concrete import OFFSET_AS_INSTRUCTION +from _pydevd_frame_eval.vendored.bytecode.tests import disassemble class DumpCodeTests(unittest.TestCase): @@ -39,10 +41,11 @@ class DumpCodeTests(unittest.TestCase): code = disassemble(source, function=True) # without line numbers - expected = """ + enum_repr = "" + expected = f""" LOAD_FAST 'test' LOAD_CONST 1 - COMPARE_OP + COMPARE_OP {enum_repr} POP_JUMP_IF_FALSE LOAD_CONST 1 RETURN_VALUE @@ -50,7 +53,7 @@ class DumpCodeTests(unittest.TestCase): label_instr6: LOAD_FAST 'test' LOAD_CONST 2 - COMPARE_OP + COMPARE_OP {enum_repr} POP_JUMP_IF_FALSE LOAD_CONST 2 RETURN_VALUE @@ -67,10 +70,10 @@ label_instr13: self.check_dump_bytecode(code, expected) # with line numbers - expected = """ + expected = f""" L. 2 0: LOAD_FAST 'test' 1: LOAD_CONST 1 - 2: COMPARE_OP + 2: COMPARE_OP {enum_repr} 3: POP_JUMP_IF_FALSE L. 3 4: LOAD_CONST 1 5: RETURN_VALUE @@ -78,7 +81,7 @@ label_instr13: label_instr6: L. 4 7: LOAD_FAST 'test' 8: LOAD_CONST 2 - 9: COMPARE_OP + 9: COMPARE_OP {enum_repr} 10: POP_JUMP_IF_FALSE L. 5 11: LOAD_CONST 2 12: RETURN_VALUE @@ -128,12 +131,13 @@ label_instr13: code = ControlFlowGraph.from_bytecode(code) # without line numbers + enum_repr = "" expected = textwrap.dedent( - """ + f""" block1: LOAD_FAST 'test' LOAD_CONST 1 - COMPARE_OP + COMPARE_OP {enum_repr} POP_JUMP_IF_FALSE -> block2 @@ -144,7 +148,7 @@ label_instr13: block3: LOAD_FAST 'test' LOAD_CONST 2 - COMPARE_OP + COMPARE_OP {enum_repr} POP_JUMP_IF_FALSE -> block4 @@ -162,11 +166,11 @@ label_instr13: # with line numbers expected = textwrap.dedent( - """ + f""" block1: L. 2 0: LOAD_FAST 'test' 1: LOAD_CONST 1 - 2: COMPARE_OP + 2: COMPARE_OP {enum_repr} 3: POP_JUMP_IF_FALSE -> block2 @@ -177,7 +181,7 @@ label_instr13: block3: L. 4 0: LOAD_FAST 'test' 1: LOAD_CONST 2 - 2: COMPARE_OP + 2: COMPARE_OP {enum_repr} 3: POP_JUMP_IF_FALSE -> block4 @@ -206,85 +210,45 @@ label_instr13: code = code.to_concrete_bytecode() # without line numbers - if WORDCODE: - expected = """ + expected = f""" 0 LOAD_FAST 0 2 LOAD_CONST 1 4 COMPARE_OP 2 - 6 POP_JUMP_IF_FALSE 12 + 6 POP_JUMP_IF_FALSE {6 if OFFSET_AS_INSTRUCTION else 12} 8 LOAD_CONST 1 10 RETURN_VALUE 12 LOAD_FAST 0 14 LOAD_CONST 2 16 COMPARE_OP 2 - 18 POP_JUMP_IF_FALSE 24 + 18 POP_JUMP_IF_FALSE {12 if OFFSET_AS_INSTRUCTION else 24} 20 LOAD_CONST 2 22 RETURN_VALUE 24 LOAD_CONST 3 26 RETURN_VALUE """.lstrip( - "\n" - ) - else: - expected = """ - 0 LOAD_FAST 0 - 3 LOAD_CONST 1 - 6 COMPARE_OP 2 - 9 POP_JUMP_IF_FALSE 16 - 12 LOAD_CONST 1 - 15 RETURN_VALUE - 16 LOAD_FAST 0 - 19 LOAD_CONST 2 - 22 COMPARE_OP 2 - 25 POP_JUMP_IF_FALSE 32 - 28 LOAD_CONST 2 - 31 RETURN_VALUE - 32 LOAD_CONST 3 - 35 RETURN_VALUE -""".lstrip( - "\n" - ) + "\n" + ) self.check_dump_bytecode(code, expected) # with line numbers - if WORDCODE: - expected = """ + expected = f""" L. 2 0: LOAD_FAST 0 2: LOAD_CONST 1 4: COMPARE_OP 2 - 6: POP_JUMP_IF_FALSE 12 + 6: POP_JUMP_IF_FALSE {6 if OFFSET_AS_INSTRUCTION else 12} L. 3 8: LOAD_CONST 1 10: RETURN_VALUE L. 4 12: LOAD_FAST 0 14: LOAD_CONST 2 16: COMPARE_OP 2 - 18: POP_JUMP_IF_FALSE 24 + 18: POP_JUMP_IF_FALSE {12 if OFFSET_AS_INSTRUCTION else 24} L. 5 20: LOAD_CONST 2 22: RETURN_VALUE L. 6 24: LOAD_CONST 3 26: RETURN_VALUE """.lstrip( - "\n" - ) - else: - expected = """ -L. 2 0: LOAD_FAST 0 - 3: LOAD_CONST 1 - 6: COMPARE_OP 2 - 9: POP_JUMP_IF_FALSE 16 -L. 3 12: LOAD_CONST 1 - 15: RETURN_VALUE -L. 4 16: LOAD_FAST 0 - 19: LOAD_CONST 2 - 22: COMPARE_OP 2 - 25: POP_JUMP_IF_FALSE 32 -L. 5 28: LOAD_CONST 2 - 31: RETURN_VALUE -L. 6 32: LOAD_CONST 3 - 35: RETURN_VALUE -""".lstrip( - "\n" - ) + "\n" + ) self.check_dump_bytecode(code, expected, lineno=True) def test_type_validation(self): diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/util_annotation.py b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/util_annotation.py new file mode 100644 index 00000000..b6475434 --- /dev/null +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/util_annotation.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +import textwrap +import types + + +def get_code(source, *, filename="", function=False): + source = textwrap.dedent(source).strip() + code = compile(source, filename, "exec") + if function: + sub_code = [ + const for const in code.co_consts if isinstance(const, types.CodeType) + ] + if len(sub_code) != 1: + raise ValueError("unable to find function code") + code = sub_code[0] + return code diff --git a/src/debugpy/_vendored/pydevd/conftest.py b/src/debugpy/_vendored/pydevd/conftest.py index e5b1e677..c46c3f9f 100644 --- a/src/debugpy/_vendored/pydevd/conftest.py +++ b/src/debugpy/_vendored/pydevd/conftest.py @@ -92,7 +92,7 @@ def _start_monitoring_threads(): os._exit(123) dump_current_frames_thread = DumpThreads() - dump_current_frames_thread.setDaemon(True) # Daemon so that this thread doesn't halt it! + dump_current_frames_thread.daemon = True # Daemon so that this thread doesn't halt it! dump_current_frames_thread.start() diff --git a/src/debugpy/_vendored/pydevd/pydev_run_in_console.py b/src/debugpy/_vendored/pydevd/pydev_run_in_console.py index 2649589b..d6b2f723 100644 --- a/src/debugpy/_vendored/pydevd/pydev_run_in_console.py +++ b/src/debugpy/_vendored/pydevd/pydev_run_in_console.py @@ -131,7 +131,7 @@ if __name__ == '__main__': server_thread = threading.Thread(target=start_console_server, name='ServerThread', args=(host, int(port), interpreter)) - server_thread.setDaemon(True) + server_thread.daemon = True server_thread.start() sys.stdin = StdIn(interpreter, host, client_port, sys.stdin) diff --git a/src/debugpy/_vendored/pydevd/runfiles.py b/src/debugpy/_vendored/pydevd/runfiles.py index 90c46438..8d17ac63 100644 --- a/src/debugpy/_vendored/pydevd/runfiles.py +++ b/src/debugpy/_vendored/pydevd/runfiles.py @@ -318,5 +318,5 @@ if __name__ == '__main__': dump_current_frames_thread = DumpThreads() - dump_current_frames_thread.setDaemon(True) # Daemon so that this thread doesn't halt it! + dump_current_frames_thread.daemon = True # Daemon so that this thread doesn't halt it! dump_current_frames_thread.start() diff --git a/src/debugpy/_vendored/pydevd/tests/test_check_pydevconsole.py b/src/debugpy/_vendored/pydevd/tests/test_check_pydevconsole.py index 33d02567..8795918b 100644 --- a/src/debugpy/_vendored/pydevd/tests/test_check_pydevconsole.py +++ b/src/debugpy/_vendored/pydevd/tests/test_check_pydevconsole.py @@ -57,7 +57,7 @@ class Test(unittest.TestCase): client_thread = ClientThread(client_port) client_thread.requested_input = False client_thread.notified_finished = 0 - client_thread.setDaemon(True) + client_thread.daemon = True client_thread.start() return client_thread @@ -84,7 +84,7 @@ class Test(unittest.TestCase): 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.setDaemon(True) + server_thread.daemon = True server_thread.start() client_thread = self.start_client_thread(client_port) #@UnusedVariable diff --git a/src/debugpy/_vendored/pydevd/tests/test_pydev_ipython_011.py b/src/debugpy/_vendored/pydevd/tests/test_pydev_ipython_011.py index 17a45547..40c51eab 100644 --- a/src/debugpy/_vendored/pydevd/tests/test_pydev_ipython_011.py +++ b/src/debugpy/_vendored/pydevd/tests/test_pydev_ipython_011.py @@ -238,7 +238,7 @@ class TestRunningCode(TestBase): self.client_server.shutdown() client_thread = ClientThread(client_port) - client_thread.setDaemon(True) + client_thread.daemon = True client_thread.start() return client_thread diff --git a/src/debugpy/_vendored/pydevd/tests/test_pydevconsole.py b/src/debugpy/_vendored/pydevd/tests/test_pydevconsole.py index dd717935..4372f133 100644 --- a/src/debugpy/_vendored/pydevd/tests/test_pydevconsole.py +++ b/src/debugpy/_vendored/pydevd/tests/test_pydevconsole.py @@ -163,7 +163,7 @@ class Test(unittest.TestCase): client_thread = ClientThread(client_port) client_thread.requested_input = False client_thread.notified_finished = 0 - client_thread.setDaemon(True) + client_thread.daemon = True client_thread.start() return client_thread @@ -185,7 +185,7 @@ class Test(unittest.TestCase): socket_code(socket) debugger_thread = DebuggerServerThread(debugger_port, socket_code) - debugger_thread.setDaemon(True) + debugger_thread.daemon = True debugger_thread.start() return debugger_thread @@ -219,7 +219,7 @@ class Test(unittest.TestCase): pydevconsole.start_server(pydev_localhost.get_localhost(), self.server_port, self.client_port) server_thread = ServerThread(client_port, server_port) - server_thread.setDaemon(True) + server_thread.daemon = True server_thread.start() client_thread = self.start_client_thread(client_port) # @UnusedVariable diff --git a/src/debugpy/_vendored/pydevd/tests_python/debugger_unittest.py b/src/debugpy/_vendored/pydevd/tests_python/debugger_unittest.py index 0a9967c0..d2998a97 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/debugger_unittest.py +++ b/src/debugpy/_vendored/pydevd/tests_python/debugger_unittest.py @@ -201,7 +201,7 @@ class ReaderThread(threading.Thread): except ImportError: from Queue import Queue - self.setDaemon(True) + self.daemon = True self._buffer = b'' self.sock = sock self._queue = Queue() @@ -382,7 +382,7 @@ def read_process(stream, buffer, debug_stream, stream_name, finish): def start_in_daemon_thread(target, args): t0 = threading.Thread(target=target, args=args) - t0.setDaemon(True) + t0.daemon = True t0.start() @@ -671,7 +671,7 @@ class AbstractWriterThread(threading.Thread): def __init__(self, *args, **kwargs): threading.Thread.__init__(self, *args, **kwargs) self.process = None # Set after the process is created. - self.setDaemon(True) + self.daemon = True self.finished_ok = False self.finished_initialization = False self._next_breakpoint_id = 0 diff --git a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_adjust_breakpoint.py b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_adjust_breakpoint.py index 0c26a8c4..18fdd445 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_adjust_breakpoint.py +++ b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_adjust_breakpoint.py @@ -1,10 +1,11 @@ def Call(): b = True - while b: # expected - pass # requested + 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!') \ No newline at end of file + print('TEST SUCEEDED!') diff --git a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_check_tracer.py b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_check_tracer.py index 0fa373f2..0b284766 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_check_tracer.py +++ b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_check_tracer.py @@ -68,7 +68,7 @@ def thread_func(): th = threading.Thread(target=thread_func) -th.setDaemon(True) +th.daemon = True th.start() event = threading.Event() diff --git a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_stop_async_iteration.py b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_stop_async_iteration.py index e2851fbe..fe541327 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_stop_async_iteration.py +++ b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_stop_async_iteration.py @@ -9,6 +9,6 @@ async def run(): print(p) if __name__ == "__main__": - loop = asyncio.get_event_loop() + 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/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_unhandled_exceptions.py b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_unhandled_exceptions.py index 57e17d62..f08e1d75 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_unhandled_exceptions.py +++ b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_unhandled_exceptions.py @@ -35,7 +35,7 @@ def thread_func2(n): th = threading.Thread(target=lambda: thread_func2(1)) -th.setDaemon(True) +th.daemon = True th.start() th.join() diff --git a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_unhandled_exceptions_custom.py b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_unhandled_exceptions_custom.py index a0b5f71d..6065110d 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_unhandled_exceptions_custom.py +++ b/src/debugpy/_vendored/pydevd/tests_python/resources/_debugger_case_unhandled_exceptions_custom.py @@ -41,7 +41,7 @@ def thread_func2(n): th = threading.Thread(target=lambda: thread_func2(1)) -th.setDaemon(True) +th.daemon = True th.start() th.join() diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_smart_step_into_bytecode.py b/src/debugpy/_vendored/pydevd/tests_python/test_smart_step_into_bytecode.py index 48924c52..f0f9caab 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/test_smart_step_into_bytecode.py +++ b/src/debugpy/_vendored/pydevd/tests_python/test_smart_step_into_bytecode.py @@ -22,13 +22,16 @@ def check(found, expected): last_offset = -1 for f, e in zip(found, expected): - 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 + 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. @@ -1098,18 +1101,23 @@ def _test_find_bytecode(): import glob import dis from io import StringIO - root_dir = 'C:\\bin\\Miniconda\\envs\\py36_tests\\Lib\\site-packages\\' + 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: - contents = stream.read() + 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) - if 'EXTENDED_ARG' in s.getvalue(): + # 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)