Skip to content

Commit

Permalink
Add unit tests for commands getting extra docker configs
Browse files Browse the repository at this point in the history
  • Loading branch information
jhonabreul committed Sep 19, 2023
1 parent c3b155b commit 13d2471
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 39 deletions.
2 changes: 1 addition & 1 deletion lean/commands/optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ def optimize(project: Path,
)
container.update_manager.pull_docker_image_if_necessary(engine_image, update, no_update)

# Add know additional run options from the extra docker config
# Add known additional run options from the extra docker config
LeanRunner.parse_extra_docker_config(run_options, json.loads(extra_docker_config))

project_manager.copy_code(algorithm_file.parent, output / "code")
Expand Down
2 changes: 1 addition & 1 deletion lean/commands/research.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def research(project: Path,
# Run the script that starts Jupyter Lab when all set up has been done
run_options["commands"].append("./start.sh")

# Add know additional run options from the extra docker config
# Add known additional run options from the extra docker config
LeanRunner.parse_extra_docker_config(run_options, json.loads(extra_docker_config))

project_config_manager = container.project_config_manager
Expand Down
4 changes: 2 additions & 2 deletions lean/components/docker/lean_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def run_lean(self,
release,
detach)

# Add know additional run options from the extra docker config
# Add known additional run options from the extra docker config
self.parse_extra_docker_config(run_options, extra_docker_config)

# Set up PTVSD debugging
Expand Down Expand Up @@ -772,7 +772,7 @@ def mount_project_and_library_directories(self, project_dir: Path, run_options:

@staticmethod
def parse_extra_docker_config(run_options: Dict[str, Any], extra_docker_config: Optional[Dict[str, Any]]) -> None:
# Add know additional run options from the extra docker config.
# Add known additional run options from the extra docker config.
# For now, only device_requests is supported
if extra_docker_config is not None and "device_requests" in extra_docker_config:
run_options["device_requests"] = [docker.types.DeviceRequest(**device_request)
Expand Down
44 changes: 36 additions & 8 deletions tests/commands/test_backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ def test_backtest_calls_lean_runner_with_correct_algorithm_file() -> None:
ENGINE_IMAGE,
None,
False,
False)
False,
{})


def test_backtest_calls_lean_runner_with_default_output_directory() -> None:
Expand Down Expand Up @@ -88,7 +89,8 @@ def test_backtest_calls_lean_runner_with_custom_output_directory() -> None:
ENGINE_IMAGE,
None,
False,
False)
False,
{})


def test_backtest_calls_lean_runner_with_release_mode() -> None:
Expand All @@ -105,7 +107,8 @@ def test_backtest_calls_lean_runner_with_release_mode() -> None:
ENGINE_IMAGE,
None,
True,
False)
False,
{})


def test_backtest_calls_lean_runner_with_detach() -> None:
Expand All @@ -122,7 +125,8 @@ def test_backtest_calls_lean_runner_with_detach() -> None:
ENGINE_IMAGE,
None,
False,
True)
True,
{})


def test_backtest_aborts_when_project_does_not_exist() -> None:
Expand Down Expand Up @@ -163,7 +167,8 @@ def test_backtest_forces_update_when_update_option_given() -> None:
ENGINE_IMAGE,
None,
False,
False)
False,
{})


def test_backtest_passes_custom_image_to_lean_runner_when_set_in_config() -> None:
Expand All @@ -182,7 +187,8 @@ def test_backtest_passes_custom_image_to_lean_runner_when_set_in_config() -> Non
DockerImage(name="custom/lean", tag="123"),
None,
False,
False)
False,
{})


def test_backtest_passes_custom_image_to_lean_runner_when_given_as_option() -> None:
Expand All @@ -201,7 +207,8 @@ def test_backtest_passes_custom_image_to_lean_runner_when_given_as_option() -> N
DockerImage(name="custom/lean", tag="456"),
None,
False,
False)
False,
{})


@pytest.mark.parametrize("python_venv", ["Custom-venv",
Expand Down Expand Up @@ -289,7 +296,8 @@ def test_backtest_passes_correct_debugging_method_to_lean_runner(value: str, deb
ENGINE_IMAGE,
debugging_method,
False,
False)
False,
{})


def test_backtest_auto_updates_outdated_python_pycharm_debug_config() -> None:
Expand Down Expand Up @@ -649,3 +657,23 @@ def test_backtest_adds_python_libraries_path_to_lean_config() -> None:
expected_library_path = (Path("/") / library_path.relative_to(lean_cli_root_dir)).as_posix()

assert expected_library_path in lean_config.get('python-additional-paths')


def test_backtest_calls_lean_runner_with_extra_docker_config() -> None:
create_fake_lean_cli_directory()

result = CliRunner().invoke(lean, ["backtest", "Python Project",
"--extra-docker-config",
'{"device_requests": [{"count": -1, "capabilities": [[""]]}]}'])

assert result.exit_code == 0

container.lean_runner.run_lean.assert_called_once_with(mock.ANY,
"backtesting",
Path("Python Project/main.py").resolve(),
mock.ANY,
ENGINE_IMAGE,
None,
False,
False,
{"device_requests": [{"count": -1, "capabilities": [[""]]}]})
65 changes: 52 additions & 13 deletions tests/commands/test_live.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,34 @@ def test_live_calls_lean_runner_with_correct_algorithm_file() -> None:
ENGINE_IMAGE,
None,
False,
False)
False,
{})


def test_live_calls_lean_runner_with_extra_docker_config() -> None:
# TODO: currently it is not using the live-paper environment
create_fake_lean_cli_directory()
create_fake_environment("live-paper", True)

result = CliRunner().invoke(lean, ["live", "Python Project",
"--environment",
"live-paper",
"--extra-docker-config",
'{"device_requests": [{"count": -1, "capabilities": [[""]]}]}'])

traceback.print_exception(*result.exc_info)

assert result.exit_code == 0

container.lean_runner.run_lean.assert_called_once_with(mock.ANY,
"live-paper",
Path("Python Project/main.py").resolve(),
mock.ANY,
ENGINE_IMAGE,
None,
False,
False,
{"device_requests": [{"count": -1, "capabilities": [[""]]}]})


def test_live_aborts_when_environment_does_not_exist() -> None:
Expand Down Expand Up @@ -159,7 +186,8 @@ def test_live_calls_lean_runner_with_release_mode() -> None:
ENGINE_IMAGE,
None,
True,
False)
False,
{})


def test_live_calls_lean_runner_with_detach() -> None:
Expand All @@ -178,7 +206,8 @@ def test_live_calls_lean_runner_with_detach() -> None:
ENGINE_IMAGE,
None,
False,
True)
True,
{})


def test_live_aborts_when_project_does_not_exist() -> None:
Expand Down Expand Up @@ -366,7 +395,8 @@ def test_live_calls_lean_runner_with_data_provider(data_provider: str) -> None:
ENGINE_IMAGE,
None,
False,
False)
False,
{})


@pytest.mark.parametrize("brokerage", brokerage_required_options.keys() - ["Paper Trading"])
Expand Down Expand Up @@ -468,7 +498,8 @@ def test_live_non_interactive_do_not_store_non_persistent_properties_in_lean_con
ENGINE_IMAGE,
None,
False,
False)
False,
{})

config = container.lean_config_manager.get_lean_config()
if brokerage in brokerage_required_options_not_persistently_save_in_lean_config:
Expand Down Expand Up @@ -509,7 +540,8 @@ def test_live_non_interactive_calls_run_lean_when_all_options_given(brokerage: s
ENGINE_IMAGE,
None,
False,
False)
False,
{})

@pytest.mark.parametrize("brokerage,data_feed1,data_feed2",[(brokerage, *data_feeds) for brokerage, data_feeds in
itertools.product(brokerage_required_options.keys(), itertools.combinations(data_feed_required_options.keys(), 2))])
Expand Down Expand Up @@ -548,7 +580,8 @@ def test_live_non_interactive_calls_run_lean_when_all_options_given_with_multipl
ENGINE_IMAGE,
None,
False,
False)
False,
{})


@pytest.mark.parametrize("brokerage", brokerage_required_options.keys() - ["Paper Trading"])
Expand Down Expand Up @@ -606,7 +639,8 @@ def test_live_non_interactive_falls_back_to_lean_config_for_brokerage_settings(b
ENGINE_IMAGE,
None,
False,
False)
False,
{})


@pytest.mark.parametrize("data_feed", data_feed_required_options.keys())
Expand Down Expand Up @@ -653,7 +687,8 @@ def test_live_non_interactive_falls_back_to_lean_config_for_data_feed_settings(d
ENGINE_IMAGE,
None,
False,
False)
False,
{})


@pytest.mark.parametrize("data_feed1,data_feed2", itertools.combinations(data_feed_required_options.keys(), 2))
Expand Down Expand Up @@ -702,7 +737,8 @@ def test_live_non_interactive_falls_back_to_lean_config_for_multiple_data_feed_s
ENGINE_IMAGE,
None,
False,
False)
False,
{})


def test_live_forces_update_when_update_option_given() -> None:
Expand All @@ -721,7 +757,8 @@ def test_live_forces_update_when_update_option_given() -> None:
ENGINE_IMAGE,
None,
False,
False)
False,
{})


def test_live_passes_custom_image_to_lean_runner_when_set_in_config() -> None:
Expand All @@ -741,7 +778,8 @@ def test_live_passes_custom_image_to_lean_runner_when_set_in_config() -> None:
DockerImage(name="custom/lean", tag="123"),
None,
False,
False)
False,
{})


def test_live_passes_custom_image_to_lean_runner_when_given_as_option() -> None:
Expand All @@ -762,7 +800,8 @@ def test_live_passes_custom_image_to_lean_runner_when_given_as_option() -> None:
DockerImage(name="custom/lean", tag="456"),
None,
False,
False)
False,
{})


@pytest.mark.parametrize("python_venv", ["Custom-venv",
Expand Down
26 changes: 26 additions & 0 deletions tests/commands/test_optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,3 +753,29 @@ def run_image_for_estimate(image: DockerImage, **kwargs) -> bool:
args, kwargs = docker_manager.run_image.call_args

assert any(command == 'dotnet QuantConnect.Optimizer.Launcher.dll --estimate' for command in kwargs["commands"])


def test_optimize_runs_lean_container_with_extra_docker_config() -> None:
import docker.types

create_fake_lean_cli_directory()

docker_manager = mock.MagicMock()
docker_manager.run_image.side_effect = run_image
container.initialize(docker_manager=docker_manager)
container.optimizer_config_manager = _get_optimizer_config_manager_mock()

Storage(str(Path.cwd() / "Python Project" / "config.json")).set("parameters", {"param1": "1"})

result = CliRunner().invoke(lean, ["optimize", "Python Project",
"--extra-docker-config",
'{"device_requests": [{"count": -1, "capabilities": [[""]]}]}'])

assert result.exit_code == 0

docker_manager.run_image.assert_called_once()
args, kwargs = docker_manager.run_image.call_args

assert args[0] == ENGINE_IMAGE
assert "device_requests" in kwargs
assert kwargs["device_requests"] == [docker.types.DeviceRequest(count=-1, capabilities=[[""]])]
22 changes: 22 additions & 0 deletions tests/commands/test_research.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,25 @@ def test_research_runs_custom_image_when_given_as_option() -> None:
args, kwargs = docker_manager.run_image.call_args

assert args[0] == DockerImage(name="custom/research", tag="456")


def test_optimize_runs_lean_container_with_extra_docker_config() -> None:
import docker.types

create_fake_lean_cli_directory()

docker_manager = mock.MagicMock()
container.initialize(docker_manager)

result = CliRunner().invoke(lean, ["research", "Python Project",
"--extra-docker-config",
'{"device_requests": [{"count": -1, "capabilities": [[""]]}]}'])

assert result.exit_code == 0

docker_manager.run_image.assert_called_once()
args, kwargs = docker_manager.run_image.call_args

assert args[0] == RESEARCH_IMAGE
assert "device_requests" in kwargs
assert kwargs["device_requests"] == [docker.types.DeviceRequest(count=-1, capabilities=[[""]])]
Loading

0 comments on commit 13d2471

Please sign in to comment.