robotcode 2.6.2__py3-none-any.whl → 2.7.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/cli/__init__.py +117 -0
- robotcode/cli/__version__.py +1 -1
- {robotcode-2.6.2.dist-info → robotcode-2.7.0.dist-info}/METADATA +16 -16
- robotcode-2.7.0.dist-info/RECORD +12 -0
- {robotcode-2.6.2.dist-info → robotcode-2.7.0.dist-info}/WHEEL +1 -1
- robotcode-2.6.2.dist-info/RECORD +0 -12
- {robotcode-2.6.2.dist-info → robotcode-2.7.0.dist-info}/entry_points.txt +0 -0
- {robotcode-2.6.2.dist-info → robotcode-2.7.0.dist-info}/licenses/LICENSE.txt +0 -0
robotcode/cli/__init__.py
CHANGED
|
@@ -2,6 +2,9 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
import logging.config
|
|
4
4
|
import os
|
|
5
|
+
import shlex
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
5
8
|
from pathlib import Path
|
|
6
9
|
from typing import Any, List, Literal, Optional
|
|
7
10
|
|
|
@@ -18,6 +21,7 @@ from robotcode.plugin import (
|
|
|
18
21
|
from robotcode.plugin._agent_detection import is_running_in_ai_agent
|
|
19
22
|
from robotcode.plugin.click_helper.aliases import AliasedGroup
|
|
20
23
|
from robotcode.plugin.click_helper.types import EnumChoice
|
|
24
|
+
from robotcode.plugin.click_helper.wrappable import WRAPPER_APPLIED_ENV, is_wrappable
|
|
21
25
|
from robotcode.plugin.manager import PluginManager
|
|
22
26
|
|
|
23
27
|
from .__version__ import __version__
|
|
@@ -46,6 +50,99 @@ class RobotCodeFormatter(logging.Formatter):
|
|
|
46
50
|
super().__init__(*args, defaults=defaults, **kwargs)
|
|
47
51
|
|
|
48
52
|
|
|
53
|
+
def _maybe_reexec_under_wrapper(
|
|
54
|
+
ctx: click.Context, app: Application, cli_wrapper: Optional[str] = None, no_wrapper: bool = False
|
|
55
|
+
) -> None:
|
|
56
|
+
"""Re-execute this process through a configured ``wrapper`` command.
|
|
57
|
+
|
|
58
|
+
When a ``wrapper`` is configured - either via ``--wrapper`` on the command
|
|
59
|
+
line (``cli_wrapper``) or the selected profile's ``wrapper`` (e.g. to run
|
|
60
|
+
the tests inside a specific X11/Wayland session) - and the invoked command
|
|
61
|
+
is ``@wrappable`` (i.e. it executes Robot Framework), the process
|
|
62
|
+
re-executes itself **once** through that command before Robot Framework
|
|
63
|
+
starts. ``--wrapper`` overrides the profile; ``--no-wrapper`` disables
|
|
64
|
+
wrapping for this run. The guard env var prevents infinite recursion and
|
|
65
|
+
lets an outer layer suppress the re-exec by setting it itself.
|
|
66
|
+
"""
|
|
67
|
+
if no_wrapper:
|
|
68
|
+
if cli_wrapper:
|
|
69
|
+
app.warning("Ignoring --wrapper because --no-wrapper was given.")
|
|
70
|
+
return
|
|
71
|
+
if os.environ.get(WRAPPER_APPLIED_ENV):
|
|
72
|
+
return
|
|
73
|
+
|
|
74
|
+
sub_name = ctx.invoked_subcommand
|
|
75
|
+
if not sub_name:
|
|
76
|
+
return
|
|
77
|
+
# The command itself opts in via @wrappable; aliases resolve to the same
|
|
78
|
+
# command object, so this is alias-safe and needs no central name list.
|
|
79
|
+
sub_cmd = ctx.command.get_command(ctx, sub_name) if isinstance(ctx.command, click.Group) else None
|
|
80
|
+
if sub_cmd is None or not is_wrappable(sub_cmd):
|
|
81
|
+
if cli_wrapper:
|
|
82
|
+
app.warning(f"Ignoring --wrapper: '{sub_name}' does not execute Robot Framework.")
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
from robotcode.robot.config.loader import load_robot_config_from_path
|
|
86
|
+
from robotcode.robot.config.utils import get_config_files
|
|
87
|
+
|
|
88
|
+
profile_wrapper = None
|
|
89
|
+
try:
|
|
90
|
+
config_files, _, _ = get_config_files(
|
|
91
|
+
config_files=app.config.config_files,
|
|
92
|
+
root_folder=app.config.root,
|
|
93
|
+
no_vcs=app.config.no_vcs,
|
|
94
|
+
verbose_callback=app.verbose,
|
|
95
|
+
)
|
|
96
|
+
# `evaluated_with_env` also applies the profile's `env` to `os.environ`,
|
|
97
|
+
# so the wrapper command can rely on it.
|
|
98
|
+
profile = (
|
|
99
|
+
load_robot_config_from_path(*config_files, verbose_callback=app.verbose)
|
|
100
|
+
.combine_profiles(*(app.config.profiles or []), verbose_callback=app.verbose, error_callback=app.error)
|
|
101
|
+
.evaluated_with_env(verbose_callback=app.verbose, error_callback=app.error)
|
|
102
|
+
)
|
|
103
|
+
profile_wrapper = profile.wrapper
|
|
104
|
+
except Exception as e:
|
|
105
|
+
# Don't fail early on config problems here; the actual command loads the
|
|
106
|
+
# config again and reports errors properly. An explicit --wrapper is
|
|
107
|
+
# still honored below.
|
|
108
|
+
message = str(e)
|
|
109
|
+
app.verbose(lambda: f"Skipping profile wrapper detection: {message}")
|
|
110
|
+
|
|
111
|
+
# `--wrapper` overrides the profile's `wrapper`. The evaluated profile turns
|
|
112
|
+
# StringExpression entries into plain strings.
|
|
113
|
+
if cli_wrapper:
|
|
114
|
+
wrapper = shlex.split(cli_wrapper)
|
|
115
|
+
elif profile_wrapper:
|
|
116
|
+
wrapper = [str(w) for w in profile_wrapper]
|
|
117
|
+
else:
|
|
118
|
+
return
|
|
119
|
+
|
|
120
|
+
# Rebuild the invocation the way this process was actually started, so the
|
|
121
|
+
# re-exec finds robotcode even when it runs from a bundled path (VS Code) and
|
|
122
|
+
# is not installed in the interpreter. `launcher_script` is set only when we
|
|
123
|
+
# were started through a bundled entry (its `__main__` sets it) or an explicit
|
|
124
|
+
# `--launcher-script`; otherwise robotcode is importable directly and
|
|
125
|
+
# `-m robotcode.cli` is correct. We deliberately do NOT consult the
|
|
126
|
+
# ROBOTCODE_BUNDLED_ROBOTCODE_MAIN env var: VS Code sets it in every terminal,
|
|
127
|
+
# so a directly started robotcode would be diverted to the bundled copy.
|
|
128
|
+
# Mirrors the debug launcher's `debugger_script` handling.
|
|
129
|
+
entry = [str(app.config.launcher_script)] if app.config.launcher_script else ["-m", "robotcode.cli"]
|
|
130
|
+
command = [*wrapper, sys.executable, *entry, *sys.argv[1:]]
|
|
131
|
+
app.verbose(lambda: "Running under wrapper: " + " ".join(command))
|
|
132
|
+
|
|
133
|
+
# Run robotcode again under the wrapper; the guard env stops the spawned
|
|
134
|
+
# robotcode from wrapping a second time. On POSIX we replace this process with
|
|
135
|
+
# execvp (no extra process); Windows has no such exec, so there we spawn the
|
|
136
|
+
# command, wait, and forward its exit code.
|
|
137
|
+
os.environ[WRAPPER_APPLIED_ENV] = "1"
|
|
138
|
+
try:
|
|
139
|
+
if sys.platform == "win32":
|
|
140
|
+
sys.exit(subprocess.run(command).returncode)
|
|
141
|
+
os.execvp(command[0], command)
|
|
142
|
+
except OSError as e:
|
|
143
|
+
raise click.ClickException(f"Failed to execute wrapper command {wrapper!r}: {e}") from e
|
|
144
|
+
|
|
145
|
+
|
|
49
146
|
@click.group(
|
|
50
147
|
cls=AliasedGroup,
|
|
51
148
|
context_settings={"auto_envvar_prefix": "ROBOTCODE"},
|
|
@@ -129,6 +226,20 @@ class RobotCodeFormatter(logging.Formatter):
|
|
|
129
226
|
help="Enables verbose mode.",
|
|
130
227
|
show_envvar=True,
|
|
131
228
|
)
|
|
229
|
+
@click.option(
|
|
230
|
+
"--wrapper",
|
|
231
|
+
type=str,
|
|
232
|
+
default=None,
|
|
233
|
+
show_envvar=True,
|
|
234
|
+
help='Command prefix to run the test execution through, e.g. `--wrapper "xvfb-run -a"`. '
|
|
235
|
+
"Split like a shell command. Applies only to commands that execute Robot Framework "
|
|
236
|
+
"(run/debug/repl). Overrides the profile's `wrapper`.",
|
|
237
|
+
)
|
|
238
|
+
@click.option(
|
|
239
|
+
"--no-wrapper",
|
|
240
|
+
is_flag=True,
|
|
241
|
+
help="Disable any configured `wrapper` (profile or --wrapper) for this run.",
|
|
242
|
+
)
|
|
132
243
|
@click.option("--log", is_flag=True, help="Enables logging.", show_envvar=True)
|
|
133
244
|
@click.option(
|
|
134
245
|
"--log-level",
|
|
@@ -230,7 +341,9 @@ class RobotCodeFormatter(logging.Formatter):
|
|
|
230
341
|
)
|
|
231
342
|
@click.version_option(version=__version__, prog_name="robotcode")
|
|
232
343
|
@pass_application
|
|
344
|
+
@click.pass_context
|
|
233
345
|
def robotcode(
|
|
346
|
+
ctx: click.Context,
|
|
234
347
|
app: Application,
|
|
235
348
|
config_files: Optional[List[Path]],
|
|
236
349
|
profiles: Optional[List[str]],
|
|
@@ -249,6 +362,8 @@ def robotcode(
|
|
|
249
362
|
log_calls: bool,
|
|
250
363
|
log_config: Optional[Path],
|
|
251
364
|
default_path: Optional[List[str]],
|
|
365
|
+
wrapper: Optional[str] = None,
|
|
366
|
+
no_wrapper: bool = False,
|
|
252
367
|
launcher_script: Optional[str] = None,
|
|
253
368
|
debugpy: bool = False,
|
|
254
369
|
debugpy_port: int = 5678,
|
|
@@ -295,6 +410,8 @@ def robotcode(
|
|
|
295
410
|
app.config.log_level = log_level
|
|
296
411
|
app.config.log_calls = log_calls
|
|
297
412
|
|
|
413
|
+
_maybe_reexec_under_wrapper(ctx, app, wrapper, no_wrapper)
|
|
414
|
+
|
|
298
415
|
if log_config:
|
|
299
416
|
if log_calls:
|
|
300
417
|
LoggingDescriptor.set_call_tracing(True)
|
robotcode/cli/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.
|
|
1
|
+
__version__ = "2.7.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: robotcode
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: Command line interface for RobotCode
|
|
5
5
|
Project-URL: Homepage, https://robotcode.io
|
|
6
6
|
Project-URL: Donate, https://opencollective.com/robotcode
|
|
@@ -33,35 +33,35 @@ Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE)
|
|
|
33
33
|
Classifier: Topic :: Utilities
|
|
34
34
|
Classifier: Typing :: Typed
|
|
35
35
|
Requires-Python: >=3.10
|
|
36
|
-
Requires-Dist: robotcode-core==2.
|
|
37
|
-
Requires-Dist: robotcode-plugin==2.
|
|
38
|
-
Requires-Dist: robotcode-robot==2.
|
|
36
|
+
Requires-Dist: robotcode-core==2.7.0
|
|
37
|
+
Requires-Dist: robotcode-plugin==2.7.0
|
|
38
|
+
Requires-Dist: robotcode-robot==2.7.0
|
|
39
39
|
Provides-Extra: all
|
|
40
40
|
Requires-Dist: docutils; extra == 'all'
|
|
41
41
|
Requires-Dist: pyyaml>=5.4; extra == 'all'
|
|
42
|
-
Requires-Dist: robotcode-analyze==2.
|
|
43
|
-
Requires-Dist: robotcode-debugger==2.
|
|
44
|
-
Requires-Dist: robotcode-language-server==2.
|
|
45
|
-
Requires-Dist: robotcode-repl-server==2.
|
|
46
|
-
Requires-Dist: robotcode-repl==2.
|
|
47
|
-
Requires-Dist: robotcode-runner==2.
|
|
42
|
+
Requires-Dist: robotcode-analyze==2.7.0; extra == 'all'
|
|
43
|
+
Requires-Dist: robotcode-debugger==2.7.0; extra == 'all'
|
|
44
|
+
Requires-Dist: robotcode-language-server==2.7.0; extra == 'all'
|
|
45
|
+
Requires-Dist: robotcode-repl-server==2.7.0; extra == 'all'
|
|
46
|
+
Requires-Dist: robotcode-repl==2.7.0; extra == 'all'
|
|
47
|
+
Requires-Dist: robotcode-runner==2.7.0; extra == 'all'
|
|
48
48
|
Requires-Dist: robotframework-robocop>=6.0.0; extra == 'all'
|
|
49
49
|
Provides-Extra: analyze
|
|
50
|
-
Requires-Dist: robotcode-analyze==2.
|
|
50
|
+
Requires-Dist: robotcode-analyze==2.7.0; extra == 'analyze'
|
|
51
51
|
Provides-Extra: debugger
|
|
52
|
-
Requires-Dist: robotcode-debugger==2.
|
|
52
|
+
Requires-Dist: robotcode-debugger==2.7.0; extra == 'debugger'
|
|
53
53
|
Provides-Extra: languageserver
|
|
54
|
-
Requires-Dist: robotcode-language-server==2.
|
|
54
|
+
Requires-Dist: robotcode-language-server==2.7.0; extra == 'languageserver'
|
|
55
55
|
Provides-Extra: lint
|
|
56
56
|
Requires-Dist: robotframework-robocop>=2.0.0; extra == 'lint'
|
|
57
57
|
Provides-Extra: repl
|
|
58
|
-
Requires-Dist: robotcode-repl==2.
|
|
58
|
+
Requires-Dist: robotcode-repl==2.7.0; extra == 'repl'
|
|
59
59
|
Provides-Extra: replserver
|
|
60
|
-
Requires-Dist: robotcode-repl-server==2.
|
|
60
|
+
Requires-Dist: robotcode-repl-server==2.7.0; extra == 'replserver'
|
|
61
61
|
Provides-Extra: rest
|
|
62
62
|
Requires-Dist: docutils; extra == 'rest'
|
|
63
63
|
Provides-Extra: runner
|
|
64
|
-
Requires-Dist: robotcode-runner==2.
|
|
64
|
+
Requires-Dist: robotcode-runner==2.7.0; extra == 'runner'
|
|
65
65
|
Provides-Extra: yaml
|
|
66
66
|
Requires-Dist: pyyaml>=5.4; extra == 'yaml'
|
|
67
67
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
robotcode/cli/__init__.py,sha256=qvIUqcHP8K1FNyu3whFDe6M_Wyeo_SKCqwBxtPeQfy0,15608
|
|
2
|
+
robotcode/cli/__main__.py,sha256=hX3nwROMTnsYGT1KS0rXUYrslu9sFzctYdAh66Rcckw,153
|
|
3
|
+
robotcode/cli/__version__.py,sha256=EtKWW0Hnl5oWglRNH0HZigvcDT2FEs58ek8buJdwW1E,22
|
|
4
|
+
robotcode/cli/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
|
|
5
|
+
robotcode/cli/commands/__init__.py,sha256=XJHRt_YwMO2Ni2EfL2aj4jkJXMVG6NGFTpzvSVgIRnQ,92
|
|
6
|
+
robotcode/cli/commands/config.py,sha256=0Jmf7HDIo7IIaOMU9M_bYi7PdHAfcae6x3SW93NA3EA,10481
|
|
7
|
+
robotcode/cli/commands/profiles.py,sha256=5H9lvSVCMggWXf0IH54QtgDgqupEEvpcUrEsTZvZsNM,6127
|
|
8
|
+
robotcode-2.7.0.dist-info/METADATA,sha256=nJWf0wXHOE5LlTfA-cTYK3NsBzv6tGYnOfKj8XZSt9M,14582
|
|
9
|
+
robotcode-2.7.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
10
|
+
robotcode-2.7.0.dist-info/entry_points.txt,sha256=Pb4DKVVdJb5PboVl48njwk3DkKQHBJOL1A8KkpemqA8,58
|
|
11
|
+
robotcode-2.7.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
|
12
|
+
robotcode-2.7.0.dist-info/RECORD,,
|
robotcode-2.6.2.dist-info/RECORD
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
robotcode/cli/__init__.py,sha256=-zPNouLiGkJg8KKz6gVzyVm47dXHqM-zv2gJV3r-n7Y,10254
|
|
2
|
-
robotcode/cli/__main__.py,sha256=hX3nwROMTnsYGT1KS0rXUYrslu9sFzctYdAh66Rcckw,153
|
|
3
|
-
robotcode/cli/__version__.py,sha256=53Sii4w6BIWn-1RhaTyqUO46gDe4nDCRQDAcpsWFH24,22
|
|
4
|
-
robotcode/cli/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
|
|
5
|
-
robotcode/cli/commands/__init__.py,sha256=XJHRt_YwMO2Ni2EfL2aj4jkJXMVG6NGFTpzvSVgIRnQ,92
|
|
6
|
-
robotcode/cli/commands/config.py,sha256=0Jmf7HDIo7IIaOMU9M_bYi7PdHAfcae6x3SW93NA3EA,10481
|
|
7
|
-
robotcode/cli/commands/profiles.py,sha256=5H9lvSVCMggWXf0IH54QtgDgqupEEvpcUrEsTZvZsNM,6127
|
|
8
|
-
robotcode-2.6.2.dist-info/METADATA,sha256=OV5izStIuVLT677FLY1vM3MUTPLaRqb7ESS-cm3LkXU,14582
|
|
9
|
-
robotcode-2.6.2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
10
|
-
robotcode-2.6.2.dist-info/entry_points.txt,sha256=Pb4DKVVdJb5PboVl48njwk3DkKQHBJOL1A8KkpemqA8,58
|
|
11
|
-
robotcode-2.6.2.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
|
12
|
-
robotcode-2.6.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|