Skip to content

Commit 2232a1a

Browse files
Introduce DAN Runner (#129)
DAN (Do Anything Now), inspired from the chatGPT jailbreakers, is a runner that simply does what the user instructs. We are adding this because we anticipate having hundreds of different scenarios to deal with, and many different commands. You can think of this as having a custom runner without having to create one. It is a very power "override all commands" options, with no safety checks. We will depend heavily on documentation and user-instructing for using this. The idea is to give the user the power of what will be run when collecting tests and doing something with them.
1 parent 8c5b289 commit 2232a1a

4 files changed

Lines changed: 131 additions & 0 deletions

File tree

codecov_cli/runners/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22

3+
from codecov_cli.runners.dan_runner import DoAnythingNowRunner
34
from codecov_cli.runners.python_standard_runner import PythonStandardRunner
45
from codecov_cli.runners.types import LabelAnalysisRunnerInterface
56

@@ -18,6 +19,9 @@ def get_runner(cli_config, runner_name) -> LabelAnalysisRunnerInterface:
1819
if runner_name == "python":
1920
config_params = cli_config.get("runners", {}).get("python", {})
2021
return PythonStandardRunner(config_params)
22+
elif runner_name == "dan":
23+
config_params = cli_config.get("runners", {}).get("dan", {})
24+
return DoAnythingNowRunner(config_params)
2125
logger.debug(
2226
f"Trying to load runner {runner_name}",
2327
extra=dict(

codecov_cli/runners/dan_runner.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import subprocess
2+
from typing import List, TypedDict, Union
3+
4+
from codecov_cli.runners.types import (
5+
LabelAnalysisRequestResult,
6+
LabelAnalysisRunnerInterface,
7+
)
8+
9+
10+
class DoAnythingNowConfigParams(TypedDict):
11+
collect_tests_command: Union[List[str], str]
12+
process_labelanalysis_result_command: Union[List[str], str]
13+
14+
15+
class DoAnythingNowRunner(LabelAnalysisRunnerInterface):
16+
def __init__(self, config_params: DoAnythingNowConfigParams = None) -> None:
17+
super().__init__()
18+
if config_params is None:
19+
config_params = DoAnythingNowConfigParams()
20+
self.params = config_params
21+
22+
def collect_tests(self) -> List[str]:
23+
command = self.params.get("collect_tests_command", None)
24+
if command is None:
25+
raise Exception(
26+
"DAN runner missing 'collect_tests_command' configuration value"
27+
)
28+
return subprocess.run(command, check=True, capture_output=True).stdout.decode()
29+
30+
def process_labelanalysis_result(self, result: LabelAnalysisRequestResult):
31+
command = self.params.get("process_labelanalysis_result_command", None)
32+
if command is None:
33+
raise Exception(
34+
"DAN runner missing 'process_labelanalysis_result_command' configuration value"
35+
)
36+
return subprocess.run(command, check=True, capture_output=True).stdout.decode()

tests/runners/test_dan_runner.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from unittest.mock import MagicMock, patch
2+
3+
import pytest
4+
5+
from codecov_cli.runners.dan_runner import DoAnythingNowRunner
6+
from codecov_cli.runners.python_standard_runner import PythonStandardRunner
7+
8+
9+
class TestPythonStandardRunner(object):
10+
@patch("codecov_cli.runners.dan_runner.subprocess.run")
11+
def test_collect_tests(self, mock_run):
12+
test_list = ["test_1", "test_2", "test_3"]
13+
mock_stdout = MagicMock()
14+
mock_stdout.configure_mock(
15+
**{"stdout.decode.return_value": "\n".join(test_list)}
16+
)
17+
mock_run.return_value = mock_stdout
18+
19+
config_options = {"collect_tests_command": ["mycommand", "--option"]}
20+
runner = DoAnythingNowRunner(config_options)
21+
assert runner.params == config_options
22+
resp = runner.collect_tests()
23+
assert resp.split() == test_list
24+
mock_run.assert_called_with(
25+
["mycommand", "--option"],
26+
capture_output=True,
27+
check=True,
28+
)
29+
30+
def test_collect_test_no_config(self):
31+
runner = DoAnythingNowRunner()
32+
with pytest.raises(Exception) as exp:
33+
runner.collect_tests()
34+
assert (
35+
str(exp.value)
36+
== "DAN runner missing 'collect_tests_command' configuration value"
37+
)
38+
39+
@patch("codecov_cli.runners.dan_runner.subprocess.run")
40+
def test_process_labelanalysis_result(self, mock_run):
41+
label_analysis_result = {
42+
"present_report_labels": ["test_present"],
43+
"absent_labels": ["test_absent"],
44+
"present_diff_labels": ["test_in_diff"],
45+
"global_level_labels": ["test_global"],
46+
}
47+
cmd_output = "My command output"
48+
mock_stdout = MagicMock()
49+
mock_stdout.configure_mock(**{"stdout.decode.return_value": cmd_output})
50+
mock_run.return_value = mock_stdout
51+
config_options = {
52+
"process_labelanalysis_result_command": ["mycommand", "--option"]
53+
}
54+
runner = DoAnythingNowRunner(config_options)
55+
runner.process_labelanalysis_result(label_analysis_result)
56+
assert runner.params == config_options
57+
mock_run.assert_called_with(
58+
["mycommand", "--option"],
59+
capture_output=True,
60+
check=True,
61+
)
62+
63+
def test_process_labelanalysis_result_no_config(self):
64+
label_analysis_result = {
65+
"present_report_labels": ["test_present"],
66+
"absent_labels": ["test_absent"],
67+
"present_diff_labels": ["test_in_diff"],
68+
"global_level_labels": ["test_global"],
69+
}
70+
runner = DoAnythingNowRunner()
71+
with pytest.raises(Exception) as exp:
72+
runner.process_labelanalysis_result(label_analysis_result)
73+
assert (
74+
str(exp.value)
75+
== "DAN runner missing 'process_labelanalysis_result_command' configuration value"
76+
)

tests/runners/test_runners.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
from unittest.mock import patch
22

33
from codecov_cli.runners import get_runner
4+
from codecov_cli.runners.dan_runner import DoAnythingNowRunner
45
from codecov_cli.runners.python_standard_runner import PythonStandardRunner
56

67

78
class TestRunners(object):
89
def test_get_standard_runners(self):
910
assert isinstance(get_runner({}, "python"), PythonStandardRunner)
11+
assert isinstance(get_runner({}, "dan"), DoAnythingNowRunner)
1012
# TODO: Extend with other standard runners once we create them (e.g. JS)
1113

1214
def test_python_standard_runner_with_options(self):
@@ -17,6 +19,19 @@ def test_python_standard_runner_with_options(self):
1719
assert isinstance(runner_instance, PythonStandardRunner)
1820
assert runner_instance.params == {**config_params, "include_curr_dir": False}
1921

22+
def test_get_dan_runner_with_params(self):
23+
config = {
24+
"runners": {
25+
"dan": {
26+
"collect_tests_command": ["mycommand", "--collect"],
27+
"process_labelanalysis_result_command": ["mycommand", "--process"],
28+
}
29+
}
30+
}
31+
runner = get_runner(config, "dan")
32+
assert isinstance(runner, DoAnythingNowRunner)
33+
assert runner.params == config["runners"]["dan"]
34+
2035
@patch("codecov_cli.runners._load_runner_from_yaml")
2136
def test_get_runner_from_yaml(self, mock_load_runner):
2237
config = {"runners": {"my_runner": {"path": "path_to_my_runner"}}}

0 commit comments

Comments
 (0)