lean-runtime 4.30.0__tar.gz → 4.33.0__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.
Files changed (203) hide show
  1. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/CHANGELOG.md +25 -2
  2. {lean_runtime-4.30.0/lean_runtime.egg-info → lean_runtime-4.33.0}/PKG-INFO +1 -1
  3. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/bundles.py +127 -9
  4. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/capsules.py +50 -9
  5. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/cli.py +3 -3
  6. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/console.py +37 -6
  7. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/declaration_index_build.py +32 -0
  8. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/declaration_index_oci.py +38 -0
  9. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/events.py +22 -0
  10. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/packs.py +57 -42
  11. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/programs.py +33 -3
  12. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/progress.py +70 -0
  13. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/project_execution.py +6 -0
  14. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/projects.py +8 -0
  15. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/runtime.py +77 -42
  16. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/store.py +139 -26
  17. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/toolchain_oci.py +28 -2
  18. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/toolchain_slim.py +49 -20
  19. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/toolchains.py +18 -9
  20. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/verification.py +67 -37
  21. {lean_runtime-4.30.0 → lean_runtime-4.33.0/lean_runtime.egg-info}/PKG-INFO +1 -1
  22. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime.egg-info/SOURCES.txt +1 -0
  23. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/pyproject.toml +1 -1
  24. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_progress.py +7 -1
  25. lean_runtime-4.33.0/tests/test_progress_counted.py +155 -0
  26. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/LICENSE +0 -0
  27. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/MANIFEST.in +0 -0
  28. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/README.md +0 -0
  29. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/environments.toml +0 -0
  30. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/core-v4.32.2.lock.json +0 -0
  31. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/leancert-v4.30.0.5.lock.json +0 -0
  32. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/leancert-v4.31.0.lock.json +0 -0
  33. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/leancert-v4.32.2.4.lock.json +0 -0
  34. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/leancert-v4.33.0.lock.json +0 -0
  35. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/mathlib-v4.30.0.lock.json +0 -0
  36. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/mathlib-v4.31.0.lock.json +0 -0
  37. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/mathlib-v4.32.2.lock.json +0 -0
  38. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/mathlib-v4.33.0.lock.json +0 -0
  39. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/catalog/locks/mathlib-v4.33.1.lock.json +0 -0
  40. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/compatibility/README.md +0 -0
  41. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/compatibility/lake-artifact-cache-4.33.0.json +0 -0
  42. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/compatibility/mathlib-4.32.2.json +0 -0
  43. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/compatibility/mathlib-4.32.2.toml +0 -0
  44. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/compatibility/mathlib-4.33.0.json +0 -0
  45. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/compatibility/mathlib-4.33.0.toml +0 -0
  46. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/concepts/context-selection.md +0 -0
  47. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/index.md +0 -0
  48. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/reference/commands.md +0 -0
  49. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/reference/python-advanced.md +0 -0
  50. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/reference/python-api.md +0 -0
  51. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/reference/storage.md +0 -0
  52. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/trust.md +0 -0
  53. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/tutorial.md +0 -0
  54. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/workflows/check-files.md +0 -0
  55. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/docs/workflows/lake-projects.md +0 -0
  56. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/examples/mathlib.toml +0 -0
  57. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/__init__.py +0 -0
  58. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/__main__.py +0 -0
  59. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/_git.py +0 -0
  60. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/_paths.py +0 -0
  61. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/backends.py +0 -0
  62. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/comparison.py +0 -0
  63. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/context_resolution.py +0 -0
  64. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/decisions.py +0 -0
  65. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/declaration_index.py +0 -0
  66. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/diagnostics.py +0 -0
  67. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/__init__.py +0 -0
  68. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/analyzer.py +0 -0
  69. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/api.py +0 -0
  70. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/candidate.py +0 -0
  71. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/catalog.py +0 -0
  72. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/catalog_build.py +0 -0
  73. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/catalog_cli.py +0 -0
  74. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/catalog_manifest.py +0 -0
  75. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/data/catalog.json +0 -0
  76. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/defaults.py +0 -0
  77. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/engine.py +0 -0
  78. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/errors.py +0 -0
  79. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/history.py +0 -0
  80. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/memo.py +0 -0
  81. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/module_inventory.py +0 -0
  82. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/planner.py +0 -0
  83. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/policy.py +0 -0
  84. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/probe.py +0 -0
  85. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/py.typed +0 -0
  86. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/result.py +0 -0
  87. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/schema_resources.py +0 -0
  88. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/schemas/catalog-v1.schema.json +0 -0
  89. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/schemas/plan-v1.schema.json +0 -0
  90. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/discovery/schemas/result-v1.schema.json +0 -0
  91. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/environments.py +0 -0
  92. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/errors.py +0 -0
  93. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/facade.py +0 -0
  94. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/frontmatter.py +0 -0
  95. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/header_cache.py +0 -0
  96. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/health.py +0 -0
  97. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/identifier_resolver.py +0 -0
  98. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/import_syntax.py +0 -0
  99. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/lake.py +0 -0
  100. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/lake_cache.py +0 -0
  101. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/lockfiles.py +0 -0
  102. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/locking.py +0 -0
  103. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/matrix.py +0 -0
  104. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/models.py +0 -0
  105. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/oci.py +0 -0
  106. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/oci_protocol.py +0 -0
  107. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/package_ids.py +0 -0
  108. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/policies.py +0 -0
  109. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/profiling.py +0 -0
  110. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/project_sharing.py +0 -0
  111. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/publisher_verification.py +0 -0
  112. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/py.typed +0 -0
  113. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/references.py +0 -0
  114. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/resolver.py +0 -0
  115. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/run_cli.py +0 -0
  116. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/schema_resources.py +0 -0
  117. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/serialization.py +0 -0
  118. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/shared_projects.py +0 -0
  119. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/specs.py +0 -0
  120. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/timings.py +0 -0
  121. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime/wire.py +0 -0
  122. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime.egg-info/dependency_links.txt +0 -0
  123. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime.egg-info/entry_points.txt +0 -0
  124. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime.egg-info/requires.txt +0 -0
  125. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/lean_runtime.egg-info/top_level.txt +0 -0
  126. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/mkdocs.yml +0 -0
  127. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/attestation-v1.schema.json +0 -0
  128. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/check-batch-v1.schema.json +0 -0
  129. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/cleanup-v1.schema.json +0 -0
  130. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/comparison-v1.schema.json +0 -0
  131. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/execution-v1.schema.json +0 -0
  132. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/inspect-v1.schema.json +0 -0
  133. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/matrix-v1.schema.json +0 -0
  134. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/plan-v1.schema.json +0 -0
  135. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/profile-v1.schema.json +0 -0
  136. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/publication-v1.schema.json +0 -0
  137. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/status-v1.schema.json +0 -0
  138. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/schemas/verify-v1.schema.json +0 -0
  139. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/announcement_gate.py +0 -0
  140. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/catalog_update.py +0 -0
  141. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/lake_cache_gate.py +0 -0
  142. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/prepare_declaration_index.py +0 -0
  143. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/publish_declaration_index.py +0 -0
  144. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/registry_preflight.py +0 -0
  145. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/run_compatibility.py +0 -0
  146. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/run_v1_case_study.py +0 -0
  147. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/scripts/smoke_wheel.py +0 -0
  148. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/setup.cfg +0 -0
  149. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/conftest.py +0 -0
  150. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/e2e/test_real_discovery.py +0 -0
  151. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/test_analyzer.py +0 -0
  152. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/test_catalog.py +0 -0
  153. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/test_catalog_build.py +0 -0
  154. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/test_discovery_schema_resources.py +0 -0
  155. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/test_engine.py +0 -0
  156. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/test_memo.py +0 -0
  157. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/test_planner.py +0 -0
  158. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/discovery/test_policy.py +0 -0
  159. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_announcement_gate.py +0 -0
  160. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_backend.py +0 -0
  161. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_bundles.py +0 -0
  162. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_capsules.py +0 -0
  163. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_cli.py +0 -0
  164. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_console.py +0 -0
  165. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_context_resolution.py +0 -0
  166. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_declaration_index.py +0 -0
  167. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_diagnostics.py +0 -0
  168. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_environment_integration.py +0 -0
  169. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_events_health.py +0 -0
  170. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_facade.py +0 -0
  171. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_frontmatter.py +0 -0
  172. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_git.py +0 -0
  173. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_header_cache.py +0 -0
  174. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_identifier_resolver.py +0 -0
  175. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_interactive.py +0 -0
  176. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_lake_cache.py +0 -0
  177. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_lockfiles.py +0 -0
  178. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_locking.py +0 -0
  179. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_models.py +0 -0
  180. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_multifile.py +0 -0
  181. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_oci_protocol.py +0 -0
  182. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_package_ids.py +0 -0
  183. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_packs.py +0 -0
  184. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_paths.py +0 -0
  185. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_prebuilt_policy.py +0 -0
  186. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_programs.py +0 -0
  187. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_project_bootstrap.py +0 -0
  188. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_project_publish.py +0 -0
  189. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_projects.py +0 -0
  190. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_references.py +0 -0
  191. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_run_cli.py +0 -0
  192. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_runtime.py +0 -0
  193. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_schema_resources.py +0 -0
  194. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_schemas.py +0 -0
  195. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_signatures.py +0 -0
  196. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_specs.py +0 -0
  197. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_store.py +0 -0
  198. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_toolchain_oci.py +0 -0
  199. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_toolchain_slim.py +0 -0
  200. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_toolchains.py +0 -0
  201. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_v1_precision.py +0 -0
  202. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_verification_inventory.py +0 -0
  203. {lean_runtime-4.30.0 → lean_runtime-4.33.0}/tests/test_verification_probe.py +0 -0
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 4.33.0 - 2026-08-27
6
+
7
+ - Cover the remaining silent phases with progress. Elan bootstrap and
8
+ `elan toolchain install`, and the `lake init`/`lake update` behind `new`, now
9
+ stream their output as `process.progress`/`process.output` like every other
10
+ subprocess. Long pure-Python loops report counted progress that renders as a
11
+ bar: `verification.inventory` (hashing build artifacts in `verify`),
12
+ `bundle.tree_inventory` (`env export`/`import`), `source.snapshot_digest`
13
+ (source fingerprints, including path dependencies during `adopt`), and
14
+ `capsule.import_parse`. The publish preflight fetch
15
+ (`publish.remote_probe_started`) and the Lake configuration read behind
16
+ project-wide `check` (`project.config_translate_started`) announce
17
+ themselves. Any event carrying `current`/`total` and a `label` now renders as
18
+ a counted bar without a dedicated console handler, and deep helpers reach
19
+ the active runtime's emitter through `lean_runtime.events.current()`.
20
+ - Re-running `adopt` over a tree no longer re-probes every already attached
21
+ project (a Lake graph load each, up to two minutes for Mathlib); the plan
22
+ already reports them as attached and `verify` re-checks links. Attachment
23
+ now announces `adopt.attach_started` per project, rendered as
24
+ `Attaching projects [bar] i/n`, and the pre-swap Lake graph probe streams its
25
+ output like every other Lake invocation instead of running silently.
26
+
5
27
  ## 4.30.0 - 2026-08-26
6
28
 
7
29
  - Attach shared dependencies on Windows without administrator rights. Creating
@@ -29,8 +51,9 @@
29
51
  `project.detach.package_started` for each package `unshare` materializes; all
30
52
  carry `current`/`total` and render as the same counted bar.
31
53
  - Keep the terminal alive during any silent stretch: when no event has arrived
32
- for two seconds the console shows `⋯ <last activity> (Ns)` in place; plain
33
- logs print `Still working: …` after ten seconds and then every thirty.
54
+ for two seconds the console shows `⋯ no new events for Ns · last: <activity>`
55
+ in place; plain logs print `Still working (…)` after ten seconds and then
56
+ every thirty.
34
57
  - Name new shared package directories `pkg_<32 hex>` instead of
35
58
  `project_package_<64 hex>`. The 80-character name pushed Mathlib's deepest
36
59
  build outputs past Windows' 260-character path limit, so an adopted Mathlib
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lean-runtime
3
- Version: 4.30.0
3
+ Version: 4.33.0
4
4
  Summary: Run Lean 4 proofs from Python or standalone files
5
5
  Author: Alejandro Radisic
6
6
  License-Expression: Apache-2.0
@@ -13,10 +13,11 @@ import tarfile
13
13
  import tempfile
14
14
  import uuid
15
15
  from collections.abc import Iterable, Mapping, Sequence
16
+ from contextlib import nullcontext
16
17
  from dataclasses import dataclass
17
18
  from datetime import datetime, timezone
18
19
  from pathlib import Path, PurePosixPath
19
- from typing import Any
20
+ from typing import Any, Protocol
20
21
 
21
22
  import zstandard
22
23
 
@@ -33,7 +34,7 @@ from .capsules import (
33
34
  setup_artifact_groups,
34
35
  )
35
36
  from .errors import EnvironmentError
36
- from .events import EventEmitter
37
+ from .events import EventEmitter, current
37
38
  from .lake import ROOT_MODULE
38
39
  from .lockfiles import EnvironmentLock, LockedPackage
39
40
  from .locking import FileLock
@@ -61,6 +62,7 @@ from .packs import (
61
62
  unpack_frame,
62
63
  )
63
64
  from .policies import ExecutionPolicy
65
+ from .progress import CountedProgress
64
66
  from .serialization import canonical_json_bytes, write_json_atomic
65
67
  from .store import (
66
68
  EnvironmentStore,
@@ -81,6 +83,53 @@ SOURCE_TREE_INVENTORY = ".lean-runtime-source-tree.json"
81
83
  MAX_CAPSULE_CONFIG_BYTES = 64 * 1024**2
82
84
 
83
85
 
86
+ class _BinaryReader(Protocol):
87
+ def read(self, size: int = -1) -> bytes: ...
88
+
89
+ def readinto(self, buffer: Any) -> int | None: ...
90
+
91
+ def seek(self, offset: int, whence: int = 0) -> int: ...
92
+
93
+ def tell(self) -> int: ...
94
+
95
+
96
+ class _ProgressReader:
97
+ """Report bytes after a consumer has actually read them."""
98
+
99
+ def __init__(
100
+ self, handle: _BinaryReader, progress: CountedProgress, *, offset: int = 0
101
+ ) -> None:
102
+ self._handle = handle
103
+ self._progress = progress
104
+ self._offset = offset
105
+ self._furthest = offset
106
+
107
+ def _report(self) -> None:
108
+ position = self._offset + self._handle.tell()
109
+ if position > self._furthest:
110
+ self._furthest = position
111
+ self._progress.advance(to=position)
112
+
113
+ def read(self, size: int = -1) -> bytes:
114
+ data = self._handle.read(size)
115
+ self._report()
116
+ return data
117
+
118
+ def readinto(self, buffer: Any) -> int:
119
+ count = self._handle.readinto(buffer)
120
+ self._report()
121
+ return count if count is not None else 0
122
+
123
+ def seek(self, offset: int, whence: int = 0) -> int:
124
+ return self._handle.seek(offset, whence)
125
+
126
+ def tell(self) -> int:
127
+ return self._handle.tell()
128
+
129
+ def __getattr__(self, name: str) -> Any:
130
+ return getattr(self._handle, name)
131
+
132
+
84
133
  @dataclass(frozen=True, slots=True)
85
134
  class PortableCopyInfo:
86
135
  environment_id: str
@@ -130,8 +179,27 @@ def _tree_entries(
130
179
  excluded_names: frozenset[str] = frozenset(),
131
180
  omit_volatile_build_metadata: bool = False,
132
181
  ) -> Iterable[tuple[Path, str]]:
133
- for path in sorted(root.rglob("*"), key=lambda value: value.relative_to(root).as_posix()):
182
+ scan = CountedProgress(
183
+ current().emit,
184
+ "bundle.tree_scan",
185
+ f"Scanning {root.name}",
186
+ 1,
187
+ phase="bundle",
188
+ )
189
+ scan.start()
190
+ paths = sorted(root.rglob("*"), key=lambda value: value.relative_to(root).as_posix())
191
+ scan.advance(f"{len(paths)} entries")
192
+ progress = CountedProgress(
193
+ current().emit,
194
+ "bundle.tree_inventory",
195
+ f"Inventorying {root.name}",
196
+ len(paths),
197
+ phase="bundle",
198
+ )
199
+ progress.start()
200
+ for path in paths:
134
201
  if excluded is not None and (path == excluded or excluded in path.parents):
202
+ progress.advance(path.relative_to(root).as_posix())
135
203
  continue
136
204
  relative = path.relative_to(root)
137
205
  if relative.parts and relative.parts[0] in excluded_names:
@@ -145,8 +213,10 @@ def _tree_entries(
145
213
  or relative.name.endswith(".rsp")
146
214
  )
147
215
  ):
216
+ progress.advance(relative.as_posix())
148
217
  continue
149
218
  yield path, relative.as_posix()
219
+ progress.advance(relative.as_posix())
150
220
 
151
221
 
152
222
  def _write_tar_gzip(
@@ -219,6 +289,18 @@ def _oci_archive(entries: dict[str, bytes]) -> bytes:
219
289
 
220
290
 
221
291
  def _write_oci_archive(entries: dict[str, Path], output: Path) -> None:
292
+ ordered = sorted(entries.items())
293
+ total = sum(path.stat().st_size for _name, path in ordered)
294
+ progress = CountedProgress(
295
+ current().emit,
296
+ "bundle.archive_write",
297
+ "Writing portable archive",
298
+ total,
299
+ phase="bundle",
300
+ unit="bytes",
301
+ )
302
+ progress.start()
303
+ written = 0
222
304
  with (
223
305
  output.open("wb") as raw_output,
224
306
  gzip.GzipFile(
@@ -226,11 +308,13 @@ def _write_oci_archive(entries: dict[str, Path], output: Path) -> None:
226
308
  ) as compressed,
227
309
  tarfile.open(fileobj=compressed, mode="w|", format=tarfile.PAX_FORMAT) as archive,
228
310
  ):
229
- for name, path in sorted(entries.items()):
311
+ for name, path in ordered:
230
312
  info = _normalized_info(name, mode=0o644)
231
313
  info.size = path.stat().st_size
232
314
  with path.open("rb") as handle:
233
- archive.addfile(info, handle)
315
+ archive.addfile(info, _ProgressReader(handle, progress, offset=written))
316
+ written += info.size
317
+ progress.advance(name, to=written)
234
318
 
235
319
 
236
320
  def _safe_name(name: str) -> PurePosixPath:
@@ -315,16 +399,32 @@ def _extract_layer(data: bytes | Path, destination: Path) -> None:
315
399
  if destination.is_symlink():
316
400
  raise EnvironmentError("bundle extraction destination must not be a symlink")
317
401
  destination.mkdir(parents=True, exist_ok=True)
402
+ progress: CountedProgress | None = None
403
+ raw_handle: Any = None
318
404
  try:
319
405
  if isinstance(data, Path):
320
- archive = tarfile.open(data, mode="r:gz") # noqa: SIM115
406
+ raw_handle = data.open("rb")
407
+ progress = CountedProgress(
408
+ current().emit,
409
+ "bundle.layer_extract",
410
+ f"Extracting {destination.name}",
411
+ data.stat().st_size,
412
+ phase="bundle",
413
+ unit="bytes",
414
+ )
415
+ progress.start()
416
+ archive = tarfile.open( # noqa: SIM115
417
+ fileobj=_ProgressReader(raw_handle, progress), mode="r:gz"
418
+ )
321
419
  else:
322
420
  archive = tarfile.open( # noqa: SIM115
323
421
  fileobj=io.BytesIO(data), mode="r:gz"
324
422
  )
325
423
  except (tarfile.TarError, OSError) as exc:
424
+ if raw_handle is not None:
425
+ raw_handle.close()
326
426
  raise EnvironmentError("bundle layer is not a valid gzip tar archive") from exc
327
- with archive:
427
+ with archive, raw_handle if raw_handle is not None else nullcontext():
328
428
  for member in archive:
329
429
  count += 1
330
430
  total += member.size
@@ -353,6 +453,8 @@ def _extract_layer(data: bytes | Path, destination: Path) -> None:
353
453
  target.symlink_to(member.linkname)
354
454
  else:
355
455
  raise EnvironmentError(f"unsupported bundle member: {member.name!r}")
456
+ if progress is not None:
457
+ progress.advance(to=progress.total)
356
458
 
357
459
 
358
460
  def _git_object_id(kind: str, data: bytes) -> str:
@@ -1112,11 +1214,26 @@ class EnvironmentBundles:
1112
1214
  entries: dict[str, Path] = {}
1113
1215
  total = 0
1114
1216
  count = 0
1217
+ byte_progress = CountedProgress(
1218
+ current().emit,
1219
+ "bundle.archive_extract",
1220
+ f"Reading {bundle.name}",
1221
+ bundle.stat().st_size,
1222
+ phase="bundle",
1223
+ unit="bytes",
1224
+ )
1225
+ byte_progress.start()
1226
+ raw_handle: Any = None
1115
1227
  try:
1116
- archive = tarfile.open(bundle, mode="r:gz") # noqa: SIM115
1228
+ raw_handle = bundle.open("rb")
1229
+ archive = tarfile.open( # noqa: SIM115
1230
+ fileobj=_ProgressReader(raw_handle, byte_progress), mode="r:gz"
1231
+ )
1117
1232
  except (tarfile.TarError, OSError) as exc:
1233
+ if raw_handle is not None:
1234
+ raw_handle.close()
1118
1235
  raise EnvironmentError(f"could not read OCI bundle: {bundle}") from exc
1119
- with archive:
1236
+ with archive, raw_handle:
1120
1237
  for member in archive:
1121
1238
  count += 1
1122
1239
  if count > MAX_FILES:
@@ -1136,6 +1253,7 @@ class EnvironmentBundles:
1136
1253
  with path.open("wb") as output:
1137
1254
  shutil.copyfileobj(source, output)
1138
1255
  entries[member.name] = path
1256
+ byte_progress.advance(to=byte_progress.total)
1139
1257
  return entries
1140
1258
 
1141
1259
  def _import_capsule_layout(
@@ -21,8 +21,10 @@ from pathlib import Path, PurePosixPath
21
21
  from typing import Any, Literal
22
22
 
23
23
  from .errors import EnvironmentError
24
+ from .events import current
24
25
  from .import_syntax import IMPORT_STATEMENT
25
26
  from .lockfiles import EnvironmentLock
27
+ from .progress import CountedProgress
26
28
  from .serialization import canonical_json_bytes, write_json_atomic
27
29
 
28
30
  CAPSULE_SCHEMA = "lean-runtime-check-capsule/1"
@@ -253,6 +255,14 @@ def parse_import_headers(
253
255
  with tempfile.TemporaryDirectory(prefix="lean-runtime-imports-") as raw:
254
256
  helper = Path(raw) / "ParseImports.lean"
255
257
  helper.write_text(IMPORT_PARSER_SOURCE, encoding="utf-8")
258
+ progress = CountedProgress(
259
+ current().emit,
260
+ "capsule.import_parse",
261
+ "Parsing imports",
262
+ len(source_paths),
263
+ phase="capsule",
264
+ )
265
+ progress.start()
256
266
  for offset in range(0, len(source_paths), batch_size):
257
267
  batch = list(source_paths[offset : offset + batch_size])
258
268
  process = subprocess.run(
@@ -286,6 +296,7 @@ def parse_import_headers(
286
296
  if isinstance(item, dict) and isinstance(item.get("module"), str)
287
297
  }
288
298
  result[path] = tuple(sorted(names))
299
+ progress.advance(to=min(offset + len(batch), len(source_paths)))
289
300
  return result
290
301
 
291
302
 
@@ -369,16 +380,34 @@ def build_manifest(
369
380
  complete_modules: frozenset[str] | None = None,
370
381
  ) -> CapsuleManifest:
371
382
  """Inventory retained module artifacts beneath package build roots."""
383
+ scan = CountedProgress(
384
+ current().emit,
385
+ "capsule.artifact_scan",
386
+ "Scanning capsule artifacts",
387
+ 1,
388
+ phase="capsule",
389
+ )
390
+ scan.start()
391
+ paths = [
392
+ (package, root, path)
393
+ for package, root in sorted(build_roots.items())
394
+ if root.is_dir()
395
+ for path in sorted(root.rglob("*"))
396
+ if path.is_file()
397
+ ]
398
+ scan.advance(f"{len(paths)} files")
399
+ progress = CountedProgress(
400
+ current().emit,
401
+ "capsule.artifact_inventory",
402
+ "Hashing capsule artifacts",
403
+ len(paths),
404
+ phase="capsule",
405
+ )
406
+ progress.start()
372
407
  modules: dict[str, tuple[str, list[CapsuleArtifact]]] = {}
373
- for package, root in sorted(build_roots.items()):
374
- if not root.is_dir():
375
- continue
376
- for path in sorted(root.rglob("*")):
377
- if not path.is_file():
378
- continue
379
- module = module_from_artifact(path.relative_to(root))
380
- if module is None:
381
- continue
408
+ for package, root, path in paths:
409
+ module = module_from_artifact(path.relative_to(root))
410
+ if module is not None:
382
411
  relative = path.relative_to(workspace).as_posix()
383
412
  capability = artifact_capability(path)
384
413
  artifact = CapsuleArtifact(
@@ -390,6 +419,7 @@ def build_manifest(
390
419
  f"capsule module {module} is provided by both {existing[0]} and {package}"
391
420
  )
392
421
  modules.setdefault(module, (package, []))[1].append(artifact)
422
+ progress.advance(path.relative_to(workspace).as_posix())
393
423
  known_complete = frozenset(imports) if complete_modules is None else complete_modules
394
424
  records = tuple(
395
425
  CapsuleModule(
@@ -436,6 +466,14 @@ def inventory_workspace(
436
466
  ) -> CapsuleManifest:
437
467
  """Build an exact capsule inventory from a verified full workspace."""
438
468
  source_roots, build_roots = _package_directories(workspace, lock)
469
+ discovery = CountedProgress(
470
+ current().emit,
471
+ "capsule.module_discovery",
472
+ "Discovering capsule modules",
473
+ len(build_roots) + len(source_roots),
474
+ phase="capsule",
475
+ )
476
+ discovery.start()
439
477
  modules_by_package: dict[str, set[str]] = {}
440
478
  for package, root in build_roots.items():
441
479
  modules_by_package[package] = {
@@ -443,11 +481,13 @@ def inventory_workspace(
443
481
  for path in root.rglob("*.olean")
444
482
  if (module := module_from_artifact(path.relative_to(root))) is not None
445
483
  }
484
+ discovery.advance(package)
446
485
 
447
486
  source_modules: dict[Path, str] = {}
448
487
  claimed: dict[str, tuple[int, Path]] = {}
449
488
  for package, root in source_roots.items():
450
489
  if not root.is_dir():
490
+ discovery.advance(package)
451
491
  continue
452
492
  available = modules_by_package[package]
453
493
  for path in sorted(root.rglob("*.lean")):
@@ -473,6 +513,7 @@ def inventory_workspace(
473
513
  source_modules.pop(previous[1], None)
474
514
  claimed[module] = (stripped, path)
475
515
  source_modules[path] = module
516
+ discovery.advance(package)
476
517
 
477
518
  parsed = parse_import_headers(lean_command, tuple(source_modules))
478
519
  imports = {source_modules[path]: names for path, names in parsed.items()}
@@ -1970,9 +1970,9 @@ def main(argv: list[str] | None = None) -> int:
1970
1970
  )
1971
1971
  if declined is not None:
1972
1972
  return declined
1973
- di_publication = OCIDeclarationIndexPublisher(di_repository).publish(
1974
- tuple(di_item.source for di_item in built.shards), lock_id=lock.lock_id
1975
- )
1973
+ di_publication = OCIDeclarationIndexPublisher(
1974
+ di_repository, events=runtime.events
1975
+ ).publish(tuple(di_item.source for di_item in built.shards), lock_id=lock.lock_id)
1976
1976
  if args.sign:
1977
1977
  CosignVerifier(executable=runtime.verification_executable).sign(
1978
1978
  di_repository, di_publication.manifest_digest
@@ -141,6 +141,19 @@ class ConsoleRenderer:
141
141
  handler = getattr(self, "_render_" + event.kind.replace(".", "_"), None)
142
142
  if handler is not None:
143
143
  handler(event)
144
+ elif (
145
+ isinstance(event.data.get("current"), int)
146
+ and isinstance(event.data.get("total"), int)
147
+ and event.data.get("label")
148
+ ):
149
+ # Any counted event renders as a bar without a dedicated handler.
150
+ self._render_count_progress(
151
+ str(event.data["label"]),
152
+ event.data["current"],
153
+ event.data["total"],
154
+ str(event.data.get("detail") or ""),
155
+ bytes_unit=event.data.get("unit") == "bytes",
156
+ )
144
157
 
145
158
  def note(self, message: str) -> None:
146
159
  """Print one renderer-owned status line."""
@@ -183,11 +196,12 @@ class ConsoleRenderer:
183
196
  idle = self._clock() - self._last_event_at
184
197
  if idle < self._heartbeat_seconds:
185
198
  continue
199
+ last = _truncate(self._last_message, _OUTPUT_WIDTH)
186
200
  if self.mode == "tty":
187
- text = f"⋯ {_truncate(self._last_message, _OUTPUT_WIDTH)} ({int(idle)}s)"
201
+ text = f"⋯ no new events for {int(idle)}s · last: {last}"
188
202
  self._draw_line(text, self.style.dim(text))
189
203
  elif idle >= self._next_plain_heartbeat:
190
- self._print(f"Still working: {self._last_message} ({int(idle)}s)")
204
+ self._print(f"Still working ({int(idle)}s without events; last: {last})")
191
205
  self._next_plain_heartbeat = idle + _PLAIN_HEARTBEAT_REPEAT_SECONDS
192
206
 
193
207
  # -- individual event renderings ------------------------------------
@@ -366,6 +380,9 @@ class ConsoleRenderer:
366
380
  def _render_adopt_identity_started(self, event: RuntimeEvent) -> None:
367
381
  self._count_from(event, "Resolving dependency identities", "name")
368
382
 
383
+ def _render_adopt_attach_started(self, event: RuntimeEvent) -> None:
384
+ self._count_from(event, "Attaching projects", "name")
385
+
369
386
  def _render_project_detach_package_started(self, event: RuntimeEvent) -> None:
370
387
  self._count_from(event, "Materializing packages", "package")
371
388
 
@@ -376,7 +393,11 @@ class ConsoleRenderer:
376
393
  return
377
394
  self._render_count_progress(label, current, total, str(event.data.get(detail_key) or ""))
378
395
 
379
- def _render_count_progress(self, label: str, current: int, total: int, detail: str) -> None:
396
+ def _render_count_progress(
397
+ self, label: str, current: int, total: int, detail: str, *, bytes_unit: bool = False
398
+ ) -> None:
399
+ if total <= 0:
400
+ return
380
401
  current = min(current, total)
381
402
  if self.mode == "tty":
382
403
  now = self._clock()
@@ -390,10 +411,15 @@ class ConsoleRenderer:
390
411
  filled = _BAR_WIDTH * current // total
391
412
  bar = "█" * filled + "░" * (_BAR_WIDTH - filled)
392
413
  suffix = f" · {_truncate(detail, _DETAIL_WIDTH)}" if detail else ""
393
- plain = f"{label} [{bar}] {current}/{total}{suffix}"
414
+ amount = (
415
+ f"{format_byte_size(current)}/{format_byte_size(total)}"
416
+ if bytes_unit
417
+ else f"{current}/{total}"
418
+ )
419
+ plain = f"{label} [{bar}] {amount}{suffix}"
394
420
  styled = (
395
421
  f"{label} [{self.style.cyan(bar)}] "
396
- f"{self.style.bold(f'{current}/{total}')}{self.style.dim(suffix)}"
422
+ f"{self.style.bold(amount)}{self.style.dim(suffix)}"
397
423
  )
398
424
  self._draw_line(plain, styled)
399
425
  if current >= total:
@@ -405,7 +431,12 @@ class ConsoleRenderer:
405
431
  self._count_checkpoint = _PLAIN_CHECKPOINT_PERCENT
406
432
  percent = current * 100 // total
407
433
  while self._count_checkpoint <= percent:
408
- self._print(f"{label}: {self._count_checkpoint}% ({current}/{total})")
434
+ amount = (
435
+ f"{format_byte_size(current)}/{format_byte_size(total)}"
436
+ if bytes_unit
437
+ else f"{current}/{total}"
438
+ )
439
+ self._print(f"{label}: {self._count_checkpoint}% ({amount})")
409
440
  self._count_checkpoint += _PLAIN_CHECKPOINT_PERCENT
410
441
 
411
442
  # -- low-level output -----------------------------------------------
@@ -19,7 +19,9 @@ from .declaration_index import (
19
19
  )
20
20
  from .declaration_index_oci import DeclarationShardSource
21
21
  from .errors import EnvironmentError
22
+ from .events import current
22
23
  from .lockfiles import EnvironmentLock, LockedPackage
24
+ from .progress import CountedProgress
23
25
  from .runtime import Runtime
24
26
  from .serialization import canonical_json_bytes
25
27
 
@@ -101,9 +103,26 @@ def _declarations(root: Path) -> tuple[dict[str, str], tuple[str, ...], tuple[st
101
103
  declarations: dict[str, str] = {}
102
104
  ambiguous: set[str] = set()
103
105
  modules: set[str] = set()
106
+ scan = CountedProgress(
107
+ current().emit,
108
+ "declaration_index.scan",
109
+ f"Scanning declarations in {root.name}",
110
+ 1,
111
+ phase="declaration-index",
112
+ )
113
+ scan.start()
104
114
  ileans = tuple(sorted(root.rglob("*.ilean"), key=lambda item: item.as_posix()))
115
+ scan.advance(f"{len(ileans)} files")
105
116
  if not ileans:
106
117
  raise EnvironmentError(f"compiled declaration root contains no .ilean files: {root}")
118
+ progress = CountedProgress(
119
+ current().emit,
120
+ "declaration_index.parse",
121
+ f"Reading declarations in {root.name}",
122
+ len(ileans),
123
+ phase="declaration-index",
124
+ )
125
+ progress.start()
107
126
  for path in ileans:
108
127
  if path.stat().st_size > MAX_ILEAN_BYTES:
109
128
  raise EnvironmentError(f"Lean index exceeds its supported size: {path}")
@@ -129,6 +148,7 @@ def _declarations(root: Path) -> tuple[dict[str, str], tuple[str, ...], tuple[st
129
148
  ambiguous.add(name)
130
149
  continue
131
150
  declarations[name] = module
151
+ progress.advance(path.name)
132
152
  if not declarations:
133
153
  raise EnvironmentError(f"compiled declaration root produced no public names: {root}")
134
154
  namespace_roots = {name.split(".", 1)[0] for name in declarations}
@@ -147,6 +167,14 @@ def _write_shard(
147
167
  ) -> None:
148
168
  if output.exists():
149
169
  raise EnvironmentError(f"refusing to overwrite declaration shard: {output}")
170
+ progress = CountedProgress(
171
+ current().emit,
172
+ "declaration_index.sqlite",
173
+ f"Writing declaration shard {output.stem[:20]}",
174
+ 4,
175
+ phase="declaration-index",
176
+ )
177
+ progress.start()
150
178
  with sqlite3.connect(output) as connection:
151
179
  connection.executescript(
152
180
  f"""
@@ -171,6 +199,7 @@ def _write_shard(
171
199
  ) WITHOUT ROWID;
172
200
  """
173
201
  )
202
+ progress.advance("schema")
174
203
  metadata = {
175
204
  "schema": DECLARATION_SHARD_SCHEMA,
176
205
  "shard_id": shard_id,
@@ -184,12 +213,15 @@ def _write_shard(
184
213
  for name in sorted(declarations)
185
214
  ]
186
215
  connection.executemany("INSERT INTO decl VALUES (?, ?, ?, ?)", rows)
216
+ progress.advance("declarations")
187
217
  connection.executemany(
188
218
  "INSERT INTO suffix VALUES (?, ?)",
189
219
  sorted((name.rsplit(".", 1)[-1], name) for name in declarations),
190
220
  )
191
221
  connection.commit()
222
+ progress.advance("suffix index")
192
223
  connection.execute("VACUUM")
224
+ progress.advance("vacuum")
193
225
  DeclarationIndex(output, expected_shard_id=shard_id)
194
226
 
195
227