forked from QuantConnect/lean-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
remove.py
127 lines (94 loc) · 4.94 KB
/
remove.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean CLI v1.0. Copyright 2021 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import shutil
import subprocess
from pathlib import Path
import click
from pkg_resources import Requirement
from lean.click import LeanCommand, PathParameter
from lean.container import container
from lean.models.errors import MoreInfoError
def _remove_csharp(project_dir: Path, name: str, no_local: bool) -> None:
"""Removes a custom C# library from a C# project.
Removes the library from the project's .csproj file,
and restores the project if dotnet is on the user's PATH and no_local is False.
:param project_dir: the path to the project directory
:param name: the name of the library to remove
:param no_local:
"""
logger = container.logger()
path_manager = container.path_manager()
csproj_file = next(p for p in project_dir.iterdir() if p.name.endswith(".csproj"))
logger.info(f"Removing {name} from '{path_manager.get_relative_path(csproj_file)}'")
xml_manager = container.xml_manager()
csproj_tree = xml_manager.parse(csproj_file.read_text(encoding="utf-8"))
for package_reference in csproj_tree.findall(".//PackageReference"):
if package_reference.get("Include", "").lower() == name.lower():
package_reference.getparent().remove(package_reference)
csproj_file.write_text(xml_manager.to_string(csproj_tree), encoding="utf-8")
if not no_local and shutil.which("dotnet") is not None:
logger.info(f"Restoring packages in '{path_manager.get_relative_path(project_dir)}'")
process = subprocess.run(["dotnet", "restore", str(csproj_file)], cwd=project_dir)
if process.returncode != 0:
raise RuntimeError("Something went wrong while restoring packages, see the logs above for more information")
def _remove_python(project_dir: Path, name: str) -> None:
"""Removes a custom Python library from a Python project.
Removes the library from the project's requirements.txt file.
:param project_dir: the path to the project directory
:param name: the name of the library to remove
"""
logger = container.logger()
path_manager = container.path_manager()
requirements_file = project_dir / "requirements.txt"
logger.info(f"Removing {name} from '{path_manager.get_relative_path(requirements_file)}'")
if not requirements_file.is_file():
return
requirements_content = requirements_file.read_text(encoding="utf-8")
new_lines = []
for line in requirements_content.splitlines():
try:
requirement = Requirement.parse(line)
if requirement.name.lower() != name.lower():
new_lines.append(line)
except ValueError:
new_lines.append(line)
new_content = "\n".join(new_lines).strip()
new_content = new_content + "\n" if len(new_content) > 0 else new_content
requirements_file.write_text(new_content, encoding="utf-8")
@click.command(cls=LeanCommand, requires_docker=True)
@click.argument("project", type=PathParameter(exists=True, file_okay=False, dir_okay=True))
@click.argument("name", type=str)
@click.option("--no-local", is_flag=True, default=False, help="Skip making changes to your local environment")
def remove(project: Path, name: str, no_local: bool) -> None:
"""Remove a custom library from a project.
PROJECT must be the path to the project directory.
NAME must be the name of the NuGet package (for C# projects) or of the PyPI package (for Python projects) to remove.
Custom C# libraries are removed from the project's .csproj file,
which is then restored if dotnet is on your PATH and the --no-local flag has not been given.
Custom Python libraries are removed from the project's requirements.txt file.
\b
C# example usage:
$ lean library remove "My CSharp Project" Microsoft.ML
\b
Python example usage:
$ lean library remove "My Python Project" tensorflow
"""
project_config = container.project_config_manager().get_project_config(project)
project_language = project_config.get("algorithm-language", None)
if project_language is None:
raise MoreInfoError(f"{project} is not a Lean CLI project",
"https://www.lean.io/docs/lean-cli/projects/project-management#02-Create-Projects")
if project_language == "CSharp":
_remove_csharp(project, name, no_local)
else:
_remove_python(project, name)