This repository was archived by the owner on Sep 23, 2025. It is now read-only.
forked from Tudat/tudatBundle
-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathuninstall.py
More file actions
156 lines (125 loc) · 4.99 KB
/
uninstall.py
File metadata and controls
156 lines (125 loc) · 4.99 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
from pathlib import Path
import sys
import os
import argparse
import shutil
class RemoveParser(argparse.ArgumentParser):
def __init__(self) -> None:
super().__init__(
prog="uninstall.py",
)
self.add_argument(
"--build-dir",
metavar="<path>",
type=str,
default="build",
help="Build directory",
)
return None
class Remover:
def __init__(self) -> None:
self.args = RemoveParser().parse_args()
# Resolve build directory
self.build_dir = Path(self.args.build_dir).resolve()
if not self.build_dir.exists():
raise FileNotFoundError(
f"Build directory {self.build_dir} does not exist."
)
# Resolve conda prefix
self.conda_prefix = Path(os.environ["CONDA_PREFIX"])
if not self.conda_prefix.exists():
raise FileNotFoundError(
f"Conda prefix {self.conda_prefix} does not exist."
)
# Resolve installation manifest
self.manifest_dir = self.build_dir / "manifests"
self.manifest = self.manifest_dir / f"{self.conda_prefix.name}.txt"
if not self.manifest.exists():
# Backwards compatibility: Try to look for the old manifest
self.manifest = self.build_dir / "custom-manifest.txt"
if not self.manifest.exists():
raise FileNotFoundError(
"Installation manifest not found for active "
f"conda environment: {self.conda_prefix.name}"
)
# Check if the format of the old manifest is compatible
content = self.manifest.read_text().splitlines()
for line in content:
if len(line.split(" ")) != 2 and line != "":
print(
"WARNING\n"
"It looks like your current installation of tudatpy was"
"\ninstalled using a version of `tudat-bundle` that is"
"\nincompatible with this script.\n"
"You can find instructions on how to remove it here:\n"
"https://github.com/tudat-team/tudat-bundle/wiki/backwards-compatibility"
)
exit(1)
return None
def preserve_remaining(self) -> list[str]:
preserve = []
for line in self.manifest.read_text().splitlines():
code, _element = line.split(" ")
element = Path(_element.strip())
if element.exists():
preserve.append(f"{code} {element}")
# Write remaining entries to manifest
with self.manifest.open("w") as manifest:
manifest.write("\n".join(preserve))
return preserve
def remove(self) -> None:
links = []
directories = []
remaining = {}
for line in self.manifest.read_text().splitlines():
code, _element = line.split(" ")
element = Path(_element.strip())
# Parse manifest for invalid entries before starting removal
match code:
case "000":
if not element.is_symlink():
raise ValueError(
"Aborting uninstall: "
f"Not a symlink with code 000: {element}"
)
links.append(element)
case "999":
if not element.is_dir():
raise ValueError(
"Aborting uninstall: "
f"Not a directory with code 999: {element}"
)
if element.name not in ["tudat", "tudatpy"]:
raise ValueError(
"Aborting uninstall: Attempted to delete unexpected"
f" directory: {element}\n"
"This error is a safeguard and it should not occur."
"Please, contact the tudatpy team for support. "
)
directories.append(element)
case _:
raise ValueError(
"Aborting uninstall: "
f"Unknown code {code} for {element}"
)
# Remove links
for link in links:
try:
link.unlink()
finally:
self.preserve_remaining()
# Remove directories
for directory in directories:
try:
shutil.rmtree(directory)
finally:
self.preserve_remaining()
# Remove manifest
remaining = self.preserve_remaining()
if len(remaining) == 0:
self.manifest.unlink()
else:
for item in remaining:
print(f"Failed to remove: {item.split(' ')[1]}")
if __name__ == "__main__":
Remover().remove()