speedy-utils 2.0.2__tar.gz → 2.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.githooks/pre-commit +28 -54
- speedy_utils-2.0.5/.github/skills/make-vscode-happy/SKILL.md +80 -0
- speedy_utils-2.0.5/.github/skills/make-vscode-happy/references/diagnostic-playbook.md +94 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.gitignore +2 -1
- speedy_utils-2.0.5/CLAUDE.md +201 -0
- speedy_utils-2.0.5/CODING_STYLE.md +521 -0
- speedy_utils-2.0.5/PKG-INFO +660 -0
- speedy_utils-2.0.5/README.md +607 -0
- speedy_utils-2.0.5/debug/test_qwen3_generate.md +50 -0
- speedy_utils-2.0.5/docs/GENERATE_QUICKREF.md +138 -0
- speedy_utils-2.0.5/docs/MIGRATION_THINKING.md +109 -0
- speedy_utils-2.0.5/docs/PR_LIBRARY_ERROR_HANDLING_REFACTOR_PLAN.md +165 -0
- speedy_utils-2.0.5/docs/TOKENIZATION.md +105 -0
- speedy_utils-2.0.5/docs/TOKENIZATION_IMPLEMENTATION.md +76 -0
- speedy_utils-2.0.5/examples/llm_public_api_example.ipynb +164 -0
- speedy_utils-2.0.5/notebooks/demo_multi_process.py +128 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/notebooks/llm_utils/llm_as_a_judge.ipynb +4 -16
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/pyproject.toml +8 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/pyrightconfig.json +3 -3
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/ruff.toml +16 -0
- speedy_utils-2.0.5/scripts/debug_import_time.py +417 -0
- speedy_utils-2.0.5/scripts/debug_multi_process.py +20 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/datasets_utils/viz_chat.py +3 -2
- speedy_utils-2.0.5/src/llm_utils/__init__.py +34 -0
- speedy_utils-2.0.5/src/llm_utils/_traceback.py +235 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/chat_format/display.py +4 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/lm/__init__.py +0 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/lm/llm.py +28 -14
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/lm/llm_qwen3.py +309 -194
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/lm/llm_signature.py +55 -4
- speedy_utils-2.0.5/src/llm_utils/lm/openai_memoize.py +430 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/lm/utils.py +2 -3
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/scripts/sp_chat.py +1 -0
- speedy_utils-2.0.5/src/llm_utils/utils.py +42 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/__imports.py +1 -6
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/__init__.py +17 -38
- speedy_utils-2.0.5/src/speedy_utils/common/exceptions.py +69 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/utils_cache.py +10 -8
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/utils_error.py +8 -14
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/utils_io.py +28 -3
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/utils_misc.py +2 -0
- speedy_utils-2.0.5/src/speedy_utils/multi_worker/_mp_backends.py +814 -0
- speedy_utils-2.0.5/src/speedy_utils/multi_worker/_mp_progress.py +128 -0
- speedy_utils-2.0.5/src/speedy_utils/multi_worker/_mp_spawn.py +335 -0
- speedy_utils-2.0.5/src/speedy_utils/multi_worker/_multi_process.py +321 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/multi_worker/common.py +190 -180
- speedy_utils-2.0.5/src/speedy_utils/multi_worker/dataset_sharding.py +226 -0
- speedy_utils-2.0.5/src/speedy_utils/multi_worker/process.py +23 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/multi_worker/thread.py +302 -179
- speedy_utils-2.0.5/src/vision_utils/README.md +122 -0
- speedy_utils-2.0.5/src/vision_utils/__init__.py +19 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/llm_utils/test_llm_call_contract.py +33 -1
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/llm_utils/test_llm_mixins.py +291 -34
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/llm_utils/test_llm_signature.py +1 -1
- speedy_utils-2.0.5/tests/llm_utils/test_public_api.py +117 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test.py +6 -3
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_memoize_typing.py +4 -0
- speedy_utils-2.0.5/tests/test_mp_no_main_guard.py +154 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_multi_process.py +66 -63
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_multi_thread.py +4 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_process.py +133 -40
- speedy_utils-2.0.5/tests/test_process_update.py +343 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_thread.py +14 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_tokenization.py +8 -5
- speedy_utils-2.0.5/tests/test_utils_io.py +18 -0
- speedy_utils-2.0.5/tools/check_syntax.py +185 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tools/uv_test.sh +1 -1
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/uv.lock +35 -4
- speedy_utils-2.0.2/CLAUDE.md +0 -180
- speedy_utils-2.0.2/PKG-INFO +0 -710
- speedy_utils-2.0.2/README.md +0 -658
- speedy_utils-2.0.2/chainlit.md +0 -14
- speedy_utils-2.0.2/debug/test_qwen3_generate.md +0 -87
- speedy_utils-2.0.2/docs/GENERATE_QUICKREF.md +0 -133
- speedy_utils-2.0.2/docs/MIGRATION_THINKING.md +0 -73
- speedy_utils-2.0.2/docs/TOKENIZATION.md +0 -325
- speedy_utils-2.0.2/docs/TOKENIZATION_IMPLEMENTATION.md +0 -104
- speedy_utils-2.0.2/examples/llm_public_api_example.ipynb +0 -273
- speedy_utils-2.0.2/experiments/exp1/test.png +0 -0
- speedy_utils-2.0.2/notebooks/test_multi_thread.ipynb +0 -82
- speedy_utils-2.0.2/scripts/debug_import_time.py +0 -210
- speedy_utils-2.0.2/src/llm_utils/__init__.py +0 -75
- speedy_utils-2.0.2/src/llm_utils/group_messages.py +0 -123
- speedy_utils-2.0.2/src/llm_utils/lm/openai_memoize.py +0 -172
- speedy_utils-2.0.2/src/speedy_utils/multi_worker/_multi_process.py +0 -819
- speedy_utils-2.0.2/src/speedy_utils/multi_worker/dataset_sharding.py +0 -192
- speedy_utils-2.0.2/src/speedy_utils/multi_worker/process.py +0 -71
- speedy_utils-2.0.2/src/vision_utils/README.md +0 -202
- speedy_utils-2.0.2/src/vision_utils/__init__.py +0 -39
- speedy_utils-2.0.2/tests/test_process_update.py +0 -129
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.codex +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.githooks/pre-push +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/prompts/improveParallelErrorHandling.prompt.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/caching-utilities/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/caching-utilities/examples/caching_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/dataset-processing-multiprocessing/CONFIG_REFERENCE.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/dataset-processing-multiprocessing/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/dataset-processing-multiprocessing/example_tokenize_pack.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/edit-llm-inference-style/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/io-utilities/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/io-utilities/examples/io_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/llm-integration/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/llm-integration/examples/llm_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/multi-threading-processing/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/ray-distributed-computing/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/skill-creation/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/vision-utilities/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/skills/vision-utilities/examples/vision_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.github/workflows/publish.yml +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/.pre-commit-config.yaml +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/AGENTS.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/bumpversion.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/debug_generate_response.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/debug_n_param.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/debug_n_structure.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/integration_test.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/multi_thread.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/test_decode_api.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/test_endpoints.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/test_generate.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/test_generate_endpoint.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/debug/test_qwen3_generate.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/examples/generate_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/examples/model_specific_thinking_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/examples/tokenization_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/examples/vision_utils_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/experiments/exp1/dockerfile +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/experiments/exp1/run_in_docker.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/notebooks/test.ipynb +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/bug_simple.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/deploy.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/imports.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/install_hooks.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/test.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/test_error_handling.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/test_import_time_vision.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/test_locals.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/scripts/test_ray_mp.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/setup.cfg +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/datasets_utils/convert_to_arrow.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/chat_format/__init__.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/chat_format/transform.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/chat_format/utils.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/lm/base_prompt_builder.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/lm/lm_base.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/llm_utils/lm/signature.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/__init__.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/clock.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/function_decorator.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/logger.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/notebook_utils.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/patcher.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/report_manager.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/common/utils_print.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/multi_worker/__init__.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/scripts/__init__.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/scripts/kill_mpython.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/scripts/mpython.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/scripts/openapi_client_codegen.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/speedy_utils/scripts/prefetch_large_model.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/vision_utils/io_utils.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/src/vision_utils/plot.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/import_all.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/import_time_report.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/llm_utils/test_openai_memoize_completion_cache.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/llm_utils/test_openai_proxy_localhost.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/llm_utils/test_sp_chat.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/sample_objects.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_import_time.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_logger.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_logger_format.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_mpython.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_multithread_error_trace.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_prefetch_large_model.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.5}/tests/test_viz_chat.py +0 -0
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Pre-commit hook to ensure import time is under 0.4 seconds.
|
|
4
|
-
|
|
5
|
-
This enforces the project's performance requirement that speedy_utils
|
|
6
|
-
must import quickly (< 0.4s). This is critical for user experience.
|
|
7
|
-
|
|
8
|
-
Strategy: Use lazy imports for heavy modules (torch, ray, matplotlib, pandas)
|
|
9
|
-
inside functions that need them, not at module level.
|
|
10
|
-
"""
|
|
2
|
+
"""Pre-commit hook to enforce import-time budgets with actionable output."""
|
|
11
3
|
|
|
12
4
|
import os
|
|
13
5
|
import subprocess
|
|
@@ -73,57 +65,39 @@ def _build_env() -> dict[str, str]:
|
|
|
73
65
|
return env
|
|
74
66
|
|
|
75
67
|
|
|
76
|
-
def
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
def _helper_script() -> Path:
|
|
69
|
+
return _REPO_ROOT / "scripts" / "debug_import_time.py"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main() -> int:
|
|
73
|
+
"""Run import-time checks through the shared helper script."""
|
|
74
|
+
print("Checking import times... (max: {:.1f}s)".format(MAX_IMPORT_TIME))
|
|
75
|
+
|
|
76
|
+
helper = _helper_script()
|
|
79
77
|
result = subprocess.run(
|
|
80
|
-
[
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
[
|
|
79
|
+
_PYTHON,
|
|
80
|
+
str(helper),
|
|
81
|
+
"--max-total-sec",
|
|
82
|
+
str(MAX_IMPORT_TIME),
|
|
83
|
+
"--min-sec",
|
|
84
|
+
"0.01",
|
|
85
|
+
"--top",
|
|
86
|
+
"12",
|
|
87
|
+
"--no-stdlib",
|
|
88
|
+
"--quiet-success",
|
|
89
|
+
*MODULES,
|
|
90
|
+
],
|
|
83
91
|
env=_build_env(),
|
|
84
92
|
cwd=str(_REPO_ROOT),
|
|
85
93
|
)
|
|
86
|
-
if result.returncode != 0:
|
|
87
|
-
err = (result.stderr or result.stdout or "").strip()
|
|
88
|
-
return False, -1, err
|
|
89
|
-
try:
|
|
90
|
-
import_time = float(result.stdout.strip())
|
|
91
|
-
return import_time <= MAX_IMPORT_TIME, import_time, ""
|
|
92
|
-
except ValueError:
|
|
93
|
-
err = (result.stderr or result.stdout or "").strip()
|
|
94
|
-
return False, -1, err
|
|
95
94
|
|
|
95
|
+
if result.returncode != 0:
|
|
96
|
+
print("\nImport time check failed.")
|
|
97
|
+
print("Rerun the helper above after moving heavy imports into function scope")
|
|
98
|
+
print("or a lazy __getattr__ export to pinpoint the slow path.")
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
"""Run import time checks."""
|
|
99
|
-
failed = False
|
|
100
|
-
|
|
101
|
-
print("Checking import times... (max: {:.1f}s)".format(MAX_IMPORT_TIME))
|
|
102
|
-
|
|
103
|
-
for module in MODULES:
|
|
104
|
-
passed, import_time, err = check_import_time(module)
|
|
105
|
-
|
|
106
|
-
if import_time < 0:
|
|
107
|
-
print(f" {module}: FAILED - import error")
|
|
108
|
-
if err:
|
|
109
|
-
last_line = err.splitlines()[-1]
|
|
110
|
-
print(f" ↳ {last_line}")
|
|
111
|
-
failed = True
|
|
112
|
-
elif passed:
|
|
113
|
-
print(f" {module}: {import_time:.3f}s")
|
|
114
|
-
else:
|
|
115
|
-
print(f" {module}: FAILED - {import_time:.3f}s exceeds {MAX_IMPORT_TIME:.1f}s")
|
|
116
|
-
failed = True
|
|
117
|
-
|
|
118
|
-
if failed:
|
|
119
|
-
print("\nImport time check failed! To fix:")
|
|
120
|
-
print(" 1. Use lazy imports for heavy modules inside functions")
|
|
121
|
-
print(" 2. Move heavy imports to function scope, not module level")
|
|
122
|
-
print(" 3. Use the _LazyModule pattern from __imports.py")
|
|
123
|
-
print("\nHeavy modules to lazy-load: torch, ray, matplotlib, pandas")
|
|
124
|
-
return 1
|
|
125
|
-
|
|
126
|
-
return 0
|
|
100
|
+
return result.returncode
|
|
127
101
|
|
|
128
102
|
|
|
129
103
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 'make-vscode-happy'
|
|
3
|
+
description: 'Reduce VS Code Python red squiggles to zero in this repository. Use when Pylance or pyright reports errors, when tools/check_syntax.py fails, or when a change should leave VS Code diagnostics clean.'
|
|
4
|
+
argument-hint: 'Optional file path, module name, or failing area to fix'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Make VS Code Happy
|
|
8
|
+
|
|
9
|
+
Use this skill when the goal is to make VS Code and Pylance happy in this
|
|
10
|
+
repository by driving Python diagnostics to zero with the repo's existing
|
|
11
|
+
checker: `tools/check_syntax.py`.
|
|
12
|
+
|
|
13
|
+
## When to Use
|
|
14
|
+
|
|
15
|
+
Use this skill when you need to:
|
|
16
|
+
- Fix Python red squiggles in VS Code.
|
|
17
|
+
- Reconcile Pylance diagnostics with command-line validation.
|
|
18
|
+
- Clean up pyright issues before committing.
|
|
19
|
+
- Verify that a targeted change did not leave new diagnostics behind.
|
|
20
|
+
|
|
21
|
+
## Primary Checker
|
|
22
|
+
|
|
23
|
+
The authoritative checker for this repo is:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uv run python tools/check_syntax.py
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Useful variants:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv run python tools/check_syntax.py --file src/llm_utils/lm/llm_qwen3.py
|
|
33
|
+
uv run python tools/check_syntax.py --include tests
|
|
34
|
+
uv run python tools/check_syntax.py --json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This script mirrors the diagnostics VS Code Pylance shows for the repository's
|
|
38
|
+
`pyrightconfig.json`.
|
|
39
|
+
|
|
40
|
+
## Procedure
|
|
41
|
+
|
|
42
|
+
1. Pick scope first.
|
|
43
|
+
- If the request names a file, start with `--file` for that file.
|
|
44
|
+
- If the issue sounds cross-cutting or unclear, run the full check first.
|
|
45
|
+
2. Read diagnostics and group them by root cause instead of fixing them one by
|
|
46
|
+
one in isolation.
|
|
47
|
+
3. Fix the real source of the type error.
|
|
48
|
+
- Prefer correcting annotations, overloads, return types, and control flow.
|
|
49
|
+
- Use repo-approved ignores only when the code is intentionally dynamic.
|
|
50
|
+
4. Re-run the smallest relevant check after each edit.
|
|
51
|
+
5. Before concluding, run the broader validation needed for the scope.
|
|
52
|
+
- If you touched one file, re-run that file and then a full check if the
|
|
53
|
+
change affects shared APIs.
|
|
54
|
+
- If you changed common utilities, package exports, or typing helpers, run
|
|
55
|
+
the full check.
|
|
56
|
+
6. If the fix changes imports in public packages, protect the import-time
|
|
57
|
+
budget as well.
|
|
58
|
+
|
|
59
|
+
## Decision Points
|
|
60
|
+
|
|
61
|
+
- Single-file symptom vs shared typing pattern:
|
|
62
|
+
Start narrow for local regressions; go broad if the same diagnostic appears in
|
|
63
|
+
multiple files or stems from a shared helper.
|
|
64
|
+
- True bug vs accepted dynamic pattern:
|
|
65
|
+
Prefer a real type fix first. Only use a targeted ignore when the repository
|
|
66
|
+
already treats that pattern as intentionally dynamic.
|
|
67
|
+
- Typing fix vs performance regression:
|
|
68
|
+
Do not fix types by introducing heavy top-level imports in `__init__.py` or
|
|
69
|
+
other import-sensitive modules.
|
|
70
|
+
|
|
71
|
+
## Completion Criteria
|
|
72
|
+
|
|
73
|
+
- `tools/check_syntax.py` reports zero relevant errors for the changed scope.
|
|
74
|
+
- Touched files do not introduce new warnings unless the user accepted them.
|
|
75
|
+
- The fix matches repository typing conventions.
|
|
76
|
+
- No eager heavy imports were added just to satisfy typing.
|
|
77
|
+
|
|
78
|
+
## References
|
|
79
|
+
|
|
80
|
+
- [Diagnostic playbook](./references/diagnostic-playbook.md)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Diagnostic Playbook
|
|
2
|
+
|
|
3
|
+
This reference supports the `make-vscode-happy` skill for the `speedy_utils`
|
|
4
|
+
repository.
|
|
5
|
+
|
|
6
|
+
## Repo Rules That Matter
|
|
7
|
+
|
|
8
|
+
- Use `uv run python tools/check_syntax.py` as the source of truth for Python
|
|
9
|
+
diagnostics.
|
|
10
|
+
- Fix root causes instead of masking errors with broad ignores.
|
|
11
|
+
- Keep public package import time under `0.4s`.
|
|
12
|
+
- Do not introduce heavy top-level imports such as `torch`, `pandas`,
|
|
13
|
+
`matplotlib`, or `IPython` in `__init__.py` files.
|
|
14
|
+
|
|
15
|
+
## Fast Triage
|
|
16
|
+
|
|
17
|
+
### If the prompt names a specific file
|
|
18
|
+
|
|
19
|
+
Run:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv run python tools/check_syntax.py --file path/to/file.py
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Then fix the reported issue and re-run the same command.
|
|
26
|
+
|
|
27
|
+
### If the prompt is vague or broad
|
|
28
|
+
|
|
29
|
+
Run:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv run python tools/check_syntax.py
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If the change touches tests or test helpers, consider:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uv run python tools/check_syntax.py --include tests
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Common Fix Patterns In This Repo
|
|
42
|
+
|
|
43
|
+
### Overload ordering
|
|
44
|
+
|
|
45
|
+
Put the `Awaitable[...]` overload before the generic non-awaitable overload to
|
|
46
|
+
avoid overlapping-overload diagnostics.
|
|
47
|
+
|
|
48
|
+
### Dynamic Pydantic-style attributes
|
|
49
|
+
|
|
50
|
+
When the code intentionally sets attributes not declared in the model schema,
|
|
51
|
+
use a narrow ignore such as:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
# type: ignore[attr-defined]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Do not apply it broadly if a better annotation is possible.
|
|
58
|
+
|
|
59
|
+
### `tqdm` annotations
|
|
60
|
+
|
|
61
|
+
Use the string literal form in annotations:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
"tqdm"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Lazy exports
|
|
68
|
+
|
|
69
|
+
For names loaded through `__getattr__`, follow the existing lazy-export pattern
|
|
70
|
+
instead of forcing eager imports for type convenience.
|
|
71
|
+
|
|
72
|
+
### `__all__` with heavy lazy names
|
|
73
|
+
|
|
74
|
+
Do not add heavy lazy names to `__all__`, because star imports will defeat lazy
|
|
75
|
+
loading and hurt import time.
|
|
76
|
+
|
|
77
|
+
## When a Typing Fix Touches Imports
|
|
78
|
+
|
|
79
|
+
If you changed imports in a public package, especially `speedy_utils`,
|
|
80
|
+
`llm_utils`, or `vision_utils`, run:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
uv run python scripts/debug_import_time.py speedy_utils llm_utils vision_utils --max-total-sec 0.4 --top 12 --min-sec 0.01 --no-stdlib
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Use that output to move heavy imports behind lazy boundaries if needed.
|
|
87
|
+
|
|
88
|
+
## Definition of Done
|
|
89
|
+
|
|
90
|
+
- Targeted diagnostics are gone.
|
|
91
|
+
- Shared changes were validated with a broader repo check.
|
|
92
|
+
- The fix preserves existing lazy-import and typing conventions.
|
|
93
|
+
- VS Code should agree with command-line output because the checker mirrors
|
|
94
|
+
Pylance behavior for this repository.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance for working in this repository.
|
|
4
|
+
|
|
5
|
+
## Development Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install dependencies
|
|
9
|
+
uv sync
|
|
10
|
+
|
|
11
|
+
# Run tests
|
|
12
|
+
./tools/uv_test.sh -n 32
|
|
13
|
+
|
|
14
|
+
# Run a single test file
|
|
15
|
+
./tools/uv_test.sh tests/test_thread.py
|
|
16
|
+
|
|
17
|
+
# Run with verbose output
|
|
18
|
+
./tools/uv_test.sh -v
|
|
19
|
+
|
|
20
|
+
# Check import time for the exported packages
|
|
21
|
+
uv run python scripts/debug_import_time.py speedy_utils llm_utils vision_utils \
|
|
22
|
+
--max-total-sec 0.4 --top 12 --min-sec 0.01 --no-stdlib
|
|
23
|
+
|
|
24
|
+
# Lint and format
|
|
25
|
+
uv run ruff check .
|
|
26
|
+
uv run ruff format .
|
|
27
|
+
|
|
28
|
+
# Pyright / Pylance parity check
|
|
29
|
+
uv run python tools/check_syntax.py
|
|
30
|
+
|
|
31
|
+
# Bump version (runs tests, then commits and pushes)
|
|
32
|
+
./bumpversion.sh patch # or minor / major
|
|
33
|
+
|
|
34
|
+
# Deploy to PyPI (requires PYPI_API_TOKEN)
|
|
35
|
+
./scripts/deploy.sh
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Performance Requirement: Import Time < 0.4s
|
|
39
|
+
|
|
40
|
+
The repository hook budget is `0.4s` for the exported packages checked by
|
|
41
|
+
`.githooks/pre-commit`:
|
|
42
|
+
|
|
43
|
+
- `speedy_utils`
|
|
44
|
+
- `llm_utils`
|
|
45
|
+
- `vision_utils`
|
|
46
|
+
|
|
47
|
+
Use the shared helper when import time regresses:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv run python scripts/debug_import_time.py speedy_utils llm_utils vision_utils \
|
|
51
|
+
--max-total-sec 0.4 --top 12 --min-sec 0.01 --no-stdlib
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Current code structure keeps the budget by avoiding heavy external imports at
|
|
55
|
+
module import time.
|
|
56
|
+
|
|
57
|
+
### What to keep lazy
|
|
58
|
+
|
|
59
|
+
These imports are intentionally kept behind helpers or function scope because
|
|
60
|
+
they are expensive enough to matter for import time:
|
|
61
|
+
|
|
62
|
+
- `torch`
|
|
63
|
+
- `pandas`
|
|
64
|
+
- `matplotlib`
|
|
65
|
+
- `IPython`
|
|
66
|
+
- tokenizer-loading code in `Qwen3LLM`
|
|
67
|
+
|
|
68
|
+
### How the current code does it
|
|
69
|
+
|
|
70
|
+
- `speedy_utils.__init__` imports lightweight internal modules directly.
|
|
71
|
+
- heavy external helpers live in `speedy_utils.__imports`.
|
|
72
|
+
- `llm_utils.__init__` exports selected public classes and helpers directly.
|
|
73
|
+
- `vision_utils` keeps plotting and image backends lazy inside function bodies.
|
|
74
|
+
|
|
75
|
+
Do not add new top-level imports for heavy third-party libraries in public
|
|
76
|
+
package `__init__.py` files unless you have rechecked import-time impact.
|
|
77
|
+
|
|
78
|
+
### Hook vs test budget
|
|
79
|
+
|
|
80
|
+
The pre-commit hook is stricter than the regression test:
|
|
81
|
+
|
|
82
|
+
- `.githooks/pre-commit` enforces `0.4s`
|
|
83
|
+
- `tests/test_import_time.py` currently guards `speedy_utils` at `1.0s`
|
|
84
|
+
|
|
85
|
+
Treat the hook budget as the real policy.
|
|
86
|
+
|
|
87
|
+
## Architecture
|
|
88
|
+
|
|
89
|
+
### Package Structure
|
|
90
|
+
|
|
91
|
+
The wheel currently ships four packages from `src/`:
|
|
92
|
+
|
|
93
|
+
- `speedy_utils`: caching, file I/O, formatting, timing, and parallel helpers
|
|
94
|
+
- `llm_utils`: OpenAI-compatible LLM wrappers, memoized clients, chat-format helpers
|
|
95
|
+
- `vision_utils`: image loading, notebook plotting, and mmap-backed image datasets
|
|
96
|
+
- `datasets_utils`: dataset inspection helpers such as `viz_chat`
|
|
97
|
+
|
|
98
|
+
### Important Modules
|
|
99
|
+
|
|
100
|
+
- `src/speedy_utils/common/utils_cache.py`
|
|
101
|
+
- `memoize`, `imemoize`, `identify`
|
|
102
|
+
- default disk cache root: `~/.cache/speedy_cache`
|
|
103
|
+
- `src/speedy_utils/common/utils_io.py`
|
|
104
|
+
- `load_jsonl`, `fast_load_jsonl`, `load_json_or_pickle`, `load_by_ext`
|
|
105
|
+
- `src/speedy_utils/multi_worker/thread.py`
|
|
106
|
+
- `multi_thread`
|
|
107
|
+
- `src/speedy_utils/multi_worker/_multi_process.py`
|
|
108
|
+
- `multi_process`
|
|
109
|
+
- `src/llm_utils/lm/llm.py`
|
|
110
|
+
- `LLM.chat_completion`, `LLM.generate`, `LLM.pydantic_parse`, `LLM.inspect_history`
|
|
111
|
+
- `src/llm_utils/lm/llm_signature.py`
|
|
112
|
+
- `LLMSignature`
|
|
113
|
+
- `src/llm_utils/lm/llm_qwen3.py`
|
|
114
|
+
- `Qwen3LLM`, `complete_until`, `complete_reasoning`, `complete_content`
|
|
115
|
+
- `src/vision_utils/io_utils.py`
|
|
116
|
+
- `read_images`, `read_images_cpu`, `read_images_gpu`, `ImageMmap`, `ImageMmapDynamic`
|
|
117
|
+
- `src/vision_utils/plot.py`
|
|
118
|
+
- `plot_images_notebook`
|
|
119
|
+
- `src/datasets_utils/viz_chat.py`
|
|
120
|
+
- dataset and conversation inspection CLI
|
|
121
|
+
|
|
122
|
+
## Public API Notes
|
|
123
|
+
|
|
124
|
+
### `speedy_utils`
|
|
125
|
+
|
|
126
|
+
- `memoize` supports sync and async functions.
|
|
127
|
+
- `load_json_or_pickle` is for `.json` and pickle-like files.
|
|
128
|
+
- use `load_jsonl` or `fast_load_jsonl` for JSONL.
|
|
129
|
+
- `multi_process(num_procs=None)` currently normalizes to `1`; it does not auto-pick a process count.
|
|
130
|
+
|
|
131
|
+
### `llm_utils`
|
|
132
|
+
|
|
133
|
+
- `LLM()` defaults to the chat path.
|
|
134
|
+
- `LLM.generate()` uses the completions API and returns a `CompletionChoice`-like object.
|
|
135
|
+
- `LLM.generate()` expects a string prompt and only supports `n=1`.
|
|
136
|
+
- `LLM.pydantic_parse()` is the structured-output API.
|
|
137
|
+
- `LLM(..., return_dict=True)` returns a normalized dict with `completion`, `message`, `messages`, and `parsed`.
|
|
138
|
+
- `LLMSignature` defaults structured outputs to the signature's output model.
|
|
139
|
+
- `Qwen3LLM.chat_completion()` returns an OpenAI-style `ChatCompletionMessage` with optional dynamic attrs such as `reasoning_content`, `usage`, and `call_count`.
|
|
140
|
+
- `Qwen3LLM.complete_until()` returns a continuation-state object, not a `ChatCompletionMessage`.
|
|
141
|
+
|
|
142
|
+
### `vision_utils`
|
|
143
|
+
|
|
144
|
+
- `read_images*()` returns `dict[path, ndarray | None]`.
|
|
145
|
+
- `plot_images_notebook()` expects arrays/tensors or lists/tuples of arrays.
|
|
146
|
+
- if you loaded images with `read_images*()`, pass `list(images.values())` to the plotter.
|
|
147
|
+
- `ImageMmap` and `ImageMmapDynamic` take image-path sequences and build cache files as needed.
|
|
148
|
+
|
|
149
|
+
## CLI Tools
|
|
150
|
+
|
|
151
|
+
Registered console scripts in `pyproject.toml`:
|
|
152
|
+
|
|
153
|
+
- `mpython`
|
|
154
|
+
- `kill-mpython`
|
|
155
|
+
- `sp_chat`
|
|
156
|
+
- `spu-prefetch-large-model`
|
|
157
|
+
- `viz_chat`
|
|
158
|
+
- `openapi_client_codegen`
|
|
159
|
+
|
|
160
|
+
## Code Style
|
|
161
|
+
|
|
162
|
+
- Line length: `88`
|
|
163
|
+
- Quote style: double quotes
|
|
164
|
+
- Ruff is the formatter and linter
|
|
165
|
+
- Avoid unnecessary wrappers and ceremony; see `CODING_STYLE.md`
|
|
166
|
+
- Keep public docs/examples aligned with tests and current implementation, not with historical helper scripts
|
|
167
|
+
|
|
168
|
+
## Type Checking with Pyright
|
|
169
|
+
|
|
170
|
+
Use:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
uv run python tools/check_syntax.py
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
This mirrors what VS Code Pylance reports for the configured project files.
|
|
177
|
+
|
|
178
|
+
### pyright config (`pyrightconfig.json`)
|
|
179
|
+
|
|
180
|
+
Current notable suppressions:
|
|
181
|
+
|
|
182
|
+
| Rule | Why suppressed |
|
|
183
|
+
|------|----------------|
|
|
184
|
+
| `reportMissingImports` | Optional GPU and backend dependencies are not always installed |
|
|
185
|
+
| `reportAttributeAccessIssue` | OpenAI response models and runtime message objects gain dynamic attrs such as `usage`, `reasoning_content`, and `call_count` |
|
|
186
|
+
| `reportUnsupportedDunderAll` | Some modules rely on broad export patterns that are noisy for pyright |
|
|
187
|
+
|
|
188
|
+
### Common annotation patterns in this repo
|
|
189
|
+
|
|
190
|
+
- use string literal `"tqdm"` when needed in type hints
|
|
191
|
+
- put `Awaitable[R]` overloads before generic `R` overloads
|
|
192
|
+
- use `# type: ignore[attr-defined]` for dynamic OpenAI message attrs where necessary
|
|
193
|
+
- keep dataset `__getitem__` overrides narrow and explicit
|
|
194
|
+
|
|
195
|
+
## Version Management
|
|
196
|
+
|
|
197
|
+
Version lives in `pyproject.toml`. `./bumpversion.sh` currently:
|
|
198
|
+
|
|
199
|
+
1. runs tests
|
|
200
|
+
2. bumps the package version
|
|
201
|
+
3. commits and pushes
|