Coverage for src/lilbee/__init__.py: 100%
39 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-11-06 08:17 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-11-06 08:17 +0000
1"""lilbee: local knowledge base."""
3from __future__ import annotations
5import os
6import sys
7import threading
9# Suppress HF-default tqdm bars (metadata probes, snapshot summaries) that
10# leak cursor escapes into the TUI. Our custom tqdm_class is NOT a subclass
11# of huggingface_hub.utils.tqdm, so huggingface_hub's `_create_progress_bar`
12# instantiates it directly without honoring this flag. Download callbacks
13# continue to fire. See lilbee/catalog/download_progress.py::_CallbackProgressBar.
14os.environ.setdefault("HF_HUB_DISABLE_PROGRESS_BARS", "1")
17def _disable_xet_where_it_stalls() -> None:
18 """Fall back to the plain HTTP download path on Windows.
20 hf_xet transfers stall or deadlock on Windows (xet-core issues #446, #789,
21 #850), while the plain path downloads at line speed. Everywhere else xet
22 stays on: it is the fast path. huggingface_hub parses the variable once at
23 its import, so it is set here at import, before anything imports the hub,
24 and a variable the user exported wins.
25 """
26 if sys.platform == "win32":
27 os.environ.setdefault("HF_HUB_DISABLE_XET", "1")
30_disable_xet_where_it_stalls()
33def _install_thread_only_tqdm_lock() -> None:
34 """Pin ``tqdm.std.tqdm._lock`` to a threading RLock.
36 Bypasses tqdm's lazy multiprocessing-lock init, which tries to
37 fork_exec the MP resource tracker with ``sys.stderr.fileno() == -1``
38 under Textual and crashes with ``bad value(s) in fds_to_keep``.
39 Matches huggingface_hub PR #4065 but applied at the base class so
40 every tqdm instance in the process inherits the lock via MRO.
41 """
42 try:
43 from tqdm.std import tqdm as _tqdm_base
44 except ImportError:
45 return
46 if getattr(_tqdm_base, "_lock", None) is None:
47 _tqdm_base._lock = threading.RLock()
50_install_thread_only_tqdm_lock()
53def _shrink_hf_download_chunk_size() -> None:
54 """Shrink huggingface_hub's 10MB download chunk to 200KB.
56 The HTTP path fires the progress callback once per chunk, so the default
57 leaves multi-second gaps. Patched rather than configured: there is no env
58 override.
59 """
60 try:
61 from huggingface_hub import constants as _hf_constants
63 _hf_constants.DOWNLOAD_CHUNK_SIZE = 200 * 1024
64 except ImportError:
65 pass # huggingface_hub may be absent in stripped-down environments
68_shrink_hf_download_chunk_size()
71# The HF log filter lives next to its implementation (catalog/hf_client.py).
72# It installs itself on module import; this package's __init__.py stays free of
73# HF implementation detail.
76# Must follow HF environment / constants setup above.
77from typing import TYPE_CHECKING # noqa: E402
79if TYPE_CHECKING:
80 from lilbee.api import Lilbee
82__all__ = ["Lilbee"]
85def __getattr__(name: str) -> object:
86 """Lazy-load ``Lilbee`` and fall back to normal submodule import."""
87 if name == "Lilbee":
88 from lilbee.api import Lilbee
90 return Lilbee
91 if name.startswith("__") and name.endswith("__"):
92 # Introspection probes (__wrapped__, __all__ fallbacks, copy/pickle
93 # dunders) are frequent and never name a submodule; skip the import.
94 raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
95 # PEP 562: `lilbee.<submodule>` must behave like a plain package attribute
96 # even when the submodule has not been imported yet (dotted-path resolvers
97 # such as monkeypatch.setattr and mock.patch rely on getattr succeeding).
98 import importlib
100 try:
101 return importlib.import_module(f".{name}", __name__)
102 except ModuleNotFoundError as exc:
103 if exc.name == f"{__name__}.{name}":
104 raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
105 raise