Skip to content

Commit 8ea82e4

Browse files
committed
refactor(debugger): replace instance method calls with property access for consistency
1 parent 916b2c0 commit 8ea82e4

File tree

4 files changed

+103
-69
lines changed

4 files changed

+103
-69
lines changed

packages/debugger/src/robotcode/debugger/debugger.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,15 +293,44 @@ class ExceptionInformation(TypedDict):
293293
status: str
294294

295295

296+
class _DebuggerInstanceDescriptor:
297+
"""Descriptor that forwards all attribute access to the singleton instance."""
298+
299+
def __init__(self) -> None:
300+
self._owner_class: Optional[type] = None
301+
302+
def __set_name__(self, owner: type, name: str) -> None:
303+
"""Called when the descriptor is assigned to a class."""
304+
self._owner_class = owner
305+
306+
def __get__(self, obj: Any, owner: Optional[type]) -> "Debugger":
307+
if self._owner_class is None:
308+
self._owner_class = owner
309+
if self._owner_class is not None and hasattr(self._owner_class, "_get_instance"):
310+
return cast("Debugger", self._owner_class._get_instance())
311+
# This should never happen in practice, but needed for type checking
312+
raise RuntimeError("Debugger class not properly initialized")
313+
314+
def __set__(self, obj: Any, value: Any) -> None:
315+
raise AttributeError("Cannot replace the debugger instance")
316+
317+
def __delete__(self, obj: Any) -> None:
318+
raise AttributeError("Cannot delete the debugger instance")
319+
320+
296321
class Debugger:
297322
__instance: ClassVar[Optional["Debugger"]] = None
298323
__lock: ClassVar = threading.RLock()
299324
__inside_instance: ClassVar = False
300325

301326
_logger = LoggingDescriptor()
302327

328+
# Descriptor that allows Debugger.instance.field = value syntax
329+
instance = _DebuggerInstanceDescriptor()
330+
303331
@classmethod
304-
def instance(cls) -> "Debugger":
332+
def _get_instance(cls) -> "Debugger":
333+
"""Internal method to get the singleton instance."""
305334
if cls.__instance is not None:
306335
return cls.__instance
307336
with cls.__lock:
@@ -314,6 +343,11 @@ def instance(cls) -> "Debugger":
314343
cls.__inside_instance = False
315344
return cls.__instance
316345

346+
@classmethod
347+
def get_instance(cls) -> "Debugger":
348+
"""Backward compatibility method for old instance() calls."""
349+
return cls._get_instance()
350+
317351
def __new__(cls, *args: Any, **kwargs: Any) -> Any:
318352
if cls.__instance is None:
319353
with cls.__lock:

packages/debugger/src/robotcode/debugger/listeners.py

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def __init__(self) -> None:
6767
def start_suite(self, name: str, attributes: Dict[str, Any]) -> None:
6868
id = f"{source_from_attributes(attributes)};{attributes.get('longname', '')}"
6969

70-
Debugger.instance().send_event(
70+
Debugger.instance.send_event(
7171
self,
7272
Event(
7373
event="robotStarted",
@@ -83,18 +83,18 @@ def start_suite(self, name: str, attributes: Dict[str, Any]) -> None:
8383
),
8484
)
8585

86-
Debugger.instance().start_output_group(name, attributes, "SUITE")
86+
Debugger.instance.start_output_group(name, attributes, "SUITE")
8787

88-
Debugger.instance().start_suite(name, attributes)
88+
Debugger.instance.start_suite(name, attributes)
8989
self.suite_id_stack.append(id)
9090

9191
def end_suite(self, name: str, attributes: Dict[str, Any]) -> None:
9292
id = f"{source_from_attributes(attributes)};{attributes.get('longname', '')}"
93-
Debugger.instance().end_suite(name, attributes)
93+
Debugger.instance.end_suite(name, attributes)
9494

95-
Debugger.instance().end_output_group(name, attributes, "SUITE")
95+
Debugger.instance.end_output_group(name, attributes, "SUITE")
9696

97-
Debugger.instance().send_event(
97+
Debugger.instance.send_event(
9898
self,
9999
Event(
100100
event="robotEnded",
@@ -116,7 +116,7 @@ def end_suite(self, name: str, attributes: Dict[str, Any]) -> None:
116116
def start_test(self, name: str, attributes: Dict[str, Any]) -> None:
117117
self.failed_keywords = None
118118

119-
Debugger.instance().send_event(
119+
Debugger.instance.send_event(
120120
self,
121121
Event(
122122
event="robotStarted",
@@ -133,16 +133,16 @@ def start_test(self, name: str, attributes: Dict[str, Any]) -> None:
133133
),
134134
)
135135

136-
Debugger.instance().start_output_group(name, attributes, "TEST")
136+
Debugger.instance.start_output_group(name, attributes, "TEST")
137137

138-
Debugger.instance().start_test(name, attributes)
138+
Debugger.instance.start_test(name, attributes)
139139

140140
def end_test(self, name: str, attributes: Dict[str, Any]) -> None:
141-
Debugger.instance().end_test(name, attributes)
141+
Debugger.instance.end_test(name, attributes)
142142

143-
Debugger.instance().end_output_group(name, attributes, "TEST")
143+
Debugger.instance.end_output_group(name, attributes, "TEST")
144144

145-
Debugger.instance().send_event(
145+
Debugger.instance.send_event(
146146
self,
147147
Event(
148148
event="robotEnded",
@@ -164,14 +164,14 @@ def end_test(self, name: str, attributes: Dict[str, Any]) -> None:
164164

165165
def start_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
166166
if attributes["type"] in ["KEYWORD", "SETUP", "TEARDOWN"]:
167-
Debugger.instance().start_output_group(
167+
Debugger.instance.start_output_group(
168168
f"{name}({', '.join(repr(v) for v in attributes.get('args', []))})",
169169
attributes,
170170
attributes.get("type"),
171171
)
172172

173-
# if Debugger.instance().state != State.CallKeyword:
174-
# Debugger.instance().send_event(
173+
# if Debugger.instance.state != State.CallKeyword:
174+
# Debugger.instance.send_event(
175175
# self,
176176
# Event(
177177
# event="robotStarted",
@@ -187,13 +187,13 @@ def start_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
187187
# ),
188188
# )
189189

190-
Debugger.instance().start_keyword(name, attributes)
190+
Debugger.instance.start_keyword(name, attributes)
191191

192192
def end_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
193-
Debugger.instance().end_keyword(name, attributes)
193+
Debugger.instance.end_keyword(name, attributes)
194194

195-
# if Debugger.instance().state != State.CallKeyword:
196-
# Debugger.instance().send_event(
195+
# if Debugger.instance.state != State.CallKeyword:
196+
# Debugger.instance.send_event(
197197
# self,
198198
# Event(
199199
# event="robotEnded",
@@ -210,7 +210,7 @@ def end_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
210210
# )
211211

212212
if attributes["type"] in ["KEYWORD", "SETUP", "TEARDOWN"]:
213-
Debugger.instance().end_output_group(name, attributes, attributes.get("type"))
213+
Debugger.instance.end_output_group(name, attributes, attributes.get("type"))
214214

215215
if attributes["status"] == "FAIL" and attributes.get("source"):
216216
if self.failed_keywords is None:
@@ -222,11 +222,11 @@ def end_keyword(self, name: str, attributes: Dict[str, Any]) -> None:
222222

223223
def log_message(self, message: Dict[str, Any]) -> None:
224224
if message["level"] in ["FAIL", "ERROR", "WARN"]:
225-
current_frame = Debugger.instance().full_stack_frames[0] if Debugger.instance().full_stack_frames else None
225+
current_frame = Debugger.instance.full_stack_frames[0] if Debugger.instance.full_stack_frames else None
226226

227227
if message["level"] == "FAIL":
228228
self.last_fail_message = message["message"]
229-
Debugger.instance().last_fail_message = self.last_fail_message
229+
Debugger.instance.last_fail_message = self.last_fail_message
230230

231231
source = current_frame.source if current_frame else None
232232
line = current_frame.line if current_frame else None
@@ -240,7 +240,7 @@ def log_message(self, message: Dict[str, Any]) -> None:
240240
else f"{normalized_path(Path(item.source)) if item.source is not None else ''};"
241241
f"{item.longname};{item.line}"
242242
)
243-
for item in Debugger.instance().full_stack_frames
243+
for item in Debugger.instance.full_stack_frames
244244
if item.type in ["SUITE", "TEST"]
245245
),
246246
None,
@@ -254,7 +254,7 @@ def log_message(self, message: Dict[str, Any]) -> None:
254254
msg = match.group("message")
255255
column = 0
256256

257-
Debugger.instance().send_event(
257+
Debugger.instance.send_event(
258258
self,
259259
Event(
260260
event="robotLog",
@@ -271,11 +271,11 @@ def log_message(self, message: Dict[str, Any]) -> None:
271271
),
272272
)
273273

274-
Debugger.instance().log_message(message)
274+
Debugger.instance.log_message(message)
275275

276276
def message(self, message: Dict[str, Any]) -> None:
277277
if message["level"] in ["FAIL", "ERROR", "WARN"]:
278-
current_frame = Debugger.instance().full_stack_frames[0] if Debugger.instance().full_stack_frames else None
278+
current_frame = Debugger.instance.full_stack_frames[0] if Debugger.instance.full_stack_frames else None
279279

280280
source = current_frame.source if current_frame else None
281281
line = current_frame.line if current_frame else None
@@ -289,7 +289,7 @@ def message(self, message: Dict[str, Any]) -> None:
289289
else f"{normalized_path(Path(item.source)) if item.source is not None else ''};"
290290
f"{item.longname};{item.line}"
291291
)
292-
for item in Debugger.instance().full_stack_frames
292+
for item in Debugger.instance.full_stack_frames
293293
if item.type in ["SUITE", "TEST"]
294294
),
295295
None,
@@ -303,7 +303,7 @@ def message(self, message: Dict[str, Any]) -> None:
303303
msg = match.group("message")
304304
column = 0
305305

306-
Debugger.instance().send_event(
306+
Debugger.instance.send_event(
307307
self,
308308
Event(
309309
event="robotMessage",
@@ -320,7 +320,7 @@ def message(self, message: Dict[str, Any]) -> None:
320320
),
321321
)
322322

323-
Debugger.instance().message(message)
323+
Debugger.instance.message(message)
324324

325325
def library_import(self, name: str, attributes: Dict[str, Any]) -> None:
326326
pass
@@ -332,13 +332,13 @@ def variables_import(self, name: str, attributes: Dict[str, Any]) -> None:
332332
pass
333333

334334
def output_file(self, path: str) -> None:
335-
Debugger.instance().robot_output_file = path
335+
Debugger.instance.robot_output_file = path
336336

337337
def log_file(self, path: str) -> None:
338-
Debugger.instance().robot_log_file = path
338+
Debugger.instance.robot_log_file = path
339339

340340
def report_file(self, path: str) -> None:
341-
Debugger.instance().robot_report_file = path
341+
Debugger.instance.robot_report_file = path
342342

343343
def xunit_file(self, path: str) -> None:
344344
pass
@@ -378,7 +378,7 @@ def enqueue(
378378

379379
items = list(reversed(list(enqueue(cast(running.model.TestSuite, data)))))
380380

381-
Debugger.instance().send_event(self, Event(event="robotEnqueued", body=RobotEnqueuedEventBody(items)))
381+
Debugger.instance.send_event(self, Event(event="robotEnqueued", body=RobotEnqueuedEventBody(items)))
382382

383383
self._event_sended = True
384384

@@ -389,7 +389,7 @@ def report_status(
389389
message: str,
390390
) -> None:
391391
if isinstance(result_item, result.TestCase):
392-
Debugger.instance().send_event(
392+
Debugger.instance.send_event(
393393
self,
394394
Event(
395395
event="robotSetFailed",

packages/debugger/src/robotcode/debugger/run.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -223,17 +223,17 @@ def run_debugger(
223223
*args,
224224
]
225225

226-
Debugger.instance().stop_on_entry = stop_on_entry
227-
Debugger.instance().output_messages = output_messages
228-
Debugger.instance().output_log = output_log
229-
Debugger.instance().group_output = group_output
230-
Debugger.instance().output_timestamps = output_timestamps
231-
Debugger.instance().colored_output = app.colored
232-
Debugger.instance().debug = debug
233-
Debugger.instance().set_main_thread(threading.current_thread())
226+
Debugger.instance.stop_on_entry = stop_on_entry
227+
Debugger.instance.output_messages = output_messages
228+
Debugger.instance.output_log = output_log
229+
Debugger.instance.group_output = group_output
230+
Debugger.instance.output_timestamps = output_timestamps
231+
Debugger.instance.colored_output = app.colored
232+
Debugger.instance.debug = debug
233+
Debugger.instance.set_main_thread(threading.current_thread())
234234

235235
app.verbose("Start the debugger instance")
236-
Debugger.instance().start()
236+
Debugger.instance.start()
237237

238238
exit_code = 0
239239
try:
@@ -252,9 +252,9 @@ def run_debugger(
252252
Event(
253253
event="robotExited",
254254
body={
255-
"reportFile": Debugger.instance().robot_report_file,
256-
"logFile": Debugger.instance().robot_log_file,
257-
"outputFile": Debugger.instance().robot_output_file,
255+
"reportFile": Debugger.instance.robot_report_file,
256+
"logFile": Debugger.instance.robot_log_file,
257+
"outputFile": Debugger.instance.robot_output_file,
258258
"exitCode": exit_code,
259259
},
260260
)

0 commit comments

Comments
 (0)