mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 19:06:11 +00:00
doctor judged the local provider by the API key it does not use, so a fully local machine always saw a red mark, and it crashed outright with local cleanup picked; both lines now ask readiness. config list printed the Groq key in plaintext while masking the other two. The one subprocess decoded with the locale codepage gets its UTF-8 back, so a Turkish filename cannot hang a file transcription, and a redirected stdout on Windows replaces what it cannot encode instead of failing after the work succeeded. meeting-cancel stops advertising a --wait the server never honoured. "you" and "bye" leave the hallucination list: people dictate them. The minutes stage failing no longer burns the transcription checkpoint, and an untouched meeting-length dial no longer rewrites a value the command line set in seconds. A prompt box compared against the wrong language's default after a switch no longer fossilizes the old default as a custom prompt. The 67 strings of the local-model box, the whole first-run screen of the shipped default, get their Turkish. The hub cache moves to the platform's cache directory instead of ~/.cache on every system; the old directory is a few orphaned kilobytes with a six-hour shelf life. The last NO_WINDOW spellings collapse into the constant paths already carries, one windowed-executable lookup, one session-file reader, one install-record reader, one download progress signal carrying its destination, and the KDE conflict scan loses the branch its other branch already covered. Co-Authored-By: Claude Fable 5 <[email protected]>
195 lines
7.3 KiB
Python
195 lines
7.3 KiB
Python
"""What GitHub and Hugging Face are asked, and what is believed of the answer."""
|
|
|
|
import json
|
|
|
|
from dikte import hub
|
|
from dikte import paths
|
|
from tests.support import DikteTest, fake_urlopen, http_error, url_error
|
|
|
|
RELEASE = {
|
|
"tag_name": "v1.9.1",
|
|
"assets": [
|
|
{"name": "whisper-bin-ubuntu-x64.tar.gz",
|
|
"browser_download_url": "https://example.invalid/ubuntu-x64.tar.gz",
|
|
"size": 9379235, "digest": "sha256:" + "a" * 64},
|
|
{"name": "whisper-bin-x64.zip",
|
|
"browser_download_url": "https://example.invalid/win.zip",
|
|
"size": 100, "digest": "sha256:" + "b" * 64},
|
|
{"name": "no-url-here.zip", "size": 1},
|
|
],
|
|
}
|
|
|
|
TREE = [
|
|
{"type": "file", "path": ".gitattributes", "size": 1477},
|
|
{"type": "file", "path": "ggml-base.bin", "size": 147951465,
|
|
"lfs": {"oid": "c" * 64, "size": 147951465}},
|
|
{"type": "directory", "path": "extra"},
|
|
{"type": "file", "path": "extra/ggml-tiny.bin", "size": 77691713,
|
|
"lfs": {"oid": "d" * 64, "size": 77691713}},
|
|
]
|
|
|
|
MODELS = [
|
|
{"id": "ggml-org/gemma-3-4b-it-GGUF", "downloads": 44606,
|
|
"lastModified": "2026-07-01T00:00:00.000Z"},
|
|
{"id": "ggml-org/gpt-oss-20b-GGUF", "downloads": 47975},
|
|
{"noid": True},
|
|
]
|
|
|
|
|
|
class Releases(DikteTest):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.patch_attr(hub, "CACHE_DIR", self.path("cache"))
|
|
|
|
def test_the_tag_and_the_assets_come_back(self):
|
|
with fake_urlopen(RELEASE) as calls:
|
|
tag, assets = hub.release("ggml-org/whisper.cpp")
|
|
self.assertEqual(tag, "v1.9.1")
|
|
self.assertEqual([a.name for a in assets],
|
|
["whisper-bin-ubuntu-x64.tar.gz", "whisper-bin-x64.zip"])
|
|
self.assertEqual(calls[0].full_url,
|
|
"https://api.github.com/repos/ggml-org/whisper.cpp/"
|
|
"releases/latest")
|
|
|
|
def test_the_sha256_prefix_is_dropped(self):
|
|
with fake_urlopen(RELEASE):
|
|
_, assets = hub.release("ggml-org/whisper.cpp")
|
|
self.assertEqual(assets[0].sha256, "a" * 64)
|
|
|
|
def test_a_tag_asks_for_that_tag(self):
|
|
with fake_urlopen(RELEASE) as calls:
|
|
hub.release("ggml-org/whisper.cpp", "v1.9.1")
|
|
self.assertTrue(calls[0].full_url.endswith("/releases/tags/v1.9.1"))
|
|
|
|
def test_a_release_with_no_assets_is_an_error(self):
|
|
with fake_urlopen({"tag_name": "v1", "assets": []}):
|
|
with self.assertRaises(hub.HubError):
|
|
hub.release("ggml-org/whisper.cpp")
|
|
|
|
def test_the_second_call_asks_nobody(self):
|
|
with fake_urlopen(RELEASE) as calls:
|
|
hub.release("ggml-org/whisper.cpp")
|
|
hub.release("ggml-org/whisper.cpp")
|
|
self.assertEqual(len(calls), 1)
|
|
|
|
def test_a_refresh_asks_again(self):
|
|
with fake_urlopen(RELEASE) as calls:
|
|
hub.release("ggml-org/whisper.cpp")
|
|
hub.release("ggml-org/whisper.cpp", refresh=True)
|
|
self.assertEqual(len(calls), 2)
|
|
|
|
def test_an_old_cache_beats_no_answer(self):
|
|
with fake_urlopen(RELEASE):
|
|
hub.release("ggml-org/whisper.cpp")
|
|
# Old enough that it would normally be fetched again, and no network
|
|
# to fetch it with.
|
|
for path in self.path("cache").iterdir():
|
|
os_utime(path)
|
|
with fake_urlopen(url_error()):
|
|
tag, assets = hub.release("ggml-org/whisper.cpp")
|
|
self.assertEqual(tag, "v1.9.1")
|
|
self.assertEqual(len(assets), 2)
|
|
|
|
def test_no_cache_and_no_network_says_so(self):
|
|
with fake_urlopen(url_error("no route to host")):
|
|
with self.assertRaises(hub.HubError) as caught:
|
|
hub.release("ggml-org/whisper.cpp")
|
|
self.assertIn("api.github.com", str(caught.exception))
|
|
|
|
def test_an_http_error_names_the_host_and_the_code(self):
|
|
with fake_urlopen(http_error(404, "nope")):
|
|
with self.assertRaises(hub.HubError) as caught:
|
|
hub.release("ggml-org/nothing")
|
|
self.assertIn("404", str(caught.exception))
|
|
|
|
|
|
class Files(DikteTest):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.patch_attr(hub, "CACHE_DIR", self.path("cache"))
|
|
|
|
def test_directories_are_left_out(self):
|
|
with fake_urlopen(TREE):
|
|
files = hub.files("ggerganov/whisper.cpp")
|
|
self.assertEqual([f.name for f in files],
|
|
[".gitattributes", "ggml-base.bin", "extra/ggml-tiny.bin"])
|
|
|
|
def test_the_url_is_the_one_that_serves_the_bytes(self):
|
|
with fake_urlopen(TREE):
|
|
files = hub.files("ggerganov/whisper.cpp")
|
|
self.assertEqual(
|
|
files[1].url,
|
|
"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.bin")
|
|
|
|
def test_the_lfs_object_id_is_the_checksum(self):
|
|
with fake_urlopen(TREE):
|
|
files = hub.files("ggerganov/whisper.cpp")
|
|
self.assertEqual(files[1].sha256, "c" * 64)
|
|
self.assertEqual(files[1].size, 147951465)
|
|
|
|
def test_a_file_outside_lfs_has_no_checksum(self):
|
|
with fake_urlopen(TREE):
|
|
files = hub.files("ggerganov/whisper.cpp")
|
|
self.assertEqual(files[0].sha256, "")
|
|
|
|
def test_an_answer_that_is_not_a_list_is_an_error(self):
|
|
with fake_urlopen({"error": "Invalid username or password."}):
|
|
with self.assertRaises(hub.HubError):
|
|
hub.files("ggml-org/whisper.cpp")
|
|
|
|
|
|
class Repos(DikteTest):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.patch_attr(hub, "CACHE_DIR", self.path("cache"))
|
|
|
|
def test_it_asks_for_one_author_and_for_gguf(self):
|
|
with fake_urlopen(MODELS) as calls:
|
|
found = hub.repos(author="ggml-org")
|
|
self.assertIn("author=ggml-org", calls[0].full_url)
|
|
self.assertIn("filter=gguf", calls[0].full_url)
|
|
self.assertEqual([r.id for r in found],
|
|
["ggml-org/gemma-3-4b-it-GGUF", "ggml-org/gpt-oss-20b-GGUF"])
|
|
|
|
def test_a_missing_download_count_is_zero(self):
|
|
with fake_urlopen(MODELS):
|
|
found = hub.repos(author="ggml-org")
|
|
self.assertEqual(found[0].downloads, 44606)
|
|
self.assertEqual(found[1].updated, "")
|
|
|
|
|
|
def os_utime(path):
|
|
"""Backdate a cache file past its time to live."""
|
|
import os
|
|
import time
|
|
old = time.time() - hub.CACHE_TTL - 60
|
|
os.utime(path, (old, old))
|
|
|
|
|
|
class CacheLocation(DikteTest):
|
|
"""Resolved at import, like every other path constant."""
|
|
|
|
def test_the_cache_lives_in_the_system_cache_directory(self):
|
|
# One answer for both, the same way ggml and config share DATA_DIR:
|
|
# hub asked paths once, at import, and kept what it was told.
|
|
self.assertEqual(hub.CACHE_DIR, paths.cache_dir())
|
|
|
|
|
|
class CacheOnDisk(DikteTest):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.patch_attr(hub, "CACHE_DIR", self.path("cache"))
|
|
|
|
def test_what_is_stored_is_what_came_back(self):
|
|
with fake_urlopen(RELEASE):
|
|
hub.release("ggml-org/whisper.cpp")
|
|
stored = [json.loads(p.read_text()) for p in self.path("cache").iterdir()]
|
|
self.assertEqual(stored[0]["tag_name"], "v1.9.1")
|
|
|
|
def test_a_cache_that_cannot_be_written_is_not_a_failure(self):
|
|
self.patch_attr(hub, "CACHE_DIR", self.path("nope", "deeper"))
|
|
self.path("nope").write_text("a file where a directory would go")
|
|
with fake_urlopen(RELEASE):
|
|
tag, _ = hub.release("ggml-org/whisper.cpp")
|
|
self.assertEqual(tag, "v1.9.1")
|