dirsql 0.4.83__tar.gz → 0.4.85__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 (354) hide show
  1. {dirsql-0.4.83 → dirsql-0.4.85}/Cargo.lock +2 -2
  2. {dirsql-0.4.83 → dirsql-0.4.85}/PKG-INFO +1 -1
  3. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/_async.py +27 -7
  4. {dirsql-0.4.83/packages/rust → dirsql-0.4.85}/docs/reference/config.md +4 -0
  5. {dirsql-0.4.83/packages/rust → dirsql-0.4.85}/docs/reference/http-api.md +1 -1
  6. {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/sdk.md +4 -0
  7. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/Cargo.toml +1 -1
  8. dirsql-0.4.85/packages/python/changelog.d/2026-10-06-one-glob-compiler.md +3 -0
  9. dirsql-0.4.85/packages/python/changelog.d/2026-10-06-watch-broadcast.md +3 -0
  10. dirsql-0.4.85/packages/python/changelog.d/2026-10-06-zero-match-config-table-warning.md +3 -0
  11. {dirsql-0.4.83 → dirsql-0.4.85/packages/python}/docs/reference/config.md +4 -0
  12. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/http-api.md +1 -1
  13. {dirsql-0.4.83/packages/rust → dirsql-0.4.85/packages/python}/docs/reference/sdk.md +4 -0
  14. dirsql-0.4.85/packages/python/e2e-attestations/bot-1397-watch-broadcast.json +7 -0
  15. dirsql-0.4.85/packages/python/e2e-attestations/bot-1398-inotify-error.json +7 -0
  16. dirsql-0.4.85/packages/python/e2e-attestations/bot-1407-child-place-depth.json +7 -0
  17. dirsql-0.4.85/packages/python/e2e-attestations/claude-1232-zero-match.json +7 -0
  18. dirsql-0.4.85/packages/python/e2e-attestations/claude-1258-one-pattern.json +7 -0
  19. dirsql-0.4.85/packages/python/e2e-attestations/claude-1330-vtab-prefetch-flag.json +7 -0
  20. dirsql-0.4.85/packages/python/migrations.d/2026-10-06-one-glob-compiler.md +28 -0
  21. dirsql-0.4.85/packages/python/migrations.d/2026-10-06-watch-broadcast.md +46 -0
  22. dirsql-0.4.85/packages/python/migrations.d/2026-10-06-zero-match-config-table-warning.md +25 -0
  23. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/Cargo.toml +1 -1
  24. {dirsql-0.4.83/packages/python → dirsql-0.4.85/packages/rust}/docs/reference/config.md +4 -0
  25. {dirsql-0.4.83 → dirsql-0.4.85/packages/rust}/docs/reference/http-api.md +1 -1
  26. {dirsql-0.4.83/packages/python → dirsql-0.4.85/packages/rust}/docs/reference/sdk.md +4 -0
  27. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/router.rs +19 -0
  28. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/server.rs +39 -11
  29. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/lib.rs +69 -5
  30. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/matcher.rs +3 -2
  31. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/scanner.rs +29 -0
  32. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/vtab_scaffold.rs +1 -1
  33. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/watcher.rs +74 -2
  34. {dirsql-0.4.83 → dirsql-0.4.85}/Cargo.toml +0 -0
  35. {dirsql-0.4.83 → dirsql-0.4.85}/README.md +0 -0
  36. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/__init__.py +0 -0
  37. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/_dirsql.pyi +0 -0
  38. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/__init__.py +0 -0
  39. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/__init__.py +0 -0
  40. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
  41. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
  42. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
  43. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
  44. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/main.py +0 -0
  45. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/cli/resolve_config_extensions.py +0 -0
  46. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/plan_entry_path.py +0 -0
  47. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/py.typed +0 -0
  48. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/read_config.py +0 -0
  49. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/resolve_configs_extension_specs.py +0 -0
  50. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/resolve_extension.py +0 -0
  51. {dirsql-0.4.83 → dirsql-0.4.85}/dirsql/resolve_package.py +0 -0
  52. {dirsql-0.4.83 → dirsql-0.4.85}/docs/.claude/CLAUDE.md +0 -0
  53. {dirsql-0.4.83 → dirsql-0.4.85}/docs/.vitepress/config.ts +0 -0
  54. {dirsql-0.4.83 → dirsql-0.4.85}/docs/.vitepress/theme/index.ts +0 -0
  55. {dirsql-0.4.83 → dirsql-0.4.85}/docs/.vitepress/theme/lang.ts +0 -0
  56. {dirsql-0.4.83 → dirsql-0.4.85}/docs/AGENTS.md +0 -0
  57. {dirsql-0.4.83 → dirsql-0.4.85}/docs/context/.gitattributes +0 -0
  58. {dirsql-0.4.83 → dirsql-0.4.85}/docs/context/recipes.md +0 -0
  59. {dirsql-0.4.83 → dirsql-0.4.85}/docs/context/troubleshooting.md +0 -0
  60. {dirsql-0.4.83 → dirsql-0.4.85}/docs/context/usage.md +0 -0
  61. {dirsql-0.4.83 → dirsql-0.4.85}/docs/explanation.md +0 -0
  62. {dirsql-0.4.83 → dirsql-0.4.85}/docs/getting-started.md +0 -0
  63. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/agent-skill.md +0 -0
  64. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/columns-from-paths.md +0 -0
  65. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/define-tables.md +0 -0
  66. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/embed.md +0 -0
  67. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/extract-from-contents.md +0 -0
  68. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/load-extension.md +0 -0
  69. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/parse-files-into-columns.md +0 -0
  70. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/persist.md +0 -0
  71. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/query-json.md +0 -0
  72. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/query-without-config.md +0 -0
  73. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/react-to-changes.md +0 -0
  74. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/search-by-meaning.md +0 -0
  75. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/search-indexes.md +0 -0
  76. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/skip-files.md +0 -0
  77. {dirsql-0.4.83 → dirsql-0.4.85}/docs/howto/write-a-plugin.md +0 -0
  78. {dirsql-0.4.83 → dirsql-0.4.85}/docs/index.md +0 -0
  79. {dirsql-0.4.83 → dirsql-0.4.85}/docs/package.json +0 -0
  80. {dirsql-0.4.83 → dirsql-0.4.85}/docs/plugins.md +0 -0
  81. {dirsql-0.4.83 → dirsql-0.4.85}/docs/pnpm-lock.yaml +0 -0
  82. {dirsql-0.4.83 → dirsql-0.4.85}/docs/pnpm-workspace.yaml +0 -0
  83. {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/cli.md +0 -0
  84. {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/columns.md +0 -0
  85. {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/hooks.md +0 -0
  86. {dirsql-0.4.83 → dirsql-0.4.85}/docs/reference/path-tables.md +0 -0
  87. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/CHANGELOG.md +0 -0
  88. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/MIGRATIONS.md +0 -0
  89. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/README.md +0 -0
  90. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  91. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
  92. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  93. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
  94. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  95. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
  96. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
  97. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
  98. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  99. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
  100. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
  101. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
  102. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
  103. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
  104. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
  105. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
  106. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
  107. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
  108. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
  109. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
  110. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
  111. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
  112. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
  113. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
  114. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
  115. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
  116. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
  117. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
  118. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  119. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  120. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-02-readme-docs-host.md +0 -0
  121. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  122. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-03-path-table-directory-one-level.md +0 -0
  123. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  124. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  125. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-cli-context.md +0 -0
  126. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-gitignore-requires-repo.md +0 -0
  127. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-path-table-node-modules-named.md +0 -0
  128. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-path-table-symlinks.md +0 -0
  129. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-05-path-table-trailing-slash.md +0 -0
  130. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
  131. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/2026-10-06-plugin-no-default-records.md +0 -0
  132. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/changelog.d/README.md +0 -0
  133. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/conftest.py +0 -0
  134. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/.claude/CLAUDE.md +0 -0
  135. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/.vitepress/config.ts +0 -0
  136. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/.vitepress/theme/index.ts +0 -0
  137. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
  138. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/AGENTS.md +0 -0
  139. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/context/.gitattributes +0 -0
  140. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/context/recipes.md +0 -0
  141. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/context/troubleshooting.md +0 -0
  142. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/context/usage.md +0 -0
  143. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/explanation.md +0 -0
  144. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/getting-started.md +0 -0
  145. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/agent-skill.md +0 -0
  146. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/columns-from-paths.md +0 -0
  147. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/define-tables.md +0 -0
  148. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/embed.md +0 -0
  149. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/extract-from-contents.md +0 -0
  150. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/load-extension.md +0 -0
  151. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
  152. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/persist.md +0 -0
  153. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/query-json.md +0 -0
  154. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/query-without-config.md +0 -0
  155. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/react-to-changes.md +0 -0
  156. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/search-by-meaning.md +0 -0
  157. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/search-indexes.md +0 -0
  158. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/skip-files.md +0 -0
  159. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/howto/write-a-plugin.md +0 -0
  160. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/index.md +0 -0
  161. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/package.json +0 -0
  162. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/plugins.md +0 -0
  163. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/pnpm-lock.yaml +0 -0
  164. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/pnpm-workspace.yaml +0 -0
  165. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/cli.md +0 -0
  166. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/columns.md +0 -0
  167. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/hooks.md +0 -0
  168. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/docs/reference/path-tables.md +0 -0
  169. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
  170. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
  171. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
  172. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
  173. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
  174. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
  175. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
  176. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
  177. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
  178. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
  179. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
  180. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
  181. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
  182. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
  183. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
  184. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
  185. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
  186. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
  187. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
  188. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
  189. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
  190. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
  191. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
  192. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
  193. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1196-join-index.json +0 -0
  194. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1199-glob-prefix.json +0 -0
  195. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1201-single-walk.json +0 -0
  196. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1204-embed-batch.json +0 -0
  197. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +0 -0
  198. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +0 -0
  199. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1215-on-file-batch.json +0 -0
  200. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1216-on-file-cleanup.json +0 -0
  201. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1223-config-glob-rule.json +0 -0
  202. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1223-dir-one-level.json +0 -0
  203. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1225-plugin-no-default.json +0 -0
  204. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1226-stale-docs.json +0 -0
  205. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1232-anchor-plumbing.json +0 -0
  206. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1232-config-anchor.json +0 -0
  207. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1232-multi-watch.json +0 -0
  208. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1238-parallel-walk.json +0 -0
  209. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1241-content-prefetch.json +0 -0
  210. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1243-ingest-perf.json +0 -0
  211. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1249-dotfiles.json +0 -0
  212. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1256-symlinks.json +0 -0
  213. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1257-trailing-slash.json +0 -0
  214. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1262-brace-literal.json +0 -0
  215. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1264-context.json +0 -0
  216. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1267-posix-classes.json +0 -0
  217. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1269-utf8-chars.json +0 -0
  218. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1271-node-modules-named.json +0 -0
  219. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1272-ancestor-gitignore.json +0 -0
  220. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1273-walk-prune.json +0 -0
  221. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1285-ingest-fast.json +0 -0
  222. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1286-nested-repo.json +0 -0
  223. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1305-glob-speed.json +0 -0
  224. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1308-glob-speed.json +0 -0
  225. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1310-glob-speed.json +0 -0
  226. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1311-glob-speed.json +0 -0
  227. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1312-glob-speed.json +0 -0
  228. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1318-lazy-stat.json +0 -0
  229. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1320-walk-speed.json +0 -0
  230. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1322-walk-readdir.json +0 -0
  231. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1325-parallel-walk.json +0 -0
  232. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1326-stream-rows.json +0 -0
  233. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-python-dirsql-patch.json +0 -0
  234. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-python-extensions-patch.json +0 -0
  235. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-scanner-effects.json +0 -0
  236. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-scanner-gitignore.json +0 -0
  237. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1330-vtab-read.json +0 -0
  238. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-1351-dot-dirs.json +0 -0
  239. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
  240. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
  241. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
  242. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
  243. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
  244. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
  245. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
  246. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
  247. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
  248. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
  249. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
  250. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
  251. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
  252. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
  253. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
  254. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  255. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  256. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  257. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
  258. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
  259. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
  260. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  261. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
  262. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
  263. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
  264. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  265. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  266. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-02-readme-docs-host.md +0 -0
  267. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  268. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-03-path-table-directory-one-level.md +0 -0
  269. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  270. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  271. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-cli-context.md +0 -0
  272. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md +0 -0
  273. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-path-table-node-modules-named.md +0 -0
  274. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-path-table-symlinks.md +0 -0
  275. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-05-path-table-trailing-slash.md +0 -0
  276. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
  277. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/2026-10-06-plugin-no-default-records.md +0 -0
  278. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/migrations.d/README.md +0 -0
  279. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/src/lib.rs +0 -0
  280. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/testing-conventions.toml +0 -0
  281. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/__init__.py +0 -0
  282. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/conftest.py +0 -0
  283. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/e2e/__init__.py +0 -0
  284. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
  285. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
  286. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/e2e/speed_of_light.py +0 -0
  287. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/integration/__init__.py +0 -0
  288. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/integration/binding/__init__.py +0 -0
  289. {dirsql-0.4.83 → dirsql-0.4.85}/packages/python/tests/integration/hermetic/__init__.py +0 -0
  290. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/CHANGELOG.md +0 -0
  291. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/MIGRATIONS.md +0 -0
  292. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/README.md +0 -0
  293. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/benches/db_bench.rs +0 -0
  294. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/benches/differ_bench.rs +0 -0
  295. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/benches/matcher_bench.rs +0 -0
  296. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/benches/scanner_bench.rs +0 -0
  297. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/context/.gitattributes +0 -0
  298. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/context/recipes.md +0 -0
  299. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/context/troubleshooting.md +0 -0
  300. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/context/usage.md +0 -0
  301. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/explanation.md +0 -0
  302. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/getting-started.md +0 -0
  303. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/agent-skill.md +0 -0
  304. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/columns-from-paths.md +0 -0
  305. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/define-tables.md +0 -0
  306. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/embed.md +0 -0
  307. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/extract-from-contents.md +0 -0
  308. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/load-extension.md +0 -0
  309. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
  310. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/persist.md +0 -0
  311. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/query-json.md +0 -0
  312. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/query-without-config.md +0 -0
  313. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/react-to-changes.md +0 -0
  314. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/search-by-meaning.md +0 -0
  315. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/search-indexes.md +0 -0
  316. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/skip-files.md +0 -0
  317. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/howto/write-a-plugin.md +0 -0
  318. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/index.md +0 -0
  319. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/plugins.md +0 -0
  320. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/reference/cli.md +0 -0
  321. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/reference/columns.md +0 -0
  322. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/reference/hooks.md +0 -0
  323. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/docs/reference/path-tables.md +0 -0
  324. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/bin/dirsql.rs +0 -0
  325. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/brace.rs +0 -0
  326. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/context.rs +0 -0
  327. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/execute.rs +0 -0
  328. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/init.rs +0 -0
  329. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/mod.rs +0 -0
  330. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/repl.rs +0 -0
  331. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/run.rs +0 -0
  332. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/serialize.rs +0 -0
  333. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/cli/table.rs +0 -0
  334. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/command.rs +0 -0
  335. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/config.rs +0 -0
  336. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/db.rs +0 -0
  337. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/default_config.toml +0 -0
  338. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/differ.rs +0 -0
  339. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/extension_resolution.rs +0 -0
  340. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/functions.rs +0 -0
  341. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/infer.rs +0 -0
  342. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/launcher.rs +0 -0
  343. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/listing.rs +0 -0
  344. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/on_file.rs +0 -0
  345. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/parsed_vtab.rs +0 -0
  346. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/path_table.rs +0 -0
  347. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/persist.rs +0 -0
  348. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/posix_class.rs +0 -0
  349. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/progress.rs +0 -0
  350. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/row_event_flat.rs +0 -0
  351. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/sql_literal.rs +0 -0
  352. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/tree_walk.rs +0 -0
  353. {dirsql-0.4.83 → dirsql-0.4.85}/packages/rust/src/vtab.rs +0 -0
  354. {dirsql-0.4.83 → dirsql-0.4.85}/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.85"
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.85"
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.85
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
@@ -112,4 +112,4 @@ Row values serialize as in [`POST /query`](#value-serialization).
112
112
  |---|---|
113
113
  | `200` | Stream opened (`text/event-stream`). |
114
114
  | `405` | `POST /events`. Plain-text body `method not allowed`. |
115
- | `503` | The server is in [degraded mode](./cli.md#degraded-mode). JSON `{"error": …}` body. |
115
+ | `503` | The server is in [degraded mode](./cli.md#degraded-mode), or its filesystem watcher failed to start (for example, the inotify limit is exhausted). JSON `{"error": …}` body; for a watcher failure the message starts `filesystem watcher failed to start:` and gives the reason. `POST /query` keeps working. |
@@ -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.85"
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
+ **Changed** A declared `[[table]] glob` is compiled by the same glob compiler
2
+ as a path-table, so brace ranges such as `f{1..3}.md` and the other bash brace
3
+ rules now read the same on both surfaces.
@@ -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
@@ -112,4 +112,4 @@ Row values serialize as in [`POST /query`](#value-serialization).
112
112
  |---|---|
113
113
  | `200` | Stream opened (`text/event-stream`). |
114
114
  | `405` | `POST /events`. Plain-text body `method not allowed`. |
115
- | `503` | The server is in [degraded mode](./cli.md#degraded-mode). JSON `{"error": …}` body. |
115
+ | `503` | The server is in [degraded mode](./cli.md#degraded-mode), or its filesystem watcher failed to start (for example, the inotify limit is exhausted). JSON `{"error": …}` body; for a watcher failure the message starts `filesystem watcher failed to start:` and gives the reason. `POST /query` keeps working. |
@@ -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/cli_version_test.py tests/e2e/query_contract_test.py -x -q",
3
+ "ran_at": 1791309015,
4
+ "exit_code": 0,
5
+ "commit": "d60aff48881ae3201bccd0e6e77f52e6cd62c646",
6
+ "branch": "bot/1398-inotify-error"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/fanout_test.py -x -q",
3
+ "ran_at": 1791310157,
4
+ "exit_code": 0,
5
+ "commit": "7104e6400efd6f912a92a53dd0d8f6d4c6c3a947",
6
+ "branch": "bot/1407-child-place-depth"
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,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/capture_collision_test.py tests/e2e/declared_table_name_test.py tests/e2e/extension_package_test.py tests/e2e/query_contract_test.py tests/e2e/plugin_discovery_test.py tests/e2e/sigint_interrupt_test.py tests/e2e/fanout_test.py tests/e2e/use_case_transcripts_test.py tests/e2e/plugin_extension_discovery_test.py -x -q",
3
+ "ran_at": 1791301900,
4
+ "exit_code": 0,
5
+ "commit": "14d2a11edd69bb0715bbffdb085b1d6582728dd8",
6
+ "branch": "claude/1258-one-pattern"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/query_contract_test.py tests/e2e/declared_table_name_test.py tests/e2e/fanout_test.py -x -q",
3
+ "ran_at": 1791310416,
4
+ "exit_code": 0,
5
+ "commit": "bcedde49401cf6f9cc01deb2d95af1d1e907f0f7",
6
+ "branch": "claude/1330-vtab-prefetch-flag"
7
+ }
@@ -0,0 +1,28 @@
1
+ ### Config table globs share the path-table glob compiler
2
+
3
+ #### Summary
4
+
5
+ A declared `[[table]] glob` is now compiled by the same compiler as a
6
+ path-table. A brace range such as `f{1..3}.md` expands as in bash instead of
7
+ matching nothing. Nothing else changes.
8
+
9
+ #### Required changes
10
+
11
+ _None._
12
+
13
+ #### Deprecations removed
14
+
15
+ _None._
16
+
17
+ #### Behavior changes without code changes
18
+
19
+ - `glob = "f{1..3}.md"` matches `f1.md`, `f2.md` and `f3.md`.
20
+
21
+ #### Verification
22
+
23
+ ```bash
24
+ cd "$(mktemp -d)"
25
+ touch f1.md f2.md f3.md f4.md
26
+ dirsql query "SELECT path FROM './f{1..3}.md' ORDER BY path"
27
+ # expected: [{"path":"f1.md"},{"path":"f2.md"},{"path":"f3.md"}]
28
+ ```
@@ -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.85"
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
@@ -112,4 +112,4 @@ Row values serialize as in [`POST /query`](#value-serialization).
112
112
  |---|---|
113
113
  | `200` | Stream opened (`text/event-stream`). |
114
114
  | `405` | `POST /events`. Plain-text body `method not allowed`. |
115
- | `503` | The server is in [degraded mode](./cli.md#degraded-mode). JSON `{"error": …}` body. |
115
+ | `503` | The server is in [degraded mode](./cli.md#degraded-mode), or its filesystem watcher failed to start (for example, the inotify limit is exhausted). JSON `{"error": …}` body; for a watcher failure the message starts `filesystem watcher failed to start:` and gives the reason. `POST /query` keeps working. |
@@ -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.
@@ -26,6 +26,7 @@ use super::execute::{QueryFailure, execute_query, require_ready};
26
26
  pub(super) struct AppContext {
27
27
  pub state: AppState,
28
28
  pub events: broadcast::Sender<String>,
29
+ pub watch_failure: Option<String>,
29
30
  pub cancel: watch::Receiver<bool>,
30
31
  pub query_timeout: Duration,
31
32
  }
@@ -72,6 +73,9 @@ async fn handle_events(State(ctx): State<SharedCtx>) -> Response {
72
73
  if let Err(failure) = require_ready(&ctx.state) {
73
74
  return failure_response(&failure);
74
75
  }
76
+ if let Some(reason) = &ctx.watch_failure {
77
+ return failure_response(&QueryFailure::Unavailable(reason.clone()));
78
+ }
75
79
 
76
80
  // Subscribe BEFORE anything that might block so we don't drop events
77
81
  // that fire between subscribing and the first poll.
@@ -163,6 +167,21 @@ mod tests {
163
167
  );
164
168
  }
165
169
 
170
+ #[tokio::test]
171
+ async fn events_return_503_while_the_server_is_unavailable() {
172
+ let (events, _) = broadcast::channel::<String>(1);
173
+ let (_cancel_tx, cancel) = watch::channel(false);
174
+ let ctx = Arc::new(AppContext {
175
+ state: AppState::Unavailable("config failed to load".into()),
176
+ events,
177
+ watch_failure: None,
178
+ cancel,
179
+ query_timeout: Duration::from_secs(1),
180
+ });
181
+ let resp = handle_events(State(ctx)).await;
182
+ assert_eq!(resp.status(), StatusCode::SERVICE_UNAVAILABLE);
183
+ }
184
+
166
185
  #[test]
167
186
  fn error_response_sets_json_content_type() {
168
187
  let resp = error_response(StatusCode::BAD_REQUEST, "boom");
@@ -38,14 +38,16 @@ pub async fn serve_with_state(
38
38
  // the underlying notify watcher (which `DirSQL::watch` only permits
39
39
  // once per instance).
40
40
  let (event_tx, _) = broadcast::channel::<String>(256);
41
- if let AppState::Ready(ref db) = state {
42
- start_watch_task(db.clone(), event_tx.clone());
43
- }
41
+ let watch_failure = match state {
42
+ AppState::Ready(ref db) => start_watch_task(db.clone(), event_tx.clone()),
43
+ AppState::Unavailable(_) => None,
44
+ };
44
45
 
45
46
  let (cancel_tx, cancel_rx) = watch::channel(false);
46
47
  let shared = Arc::new(AppContext {
47
48
  state,
48
49
  events: event_tx,
50
+ watch_failure,
49
51
  cancel: cancel_rx,
50
52
  query_timeout: config.query_timeout,
51
53
  });
@@ -69,18 +71,20 @@ pub async fn serve_with_state(
69
71
  })
70
72
  }
71
73
 
72
- fn start_watch_task(db: DirSQL, tx: broadcast::Sender<String>) {
74
+ /// Returns the reason `/events` must refuse requests when the watcher
75
+ /// could not attach.
76
+ fn start_watch_task(db: DirSQL, tx: broadcast::Sender<String>) -> Option<String> {
73
77
  // `db.watch()` spawns its own OS thread and returns an async stream.
74
78
  // We pump the stream into the broadcast channel. If no subscribers
75
79
  // exist, send() errors but we keep pumping (future subscribers
76
80
  // will get subsequent events).
77
- let Ok(mut stream) = db.watch().map_err(|err| {
78
- eprintln!(
79
- "dirsql: failed to attach filesystem watcher ({err}); \
80
- /events will return an empty stream"
81
- );
82
- }) else {
83
- return;
81
+ let mut stream = match db.watch() {
82
+ Ok(stream) => stream,
83
+ Err(err) => {
84
+ let reason = format!("filesystem watcher failed to start: {err}");
85
+ eprintln!("dirsql: {reason}; /events will return 503");
86
+ return Some(reason);
87
+ }
84
88
  };
85
89
  tokio::spawn(async move {
86
90
  while let Some(event) = stream.next().await {
@@ -88,6 +92,7 @@ fn start_watch_task(db: DirSQL, tx: broadcast::Sender<String>) {
88
92
  let _ = tx.send(payload);
89
93
  }
90
94
  });
95
+ None
91
96
  }
92
97
 
93
98
  #[cfg(test)]
@@ -122,6 +127,29 @@ mod tests {
122
127
  handle.shutdown().await.expect("graceful shutdown");
123
128
  }
124
129
 
130
+ #[tokio::test]
131
+ async fn start_watch_task_reports_no_failure_once_the_watcher_attaches() {
132
+ let dir = tempfile::tempdir().unwrap();
133
+ let db = DirSQL::new(dir.path(), Vec::new()).unwrap();
134
+ let (tx, _) = broadcast::channel::<String>(1);
135
+ assert_eq!(start_watch_task(db, tx), None);
136
+ }
137
+
138
+ // `poll_events` locks out `watch`, the one deterministic way to make the
139
+ // watcher refuse to attach without exhausting inotify.
140
+ #[tokio::test]
141
+ async fn start_watch_task_returns_the_reason_when_the_watcher_cannot_attach() {
142
+ let dir = tempfile::tempdir().unwrap();
143
+ let db = DirSQL::new(dir.path(), Vec::new()).unwrap();
144
+ db.poll_events(std::time::Duration::ZERO).unwrap();
145
+ let (tx, _) = broadcast::channel::<String>(1);
146
+ let reason = start_watch_task(db, tx).expect("watch() must fail");
147
+ assert!(
148
+ reason.starts_with("filesystem watcher failed to start: "),
149
+ "got: {reason}"
150
+ );
151
+ }
152
+
125
153
  // Binding to a non-local TEST-NET address (RFC 5737) fails with
126
154
  // "cannot assign requested address", surfacing `ServerError::Bind` rather
127
155
  // than panicking — deterministic and DNS-free.