Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 6 additions & 14 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ jobs:
timeout-minutes: 30
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v6
Expand Down Expand Up @@ -70,16 +69,9 @@ jobs:
benchmarks/results/latest.md
retention-days: 30

- name: Post PR comment
if: github.event_name == 'pull_request'
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
const body = fs.readFileSync('benchmarks/results/latest.md', 'utf8');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `<details><summary>Benchmark results</summary>\n\n${body}\n</details>`,
});
# The full report goes to the run's job summary (and the artifact above),
# not a PR comment: clean CI lacks the remote data tiers, so the absolute
# numbers are misleading for resolvekit and add noise rather than review
# signal in the PR thread.
- name: Publish job summary
run: cat benchmarks/results/latest.md >> "$GITHUB_STEP_SUMMARY"
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.1.2 (2026-06-11)

**Fixed.** `download()` crashed on a clean install with "Missing package
'tqdm' required for progress bars": pooch's progress bar needs tqdm, which is
not a resolvekit dependency. Downloads now show a progress bar when tqdm is
installed and run silently when it isn't.

## 0.1.1 (2026-06-11)

**Fixed.** Partial remote caches no longer error: after downloading a single
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ rk.download("geo.admin1") # ~12 MB; verifies checksum, then marks is_available
```python
>>> import resolvekit as rk
>>> rk.__version__
'0.1.1'
'0.1.2'
>>> rk.resolve_id("United States")
'country/USA'
```
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ Resolver.lite().domains # ['geo']

```python
r.info.data_version # "2026.06"
r.info.resolvekit_version # "0.1.1"
r.info.resolvekit_version # "0.1.2"
r.info.domains # ("geo", "org")
r.info.routing_mode # "auto"
r.info.closed # False
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "resolvekit"
version = "0.1.1"
version = "0.1.2"
description = "Entity and place resolution system that maps messy place/entity strings and codes to canonical entities"
requires-python = ">=3.12"

Expand Down
12 changes: 11 additions & 1 deletion src/resolvekit/core/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ def download_module_data(
return cache_dir


def _progressbar_available() -> bool:
"""Pooch's progress bar requires tqdm, which is not a resolvekit
dependency; downloads degrade to silent when it isn't installed."""
import importlib.util

return importlib.util.find_spec("tqdm") is not None


def _download_one_artifact(
metadata: DataPackMetadata,
artifact_type: str,
Expand All @@ -234,7 +242,9 @@ def _download_one_artifact(
processor = pooch.Decompress() if fname.endswith(".gz") else None

try:
downloaded_path = fetcher.fetch(fname, progressbar=True, processor=processor)
downloaded_path = fetcher.fetch(
fname, progressbar=_progressbar_available(), processor=processor
)
except Exception as exc:
logger.error(
"Download failed for %s/%s: %s", metadata.module_id, artifact_type, exc
Expand Down
58 changes: 58 additions & 0 deletions tests/core/test_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,3 +468,61 @@ def test_make_fetcher_adds_trailing_slash_to_override(
)
fetcher = _make_fetcher(remote_metadata, _sqlite_spec(remote_metadata))
assert fetcher.base_url.endswith("/")


class TestProgressbarFallback:
"""Pooch's progress bar requires tqdm, which resolvekit does not depend
on — downloads must work silently when tqdm is not installed."""

def test_progressbar_available_reflects_tqdm_presence(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
import importlib.util

from resolvekit.core.remote import _progressbar_available

real_find_spec = importlib.util.find_spec

def fake_find_spec(name: str, *args: object, **kwargs: object) -> object:
if name == "tqdm":
return None
return real_find_spec(name, *args, **kwargs)

monkeypatch.setattr(importlib.util, "find_spec", fake_find_spec)
assert _progressbar_available() is False

def test_fetch_runs_without_progressbar_when_tqdm_missing(
self,
remote_metadata: DataPackMetadata,
package_dir: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
from resolvekit.core import remote

monkeypatch.setattr(remote, "_progressbar_available", lambda: False)
sqlite_content = b"fake sqlite content for testing"

def fake_fetch(
fname: str, progressbar: bool = False, processor: object = None
) -> str:
assert progressbar is False
cache_dir = _module_cache_dir(remote_metadata.module_id)
cache_dir.mkdir(parents=True, exist_ok=True)
decompressed_name = (
fname.removesuffix(".gz") if fname.endswith(".gz") else fname
)
sqlite_path = cache_dir / decompressed_name
sqlite_path.write_bytes(sqlite_content)
return str(sqlite_path)

with patch("resolvekit.core.remote._make_fetcher") as mock_fetcher:
fetcher = MagicMock()
fetcher.fetch.side_effect = fake_fetch
mock_fetcher.return_value = fetcher

result = download_module_data(remote_metadata, package_dir)

assert fetcher.fetch.call_count >= 1
for call in fetcher.fetch.call_args_list:
assert call.kwargs["progressbar"] is False
assert (result / "entities.sqlite").exists()
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading