Add uninstaller

Closes #2

Also document installer, fix some formatting issues, add encoding to an
open(), and remove an obsolete TODO.
This commit is contained in:
Samuel Sloniker 2024-06-30 09:34:51 -07:00
parent 19ed511769
commit 21865ee327

View File

@ -49,6 +49,7 @@ def _mkdir_p(parts: Sequence[str]) -> None:
# (end code derived from `pathlib`)
class InvalidFileError(BaseException):
"""
CircuitPack package file is invalid.
@ -77,8 +78,9 @@ class _ResponseFile: # pylint: disable=too-few-public-methods
return response
def unpack(package: Union[BinaryIO, _ResponseFile], target: str) -> Iterable[str]:
# TODO: add a way to limit where packages can store files?
def unpack(
package: Union[BinaryIO, _ResponseFile], target: str
) -> Iterable[str]:
"""
Unpack the given file-like object `package` into the directory `target`,
which may, but is not required to, already exist. Return the unpacked
@ -135,14 +137,42 @@ def unpack_url(url: str, target: str) -> Iterable[str]:
return unpack(_ResponseFile(requests.get(url)), target)
def install(name: str, version_hash: str, repo: str, target: str, records: str) -> None:
def install(
name: str, version_hash: str, repo: str, target: str, records: str
) -> None:
"""
Download version `version_hash` of package `name` from `repo`, unpack it
into the directory `target`, and create a record file in `records`.
"""
if not repo.endswith("/"):
repo = repo + "/"
file_names = unpack_url(f"{repo}{name}.{version_hash}.cpa", target)
with open(f"{records}/{name}", "w+") as f:
f.write(f"{version_hash}\n")
with open(f"{records}/{name}", "w+", encoding="utf-8") as record:
record.write(f"{version_hash}\n")
for file_name in file_names:
f.write(f"{file_name}\n")
record.write(f"{file_name}\n")
def uninstall(name: str, target: str, records: str) -> None:
"""
Uninstall package `name` from `target` using the information stored in
`records`.
"""
with open(f"{records}/{name}", "r", encoding="utf-8") as record:
record.readline() # Skip over version hash
while True:
file_name = record.readline().strip()
if file_name:
os.remove(f"{target}/{file_name}")
else:
break
os.remove(f"{records}/{name}")