robotcode-repl-server 2.7.0__tar.gz → 2.8.0.dev631__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_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/.gitignore +4 -1
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/PKG-INFO +5 -4
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/pyproject.toml +3 -2
- robotcode_repl_server-2.8.0.dev631/src/robotcode/repl_server/__version__.py +1 -0
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/src/robotcode/repl_server/cli.py +29 -11
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/src/robotcode/repl_server/interpreter.py +16 -1
- robotcode_repl_server-2.7.0/src/robotcode/repl_server/__version__.py +0 -1
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/README.md +0 -0
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/src/robotcode/repl_server/__init__.py +0 -0
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/src/robotcode/repl_server/hooks.py +0 -0
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/src/robotcode/repl_server/protocol.py +0 -0
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/src/robotcode/repl_server/py.typed +0 -0
- {robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/src/robotcode/repl_server/server.py +0 -0
|
@@ -279,6 +279,9 @@ dist
|
|
|
279
279
|
# vuepress build output
|
|
280
280
|
.vuepress/dist
|
|
281
281
|
|
|
282
|
+
# Astro (documentation site)
|
|
283
|
+
docs/.astro/
|
|
284
|
+
|
|
282
285
|
# Serverless directories
|
|
283
286
|
.serverless/
|
|
284
287
|
|
|
@@ -339,7 +342,7 @@ bundled/libs
|
|
|
339
342
|
# .agents
|
|
340
343
|
.agents/
|
|
341
344
|
skills-lock.json
|
|
342
|
-
|
|
345
|
+
#.claude
|
|
343
346
|
|
|
344
347
|
# sarif files
|
|
345
348
|
/**/*.sarif.json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: robotcode-repl-server
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0-dev.631
|
|
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
|
|
@@ -20,13 +20,14 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
23
24
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
24
25
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
25
26
|
Classifier: Topic :: Utilities
|
|
26
27
|
Classifier: Typing :: Typed
|
|
27
28
|
Requires-Python: >=3.10
|
|
28
|
-
Requires-Dist: robotcode-jsonrpc2==2.
|
|
29
|
-
Requires-Dist: robotcode-runner==2.
|
|
29
|
+
Requires-Dist: robotcode-jsonrpc2==2.8.0-dev.631
|
|
30
|
+
Requires-Dist: robotcode-runner==2.8.0-dev.631
|
|
30
31
|
Description-Content-Type: text/markdown
|
|
31
32
|
|
|
32
33
|
# robotcode-repl-server
|
|
@@ -18,6 +18,7 @@ classifiers = [
|
|
|
18
18
|
"Programming Language :: Python :: 3.12",
|
|
19
19
|
"Programming Language :: Python :: 3.13",
|
|
20
20
|
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Programming Language :: Python :: 3.15",
|
|
21
22
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
22
23
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
23
24
|
"Operating System :: OS Independent",
|
|
@@ -28,8 +29,8 @@ classifiers = [
|
|
|
28
29
|
]
|
|
29
30
|
dynamic = ["version"]
|
|
30
31
|
dependencies = [
|
|
31
|
-
"robotcode-jsonrpc2==2.
|
|
32
|
-
"robotcode-runner==2.
|
|
32
|
+
"robotcode-jsonrpc2==2.8.0-dev.631",
|
|
33
|
+
"robotcode-runner==2.8.0-dev.631"
|
|
33
34
|
]
|
|
34
35
|
|
|
35
36
|
[project.entry-points.robotcode]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.8.0-dev.631"
|
{robotcode_repl_server-2.7.0 → robotcode_repl_server-2.8.0.dev631}/src/robotcode/repl_server/cli.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import threading
|
|
3
3
|
import time
|
|
4
|
+
from concurrent.futures import wait
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import Any, Optional, Sequence, Tuple
|
|
6
7
|
|
|
@@ -81,7 +82,11 @@ def run_jsonrpc_server(
|
|
|
81
82
|
) -> None:
|
|
82
83
|
loop = asyncio.new_event_loop()
|
|
83
84
|
asyncio.set_event_loop(loop)
|
|
84
|
-
|
|
85
|
+
try:
|
|
86
|
+
run_jsonrpc_server_async(mode, port, bind, pipe_name, interpreter)
|
|
87
|
+
finally:
|
|
88
|
+
# closed here, not by the garbage collector at exit, which can fail with a traceback on Python 3.11
|
|
89
|
+
loop.close()
|
|
85
90
|
|
|
86
91
|
|
|
87
92
|
@wrappable
|
|
@@ -156,11 +161,11 @@ def run_jsonrpc_server(
|
|
|
156
161
|
"--source",
|
|
157
162
|
type=click.Path(path_type=Path),
|
|
158
163
|
metavar="FILE",
|
|
159
|
-
help="
|
|
160
|
-
"
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"need to exist.",
|
|
164
|
+
help="Run the session as if its keywords were written in FILE: `${CURDIR}` is the "
|
|
165
|
+
"directory of FILE, `${SUITE SOURCE}` is FILE and, on Robot Framework 7.4 and newer, "
|
|
166
|
+
"relative paths in `Import Resource`, `Import Library`, and `Import Variables` resolve "
|
|
167
|
+
"against that directory. A relative FILE is resolved against the directory the command "
|
|
168
|
+
"is started from. The file itself is never read or written, so the path doesn't need to exist.",
|
|
164
169
|
)
|
|
165
170
|
@click.argument(
|
|
166
171
|
"files",
|
|
@@ -213,12 +218,17 @@ def repl_server(
|
|
|
213
218
|
|
|
214
219
|
interpreter = Interpreter(list(files))
|
|
215
220
|
|
|
216
|
-
|
|
221
|
+
# A dry run starts no server; `run_repl` only prints what it would execute.
|
|
222
|
+
server_task = (
|
|
223
|
+
None
|
|
224
|
+
if app.config.dry
|
|
225
|
+
else run_as_debugpy_hidden_task(run_jsonrpc_server, mode, port, bind, pipe_name, interpreter)
|
|
226
|
+
)
|
|
217
227
|
|
|
218
|
-
server = wait_for_server(server_task)
|
|
228
|
+
server = wait_for_server(server_task) if server_task is not None else None
|
|
219
229
|
|
|
220
230
|
try:
|
|
221
|
-
run_repl(
|
|
231
|
+
result = run_repl(
|
|
222
232
|
interpreter=interpreter,
|
|
223
233
|
app=app,
|
|
224
234
|
variable=variable,
|
|
@@ -233,7 +243,15 @@ def repl_server(
|
|
|
233
243
|
files=files,
|
|
234
244
|
)
|
|
235
245
|
finally:
|
|
246
|
+
# Closing stops the server's stdio reader too. It runs on the server's loop, because
|
|
247
|
+
# called from here it waits until all clients of a TCP server have disconnected (from
|
|
248
|
+
# Python 3.12 on). The wait must not raise: an error of the session, such as an
|
|
249
|
+
# invalid robot.toml, has to reach Click unchanged.
|
|
236
250
|
if server is not None:
|
|
237
|
-
server.loop.
|
|
251
|
+
server.loop.call_soon_threadsafe(server.close)
|
|
252
|
+
|
|
253
|
+
if server_task is not None:
|
|
254
|
+
wait([server_task], timeout=1)
|
|
238
255
|
|
|
239
|
-
|
|
256
|
+
if result.exit_code is not None:
|
|
257
|
+
app.exit(result.exit_code)
|
|
@@ -118,6 +118,8 @@ class Interpreter(BaseInterpreter):
|
|
|
118
118
|
self._interrupted = False
|
|
119
119
|
self._has_shutdown = False
|
|
120
120
|
self._cell_errors: List[str] = []
|
|
121
|
+
# Set while the session waits for a cell: SIGTERM then ends the wait (`_end_waiting`).
|
|
122
|
+
self._waiting = False
|
|
121
123
|
|
|
122
124
|
def shutdown(self) -> None:
|
|
123
125
|
self._code = []
|
|
@@ -270,7 +272,14 @@ class Interpreter(BaseInterpreter):
|
|
|
270
272
|
self._success = True
|
|
271
273
|
|
|
272
274
|
def run_input(self) -> None:
|
|
273
|
-
self.
|
|
275
|
+
self._waiting = True
|
|
276
|
+
try:
|
|
277
|
+
# Checked after marking the wait: a SIGTERM in between can't be missed.
|
|
278
|
+
if self._termination_requested:
|
|
279
|
+
raise EOFError
|
|
280
|
+
self.has_input.wait()
|
|
281
|
+
finally:
|
|
282
|
+
self._waiting = False
|
|
274
283
|
if self._has_shutdown:
|
|
275
284
|
self.executed.set()
|
|
276
285
|
raise EOFError
|
|
@@ -280,3 +289,9 @@ class Interpreter(BaseInterpreter):
|
|
|
280
289
|
finally:
|
|
281
290
|
self.has_input.clear()
|
|
282
291
|
self.executed.set()
|
|
292
|
+
|
|
293
|
+
def _end_waiting(self) -> None:
|
|
294
|
+
# Raised rather than `shutdown()`: setting the event takes a lock that the main
|
|
295
|
+
# thread, interrupted by the signal, may hold.
|
|
296
|
+
if self._waiting:
|
|
297
|
+
raise EOFError
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.7.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|