speedy-utils 2.0.2__tar.gz → 2.0.4__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.4}/.githooks/pre-commit +28 -54
- speedy_utils-2.0.4/.github/skills/make-vscode-happy/SKILL.md +80 -0
- speedy_utils-2.0.4/.github/skills/make-vscode-happy/references/diagnostic-playbook.md +94 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.gitignore +2 -1
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/CLAUDE.md +62 -5
- speedy_utils-2.0.4/CODING_STYLE.md +521 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/PKG-INFO +12 -10
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/README.md +9 -8
- speedy_utils-2.0.4/docs/PR_LIBRARY_ERROR_HANDLING_REFACTOR_PLAN.md +165 -0
- speedy_utils-2.0.4/notebooks/demo_multi_process.py +128 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/notebooks/llm_utils/llm_as_a_judge.ipynb +4 -16
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/pyproject.toml +7 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/pyrightconfig.json +3 -3
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/ruff.toml +16 -0
- speedy_utils-2.0.4/scripts/debug_import_time.py +417 -0
- speedy_utils-2.0.4/scripts/debug_multi_process.py +20 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/datasets_utils/viz_chat.py +3 -2
- speedy_utils-2.0.4/src/llm_utils/__init__.py +34 -0
- speedy_utils-2.0.4/src/llm_utils/_traceback.py +235 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/chat_format/display.py +4 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/lm/__init__.py +0 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/lm/llm.py +26 -13
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/lm/llm_qwen3.py +93 -22
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/lm/llm_signature.py +55 -4
- speedy_utils-2.0.4/src/llm_utils/lm/openai_memoize.py +430 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/lm/utils.py +2 -3
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/scripts/sp_chat.py +1 -0
- speedy_utils-2.0.4/src/llm_utils/utils.py +42 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/__imports.py +1 -6
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/__init__.py +17 -38
- speedy_utils-2.0.4/src/speedy_utils/common/exceptions.py +69 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/utils_cache.py +10 -8
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/utils_error.py +8 -14
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/utils_io.py +6 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/utils_misc.py +2 -0
- speedy_utils-2.0.4/src/speedy_utils/multi_worker/_mp_backends.py +814 -0
- speedy_utils-2.0.4/src/speedy_utils/multi_worker/_mp_progress.py +128 -0
- speedy_utils-2.0.4/src/speedy_utils/multi_worker/_mp_spawn.py +335 -0
- speedy_utils-2.0.4/src/speedy_utils/multi_worker/_multi_process.py +321 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/multi_worker/common.py +190 -180
- speedy_utils-2.0.4/src/speedy_utils/multi_worker/dataset_sharding.py +226 -0
- speedy_utils-2.0.4/src/speedy_utils/multi_worker/process.py +23 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/multi_worker/thread.py +302 -179
- speedy_utils-2.0.4/src/vision_utils/__init__.py +19 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/llm_utils/test_llm_call_contract.py +33 -1
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/llm_utils/test_llm_mixins.py +55 -5
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/llm_utils/test_llm_signature.py +1 -1
- speedy_utils-2.0.4/tests/llm_utils/test_public_api.py +117 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test.py +6 -3
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_memoize_typing.py +4 -0
- speedy_utils-2.0.4/tests/test_mp_no_main_guard.py +154 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_multi_process.py +66 -63
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_multi_thread.py +4 -2
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_process.py +133 -40
- speedy_utils-2.0.4/tests/test_process_update.py +343 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_thread.py +14 -2
- speedy_utils-2.0.4/tests/test_utils_io.py +18 -0
- speedy_utils-2.0.4/tools/check_syntax.py +185 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tools/uv_test.sh +1 -1
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/uv.lock +8 -3
- speedy_utils-2.0.2/chainlit.md +0 -14
- 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/__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.4}/.codex +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.githooks/pre-push +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/prompts/improveParallelErrorHandling.prompt.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/caching-utilities/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/caching-utilities/examples/caching_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/dataset-processing-multiprocessing/CONFIG_REFERENCE.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/dataset-processing-multiprocessing/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/dataset-processing-multiprocessing/example_tokenize_pack.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/edit-llm-inference-style/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/io-utilities/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/io-utilities/examples/io_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/llm-integration/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/llm-integration/examples/llm_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/multi-threading-processing/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/ray-distributed-computing/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/skill-creation/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/vision-utilities/SKILL.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/skills/vision-utilities/examples/vision_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.github/workflows/publish.yml +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/.pre-commit-config.yaml +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/AGENTS.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/bumpversion.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/debug_generate_response.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/debug_n_param.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/debug_n_structure.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/integration_test.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/multi_thread.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/test_decode_api.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/test_endpoints.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/test_generate.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/test_generate_endpoint.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/test_qwen3_generate.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/debug/test_qwen3_generate.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/docs/GENERATE_QUICKREF.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/docs/MIGRATION_THINKING.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/docs/TOKENIZATION.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/docs/TOKENIZATION_IMPLEMENTATION.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/examples/generate_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/examples/llm_public_api_example.ipynb +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/examples/model_specific_thinking_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/examples/tokenization_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/examples/vision_utils_example.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/experiments/exp1/dockerfile +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/experiments/exp1/run_in_docker.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/experiments/exp1/test.png +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/notebooks/test.ipynb +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/bug_simple.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/deploy.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/imports.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/install_hooks.sh +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/test.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/test_error_handling.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/test_import_time_vision.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/test_locals.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/scripts/test_ray_mp.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/setup.cfg +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/datasets_utils/convert_to_arrow.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/chat_format/__init__.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/chat_format/transform.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/chat_format/utils.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/lm/base_prompt_builder.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/lm/lm_base.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/llm_utils/lm/signature.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/__init__.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/clock.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/function_decorator.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/logger.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/notebook_utils.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/patcher.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/report_manager.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/common/utils_print.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/multi_worker/__init__.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/scripts/__init__.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/scripts/kill_mpython.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/scripts/mpython.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/scripts/openapi_client_codegen.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/speedy_utils/scripts/prefetch_large_model.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/vision_utils/README.md +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/vision_utils/io_utils.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/src/vision_utils/plot.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/import_all.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/import_time_report.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/llm_utils/test_openai_memoize_completion_cache.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/llm_utils/test_openai_proxy_localhost.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/llm_utils/test_sp_chat.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/sample_objects.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_import_time.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_logger.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_logger_format.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_mpython.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_multithread_error_trace.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_prefetch_large_model.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/tests/test_tokenization.py +0 -0
- {speedy_utils-2.0.2 → speedy_utils-2.0.4}/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.
|
|
@@ -9,19 +9,22 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
9
9
|
uv sync
|
|
10
10
|
|
|
11
11
|
# Run tests
|
|
12
|
-
|
|
12
|
+
./tools/uv_test.sh -n 32
|
|
13
13
|
|
|
14
14
|
# Run a single test file
|
|
15
|
-
|
|
15
|
+
./tools/uv_test.sh tests/test_thread.py
|
|
16
16
|
|
|
17
17
|
# Run with verbose output
|
|
18
|
-
|
|
18
|
+
./tools/uv_test.sh -v
|
|
19
19
|
|
|
20
20
|
# Check import time (must be < 0.4s)
|
|
21
21
|
uv run python -c "import time; start=time.perf_counter(); import speedy_utils; print(f'{time.perf_counter()-start:.3f}s')"
|
|
22
22
|
|
|
23
|
-
# Detailed import analysis
|
|
24
|
-
uv run python scripts/debug_import_time.py speedy_utils --min-sec 0.
|
|
23
|
+
# Detailed import analysis / import budget check
|
|
24
|
+
uv run python scripts/debug_import_time.py speedy_utils --max-total-sec 0.4 --top 12 --min-sec 0.01 --no-stdlib
|
|
25
|
+
|
|
26
|
+
# Check all public packages with the same helper used by pre-commit
|
|
27
|
+
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
|
|
25
28
|
|
|
26
29
|
# Lint with ruff
|
|
27
30
|
uv run ruff check .
|
|
@@ -40,6 +43,16 @@ uv run ruff format .
|
|
|
40
43
|
|
|
41
44
|
**CRITICAL:** All modules must import in under 0.4 seconds. This is enforced by a git pre-commit hook.
|
|
42
45
|
|
|
46
|
+
When the import-time hook fails, rerun `scripts/debug_import_time.py` with the
|
|
47
|
+
same package list and budget. The helper now prints both:
|
|
48
|
+
|
|
49
|
+
- top-level contributors by aggregated self time
|
|
50
|
+
- slowest full import paths from `python -X importtime`
|
|
51
|
+
|
|
52
|
+
Use that output to pinpoint which import chain needs to be moved behind a lazy
|
|
53
|
+
import. Keep the helper's default package list and thresholds aligned with the
|
|
54
|
+
packages this repo exports as the project evolves.
|
|
55
|
+
|
|
43
56
|
### Lazy Import Strategy
|
|
44
57
|
|
|
45
58
|
Import heavy modules inside functions, NOT at module level:
|
|
@@ -170,6 +183,50 @@ The package provides these CLI commands:
|
|
|
170
183
|
- Ignore rules `E402`, `F401`, `F403` in `__init__.py` files for lazy import patterns
|
|
171
184
|
- Quote style: double quotes
|
|
172
185
|
- Avoid hacky workarounds like sys.path.insert
|
|
186
|
+
- Follow `CODE_STYLE.md` for general style guidelines
|
|
187
|
+
|
|
188
|
+
## Type Checking with Pyright
|
|
189
|
+
|
|
190
|
+
**CRITICAL:** Before committing, always run `uv run python tools/check_syntax.py` to
|
|
191
|
+
verify there are **zero** pyright errors. This tool mirrors exactly what VS Code
|
|
192
|
+
Pylance shows as red diagnostics.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Full check (src/ + tests/, honours pyrightconfig.json)
|
|
196
|
+
uv run python tools/check_syntax.py
|
|
197
|
+
|
|
198
|
+
# Import-time budget check with root-cause breakdown
|
|
199
|
+
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
|
|
200
|
+
|
|
201
|
+
# Check a single file
|
|
202
|
+
uv run python tools/check_syntax.py --file src/llm_utils/lm/llm_qwen3.py
|
|
203
|
+
|
|
204
|
+
# Machine-readable JSON output
|
|
205
|
+
uv run python tools/check_syntax.py --json
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### pyright config (`pyrightconfig.json`)
|
|
209
|
+
|
|
210
|
+
The config lives at the repo root. Key rules that are **suppressed** (because
|
|
211
|
+
they produce false positives in this codebase):
|
|
212
|
+
|
|
213
|
+
| Rule | Why suppressed |
|
|
214
|
+
|------|---------------|
|
|
215
|
+
| `reportMissingImports` | Optional GPU deps (`torch`, `nvidia.dali`) not installed everywhere |
|
|
216
|
+
| `reportAttributeAccessIssue` | Dynamic attrs on OpenAI pydantic models (`choice.usage`, `message.call_count`) |
|
|
217
|
+
| `reportUnsupportedDunderAll` | Lazy `__getattr__` exports listed in `__all__` |
|
|
218
|
+
|
|
219
|
+
### Common type-annotation patterns
|
|
220
|
+
|
|
221
|
+
- **Lazy-loaded `__all__` entries** — never trigger `__getattr__`; use `# type: ignore[override]`
|
|
222
|
+
only on the `__getitem__` override pattern in datasets.
|
|
223
|
+
- **Dynamic pydantic attrs** — use `# type: ignore[attr-defined]` when setting attrs
|
|
224
|
+
not in the schema (e.g. `message.call_count = …`).
|
|
225
|
+
- **Overload ordering** — put the `Awaitable[R]` overload **before** the generic `R`
|
|
226
|
+
overload; otherwise pyright reports `reportOverlappingOverload`.
|
|
227
|
+
- **`tqdm` in type hints** — use string literal `"tqdm"` to avoid `reportInvalidTypeForm`.
|
|
228
|
+
- **Future custom attrs** — `concurrent.futures.Future` doesn't declare custom attrs;
|
|
229
|
+
suppress with `reportAttributeAccessIssue: "none"` in config.
|
|
173
230
|
|
|
174
231
|
|
|
175
232
|
## Version Management
|