Skip to content

Commit 693a876

Browse files
committed
enhance debugging for new RF5 TRY/EXCEPT/WHILE statements, some refactoring
1 parent 65a2a1d commit 693a876

File tree

8 files changed

+83
-65
lines changed

8 files changed

+83
-65
lines changed

robotcode/debugger/__main__.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,25 @@
3434
_logger = LoggingDescriptor(name=__package__)
3535

3636
if TYPE_CHECKING:
37-
from .server import LaucherServer
37+
from .server import DebugAdapterServer
3838

3939
server_lock = threading.RLock()
40-
_server: Optional["LaucherServer"] = None
40+
_server: Optional["DebugAdapterServer"] = None
4141

4242

43-
def get_server() -> Optional["LaucherServer"]:
43+
def get_server() -> Optional["DebugAdapterServer"]:
4444
with server_lock:
4545
return _server
4646

4747

48-
def set_server(value: "LaucherServer") -> None:
48+
def set_server(value: "DebugAdapterServer") -> None:
4949
with server_lock:
5050
global _server
5151
_server = value
5252

5353

5454
@_logger.call
55-
async def wait_for_server(timeout: float = 5) -> "LaucherServer":
55+
async def wait_for_server(timeout: float = 5) -> "DebugAdapterServer":
5656
async def wait() -> None:
5757
while get_server() is None:
5858
await asyncio.sleep(0.05)
@@ -67,12 +67,12 @@ async def wait() -> None:
6767
@_logger.call
6868
def run_server(port: int, loop: asyncio.AbstractEventLoop) -> None:
6969
from ..jsonrpc2.server import TcpParams
70-
from .server import LaucherServer
70+
from .server import DebugAdapterServer
7171

7272
asyncio.set_event_loop(loop)
7373

74-
with LaucherServer(tcp_params=TcpParams("127.0.0.1", port)) as server:
75-
set_server(cast(LaucherServer, server))
74+
with DebugAdapterServer(tcp_params=TcpParams("127.0.0.1", port)) as server:
75+
set_server(cast(DebugAdapterServer, server))
7676
try:
7777
server.run()
7878
except asyncio.CancelledError:
@@ -144,7 +144,9 @@ async def start_debugpy_async() -> None:
144144
server.protocol.wait_for_client(wait_for_client_timeout), loop=loop
145145
)
146146
)
147-
except (asyncio.CancelledError, SystemExit, KeyboardInterrupt):
147+
except SystemExit:
148+
raise
149+
except (asyncio.CancelledError, KeyboardInterrupt):
148150
pass
149151
except asyncio.TimeoutError:
150152
raise ConnectionError("No incomming connection from a debugger client.")
@@ -158,7 +160,9 @@ async def start_debugpy_async() -> None:
158160
server.protocol.wait_for_configuration_done(configuration_done_timeout), loop=loop
159161
)
160162
)
161-
except (asyncio.CancelledError, SystemExit, KeyboardInterrupt):
163+
except SystemExit:
164+
raise
165+
except (asyncio.CancelledError, KeyboardInterrupt):
162166
pass
163167
except asyncio.TimeoutError:
164168
raise ConnectionError("Timeout to get configuration from client.")
@@ -362,11 +366,13 @@ def main() -> None:
362366
_logger.logger.addHandler(get_log_handler(args.log_file))
363367

364368
if not args.log_asyncio:
365-
logging.getLogger("asyncio").level = logging.CRITICAL
369+
logging.getLogger("asyncio").setLevel(logging.CRITICAL)
366370

367371
if not args.log_debugger:
368-
logging.getLogger("robotcode.debugger").level = logging.CRITICAL
369-
logging.getLogger("robotcode.debugger").level = logging.CRITICAL
372+
logging.getLogger("robotcode.debugger").propagate = True
373+
logging.getLogger("robotcode.debugger").setLevel(logging.CRITICAL)
374+
logging.getLogger("robotcode.jsonrpc2").propagate = True
375+
logging.getLogger("robotcode.jsonrpc2").setLevel(logging.CRITICAL)
370376

371377
_logger.info(f"starting {__package__} version={__version__}")
372378
_logger.debug(f"args={args}")

robotcode/debugger/debugger.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,17 @@ def next(self, thread_id: int, granularity: Optional[SteppingGranularity] = None
269269
self.requested_state = RequestedState.Next
270270

271271
self.stop_stack_len = len(self.stack_frames)
272-
if self.stack_frames and self.stack_frames[0].type in ["FOR", "FOR ITERATION", "IF", "ELSE", "ELSE IF"]:
272+
if self.stack_frames and self.stack_frames[0].type in [
273+
"FOR",
274+
"FOR ITERATION",
275+
"ITERATION",
276+
"IF",
277+
"ELSE",
278+
"ELSE IF",
279+
"TRY",
280+
"EXCEPT",
281+
"WHILE",
282+
]:
273283
self.stop_stack_len += 1
274284

275285
self.condition.notify_all()
@@ -302,9 +312,13 @@ def step_out(self, thread_id: int, granularity: Optional[SteppingGranularity] =
302312
while i < len(self.stack_frames) and self.stack_frames[i].type in [
303313
"FOR",
304314
"FOR ITERATION",
315+
"ITERATION",
305316
"IF",
306317
"ELSE",
307318
"ELSE IF",
319+
"TRY",
320+
"EXCEPT",
321+
"WHILE",
308322
]:
309323
self.stop_stack_len -= 1
310324
i += 1
@@ -599,11 +613,10 @@ def start_test(self, name: str, attributes: Dict[str, Any]) -> None:
599613

600614
entry = self.add_stackframe_entry(longname, type, source, line_no)
601615

602-
if self.debug:
603-
if entry.source:
604-
self.process_start_state(entry.source, entry.line, entry.type, status)
616+
if self.debug and entry.source:
617+
self.process_start_state(entry.source, entry.line, entry.type, status)
605618

606-
self.wait_for_running()
619+
self.wait_for_running()
607620

608621
def end_test(self, name: str, attributes: Dict[str, Any]) -> None:
609622
if self.debug:
@@ -638,10 +651,11 @@ def start_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
638651
self.wait_for_running()
639652

640653
def end_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
654+
type = attributes.get("type", None)
641655
if self.debug:
642656
status = attributes.get("status", "")
643657

644-
if status != "NOT RUN":
658+
if status != "NOT RUN" and type in ["KEYWORD", "SETUP", "TEARDOWN"]:
645659
self.process_end_state(
646660
status,
647661
"failed_keyword",

robotcode/debugger/launcher/__main__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ def get_log_handler(logfile: str) -> logging.FileHandler:
5151

5252
def run_server(mode: str, port: int) -> None:
5353
from ...jsonrpc2.server import JsonRpcServerMode, TcpParams
54-
from .server import DebugAdapterServer
54+
from .server import LauncherServer
5555

56-
with DebugAdapterServer(JsonRpcServerMode(mode), tcp_params=TcpParams("127.0.0.1", port)) as server:
56+
with LauncherServer(JsonRpcServerMode(mode), tcp_params=TcpParams("127.0.0.1", port)) as server:
5757
try:
5858
server.run()
5959
except (SystemExit, KeyboardInterrupt):
@@ -140,10 +140,11 @@ def main() -> None:
140140
_logger.logger.addHandler(get_log_handler(args.log_file))
141141

142142
if not args.log_asyncio:
143-
logging.getLogger("asyncio").level = logging.CRITICAL
143+
logging.getLogger("asyncio").setLevel(logging.CRITICAL)
144144

145145
if not args.log_debugger_launcher:
146-
logging.getLogger("robotcode.debugger.launcher").level = logging.CRITICAL
146+
logging.getLogger("robotcode.debugger.launcher").setLevel(logging.CRITICAL)
147+
logging.getLogger("robotcode.jsonrpc2").setLevel(logging.CRITICAL)
147148

148149
_logger.info(f"starting debugger launcher server version={__version__}")
149150
_logger.debug(f"args={args}")

robotcode/debugger/launcher/server.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535

3636
class OutputProtocol(asyncio.SubprocessProtocol):
37-
def __init__(self, parent: DAPServerProtocol) -> None:
37+
def __init__(self, parent: LauncherDebugAdapterProtocol) -> None:
3838
super().__init__()
3939
self.parent = parent
4040

@@ -49,7 +49,7 @@ def pipe_data_received(self, fd: Any, data: bytes) -> None:
4949
self.parent.send_event(OutputEvent(body=OutputEventBody(output=data.decode(), category=category)))
5050

5151

52-
class DAPServerProtocol(DebugAdapterProtocol):
52+
class LauncherDebugAdapterProtocol(DebugAdapterProtocol):
5353
_logger = LoggingDescriptor()
5454

5555
def __init__(self) -> None:
@@ -268,7 +268,7 @@ async def handle_unknown_command(self, message: Request) -> Any:
268268
TCP_DEFAULT_PORT = 6611
269269

270270

271-
class DebugAdapterServer(JsonRPCServer[DAPServerProtocol]):
271+
class LauncherServer(JsonRPCServer[LauncherDebugAdapterProtocol]):
272272
def __init__(
273273
self,
274274
mode: JsonRpcServerMode = JsonRpcServerMode.STDIO,
@@ -279,5 +279,5 @@ def __init__(
279279
tcp_params=tcp_params,
280280
)
281281

282-
def create_protocol(self) -> DAPServerProtocol:
283-
return DAPServerProtocol()
282+
def create_protocol(self) -> LauncherDebugAdapterProtocol:
283+
return LauncherDebugAdapterProtocol()

robotcode/debugger/listeners.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,32 +75,36 @@ def end_test(self, name: str, attributes: Dict[str, Any]) -> None:
7575
self.failed_keywords = None
7676

7777
def start_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
78-
Debugger.instance().send_event(
79-
self, Event(event="robotStarted", body=RobotExecutionEventBody(type="keyword", attributes=dict(attributes)))
80-
)
81-
82-
Debugger.instance().start_output_group(
83-
f"{name}({', '.join(repr(v) for v in attributes.get('args', []))})",
84-
attributes,
85-
attributes.get("type", None),
86-
)
78+
if attributes["type"] in ["KEYWORD", "SETUP", "TEARDOWN"]:
79+
Debugger.instance().send_event(
80+
self,
81+
Event(event="robotStarted", body=RobotExecutionEventBody(type="keyword", attributes=dict(attributes))),
82+
)
83+
84+
Debugger.instance().start_output_group(
85+
f"{name}({', '.join(repr(v) for v in attributes.get('args', []))})",
86+
attributes,
87+
attributes.get("type", None),
88+
)
8789

8890
Debugger.instance().start_keyword(name, attributes)
8991

9092
def end_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
9193
Debugger.instance().end_keyword(name, attributes)
9294

93-
Debugger.instance().end_output_group(name, attributes)
95+
if attributes["type"] in ["KEYWORD", "SETUP", "TEARDOWN"]:
96+
Debugger.instance().end_output_group(name, attributes)
9497

95-
if attributes["status"] == "FAIL" and attributes.get("source", None):
96-
if self.failed_keywords is None:
97-
self.failed_keywords = []
98+
if attributes["status"] == "FAIL" and attributes.get("source", None):
99+
if self.failed_keywords is None:
100+
self.failed_keywords = []
98101

99-
self.failed_keywords.insert(0, {"message": self.last_fail_message, **attributes})
102+
self.failed_keywords.insert(0, {"message": self.last_fail_message, **attributes})
100103

101-
Debugger.instance().send_event(
102-
self, Event(event="robotEnded", body=RobotExecutionEventBody(type="keyword", attributes=dict(attributes)))
103-
)
104+
Debugger.instance().send_event(
105+
self,
106+
Event(event="robotEnded", body=RobotExecutionEventBody(type="keyword", attributes=dict(attributes))),
107+
)
104108

105109
def log_message(self, message: Dict[str, Any]) -> None:
106110
current_frame = Debugger.instance().stack_frames[0] if Debugger.instance().stack_frames else None

robotcode/debugger/protocol.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import asyncio
44
import inspect
55
import json
6-
import logging
76
import threading
87
import traceback
98
from collections import OrderedDict
@@ -78,7 +77,6 @@ def __init__(
7877
class DebugAdapterProtocol(JsonRPCProtocolBase):
7978

8079
_logger = LoggingDescriptor()
81-
_message_logger = LoggingDescriptor(postfix=".message")
8280

8381
def __init__(self) -> None:
8482
super().__init__()
@@ -90,19 +88,14 @@ def __init__(self) -> None:
9088

9189
@_logger.call
9290
def send_message(self, message: ProtocolMessage) -> None:
93-
body = as_json(message, indent=self._message_logger.is_enabled_for(logging.DEBUG) or None).encode(self.CHARSET)
91+
body = as_json(message, compact=True).encode(self.CHARSET)
9492

9593
header = (f"Content-Length: {len(body)}\r\n\r\n").encode("ascii")
9694

97-
self._message_logger.debug(
98-
lambda: "write ->\n" + (header.decode("ascii") + body.decode(self.CHARSET)).replace("\r\n", "\n")
99-
)
100-
10195
if self.write_transport is not None:
10296
msg = header + body
103-
if self._loop == asyncio.get_running_loop():
104-
self.write_transport.write(msg)
105-
elif self._loop is not None:
97+
98+
if self._loop:
10699
self._loop.call_soon_threadsafe(self.write_transport.write, msg)
107100

108101
def send_error(

robotcode/debugger/server.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
TCP_DEFAULT_PORT = 6612
4646

4747

48-
class LauncherServerProtocol(DebugAdapterProtocol):
48+
class DebugAdapterServerProtocol(DebugAdapterProtocol):
4949
_logger = LoggingDescriptor()
5050

5151
def __init__(self) -> None:
@@ -272,7 +272,7 @@ async def _set_exception_breakpoints(
272272
return SetExceptionBreakpointsResponseBody(breakpoints=result) if result else None
273273

274274

275-
class LaucherServer(JsonRPCServer[LauncherServerProtocol]):
275+
class DebugAdapterServer(JsonRPCServer[DebugAdapterServerProtocol]):
276276
def __init__(
277277
self,
278278
tcp_params: TcpParams = TcpParams(None, TCP_DEFAULT_PORT),
@@ -281,7 +281,7 @@ def __init__(
281281
mode=JsonRpcServerMode.TCP,
282282
tcp_params=tcp_params,
283283
)
284-
self.protocol = LauncherServerProtocol()
284+
self.protocol = DebugAdapterServerProtocol()
285285

286-
def create_protocol(self) -> LauncherServerProtocol:
286+
def create_protocol(self) -> DebugAdapterServerProtocol:
287287
return self.protocol

robotcode/language_server/__main__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,17 @@ def init_logging(args: argparse.Namespace) -> None:
152152
_logger.logger.addHandler(get_log_handler(args.log_file))
153153

154154
if not args.log_robotframework:
155-
logging.getLogger("robotcode.language_server.robotframework").level = logging.CRITICAL
155+
logging.getLogger("robotcode.language_server.robotframework").setLevel(logging.CRITICAL)
156156
if not args.log_language_server_parts:
157-
logging.getLogger("robotcode.language_server.common.parts").level = logging.CRITICAL
157+
logging.getLogger("robotcode.language_server.common.parts").setLevel(logging.CRITICAL)
158158
if not args.log_language_server:
159-
logging.getLogger("robotcode.language_server.common").level = logging.CRITICAL
159+
logging.getLogger("robotcode.language_server.common").setLevel(logging.CRITICAL)
160160
if not args.log_json_rpc:
161-
logging.getLogger("robotcode.jsonrpc2").level = logging.CRITICAL
161+
logging.getLogger("robotcode.jsonrpc2").setLevel(logging.CRITICAL)
162162
if not args.log_json_rpc_data:
163-
logging.getLogger("robotcode.jsonrpc2.protocol.JsonRPCProtocol_data").level = logging.CRITICAL
163+
logging.getLogger("robotcode.jsonrpc2.protocol.JsonRPCProtocol_data").setLevel(logging.CRITICAL)
164164
if not args.log_asyncio:
165-
logging.getLogger("asyncio").level = logging.CRITICAL
165+
logging.getLogger("asyncio").setLevel(logging.CRITICAL)
166166

167167

168168
def main() -> None:

0 commit comments

Comments
 (0)