diff --git a/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles.py b/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles.py index ca786c376b..3a4d36c6f7 100644 --- a/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles.py +++ b/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles.py @@ -6,6 +6,7 @@ from _pydevd_bundle.pydevd_constants import * # @UnusedWildImport import re import time +import json # ======================================================================================================================= @@ -228,6 +229,20 @@ def parse_cmdline(argv=None): else: sys.stderr.write("Could not find config file: %s\n" % (config_file,)) + filter_tests_env_var = os.environ.get("PYDEV_RUNFILES_FILTER_TESTS", None) + if filter_tests_env_var: + print("PYDEV_RUNFILES_FILTER_TESTS", filter_tests_env_var) + loaded = json.loads(filter_tests_env_var) + include = loaded["include"] + exclude = loaded["exclude"] + for path, name in include: + existing = files_to_tests.get(path) + if not existing: + existing = files_to_tests[path] = [] + existing.append(name) + # TODO: Handle name == '*' + # TODO: Handle exclude + if type([]) != type(dirs): dirs = [dirs] @@ -750,7 +765,8 @@ def run_tests(self, handle_coverage=True): if self.configuration.django: import django - if hasattr(django, 'setup'): + + if hasattr(django, "setup"): django.setup() if handle_coverage: diff --git a/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles_pytest2.py b/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles_pytest2.py index 3cca7a2888..acd99c3e62 100644 --- a/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles_pytest2.py +++ b/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles_pytest2.py @@ -1,14 +1,16 @@ -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 pickle import sys import time +import zlib from pathlib import Path +import pytest +from pydevd_file_utils import canonical_normalized_path + +from _pydev_runfiles import pydev_runfiles_xml_rpc + # ========================================================================= # Load filters with tests we should skip # ========================================================================= @@ -51,7 +53,9 @@ def connect_to_server_for_communication_to_xml_rpc_on_xdist(): connected = True if is_in_xdist_node(): port = os.environ.get("PYDEV_PYTEST_SERVER") - if not port: + if port == "None": + pass + elif 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) diff --git a/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles_xml_rpc.py b/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles_xml_rpc.py index a34472ee99..1bcaedfc85 100644 --- a/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles_xml_rpc.py +++ b/plugins/org.python.pydev.core/pysrc/_pydev_runfiles/pydev_runfiles_xml_rpc.py @@ -4,7 +4,7 @@ import warnings from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding -from _pydev_bundle.pydev_imports import xmlrpclib, _queue +from _pydev_bundle.pydev_imports import _queue, xmlrpclib from _pydevd_bundle.pydevd_constants import Null Queue = _queue.Queue @@ -159,7 +159,8 @@ def initialize_server(port, daemon=False): _ServerHolder.SERVER_COMM = Null() try: - _ServerHolder.SERVER.notifyConnected() + if _ServerHolder.SERVER is not None: + _ServerHolder.SERVER.notifyConnected() except: traceback.print_exc() @@ -170,7 +171,8 @@ def initialize_server(port, daemon=False): def notifyTestsCollected(tests_count): assert tests_count is not None try: - _ServerHolder.SERVER.notifyTestsCollected(tests_count) + if _ServerHolder.SERVER is not None: + _ServerHolder.SERVER.notifyTestsCollected(tests_count) except: traceback.print_exc() @@ -188,7 +190,8 @@ def notifyStartTest(file, test): test = "" # Could happen if we have an import error importing module. try: - _ServerHolder.SERVER.notifyStartTest(file, test) + if _ServerHolder.SERVER is not None: + _ServerHolder.SERVER.notifyStartTest(file, test) except: traceback.print_exc() @@ -200,7 +203,7 @@ def _encode_if_needed(obj): elif isinstance(obj, bytes): try: - return xmlrpclib.Binary(obj.decode(sys.stdin.encoding).encode("ISO-8859-1", "xmlcharrefreplace")) + return xmlrpclib.Binary(obj.decode(sys.stdin.encoding, 'replace').encode("ISO-8859-1", "xmlcharrefreplace")) except: return xmlrpclib.Binary(obj) # bytes already @@ -219,6 +222,9 @@ def notifyTest(cond, captured_output, error_contents, file, test, time): @param test: the test ran (i.e.: TestCase.test1) @param time: float with the number of seconds elapsed """ + if _ServerHolder.SERVER is None: + return + assert cond is not None assert captured_output is not None assert error_contents is not None @@ -241,7 +247,8 @@ def notifyTest(cond, captured_output, error_contents, file, test, time): def notifyTestRunFinished(total_time): assert total_time is not None try: - _ServerHolder.SERVER.notifyTestRunFinished(total_time) + if _ServerHolder.SERVER is not None: + _ServerHolder.SERVER.notifyTestRunFinished(total_time) except: traceback.print_exc() diff --git a/plugins/org.python.pydev.core/pysrc/_pydevd_bundle/pydevd_comm.py b/plugins/org.python.pydev.core/pysrc/_pydevd_bundle/pydevd_comm.py index b154791516..b8a3a043fe 100644 --- a/plugins/org.python.pydev.core/pysrc/_pydevd_bundle/pydevd_comm.py +++ b/plugins/org.python.pydev.core/pysrc/_pydevd_bundle/pydevd_comm.py @@ -472,7 +472,10 @@ def start_server(port): try: s.listen(1) # Let the user know it's halted waiting for the connection. - pydev_log.critical("pydevd: waiting for connection at: %s:%s\n", *s.getsockname()) + host, port = s.getsockname() + msg = f"pydevd: waiting for connection at: {host}:{port}" + print(msg, file=sys.stderr) + pydev_log.info(msg) new_socket, _addr = s.accept() pydev_log.info("Connection accepted") @@ -527,7 +530,7 @@ def start_client(host, port): s.settimeout(timeout) s.connect((host, port)) s.settimeout(None) # no timeout after connected - pydev_log.info("Connected.") + pydev_log.info(f"Connected to: {s}.") return s except: pydev_log.exception("Could not connect to %s: %s", host, port) diff --git a/plugins/org.python.pydev.core/pysrc/pydevd.py b/plugins/org.python.pydev.core/pysrc/pydevd.py index 532eb88e8f..6cb62c6a78 100644 --- a/plugins/org.python.pydev.core/pysrc/pydevd.py +++ b/plugins/org.python.pydev.core/pysrc/pydevd.py @@ -2937,6 +2937,7 @@ def settrace( access_token=None, client_access_token=None, notify_stdin=True, + protocol=None, **kwargs, ): """Sets the tracing function with the pydev debug function and initializes needed facilities. @@ -2991,7 +2992,14 @@ def settrace( 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). + + :param protocol: + When using in Eclipse the protocol should not be passed, but when used in VSCode + or some other IDE/editor that accepts the Debug Adapter Protocol then 'dap' should + be passed. """ + if protocol and protocol.lower() == "dap": + pydevd_defaults.PydevdCustomization.DEFAULT_PROTOCOL = pydevd_constants.HTTP_JSON_PROTOCOL 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 diff --git a/plugins/org.python.pydev.core/pysrc/runfiles.py b/plugins/org.python.pydev.core/pysrc/runfiles.py index 4b364986b0..a89c3c44f6 100644 --- a/plugins/org.python.pydev.core/pysrc/runfiles.py +++ b/plugins/org.python.pydev.core/pysrc/runfiles.py @@ -46,7 +46,7 @@ def get_with_filesystem_case(f): from _pydevd_bundle import pydevd_constants from pydevd_file_utils import canonical_normalized_path - DEBUG = 0 + DEBUG = 1 if DEBUG: sys.stdout.write("Received parameters: %s\n" % (sys.argv,)) sys.stdout.write("Params for pydev: %s\n" % (pydev_params,)) diff --git a/plugins/org.python.pydev.core/pysrc/tests_runfiles/samples_integrated/root/__init__.py b/plugins/org.python.pydev.core/pysrc/tests_runfiles/samples_integrated/root/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/org.python.pydev.core/pysrc/tests_runfiles/samples_integrated/root/test_in_root.py b/plugins/org.python.pydev.core/pysrc/tests_runfiles/samples_integrated/root/test_in_root.py new file mode 100644 index 0000000000..38c6291440 --- /dev/null +++ b/plugins/org.python.pydev.core/pysrc/tests_runfiles/samples_integrated/root/test_in_root.py @@ -0,0 +1,6 @@ +import unittest + + +class MyTest(unittest.TestCase): + def test1(self): + print("--on-test-1") diff --git a/plugins/org.python.pydev.core/pysrc/tests_runfiles/test_runfiles.py b/plugins/org.python.pydev.core/pysrc/tests_runfiles/test_runfiles.py index 91997b9d50..03aff39ad1 100644 --- a/plugins/org.python.pydev.core/pysrc/tests_runfiles/test_runfiles.py +++ b/plugins/org.python.pydev.core/pysrc/tests_runfiles/test_runfiles.py @@ -3,16 +3,8 @@ 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) +project_rootdir = os.path.abspath(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +sys.path.insert(0, project_rootdir) from _pydev_runfiles import pydev_runfiles_unittest from _pydev_runfiles import pydev_runfiles_xml_rpc @@ -43,7 +35,7 @@ sys.path = orig_syspath[:] # remove it so that we leave it ok for other tests -sys.path.remove(desired_runfiles_path) +sys.path.remove(project_rootdir) class RunfilesTest(unittest.TestCase): @@ -75,7 +67,7 @@ def _setup_scenario( 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.file_dir = [os.path.abspath(os.path.join(project_rootdir, "tests_runfiles", "samples"))] self._setup_scenario(self.file_dir, None) def test_suite_used(self): diff --git a/plugins/org.python.pydev.core/pysrc/tests_runfiles/test_runfiles_integrated.py b/plugins/org.python.pydev.core/pysrc/tests_runfiles/test_runfiles_integrated.py new file mode 100644 index 0000000000..d9afd9dc04 --- /dev/null +++ b/plugins/org.python.pydev.core/pysrc/tests_runfiles/test_runfiles_integrated.py @@ -0,0 +1,58 @@ +import os +from subprocess import CompletedProcess +import subprocess +import sys +from typing import Union, Literal, Optional, Dict +import json + + +def python_run( + cmdline, + returncode: Union[Literal["error"], Literal["any"], int], + cwd=None, + additional_env: Optional[Dict[str, str]] = None, + timeout=None, +) -> CompletedProcess: + cp = os.environ.copy() + cp["PYTHONPATH"] = os.pathsep.join([x for x in sys.path if x]) + if additional_env: + cp.update(additional_env) + args = [sys.executable] + cmdline + result = subprocess.run(args, capture_output=True, env=cp, cwd=cwd, timeout=timeout) + + if returncode == "any": + return result + + if returncode == "error" and result.returncode: + return result + + if result.returncode == returncode: + return result + + # This is a bit too verbose, so, commented out for now. + # env_str = "\n".join(str(x) for x in sorted(cp.items())) + + raise AssertionError( + f"""Expected returncode: {returncode}. Found: {result.returncode}. +=== stdout: +{result.stdout.decode('utf-8')} + +=== stderr: +{result.stderr.decode('utf-8')} + +=== Args: +{args} + +""" + ) + + +def test_runfiles_integrated(): + project_rootdir = os.path.abspath(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + cwd = os.path.join(project_rootdir, "tests_runfiles", "samples_integrated") + runfiles = os.path.join(project_rootdir, "runfiles.py") + assert os.path.exists(cwd), f"{cwd} does not exist." + env = {"PYDEV_RUNFILES_FILTER_TESTS": json.dumps({})} + completed = python_run(["-Xfrozen_modules=off", runfiles, cwd], returncode=0, cwd=cwd, env=env) + print(completed.stdout.decode("utf-8")) + print(completed.stderr.decode("utf-8"))