robotcode-repl-server 0.100.2__py3-none-any.whl → 0.101.0__py3-none-any.whl
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/repl_server/__version__.py +1 -1
- robotcode/repl_server/interpreter.py +50 -144
- {robotcode_repl_server-0.100.2.dist-info → robotcode_repl_server-0.101.0.dist-info}/METADATA +3 -3
- {robotcode_repl_server-0.100.2.dist-info → robotcode_repl_server-0.101.0.dist-info}/RECORD +7 -8
- robotcode/repl_server/html_writer.py +0 -324
- {robotcode_repl_server-0.100.2.dist-info → robotcode_repl_server-0.101.0.dist-info}/WHEEL +0 -0
- {robotcode_repl_server-0.100.2.dist-info → robotcode_repl_server-0.101.0.dist-info}/entry_points.txt +0 -0
- {robotcode_repl_server-0.100.2.dist-info → robotcode_repl_server-0.101.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.
|
1
|
+
__version__ = "0.101.0"
|
@@ -1,16 +1,17 @@
|
|
1
|
+
import textwrap
|
1
2
|
from dataclasses import dataclass, field
|
2
|
-
from datetime import datetime
|
3
|
+
from datetime import datetime, timedelta
|
3
4
|
from pathlib import Path
|
4
5
|
from threading import Event
|
5
6
|
from typing import TYPE_CHECKING, Iterator, List, Optional, Protocol, Union, runtime_checkable
|
6
|
-
from uuid import uuid4
|
7
7
|
|
8
8
|
from robot.running import Keyword
|
9
|
+
from robot.utils.markuputils import html_format
|
10
|
+
from robot.utils.robottime import elapsed_time_to_string
|
9
11
|
|
10
12
|
from robotcode.core.utils.dataclasses import as_json
|
11
13
|
from robotcode.repl.base_interpreter import BaseInterpreter, is_true
|
12
|
-
|
13
|
-
from .html_writer import Element, create_keyword_html, create_message_html
|
14
|
+
from robotcode.robot.utils import get_robot_version
|
14
15
|
|
15
16
|
if TYPE_CHECKING:
|
16
17
|
from robot import result, running
|
@@ -76,13 +77,28 @@ class KeywordResultData(ResultData):
|
|
76
77
|
message: str
|
77
78
|
start_time: Optional[str]
|
78
79
|
end_time: Optional[str]
|
79
|
-
elapsed_time: Optional[
|
80
|
+
elapsed_time: Optional[str]
|
80
81
|
|
81
82
|
items: List[ResultData] = field(default_factory=list)
|
82
83
|
|
83
84
|
node_type: str = "keyword"
|
84
85
|
|
85
86
|
|
87
|
+
if get_robot_version() < (7, 0):
|
88
|
+
|
89
|
+
def make_elapsed_time_str(elapsed_time: Union[timedelta, int, float, None]) -> Optional[str]:
|
90
|
+
if elapsed_time is None:
|
91
|
+
return None
|
92
|
+
return str(elapsed_time_to_string(elapsed_time))
|
93
|
+
|
94
|
+
else:
|
95
|
+
|
96
|
+
def make_elapsed_time_str(elapsed_time: Union[timedelta, int, float, None]) -> Optional[str]:
|
97
|
+
if elapsed_time is None:
|
98
|
+
return None
|
99
|
+
return str(elapsed_time_to_string(elapsed_time, seconds=True))
|
100
|
+
|
101
|
+
|
86
102
|
class Interpreter(BaseInterpreter):
|
87
103
|
def __init__(
|
88
104
|
self,
|
@@ -93,45 +109,24 @@ class Interpreter(BaseInterpreter):
|
|
93
109
|
self.has_input = Event()
|
94
110
|
self.executed = Event()
|
95
111
|
self._code: List[str] = []
|
96
|
-
self._html_result: Optional[Element] = None
|
97
|
-
self._result_stack: List[Element] = []
|
98
|
-
self._output_stack: List[Element] = []
|
99
|
-
self._shadow_marker: Optional[str] = None
|
100
112
|
self._success: Optional[bool] = None
|
101
113
|
self._result_data: Optional[ResultData] = None
|
102
114
|
self._result_data_stack: List[ResultData] = []
|
103
115
|
self.collect_messages: bool = False
|
104
116
|
self._has_shutdown = False
|
117
|
+
self._cell_errors: List[str] = []
|
105
118
|
|
106
119
|
def shutdown(self) -> None:
|
107
120
|
self._code = []
|
108
121
|
self._has_shutdown = True
|
109
122
|
self.has_input.set()
|
110
|
-
# self.executed.set()
|
111
123
|
|
112
124
|
def execute(self, source: str) -> ExecutionResult:
|
113
|
-
self._result_stack = []
|
114
125
|
self._result_data_stack = []
|
115
126
|
|
116
127
|
self._success = None
|
117
128
|
try:
|
118
|
-
self.
|
119
|
-
|
120
|
-
html_result = Element("div", classes=["robot-results"])
|
121
|
-
|
122
|
-
with html_result.tag(
|
123
|
-
"div", attributes={"data-shadow-marker": self._shadow_marker}, styles={"display": "none"}
|
124
|
-
):
|
125
|
-
pass
|
126
|
-
|
127
|
-
outer_test: Optional[Element] = None
|
128
|
-
with html_result.tag("div", classes=["result_body"]) as body:
|
129
|
-
with body.tag("div", classes=["test"]) as test:
|
130
|
-
with test.tag("div", classes=["children"], styles={"display": "block"}):
|
131
|
-
pass
|
132
|
-
outer_test = test
|
133
|
-
|
134
|
-
self._html_result = outer_test
|
129
|
+
self._cell_errors = []
|
135
130
|
self._result_data = RootResultData()
|
136
131
|
|
137
132
|
self.executed.clear()
|
@@ -148,12 +143,18 @@ class Interpreter(BaseInterpreter):
|
|
148
143
|
ExecutionOutput(
|
149
144
|
"x-application/robotframework-repl-log", as_json(self._result_data, compact=True)
|
150
145
|
),
|
151
|
-
|
152
|
-
"
|
146
|
+
*(
|
147
|
+
[ExecutionOutput("application/vnd.code.notebook.stderr", "\n".join(self._cell_errors))]
|
148
|
+
if self._cell_errors
|
149
|
+
else []
|
153
150
|
),
|
154
151
|
]
|
155
152
|
if self._success is not None
|
156
|
-
else
|
153
|
+
else (
|
154
|
+
[ExecutionOutput("application/vnd.code.notebook.stderr", "\n".join(self._cell_errors))]
|
155
|
+
if self._cell_errors
|
156
|
+
else []
|
157
|
+
)
|
157
158
|
),
|
158
159
|
)
|
159
160
|
except BaseException as e:
|
@@ -164,7 +165,12 @@ class Interpreter(BaseInterpreter):
|
|
164
165
|
s = self._code.pop(0)
|
165
166
|
test, errors = self.get_test_body_from_string(s)
|
166
167
|
if errors:
|
167
|
-
|
168
|
+
self._cell_errors.append(
|
169
|
+
"CellInputError: " + ("\n" + textwrap.indent("\n".join(errors), " "))
|
170
|
+
if len(errors) > 1
|
171
|
+
else errors[0]
|
172
|
+
)
|
173
|
+
# raise CellInputError(errors)
|
168
174
|
|
169
175
|
for kw in test.body:
|
170
176
|
yield kw
|
@@ -183,29 +189,6 @@ class Interpreter(BaseInterpreter):
|
|
183
189
|
)
|
184
190
|
)
|
185
191
|
|
186
|
-
if level in ("DEBUG", "TRACE"):
|
187
|
-
return
|
188
|
-
|
189
|
-
if self._html_result is None:
|
190
|
-
return
|
191
|
-
|
192
|
-
items = next(
|
193
|
-
(
|
194
|
-
i
|
195
|
-
for i in self._html_result.children
|
196
|
-
if isinstance(i, Element) and i.tag_name == "div" and i.classes is not None and "children" in i.classes
|
197
|
-
),
|
198
|
-
None,
|
199
|
-
)
|
200
|
-
if items is None:
|
201
|
-
items = Element("div", classes=["children"])
|
202
|
-
self._html_result.add_element(items)
|
203
|
-
|
204
|
-
id = f"message-{len(items.children)}"
|
205
|
-
|
206
|
-
message_data = create_message_html(id, message, level, html, timestamp, shadow_root_id=self._shadow_marker)
|
207
|
-
items.add_element(message_data)
|
208
|
-
|
209
192
|
def message(
|
210
193
|
self, message: str, level: str, html: Union[str, bool] = False, timestamp: Union[datetime, str, None] = None
|
211
194
|
) -> None:
|
@@ -232,7 +215,7 @@ class Interpreter(BaseInterpreter):
|
|
232
215
|
name=result.name if getattr(result, "name", None) else "",
|
233
216
|
owner=result.owner if getattr(result, "owner", None) else "",
|
234
217
|
source_name=result.source_name if getattr(result, "source_name", None) else "",
|
235
|
-
doc=result.doc if getattr(result, "doc", None) else "",
|
218
|
+
doc=html_format(result.doc) if getattr(result, "doc", None) else "",
|
236
219
|
args=list(result.args) if getattr(result, "args", None) else [],
|
237
220
|
assign=list(result.assign) if getattr(result, "assign", None) else [],
|
238
221
|
tags=list(result.tags) if getattr(result, "tags", None) else [],
|
@@ -242,43 +225,29 @@ class Interpreter(BaseInterpreter):
|
|
242
225
|
message=result.message,
|
243
226
|
start_time=result.starttime,
|
244
227
|
end_time=result.endtime,
|
245
|
-
elapsed_time=
|
228
|
+
elapsed_time=(
|
229
|
+
make_elapsed_time_str(result.elapsedtime)
|
230
|
+
if get_robot_version() < (7, 0)
|
231
|
+
else make_elapsed_time_str(result.elapsed_time)
|
232
|
+
),
|
246
233
|
)
|
247
234
|
if self._result_data is not None and isinstance(self._result_data, ResultDataWithChildren):
|
248
235
|
self._result_data.items.append(kw_data)
|
249
236
|
self._result_data_stack.append(self._result_data)
|
250
237
|
self._result_data = kw_data
|
251
238
|
|
252
|
-
if self._html_result is not None:
|
253
|
-
self._result_stack.append(self._html_result)
|
254
|
-
kw = self.create_keyword_html_element(result)
|
255
|
-
|
256
|
-
children = next(
|
257
|
-
(
|
258
|
-
i
|
259
|
-
for i in self._html_result.children
|
260
|
-
if isinstance(i, Element)
|
261
|
-
and i.tag_name == "div"
|
262
|
-
and i.classes is not None
|
263
|
-
and "children" in i.classes
|
264
|
-
),
|
265
|
-
None,
|
266
|
-
)
|
267
|
-
|
268
|
-
if children is None:
|
269
|
-
self._html_result.add_element(kw)
|
270
|
-
else:
|
271
|
-
children.add_element(kw)
|
272
|
-
|
273
|
-
self._html_result = kw
|
274
|
-
|
275
239
|
def end_keyword(self, data: "running.Keyword", result: "result.Keyword") -> None:
|
276
240
|
if data.type in ["IF/ELSE ROOT", "TRY/EXCEPT ROOT"]:
|
277
241
|
return
|
242
|
+
|
278
243
|
if self._result_data is not None:
|
279
244
|
if isinstance(self._result_data, KeywordResultData):
|
280
245
|
self._result_data.end_time = result.endtime
|
281
|
-
self._result_data.elapsed_time =
|
246
|
+
self._result_data.elapsed_time = (
|
247
|
+
make_elapsed_time_str(result.elapsedtime)
|
248
|
+
if get_robot_version() < (7, 0)
|
249
|
+
else make_elapsed_time_str(result.elapsed_time)
|
250
|
+
)
|
282
251
|
self._result_data.status = result.status
|
283
252
|
self._result_data.message = result.message
|
284
253
|
|
@@ -289,69 +258,6 @@ class Interpreter(BaseInterpreter):
|
|
289
258
|
elif result.status == "PASS" and self.last_result is not False:
|
290
259
|
self._success = True
|
291
260
|
|
292
|
-
if self._html_result is not None and isinstance(self._html_result, Element):
|
293
|
-
kw = self.create_keyword_html_element(result)
|
294
|
-
|
295
|
-
old_children = next(
|
296
|
-
(
|
297
|
-
i
|
298
|
-
for i in self._html_result.children
|
299
|
-
if isinstance(i, Element)
|
300
|
-
and i.tag_name == "div"
|
301
|
-
and i.classes is not None
|
302
|
-
and "children" in i.classes
|
303
|
-
),
|
304
|
-
None,
|
305
|
-
)
|
306
|
-
if old_children is not None:
|
307
|
-
new_children = next(
|
308
|
-
(
|
309
|
-
i
|
310
|
-
for i in kw.children
|
311
|
-
if isinstance(i, Element)
|
312
|
-
and i.tag_name == "div"
|
313
|
-
and i.classes is not None
|
314
|
-
and "children" in i.classes
|
315
|
-
),
|
316
|
-
None,
|
317
|
-
)
|
318
|
-
if new_children is None:
|
319
|
-
new_children = Element("div", classes=["children"])
|
320
|
-
self._html_result.add_element(new_children)
|
321
|
-
|
322
|
-
for old_child in old_children.children:
|
323
|
-
if not (
|
324
|
-
isinstance(old_child, Element)
|
325
|
-
and old_child.tag_name == "table"
|
326
|
-
and old_child.classes is not None
|
327
|
-
and "metadata" in old_child.classes
|
328
|
-
):
|
329
|
-
new_children.add_element(old_child)
|
330
|
-
|
331
|
-
self._html_result.children = kw.children
|
332
|
-
|
333
|
-
self._html_result = self._result_stack.pop()
|
334
|
-
|
335
|
-
def create_keyword_html_element(self, result: "result.Keyword") -> Element:
|
336
|
-
return create_keyword_html(
|
337
|
-
id=result.id,
|
338
|
-
name=result.name if getattr(result, "name", None) else None,
|
339
|
-
owner=result.owner if getattr(result, "owner", None) else None,
|
340
|
-
source_name=result.source_name if getattr(result, "source_name", None) else None,
|
341
|
-
doc=result.doc if getattr(result, "doc", None) else None,
|
342
|
-
args=result.args if getattr(result, "args", None) else (),
|
343
|
-
assign=result.assign if getattr(result, "assign", None) else (),
|
344
|
-
tags=result.tags if getattr(result, "tags", None) else (),
|
345
|
-
timeout=result.timeout if getattr(result, "timeout", None) else None,
|
346
|
-
type=result.type,
|
347
|
-
status=result.status,
|
348
|
-
message=result.message,
|
349
|
-
start_time=result.starttime,
|
350
|
-
end_time=result.endtime,
|
351
|
-
elapsed_time=result.elapsedtime,
|
352
|
-
shadow_root_id=self._shadow_marker,
|
353
|
-
)
|
354
|
-
|
355
261
|
def run_input(self) -> None:
|
356
262
|
self.has_input.wait()
|
357
263
|
if self._has_shutdown:
|
{robotcode_repl_server-0.100.2.dist-info → robotcode_repl_server-0.101.0.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: robotcode-repl-server
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.101.0
|
4
4
|
Summary: RobotCode REPL Server for Robot Framework
|
5
5
|
Project-URL: Homepage, https://robotcode.io
|
6
6
|
Project-URL: Donate, https://opencollective.com/robotcode
|
@@ -24,8 +24,8 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
24
24
|
Classifier: Topic :: Utilities
|
25
25
|
Classifier: Typing :: Typed
|
26
26
|
Requires-Python: >=3.8
|
27
|
-
Requires-Dist: robotcode-jsonrpc2==0.
|
28
|
-
Requires-Dist: robotcode-runner==0.
|
27
|
+
Requires-Dist: robotcode-jsonrpc2==0.101.0
|
28
|
+
Requires-Dist: robotcode-runner==0.101.0
|
29
29
|
Description-Content-Type: text/markdown
|
30
30
|
|
31
31
|
# robotcode-repl-server
|
@@ -1,14 +1,13 @@
|
|
1
1
|
robotcode/repl_server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
robotcode/repl_server/__version__.py,sha256=
|
2
|
+
robotcode/repl_server/__version__.py,sha256=tErTpFCmZUfGTNOXJztDNy6EvOoUJyR9YDFmyRr1HdE,24
|
3
3
|
robotcode/repl_server/cli.py,sha256=yxgD_4QFwRD-BSGxto3MeimKess5_KZWkUJldERBsSk,5970
|
4
4
|
robotcode/repl_server/hooks.py,sha256=4O9H8cefHc6T7erjPxzU941w3KWytTBB5gmvYb4bs_I,196
|
5
|
-
robotcode/repl_server/
|
6
|
-
robotcode/repl_server/interpreter.py,sha256=5Xgr2bACjU2-hOvZYe2p4MP4c9K3XivsUpyFd6Vbrz4,12557
|
5
|
+
robotcode/repl_server/interpreter.py,sha256=gzCwKiYfzVuOl4FHC_lpt5HLH8WdKwMz2CKmgbATFKk,9053
|
7
6
|
robotcode/repl_server/protocol.py,sha256=4Eeoz45DfkKuzMZ7NJed8x0m0SWJdKkeFbnuO3e6DgQ,980
|
8
7
|
robotcode/repl_server/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
|
9
8
|
robotcode/repl_server/server.py,sha256=zzFsD6ds56d4GQJKXoysVZP-oiS08AtMKeyLKXH9Fss,746
|
10
|
-
robotcode_repl_server-0.
|
11
|
-
robotcode_repl_server-0.
|
12
|
-
robotcode_repl_server-0.
|
13
|
-
robotcode_repl_server-0.
|
14
|
-
robotcode_repl_server-0.
|
9
|
+
robotcode_repl_server-0.101.0.dist-info/METADATA,sha256=c9BuRjQ0U2RsM6uTrSkiq_qdqLQSy65b9xFsPoLbMV8,2112
|
10
|
+
robotcode_repl_server-0.101.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
11
|
+
robotcode_repl_server-0.101.0.dist-info/entry_points.txt,sha256=U_1iYu71VNyPq_epO0fXHki3B4BE4gR2mbZFAOWN1cg,54
|
12
|
+
robotcode_repl_server-0.101.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
13
|
+
robotcode_repl_server-0.101.0.dist-info/RECORD,,
|
@@ -1,324 +0,0 @@
|
|
1
|
-
from contextlib import contextmanager
|
2
|
-
from datetime import datetime, timedelta
|
3
|
-
from typing import Any, Dict, Generator, List, Optional, Sequence, TypeVar, Union
|
4
|
-
|
5
|
-
from robot.utils.robottime import elapsed_time_to_string
|
6
|
-
|
7
|
-
from robotcode.repl.base_interpreter import is_true
|
8
|
-
from robotcode.robot.utils import get_robot_version
|
9
|
-
|
10
|
-
|
11
|
-
class ElementDataBase:
|
12
|
-
def as_str(self, indent: int = 0) -> str:
|
13
|
-
raise NotImplementedError
|
14
|
-
|
15
|
-
def __str__(self) -> str:
|
16
|
-
return self.as_str(0)
|
17
|
-
|
18
|
-
|
19
|
-
_T = TypeVar("_T", bound=ElementDataBase)
|
20
|
-
|
21
|
-
|
22
|
-
class TextElement(ElementDataBase):
|
23
|
-
def __init__(self, text: str) -> None:
|
24
|
-
self.text = text
|
25
|
-
|
26
|
-
def as_str(self, indent: int = 0) -> str:
|
27
|
-
return f"{' '*indent}{self.text}"
|
28
|
-
|
29
|
-
|
30
|
-
class RawElement(ElementDataBase):
|
31
|
-
def __init__(self, text: str) -> None:
|
32
|
-
self.text = text
|
33
|
-
|
34
|
-
def as_str(self, indent: int = 0) -> str:
|
35
|
-
return f"{' '*indent}{self.text}"
|
36
|
-
|
37
|
-
|
38
|
-
class Element(ElementDataBase):
|
39
|
-
def __init__(
|
40
|
-
self,
|
41
|
-
tag_name: str,
|
42
|
-
text: Optional[str] = None,
|
43
|
-
classes: Optional[List[str]] = None,
|
44
|
-
styles: Optional[Dict[str, str]] = None,
|
45
|
-
attributes: Optional[Dict[str, str]] = None,
|
46
|
-
**kwargs: Any,
|
47
|
-
) -> None:
|
48
|
-
self.tag_name = tag_name
|
49
|
-
self.classes = classes
|
50
|
-
self.styles = styles
|
51
|
-
if attributes is None:
|
52
|
-
attributes = {}
|
53
|
-
attributes.update(kwargs)
|
54
|
-
self.attributes = attributes
|
55
|
-
self.children: List[ElementDataBase] = []
|
56
|
-
|
57
|
-
if text is not None:
|
58
|
-
self.add_element(TextElement(text))
|
59
|
-
|
60
|
-
def add_element(self, child: _T) -> _T:
|
61
|
-
self.children.append(child)
|
62
|
-
return child
|
63
|
-
|
64
|
-
@contextmanager
|
65
|
-
def tag(
|
66
|
-
self,
|
67
|
-
tag_name: str,
|
68
|
-
*,
|
69
|
-
text: Optional[str] = None,
|
70
|
-
classes: Optional[List[str]] = None,
|
71
|
-
styles: Optional[Dict[str, str]] = None,
|
72
|
-
attributes: Optional[Dict[str, str]] = None,
|
73
|
-
**kwargs: Any,
|
74
|
-
) -> Generator["Element", None, None]:
|
75
|
-
element = Element(tag_name, text=text, classes=classes, styles=styles, attributes=attributes, **kwargs)
|
76
|
-
|
77
|
-
yield element
|
78
|
-
|
79
|
-
self.add_element(element)
|
80
|
-
|
81
|
-
def add_raw(self, text: Any) -> None:
|
82
|
-
self.add_element(RawElement(str(text)))
|
83
|
-
|
84
|
-
def add_text(self, text: Any) -> None:
|
85
|
-
self.add_element(TextElement(str(text)))
|
86
|
-
|
87
|
-
def _build_attributes(self) -> str:
|
88
|
-
result = []
|
89
|
-
if self.classes:
|
90
|
-
result.append(f'class="{" ".join(s for s in self.classes if s)}"')
|
91
|
-
if self.styles:
|
92
|
-
result.append(f'style="{"; ".join(f"{k}: {v}" for k, v in self.styles.items() if v)}"')
|
93
|
-
if self.attributes:
|
94
|
-
result.extend(f'{k}="{v}"' for k, v in self.attributes.items())
|
95
|
-
|
96
|
-
return " ".join(result)
|
97
|
-
|
98
|
-
NON_BREAKABLE_TAGS = {"span", "a", "b", "i", "u", "strong", "em", "code", "pre", "tt", "samp", "kbd", "var", "td"}
|
99
|
-
|
100
|
-
def as_str(self, indent: int = 0, *, only_children: bool = False) -> str:
|
101
|
-
if not only_children:
|
102
|
-
attributes = self._build_attributes()
|
103
|
-
|
104
|
-
if attributes:
|
105
|
-
start_tag = f"<{self.tag_name} {attributes}>"
|
106
|
-
else:
|
107
|
-
start_tag = f"<{self.tag_name}>"
|
108
|
-
|
109
|
-
end_tag = f"</{self.tag_name}>"
|
110
|
-
|
111
|
-
result = " " * indent + start_tag
|
112
|
-
else:
|
113
|
-
result = ""
|
114
|
-
end_tag = None
|
115
|
-
|
116
|
-
if self.children:
|
117
|
-
result += "\n" if self.tag_name not in self.NON_BREAKABLE_TAGS else ""
|
118
|
-
for child in self.children:
|
119
|
-
result += child.as_str((indent + 1) if self.tag_name not in self.NON_BREAKABLE_TAGS else 0) + (
|
120
|
-
"\n" if self.tag_name not in self.NON_BREAKABLE_TAGS else ""
|
121
|
-
)
|
122
|
-
result += (" " * indent) if self.tag_name not in self.NON_BREAKABLE_TAGS else ""
|
123
|
-
|
124
|
-
if end_tag:
|
125
|
-
result += end_tag
|
126
|
-
|
127
|
-
return result
|
128
|
-
|
129
|
-
|
130
|
-
def create_keyword_html(
|
131
|
-
id: Optional[str] = None,
|
132
|
-
name: Optional[str] = "",
|
133
|
-
owner: Optional[str] = None,
|
134
|
-
source_name: Optional[str] = None,
|
135
|
-
doc: Optional[str] = "",
|
136
|
-
args: Sequence[str] = (),
|
137
|
-
assign: Sequence[str] = (),
|
138
|
-
tags: Sequence[str] = (),
|
139
|
-
timeout: Optional[str] = None,
|
140
|
-
type: str = "KEYWORD",
|
141
|
-
status: str = "FAIL",
|
142
|
-
message: str = "",
|
143
|
-
start_time: Union[datetime, str, None] = None,
|
144
|
-
end_time: Union[datetime, str, None] = None,
|
145
|
-
elapsed_time: Union[timedelta, int, float, None] = None,
|
146
|
-
shadow_root_id: Optional[str] = None,
|
147
|
-
) -> Element:
|
148
|
-
result = Element("div", classes=["keyword"], id=id)
|
149
|
-
|
150
|
-
elapsed_time_str = (
|
151
|
-
(
|
152
|
-
elapsed_time_to_string(elapsed_time)
|
153
|
-
if get_robot_version() < (7, 0)
|
154
|
-
else elapsed_time_to_string(elapsed_time, seconds=True)
|
155
|
-
)
|
156
|
-
if elapsed_time is not None
|
157
|
-
else ""
|
158
|
-
)
|
159
|
-
|
160
|
-
with result.tag(
|
161
|
-
"div",
|
162
|
-
classes=["element-header", "closed" if status not in ["FAIL"] else ""],
|
163
|
-
onclick=f"toggleKeyword('{id}', '{shadow_root_id}')",
|
164
|
-
) as e_element_header:
|
165
|
-
with e_element_header.tag(
|
166
|
-
"div",
|
167
|
-
classes=["element-header-left"],
|
168
|
-
title=f"{type.upper()} {owner}.{name} [{status}]",
|
169
|
-
) as e_header_left:
|
170
|
-
if elapsed_time is not None:
|
171
|
-
with e_header_left.tag("span", classes=["elapsed"]) as e_elapsed:
|
172
|
-
e_elapsed.add_text(elapsed_time_str)
|
173
|
-
with e_header_left.tag("span", classes=["label", status.lower()]) as e_label:
|
174
|
-
e_label.add_text(str(type).upper())
|
175
|
-
with e_header_left.tag("span", classes=["assign"]) as e_assign:
|
176
|
-
e_assign.add_text(" ".join(assign))
|
177
|
-
with e_header_left.tag("span", classes=["name"]) as e_name:
|
178
|
-
with e_name.tag("span", classes=["parent-name"]) as parent_name:
|
179
|
-
parent_name.add_text((owner + " . ") if owner else "")
|
180
|
-
e_name.add_text(name)
|
181
|
-
e_header_left.add_raw(" ")
|
182
|
-
with e_header_left.tag("span", classes=["arg"]) as args_tag:
|
183
|
-
args_tag.add_text(" ".join(args))
|
184
|
-
with e_element_header.tag("div", classes=["element-header-right"]) as e_header_right:
|
185
|
-
with e_header_right.tag(
|
186
|
-
"div",
|
187
|
-
classes=["expand"],
|
188
|
-
title="Expand all",
|
189
|
-
onclick=f"expandAll(event, '{id}', '{shadow_root_id}')",
|
190
|
-
):
|
191
|
-
pass
|
192
|
-
with e_header_right.tag(
|
193
|
-
"div",
|
194
|
-
classes=["collapse"],
|
195
|
-
title="Collapse all",
|
196
|
-
onclick=f"collapseAll(event, '{id}', '{shadow_root_id}')",
|
197
|
-
):
|
198
|
-
pass
|
199
|
-
with e_header_right.tag(
|
200
|
-
"div",
|
201
|
-
classes=["link"],
|
202
|
-
title="Highlight this item",
|
203
|
-
onclick=f"makeElementVisible(event, '{id}', '{shadow_root_id}')",
|
204
|
-
):
|
205
|
-
pass
|
206
|
-
with e_element_header.tag("div", classes=["element-header-toggle"], title="Toggle visibility"):
|
207
|
-
pass
|
208
|
-
|
209
|
-
with result.tag(
|
210
|
-
"div", classes=["children", "populated"], styles={"display": "none" if status not in ["FAIL"] else "block"}
|
211
|
-
) as e_children:
|
212
|
-
with e_children.tag("table", classes=["metadata", "keyword-metadata"]) as e_body:
|
213
|
-
if doc:
|
214
|
-
with e_body.tag("tr") as tr:
|
215
|
-
with tr.tag("th", text="Documentation:"):
|
216
|
-
pass
|
217
|
-
with tr.tag("td", classes=["doc"]) as td:
|
218
|
-
td.add_text(doc)
|
219
|
-
if tags:
|
220
|
-
with e_body.tag("tr") as tr:
|
221
|
-
with tr.tag("th", text="Tags:"):
|
222
|
-
pass
|
223
|
-
with tr.tag("td", classes=["tags"]) as td:
|
224
|
-
td.add_text(", ".join(tags))
|
225
|
-
if timeout:
|
226
|
-
with e_body.tag("tr") as tr:
|
227
|
-
with tr.tag("th", text="Timeout:"):
|
228
|
-
pass
|
229
|
-
with tr.tag("td", classes=["timeout"]) as td:
|
230
|
-
td.add_text(timeout)
|
231
|
-
if source_name:
|
232
|
-
with e_body.tag("tr") as tr:
|
233
|
-
with tr.tag("th", text="Source:"):
|
234
|
-
pass
|
235
|
-
with tr.tag("td", classes=["source"]) as td:
|
236
|
-
td.add_text(source_name)
|
237
|
-
with e_body.tag("tr") as tr:
|
238
|
-
with tr.tag("th", text="Start / End / Elapsed:"):
|
239
|
-
pass
|
240
|
-
with tr.tag("td", classes=["message"]) as td:
|
241
|
-
td.add_text(str(start_time) + " / " + str(end_time) + " / " + elapsed_time_str)
|
242
|
-
if message:
|
243
|
-
with e_body.tag("tr") as tr:
|
244
|
-
with tr.tag("th", text="Message:"):
|
245
|
-
pass
|
246
|
-
with tr.tag("td", classes=["message"]) as td:
|
247
|
-
td.add_text(message)
|
248
|
-
|
249
|
-
return result
|
250
|
-
|
251
|
-
|
252
|
-
def create_message_html(
|
253
|
-
id: str,
|
254
|
-
message: str,
|
255
|
-
level: str,
|
256
|
-
html: Union[str, bool] = False,
|
257
|
-
timestamp: Union[datetime, str, None] = None,
|
258
|
-
shadow_root_id: Optional[str] = None,
|
259
|
-
) -> Element:
|
260
|
-
result = Element("table", classes=["messages", f"{level.lower()}-message"], id=id)
|
261
|
-
|
262
|
-
with result.tag("tr", classes=["message-row"]) as tr:
|
263
|
-
with tr.tag("td", classes=["time"]) as td:
|
264
|
-
if isinstance(timestamp, datetime):
|
265
|
-
td.add_text(timestamp.strftime("%H:%M:%S"))
|
266
|
-
else:
|
267
|
-
td.add_text(timestamp)
|
268
|
-
with tr.tag("td", classes=["level", level.lower()]) as td:
|
269
|
-
with td.tag("span", classes=["label", level.lower()]) as sp:
|
270
|
-
sp.add_text(level.upper())
|
271
|
-
with tr.tag("td", classes=["message"]) as td:
|
272
|
-
if is_true(html):
|
273
|
-
td.add_raw(message)
|
274
|
-
else:
|
275
|
-
td.add_text(message)
|
276
|
-
with tr.tag(
|
277
|
-
"td",
|
278
|
-
classes=["select-message"],
|
279
|
-
onclick=f"selectMessage('{id}', '{shadow_root_id}')",
|
280
|
-
title="Select message text",
|
281
|
-
) as td:
|
282
|
-
with td.tag("div"):
|
283
|
-
pass
|
284
|
-
|
285
|
-
return result
|
286
|
-
|
287
|
-
|
288
|
-
if __name__ == "__main__":
|
289
|
-
# div = Element("div", id="main", classes=["test", "test2"], styles={"color": "red", "font-size": "12px"})
|
290
|
-
# p = div.add_element(Element("p", text="Hello, world!"))
|
291
|
-
# p.add_element(Element("span", text="This is a test"))
|
292
|
-
# print(div)
|
293
|
-
|
294
|
-
# body = Element("body")
|
295
|
-
# with body.tag("div", id="main", classes=["test", "test2"], styles={"color": "red"}) as div:
|
296
|
-
# with div.tag("p") as p:
|
297
|
-
# p.add_text("Hello, world!")
|
298
|
-
# with p.tag("span") as span:
|
299
|
-
# span.add_text("This is a test")
|
300
|
-
# with span.tag("br"):
|
301
|
-
# pass
|
302
|
-
# span.add_text("This is a test")
|
303
|
-
# with span.tag("br", id="test"):
|
304
|
-
# pass
|
305
|
-
# print(body)
|
306
|
-
|
307
|
-
# r = create_keyword_html(
|
308
|
-
# id="ts-1-2-3-4-5-6",
|
309
|
-
# name="Test Keyword",
|
310
|
-
# owner="Test Library",
|
311
|
-
# doc="This is a test keyword",
|
312
|
-
# args=("arg1", "arg2"),
|
313
|
-
# assign=("${var1}", "${var2}"),
|
314
|
-
# tags=("tag1", "tag2"),
|
315
|
-
# timeout="10s",
|
316
|
-
# type="KEYWORD",
|
317
|
-
# status="PASS",
|
318
|
-
# message="This is a test message",
|
319
|
-
# start_time=datetime.now(timezone.utc),
|
320
|
-
# end_time=datetime.now(timezone.utc),
|
321
|
-
# elapsed_time=timedelta(seconds=5),
|
322
|
-
# )
|
323
|
-
r = create_message_html("ts-1-2-3-4-5-6", "This is a test message", "INFO", timestamp="2021-10-10 12:00:00")
|
324
|
-
print(r)
|
File without changes
|
{robotcode_repl_server-0.100.2.dist-info → robotcode_repl_server-0.101.0.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|