Skip to content

Commit

Permalink
Improve handling of net versions missmatch (#526)
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin-Molinero authored Dec 18, 2024
1 parent 0f8aa4f commit 317d538
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 16 deletions.
32 changes: 22 additions & 10 deletions lean/components/docker/lean_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,13 +585,14 @@ def set_up_csharp_options(self, project_dir: Path, run_options: Dict[str, Any],
"mode": "rw"
}

framework_ver = self._docker_manager.get_image_label(image, 'target_framework',
DEFAULT_LEAN_DOTNET_FRAMEWORK)

# Ensure all .csproj files refer to the version of LEAN in the Docker container
csproj_temp_dir = self._temp_manager.create_temporary_directory()
for path in compile_root.rglob("*.csproj"):
self._ensure_csproj_uses_correct_lean(compile_root, path, csproj_temp_dir, run_options)
self._ensure_csproj_is_valid(compile_root, path, csproj_temp_dir, run_options, framework_ver)

framework_ver = self._docker_manager.get_image_label(image, 'target_framework',
DEFAULT_LEAN_DOTNET_FRAMEWORK)
# Set up the MSBuild properties
msbuild_properties = {
"Configuration": "Release" if release else "Debug",
Expand All @@ -601,8 +602,6 @@ def set_up_csharp_options(self, project_dir: Path, run_options: Dict[str, Any],
"GenerateAssemblyInfo": "false",
"GenerateTargetFrameworkAttribute": "false",
"AppendTargetFrameworkToOutputPath": "false",
"AutoGenerateBindingRedirects": "true",
"GenerateBindingRedirectsOutputType": "true",
"AutomaticallyUseReferenceAssemblyPackages": "false",
"CopyLocalLockFileAssemblies": "true",
"PathMap": f"/LeanCLI={str(compile_root)}",
Expand Down Expand Up @@ -770,11 +769,12 @@ def _get_csharp_compile_root(self, project_dir: Path) -> Path:

return project_dir

def _ensure_csproj_uses_correct_lean(self,
compile_root: Path,
csproj_path: Path,
temp_dir: Path,
run_options: Dict[str, Any]) -> None:
def _ensure_csproj_is_valid(self,
compile_root: Path,
csproj_path: Path,
temp_dir: Path,
run_options: Dict[str, Any],
net_framework: str) -> None:
"""Ensures a C# project is compiled using the version of LEAN in the Docker container.
When a .csproj file refers to the NuGet version of LEAN,
Expand All @@ -791,6 +791,18 @@ def _ensure_csproj_uses_correct_lean(self,
csproj = self._xml_manager.parse(csproj_path.read_text(encoding="utf-8"))
include_added = False

if net_framework:
target_framework_iter = csproj.iter("TargetFramework")
if target_framework_iter:
target_frameworks = [framework.text for framework in target_framework_iter]
if target_frameworks:
if net_framework not in target_frameworks:
raise RuntimeError(f"This project is targeting {target_frameworks[0].replace('net', 'Net ')}"
f" and {net_framework.replace('net', 'Net ')} is required. Please"
f" update the \"Target Framework\" project setting in VSCode to"
f" the new SDK or modify the csproj file directly to "
f"\"<TargetFramework>{net_framework}</TargetFramework>\".")

for package_reference in csproj.iter("PackageReference"):
if not package_reference.get("Include", "").lower().startswith("quantconnect."):
continue
Expand Down
4 changes: 2 additions & 2 deletions lean/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@

# we get these values from the image labels, but we still have defaults just in case
DEFAULT_LEAN_PYTHON_VERSION = "3.11"
DEFAULT_LEAN_STRICT_PYTHON_VERSION = f"{DEFAULT_LEAN_PYTHON_VERSION}.7"
DEFAULT_LEAN_DOTNET_FRAMEWORK = "net6.0"
DEFAULT_LEAN_STRICT_PYTHON_VERSION = f"{DEFAULT_LEAN_PYTHON_VERSION}.11"
DEFAULT_LEAN_DOTNET_FRAMEWORK = "net9.0"

# Label name used in Docker containers to specify the version of Lean being used
CONTAINER_LABEL_LEAN_VERSION_NAME = "lean_version"
Expand Down
2 changes: 1 addition & 1 deletion tests/commands/test_backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ def test_backtest_auto_updates_outdated_csharp_csproj() -> None:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<OutputPath>bin/$(Configuration)</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<NoWarn>CS0618</NoWarn>
Expand Down
4 changes: 2 additions & 2 deletions tests/components/config/test_project_config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def test_get_csharp_libraries_returns_all_libraries_in_package_reference_tags_in
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<OutputPath>bin/$(Configuration)</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<NoWarn>CS0618</NoWarn>
Expand Down Expand Up @@ -99,7 +99,7 @@ def test_get_csharp_libraries_skips_invalid_package_reference_tags() -> None:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<OutputPath>bin/$(Configuration)</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<NoWarn>CS0618</NoWarn>
Expand Down
7 changes: 6 additions & 1 deletion tests/components/docker/test_lean_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from lean.components.util.project_manager import ProjectManager
from lean.components.util.temp_manager import TempManager
from lean.components.util.xml_manager import XMLManager
from lean.constants import DEFAULT_ENGINE_IMAGE, LEAN_ROOT_PATH, DEFAULT_DATA_DIRECTORY_NAME
from lean.constants import DEFAULT_ENGINE_IMAGE, LEAN_ROOT_PATH, DEFAULT_DATA_DIRECTORY_NAME, DEFAULT_LEAN_DOTNET_FRAMEWORK
from lean.models.utils import DebuggingMethod
from lean.models.docker import DockerImage
from lean.models.modules import NuGetPackage
Expand Down Expand Up @@ -97,6 +97,7 @@ def test_run_lean_compiles_csharp_project_in_correct_configuration(release: bool

docker_manager = mock.Mock()
docker_manager.run_image.return_value = True
docker_manager.get_image_label.return_value = DEFAULT_LEAN_DOTNET_FRAMEWORK

lean_runner = create_lean_runner(docker_manager)

Expand All @@ -123,6 +124,7 @@ def test_run_lean_runs_lean_container_detached() -> None:

docker_manager = mock.Mock()
docker_manager.run_image.return_value = True
docker_manager.get_image_label.return_value = DEFAULT_LEAN_DOTNET_FRAMEWORK

lean_runner = create_lean_runner(docker_manager)

Expand Down Expand Up @@ -384,6 +386,7 @@ def test_run_lean_sets_image_name_when_debugging_with_vsdbg() -> None:

docker_manager = mock.Mock()
docker_manager.run_image.return_value = True
docker_manager.get_image_label.return_value = DEFAULT_LEAN_DOTNET_FRAMEWORK

lean_runner = create_lean_runner(docker_manager)

Expand All @@ -407,6 +410,7 @@ def test_run_lean_exposes_ssh_when_debugging_with_rider() -> None:

docker_manager = mock.Mock()
docker_manager.run_image.return_value = True
docker_manager.get_image_label.return_value = DEFAULT_LEAN_DOTNET_FRAMEWORK

lean_runner = create_lean_runner(docker_manager)

Expand Down Expand Up @@ -556,6 +560,7 @@ def test_run_lean_compiles_csharp_project_that_is_part_of_a_solution(in_solution

docker_manager = mock.Mock()
docker_manager.run_image.return_value = True
docker_manager.get_image_label.return_value = DEFAULT_LEAN_DOTNET_FRAMEWORK

root_dir = Path.cwd()
lean_runner = create_lean_runner(docker_manager)
Expand Down

0 comments on commit 317d538

Please sign in to comment.