socx-cli 0.13.7__tar.gz → 0.13.8__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.
- {socx_cli-0.13.7 → socx_cli-0.13.8}/PKG-INFO +1 -1
- {socx_cli-0.13.7 → socx_cli-0.13.8}/pyproject.toml +1 -1
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/config/converters.py +7 -7
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/regression/test.py +29 -7
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/details.py +4 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/dialog.py +6 -8
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/widget.py +18 -7
- {socx_cli-0.13.7 → socx_cli-0.13.8}/.gitignore +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/LICENSE +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/README.md +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/__main__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/cli/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/cli/_cli.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/cli/_jinja.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/cli/callbacks.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/cli/cfg.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/cli/cli.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/cli/params.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/cli/types.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/config/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/config/_config.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/config/_settings.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/config/encoders.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/config/formatters.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/config/serializers.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/config/validators.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/_paths.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/encoder.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/enums.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/funcs.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/metadata.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/paths.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/schema/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/schema/git/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/schema/git/git.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/schema/git/manifest.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/schema/plugin.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/schema/types.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/core/serializer.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/git/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/git/_git.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/git/_manifest.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/git/_ssh.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/io/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/io/console.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/io/decorators.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/io/log.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/mixins/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/mixins/proxy.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/mixins/uid.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/singleton/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/singleton/singleton.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/visitor/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/visitor/protocol.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/patterns/visitor/traversal.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/regression/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/regression/progress.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/regression/regression.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/regression/status.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/regression/validator.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/regression/visitor.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/settings/cli.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/settings/console.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/settings/git.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/settings/logging.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/settings/plugins.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/settings/regression.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/settings/rich_click.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/settings/settings.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/static/sql/socx.sql +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/utils/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx/utils/decorators.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/config/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/config/_config.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/config/edit.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/git/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/git/arguments.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/git/callbacks.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/git/cli.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/git/manifest.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/git/renderables.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/git/summary.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/git/utils.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/plugin/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/plugin/example.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/plugin/schema.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/regression/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/regression/_run.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/regression/callbacks.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/regression/cli.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/regression/run.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/regression/tui.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/version/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_plugins/version/__main__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/__main__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/app.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/bindings/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/bindings/vim/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/bindings/vim/mode.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/bindings/vim/vim.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/containers.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/mixins/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/mixins/composable.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/mixins/configurable.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/preview.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/table.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/regression/tree.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/static/tcss/regression/app.tcss +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.8}/socx_tui/static/tcss/regression/preview.tcss +0 -0
|
@@ -29,7 +29,7 @@ socx = 'socx.__main__:main'
|
|
|
29
29
|
[project]
|
|
30
30
|
name = "socx-cli"
|
|
31
31
|
readme = "README.md"
|
|
32
|
-
version = "0.13.
|
|
32
|
+
version = "0.13.8"
|
|
33
33
|
license = "Apache-2.0"
|
|
34
34
|
authors = [{ name = "Sagi Kimhi", email = "sagi.kim5@gmail.com" }]
|
|
35
35
|
maintainers = [{ name = "Sagi Kimhi", email = "sagi.kim5@gmail.com" }]
|
|
@@ -310,8 +310,8 @@ class SymbolConverter(Converter[str | Lazy, Any]):
|
|
|
310
310
|
|
|
311
311
|
class CommandConverter(
|
|
312
312
|
Converter[
|
|
313
|
-
str | Lazy |
|
|
314
|
-
str | Lazy | click.Command,
|
|
313
|
+
str | Lazy | BaseCommand | click.Command | PluginModel,
|
|
314
|
+
str | Lazy | click.Command | click.Group,
|
|
315
315
|
]
|
|
316
316
|
):
|
|
317
317
|
"""Turn module or script references into Rich Click commands."""
|
|
@@ -351,7 +351,7 @@ class CommandConverter(
|
|
|
351
351
|
@overload
|
|
352
352
|
def __call__(
|
|
353
353
|
self,
|
|
354
|
-
value:
|
|
354
|
+
value: BaseCommand,
|
|
355
355
|
*args: Any,
|
|
356
356
|
**kwargs: Any,
|
|
357
357
|
) -> click.Command: ...
|
|
@@ -374,10 +374,10 @@ class CommandConverter(
|
|
|
374
374
|
@_validate
|
|
375
375
|
def __call__(
|
|
376
376
|
self,
|
|
377
|
-
value: str | Lazy |
|
|
377
|
+
value: str | Lazy | BaseCommand | click.Command | PluginModel,
|
|
378
378
|
*args: Any,
|
|
379
379
|
**kwargs: Any,
|
|
380
|
-
) -> Lazy | click.Command | click.Group:
|
|
380
|
+
) -> str | Lazy | click.Command | click.Group:
|
|
381
381
|
"""Build a Click command from dotted paths or reuse existing ones."""
|
|
382
382
|
if isinstance(value, Lazy):
|
|
383
383
|
if value.casting is self:
|
|
@@ -401,9 +401,9 @@ class CommandConverter(
|
|
|
401
401
|
nonlocal value
|
|
402
402
|
|
|
403
403
|
if TYPE_CHECKING:
|
|
404
|
-
value = cast(str |
|
|
404
|
+
value = cast(str | BaseCommand | PluginModel, value)
|
|
405
405
|
|
|
406
|
-
if isinstance(value,
|
|
406
|
+
if isinstance(value, str | BaseCommand):
|
|
407
407
|
return self._run_shell_script(value, *args)
|
|
408
408
|
|
|
409
409
|
if isinstance(value, PluginModel) and value.is_script():
|
|
@@ -10,6 +10,7 @@ import signal
|
|
|
10
10
|
import asyncio as aio
|
|
11
11
|
import logging
|
|
12
12
|
from textwrap import dedent
|
|
13
|
+
from typing import Any
|
|
13
14
|
from enum import IntEnum, StrEnum, auto
|
|
14
15
|
from pathlib import Path
|
|
15
16
|
from subprocess import CalledProcessError
|
|
@@ -27,7 +28,6 @@ from pydantic import (
|
|
|
27
28
|
computed_field,
|
|
28
29
|
)
|
|
29
30
|
from anyio.abc import Process, TaskStatus
|
|
30
|
-
from anyio.to_thread import run_sync
|
|
31
31
|
|
|
32
32
|
from socx.patterns import Visitor
|
|
33
33
|
from socx.core.schema import Script, DirectoryPath
|
|
@@ -96,6 +96,22 @@ class TestBase(BaseModel):
|
|
|
96
96
|
""",
|
|
97
97
|
)
|
|
98
98
|
|
|
99
|
+
fresh_env: bool = Field(
|
|
100
|
+
default=False,
|
|
101
|
+
description="""
|
|
102
|
+
Whether or not to execute the test in a fresh environment.
|
|
103
|
+
|
|
104
|
+
A fresh environment is an environment with no environment
|
|
105
|
+
variables defined other than those defined in the ``env`` field.
|
|
106
|
+
|
|
107
|
+
A non-fresh environment will contain all environment variables of
|
|
108
|
+
the current process, as well as any variables defined in the
|
|
109
|
+
``env`` field.
|
|
110
|
+
|
|
111
|
+
If left unspecified, defaults to False.
|
|
112
|
+
""",
|
|
113
|
+
)
|
|
114
|
+
|
|
99
115
|
model_config = ConfigDict(
|
|
100
116
|
from_attributes=True,
|
|
101
117
|
arbitrary_types_allowed=True,
|
|
@@ -112,6 +128,12 @@ class TestBase(BaseModel):
|
|
|
112
128
|
_output_dir: Path | None = PrivateAttr(None)
|
|
113
129
|
_termination_requested: bool = PrivateAttr(False)
|
|
114
130
|
|
|
131
|
+
def model_post_init(self, context: Any) -> None:
|
|
132
|
+
if not self.fresh_env:
|
|
133
|
+
env = os.environ.copy()
|
|
134
|
+
env.update(self.env)
|
|
135
|
+
self.env = env
|
|
136
|
+
|
|
115
137
|
@computed_field
|
|
116
138
|
@property
|
|
117
139
|
def status(self) -> TestStatus:
|
|
@@ -301,7 +323,7 @@ class TestBase(BaseModel):
|
|
|
301
323
|
return
|
|
302
324
|
|
|
303
325
|
async with self.mutex:
|
|
304
|
-
|
|
326
|
+
self._do_reset()
|
|
305
327
|
|
|
306
328
|
async def restart(self, auto_start: bool = True) -> None:
|
|
307
329
|
"""Terminate, reset, and execute the test again."""
|
|
@@ -377,7 +399,7 @@ class Test(TestBase):
|
|
|
377
399
|
"""Concrete test model with subprocess execution support."""
|
|
378
400
|
|
|
379
401
|
exec: Script = Field(
|
|
380
|
-
|
|
402
|
+
"",
|
|
381
403
|
validation_alias=AliasChoices("exec", "command", "script"),
|
|
382
404
|
description=(
|
|
383
405
|
"A shell command or a path to an executable file to run on test "
|
|
@@ -480,7 +502,7 @@ class Test(TestBase):
|
|
|
480
502
|
) -> None:
|
|
481
503
|
async with anyio.create_task_group() as tg:
|
|
482
504
|
self._process = await anyio.open_process(
|
|
483
|
-
str(self.exec),
|
|
505
|
+
command=str(self.exec),
|
|
484
506
|
cwd=self.cwd,
|
|
485
507
|
env=self.env,
|
|
486
508
|
stdout=aio.subprocess.PIPE,
|
|
@@ -522,11 +544,11 @@ class Test(TestBase):
|
|
|
522
544
|
elif self._retcode == 0:
|
|
523
545
|
self._status = TestStatus.Finished
|
|
524
546
|
self._result = TestResult.Passed
|
|
525
|
-
elif self._retcode is None
|
|
526
|
-
self._status = TestStatus.
|
|
547
|
+
elif self._retcode is not None and 0 < self._retcode < 0x80:
|
|
548
|
+
self._status = TestStatus.Finished
|
|
527
549
|
self._result = TestResult.Failed
|
|
528
550
|
else:
|
|
529
|
-
self._status = TestStatus.
|
|
551
|
+
self._status = TestStatus.Terminated
|
|
530
552
|
self._result = TestResult.Failed
|
|
531
553
|
|
|
532
554
|
self._process = None
|
|
@@ -98,6 +98,7 @@ class RegressionStaticDetails(Static):
|
|
|
98
98
|
self.format_header(model),
|
|
99
99
|
f"💡 Status: {self.format_status(model.status)}",
|
|
100
100
|
f"🚩 Result: {self.format_result(model.result)}",
|
|
101
|
+
f"🧑💻 Exit Code: {self.format_retcode(model.retcode)}"
|
|
101
102
|
f"⌛ Elapsed Time: {self.format_timedelta(model.elapsed_time)}", # noqa: E501
|
|
102
103
|
f"⌛ Started Time: {self.format_time(model.started_time)}",
|
|
103
104
|
f"⌛ Finished Time: {self.format_time(model.finished_time)}", # noqa: E501
|
|
@@ -126,6 +127,9 @@ class RegressionStaticDetails(Static):
|
|
|
126
127
|
["## 📜 Command/Script", "```bash", script_str, "```"]
|
|
127
128
|
)
|
|
128
129
|
|
|
130
|
+
def format_retcode(self, retcode: int | None) -> str:
|
|
131
|
+
return str(retcode)
|
|
132
|
+
|
|
129
133
|
def format_result(self, result: TestResult | str) -> str:
|
|
130
134
|
if isinstance(result, TestResult):
|
|
131
135
|
return result.value
|
|
@@ -161,24 +161,22 @@ class RestartSelectionDialog(ModalScreen[str | None]):
|
|
|
161
161
|
yield Button(
|
|
162
162
|
"Restart\nAll", id="restart-scope-all", variant="success"
|
|
163
163
|
)
|
|
164
|
-
yield Button(
|
|
165
|
-
"Restart\nFailed or Stopped",
|
|
166
|
-
id="restart-scope-failed-cancelled",
|
|
167
|
-
variant="primary",
|
|
168
|
-
)
|
|
169
|
-
yield Button("Restart\nStopped", id="restart-scope-cancelled")
|
|
170
164
|
yield Button(
|
|
171
165
|
"Restart\nFailed",
|
|
172
166
|
id="restart-scope-failed",
|
|
173
167
|
variant="error",
|
|
174
168
|
)
|
|
169
|
+
yield Button(
|
|
170
|
+
"Restart\nStopped",
|
|
171
|
+
id="restart-scope-cancelled",
|
|
172
|
+
variant="primary",
|
|
173
|
+
)
|
|
175
174
|
|
|
176
175
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
177
176
|
button_id = event.button.id
|
|
178
177
|
mapping = {
|
|
179
178
|
"restart-scope-all": "all",
|
|
180
|
-
"restart-scope-failed-cancelled": "failed_or_cancelled",
|
|
181
|
-
"restart-scope-cancelled": "cancelled",
|
|
182
179
|
"restart-scope-failed": "failed",
|
|
180
|
+
"restart-scope-cancelled": "cancelled",
|
|
183
181
|
}
|
|
184
182
|
self.dismiss(mapping.get(button_id))
|
|
@@ -9,7 +9,15 @@ from typing import Any, ClassVar
|
|
|
9
9
|
|
|
10
10
|
import rich.repr
|
|
11
11
|
from rich.text import Text
|
|
12
|
-
from socx import
|
|
12
|
+
from socx import (
|
|
13
|
+
Regression,
|
|
14
|
+
Test,
|
|
15
|
+
TestBase,
|
|
16
|
+
TestResult,
|
|
17
|
+
settings,
|
|
18
|
+
enums,
|
|
19
|
+
TestStatus,
|
|
20
|
+
)
|
|
13
21
|
from textual import on, work
|
|
14
22
|
from textual.app import ComposeResult
|
|
15
23
|
from textual.binding import Binding, BindingType
|
|
@@ -237,12 +245,10 @@ class RegressionWidget(Widget, can_focus=False, inherit_bindings=True):
|
|
|
237
245
|
match scope:
|
|
238
246
|
case "all":
|
|
239
247
|
return True
|
|
240
|
-
case "cancelled":
|
|
241
|
-
return t.terminated
|
|
242
248
|
case "failed":
|
|
243
|
-
return t.
|
|
244
|
-
case "
|
|
245
|
-
return t.
|
|
249
|
+
return t.result is TestResult.Failed
|
|
250
|
+
case "cancelled":
|
|
251
|
+
return t.status is TestStatus.Terminated
|
|
246
252
|
case _:
|
|
247
253
|
return False
|
|
248
254
|
|
|
@@ -480,7 +486,12 @@ class RegressionWidget(Widget, can_focus=False, inherit_bindings=True):
|
|
|
480
486
|
def _format_test_status_label(self, test: TestBase) -> Text:
|
|
481
487
|
status = f"💡 {self.details_view.details.format_status(test.status)}"
|
|
482
488
|
result = f"🚩 {self.details_view.details.format_result(test.result)}"
|
|
483
|
-
|
|
489
|
+
|
|
490
|
+
if isinstance(test, Test):
|
|
491
|
+
retcode = f"🧑💻 {self.details_view.details.format_retcode(test.retcode)}" # noqa: E501
|
|
492
|
+
return Text.assemble("[", "|".join([status, result, retcode]), "]")
|
|
493
|
+
else:
|
|
494
|
+
return Text.assemble("[", "|".join([status, result]), "]")
|
|
484
495
|
|
|
485
496
|
def _no_model_selected_notification(self) -> None:
|
|
486
497
|
msg = "Select a regression or test first."
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|