robotframework-debug 4.3.4__tar.gz → 4.5.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.
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/PKG-INFO +6 -1
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/RobotDebug.py +1 -1
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/cmdcompleter.py +125 -51
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/debugcmd.py +13 -4
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/globals.py +7 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/history_app.py +7 -3
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/lexer.py +8 -7
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/prompttoolkitcmd.py +4 -4
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/robotkeyword.py +11 -6
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/robotlib.py +3 -1
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/sourcelines.py +6 -2
- robotframework-debug-4.5.0/RobotDebug/version.py +1 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/pyproject.toml +5 -4
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/PKG-INFO +6 -1
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/SOURCES.txt +1 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/requires.txt +1 -1
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/setup.py +6 -13
- robotframework-debug-4.5.0/tests/debug.robot +4 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/tests/step.robot +1 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/tests/test_debuglibrary.py +1 -1
- robotframework-debug-4.3.4/RobotDebug/version.py +0 -1
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/.coveragerc +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/.gitpod.yml +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/ChangeLog +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/CreateWheel.sh +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/LICENSE +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/MANIFEST.in +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/README.rst +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/__init__.py +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/shell.py +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/RobotDebug/styles.py +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/_config.yml +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/dependency_links.txt +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/entry_points.txt +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/not-zip-safe +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/top_level.txt +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/setup.cfg +0 -0
- {robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework-debug
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.0
|
|
4
4
|
Summary: RobotFramework debug shell
|
|
5
5
|
Home-page: https://github.com/imbus/robotframework-debug/
|
|
6
6
|
Author: René Rohner
|
|
@@ -22,10 +22,15 @@ Classifier: Programming Language :: Python :: 3.7
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.8
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.9
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.10
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
25
26
|
Classifier: Topic :: Utilities
|
|
26
27
|
Requires-Python: >=3.8.0
|
|
27
28
|
Description-Content-Type: text/x-rst
|
|
28
29
|
License-File: LICENSE
|
|
30
|
+
Requires-Dist: prompt-toolkit>=3.0.38
|
|
31
|
+
Requires-Dist: robotframework<8.0,>=5.0
|
|
32
|
+
Requires-Dist: pygments>=2.14.0
|
|
33
|
+
Requires-Dist: pyperclip>=1.8.2
|
|
29
34
|
|
|
30
35
|
Debug Library for Robot Framework
|
|
31
36
|
=================================
|
|
@@ -44,7 +44,7 @@ class Listener:
|
|
|
44
44
|
|
|
45
45
|
path = attrs["source"]
|
|
46
46
|
if path and Path(path).exists() and path not in self.source_files:
|
|
47
|
-
self.source_files[path] = Path(path).open().readlines()
|
|
47
|
+
self.source_files[path] = Path(path).open().readlines() # noqa: SIM115
|
|
48
48
|
lineno = attrs["lineno"]
|
|
49
49
|
self.library.current_source_path = path
|
|
50
50
|
self.library.current_source_line = lineno
|
|
@@ -8,6 +8,7 @@ from prompt_toolkit.document import Document
|
|
|
8
8
|
from robot.libraries.BuiltIn import BuiltIn
|
|
9
9
|
from robot.parsing.parser.parser import _tokens_to_statements
|
|
10
10
|
|
|
11
|
+
from .globals import IS_RF_7, KEYWORD_SEP
|
|
11
12
|
from .lexer import get_robot_token, get_variable_token
|
|
12
13
|
from .prompttoolkitcmd import PromptToolkitCmd
|
|
13
14
|
from .robotkeyword import normalize_kw
|
|
@@ -68,7 +69,16 @@ class StatementInformation:
|
|
|
68
69
|
|
|
69
70
|
def _find_token_at_cursor(self):
|
|
70
71
|
for token in self.statement.tokens:
|
|
71
|
-
if token.type in [
|
|
72
|
+
if token.type in [
|
|
73
|
+
"KEYWORD",
|
|
74
|
+
"IF",
|
|
75
|
+
"FOR",
|
|
76
|
+
"ELSE",
|
|
77
|
+
"ELSE IF",
|
|
78
|
+
"TRY",
|
|
79
|
+
"WHILE",
|
|
80
|
+
"VAR",
|
|
81
|
+
]: # TODO: Commented to get all tokens in debug. lets see the impact
|
|
72
82
|
self.statement_type = token.type
|
|
73
83
|
if (
|
|
74
84
|
token.lineno == self.cursor_row + 1
|
|
@@ -90,6 +100,12 @@ class CmdCompleter(Completer):
|
|
|
90
100
|
self.helps = helps
|
|
91
101
|
self.libs = libs
|
|
92
102
|
self.keywords = list(keywords)
|
|
103
|
+
self.keywords_catalog = {}
|
|
104
|
+
for keyword in self.keywords:
|
|
105
|
+
self.keywords_catalog[normalize_kw(keyword.name)] = keyword
|
|
106
|
+
self.keywords_catalog[
|
|
107
|
+
f"{normalize_kw(keyword.parent.name)}.{normalize_kw(keyword.name)}"
|
|
108
|
+
] = keyword
|
|
93
109
|
self.current_statement = None
|
|
94
110
|
for name, display, display_meta in self.get_commands():
|
|
95
111
|
self.names.append(name)
|
|
@@ -160,28 +176,28 @@ class CmdCompleter(Completer):
|
|
|
160
176
|
)
|
|
161
177
|
|
|
162
178
|
def _get_argument_completer(self, text):
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
else:
|
|
175
|
-
yield from self.get_pos_arg_completion(args, set_pos_args)
|
|
179
|
+
keyword = self.keywords_catalog.get(
|
|
180
|
+
normalize_kw(self.current_statement.statement.keyword), None
|
|
181
|
+
)
|
|
182
|
+
if keyword:
|
|
183
|
+
data_tokens = self.current_statement.statement.data_tokens
|
|
184
|
+
args = keyword.args
|
|
185
|
+
set_named_args, set_pos_args = self.get_set_args(args, data_tokens)
|
|
186
|
+
if set_named_args:
|
|
187
|
+
yield from self.get_named_arg_completion(args, set_named_args, set_pos_args)
|
|
188
|
+
else:
|
|
189
|
+
yield from self.get_pos_arg_completion(args, set_pos_args)
|
|
176
190
|
|
|
177
|
-
def get_pos_arg_completion(
|
|
191
|
+
def get_pos_arg_completion(
|
|
192
|
+
self, args, set_pos_args
|
|
193
|
+
): # TODO: here is an issue. if more positional args are set, than existing, named_only will be removed from proposal
|
|
178
194
|
for index, arg in enumerate([*args.positional_or_named, *args.named_only]):
|
|
179
195
|
if index + 1 > len(set_pos_args):
|
|
180
|
-
suffix = "=" if arg in [*args.positional_or_named, *args.named_only] else ""
|
|
196
|
+
# suffix = "=" if arg in [*args.positional_or_named, *args.named_only] else ""
|
|
181
197
|
yield Completion(
|
|
182
|
-
f"{arg}",
|
|
198
|
+
f"{arg}=",
|
|
183
199
|
0,
|
|
184
|
-
display=f"{arg}
|
|
200
|
+
display=f"{arg}=",
|
|
185
201
|
display_meta=str(args.defaults.get(arg, "")),
|
|
186
202
|
)
|
|
187
203
|
|
|
@@ -222,9 +238,10 @@ class CmdCompleter(Completer):
|
|
|
222
238
|
previous_token = statement_info.previous_token
|
|
223
239
|
token = statement_info.token
|
|
224
240
|
cursor_pos = statement_info.cursor_pos
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
241
|
+
self.cmd_repl.set_toolbar_key(statement_type, token, cursor_pos)
|
|
242
|
+
if text == "":
|
|
243
|
+
yield from []
|
|
244
|
+
elif "FOR".startswith(text):
|
|
228
245
|
yield from [
|
|
229
246
|
Completion(
|
|
230
247
|
"FOR ${var} IN @{list}\n Log ${var}\nEND",
|
|
@@ -261,40 +278,97 @@ class CmdCompleter(Completer):
|
|
|
261
278
|
display_meta="If-Statement as multi line",
|
|
262
279
|
),
|
|
263
280
|
]
|
|
281
|
+
elif "WHILE".startswith(text):
|
|
282
|
+
yield from [
|
|
283
|
+
Completion(
|
|
284
|
+
"WHILE <py-eval>\n Log body\nEND",
|
|
285
|
+
-len(text),
|
|
286
|
+
display="WHILE loop",
|
|
287
|
+
display_meta="While-Loop",
|
|
288
|
+
),
|
|
289
|
+
Completion(
|
|
290
|
+
"WHILE <py-eval> limit=5 on_limit=pass\n Log body\nEND",
|
|
291
|
+
-len(text),
|
|
292
|
+
display="WHILE loop (with limit)",
|
|
293
|
+
display_meta="While-Loop with limit and pass when reached",
|
|
294
|
+
),
|
|
295
|
+
]
|
|
296
|
+
elif "TRY".startswith(text):
|
|
297
|
+
yield from [
|
|
298
|
+
Completion(
|
|
299
|
+
"TRY\n Some Keyword\nEXCEPT\n Error Handler\nEND",
|
|
300
|
+
-len(text),
|
|
301
|
+
display="TRY/EXCEPT Statement",
|
|
302
|
+
display_meta="Try/Except that catches any error",
|
|
303
|
+
),
|
|
304
|
+
Completion(
|
|
305
|
+
"TRY\n Some Keyword\nEXCEPT ValueError: * type=GLOB AS ${error}\n Log ${error}",
|
|
306
|
+
-len(text),
|
|
307
|
+
display="TRY/EXCEPT Statement (specific error)",
|
|
308
|
+
display_meta="Try/Except that catches a specific error as ${error}",
|
|
309
|
+
),
|
|
310
|
+
]
|
|
311
|
+
elif IS_RF_7 and "VAR".startswith(text):
|
|
312
|
+
yield from [
|
|
313
|
+
Completion(
|
|
314
|
+
"VAR ${var} <value>",
|
|
315
|
+
-len(text),
|
|
316
|
+
display="VAR (simple)",
|
|
317
|
+
display_meta="Variable assignment",
|
|
318
|
+
),
|
|
319
|
+
Completion(
|
|
320
|
+
"VAR ${var} <value> scope=Suite",
|
|
321
|
+
-len(text),
|
|
322
|
+
display="VAR (suite scope)",
|
|
323
|
+
display_meta="Suite Variable assignment",
|
|
324
|
+
),
|
|
325
|
+
Completion(
|
|
326
|
+
"VAR ${var} <value> <value> separator=${SPACE}",
|
|
327
|
+
-len(text),
|
|
328
|
+
display="VAR (multiple values)",
|
|
329
|
+
display_meta="Variable assignment concatenate",
|
|
330
|
+
),
|
|
331
|
+
]
|
|
264
332
|
elif re.fullmatch(r"style {2,}.*", text):
|
|
265
333
|
yield from _get_style_completions(text.lower())
|
|
266
334
|
elif text.startswith("*"):
|
|
267
335
|
yield from self._get_resource_completions(text.lower())
|
|
268
336
|
elif token:
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
337
|
+
yield from self._get_keyword_completions(
|
|
338
|
+
cursor_col, cursor_pos, previous_token, statement_type, token
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
def _get_keyword_completions(
|
|
342
|
+
self, cursor_col, cursor_pos, previous_token, statement_type, token
|
|
343
|
+
):
|
|
344
|
+
for var in list(get_variable_token([token])):
|
|
345
|
+
if var.col_offset <= cursor_col <= var.end_col_offset:
|
|
346
|
+
token = var
|
|
347
|
+
cursor_pos = cursor_col - var.col_offset
|
|
348
|
+
SEPARATOR_SIZE = 2
|
|
349
|
+
if token.type in ["ASSIGN", "VARIABLE"] or (
|
|
350
|
+
token.type in ["KEYWORD", "ARGUMENT"] and re.fullmatch(r"[$&@]\{[^}]*}?", token.value)
|
|
351
|
+
):
|
|
352
|
+
yield from [
|
|
353
|
+
Completion(
|
|
354
|
+
var,
|
|
355
|
+
-cursor_pos,
|
|
356
|
+
display=var,
|
|
357
|
+
display_meta=repr(val),
|
|
358
|
+
)
|
|
359
|
+
for var, val in BuiltIn().get_variables().items()
|
|
360
|
+
if normalize_kw(var[1:]).startswith(normalize_kw(token.value[1:cursor_pos]))
|
|
361
|
+
]
|
|
362
|
+
elif token.type == "KEYWORD":
|
|
363
|
+
yield from self._get_command_completions(token.value.lower())
|
|
364
|
+
elif cursor_pos == 1 and previous_token and previous_token.type == "KEYWORD":
|
|
365
|
+
yield from self._get_command_completions(f"{previous_token.value.lower()} ")
|
|
366
|
+
elif (
|
|
367
|
+
token.type in ["SEPARATOR", "EOL"]
|
|
368
|
+
and cursor_pos >= SEPARATOR_SIZE
|
|
369
|
+
and statement_type == "KEYWORD"
|
|
370
|
+
):
|
|
371
|
+
yield from self._get_argument_completer(token.value)
|
|
298
372
|
|
|
299
373
|
|
|
300
374
|
class KeywordAutoSuggestion(AutoSuggest):
|
|
@@ -304,7 +378,7 @@ class KeywordAutoSuggestion(AutoSuggest):
|
|
|
304
378
|
def get_suggestion(self, buffer: Buffer, document: Document) -> Union[Suggestion, None]:
|
|
305
379
|
text = document.text
|
|
306
380
|
completions = [compl.text for compl in self.completer.get_completions(document, None)]
|
|
307
|
-
last_word =
|
|
381
|
+
last_word = KEYWORD_SEP.split(text)[-1]
|
|
308
382
|
matches = [kw for kw in completions if kw.startswith(last_word)]
|
|
309
383
|
matches.extend([kw for kw in completions if kw.lower().startswith(last_word.lower())])
|
|
310
384
|
return Suggestion(matches[0][len(last_word) :] if matches else "")
|
|
@@ -8,11 +8,13 @@ from prompt_toolkit.styles import merge_styles
|
|
|
8
8
|
from robot.api import logger
|
|
9
9
|
from robot.errors import ExecutionFailed, HandlerExecutionFailed
|
|
10
10
|
from robot.libraries.BuiltIn import BuiltIn
|
|
11
|
+
from robot.running import Keyword
|
|
12
|
+
from robot.running.context import _ExecutionContext
|
|
11
13
|
from robot.running.signalhandler import STOP_SIGNAL_MONITOR
|
|
12
14
|
from robot.variables import is_variable
|
|
13
15
|
|
|
14
16
|
from .cmdcompleter import CmdCompleter, KeywordAutoSuggestion
|
|
15
|
-
from .globals import context
|
|
17
|
+
from .globals import IS_RF_7, context
|
|
16
18
|
from .lexer import HEADER_MATCHER
|
|
17
19
|
from .prompttoolkitcmd import PromptToolkitCmd
|
|
18
20
|
from .robotkeyword import (
|
|
@@ -100,7 +102,7 @@ Access https://github.com/imbus/robotframework-debug for more details.\
|
|
|
100
102
|
self.run_robot_command(command)
|
|
101
103
|
|
|
102
104
|
def run_robot_command(self, command):
|
|
103
|
-
"""Run command in
|
|
105
|
+
"""Run command in robotframework environment."""
|
|
104
106
|
if not command:
|
|
105
107
|
return
|
|
106
108
|
result = []
|
|
@@ -288,13 +290,13 @@ def run_command(dbg_cmd, command: str) -> List[Tuple[str, str]]:
|
|
|
288
290
|
if len(test.body) > 1:
|
|
289
291
|
start = time.monotonic()
|
|
290
292
|
for kw in test.body:
|
|
291
|
-
kw
|
|
293
|
+
run_keyword(kw, ctx)
|
|
292
294
|
dbg_cmd.last_keyword_exec_time = time.monotonic() - start
|
|
293
295
|
return_val = None
|
|
294
296
|
else:
|
|
295
297
|
kw = test.body[0]
|
|
296
298
|
start = time.monotonic()
|
|
297
|
-
return_val = kw
|
|
299
|
+
return_val = run_keyword(kw, ctx)
|
|
298
300
|
dbg_cmd.last_keyword_exec_time = time.monotonic() - start
|
|
299
301
|
assign = set(_get_assignments(test))
|
|
300
302
|
if not assign and return_val is not None:
|
|
@@ -307,3 +309,10 @@ def run_command(dbg_cmd, command: str) -> List[Tuple[str, str]]:
|
|
|
307
309
|
output.append(("#", f"{pure_var} = {val!r}"))
|
|
308
310
|
return output
|
|
309
311
|
return []
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def run_keyword(keyword: Keyword, context: _ExecutionContext):
|
|
315
|
+
if IS_RF_7:
|
|
316
|
+
test = context.test or context.suite
|
|
317
|
+
return keyword.run(test, context)
|
|
318
|
+
return keyword.run(context)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from enum import Enum
|
|
2
3
|
|
|
4
|
+
from robot.version import get_version
|
|
5
|
+
|
|
3
6
|
|
|
4
7
|
class SingletonContext:
|
|
5
8
|
in_step_mode = False
|
|
@@ -20,3 +23,7 @@ class StepMode(str, Enum):
|
|
|
20
23
|
OUT = "_OUT"
|
|
21
24
|
CONTINUE = "_CONTINUE"
|
|
22
25
|
STOP = "_STOP"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
IS_RF_7 = int(get_version().split(".", 1)[0]) >= 7 # noqa: PLR2004
|
|
29
|
+
KEYWORD_SEP = re.compile(r"[ \t]{2,}|\t")
|
|
@@ -136,10 +136,14 @@ def get_history_content(his, pure_commands: bool = True):
|
|
|
136
136
|
[
|
|
137
137
|
e
|
|
138
138
|
for e in dict.fromkeys(
|
|
139
|
-
reversed(
|
|
139
|
+
reversed(
|
|
140
|
+
[
|
|
141
|
+
re.sub(r"(?:(?<![\n ])(?:[ \t]{2,}|\t))", " " * 4, v).strip()
|
|
142
|
+
for v in his.get_strings()
|
|
143
|
+
]
|
|
144
|
+
)
|
|
140
145
|
)
|
|
141
|
-
if (
|
|
142
|
-
or (HEADER_MATCHER.match(e) and not pure_commands)
|
|
146
|
+
if bool(HEADER_MATCHER.match(e)) != pure_commands
|
|
143
147
|
]
|
|
144
148
|
)
|
|
145
149
|
)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from pathlib import Path
|
|
3
|
+
from typing import ClassVar, Dict, List
|
|
3
4
|
|
|
4
5
|
from pygments.lexer import Lexer
|
|
5
|
-
from pygments.token import Token
|
|
6
|
+
from pygments.token import Token, _TokenType
|
|
6
7
|
from robot.parsing import get_tokens
|
|
7
8
|
|
|
8
9
|
|
|
@@ -49,16 +50,15 @@ def get_variable_token(token_list):
|
|
|
49
50
|
var_tokens = list(token.tokenize_variables())
|
|
50
51
|
except Exception:
|
|
51
52
|
var_tokens = [token]
|
|
52
|
-
|
|
53
|
-
yield v_token
|
|
53
|
+
yield from var_tokens
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
class RobotFrameworkLocalLexer(Lexer):
|
|
57
57
|
name = "RobotFramework"
|
|
58
58
|
url = "http://robotframework.org"
|
|
59
|
-
aliases = ["robotframework"]
|
|
60
|
-
filenames = ["*.robot", "*.resource"]
|
|
61
|
-
mimetypes = ["text/x-robotframework"]
|
|
59
|
+
aliases: ClassVar[List[str]] = ["robotframework"]
|
|
60
|
+
filenames: ClassVar[List[str]] = ["*.robot", "*.resource"]
|
|
61
|
+
mimetypes: ClassVar[List[str]] = ["text/x-robotframework"]
|
|
62
62
|
|
|
63
63
|
# PYGMENTS_STANDARD_TYPES = {
|
|
64
64
|
# Token: '',
|
|
@@ -152,7 +152,7 @@ class RobotFrameworkLocalLexer(Lexer):
|
|
|
152
152
|
# Generic.Traceback: 'gt',
|
|
153
153
|
# }
|
|
154
154
|
|
|
155
|
-
ROBOT_TO_PYGMENTS = {
|
|
155
|
+
ROBOT_TO_PYGMENTS: ClassVar[Dict[str, _TokenType]] = {
|
|
156
156
|
"HEADER": Token.Keyword.Namespace,
|
|
157
157
|
"DEFINITION": Token.Name.Class,
|
|
158
158
|
"SETTING HEADER": Token.Keyword.Namespace,
|
|
@@ -206,6 +206,7 @@ class RobotFrameworkLocalLexer(Lexer):
|
|
|
206
206
|
"CONTINUE": Token.Keyword,
|
|
207
207
|
"BREAK": Token.Keyword,
|
|
208
208
|
"OPTION": Token.Keyword,
|
|
209
|
+
"VAR": Token.Keyword,
|
|
209
210
|
"SEPARATOR": Token.Punctuation,
|
|
210
211
|
"COMMENT": Token.Comment,
|
|
211
212
|
"CONTINUATION": Token.Operator,
|
|
@@ -304,16 +304,15 @@ class BaseCmd(cmd.Cmd):
|
|
|
304
304
|
if line is None:
|
|
305
305
|
return None
|
|
306
306
|
|
|
307
|
-
if line
|
|
307
|
+
if line in ["exit", "EOF"]:
|
|
308
308
|
line = "EOF"
|
|
309
309
|
return True
|
|
310
310
|
|
|
311
311
|
line = self.precmd(line)
|
|
312
312
|
stop = self.onecmd(line)
|
|
313
|
-
|
|
313
|
+
return self.postcmd(stop, line)
|
|
314
314
|
|
|
315
315
|
# do not run 'EOF' command to avoid override 'lastcmd'
|
|
316
|
-
return stop
|
|
317
316
|
|
|
318
317
|
def cmdloop(self, intro=None):
|
|
319
318
|
"""Better command loop.
|
|
@@ -429,7 +428,8 @@ Type "help" for more information.\
|
|
|
429
428
|
),
|
|
430
429
|
]
|
|
431
430
|
)
|
|
432
|
-
|
|
431
|
+
## UNCOMMEND FOR DEBUGGING
|
|
432
|
+
# if self.toolbar_token_tuple:
|
|
433
433
|
# base.extend(
|
|
434
434
|
# [
|
|
435
435
|
# ("class:bottom-toolbar-key", "STATEMENT: "),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import re
|
|
2
1
|
import tempfile
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
from typing import Iterator, List, Tuple
|
|
@@ -6,13 +5,17 @@ from typing import Iterator, List, Tuple
|
|
|
6
5
|
from robot.libdocpkg.model import KeywordDoc, LibraryDoc
|
|
7
6
|
from robot.libraries.BuiltIn import BuiltIn
|
|
8
7
|
from robot.parsing import get_model
|
|
9
|
-
from robot.running import TestSuite
|
|
8
|
+
from robot.running import TestSuite
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from robot.running import UserLibrary as ResourceFile
|
|
12
|
+
except ImportError:
|
|
13
|
+
from robot.running import ResourceFile
|
|
10
14
|
from robot.variables.search import is_variable
|
|
11
15
|
|
|
16
|
+
from .globals import KEYWORD_SEP
|
|
12
17
|
from .robotlib import ImportedLibraryDocBuilder, ImportedResourceDocBuilder, get_libs
|
|
13
18
|
|
|
14
|
-
KEYWORD_SEP = re.compile(" +|\t")
|
|
15
|
-
|
|
16
19
|
_lib_keywords_cache = {}
|
|
17
20
|
_resource_keywords_cache = {}
|
|
18
21
|
temp_resources = []
|
|
@@ -38,7 +41,7 @@ def parse_keyword(command) -> Tuple[List[str], str, List[str]]:
|
|
|
38
41
|
def get_lib_keywords(library) -> List[KeywordDoc]:
|
|
39
42
|
"""Get keywords of imported library."""
|
|
40
43
|
if library.name not in _lib_keywords_cache:
|
|
41
|
-
if isinstance(library,
|
|
44
|
+
if isinstance(library, ResourceFile):
|
|
42
45
|
_lib_keywords_cache[library.name]: LibraryDoc = ImportedResourceDocBuilder().build(
|
|
43
46
|
library
|
|
44
47
|
)
|
|
@@ -104,9 +107,11 @@ def _import_resource_from_string(command):
|
|
|
104
107
|
def _get_assignments(body_elem):
|
|
105
108
|
if hasattr(body_elem, "assign"):
|
|
106
109
|
yield from body_elem.assign
|
|
107
|
-
|
|
110
|
+
elif hasattr(body_elem, "body"):
|
|
108
111
|
for child in body_elem.body:
|
|
109
112
|
yield from _get_assignments(child)
|
|
113
|
+
elif body_elem.type == "VAR":
|
|
114
|
+
yield body_elem.name
|
|
110
115
|
|
|
111
116
|
|
|
112
117
|
def run_debug_if(condition, *args):
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
|
|
1
3
|
from robot.libdocpkg.model import LibraryDoc
|
|
2
4
|
from robot.libdocpkg.robotbuilder import (
|
|
3
5
|
KeywordDocBuilder,
|
|
@@ -44,7 +46,7 @@ class ImportedResourceDocBuilder(ResourceDocBuilder):
|
|
|
44
46
|
type="RESOURCE",
|
|
45
47
|
scope="GLOBAL",
|
|
46
48
|
)
|
|
47
|
-
libdoc.keywords = KeywordDocBuilder().build_keywords(resource)
|
|
49
|
+
libdoc.keywords = KeywordDocBuilder().build_keywords(deepcopy(resource))
|
|
48
50
|
return libdoc
|
|
49
51
|
|
|
50
52
|
|
|
@@ -16,7 +16,9 @@ def print_source_lines(style, source_file, lineno, before_and_after=5):
|
|
|
16
16
|
if not source_file or not lineno:
|
|
17
17
|
return
|
|
18
18
|
|
|
19
|
-
Path(
|
|
19
|
+
Path(
|
|
20
|
+
source_file
|
|
21
|
+
).open().readlines() # noqa: SIM115 TODO: not sure why i did this. Maybe to check if file is actually readable...
|
|
20
22
|
prefixed_token = get_pygments_token_from_file(lineno, source_file)
|
|
21
23
|
printable_token = filter_token_by_lineno(
|
|
22
24
|
prefixed_token, lineno - before_and_after, lineno + before_and_after + 1
|
|
@@ -28,7 +30,9 @@ def print_test_case_lines(style, source_file, current_lineno):
|
|
|
28
30
|
if not source_file or not current_lineno:
|
|
29
31
|
return
|
|
30
32
|
|
|
31
|
-
Path(
|
|
33
|
+
Path(
|
|
34
|
+
source_file
|
|
35
|
+
).open().readlines() # noqa: SIM115 TODO: not sure why i did this. Maybe to check if file is actually readable...
|
|
32
36
|
prefixed_token = get_pygments_token_from_file(current_lineno, source_file)
|
|
33
37
|
printable_token = filter_token_by_scope(prefixed_token, current_lineno)
|
|
34
38
|
print_pygments_styles(printable_token, style)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "4.5.0"
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
[tool.black]
|
|
2
2
|
target-version = ['py37']
|
|
3
|
-
line-length =
|
|
3
|
+
line-length = 100
|
|
4
4
|
|
|
5
5
|
[tool.ruff]
|
|
6
|
-
unfixable = []
|
|
6
|
+
lint.unfixable = []
|
|
7
7
|
exclude = [
|
|
8
8
|
"__pycache__",
|
|
9
|
+
"tests/"
|
|
9
10
|
]
|
|
10
|
-
ignore = [
|
|
11
|
+
lint.ignore = [
|
|
11
12
|
"B008", # do not perform function calls in argument defaults
|
|
12
13
|
"E501", # line too long
|
|
13
14
|
"N815", # mixedCase variable in class scope
|
|
@@ -18,7 +19,7 @@ ignore = [
|
|
|
18
19
|
"PLR0913", # too many arguments
|
|
19
20
|
]
|
|
20
21
|
target-version = "py37"
|
|
21
|
-
select = [
|
|
22
|
+
lint.select = [
|
|
22
23
|
"E",
|
|
23
24
|
"F",
|
|
24
25
|
"W",
|
{robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework-debug
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.0
|
|
4
4
|
Summary: RobotFramework debug shell
|
|
5
5
|
Home-page: https://github.com/imbus/robotframework-debug/
|
|
6
6
|
Author: René Rohner
|
|
@@ -22,10 +22,15 @@ Classifier: Programming Language :: Python :: 3.7
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.8
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.9
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.10
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
25
26
|
Classifier: Topic :: Utilities
|
|
26
27
|
Requires-Python: >=3.8.0
|
|
27
28
|
Description-Content-Type: text/x-rst
|
|
28
29
|
License-File: LICENSE
|
|
30
|
+
Requires-Dist: prompt-toolkit>=3.0.38
|
|
31
|
+
Requires-Dist: robotframework<8.0,>=5.0
|
|
32
|
+
Requires-Dist: pygments>=2.14.0
|
|
33
|
+
Requires-Dist: pyperclip>=1.8.2
|
|
29
34
|
|
|
30
35
|
Debug Library for Robot Framework
|
|
31
36
|
=================================
|
|
@@ -1,21 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
|
|
3
|
-
import io
|
|
4
|
-
import os
|
|
5
3
|
import re
|
|
4
|
+
from pathlib import Path
|
|
6
5
|
|
|
7
6
|
from setuptools import setup
|
|
8
7
|
|
|
9
|
-
ROOT = os.path.abspath(os.path.dirname(__file__))
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
with io.open(os.path.join(ROOT, *names), encoding=kwargs.get("encoding", "utf8")) as fp:
|
|
14
|
-
return fp.read()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def find_version(*file_paths):
|
|
18
|
-
version_file = read(*file_paths)
|
|
9
|
+
def find_version(file_paths):
|
|
10
|
+
version_file = Path(file_paths).read_text()
|
|
19
11
|
version_match = re.search(r"^VERSION = ['\"]([^'\"]*)['\"]", version_file, re.M)
|
|
20
12
|
if version_match:
|
|
21
13
|
return version_match.group(1)
|
|
@@ -26,7 +18,7 @@ setup(
|
|
|
26
18
|
name="robotframework-debug",
|
|
27
19
|
version=find_version("RobotDebug/version.py"),
|
|
28
20
|
description="RobotFramework debug shell",
|
|
29
|
-
long_description=
|
|
21
|
+
long_description=Path("README.rst").read_text(),
|
|
30
22
|
long_description_content_type=("text/x-rst"),
|
|
31
23
|
author="René Rohner",
|
|
32
24
|
author_email="snooz@postoe.de",
|
|
@@ -43,7 +35,7 @@ setup(
|
|
|
43
35
|
keywords="robotframework,debug,shell,repl",
|
|
44
36
|
install_requires=[
|
|
45
37
|
"prompt-toolkit >= 3.0.38",
|
|
46
|
-
"robotframework >= 5.0",
|
|
38
|
+
"robotframework >= 5.0, < 8.0",
|
|
47
39
|
"pygments >= 2.14.0",
|
|
48
40
|
"pyperclip >= 1.8.2",
|
|
49
41
|
],
|
|
@@ -63,6 +55,7 @@ setup(
|
|
|
63
55
|
"Programming Language :: Python :: 3.8",
|
|
64
56
|
"Programming Language :: Python :: 3.9",
|
|
65
57
|
"Programming Language :: Python :: 3.10",
|
|
58
|
+
"Programming Language :: Python :: 3.11",
|
|
66
59
|
"Topic :: Utilities",
|
|
67
60
|
],
|
|
68
61
|
)
|
|
@@ -153,7 +153,7 @@ def step_functional_testing():
|
|
|
153
153
|
check_command("", "=> BuiltIn.Log To Console another test case") # repeat last command
|
|
154
154
|
|
|
155
155
|
# Exit the debug mode started by Debug keyword.
|
|
156
|
-
check_command("c", "Exit shell.*
|
|
156
|
+
check_command("c", "Exit shell.*another test case.*end") # continue
|
|
157
157
|
# Exit the interactive shell started by "DebugLibrary/shell.py".
|
|
158
158
|
check_command("c", "Report: ")
|
|
159
159
|
child.wait()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "4.3.4"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robotframework-debug-4.3.4 → robotframework-debug-4.5.0}/robotframework_debug.egg-info/not-zip-safe
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|