def test_backtest_auto_updates_outdated_csharp_csproj() -> None: create_fake_lean_cli_directory() csproj_path = Path.cwd() / "CSharp Project" / "CSharp Project.csproj" _generate_file( csproj_path, """ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <TargetFramework>net5.0</TargetFramework> <LangVersion>9</LangVersion> <OutputPath>bin/$(Configuration)</OutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <NoWarn>CS0618</NoWarn> </PropertyGroup> <ItemGroup> <PackageReference Include="QuantConnect.Lean" Version="2.5.11940"/> </ItemGroup> </Project> """) docker_manager = mock.Mock() container.docker_manager.override(providers.Object(docker_manager)) lean_runner = mock.Mock() container.lean_runner.override(providers.Object(lean_runner)) result = CliRunner().invoke(lean, ["backtest", "CSharp Project"]) assert result.exit_code == 0 csproj = XMLManager().parse(csproj_path.read_text(encoding="utf-8")) assert csproj.find(".//PropertyGroup/DefaultItemExcludes") is not None
def create_lean_runner(docker_manager: mock.Mock) -> LeanRunner: logger = mock.Mock() logger.debug_logging_enabled = False cli_config_manager = mock.Mock() cli_config_manager.user_id.get_value.return_value = "123" cli_config_manager.api_token.get_value.return_value = "456" project_config_manager = ProjectConfigManager(XMLManager()) cache_storage = Storage(str(Path("~/.lean/cache").expanduser())) lean_config_manager = LeanConfigManager(logger, cli_config_manager, project_config_manager, mock.Mock(), cache_storage) output_config_manager = OutputConfigManager(lean_config_manager) module_manager = mock.Mock() module_manager.get_installed_packages.return_value = [ NuGetPackage(name="QuantConnect.Brokerages", version="1.0.0") ] xml_manager = XMLManager() project_manager = ProjectManager(project_config_manager, lean_config_manager, xml_manager, PlatformManager()) return LeanRunner(logger, project_config_manager, lean_config_manager, output_config_manager, docker_manager, module_manager, project_manager, TempManager(), xml_manager)
def test_backtest_auto_updates_outdated_python_pycharm_debug_config() -> None: create_fake_lean_cli_directory() workspace_xml_path = Path.cwd( ) / "Python Project" / ".idea" / "workspace.xml" _generate_file( workspace_xml_path, """ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="RunManager" selected="Python Debug Server.Debug with Lean CLI"> <configuration name="Debug with Lean CLI" type="PyRemoteDebugConfigurationType" factoryName="Python Remote Debug"> <module name="LEAN" /> <option name="PORT" value="6000" /> <option name="HOST" value="localhost" /> <PathMappingSettings> <option name="pathMappings"> <list> <mapping local-root="$PROJECT_DIR$" remote-root="/Lean/Launcher/bin/Debug" /> </list> </option> </PathMappingSettings> <option name="REDIRECT_OUTPUT" value="true" /> <option name="SUSPEND_AFTER_CONNECT" value="true" /> <method v="2" /> </configuration> <list> <item itemvalue="Python Debug Server.Debug with Lean CLI" /> </list> </component> </project> """) docker_manager = mock.Mock() container.docker_manager.override(providers.Object(docker_manager)) lean_runner = mock.Mock() container.lean_runner.override(providers.Object(lean_runner)) result = CliRunner().invoke( lean, ["backtest", "Python Project", "--debug", "pycharm"]) assert result.exit_code == 1 workspace_xml = XMLManager().parse( workspace_xml_path.read_text(encoding="utf-8")) assert workspace_xml.find( ".//mapping[@remote-root='/LeanCLI']") is not None assert workspace_xml.find( ".//mapping[@remote-root='/Lean/Launcher/bin/Debug']") is None
def test_parse_parses_xml_string() -> None: xml_string = """ <Person> <!-- Person name --> <Name>John Doe</Name> <Email/> </Person> """ xml_tree = XMLManager().parse(xml_string) assert xml_tree.find(".//Name") is not None assert xml_tree.find(".//Email") is not None assert xml_tree.find(".//Name").text == "John Doe"
def test_get_csharp_libraries_skips_invalid_package_reference_tags() -> None: create_fake_lean_cli_directory() with (Path.cwd() / "CSharp Project" / "CSharp Project.csproj").open("w+", encoding="utf-8") as file: file.write(""" <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <TargetFramework>net5.0</TargetFramework> <LangVersion>9</LangVersion> <OutputPath>bin/$(Configuration)</OutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <NoWarn>CS0618</NoWarn> </PropertyGroup> <ItemGroup> <PackageReference Include="QuantConnect.Lean" Version="2.5.11586"/> <PackageReference Include="Microsoft.ML"/> <PackageReference Version="0.94.0"/> <PackageReference/> </ItemGroup> </Project> """) project_config_manager = ProjectConfigManager(XMLManager()) libraries = project_config_manager.get_csharp_libraries(Path.cwd() / "CSharp Project") assert len(libraries) == 1 assert CSharpLibrary(name="QuantConnect.Lean", version="2.5.11586") in libraries
def test_get_project_config_returns_storage_instance_of_correct_file() -> None: create_fake_lean_cli_directory() project_config_manager = ProjectConfigManager(XMLManager()) project_config = project_config_manager.get_project_config(Path.cwd() / "Python Project") assert project_config.file == Path.cwd() / "Python Project" / "config.json"
def test_get_local_id_returns_unique_id_per_project() -> None: create_fake_lean_cli_directory() project_config_manager = ProjectConfigManager(XMLManager()) python_id = project_config_manager.get_local_id(Path.cwd() / "Python Project") csharp_id = project_config_manager.get_local_id(Path.cwd() / "CSharp Project") assert python_id != csharp_id
def _create_project_manager() -> ProjectManager: xml_manager = XMLManager() project_config_manager = ProjectConfigManager(xml_manager) cache_storage = Storage(str(Path("~/.lean/cache").expanduser())) return ProjectManager( project_config_manager, LeanConfigManager(mock.Mock(), mock.Mock(), project_config_manager, mock.Mock(), cache_storage), xml_manager, PlatformManager())
def test_create_new_project_creates_rider_debugger_config_when_rider_not_installed_yet( system: mock.Mock, os: str, path: str) -> None: system.return_value = os key_path = Path("~/.lean/ssh/key").expanduser() project_manager = _create_project_manager() project_manager.create_new_project(Path.cwd() / "CSharp Project", QCLanguage.CSharp) debugger_file = Path( path).expanduser() / "Rider" / "options" / "debugger.xml" assert debugger_file.is_file() debugger_root = XMLManager().parse( debugger_file.read_text(encoding="utf-8")) assert debugger_root.find( f".//option/option[@value='<credentials HOST=\"localhost\" PORT=\"2222\" USERNAME=\"root\" PRIVATE_KEY_FILE=\"{key_path.as_posix()}\" USE_KEY_PAIR=\"true\" USE_AUTH_AGENT=\"false\" />']" ) is not None
def test_get_local_id_returns_same_id_for_project_when_called_multiple_times() -> None: create_fake_lean_cli_directory() project_config_manager = ProjectConfigManager(XMLManager()) ids = [] for _ in range(5): ids.append(project_config_manager.get_local_id(Path.cwd() / "Python Project")) assert len(set(ids)) == 1
def test_to_string_turns_xml_element_into_pretty_string() -> None: tree = etree.fromstring( "<Person><!-- Person name --><Name>John Doe</Name><Email/></Person>") assert XMLManager().to_string(tree) == """ <Person> <!-- Person name --> <Name>John Doe</Name> <Email/> </Person> """.strip() + "\n"
def test_get_project_by_id_returns_path_to_project() -> None: create_fake_lean_cli_directory() project_dir = Path.cwd() / "Python Project" project_config_manager = ProjectConfigManager(XMLManager()) project_id = project_config_manager.get_local_id(project_dir) project_manager = _create_project_manager() assert project_manager.get_project_by_id(project_id) == project_dir
def test_backtest_auto_updates_outdated_csharp_rider_debug_config() -> None: create_fake_lean_cli_directory() for dir_name in [".idea.CSharp Project", ".idea.CSharp Project.dir"]: _generate_file( Path.cwd() / "CSharp Project" / ".idea" / dir_name / ".idea" / "workspace.xml", """ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="RunManager"> <configuration name="Debug with Lean CLI" type="ConnectRemote" factoryName="Mono Remote" show_console_on_std_err="false" show_console_on_std_out="false" port="55556" address="localhost"> <option name="allowRunningInParallel" value="false" /> <option name="listenPortForConnections" value="false" /> <option name="selectedOptions"> <list /> </option> <method v="2" /> </configuration> </component> </project> """) docker_manager = mock.Mock() container.docker_manager.override(providers.Object(docker_manager)) lean_runner = mock.Mock() container.lean_runner.override(providers.Object(lean_runner)) result = CliRunner().invoke( lean, ["backtest", "CSharp Project", "--debug", "rider"]) assert result.exit_code == 1 for dir_name in [".idea.CSharp Project", ".idea.CSharp Project.dir"]: workspace_xml_path = Path.cwd( ) / "CSharp Project" / ".idea" / dir_name / ".idea" / "workspace.xml" workspace_xml = XMLManager().parse( workspace_xml_path.read_text(encoding="utf-8")) assert workspace_xml.find( ".//configuration[@name='Debug with Lean CLI']") is None
def test_create_new_project_creates_rider_debugger_entry_when_not_set_yet( system: mock.Mock, os: str, path: str) -> None: system.return_value = os key_path = Path("~/.lean/ssh/key").expanduser() debugger_file = Path( path).expanduser() / "Rider" / "options" / "debugger.xml" debugger_file.parent.mkdir(parents=True, exist_ok=True) with debugger_file.open("w+", encoding="utf-8") as file: file.write(f""" <application> <component name="XDebuggerSettings"> <data-views /> <general /> <debuggers> <debugger id="dotnet_debugger"> <configuration> <option name="needNotifyWhenStoppedInExternalCode" value="false" /> <option name="sshCredentials"> <option value="<credentials HOST="localhost" PORT="2222" USERNAME="root" PRIVATE_KEY_FILE="{key_path.as_posix()}" USE_KEY_PAIR="true" USE_AUTH_AGENT="false" />" /> </option> </configuration> </debugger> </debuggers> </component> </application> """) project_manager = _create_project_manager() project_manager.create_new_project(Path.cwd() / "CSharp Project", QCLanguage.CSharp) debugger_root = XMLManager().parse( debugger_file.read_text(encoding="utf-8")) assert debugger_root.find( f".//option/option[@value='<credentials HOST=\"localhost\" PORT=\"2222\" USERNAME=\"root\" PRIVATE_KEY_FILE=\"{key_path.as_posix()}\" USE_KEY_PAIR=\"true\" USE_AUTH_AGENT=\"false\" />']" ) is not None
def test_get_project_by_id_raises_error_when_no_project_with_given_id_exists( ) -> None: create_fake_lean_cli_directory() project_config_manager = ProjectConfigManager(XMLManager()) python_project_id = project_config_manager.get_local_id(Path.cwd() / "Python Project") csharp_project_id = project_config_manager.get_local_id(Path.cwd() / "CSharp Project") project_manager = _create_project_manager() with pytest.raises(Exception): project_manager.get_project_by_id( max(python_project_id, csharp_project_id) + 1)
def _create_output_config_manager() -> OutputConfigManager: cache_storage = Storage(str(Path("~/.lean/cache").expanduser())) return OutputConfigManager( LeanConfigManager(mock.Mock(), mock.Mock(), ProjectConfigManager(XMLManager()), mock.Mock(), cache_storage))
def _create_lean_config_manager( cli_config_manager: Optional[CLIConfigManager] = None ) -> LeanConfigManager: return LeanConfigManager(mock.Mock(), cli_config_manager or mock.Mock(), ProjectConfigManager(XMLManager()), mock.Mock(), Storage(str(Path("~/.lean/cache").expanduser())))
def validate_xml(text: str) -> bool: try: XMLManager().parse(text) return True except etree.ParseError: return False
def test_get_csharp_libraries_returns_empty_list_when_no_csproj_in_project_directory() -> None: create_fake_lean_cli_directory() project_config_manager = ProjectConfigManager(XMLManager()) assert len(project_config_manager.get_csharp_libraries(Path.cwd() / "Python Project")) == 0