dirsql 0.4.83__tar.gz → 0.4.84__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 (348) hide show
  1. {dirsql-0.4.83 → dirsql-0.4.84}/Cargo.lock +2 -2
  2. {dirsql-0.4.83 → dirsql-0.4.84}/PKG-INFO +1 -1
  3. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/_async.py +27 -7
  4. {dirsql-0.4.83/packages/rust → dirsql-0.4.84}/docs/reference/config.md +4 -0
  5. {dirsql-0.4.83 → dirsql-0.4.84}/docs/reference/sdk.md +4 -0
  6. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/Cargo.toml +1 -1
  7. dirsql-0.4.84/packages/python/changelog.d/2026-10-06-watch-broadcast.md +3 -0
  8. dirsql-0.4.84/packages/python/changelog.d/2026-10-06-zero-match-config-table-warning.md +3 -0
  9. {dirsql-0.4.83 → dirsql-0.4.84/packages/python}/docs/reference/config.md +4 -0
  10. {dirsql-0.4.83/packages/rust → dirsql-0.4.84/packages/python}/docs/reference/sdk.md +4 -0
  11. dirsql-0.4.84/packages/python/e2e-attestations/bot-1397-watch-broadcast.json +7 -0
  12. dirsql-0.4.84/packages/python/e2e-attestations/claude-1232-zero-match.json +7 -0
  13. dirsql-0.4.84/packages/python/migrations.d/2026-10-06-watch-broadcast.md +46 -0
  14. dirsql-0.4.84/packages/python/migrations.d/2026-10-06-zero-match-config-table-warning.md +25 -0
  15. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/Cargo.toml +1 -1
  16. {dirsql-0.4.83/packages/python → dirsql-0.4.84/packages/rust}/docs/reference/config.md +4 -0
  17. {dirsql-0.4.83/packages/python → dirsql-0.4.84/packages/rust}/docs/reference/sdk.md +4 -0
  18. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/lib.rs +60 -1
  19. {dirsql-0.4.83 → dirsql-0.4.84}/Cargo.toml +0 -0
  20. {dirsql-0.4.83 → dirsql-0.4.84}/README.md +0 -0
  21. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/__init__.py +0 -0
  22. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/_dirsql.pyi +0 -0
  23. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/cli/__init__.py +0 -0
  24. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/cli/discover_plugins/__init__.py +0 -0
  25. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
  26. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
  27. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
  28. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
  29. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/cli/main.py +0 -0
  30. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/cli/resolve_config_extensions.py +0 -0
  31. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/plan_entry_path.py +0 -0
  32. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/py.typed +0 -0
  33. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/read_config.py +0 -0
  34. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/resolve_configs_extension_specs.py +0 -0
  35. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/resolve_extension.py +0 -0
  36. {dirsql-0.4.83 → dirsql-0.4.84}/dirsql/resolve_package.py +0 -0
  37. {dirsql-0.4.83 → dirsql-0.4.84}/docs/.claude/CLAUDE.md +0 -0
  38. {dirsql-0.4.83 → dirsql-0.4.84}/docs/.vitepress/config.ts +0 -0
  39. {dirsql-0.4.83 → dirsql-0.4.84}/docs/.vitepress/theme/index.ts +0 -0
  40. {dirsql-0.4.83 → dirsql-0.4.84}/docs/.vitepress/theme/lang.ts +0 -0
  41. {dirsql-0.4.83 → dirsql-0.4.84}/docs/AGENTS.md +0 -0
  42. {dirsql-0.4.83 → dirsql-0.4.84}/docs/context/.gitattributes +0 -0
  43. {dirsql-0.4.83 → dirsql-0.4.84}/docs/context/recipes.md +0 -0
  44. {dirsql-0.4.83 → dirsql-0.4.84}/docs/context/troubleshooting.md +0 -0
  45. {dirsql-0.4.83 → dirsql-0.4.84}/docs/context/usage.md +0 -0
  46. {dirsql-0.4.83 → dirsql-0.4.84}/docs/explanation.md +0 -0
  47. {dirsql-0.4.83 → dirsql-0.4.84}/docs/getting-started.md +0 -0
  48. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/agent-skill.md +0 -0
  49. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/columns-from-paths.md +0 -0
  50. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/define-tables.md +0 -0
  51. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/embed.md +0 -0
  52. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/extract-from-contents.md +0 -0
  53. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/load-extension.md +0 -0
  54. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/parse-files-into-columns.md +0 -0
  55. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/persist.md +0 -0
  56. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/query-json.md +0 -0
  57. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/query-without-config.md +0 -0
  58. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/react-to-changes.md +0 -0
  59. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/search-by-meaning.md +0 -0
  60. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/search-indexes.md +0 -0
  61. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/skip-files.md +0 -0
  62. {dirsql-0.4.83 → dirsql-0.4.84}/docs/howto/write-a-plugin.md +0 -0
  63. {dirsql-0.4.83 → dirsql-0.4.84}/docs/index.md +0 -0
  64. {dirsql-0.4.83 → dirsql-0.4.84}/docs/package.json +0 -0
  65. {dirsql-0.4.83 → dirsql-0.4.84}/docs/plugins.md +0 -0
  66. {dirsql-0.4.83 → dirsql-0.4.84}/docs/pnpm-lock.yaml +0 -0
  67. {dirsql-0.4.83 → dirsql-0.4.84}/docs/pnpm-workspace.yaml +0 -0
  68. {dirsql-0.4.83 → dirsql-0.4.84}/docs/reference/cli.md +0 -0
  69. {dirsql-0.4.83 → dirsql-0.4.84}/docs/reference/columns.md +0 -0
  70. {dirsql-0.4.83 → dirsql-0.4.84}/docs/reference/hooks.md +0 -0
  71. {dirsql-0.4.83 → dirsql-0.4.84}/docs/reference/http-api.md +0 -0
  72. {dirsql-0.4.83 → dirsql-0.4.84}/docs/reference/path-tables.md +0 -0
  73. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/CHANGELOG.md +0 -0
  74. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/MIGRATIONS.md +0 -0
  75. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/README.md +0 -0
  76. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  77. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
  78. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  79. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
  80. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  81. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
  82. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
  83. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
  84. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  85. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
  86. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
  87. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
  88. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
  89. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
  90. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
  91. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
  92. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
  93. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
  94. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
  95. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
  96. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
  97. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
  98. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
  99. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
  100. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
  101. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
  102. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
  103. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
  104. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  105. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  106. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-02-readme-docs-host.md +0 -0
  107. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  108. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-03-path-table-directory-one-level.md +0 -0
  109. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  110. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  111. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-cli-context.md +0 -0
  112. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-gitignore-requires-repo.md +0 -0
  113. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-path-table-node-modules-named.md +0 -0
  114. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-path-table-symlinks.md +0 -0
  115. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-path-table-trailing-slash.md +0 -0
  116. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
  117. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-06-plugin-no-default-records.md +0 -0
  118. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/changelog.d/README.md +0 -0
  119. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/conftest.py +0 -0
  120. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/.claude/CLAUDE.md +0 -0
  121. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/.vitepress/config.ts +0 -0
  122. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/.vitepress/theme/index.ts +0 -0
  123. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
  124. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/AGENTS.md +0 -0
  125. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/context/.gitattributes +0 -0
  126. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/context/recipes.md +0 -0
  127. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/context/troubleshooting.md +0 -0
  128. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/context/usage.md +0 -0
  129. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/explanation.md +0 -0
  130. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/getting-started.md +0 -0
  131. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/agent-skill.md +0 -0
  132. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/columns-from-paths.md +0 -0
  133. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/define-tables.md +0 -0
  134. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/embed.md +0 -0
  135. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/extract-from-contents.md +0 -0
  136. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/load-extension.md +0 -0
  137. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
  138. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/persist.md +0 -0
  139. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/query-json.md +0 -0
  140. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/query-without-config.md +0 -0
  141. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/react-to-changes.md +0 -0
  142. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/search-by-meaning.md +0 -0
  143. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/search-indexes.md +0 -0
  144. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/skip-files.md +0 -0
  145. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/howto/write-a-plugin.md +0 -0
  146. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/index.md +0 -0
  147. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/package.json +0 -0
  148. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/plugins.md +0 -0
  149. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/pnpm-lock.yaml +0 -0
  150. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/pnpm-workspace.yaml +0 -0
  151. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/reference/cli.md +0 -0
  152. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/reference/columns.md +0 -0
  153. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/reference/hooks.md +0 -0
  154. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/reference/http-api.md +0 -0
  155. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/docs/reference/path-tables.md +0 -0
  156. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
  157. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
  158. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
  159. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
  160. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
  161. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
  162. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
  163. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
  164. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
  165. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
  166. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
  167. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
  168. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
  169. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
  170. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
  171. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
  172. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
  173. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
  174. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
  175. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
  176. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
  177. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
  178. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
  179. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
  180. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1196-join-index.json +0 -0
  181. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1199-glob-prefix.json +0 -0
  182. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1201-single-walk.json +0 -0
  183. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1204-embed-batch.json +0 -0
  184. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +0 -0
  185. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +0 -0
  186. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1215-on-file-batch.json +0 -0
  187. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1216-on-file-cleanup.json +0 -0
  188. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1223-config-glob-rule.json +0 -0
  189. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1223-dir-one-level.json +0 -0
  190. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1225-plugin-no-default.json +0 -0
  191. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1226-stale-docs.json +0 -0
  192. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1232-anchor-plumbing.json +0 -0
  193. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1232-config-anchor.json +0 -0
  194. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1232-multi-watch.json +0 -0
  195. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1238-parallel-walk.json +0 -0
  196. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1241-content-prefetch.json +0 -0
  197. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1243-ingest-perf.json +0 -0
  198. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1249-dotfiles.json +0 -0
  199. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1256-symlinks.json +0 -0
  200. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1257-trailing-slash.json +0 -0
  201. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1262-brace-literal.json +0 -0
  202. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1264-context.json +0 -0
  203. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1267-posix-classes.json +0 -0
  204. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1269-utf8-chars.json +0 -0
  205. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1271-node-modules-named.json +0 -0
  206. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1272-ancestor-gitignore.json +0 -0
  207. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1273-walk-prune.json +0 -0
  208. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1285-ingest-fast.json +0 -0
  209. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1286-nested-repo.json +0 -0
  210. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1305-glob-speed.json +0 -0
  211. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1308-glob-speed.json +0 -0
  212. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1310-glob-speed.json +0 -0
  213. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1311-glob-speed.json +0 -0
  214. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1312-glob-speed.json +0 -0
  215. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1318-lazy-stat.json +0 -0
  216. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1320-walk-speed.json +0 -0
  217. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1322-walk-readdir.json +0 -0
  218. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1325-parallel-walk.json +0 -0
  219. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1326-stream-rows.json +0 -0
  220. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-python-dirsql-patch.json +0 -0
  221. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-python-extensions-patch.json +0 -0
  222. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-scanner-effects.json +0 -0
  223. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-scanner-gitignore.json +0 -0
  224. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-vtab-read.json +0 -0
  225. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1351-dot-dirs.json +0 -0
  226. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
  227. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
  228. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
  229. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
  230. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
  231. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
  232. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
  233. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
  234. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
  235. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
  236. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
  237. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
  238. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
  239. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
  240. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
  241. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  242. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  243. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  244. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
  245. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
  246. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
  247. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  248. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
  249. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
  250. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
  251. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  252. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  253. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-02-readme-docs-host.md +0 -0
  254. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  255. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-03-path-table-directory-one-level.md +0 -0
  256. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  257. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  258. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-cli-context.md +0 -0
  259. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md +0 -0
  260. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-path-table-node-modules-named.md +0 -0
  261. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-path-table-symlinks.md +0 -0
  262. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-path-table-trailing-slash.md +0 -0
  263. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
  264. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-06-plugin-no-default-records.md +0 -0
  265. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/migrations.d/README.md +0 -0
  266. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/src/lib.rs +0 -0
  267. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/testing-conventions.toml +0 -0
  268. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/__init__.py +0 -0
  269. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/conftest.py +0 -0
  270. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/e2e/__init__.py +0 -0
  271. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
  272. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
  273. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/e2e/speed_of_light.py +0 -0
  274. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/integration/__init__.py +0 -0
  275. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/integration/binding/__init__.py +0 -0
  276. {dirsql-0.4.83 → dirsql-0.4.84}/packages/python/tests/integration/hermetic/__init__.py +0 -0
  277. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/CHANGELOG.md +0 -0
  278. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/MIGRATIONS.md +0 -0
  279. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/README.md +0 -0
  280. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/benches/db_bench.rs +0 -0
  281. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/benches/differ_bench.rs +0 -0
  282. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/benches/matcher_bench.rs +0 -0
  283. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/benches/scanner_bench.rs +0 -0
  284. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/context/.gitattributes +0 -0
  285. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/context/recipes.md +0 -0
  286. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/context/troubleshooting.md +0 -0
  287. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/context/usage.md +0 -0
  288. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/explanation.md +0 -0
  289. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/getting-started.md +0 -0
  290. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/agent-skill.md +0 -0
  291. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/columns-from-paths.md +0 -0
  292. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/define-tables.md +0 -0
  293. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/embed.md +0 -0
  294. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/extract-from-contents.md +0 -0
  295. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/load-extension.md +0 -0
  296. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
  297. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/persist.md +0 -0
  298. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/query-json.md +0 -0
  299. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/query-without-config.md +0 -0
  300. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/react-to-changes.md +0 -0
  301. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/search-by-meaning.md +0 -0
  302. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/search-indexes.md +0 -0
  303. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/skip-files.md +0 -0
  304. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/howto/write-a-plugin.md +0 -0
  305. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/index.md +0 -0
  306. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/plugins.md +0 -0
  307. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/reference/cli.md +0 -0
  308. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/reference/columns.md +0 -0
  309. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/reference/hooks.md +0 -0
  310. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/reference/http-api.md +0 -0
  311. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/docs/reference/path-tables.md +0 -0
  312. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/bin/dirsql.rs +0 -0
  313. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/brace.rs +0 -0
  314. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/context.rs +0 -0
  315. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/execute.rs +0 -0
  316. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/init.rs +0 -0
  317. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/mod.rs +0 -0
  318. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/repl.rs +0 -0
  319. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/router.rs +0 -0
  320. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/run.rs +0 -0
  321. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/serialize.rs +0 -0
  322. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/server.rs +0 -0
  323. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/cli/table.rs +0 -0
  324. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/command.rs +0 -0
  325. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/config.rs +0 -0
  326. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/db.rs +0 -0
  327. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/default_config.toml +0 -0
  328. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/differ.rs +0 -0
  329. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/extension_resolution.rs +0 -0
  330. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/functions.rs +0 -0
  331. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/infer.rs +0 -0
  332. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/launcher.rs +0 -0
  333. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/listing.rs +0 -0
  334. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/matcher.rs +0 -0
  335. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/on_file.rs +0 -0
  336. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/parsed_vtab.rs +0 -0
  337. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/path_table.rs +0 -0
  338. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/persist.rs +0 -0
  339. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/posix_class.rs +0 -0
  340. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/progress.rs +0 -0
  341. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/row_event_flat.rs +0 -0
  342. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/scanner.rs +0 -0
  343. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/sql_literal.rs +0 -0
  344. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/tree_walk.rs +0 -0
  345. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/vtab.rs +0 -0
  346. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/vtab_scaffold.rs +0 -0
  347. {dirsql-0.4.83 → dirsql-0.4.84}/packages/rust/src/watcher.rs +0 -0
  348. {dirsql-0.4.83 → dirsql-0.4.84}/pyproject.toml +0 -0
@@ -552,7 +552,7 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
552
552
 
553
553
  [[package]]
554
554
  name = "dirsql"
555
- version = "0.4.83"
555
+ version = "0.4.84"
556
556
  dependencies = [
557
557
  "assert_cmd",
558
558
  "axum",
@@ -602,7 +602,7 @@ dependencies = [
602
602
 
603
603
  [[package]]
604
604
  name = "dirsql-py-ext"
605
- version = "0.4.83"
605
+ version = "0.4.84"
606
606
  dependencies = [
607
607
  "dirsql",
608
608
  "pyo3",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirsql
3
- Version: 0.4.83
3
+ Version: 0.4.84
4
4
  Requires-Dist: bin-shim>=0.1
5
5
  Summary: Ephemeral SQL index over a local directory
6
6
  Keywords: sql,filesystem,directory,sqlite,index
@@ -2,6 +2,7 @@
2
2
 
3
3
  import asyncio
4
4
  import os
5
+ import weakref
5
6
 
6
7
  from dirsql._dirsql import DirSQL as _RustDirSQL
7
8
  from dirsql.resolve_configs_extension_specs import resolve_configs_extension_specs
@@ -9,13 +10,18 @@ from dirsql.resolve_extension import resolve_extension_path
9
10
 
10
11
 
11
12
  class _WatchStream:
12
- """Async iterator that polls for file events."""
13
+ """Async iterator of file events.
14
+
15
+ Every stream on one ``DirSQL`` receives every event observed after it
16
+ was created: one shared poll fills the buffer of each live stream.
17
+ """
13
18
 
14
19
  def __init__(self, owner):
15
20
  self._owner = owner
16
21
  self._db = None
17
22
  self._started = False
18
23
  self._buffer = []
24
+ owner._watch_streams.add(self)
19
25
 
20
26
  def __aiter__(self):
21
27
  return self
@@ -29,14 +35,22 @@ class _WatchStream:
29
35
  await asyncio.to_thread(db._start_watcher)
30
36
  self._started = True
31
37
 
38
+ owner = self._owner
39
+ while not self._buffer:
40
+ poll = owner._watch_poll
41
+ if poll is None or poll.done():
42
+ poll = owner._watch_poll = asyncio.ensure_future(self._poll())
43
+ # Shielded so a cancelled consumer cannot drop a batch that the
44
+ # other streams are still waiting on.
45
+ await asyncio.shield(poll)
46
+ return self._buffer.pop(0)
47
+
48
+ async def _poll(self):
32
49
  db = self._db
33
50
  assert db is not None
34
- while True:
35
- if self._buffer:
36
- return self._buffer.pop(0)
37
- events = await asyncio.to_thread(db._poll_events, 200)
38
- if events:
39
- self._buffer.extend(events)
51
+ events = await asyncio.to_thread(db._poll_events, 200)
52
+ for stream in list(self._owner._watch_streams):
53
+ stream._buffer.extend(events)
40
54
 
41
55
 
42
56
  class DirSQL:
@@ -107,6 +121,8 @@ class DirSQL:
107
121
  self._db = None
108
122
  self._ready_event = asyncio.Event()
109
123
  self._init_error = None
124
+ self._watch_streams = weakref.WeakSet()
125
+ self._watch_poll = None
110
126
  self._task = asyncio.ensure_future(self._init_bg())
111
127
 
112
128
  async def _init_bg(self):
@@ -218,5 +234,9 @@ class DirSQL:
218
234
  before an explicit ``await db.ready()`` waits for the background scan
219
235
  (and surfaces any initialization error) instead of failing on a
220
236
  still-``None`` ``_db``.
237
+
238
+ Each call returns an independent stream, and every stream receives
239
+ every event observed after it was created, so several consumers
240
+ (one per client, say) can share one instance.
221
241
  """
222
242
  return _WatchStream(self)
@@ -274,6 +274,10 @@ So `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes
274
274
  writes `glob = "~/.claude/projects/*/*.jsonl"`. A table's `path` and `dir`
275
275
  columns, `{root}`, and `ignore` are all relative to its anchor.
276
276
 
277
+ A table whose glob matches no files prints
278
+ `dirsql: table 'sessions': glob 'projects/*/*.jsonl' matched no files under <anchor>`
279
+ to stderr; the exit code is unchanged. Path-tables and programmatic tables do not warn.
280
+
277
281
  ### Batch `ddl`
278
282
 
279
283
  `ddl` is handed to SQLite whole, so a table declaration is not limited to one
@@ -301,6 +301,10 @@ under the root. The watcher starts on first iteration (Python/TypeScript)
301
301
  or at the `watch()` call (Rust). The stream never terminates on its own;
302
302
  stop consuming it to stop.
303
303
 
304
+ Python: each `watch()` call returns an independent stream, and every stream
305
+ on one instance receives every event observed after it was created, so
306
+ several consumers (one per client, say) can share one instance.
307
+
304
308
  Rust: `watch()` may be called once per instance and is mutually exclusive
305
309
  with the polling API below — mixing them returns an error, since both drain
306
310
  the same underlying filesystem watcher.
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
4
4
  # pypi/maturin handler can rewrite it via `write-version` before
5
5
  # `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
6
6
  # and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
7
- version = "0.4.83"
7
+ version = "0.4.84"
8
8
  # abi3 note: the `abi3-py310` pyo3 feature (below) builds ONE stable-ABI
9
9
  # `cp310-abi3` wheel per platform that loads on every CPython >= 3.10
10
10
  # (matching `pyproject.toml`'s `requires-python = ">=3.10"`), instead of
@@ -0,0 +1,3 @@
1
+ **Fixed**
2
+
3
+ - **Every `DirSQL.watch()` stream on one instance now receives every event.** Two or more streams (for example one per connected client) previously split the events between them; now each stream gets every event observed after it was created. (#1397)
@@ -0,0 +1,3 @@
1
+ **Added**
2
+
3
+ - **A config `[[table]]` whose glob matches no files now prints a warning to stderr.** `dirsql: table 'sessions': glob 'projects/*/*.jsonl' matched no files under /home/u/.claude` names the table, the glob and the directory it was matched under, so a glob that silently indexes nothing is visible. The exit code is unchanged, and path-tables and programmatic tables do not warn. (#1232)
@@ -274,6 +274,10 @@ So `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes
274
274
  writes `glob = "~/.claude/projects/*/*.jsonl"`. A table's `path` and `dir`
275
275
  columns, `{root}`, and `ignore` are all relative to its anchor.
276
276
 
277
+ A table whose glob matches no files prints
278
+ `dirsql: table 'sessions': glob 'projects/*/*.jsonl' matched no files under <anchor>`
279
+ to stderr; the exit code is unchanged. Path-tables and programmatic tables do not warn.
280
+
277
281
  ### Batch `ddl`
278
282
 
279
283
  `ddl` is handed to SQLite whole, so a table declaration is not limited to one
@@ -301,6 +301,10 @@ under the root. The watcher starts on first iteration (Python/TypeScript)
301
301
  or at the `watch()` call (Rust). The stream never terminates on its own;
302
302
  stop consuming it to stop.
303
303
 
304
+ Python: each `watch()` call returns an independent stream, and every stream
305
+ on one instance receives every event observed after it was created, so
306
+ several consumers (one per client, say) can share one instance.
307
+
304
308
  Rust: `watch()` may be called once per instance and is mutually exclusive
305
309
  with the polling API below — mixing them returns an error, since both drain
306
310
  the same underlying filesystem watcher.
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/on_file_query_test.py tests/e2e/fanout_test.py tests/e2e/query_contract_test.py tests/integration/binding/async_dirsql_test.py -x -q",
3
+ "ran_at": 1791309204,
4
+ "exit_code": 0,
5
+ "commit": "9a473a8812b974362a7c408132a9724aac50605a",
6
+ "branch": "bot/1397-watch-broadcast"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/fanout_test.py tests/e2e/capture_collision_test.py tests/e2e/declared_table_name_test.py tests/e2e/extension_package_test.py tests/e2e/plugin_discovery_test.py tests/e2e/use_case_notebook_test.py tests/e2e/on_file_query_test.py tests/e2e/use_case_transcripts_test.py tests/e2e/plugin_extension_discovery_test.py tests/e2e/use_case_join_test.py tests/e2e/use_case_dossier_test.py tests/e2e/sigint_interrupt_test.py tests/e2e/query_contract_test.py -x -q",
3
+ "ran_at": 1791306078,
4
+ "exit_code": 0,
5
+ "commit": "8b587de39902adf33e4ebaa957a8fd0005875029",
6
+ "branch": "claude/1232-zero-match"
7
+ }
@@ -0,0 +1,46 @@
1
+ ### Every Python `watch()` stream receives every event (#1397)
2
+
3
+ #### Summary
4
+
5
+ Several `DirSQL.watch()` streams on one Python instance each receive every event, instead of splitting them. A single stream behaves as before. Nothing breaks.
6
+
7
+ #### Required changes
8
+
9
+ _None._
10
+
11
+ #### Deprecations removed
12
+
13
+ _None._
14
+
15
+ #### Behavior changes without code changes
16
+
17
+ - With more than one `watch()` stream on one instance, each stream now yields every event observed after it was created. Code that hand-rolled fan-out over one stream keeps working.
18
+
19
+ #### Verification
20
+
21
+ ```python
22
+ import asyncio, pathlib, tempfile
23
+ from dirsql import DirSQL, Table
24
+
25
+ async def main():
26
+ root = pathlib.Path(tempfile.mkdtemp())
27
+ table = Table(
28
+ name="files",
29
+ ddl="CREATE TABLE files (n INTEGER)",
30
+ glob="*.json",
31
+ on_file=lambda path: [{"n": 1}],
32
+ )
33
+ db = DirSQL(str(root), tables=[table])
34
+ await db.ready()
35
+
36
+ async def first(stream):
37
+ async for event in stream:
38
+ return event.action
39
+
40
+ tasks = [asyncio.create_task(first(db.watch())) for _ in range(2)]
41
+ await asyncio.sleep(0.3)
42
+ (root / "a.json").write_text("{}")
43
+ print(await asyncio.wait_for(asyncio.gather(*tasks), 5)) # ['insert', 'insert']
44
+
45
+ asyncio.run(main())
46
+ ```
@@ -0,0 +1,25 @@
1
+ ### Empty config tables warn on stderr (#1232)
2
+
3
+ #### Summary
4
+
5
+ A config `[[table]]` whose glob matches no files writes one line to stderr at startup. Nothing else changes: the query still runs and the exit code is the same.
6
+
7
+ #### Required changes
8
+
9
+ _None._ A script that treats any stderr output as failure should fix the glob or drop the table.
10
+
11
+ #### Deprecations removed
12
+
13
+ _None._
14
+
15
+ #### Behavior changes without code changes
16
+
17
+ - stderr gains `dirsql: table '<name>': glob '<glob>' matched no files under <anchor>` for each config table that matched nothing.
18
+
19
+ #### Verification
20
+
21
+ ```bash
22
+ mkdir -p /tmp/cfg /tmp/elsewhere
23
+ printf '[[table]]\nname = "t"\nddl = "CREATE TABLE t (n TEXT)"\nglob = "nothing/*.jsonl"\non-file = "printf []"\n' > /tmp/cfg/.dirsql.toml
24
+ cd /tmp/elsewhere && dirsql query "SELECT COUNT(*) AS n FROM t" -c /tmp/cfg/.dirsql.toml # stderr: dirsql: table 't': glob 'nothing/*.jsonl' matched no files under /tmp/cfg
25
+ ```
@@ -6,7 +6,7 @@ description = "Ephemeral SQL index over a local directory"
6
6
  # version stays for the binding crates (publish = false). The literal
7
7
  # intentionally lags the published version: putitoutthere rewrites it to
8
8
  # the planned release version at build time and never commits it back.
9
- version = "0.4.83"
9
+ version = "0.4.84"
10
10
  edition.workspace = true
11
11
  # Literal `license` (not `license.workspace = true`) because
12
12
  # putitoutthere's preflight check reads `[package].license` directly
@@ -274,6 +274,10 @@ So `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes
274
274
  writes `glob = "~/.claude/projects/*/*.jsonl"`. A table's `path` and `dir`
275
275
  columns, `{root}`, and `ignore` are all relative to its anchor.
276
276
 
277
+ A table whose glob matches no files prints
278
+ `dirsql: table 'sessions': glob 'projects/*/*.jsonl' matched no files under <anchor>`
279
+ to stderr; the exit code is unchanged. Path-tables and programmatic tables do not warn.
280
+
277
281
  ### Batch `ddl`
278
282
 
279
283
  `ddl` is handed to SQLite whole, so a table declaration is not limited to one
@@ -301,6 +301,10 @@ under the root. The watcher starts on first iteration (Python/TypeScript)
301
301
  or at the `watch()` call (Rust). The stream never terminates on its own;
302
302
  stop consuming it to stop.
303
303
 
304
+ Python: each `watch()` call returns an independent stream, and every stream
305
+ on one instance receives every event observed after it was created, so
306
+ several consumers (one per client, say) can share one instance.
307
+
304
308
  Rust: `watch()` may be called once per instance and is mutually exclusive
305
309
  with the polling API below — mixing them returns an error, since both drain
306
310
  the same underlying filesystem watcher.
@@ -285,6 +285,7 @@ pub struct Table {
285
285
  hook: Hook,
286
286
  anchor: Option<PathBuf>,
287
287
  ignore: Vec<String>,
288
+ warn_when_empty: bool,
288
289
  }
289
290
 
290
291
  impl Table {
@@ -298,6 +299,11 @@ impl Table {
298
299
  &self.ignore
299
300
  }
300
301
 
302
+ pub(crate) fn warning_when_empty(mut self) -> Self {
303
+ self.warn_when_empty = true;
304
+ self
305
+ }
306
+
301
307
  pub(crate) fn scoped_ignore(mut self, ignore: Vec<String>) -> Self {
302
308
  self.ignore = ignore;
303
309
  self
@@ -354,6 +360,7 @@ impl Table {
354
360
  strict: false,
355
361
  anchor: None,
356
362
  ignore: Vec::new(),
363
+ warn_when_empty: false,
357
364
  }
358
365
  }
359
366
 
@@ -400,6 +407,7 @@ impl Table {
400
407
  strict: false,
401
408
  anchor: None,
402
409
  ignore: Vec::new(),
410
+ warn_when_empty: false,
403
411
  }
404
412
  }
405
413
  }
@@ -1128,6 +1136,9 @@ impl DirSQL {
1128
1136
  let mut progress = Progress::scanning();
1129
1137
  let (scanned, seen) = scan_groups(&groups, scan, &mut progress);
1130
1138
  progress.finish(seen);
1139
+ for warning in empty_table_warnings(&tables, &anchors, &scanned) {
1140
+ eprintln!("{warning}");
1141
+ }
1131
1142
  scanned
1132
1143
  };
1133
1144
 
@@ -2019,6 +2030,28 @@ fn compile_groups(
2019
2030
  Ok((groups, anchors, names))
2020
2031
  }
2021
2032
 
2033
+ /// One stderr line per config table that matched no file in the scan, naming
2034
+ /// the table, its glob and the directory the glob was matched under.
2035
+ fn empty_table_warnings(
2036
+ tables: &[Table],
2037
+ anchors: &TableAnchors,
2038
+ scanned: &[(PathBuf, String)],
2039
+ ) -> Vec<String> {
2040
+ tables
2041
+ .iter()
2042
+ .filter(|table| table.warn_when_empty)
2043
+ .filter(|table| !scanned.iter().any(|(_, name)| *name == table.name))
2044
+ .map(|table| {
2045
+ format!(
2046
+ "dirsql: table '{}': glob '{}' matched no files under {}",
2047
+ table.name,
2048
+ table.glob,
2049
+ anchors.of(&table.name).display()
2050
+ )
2051
+ })
2052
+ .collect()
2053
+ }
2054
+
2022
2055
  /// Open (or create) the persistent SQLite cache and read its meta. If the
2023
2056
  /// meta is missing or incompatible with the current build, the resulting
2024
2057
  /// [`PersistContext`] carries an empty file index and asks for a sweep, so
@@ -2423,7 +2456,8 @@ fn build_tables_from_config(cfg: &config::Config, config_dir: &Path) -> Result<V
2423
2456
  },
2424
2457
  )
2425
2458
  .anchored(anchor)
2426
- .scoped_ignore(cfg.ignore.clone());
2459
+ .scoped_ignore(cfg.ignore.clone())
2460
+ .warning_when_empty();
2427
2461
 
2428
2462
  if table_cfg.strict == Some(true) {
2429
2463
  table.strict = true;
@@ -5451,6 +5485,31 @@ mod internal_tests {
5451
5485
  assert!(matches!(err, DirSqlError::DuplicateTable(ref name) if name == "a"));
5452
5486
  }
5453
5487
 
5488
+ #[test]
5489
+ fn an_empty_warning_table_is_named_with_its_glob_and_anchor() {
5490
+ let tables = vec![anchored_table("a", "*.txt", "/one").warning_when_empty()];
5491
+ let anchors = compile_groups(&tables, &[], Path::new("/idx")).unwrap().1;
5492
+ assert_eq!(
5493
+ empty_table_warnings(&tables, &anchors, &[]),
5494
+ vec!["dirsql: table 'a': glob '*.txt' matched no files under /one".to_string()]
5495
+ );
5496
+ }
5497
+
5498
+ #[test]
5499
+ fn a_table_with_a_matched_file_does_not_warn() {
5500
+ let tables = vec![anchored_table("a", "*.txt", "/one").warning_when_empty()];
5501
+ let anchors = compile_groups(&tables, &[], Path::new("/idx")).unwrap().1;
5502
+ let scanned = vec![(PathBuf::from("/one/x.txt"), "a".to_string())];
5503
+ assert!(empty_table_warnings(&tables, &anchors, &scanned).is_empty());
5504
+ }
5505
+
5506
+ #[test]
5507
+ fn a_programmatic_empty_table_does_not_warn() {
5508
+ let tables = vec![anchored_table("a", "*.txt", "/one")];
5509
+ let anchors = compile_groups(&tables, &[], Path::new("/idx")).unwrap().1;
5510
+ assert!(empty_table_warnings(&tables, &anchors, &[]).is_empty());
5511
+ }
5512
+
5454
5513
  #[test]
5455
5514
  fn anchors_of_an_unknown_table_is_the_index_root() {
5456
5515
  let anchors = TableAnchors::at_root(Path::new("/idx"));
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes