robotcode-debugger 0.105.0__tar.gz → 0.106.0__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-0.105.0 → robotcode_debugger-0.106.0}/PKG-INFO +3 -3
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/pyproject.toml +2 -2
- robotcode_debugger-0.106.0/src/robotcode/debugger/__version__.py +1 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/dap_types.py +3 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/debugger.py +78 -30
- robotcode_debugger-0.106.0/src/robotcode/debugger/default_capabilities.py +48 -0
- robotcode_debugger-0.106.0/src/robotcode/debugger/id_manager.py +64 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/server.py +2 -44
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/listeners.py +19 -3
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/server.py +3 -45
- robotcode_debugger-0.105.0/src/robotcode/debugger/__version__.py +0 -1
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/.gitignore +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/LICENSE.txt +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/README.md +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/__init__.py +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/cli.py +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/hooks.py +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/__init__.py +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/cli.py +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/client.py +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/run.py +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/protocol.py +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/py.typed +0 -0
- {robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/run.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: robotcode-debugger
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.106.0
|
|
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
|
|
@@ -25,8 +25,8 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
|
25
25
|
Classifier: Topic :: Utilities
|
|
26
26
|
Classifier: Typing :: Typed
|
|
27
27
|
Requires-Python: >=3.8
|
|
28
|
-
Requires-Dist: robotcode-jsonrpc2==0.
|
|
29
|
-
Requires-Dist: robotcode-runner==0.
|
|
28
|
+
Requires-Dist: robotcode-jsonrpc2==0.106.0
|
|
29
|
+
Requires-Dist: robotcode-runner==0.106.0
|
|
30
30
|
Requires-Dist: robotframework>=4.1.0
|
|
31
31
|
Provides-Extra: debugpy
|
|
32
32
|
Requires-Dist: debugpy; extra == 'debugpy'
|
|
@@ -28,8 +28,8 @@ classifiers = [
|
|
|
28
28
|
dynamic = ["version"]
|
|
29
29
|
dependencies = [
|
|
30
30
|
"robotframework>=4.1.0",
|
|
31
|
-
"robotcode-jsonrpc2==0.
|
|
32
|
-
"robotcode-runner==0.
|
|
31
|
+
"robotcode-jsonrpc2==0.106.0",
|
|
32
|
+
"robotcode-runner==0.106.0",
|
|
33
33
|
]
|
|
34
34
|
|
|
35
35
|
[project.optional-dependencies]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.106.0"
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/dap_types.py
RENAMED
|
@@ -523,6 +523,9 @@ class SourceBreakpoint(Model):
|
|
|
523
523
|
hit_condition: Optional[str] = None
|
|
524
524
|
log_message: Optional[str] = None
|
|
525
525
|
|
|
526
|
+
def __hash__(self) -> int:
|
|
527
|
+
return hash((self.line, self.column, self.condition, self.hit_condition, self.log_message))
|
|
528
|
+
|
|
526
529
|
|
|
527
530
|
@dataclass
|
|
528
531
|
class SetBreakpointsArguments(Model):
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/debugger.py
RENAMED
|
@@ -8,6 +8,7 @@ import time
|
|
|
8
8
|
import weakref
|
|
9
9
|
from collections import deque
|
|
10
10
|
from enum import Enum
|
|
11
|
+
from functools import cached_property
|
|
11
12
|
from pathlib import Path, PurePath
|
|
12
13
|
from typing import (
|
|
13
14
|
Any,
|
|
@@ -25,6 +26,7 @@ from typing import (
|
|
|
25
26
|
Sequence,
|
|
26
27
|
Set,
|
|
27
28
|
Tuple,
|
|
29
|
+
TypedDict,
|
|
28
30
|
Union,
|
|
29
31
|
cast,
|
|
30
32
|
)
|
|
@@ -67,6 +69,7 @@ from .dap_types import (
|
|
|
67
69
|
Variable,
|
|
68
70
|
VariablePresentationHint,
|
|
69
71
|
)
|
|
72
|
+
from .id_manager import IdManager
|
|
70
73
|
|
|
71
74
|
if get_robot_version() >= (7, 0):
|
|
72
75
|
from robot.running import UserKeyword as UserKeywordHandler
|
|
@@ -163,6 +166,10 @@ class InvalidThreadIdError(Exception):
|
|
|
163
166
|
super().__init__(f"Invalid thread id {thread_id}")
|
|
164
167
|
|
|
165
168
|
|
|
169
|
+
class MarkerObject:
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
|
|
166
173
|
class StackFrameEntry:
|
|
167
174
|
def __init__(
|
|
168
175
|
self,
|
|
@@ -193,10 +200,10 @@ class StackFrameEntry:
|
|
|
193
200
|
self.libname = libname
|
|
194
201
|
self.kwname = kwname
|
|
195
202
|
self.longname = longname
|
|
196
|
-
self._suite_marker =
|
|
197
|
-
self._test_marker =
|
|
198
|
-
self._local_marker =
|
|
199
|
-
self._global_marker =
|
|
203
|
+
self._suite_marker = MarkerObject()
|
|
204
|
+
self._test_marker = MarkerObject()
|
|
205
|
+
self._local_marker = MarkerObject()
|
|
206
|
+
self._global_marker = MarkerObject()
|
|
200
207
|
self.stack_frames: Deque[StackFrameEntry] = deque()
|
|
201
208
|
|
|
202
209
|
def __repr__(self) -> str:
|
|
@@ -207,21 +214,27 @@ class StackFrameEntry:
|
|
|
207
214
|
return self.stack_frames[0]
|
|
208
215
|
return self
|
|
209
216
|
|
|
210
|
-
|
|
217
|
+
_id_manager = IdManager()
|
|
218
|
+
|
|
219
|
+
@cached_property
|
|
211
220
|
def id(self) -> int:
|
|
212
|
-
return
|
|
221
|
+
return self._id_manager.get_id(self)
|
|
213
222
|
|
|
223
|
+
@cached_property
|
|
214
224
|
def test_id(self) -> int:
|
|
215
|
-
return
|
|
225
|
+
return self._id_manager.get_id(self._test_marker)
|
|
216
226
|
|
|
227
|
+
@cached_property
|
|
217
228
|
def suite_id(self) -> int:
|
|
218
|
-
return
|
|
229
|
+
return self._id_manager.get_id(self._suite_marker)
|
|
219
230
|
|
|
231
|
+
@cached_property
|
|
220
232
|
def local_id(self) -> int:
|
|
221
|
-
return
|
|
233
|
+
return self._id_manager.get_id(self._local_marker)
|
|
222
234
|
|
|
235
|
+
@cached_property
|
|
223
236
|
def global_id(self) -> int:
|
|
224
|
-
return
|
|
237
|
+
return self._id_manager.get_id(self._global_marker)
|
|
225
238
|
|
|
226
239
|
|
|
227
240
|
class HitCountEntry(NamedTuple):
|
|
@@ -268,6 +281,15 @@ else:
|
|
|
268
281
|
self.steps.pop()
|
|
269
282
|
|
|
270
283
|
|
|
284
|
+
breakpoint_id_manager = IdManager()
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class ExceptionInformation(TypedDict):
|
|
288
|
+
text: Optional[str]
|
|
289
|
+
description: str
|
|
290
|
+
status: str
|
|
291
|
+
|
|
292
|
+
|
|
271
293
|
class Debugger:
|
|
272
294
|
__instance: ClassVar[Optional["Debugger"]] = None
|
|
273
295
|
__lock: ClassVar = threading.RLock()
|
|
@@ -341,6 +363,7 @@ class Debugger:
|
|
|
341
363
|
self._evaluate_cache: List[Any] = []
|
|
342
364
|
self._variables_cache: Dict[int, Any] = {}
|
|
343
365
|
self._variables_object_cache: List[Any] = []
|
|
366
|
+
self._current_exception: Optional[ExceptionInformation] = None
|
|
344
367
|
|
|
345
368
|
@property
|
|
346
369
|
def state(self) -> State:
|
|
@@ -432,7 +455,8 @@ class Debugger:
|
|
|
432
455
|
self.condition.notify_all()
|
|
433
456
|
|
|
434
457
|
def pause_thread(self, thread_id: int) -> None:
|
|
435
|
-
|
|
458
|
+
# thread_id 0 means all threads
|
|
459
|
+
if self.main_thread is None or (thread_id != 0 and thread_id != self.main_thread.ident):
|
|
436
460
|
raise InvalidThreadIdError(thread_id)
|
|
437
461
|
|
|
438
462
|
with self.condition:
|
|
@@ -521,6 +545,7 @@ class Debugger:
|
|
|
521
545
|
lines: Optional[List[int]] = None,
|
|
522
546
|
source_modified: Optional[bool] = None,
|
|
523
547
|
) -> List[Breakpoint]:
|
|
548
|
+
|
|
524
549
|
if self.is_windows_path(source.path or ""):
|
|
525
550
|
path: pathlib.PurePath = pathlib.PureWindowsPath(source.path or "")
|
|
526
551
|
else:
|
|
@@ -535,7 +560,7 @@ class Debugger:
|
|
|
535
560
|
)
|
|
536
561
|
return [
|
|
537
562
|
Breakpoint(
|
|
538
|
-
id=
|
|
563
|
+
id=breakpoint_id_manager.get_id(v),
|
|
539
564
|
source=Source(path=str(path)),
|
|
540
565
|
verified=True,
|
|
541
566
|
line=v.line,
|
|
@@ -559,6 +584,7 @@ class Debugger:
|
|
|
559
584
|
self,
|
|
560
585
|
StoppedEvent(
|
|
561
586
|
body=StoppedEventBody(
|
|
587
|
+
description="Paused",
|
|
562
588
|
reason=StoppedReason.PAUSE,
|
|
563
589
|
thread_id=threading.current_thread().ident,
|
|
564
590
|
)
|
|
@@ -574,6 +600,7 @@ class Debugger:
|
|
|
574
600
|
self,
|
|
575
601
|
StoppedEvent(
|
|
576
602
|
body=StoppedEventBody(
|
|
603
|
+
description="Next step",
|
|
577
604
|
reason=StoppedReason.STEP,
|
|
578
605
|
thread_id=threading.current_thread().ident,
|
|
579
606
|
)
|
|
@@ -588,6 +615,7 @@ class Debugger:
|
|
|
588
615
|
self,
|
|
589
616
|
StoppedEvent(
|
|
590
617
|
body=StoppedEventBody(
|
|
618
|
+
description="Step in",
|
|
591
619
|
reason=StoppedReason.STEP,
|
|
592
620
|
thread_id=threading.current_thread().ident,
|
|
593
621
|
)
|
|
@@ -602,6 +630,7 @@ class Debugger:
|
|
|
602
630
|
self,
|
|
603
631
|
StoppedEvent(
|
|
604
632
|
body=StoppedEventBody(
|
|
633
|
+
description="Step out",
|
|
605
634
|
reason=StoppedReason.STEP,
|
|
606
635
|
thread_id=threading.current_thread().ident,
|
|
607
636
|
)
|
|
@@ -613,6 +642,7 @@ class Debugger:
|
|
|
613
642
|
if source_path in self.breakpoints:
|
|
614
643
|
breakpoints = [v for v in self.breakpoints[source_path].breakpoints if v.line == line_no]
|
|
615
644
|
if len(breakpoints) > 0:
|
|
645
|
+
|
|
616
646
|
for point in breakpoints:
|
|
617
647
|
if point.condition is not None:
|
|
618
648
|
hit = False
|
|
@@ -673,9 +703,10 @@ class Debugger:
|
|
|
673
703
|
self,
|
|
674
704
|
StoppedEvent(
|
|
675
705
|
body=StoppedEventBody(
|
|
706
|
+
description="Breakpoint hit",
|
|
676
707
|
reason=StoppedReason.BREAKPOINT,
|
|
677
708
|
thread_id=threading.current_thread().ident,
|
|
678
|
-
hit_breakpoint_ids=[
|
|
709
|
+
hit_breakpoint_ids=[breakpoint_id_manager.get_id(v) for v in breakpoints],
|
|
679
710
|
)
|
|
680
711
|
),
|
|
681
712
|
)
|
|
@@ -704,6 +735,8 @@ class Debugger:
|
|
|
704
735
|
self.requested_state = RequestedState.Nothing
|
|
705
736
|
self.state = State.Paused
|
|
706
737
|
|
|
738
|
+
self._current_exception = {"text": text, "description": description, "status": status}
|
|
739
|
+
|
|
707
740
|
self.send_event(
|
|
708
741
|
self,
|
|
709
742
|
StoppedEvent(
|
|
@@ -757,6 +790,7 @@ class Debugger:
|
|
|
757
790
|
continue
|
|
758
791
|
|
|
759
792
|
break
|
|
793
|
+
self._current_exception = None
|
|
760
794
|
|
|
761
795
|
def start_output_group(self, name: str, attributes: Dict[str, Any], type: Optional[str] = None) -> None:
|
|
762
796
|
if self.group_output:
|
|
@@ -971,7 +1005,7 @@ class Debugger:
|
|
|
971
1005
|
if status == "FAIL":
|
|
972
1006
|
self.process_end_state(
|
|
973
1007
|
status,
|
|
974
|
-
{"
|
|
1008
|
+
{""},
|
|
975
1009
|
"Test failed.",
|
|
976
1010
|
f"Test failed{f': {v}' if (v := attributes.get('message')) else ''}",
|
|
977
1011
|
)
|
|
@@ -1136,7 +1170,7 @@ class Debugger:
|
|
|
1136
1170
|
{"uncaught_failed_keyword"}
|
|
1137
1171
|
if self.is_not_caughted_by_keyword()
|
|
1138
1172
|
and self.is_not_caugthed_by_except(self.last_fail_message)
|
|
1139
|
-
else
|
|
1173
|
+
else []
|
|
1140
1174
|
),
|
|
1141
1175
|
},
|
|
1142
1176
|
"Keyword failed.",
|
|
@@ -1346,7 +1380,7 @@ class Debugger:
|
|
|
1346
1380
|
name="Local",
|
|
1347
1381
|
expensive=False,
|
|
1348
1382
|
presentation_hint="local",
|
|
1349
|
-
variables_reference=entry.local_id
|
|
1383
|
+
variables_reference=entry.local_id,
|
|
1350
1384
|
)
|
|
1351
1385
|
)
|
|
1352
1386
|
if context.variables._test is not None and entry.type == "KEYWORD":
|
|
@@ -1355,7 +1389,7 @@ class Debugger:
|
|
|
1355
1389
|
name="Test",
|
|
1356
1390
|
expensive=False,
|
|
1357
1391
|
presentation_hint="test",
|
|
1358
|
-
variables_reference=entry.test_id
|
|
1392
|
+
variables_reference=entry.test_id,
|
|
1359
1393
|
)
|
|
1360
1394
|
)
|
|
1361
1395
|
if context.variables._suite is not None and entry.type in [
|
|
@@ -1367,7 +1401,7 @@ class Debugger:
|
|
|
1367
1401
|
name="Suite",
|
|
1368
1402
|
expensive=False,
|
|
1369
1403
|
presentation_hint="suite",
|
|
1370
|
-
variables_reference=entry.suite_id
|
|
1404
|
+
variables_reference=entry.suite_id,
|
|
1371
1405
|
)
|
|
1372
1406
|
)
|
|
1373
1407
|
if context.variables._global is not None:
|
|
@@ -1376,20 +1410,24 @@ class Debugger:
|
|
|
1376
1410
|
name="Global",
|
|
1377
1411
|
expensive=False,
|
|
1378
1412
|
presentation_hint="global",
|
|
1379
|
-
variables_reference=entry.global_id
|
|
1413
|
+
variables_reference=entry.global_id,
|
|
1380
1414
|
)
|
|
1381
1415
|
)
|
|
1382
1416
|
|
|
1383
1417
|
return result
|
|
1384
1418
|
|
|
1419
|
+
_cache_id_manager = IdManager()
|
|
1420
|
+
|
|
1385
1421
|
def _new_cache_id(self) -> int:
|
|
1386
|
-
o =
|
|
1422
|
+
o = MarkerObject()
|
|
1387
1423
|
self._variables_object_cache.append(o)
|
|
1388
|
-
return
|
|
1424
|
+
return StackFrameEntry._id_manager.get_id(o)
|
|
1389
1425
|
|
|
1390
1426
|
debug_repr = DebugRepr()
|
|
1391
1427
|
|
|
1392
|
-
def _create_variable(
|
|
1428
|
+
def _create_variable(
|
|
1429
|
+
self, name: str, value: Any, presentation_hint: Optional[VariablePresentationHint] = None
|
|
1430
|
+
) -> Variable:
|
|
1393
1431
|
if isinstance(value, Mapping):
|
|
1394
1432
|
v_id = self._new_cache_id()
|
|
1395
1433
|
self._variables_cache[v_id] = value
|
|
@@ -1400,7 +1438,9 @@ class Debugger:
|
|
|
1400
1438
|
variables_reference=v_id,
|
|
1401
1439
|
named_variables=len(value) + 1,
|
|
1402
1440
|
indexed_variables=0,
|
|
1403
|
-
presentation_hint=
|
|
1441
|
+
presentation_hint=(
|
|
1442
|
+
presentation_hint if presentation_hint is not None else VariablePresentationHint(kind="data")
|
|
1443
|
+
),
|
|
1404
1444
|
)
|
|
1405
1445
|
|
|
1406
1446
|
if isinstance(value, Sequence) and not isinstance(value, str):
|
|
@@ -1443,18 +1483,18 @@ class Debugger:
|
|
|
1443
1483
|
(
|
|
1444
1484
|
v
|
|
1445
1485
|
for v in self.stack_frames
|
|
1446
|
-
if variables_reference in [v.global_id
|
|
1486
|
+
if variables_reference in [v.global_id, v.suite_id, v.test_id, v.local_id]
|
|
1447
1487
|
),
|
|
1448
1488
|
None,
|
|
1449
1489
|
)
|
|
1450
1490
|
if entry is not None:
|
|
1451
1491
|
context = entry.context()
|
|
1452
1492
|
if context is not None:
|
|
1453
|
-
if entry.global_id
|
|
1493
|
+
if entry.global_id == variables_reference:
|
|
1454
1494
|
result.update(
|
|
1455
1495
|
{k: self._create_variable(k, v) for k, v in context.variables._global.as_dict().items()}
|
|
1456
1496
|
)
|
|
1457
|
-
elif entry.suite_id
|
|
1497
|
+
elif entry.suite_id == variables_reference:
|
|
1458
1498
|
globals = context.variables._global.as_dict()
|
|
1459
1499
|
vars = entry.get_first_or_self().variables()
|
|
1460
1500
|
vars_dict = vars.as_dict() if vars is not None else {}
|
|
@@ -1465,7 +1505,7 @@ class Debugger:
|
|
|
1465
1505
|
if (k not in globals or globals[k] != v) and (k in vars_dict)
|
|
1466
1506
|
}
|
|
1467
1507
|
)
|
|
1468
|
-
elif entry.test_id
|
|
1508
|
+
elif entry.test_id == variables_reference:
|
|
1469
1509
|
globals = context.variables._suite.as_dict()
|
|
1470
1510
|
vars = entry.get_first_or_self().variables()
|
|
1471
1511
|
vars_dict = vars.as_dict() if vars is not None else {}
|
|
@@ -1476,8 +1516,16 @@ class Debugger:
|
|
|
1476
1516
|
if (k not in globals or globals[k] != v) and (k in vars_dict)
|
|
1477
1517
|
}
|
|
1478
1518
|
)
|
|
1479
|
-
elif entry.local_id
|
|
1519
|
+
elif entry.local_id == variables_reference:
|
|
1480
1520
|
vars = entry.get_first_or_self().variables()
|
|
1521
|
+
|
|
1522
|
+
if self._current_exception is not None:
|
|
1523
|
+
result["${EXCEPTION}"] = self._create_variable(
|
|
1524
|
+
"${EXCEPTION}",
|
|
1525
|
+
self._current_exception,
|
|
1526
|
+
VariablePresentationHint(kind="virtual"),
|
|
1527
|
+
)
|
|
1528
|
+
|
|
1481
1529
|
if vars is not None:
|
|
1482
1530
|
p = entry.parent() if entry.parent else None
|
|
1483
1531
|
|
|
@@ -1821,7 +1869,7 @@ class Debugger:
|
|
|
1821
1869
|
(
|
|
1822
1870
|
v
|
|
1823
1871
|
for v in self.full_stack_frames
|
|
1824
|
-
if variables_reference in [v.global_id
|
|
1872
|
+
if variables_reference in [v.global_id, v.local_id, v.suite_id, v.test_id]
|
|
1825
1873
|
),
|
|
1826
1874
|
None,
|
|
1827
1875
|
)
|
|
@@ -1856,7 +1904,7 @@ class Debugger:
|
|
|
1856
1904
|
if option.filter_id in [
|
|
1857
1905
|
"failed_keyword",
|
|
1858
1906
|
"uncaught_failed_keyword",
|
|
1859
|
-
"
|
|
1907
|
+
"",
|
|
1860
1908
|
"failed_suite",
|
|
1861
1909
|
]:
|
|
1862
1910
|
entry = ExceptionBreakpointsEntry(
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from .dap_types import Capabilities, ExceptionBreakpointsFilter
|
|
2
|
+
|
|
3
|
+
DFEAULT_CAPABILITIES = Capabilities(
|
|
4
|
+
supports_configuration_done_request=True,
|
|
5
|
+
supports_conditional_breakpoints=True,
|
|
6
|
+
supports_hit_conditional_breakpoints=True,
|
|
7
|
+
support_terminate_debuggee=True,
|
|
8
|
+
supports_evaluate_for_hovers=True,
|
|
9
|
+
supports_terminate_request=True,
|
|
10
|
+
supports_log_points=True,
|
|
11
|
+
supports_set_expression=True,
|
|
12
|
+
supports_set_variable=True,
|
|
13
|
+
supports_value_formatting_options=True,
|
|
14
|
+
exception_breakpoint_filters=[
|
|
15
|
+
ExceptionBreakpointsFilter(
|
|
16
|
+
filter="failed_keyword",
|
|
17
|
+
label="Failed Keywords",
|
|
18
|
+
description="Breaks on failed keywords",
|
|
19
|
+
default=False,
|
|
20
|
+
supports_condition=True,
|
|
21
|
+
),
|
|
22
|
+
ExceptionBreakpointsFilter(
|
|
23
|
+
filter="uncaught_failed_keyword",
|
|
24
|
+
label="Uncaught Failed Keywords",
|
|
25
|
+
description="Breaks on uncaught failed keywords",
|
|
26
|
+
default=True,
|
|
27
|
+
supports_condition=True,
|
|
28
|
+
),
|
|
29
|
+
ExceptionBreakpointsFilter(
|
|
30
|
+
filter="failed_test",
|
|
31
|
+
label="Failed Test",
|
|
32
|
+
description="Breaks on failed tests",
|
|
33
|
+
default=False,
|
|
34
|
+
supports_condition=True,
|
|
35
|
+
),
|
|
36
|
+
ExceptionBreakpointsFilter(
|
|
37
|
+
filter="failed_suite",
|
|
38
|
+
label="Failed Suite",
|
|
39
|
+
description="Breaks on failed suite",
|
|
40
|
+
default=False,
|
|
41
|
+
supports_condition=True,
|
|
42
|
+
),
|
|
43
|
+
],
|
|
44
|
+
supports_exception_options=True,
|
|
45
|
+
supports_exception_filter_options=True,
|
|
46
|
+
supports_completions_request=True,
|
|
47
|
+
supports_a_n_s_i_styling=True,
|
|
48
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import weakref
|
|
2
|
+
from collections import deque
|
|
3
|
+
from typing import Any, Deque, Dict, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class IdManager:
|
|
7
|
+
def __init__(self) -> None:
|
|
8
|
+
self.max_id: int = 2**31 - 1
|
|
9
|
+
self.next_id: int = 0
|
|
10
|
+
|
|
11
|
+
self.released_ids: Deque[int] = deque()
|
|
12
|
+
self.object_to_id: weakref.WeakKeyDictionary[Any, int] = weakref.WeakKeyDictionary()
|
|
13
|
+
self.id_to_object: weakref.WeakValueDictionary[int, Any] = weakref.WeakValueDictionary()
|
|
14
|
+
self._finalizers: Dict[int, weakref.ref[Any]] = {}
|
|
15
|
+
|
|
16
|
+
def get_id(self, obj: Any) -> int:
|
|
17
|
+
if obj in self.object_to_id:
|
|
18
|
+
return self.object_to_id[obj]
|
|
19
|
+
|
|
20
|
+
if self.released_ids:
|
|
21
|
+
obj_id: int = self.released_ids.popleft()
|
|
22
|
+
else:
|
|
23
|
+
if self.next_id > self.max_id:
|
|
24
|
+
raise RuntimeError("Keine IDs mehr verfügbar!")
|
|
25
|
+
obj_id = self.next_id
|
|
26
|
+
self.next_id += 1
|
|
27
|
+
|
|
28
|
+
self.object_to_id[obj] = obj_id
|
|
29
|
+
self.id_to_object[obj_id] = obj
|
|
30
|
+
|
|
31
|
+
def _on_object_gc(ref: "weakref.ReferenceType[Any]", id_: int = obj_id) -> None:
|
|
32
|
+
self.release_id(id_)
|
|
33
|
+
|
|
34
|
+
ref = weakref.ref(obj, _on_object_gc)
|
|
35
|
+
self._finalizers[obj_id] = ref
|
|
36
|
+
|
|
37
|
+
return obj_id
|
|
38
|
+
|
|
39
|
+
def release_id(self, obj_id: int) -> None:
|
|
40
|
+
if obj_id in self.id_to_object:
|
|
41
|
+
del self.id_to_object[obj_id]
|
|
42
|
+
|
|
43
|
+
if obj_id in self._finalizers:
|
|
44
|
+
del self._finalizers[obj_id]
|
|
45
|
+
|
|
46
|
+
self.released_ids.append(obj_id)
|
|
47
|
+
|
|
48
|
+
def release_obj(self, obj: Any) -> None:
|
|
49
|
+
if obj in self.object_to_id:
|
|
50
|
+
obj_id: int = self.object_to_id.pop(obj)
|
|
51
|
+
|
|
52
|
+
if obj_id in self.id_to_object:
|
|
53
|
+
del self.id_to_object[obj_id]
|
|
54
|
+
|
|
55
|
+
if obj_id in self._finalizers:
|
|
56
|
+
del self._finalizers[obj_id]
|
|
57
|
+
|
|
58
|
+
self.released_ids.append(obj_id)
|
|
59
|
+
|
|
60
|
+
def get_object(self, obj_id: int) -> Optional[Any]:
|
|
61
|
+
return self.id_to_object.get(obj_id)
|
|
62
|
+
|
|
63
|
+
def get_id_from_obj(self, obj: Any) -> Optional[int]:
|
|
64
|
+
return self.object_to_id.get(obj)
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/server.py
RENAMED
|
@@ -23,7 +23,6 @@ from ..dap_types import (
|
|
|
23
23
|
DisconnectArguments,
|
|
24
24
|
DisconnectRequest,
|
|
25
25
|
Event,
|
|
26
|
-
ExceptionBreakpointsFilter,
|
|
27
26
|
InitializeRequest,
|
|
28
27
|
InitializeRequestArguments,
|
|
29
28
|
LaunchRequestArguments,
|
|
@@ -39,6 +38,7 @@ from ..dap_types import (
|
|
|
39
38
|
TerminatedEvent,
|
|
40
39
|
TerminateRequest,
|
|
41
40
|
)
|
|
41
|
+
from ..default_capabilities import DFEAULT_CAPABILITIES
|
|
42
42
|
from ..protocol import DebugAdapterProtocol
|
|
43
43
|
from .client import DAPClient, DAPClientError
|
|
44
44
|
|
|
@@ -91,49 +91,7 @@ class LauncherDebugAdapterProtocol(DebugAdapterProtocol):
|
|
|
91
91
|
|
|
92
92
|
self._initialized = True
|
|
93
93
|
|
|
94
|
-
return
|
|
95
|
-
supports_configuration_done_request=True,
|
|
96
|
-
supports_conditional_breakpoints=True,
|
|
97
|
-
supports_hit_conditional_breakpoints=True,
|
|
98
|
-
support_terminate_debuggee=True,
|
|
99
|
-
# support_suspend_debuggee=True,
|
|
100
|
-
supports_evaluate_for_hovers=True,
|
|
101
|
-
supports_terminate_request=True,
|
|
102
|
-
supports_log_points=True,
|
|
103
|
-
supports_set_expression=True,
|
|
104
|
-
supports_set_variable=True,
|
|
105
|
-
supports_value_formatting_options=True,
|
|
106
|
-
exception_breakpoint_filters=[
|
|
107
|
-
ExceptionBreakpointsFilter(
|
|
108
|
-
filter="failed_keyword",
|
|
109
|
-
label="Failed Keywords",
|
|
110
|
-
description="Breaks on failed keywords",
|
|
111
|
-
default=False,
|
|
112
|
-
),
|
|
113
|
-
ExceptionBreakpointsFilter(
|
|
114
|
-
filter="uncaught_failed_keyword",
|
|
115
|
-
label="Uncaught Failed Keywords",
|
|
116
|
-
description="Breaks on uncaught failed keywords",
|
|
117
|
-
default=True,
|
|
118
|
-
),
|
|
119
|
-
ExceptionBreakpointsFilter(
|
|
120
|
-
filter="failed_test",
|
|
121
|
-
label="Failed Test",
|
|
122
|
-
description="Breaks on failed tests",
|
|
123
|
-
default=False,
|
|
124
|
-
),
|
|
125
|
-
ExceptionBreakpointsFilter(
|
|
126
|
-
filter="failed_suite",
|
|
127
|
-
label="Failed Suite",
|
|
128
|
-
description="Breaks on failed suite",
|
|
129
|
-
default=False,
|
|
130
|
-
),
|
|
131
|
-
],
|
|
132
|
-
supports_exception_options=True,
|
|
133
|
-
supports_exception_filter_options=True,
|
|
134
|
-
supports_completions_request=True,
|
|
135
|
-
supports_a_n_s_i_styling=True,
|
|
136
|
-
)
|
|
94
|
+
return DFEAULT_CAPABILITIES
|
|
137
95
|
|
|
138
96
|
@rpc_method(name="launch", param_type=LaunchRequestArguments)
|
|
139
97
|
async def _launch(
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/listeners.py
RENAMED
|
@@ -16,6 +16,8 @@ from .debugger import Debugger
|
|
|
16
16
|
class RobotExecutionEventBody(Model):
|
|
17
17
|
type: str
|
|
18
18
|
id: str
|
|
19
|
+
name: str
|
|
20
|
+
parent_id: Optional[str] = None
|
|
19
21
|
attributes: Optional[Dict[str, Any]] = None
|
|
20
22
|
failed_keywords: Optional[List[Dict[str, Any]]] = None
|
|
21
23
|
|
|
@@ -34,15 +36,19 @@ class ListenerV2:
|
|
|
34
36
|
def __init__(self) -> None:
|
|
35
37
|
self.failed_keywords: Optional[List[Dict[str, Any]]] = None
|
|
36
38
|
self.last_fail_message: Optional[str] = None
|
|
39
|
+
self.suite_id_stack: List[str] = []
|
|
37
40
|
|
|
38
41
|
def start_suite(self, name: str, attributes: Dict[str, Any]) -> None:
|
|
42
|
+
id = f"{source_from_attributes(attributes)};{attributes.get('longname', '')}"
|
|
39
43
|
Debugger.instance().send_event(
|
|
40
44
|
self,
|
|
41
45
|
Event(
|
|
42
46
|
event="robotStarted",
|
|
43
47
|
body=RobotExecutionEventBody(
|
|
44
48
|
type="suite",
|
|
45
|
-
|
|
49
|
+
name=name,
|
|
50
|
+
id=id,
|
|
51
|
+
parent_id=self.suite_id_stack[-1] if self.suite_id_stack else None,
|
|
46
52
|
attributes=dict(attributes),
|
|
47
53
|
),
|
|
48
54
|
),
|
|
@@ -51,8 +57,10 @@ class ListenerV2:
|
|
|
51
57
|
Debugger.instance().start_output_group(name, attributes, "SUITE")
|
|
52
58
|
|
|
53
59
|
Debugger.instance().start_suite(name, attributes)
|
|
60
|
+
self.suite_id_stack.append(id)
|
|
54
61
|
|
|
55
62
|
def end_suite(self, name: str, attributes: Dict[str, Any]) -> None:
|
|
63
|
+
id = f"{source_from_attributes(attributes)};{attributes.get('longname', '')}"
|
|
56
64
|
Debugger.instance().end_suite(name, attributes)
|
|
57
65
|
|
|
58
66
|
Debugger.instance().end_output_group(name, attributes, "SUITE")
|
|
@@ -63,13 +71,15 @@ class ListenerV2:
|
|
|
63
71
|
event="robotEnded",
|
|
64
72
|
body=RobotExecutionEventBody(
|
|
65
73
|
type="suite",
|
|
74
|
+
name=name,
|
|
66
75
|
attributes=dict(attributes),
|
|
67
|
-
id=
|
|
76
|
+
id=id,
|
|
77
|
+
parent_id=self.suite_id_stack[-1] if self.suite_id_stack else None,
|
|
68
78
|
failed_keywords=self.failed_keywords,
|
|
69
79
|
),
|
|
70
80
|
),
|
|
71
81
|
)
|
|
72
|
-
|
|
82
|
+
self.suite_id_stack.pop()
|
|
73
83
|
self.failed_keywords = None
|
|
74
84
|
|
|
75
85
|
def start_test(self, name: str, attributes: Dict[str, Any]) -> None:
|
|
@@ -81,8 +91,10 @@ class ListenerV2:
|
|
|
81
91
|
event="robotStarted",
|
|
82
92
|
body=RobotExecutionEventBody(
|
|
83
93
|
type="test",
|
|
94
|
+
name=name,
|
|
84
95
|
id=f"{source_from_attributes(attributes)};{attributes.get('longname', '')};"
|
|
85
96
|
f"{attributes.get('lineno', 0)}",
|
|
97
|
+
parent_id=self.suite_id_stack[-1] if self.suite_id_stack else None,
|
|
86
98
|
attributes=dict(attributes),
|
|
87
99
|
),
|
|
88
100
|
),
|
|
@@ -103,8 +115,10 @@ class ListenerV2:
|
|
|
103
115
|
event="robotEnded",
|
|
104
116
|
body=RobotExecutionEventBody(
|
|
105
117
|
type="test",
|
|
118
|
+
name=name,
|
|
106
119
|
id=f"{source_from_attributes(attributes)};{attributes.get('longname', '')};"
|
|
107
120
|
f"{attributes.get('lineno', 0)}",
|
|
121
|
+
parent_id=self.suite_id_stack[-1] if self.suite_id_stack else None,
|
|
108
122
|
attributes=dict(attributes),
|
|
109
123
|
failed_keywords=self.failed_keywords,
|
|
110
124
|
),
|
|
@@ -308,6 +322,7 @@ class ListenerV3:
|
|
|
308
322
|
event="robotSetFailed",
|
|
309
323
|
body=RobotExecutionEventBody(
|
|
310
324
|
type="test",
|
|
325
|
+
name=result_item.name,
|
|
311
326
|
attributes={
|
|
312
327
|
"longname": result_item.longname,
|
|
313
328
|
"status": str(result_item.status),
|
|
@@ -325,6 +340,7 @@ class ListenerV3:
|
|
|
325
340
|
),
|
|
326
341
|
),
|
|
327
342
|
)
|
|
343
|
+
|
|
328
344
|
if isinstance(result_item, result.TestSuite):
|
|
329
345
|
for r in result_item.suites:
|
|
330
346
|
p = next((i for i in data_item.suites if i.id == r.id), None) if data_item else None
|
|
@@ -23,7 +23,6 @@ from .dap_types import (
|
|
|
23
23
|
EvaluateArguments,
|
|
24
24
|
EvaluateResponseBody,
|
|
25
25
|
Event,
|
|
26
|
-
ExceptionBreakpointsFilter,
|
|
27
26
|
ExitedEvent,
|
|
28
27
|
ExitedEventBody,
|
|
29
28
|
InitializedEvent,
|
|
@@ -50,6 +49,7 @@ from .dap_types import (
|
|
|
50
49
|
VariablesResponseBody,
|
|
51
50
|
)
|
|
52
51
|
from .debugger import Debugger, PathMapping
|
|
52
|
+
from .default_capabilities import DFEAULT_CAPABILITIES
|
|
53
53
|
from .protocol import DebugAdapterProtocol
|
|
54
54
|
|
|
55
55
|
TCP_DEFAULT_PORT = 6612
|
|
@@ -132,7 +132,7 @@ class DebugAdapterServerProtocol(DebugAdapterProtocol):
|
|
|
132
132
|
return self._initialized
|
|
133
133
|
|
|
134
134
|
@_logger.call
|
|
135
|
-
def wait_for_disconnected(self, timeout: float =
|
|
135
|
+
def wait_for_disconnected(self, timeout: float = 1) -> bool:
|
|
136
136
|
self._disconnected_event.wait(timeout)
|
|
137
137
|
|
|
138
138
|
return not self._connected
|
|
@@ -144,49 +144,7 @@ class DebugAdapterServerProtocol(DebugAdapterProtocol):
|
|
|
144
144
|
if self.loop is not None:
|
|
145
145
|
self.loop.call_soon(self.initialized)
|
|
146
146
|
|
|
147
|
-
return
|
|
148
|
-
supports_configuration_done_request=True,
|
|
149
|
-
supports_conditional_breakpoints=True,
|
|
150
|
-
supports_hit_conditional_breakpoints=True,
|
|
151
|
-
support_terminate_debuggee=True,
|
|
152
|
-
# support_suspend_debuggee=True,
|
|
153
|
-
supports_evaluate_for_hovers=True,
|
|
154
|
-
supports_terminate_request=True,
|
|
155
|
-
supports_log_points=True,
|
|
156
|
-
supports_set_expression=True,
|
|
157
|
-
supports_set_variable=True,
|
|
158
|
-
supports_value_formatting_options=True,
|
|
159
|
-
exception_breakpoint_filters=[
|
|
160
|
-
ExceptionBreakpointsFilter(
|
|
161
|
-
filter="failed_keyword",
|
|
162
|
-
label="Failed Keywords",
|
|
163
|
-
description="Breaks on failed keywords",
|
|
164
|
-
default=False,
|
|
165
|
-
),
|
|
166
|
-
ExceptionBreakpointsFilter(
|
|
167
|
-
filter="uncaught_failed_keyword",
|
|
168
|
-
label="Uncaught Failed Keywords",
|
|
169
|
-
description="Breaks on uncaught failed keywords",
|
|
170
|
-
default=True,
|
|
171
|
-
),
|
|
172
|
-
ExceptionBreakpointsFilter(
|
|
173
|
-
filter="failed_test",
|
|
174
|
-
label="Failed Test",
|
|
175
|
-
description="Breaks on failed tests",
|
|
176
|
-
default=False,
|
|
177
|
-
),
|
|
178
|
-
ExceptionBreakpointsFilter(
|
|
179
|
-
filter="failed_suite",
|
|
180
|
-
label="Failed Suite",
|
|
181
|
-
description="Breaks on failed suite",
|
|
182
|
-
default=False,
|
|
183
|
-
),
|
|
184
|
-
],
|
|
185
|
-
supports_exception_options=True,
|
|
186
|
-
supports_exception_filter_options=True,
|
|
187
|
-
supports_completions_request=True,
|
|
188
|
-
supports_a_n_s_i_styling=True,
|
|
189
|
-
)
|
|
147
|
+
return DFEAULT_CAPABILITIES
|
|
190
148
|
|
|
191
149
|
@rpc_method(name="attach", param_type=AttachRequestArguments)
|
|
192
150
|
async def _attach(
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.105.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/cli.py
RENAMED
|
File without changes
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/client.py
RENAMED
|
File without changes
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/launcher/run.py
RENAMED
|
File without changes
|
{robotcode_debugger-0.105.0 → robotcode_debugger-0.106.0}/src/robotcode/debugger/protocol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|