Skip to content

Commit 6c6fa92

Browse files
Fix mount points conflict causing empty project DLL in research environment (#541)
* chore: exclude .python-version for git tracking * fix: mount points conflict by LeanCLI and NoteBooks directory * test: check both mount points available * chore: add explanation for the test issue * fix: use Assembly.LoadFrom(<csproj_name>) in Initialize.csx for research to keep consistent with docs * Minor unit test fix --------- Co-authored-by: Jhonathan Abreu <[email protected]>
1 parent 878d5f2 commit 6c6fa92

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

Diff for: .gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ ipython_config.py
8888
# pyenv
8989
# For a library or package, you might want to ignore these files since the code is
9090
# intended to run in multiple environments; otherwise, check them in:
91-
# .python-version
91+
.python-version
9292

9393
# pipenv
9494
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.

Diff for: lean/commands/research.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ def research(project: Path,
149149
research_image,
150150
paths_to_mount)
151151

152+
# Mount project dir to the Notebooks directory first, avoid using volumes to prevent overwriting mounting logic for /LeanCLI
153+
run_options["mounts"].append(Mount(
154+
target=f"{LEAN_ROOT_PATH}/Notebooks",
155+
source=str(project),
156+
type="bind",
157+
read_only=False
158+
))
159+
152160
# Mount the config in the notebooks directory as well
153161
local_config_path = next(m["Source"] for m in run_options["mounts"] if m["Target"].endswith("config.json"))
154162
run_options["mounts"].append(Mount(target=f"{LEAN_ROOT_PATH}/Notebooks/config.json",
@@ -166,12 +174,6 @@ def research(project: Path,
166174
# Make Ctrl+C stop Jupyter Lab immediately
167175
run_options["stop_signal"] = "SIGKILL"
168176

169-
# Mount the project to the notebooks directory
170-
run_options["volumes"][str(project)] = {
171-
"bind": f"{LEAN_ROOT_PATH}/Notebooks",
172-
"mode": "rw"
173-
}
174-
175177
# Allow notebooks to be embedded in iframes
176178
run_options["commands"].append("mkdir -p ~/.jupyter")
177179
run_options["commands"].append(

Diff for: tests/commands/test_research.py

+40
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,43 @@ def test_research_runs_lean_container_with_paths_to_mount() -> None:
280280

281281
assert mount is not None
282282
assert mount["Target"] == "/Files/file.json"
283+
284+
def test_research_mounts_project_directory_to_leancli_and_notebooks() -> None:
285+
create_fake_lean_cli_directory()
286+
287+
docker_manager = mock.MagicMock()
288+
container.initialize(docker_manager)
289+
290+
project_dir = Path.cwd() / "CSharp Project"
291+
(project_dir / "Main.cs").touch()
292+
original_csproj = project_dir / "CSharp Project.csproj"
293+
original_csproj.write_text("""
294+
<Project>
295+
<PropertyGroup></PropertyGroup>
296+
<ItemGroup>
297+
<PackageReference Include="QuantConnect.Lean.Engine" Version="2.5.*" />
298+
</ItemGroup>
299+
</Project>""")
300+
301+
result = CliRunner().invoke(lean, ["research", "CSharp Project"])
302+
303+
assert result.exit_code == 0
304+
305+
docker_manager.run_image.assert_called_once()
306+
args, kwargs = docker_manager.run_image.call_args
307+
308+
leancli_volume = next(((k, v) for (k, v) in kwargs["volumes"].items() if v['bind'] == f"/LeanCLI"), None)
309+
notebooks_mount = next((m for m in kwargs["mounts"] if m["Target"] == f"{LEAN_ROOT_PATH}/Notebooks"), None)
310+
311+
assert leancli_volume is not None, "/LeanCLI is not mounted"
312+
assert notebooks_mount is not None, "/Notebooks is not mounted"
313+
assert leancli_volume[0] == str(project_dir)
314+
assert notebooks_mount["Source"] == str(project_dir)
315+
316+
temp_csproj_mounts = [
317+
m for m in kwargs["mounts"]
318+
if m["Target"].startswith(f"/LeanCLI") and m["Target"].endswith(".csproj")
319+
]
320+
321+
assert len(temp_csproj_mounts) > 0, "No temporary csproj file mounts detected"
322+
assert all(m["Source"] != str(original_csproj) for m in temp_csproj_mounts), "Temporary csproj did not correctly overwrite user file"

0 commit comments

Comments
 (0)