Skip to content

Commit

Permalink
Updates to pydevd (runfiles).
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioz committed May 26, 2024
1 parent dca5870 commit d180402
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from _pydevd_bundle.pydevd_constants import * # @UnusedWildImport
import re
import time
import json


# =======================================================================================================================
Expand Down Expand Up @@ -228,6 +229,19 @@ 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:
loaded = json.loads(filter_tests_env_var)
include = loaded["include"]
for path, name in include:
existing = files_to_tests.get(path)
if not existing:
existing = files_to_tests[path] = []
existing.append(name)
# Note: at this point exclude or `*` is not handled.
# Clients need to do all the filtering on their side (could
# change to have `exclude` and support `*` entries).

if type([]) != type(dirs):
dirs = [dirs]

Expand Down Expand Up @@ -750,7 +764,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:
Expand Down
Original file line number Diff line number Diff line change
@@ -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
# =========================================================================
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

Expand All @@ -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()

Expand All @@ -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()

Expand All @@ -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

Expand All @@ -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
Expand All @@ -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()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions plugins/org.python.pydev.core/pysrc/pydevd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion plugins/org.python.pydev.core/pysrc/runfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def dotted(p):

curdir_abs = os.path.abspath(os.curdir)
while True:
if os.path.exists(os.path.join(curdir_abs, 'conftest.py')):
if os.path.exists(os.path.join(curdir_abs, "conftest.py")):
os.chdir(curdir_abs)
found_conftest = True
break
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import unittest


class MyTest(unittest.TestCase):

def test1(self):
print("--on-test-1")

def test2(self):
print("--on-test-2")
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
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}
"""
)


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")
test_in_root = os.path.join(cwd, "root", "test_in_root.py")

assert os.path.exists(cwd), f"{cwd} does not exist."
assert os.path.exists(runfiles), f"{runfiles} does not exist."
assert os.path.exists(test_in_root), f"{test_in_root} does not exist."
assert os.path.exists(project_rootdir), f"{project_rootdir} does not exist."


env_filter = {
"PYDEV_RUNFILES_FILTER_TESTS": json.dumps(
{
"include": [
[
test_in_root,
"MyTest.test1",
],
]
}
)
}


def test_runfiles_integrated():
use_env = {}
use_env.update(env_filter)
use_env["PYTHONPATH"] = cwd
completed = python_run(["-Xfrozen_modules=off", runfiles, cwd], returncode=0, cwd=cwd, additional_env=use_env)
# print(completed.stdout.decode("utf-8"))
# print(completed.stderr.decode("utf-8"))
output = completed.stdout.decode("utf-8")
assert "--on-test-1" in output
assert "--on-test-2" not in output
assert "--on-test-3" not in output
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
<properties>
<tycho-version>4.0.3</tycho-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<repository.id>eclipse-2023-12</repository.id>
<repository.id>eclipse-2024-03</repository.id>
<repository.url>https://download.eclipse.org/releases/2024-03/</repository.url>
</properties>
<prerequisites>
Expand Down

0 comments on commit d180402

Please sign in to comment.