mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Fix debug output and put wait back the way it was
This commit is contained in:
parent
4d609d2683
commit
fddf0de4fb
10 changed files with 49 additions and 29 deletions
|
|
@ -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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ executionEnvironments = [
|
|||
{ root = "src" }, { root = "." }
|
||||
]
|
||||
typeCheckingMode = "standard"
|
||||
enableTypeIgnoreComments = false
|
||||
|
||||
[tool.ruff]
|
||||
# Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default.
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -19,3 +19,4 @@ flask
|
|||
gevent
|
||||
numpy
|
||||
requests
|
||||
typing_extensions
|
||||
Loading…
Add table
Add a link
Reference in a new issue