robotcode-debugger 2.8.0.dev548__tar.gz → 2.8.0.dev670__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/PKG-INFO +3 -3
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/pyproject.toml +2 -2
- robotcode_debugger-2.8.0.dev670/src/robotcode/debugger/__version__.py +1 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/launcher/server.py +40 -5
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/listeners.py +24 -13
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/server.py +5 -0
- robotcode_debugger-2.8.0.dev548/src/robotcode/debugger/__version__.py +0 -1
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/.gitignore +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/README.md +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/__init__.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/cli.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/dap_types.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/debugger.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/default_capabilities.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/hooks.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/id_manager.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/launcher/__init__.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/launcher/cli.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/launcher/client.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/launcher/run.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/mixins.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/protocol.py +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/py.typed +0 -0
- {robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/run.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: robotcode-debugger
|
|
3
|
-
Version: 2.8.0-dev.
|
|
3
|
+
Version: 2.8.0-dev.670
|
|
4
4
|
Summary: RobotCode Debugger for Robot Framework
|
|
5
5
|
Project-URL: Homepage, https://robotcode.io
|
|
6
6
|
Project-URL: Donate, https://opencollective.com/robotcode
|
|
@@ -26,8 +26,8 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
|
26
26
|
Classifier: Topic :: Utilities
|
|
27
27
|
Classifier: Typing :: Typed
|
|
28
28
|
Requires-Python: >=3.10
|
|
29
|
-
Requires-Dist: robotcode-jsonrpc2==2.8.0-dev.
|
|
30
|
-
Requires-Dist: robotcode-runner==2.8.0-dev.
|
|
29
|
+
Requires-Dist: robotcode-jsonrpc2==2.8.0-dev.670
|
|
30
|
+
Requires-Dist: robotcode-runner==2.8.0-dev.670
|
|
31
31
|
Requires-Dist: robotframework>=5.0.0
|
|
32
32
|
Provides-Extra: debugpy
|
|
33
33
|
Requires-Dist: debugpy; extra == 'debugpy'
|
|
@@ -30,8 +30,8 @@ classifiers = [
|
|
|
30
30
|
dynamic = ["version"]
|
|
31
31
|
dependencies = [
|
|
32
32
|
"robotframework>=5.0.0",
|
|
33
|
-
"robotcode-jsonrpc2==2.8.0-dev.
|
|
34
|
-
"robotcode-runner==2.8.0-dev.
|
|
33
|
+
"robotcode-jsonrpc2==2.8.0-dev.670",
|
|
34
|
+
"robotcode-runner==2.8.0-dev.670",
|
|
35
35
|
]
|
|
36
36
|
|
|
37
37
|
[project.optional-dependencies]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.8.0-dev.670"
|
|
@@ -6,7 +6,7 @@ import os
|
|
|
6
6
|
import shlex
|
|
7
7
|
import sys
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Any, Dict, List, Literal, Optional
|
|
9
|
+
from typing import Any, Dict, List, Literal, Mapping, Optional
|
|
10
10
|
|
|
11
11
|
from robotcode.core.types import ServerMode, TcpParams
|
|
12
12
|
from robotcode.core.utils.logging import LoggingDescriptor
|
|
@@ -70,6 +70,30 @@ def _build_robotcode_run_args(
|
|
|
70
70
|
]
|
|
71
71
|
|
|
72
72
|
|
|
73
|
+
Console = Literal["robotcodeTerminal", "internalConsole", "integratedTerminal", "externalTerminal"]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _console_for_client(console: Optional[Console], client_id: Optional[str]) -> Optional[Console]:
|
|
77
|
+
"""The console a run uses: RobotCode's own run terminal is part of its VS Code extension, so any other client
|
|
78
|
+
gets the integrated terminal instead."""
|
|
79
|
+
if console == "robotcodeTerminal" and client_id != "vscode":
|
|
80
|
+
return "integratedTerminal"
|
|
81
|
+
return console
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _merged_environment(
|
|
85
|
+
base: Mapping[str, str], env: Mapping[str, Optional[str]], windows: bool
|
|
86
|
+
) -> Dict[str, Optional[str]]:
|
|
87
|
+
"""The environment of a run: ``base`` with the variables of ``env``. On Windows, where a name means the same
|
|
88
|
+
variable in any case, a variable of ``env`` replaces the one of ``base`` whose name differs only in case, and of
|
|
89
|
+
two names in ``env`` that differ only in case, the last one stays."""
|
|
90
|
+
if windows:
|
|
91
|
+
last = {name.upper(): name for name in env}
|
|
92
|
+
env = {name: value for name, value in env.items() if last[name.upper()] == name}
|
|
93
|
+
base = {name: value for name, value in base.items() if name.upper() not in last}
|
|
94
|
+
return {**base, **env}
|
|
95
|
+
|
|
96
|
+
|
|
73
97
|
class OutputProtocol(asyncio.SubprocessProtocol):
|
|
74
98
|
def __init__(self, parent: LauncherDebugAdapterProtocol) -> None:
|
|
75
99
|
super().__init__()
|
|
@@ -136,7 +160,7 @@ class LauncherDebugAdapterProtocol(DebugAdapterProtocol):
|
|
|
136
160
|
paths: Optional[List[str]] = None,
|
|
137
161
|
args: Optional[List[str]] = None,
|
|
138
162
|
env: Optional[Dict[str, Optional[Any]]] = None,
|
|
139
|
-
console: Optional[
|
|
163
|
+
console: Optional[Console] = "integratedTerminal",
|
|
140
164
|
name: Optional[str] = None,
|
|
141
165
|
no_debug: Optional[bool] = None,
|
|
142
166
|
robotPythonPath: Optional[List[str]] = None, # noqa: N803
|
|
@@ -263,7 +287,19 @@ class LauncherDebugAdapterProtocol(DebugAdapterProtocol):
|
|
|
263
287
|
|
|
264
288
|
env = {k: ("" if v is None else str(v)) for k, v in env.items()} if env else {}
|
|
265
289
|
|
|
266
|
-
|
|
290
|
+
console = _console_for_client(
|
|
291
|
+
console, self._initialize_arguments.client_id if self._initialize_arguments is not None else None
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
if console == "robotcodeTerminal":
|
|
295
|
+
# RobotCode's VS Code extension runs it as the process of a terminal of its own, without a shell
|
|
296
|
+
await self.send_event_async(
|
|
297
|
+
Event(
|
|
298
|
+
event="runInRobotCodeTerminal",
|
|
299
|
+
body={"cwd": cwd, "args": [*robotcode_run_args, *run_args], "env": env, "title": name},
|
|
300
|
+
)
|
|
301
|
+
)
|
|
302
|
+
elif console in ["integratedTerminal", "externalTerminal"]:
|
|
267
303
|
await self.send_request_async(
|
|
268
304
|
RunInTerminalRequest(
|
|
269
305
|
arguments=RunInTerminalRequestArguments(
|
|
@@ -284,8 +320,7 @@ class LauncherDebugAdapterProtocol(DebugAdapterProtocol):
|
|
|
284
320
|
)
|
|
285
321
|
# time.sleep(1) # Give some time for the terminal to start
|
|
286
322
|
elif console is None or console == "internalConsole":
|
|
287
|
-
run_env
|
|
288
|
-
run_env.update(env)
|
|
323
|
+
run_env = _merged_environment(os.environ, env, sys.platform == "win32")
|
|
289
324
|
|
|
290
325
|
await asyncio.get_event_loop().subprocess_exec(
|
|
291
326
|
lambda: OutputProtocol(self), *robotcode_run_args, *run_args, cwd=cwd, env=run_env
|
|
@@ -66,6 +66,15 @@ def source_from_attributes(attributes: Dict[str, Any]) -> str:
|
|
|
66
66
|
return s or ""
|
|
67
67
|
|
|
68
68
|
|
|
69
|
+
def without_empty_lineno(attributes: Dict[str, Any]) -> Dict[str, Any]:
|
|
70
|
+
"""A copy of listener attributes with an empty line number as None. Up to Robot Framework 6.1, listeners get ""
|
|
71
|
+
for a test or keyword without one, as a custom parser or a pre-run modifier creates them."""
|
|
72
|
+
result = dict(attributes)
|
|
73
|
+
if result.get("lineno") == "":
|
|
74
|
+
result["lineno"] = None
|
|
75
|
+
return result
|
|
76
|
+
|
|
77
|
+
|
|
69
78
|
class ListenerV2:
|
|
70
79
|
ROBOT_LISTENER_API_VERSION = "2"
|
|
71
80
|
|
|
@@ -146,11 +155,11 @@ class ListenerV2:
|
|
|
146
155
|
type="test",
|
|
147
156
|
name=name,
|
|
148
157
|
id=f"{source_from_attributes(attributes)};{attributes.get('longname', '')};"
|
|
149
|
-
f"{attributes.get('lineno'
|
|
158
|
+
f"{attributes.get('lineno') or 0}",
|
|
150
159
|
parent_id=self.suite_id_stack[-1] if self.suite_id_stack else None,
|
|
151
|
-
attributes=
|
|
160
|
+
attributes=without_empty_lineno(attributes),
|
|
152
161
|
source=source_from_attributes(attributes) or None,
|
|
153
|
-
lineno=attributes.get("lineno"
|
|
162
|
+
lineno=attributes.get("lineno") or None,
|
|
154
163
|
),
|
|
155
164
|
),
|
|
156
165
|
)
|
|
@@ -172,13 +181,13 @@ class ListenerV2:
|
|
|
172
181
|
type="test",
|
|
173
182
|
name=name,
|
|
174
183
|
id=f"{source_from_attributes(attributes)};{attributes.get('longname', '')};"
|
|
175
|
-
f"{attributes.get('lineno'
|
|
184
|
+
f"{attributes.get('lineno') or 0}",
|
|
176
185
|
parent_id=self.suite_id_stack[-1] if self.suite_id_stack else None,
|
|
177
|
-
attributes=
|
|
186
|
+
attributes=without_empty_lineno(attributes),
|
|
178
187
|
failed_keywords=self.failed_keywords,
|
|
179
188
|
failures=self._failures(),
|
|
180
189
|
source=source_from_attributes(attributes) or None,
|
|
181
|
-
lineno=attributes.get("lineno"
|
|
190
|
+
lineno=attributes.get("lineno") or None,
|
|
182
191
|
),
|
|
183
192
|
),
|
|
184
193
|
)
|
|
@@ -310,7 +319,7 @@ class ListenerV2:
|
|
|
310
319
|
if self.failed_keywords is None:
|
|
311
320
|
self.failed_keywords = []
|
|
312
321
|
|
|
313
|
-
keyword = {"message": self.last_fail_message, **attributes}
|
|
322
|
+
keyword = {"message": self.last_fail_message, **without_empty_lineno(attributes)}
|
|
314
323
|
# it is the nearest failed keyword around those that ended since it started and have none yet
|
|
315
324
|
for inner in self.failed_keywords[: max(0, len(self.failed_keywords) - mark)]:
|
|
316
325
|
self.failed_keyword_parents.setdefault(id(inner), keyword)
|
|
@@ -356,7 +365,7 @@ class ListenerV2:
|
|
|
356
365
|
self.failure_logged[-1] = True
|
|
357
366
|
|
|
358
367
|
source = current_frame.source if current_frame else None
|
|
359
|
-
line = current_frame.line if current_frame else None
|
|
368
|
+
line = (current_frame.line or None) if current_frame else None
|
|
360
369
|
column = current_frame.column if current_frame else None
|
|
361
370
|
|
|
362
371
|
item_id = next(
|
|
@@ -365,7 +374,7 @@ class ListenerV2:
|
|
|
365
374
|
f"{normalized_path(Path(item.source)) if item.source is not None else ''};{item.longname}"
|
|
366
375
|
if item.type == "SUITE"
|
|
367
376
|
else f"{normalized_path(Path(item.source)) if item.source is not None else ''};"
|
|
368
|
-
f"{item.longname};{item.line}"
|
|
377
|
+
f"{item.longname};{item.line or 0}"
|
|
369
378
|
)
|
|
370
379
|
for item in Debugger.instance.full_stack_frames
|
|
371
380
|
if item.type in ["SUITE", "TEST"]
|
|
@@ -405,7 +414,7 @@ class ListenerV2:
|
|
|
405
414
|
current_frame = Debugger.instance.full_stack_frames[0] if Debugger.instance.full_stack_frames else None
|
|
406
415
|
|
|
407
416
|
source = current_frame.source if current_frame else None
|
|
408
|
-
line = current_frame.line if current_frame else None
|
|
417
|
+
line = (current_frame.line or None) if current_frame else None
|
|
409
418
|
column = current_frame.column if current_frame else None
|
|
410
419
|
|
|
411
420
|
item_id = next(
|
|
@@ -414,7 +423,7 @@ class ListenerV2:
|
|
|
414
423
|
f"{normalized_path(Path(item.source)) if item.source is not None else ''};{item.longname}"
|
|
415
424
|
if item.type == "SUITE"
|
|
416
425
|
else f"{normalized_path(Path(item.source)) if item.source is not None else ''};"
|
|
417
|
-
f"{item.longname};{item.line}"
|
|
426
|
+
f"{item.longname};{item.line or 0}"
|
|
418
427
|
)
|
|
419
428
|
for item in Debugger.instance.full_stack_frames
|
|
420
429
|
if item.type in ["SUITE", "TEST"]
|
|
@@ -498,7 +507,9 @@ class ListenerV3:
|
|
|
498
507
|
yield from enqueue(s)
|
|
499
508
|
return
|
|
500
509
|
|
|
501
|
-
yield (
|
|
510
|
+
yield (
|
|
511
|
+
f"{normalized_path(item.source) if item.source is not None else ''};{item.longname};{item.lineno or 0}"
|
|
512
|
+
)
|
|
502
513
|
|
|
503
514
|
if self._event_sended:
|
|
504
515
|
return
|
|
@@ -534,7 +545,7 @@ class ListenerV3:
|
|
|
534
545
|
id=f"{normalized_path(Path(result_item.source)) if result_item.source else ''};"
|
|
535
546
|
f"{result_item.longname or ''}"
|
|
536
547
|
+ (
|
|
537
|
-
f";{data_item.lineno if data_item is not None else 0}"
|
|
548
|
+
f";{(data_item.lineno if data_item is not None else None) or 0}"
|
|
538
549
|
if isinstance(result_item, result.TestCase)
|
|
539
550
|
else ""
|
|
540
551
|
),
|
{robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/server.py
RENAMED
|
@@ -210,6 +210,11 @@ class DebugAdapterServerProtocol(DebugAdapterProtocol):
|
|
|
210
210
|
*args: Any,
|
|
211
211
|
**kwargs: Any,
|
|
212
212
|
) -> None:
|
|
213
|
+
if self.exited:
|
|
214
|
+
# The run has ended and the process only waits for the client to disconnect. A signal would end it with
|
|
215
|
+
# the exit code of an interrupt and skip its exit handlers, such as those that close a library's browsers.
|
|
216
|
+
return
|
|
217
|
+
|
|
213
218
|
Debugger.instance.terminate()
|
|
214
219
|
|
|
215
220
|
if not restart and not self._sigint_signaled:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.8.0-dev.548"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/cli.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/hooks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/mixins.py
RENAMED
|
File without changes
|
|
File without changes
|
{robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/py.typed
RENAMED
|
File without changes
|
{robotcode_debugger-2.8.0.dev548 → robotcode_debugger-2.8.0.dev670}/src/robotcode/debugger/run.py
RENAMED
|
File without changes
|