Coverage for src/lilbee/__init__.py: 100%
44 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-14 11:46 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-14 11:46 +0000
1"""lilbee: local knowledge base."""
3from __future__ import annotations
5import os
6import threading
8# Suppress HF-default tqdm bars (metadata probes, snapshot summaries) that
9# leak cursor escapes into the TUI. Our custom tqdm_class is NOT a subclass
10# of huggingface_hub.utils.tqdm, so huggingface_hub's `_create_progress_bar`
11# instantiates it directly without honoring this flag. Download callbacks
12# continue to fire. See lilbee/catalog/download_progress.py::_CallbackProgressBar.
13os.environ.setdefault("HF_HUB_DISABLE_PROGRESS_BARS", "1")
16def _install_thread_only_tqdm_lock() -> None:
17 """Pin ``tqdm.std.tqdm._lock`` to a threading RLock.
19 Bypasses tqdm's lazy multiprocessing-lock init, which tries to
20 fork_exec the MP resource tracker with ``sys.stderr.fileno() == -1``
21 under Textual and crashes with ``bad value(s) in fds_to_keep``.
22 Matches huggingface_hub PR #4065 but applied at the base class so
23 every tqdm instance in the process inherits the lock via MRO.
24 """
25 try:
26 from tqdm.std import tqdm as _tqdm_base
27 except ImportError:
28 return
29 if getattr(_tqdm_base, "_lock", None) is None:
30 _tqdm_base._lock = threading.RLock()
33def _prestart_mp_resource_tracker() -> None:
34 """Start the multiprocessing resource tracker before Textual swaps stderr.
36 The tracker launches lazily on the first semaphore creation, which in
37 the TUI is a worker's ``Value(lock=True)`` abort flag, spawned after
38 Textual has replaced ``sys.stderr`` with a stream whose ``fileno()``
39 returns -1. The tracker's launch passes that -1 into
40 ``_posixsubprocess.fork_exec`` and crashes with ``bad value(s) in
41 fds_to_keep``. Launching it here, at import time with a real stderr,
42 caches a valid tracker fd that every later ``Process.start()`` reuses.
44 Runs in frozen builds too (Nuitka onefile): the tracker re-executes
45 ``sys.executable`` with ``-c "from multiprocessing.resource_tracker
46 import main;main(N)"``, which ``__main__._dispatch_frozen_child``
47 intercepts and execs before typer sees it. No-op on Windows, which
48 does not use ``_posixsubprocess``.
49 """
50 import sys as _sys
52 if _sys.platform == "win32":
53 return
54 try:
55 from multiprocessing import resource_tracker
57 resource_tracker.ensure_running()
58 except (OSError, RuntimeError, ValueError, ImportError):
59 # Best-effort: if the tracker already crashed or cannot be started
60 # in the current env, leave the state alone. The worker's own
61 # spawn will surface a real error at call time.
62 pass
65_install_thread_only_tqdm_lock()
66_prestart_mp_resource_tracker()
69def _shrink_hf_download_chunk_size() -> None:
70 """Shrink huggingface_hub's 10MB download chunk to 200KB.
72 The HTTP path fires the progress callback once per chunk, so the default
73 leaves multi-second gaps. Patched rather than configured: there is no env
74 override.
75 """
76 try:
77 from huggingface_hub import constants as _hf_constants
79 _hf_constants.DOWNLOAD_CHUNK_SIZE = 200 * 1024
80 except ImportError:
81 pass # huggingface_hub may be absent in stripped-down environments
84_shrink_hf_download_chunk_size()
87# HF and LiteLLM log filters live next to their respective implementations
88# (catalog/hf_client.py and providers/litellm_sdk.py). They install themselves
89# on module import; this package's __init__.py stays free of HF/LiteLLM
90# implementation detail.
93# Must follow HF environment / constants setup above.
94from typing import TYPE_CHECKING # noqa: E402
96if TYPE_CHECKING:
97 from lilbee.api import Lilbee
99__all__ = ["Lilbee"]
102def __getattr__(name: str) -> object:
103 """Lazy-load ``Lilbee`` and fall back to normal submodule import."""
104 if name == "Lilbee":
105 from lilbee.api import Lilbee
107 return Lilbee
108 if name.startswith("__") and name.endswith("__"):
109 # Introspection probes (__wrapped__, __all__ fallbacks, copy/pickle
110 # dunders) are frequent and never name a submodule; skip the import.
111 raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
112 # PEP 562: `lilbee.<submodule>` must behave like a plain package attribute
113 # even when the submodule has not been imported yet (dotted-path resolvers
114 # such as monkeypatch.setattr and mock.patch rely on getattr succeeding).
115 import importlib
117 try:
118 return importlib.import_module(f".{name}", __name__)
119 except ModuleNotFoundError as exc:
120 if exc.name == f"{__name__}.{name}":
121 raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
122 raise