Skip to content

Commit 3cdd024

Browse files
committed
refactor: several code simplifications
1 parent 73b8f40 commit 3cdd024

5 files changed

Lines changed: 31 additions & 43 deletions

File tree

src/typvend/cli.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
logger = logging.getLogger("typvend")
2222
VENDORING_ERRORS = (ValueError, TypeError, niquests.RequestException, OSError)
23+
PACKAGE_NAME_PATTERN = r"[a-zA-Z0-9_-]+"
2324

2425

2526
def main() -> None:
@@ -101,15 +102,11 @@ def parse_package_arg(pkg: str) -> tuple[str, str]:
101102
Raises:
102103
ValueError: If the package name is empty or contains invalid characters.
103104
"""
104-
if "@" in pkg:
105-
parts = pkg.split("@", 1)
106-
name = parts[0]
107-
version = parts[1] or "latest"
108-
else:
109-
name = pkg
105+
name, separator, version = pkg.partition("@")
106+
if not separator or not version:
110107
version = "latest"
111108

112-
if not name or not re.fullmatch(r"[a-zA-Z0-9_-]+", name):
109+
if not name or not re.fullmatch(PACKAGE_NAME_PATTERN, name):
113110
msg = f"Invalid package name: '{name}'. Only alphanumeric, hyphens, underscores allowed."
114111
raise ValueError(msg)
115112

src/typvend/downloader.py

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def download_package(
2525
namespace: str = "preview",
2626
*,
2727
force: bool = False,
28-
) -> bool:
28+
) -> None:
2929
"""Downloads and extracts a Typst package to the local directory.
3030
3131
Args:
@@ -35,10 +35,6 @@ def download_package(
3535
namespace: The namespace of the package (e.g. "preview").
3636
force: If True, overwrite the package even if it already exists.
3737
38-
Returns:
39-
True if the package was downloaded and extracted, False if it was
40-
skipped because it already exists and force was False.
41-
4238
Raises:
4339
ValueError: If a directory traversal is detected in the tarball.
4440
niquests.RequestException: If the package download fails.
@@ -51,25 +47,28 @@ def download_package(
5147
version,
5248
dest_dir,
5349
)
54-
return False
50+
return
5551

5652
url = f"https://packages.typst.org/{namespace}/{name}-{version}.tar.gz"
5753
logger.info("Downloading %s...", url)
5854
headers = {"User-Agent": f"typvend/{__version__}"}
5955

60-
try:
61-
response = niquests.get(url, headers=headers, timeout=30)
62-
response.raise_for_status()
63-
content = response.content
64-
if not content:
65-
msg = f"Failed to download package: no content received from {url}"
66-
raise ValueError(msg)
67-
except niquests.RequestException as e:
68-
logger.error("Failed to download package %s:%s: %s", name, version, e)
69-
raise
56+
response = niquests.get(url, headers=headers, timeout=30)
57+
response.raise_for_status()
58+
content = response.content
59+
if not content:
60+
msg = f"Failed to download package: no content received from {url}"
61+
raise ValueError(msg)
7062

7163
logger.info("Extracting %s to %s...", name, dest_dir)
7264
dest_dir.mkdir(parents=True, exist_ok=True)
65+
_extract_tar(content, dest_dir)
66+
67+
logger.info("Successfully vendored %s:%s", name, version)
68+
69+
70+
def _extract_tar(content: bytes, dest_dir: Path) -> None:
71+
"""Extract a gzipped tarball while preventing directory traversal."""
7372
dest_abs = dest_dir.resolve()
7473

7574
tar_data = io.BytesIO(content)
@@ -83,6 +82,3 @@ def download_package(
8382
msg = f"Attempted directory traversal in tarball: {member.name}"
8483
raise ValueError(msg)
8584
tar.extractall(path=dest_dir)
86-
87-
logger.info("Successfully vendored %s:%s", name, version)
88-
return True

src/typvend/index.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,4 @@ def resolve_latest_version(pkg_name: str, namespace: str = "preview") -> str:
9494
msg = f"Package '{pkg_name}' not found in namespace '{namespace}'"
9595
raise ValueError(msg)
9696

97-
versions.sort(key=lambda v: v[0])
98-
return versions[-1][1]
97+
return max(versions, key=lambda v: v[0])[1]

src/typvend/scanner.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from pathlib import Path
1010

1111
logger = logging.getLogger(__name__)
12+
PACKAGE_NAME_PATTERN = r"[a-zA-Z0-9_-]+"
1213

1314

1415
def scan_file(file_path: Path, namespace: str = "preview") -> set[tuple[str, str]]:
@@ -23,21 +24,15 @@ def scan_file(file_path: Path, namespace: str = "preview") -> set[tuple[str, str
2324
Returns:
2425
A set of tuples (package_name, version).
2526
"""
26-
found: set[tuple[str, str]] = set()
27-
pattern = re.compile(rf"@{re.escape(namespace)}/([a-zA-Z0-9_-]+):(\d+\.\d+\.\d+)")
27+
pattern = re.compile(rf"@{re.escape(namespace)}/({PACKAGE_NAME_PATTERN}):(\d+\.\d+\.\d+)")
2828

2929
try:
3030
content = file_path.read_text(encoding="utf-8", errors="ignore")
3131
except OSError as e:
3232
logger.warning("Could not read file %s: %s", file_path, e)
33-
return found
34-
35-
for match in pattern.finditer(content):
36-
pkg_name = match.group(1)
37-
version = match.group(2)
38-
found.add((pkg_name, version))
33+
return set()
3934

40-
return found
35+
return {(match.group(1), match.group(2)) for match in pattern.finditer(content)}
4136

4237

4338
def scan_path(path: Path, namespace: str = "preview") -> set[tuple[str, str]]:

tests/test_downloader.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def create_mock_tarball(files: dict[str, bytes]) -> bytes:
3131
@patch("niquests.get")
3232
def test_download_package(mock_get: MagicMock, tmp_path: Path) -> None:
3333
"""Tests successful package download, extraction, and override behavior."""
34+
expected_forced_download_count = 2
3435
mock_tar = create_mock_tarball({"lib.typ": b"// lib content", "typst.toml": b"name = 'pkg'"})
3536
mock_response = MagicMock()
3637
mock_response.content = mock_tar
@@ -39,20 +40,20 @@ def test_download_package(mock_get: MagicMock, tmp_path: Path) -> None:
3940
output_dir = tmp_path / "vendor"
4041

4142
# Download first time
42-
downloaded = download_package("pkg", "0.1.0", output_dir=output_dir, force=False)
43-
assert downloaded is True
43+
download_package("pkg", "0.1.0", output_dir=output_dir, force=False)
4444

4545
pkg_dir = output_dir / "preview" / "pkg" / "0.1.0"
4646
assert (pkg_dir / "lib.typ").read_text(encoding="utf-8") == "// lib content"
4747
assert (pkg_dir / "typst.toml").read_text(encoding="utf-8") == "name = 'pkg'"
48+
assert mock_get.call_count == 1
4849

4950
# Try downloading again without force (should skip)
50-
downloaded_again = download_package("pkg", "0.1.0", output_dir=output_dir, force=False)
51-
assert downloaded_again is False
51+
download_package("pkg", "0.1.0", output_dir=output_dir, force=False)
52+
assert mock_get.call_count == 1
5253

5354
# Try downloading again with force
54-
downloaded_force = download_package("pkg", "0.1.0", output_dir=output_dir, force=True)
55-
assert downloaded_force is True
55+
download_package("pkg", "0.1.0", output_dir=output_dir, force=True)
56+
assert mock_get.call_count == expected_forced_download_count
5657

5758

5859
@patch("niquests.get")

0 commit comments

Comments
 (0)