Fix debug output and put wait back the way it was

This commit is contained in:
Rich Chiodo false 2024-07-24 17:34:23 -07:00
parent 4d609d2683
commit fddf0de4fb
10 changed files with 49 additions and 29 deletions

View file

@ -65,7 +65,7 @@ On Linux or macOS:
```
.../debugpy$ python3 -m tox
```
This will perform a full run with the default settings. A full run will run tests on Python 2.7 and 3.5-3.8, and requires all of those to be installed. If some versions are missing, or it is desired to skip them for a particular run, tox can be directed to only run tests on specific versions with `-e`. In addition, the `--developer` option can be used to skip the packaging step, running tests directly against the source code in `src/debugpy`. This should only be used when iterating on the code, and a proper run should be performed before submitting a PR. On Windows:
This will perform a full run with the default settings. A full run will run tests on Python 2.7 and 3.5-3.8, and requires all of those to be installed. If some versions are missing, or it is desired to skip them for a particular run, tox can be directed to only run tests on specific versions with `-e`. In addition, the `--develop` option can be used to skip the packaging step, running tests directly against the source code in `src/debugpy`. This should only be used when iterating on the code, and a proper run should be performed before submitting a PR. On Windows:
```
...\debugpy> py -m tox -e py27,py37 --develop
```

View file

@ -22,6 +22,7 @@ executionEnvironments = [
{ root = "src" }, { root = "." }
]
typeCheckingMode = "standard"
enableTypeIgnoreComments = false
[tool.ruff]
# Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default.

View file

@ -19,8 +19,6 @@ from debugpy.adapter import components, sessions
import traceback
import io
from debugpy.common.util import WaitForTimeout
access_token = None
"""Access token used to authenticate with the servers."""
@ -431,11 +429,14 @@ def wait_for_connection(session, predicate, timeout: Union[float, None]=None):
If there is more than one server connection already available, returns the oldest
one.
"""
def after_wait():
def wait_for_timeout():
if timeout is not None:
time.sleep(timeout)
wait_for_timeout.timed_out = True # pyright: ignore[reportFunctionMemberAccess]
with _lock:
_connections_changed.set()
wait_for_timeout = WaitForTimeout(timeout, after_wait)
wait_for_timeout.timed_out = timeout == 0 # pyright: ignore[reportFunctionMemberAccess]
if timeout:
thread = threading.Thread(
target=wait_for_timeout, name="servers.wait_for_connection() timeout"
@ -450,7 +451,7 @@ def wait_for_connection(session, predicate, timeout: Union[float, None]=None):
_connections_changed.clear()
conns = (conn for conn in _connections if predicate(conn))
conn = next(conns, None)
if conn is not None or wait_for_timeout.timed_out:
if conn is not None or wait_for_timeout.timed_out: # pyright: ignore[reportFunctionMemberAccess]
return conn
_connections_changed.wait()

View file

@ -6,6 +6,7 @@ import itertools
import os
import signal
import threading
import time
from typing import Union
from debugpy import common
@ -112,8 +113,14 @@ class Session(util.Observable):
seconds regardless of whether the predicate was satisfied. The method returns
False if it timed out, and True otherwise.
"""
wait_for_timeout = util.WaitForTimeout(timeout, lambda: self.notify_changed())
def wait_for_timeout():
if timeout is not None:
time.sleep(timeout)
wait_for_timeout.timed_out = True # pyright: ignore[reportFunctionMemberAccess]
self.notify_changed()
wait_for_timeout.timed_out = False # pyright: ignore[reportFunctionMemberAccess]
if timeout is not None:
thread = threading.Thread(
target=wait_for_timeout, name="Session.wait_for() timeout"
@ -123,7 +130,7 @@ class Session(util.Observable):
with self:
while not predicate():
if wait_for_timeout.timed_out:
if wait_for_timeout.timed_out: # pyright: ignore[reportFunctionMemberAccess]
return False
self._changed_condition.wait()
return True

View file

@ -12,8 +12,12 @@ import platform
import sys
import threading
import traceback
from typing import Any, NoReturn, Protocol, Union
from typing_extensions import TypeIs
from typing import TYPE_CHECKING, Any, NoReturn, Protocol, Union
if TYPE_CHECKING:
# Careful not force this import in production code, as it's not available in all
# code that we run.
from typing_extensions import TypeIs
import debugpy
from debugpy.common import json, timestamp, util
@ -283,7 +287,7 @@ def prefixed(format_string, *args, **kwargs):
class HasName(Protocol):
name: str
def has_name(obj: Any) -> TypeIs[HasName]:
def has_name(obj: Any) -> "TypeIs[HasName]":
try:
return hasattr(obj, "name")
except NameError:

View file

@ -20,8 +20,11 @@ import os
import socket
import sys
import threading
from typing import BinaryIO, Callable, Union, cast, Any
from typing_extensions import TypeIs
from typing import TYPE_CHECKING, BinaryIO, Callable, Union, cast, Any
if TYPE_CHECKING:
# Careful not force this import in production code, as it's not available in all
# code that we run.
from typing_extensions import TypeIs
from debugpy.common import json, log, util
from debugpy.common.util import hide_thread_from_debugger
@ -429,7 +432,7 @@ class AssociableMessageDict(MessageDict):
def associate_with(self, message: Message):
self.message = message
def is_associable(obj) -> TypeIs[AssociableMessageDict]:
def is_associable(obj) -> "TypeIs[AssociableMessageDict]":
return isinstance(obj, MessageDict) and hasattr(obj, "associate_with")
def _payload(value):

View file

@ -165,14 +165,3 @@ def hide_thread_from_debugger(thread):
thread.pydev_do_not_trace = True
thread.is_pydev_daemon_thread = True
class WaitForTimeout():
def __init__(self, timeout: Union[float, None], func: Callable[[], None]):
self._func = func
self._timeout = timeout
self.timed_out = False
def __call__(self):
if self._timeout is not None:
time.sleep(self._timeout)
self.timed_out = True
self._func()

View file

@ -4,12 +4,27 @@
import io
import os
import shutil
import pytest_timeout
import sys
from debugpy.common import json, log
def write_title(title, stream=None, sep="~"):
"""Write a section title.
If *stream* is None sys.stderr will be used, *sep* is used to
draw the line.
"""
if stream is None:
stream = sys.stderr
width, height = shutil.get_terminal_size()
fill = int((width - len(title) - 2) / 2)
line = " ".join([sep * fill, title, sep * fill])
if len(line) < width:
line += sep * (width - len(line))
stream.write("\n" + line + "\n")
def dump():
if log.log_dir is None:
return
@ -27,5 +42,5 @@ def dump():
pass
else:
path = os.path.relpath(path, log.log_dir)
pytest_timeout.write_title(path)
write_title(path)
print(s, file=sys.stderr)

View file

@ -7,7 +7,7 @@ import pytest
import pytest_timeout
import sys
from debugpy.common import log
from debugpy.common import log # pyright: ignore[reportAttributeAccessIssue]
import tests
from tests import logs
@ -56,9 +56,8 @@ def pytest_runtest_makereport(item, call):
def pytest_make_parametrize_id(config, val):
return getattr(val, "pytest_id", None)
# If a test times out and pytest tries to print the stacks of where it was hanging,
# we want to print the pydevd log as well. This is not a normal pytest hook - we
# just detour pytest_timeout.dump_stacks directly.
_dump_stacks = pytest_timeout.dump_stacks
pytest_timeout.dump_stacks = lambda: (_dump_stacks(), logs.dump())
pytest_timeout.dump_stacks = lambda terminal: (_dump_stacks(terminal), logs.dump())

View file

@ -19,3 +19,4 @@ flask
gevent
numpy
requests
typing_extensions