dirsql 0.4.82__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.82 → dirsql-0.4.84}/Cargo.lock +2 -2
  2. {dirsql-0.4.82 → dirsql-0.4.84}/PKG-INFO +1 -1
  3. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/_async.py +27 -7
  4. {dirsql-0.4.82/packages/rust → dirsql-0.4.84}/docs/howto/write-a-plugin.md +7 -6
  5. {dirsql-0.4.82 → dirsql-0.4.84}/docs/reference/cli.md +1 -1
  6. {dirsql-0.4.82/packages/rust → dirsql-0.4.84}/docs/reference/config.md +32 -9
  7. {dirsql-0.4.82 → dirsql-0.4.84}/docs/reference/hooks.md +3 -2
  8. {dirsql-0.4.82 → dirsql-0.4.84}/docs/reference/sdk.md +10 -2
  9. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/Cargo.toml +1 -1
  10. dirsql-0.4.84/packages/python/changelog.d/2026-10-06-config-globs-anchor-at-the-config.md +3 -0
  11. dirsql-0.4.84/packages/python/changelog.d/2026-10-06-watch-broadcast.md +3 -0
  12. dirsql-0.4.84/packages/python/changelog.d/2026-10-06-zero-match-config-table-warning.md +3 -0
  13. {dirsql-0.4.82 → dirsql-0.4.84/packages/python}/docs/howto/write-a-plugin.md +7 -6
  14. {dirsql-0.4.82/packages/rust → dirsql-0.4.84/packages/python}/docs/reference/cli.md +1 -1
  15. {dirsql-0.4.82 → dirsql-0.4.84/packages/python}/docs/reference/config.md +32 -9
  16. {dirsql-0.4.82/packages/rust → dirsql-0.4.84/packages/python}/docs/reference/hooks.md +3 -2
  17. {dirsql-0.4.82/packages/rust → dirsql-0.4.84/packages/python}/docs/reference/sdk.md +10 -2
  18. dirsql-0.4.84/packages/python/e2e-attestations/bot-1397-watch-broadcast.json +7 -0
  19. dirsql-0.4.84/packages/python/e2e-attestations/claude-1232-config-anchor.json +7 -0
  20. dirsql-0.4.84/packages/python/e2e-attestations/claude-1232-multi-watch.json +7 -0
  21. dirsql-0.4.84/packages/python/e2e-attestations/claude-1232-zero-match.json +7 -0
  22. dirsql-0.4.84/packages/python/e2e-attestations/claude-1330-python-extensions-patch.json +7 -0
  23. dirsql-0.4.84/packages/python/migrations.d/2026-10-06-config-globs-anchor-at-the-config.md +33 -0
  24. dirsql-0.4.84/packages/python/migrations.d/2026-10-06-watch-broadcast.md +46 -0
  25. dirsql-0.4.84/packages/python/migrations.d/2026-10-06-zero-match-config-table-warning.md +25 -0
  26. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/testing-conventions.toml +0 -5
  27. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/Cargo.toml +1 -1
  28. {dirsql-0.4.82/packages/python → dirsql-0.4.84/packages/rust}/docs/howto/write-a-plugin.md +7 -6
  29. {dirsql-0.4.82/packages/python → dirsql-0.4.84/packages/rust}/docs/reference/cli.md +1 -1
  30. {dirsql-0.4.82/packages/python → dirsql-0.4.84/packages/rust}/docs/reference/config.md +32 -9
  31. {dirsql-0.4.82/packages/python → dirsql-0.4.84/packages/rust}/docs/reference/hooks.md +3 -2
  32. {dirsql-0.4.82/packages/python → dirsql-0.4.84/packages/rust}/docs/reference/sdk.md +10 -2
  33. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/run.rs +3 -2
  34. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/db.rs +2 -2
  35. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/lib.rs +184 -27
  36. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/path_table.rs +95 -0
  37. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/persist.rs +19 -2
  38. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/watcher.rs +9 -1
  39. {dirsql-0.4.82 → dirsql-0.4.84}/Cargo.toml +0 -0
  40. {dirsql-0.4.82 → dirsql-0.4.84}/README.md +0 -0
  41. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/__init__.py +0 -0
  42. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/_dirsql.pyi +0 -0
  43. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/cli/__init__.py +0 -0
  44. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/cli/discover_plugins/__init__.py +0 -0
  45. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
  46. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
  47. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
  48. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
  49. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/cli/main.py +0 -0
  50. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/cli/resolve_config_extensions.py +0 -0
  51. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/plan_entry_path.py +0 -0
  52. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/py.typed +0 -0
  53. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/read_config.py +0 -0
  54. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/resolve_configs_extension_specs.py +0 -0
  55. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/resolve_extension.py +0 -0
  56. {dirsql-0.4.82 → dirsql-0.4.84}/dirsql/resolve_package.py +0 -0
  57. {dirsql-0.4.82 → dirsql-0.4.84}/docs/.claude/CLAUDE.md +0 -0
  58. {dirsql-0.4.82 → dirsql-0.4.84}/docs/.vitepress/config.ts +0 -0
  59. {dirsql-0.4.82 → dirsql-0.4.84}/docs/.vitepress/theme/index.ts +0 -0
  60. {dirsql-0.4.82 → dirsql-0.4.84}/docs/.vitepress/theme/lang.ts +0 -0
  61. {dirsql-0.4.82 → dirsql-0.4.84}/docs/AGENTS.md +0 -0
  62. {dirsql-0.4.82 → dirsql-0.4.84}/docs/context/.gitattributes +0 -0
  63. {dirsql-0.4.82 → dirsql-0.4.84}/docs/context/recipes.md +0 -0
  64. {dirsql-0.4.82 → dirsql-0.4.84}/docs/context/troubleshooting.md +0 -0
  65. {dirsql-0.4.82 → dirsql-0.4.84}/docs/context/usage.md +0 -0
  66. {dirsql-0.4.82 → dirsql-0.4.84}/docs/explanation.md +0 -0
  67. {dirsql-0.4.82 → dirsql-0.4.84}/docs/getting-started.md +0 -0
  68. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/agent-skill.md +0 -0
  69. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/columns-from-paths.md +0 -0
  70. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/define-tables.md +0 -0
  71. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/embed.md +0 -0
  72. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/extract-from-contents.md +0 -0
  73. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/load-extension.md +0 -0
  74. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/parse-files-into-columns.md +0 -0
  75. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/persist.md +0 -0
  76. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/query-json.md +0 -0
  77. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/query-without-config.md +0 -0
  78. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/react-to-changes.md +0 -0
  79. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/search-by-meaning.md +0 -0
  80. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/search-indexes.md +0 -0
  81. {dirsql-0.4.82 → dirsql-0.4.84}/docs/howto/skip-files.md +0 -0
  82. {dirsql-0.4.82 → dirsql-0.4.84}/docs/index.md +0 -0
  83. {dirsql-0.4.82 → dirsql-0.4.84}/docs/package.json +0 -0
  84. {dirsql-0.4.82 → dirsql-0.4.84}/docs/plugins.md +0 -0
  85. {dirsql-0.4.82 → dirsql-0.4.84}/docs/pnpm-lock.yaml +0 -0
  86. {dirsql-0.4.82 → dirsql-0.4.84}/docs/pnpm-workspace.yaml +0 -0
  87. {dirsql-0.4.82 → dirsql-0.4.84}/docs/reference/columns.md +0 -0
  88. {dirsql-0.4.82 → dirsql-0.4.84}/docs/reference/http-api.md +0 -0
  89. {dirsql-0.4.82 → dirsql-0.4.84}/docs/reference/path-tables.md +0 -0
  90. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/CHANGELOG.md +0 -0
  91. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/MIGRATIONS.md +0 -0
  92. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/README.md +0 -0
  93. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  94. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
  95. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  96. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
  97. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  98. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
  99. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
  100. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
  101. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  102. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
  103. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
  104. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
  105. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
  106. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
  107. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
  108. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
  109. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
  110. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
  111. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
  112. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
  113. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
  114. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
  115. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
  116. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
  117. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
  118. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
  119. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
  120. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
  121. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  122. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  123. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-02-readme-docs-host.md +0 -0
  124. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  125. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-03-path-table-directory-one-level.md +0 -0
  126. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  127. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  128. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-cli-context.md +0 -0
  129. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-gitignore-requires-repo.md +0 -0
  130. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-path-table-node-modules-named.md +0 -0
  131. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-path-table-symlinks.md +0 -0
  132. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-05-path-table-trailing-slash.md +0 -0
  133. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/2026-10-06-plugin-no-default-records.md +0 -0
  134. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/changelog.d/README.md +0 -0
  135. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/conftest.py +0 -0
  136. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/.claude/CLAUDE.md +0 -0
  137. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/.vitepress/config.ts +0 -0
  138. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/.vitepress/theme/index.ts +0 -0
  139. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
  140. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/AGENTS.md +0 -0
  141. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/context/.gitattributes +0 -0
  142. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/context/recipes.md +0 -0
  143. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/context/troubleshooting.md +0 -0
  144. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/context/usage.md +0 -0
  145. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/explanation.md +0 -0
  146. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/getting-started.md +0 -0
  147. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/agent-skill.md +0 -0
  148. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/columns-from-paths.md +0 -0
  149. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/define-tables.md +0 -0
  150. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/embed.md +0 -0
  151. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/extract-from-contents.md +0 -0
  152. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/load-extension.md +0 -0
  153. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
  154. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/persist.md +0 -0
  155. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/query-json.md +0 -0
  156. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/query-without-config.md +0 -0
  157. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/react-to-changes.md +0 -0
  158. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/search-by-meaning.md +0 -0
  159. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/search-indexes.md +0 -0
  160. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/howto/skip-files.md +0 -0
  161. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/index.md +0 -0
  162. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/package.json +0 -0
  163. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/plugins.md +0 -0
  164. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/pnpm-lock.yaml +0 -0
  165. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/pnpm-workspace.yaml +0 -0
  166. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/reference/columns.md +0 -0
  167. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/reference/http-api.md +0 -0
  168. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/docs/reference/path-tables.md +0 -0
  169. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
  170. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
  171. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
  172. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
  173. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
  174. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
  175. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
  176. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
  177. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
  178. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
  179. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
  180. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
  181. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
  182. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
  183. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
  184. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
  185. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
  186. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
  187. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
  188. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
  189. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
  190. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
  191. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
  192. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
  193. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1196-join-index.json +0 -0
  194. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1199-glob-prefix.json +0 -0
  195. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1201-single-walk.json +0 -0
  196. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1204-embed-batch.json +0 -0
  197. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +0 -0
  198. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +0 -0
  199. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1215-on-file-batch.json +0 -0
  200. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1216-on-file-cleanup.json +0 -0
  201. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1223-config-glob-rule.json +0 -0
  202. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1223-dir-one-level.json +0 -0
  203. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1225-plugin-no-default.json +0 -0
  204. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1226-stale-docs.json +0 -0
  205. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1232-anchor-plumbing.json +0 -0
  206. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1238-parallel-walk.json +0 -0
  207. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1241-content-prefetch.json +0 -0
  208. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1243-ingest-perf.json +0 -0
  209. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1249-dotfiles.json +0 -0
  210. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1256-symlinks.json +0 -0
  211. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1257-trailing-slash.json +0 -0
  212. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1262-brace-literal.json +0 -0
  213. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1264-context.json +0 -0
  214. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1267-posix-classes.json +0 -0
  215. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1269-utf8-chars.json +0 -0
  216. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1271-node-modules-named.json +0 -0
  217. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1272-ancestor-gitignore.json +0 -0
  218. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1273-walk-prune.json +0 -0
  219. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1285-ingest-fast.json +0 -0
  220. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1286-nested-repo.json +0 -0
  221. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1305-glob-speed.json +0 -0
  222. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1308-glob-speed.json +0 -0
  223. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1310-glob-speed.json +0 -0
  224. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1311-glob-speed.json +0 -0
  225. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1312-glob-speed.json +0 -0
  226. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1318-lazy-stat.json +0 -0
  227. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1320-walk-speed.json +0 -0
  228. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1322-walk-readdir.json +0 -0
  229. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1325-parallel-walk.json +0 -0
  230. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1326-stream-rows.json +0 -0
  231. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-python-dirsql-patch.json +0 -0
  232. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-scanner-effects.json +0 -0
  233. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-scanner-gitignore.json +0 -0
  234. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1330-vtab-read.json +0 -0
  235. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-1351-dot-dirs.json +0 -0
  236. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
  237. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
  238. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
  239. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
  240. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
  241. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
  242. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
  243. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
  244. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
  245. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
  246. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
  247. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
  248. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
  249. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
  250. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
  251. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  252. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  253. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  254. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
  255. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
  256. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
  257. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  258. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
  259. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
  260. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
  261. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  262. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  263. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-02-readme-docs-host.md +0 -0
  264. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  265. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-03-path-table-directory-one-level.md +0 -0
  266. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  267. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  268. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-cli-context.md +0 -0
  269. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md +0 -0
  270. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-path-table-node-modules-named.md +0 -0
  271. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-path-table-symlinks.md +0 -0
  272. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-05-path-table-trailing-slash.md +0 -0
  273. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/2026-10-06-plugin-no-default-records.md +0 -0
  274. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/migrations.d/README.md +0 -0
  275. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/src/lib.rs +0 -0
  276. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/__init__.py +0 -0
  277. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/conftest.py +0 -0
  278. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/e2e/__init__.py +0 -0
  279. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
  280. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
  281. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/e2e/speed_of_light.py +0 -0
  282. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/integration/__init__.py +0 -0
  283. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/integration/binding/__init__.py +0 -0
  284. {dirsql-0.4.82 → dirsql-0.4.84}/packages/python/tests/integration/hermetic/__init__.py +0 -0
  285. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/CHANGELOG.md +0 -0
  286. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/MIGRATIONS.md +0 -0
  287. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/README.md +0 -0
  288. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/benches/db_bench.rs +0 -0
  289. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/benches/differ_bench.rs +0 -0
  290. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/benches/matcher_bench.rs +0 -0
  291. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/benches/scanner_bench.rs +0 -0
  292. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/context/.gitattributes +0 -0
  293. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/context/recipes.md +0 -0
  294. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/context/troubleshooting.md +0 -0
  295. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/context/usage.md +0 -0
  296. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/explanation.md +0 -0
  297. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/getting-started.md +0 -0
  298. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/agent-skill.md +0 -0
  299. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/columns-from-paths.md +0 -0
  300. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/define-tables.md +0 -0
  301. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/embed.md +0 -0
  302. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/extract-from-contents.md +0 -0
  303. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/load-extension.md +0 -0
  304. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
  305. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/persist.md +0 -0
  306. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/query-json.md +0 -0
  307. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/query-without-config.md +0 -0
  308. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/react-to-changes.md +0 -0
  309. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/search-by-meaning.md +0 -0
  310. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/search-indexes.md +0 -0
  311. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/howto/skip-files.md +0 -0
  312. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/index.md +0 -0
  313. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/plugins.md +0 -0
  314. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/reference/columns.md +0 -0
  315. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/reference/http-api.md +0 -0
  316. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/docs/reference/path-tables.md +0 -0
  317. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/bin/dirsql.rs +0 -0
  318. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/brace.rs +0 -0
  319. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/context.rs +0 -0
  320. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/execute.rs +0 -0
  321. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/init.rs +0 -0
  322. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/mod.rs +0 -0
  323. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/repl.rs +0 -0
  324. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/router.rs +0 -0
  325. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/serialize.rs +0 -0
  326. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/server.rs +0 -0
  327. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/cli/table.rs +0 -0
  328. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/command.rs +0 -0
  329. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/config.rs +0 -0
  330. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/default_config.toml +0 -0
  331. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/differ.rs +0 -0
  332. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/extension_resolution.rs +0 -0
  333. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/functions.rs +0 -0
  334. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/infer.rs +0 -0
  335. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/launcher.rs +0 -0
  336. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/listing.rs +0 -0
  337. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/matcher.rs +0 -0
  338. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/on_file.rs +0 -0
  339. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/parsed_vtab.rs +0 -0
  340. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/posix_class.rs +0 -0
  341. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/progress.rs +0 -0
  342. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/row_event_flat.rs +0 -0
  343. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/scanner.rs +0 -0
  344. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/sql_literal.rs +0 -0
  345. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/tree_walk.rs +0 -0
  346. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/vtab.rs +0 -0
  347. {dirsql-0.4.82 → dirsql-0.4.84}/packages/rust/src/vtab_scaffold.rs +0 -0
  348. {dirsql-0.4.82 → 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.82"
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.82"
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.82
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)
@@ -62,7 +62,9 @@ and [`ignore`](../reference/config.md#dirsql-keys).
62
62
  There are **no plugin-specific keys and no plugin-specific restrictions**. The
63
63
  config schema is content-only: the index root and persistence are
64
64
  [runner-owned](../reference/config.md#dirsql-keys) — the root is the directory
65
- `dirsql` is run from (or an SDK's explicit `root`), persistence is the
65
+ `dirsql` is run from (or an SDK's explicit `root`) and governs path-tables,
66
+ while a fragment's own `[[table]]` globs anchor at the fragment's directory
67
+ (see [glob anchor](../reference/config.md#glob-anchor)); persistence is the
66
68
  `--persist [PATH]` flag — decided by whoever runs `dirsql`, never by a config
67
69
  file, so a plugin has nothing to say about them. Whatever you can put in your
68
70
  own `.dirsql.toml`, a plugin can put in its fragment, and vice-versa.
@@ -86,11 +88,10 @@ matter most for a published plugin:
86
88
  - **A hook runs in its declaring config's directory.** For a plugin that is
87
89
  the installed fragment's directory — inside **site-packages**. That is a
88
90
  read-only, shared location: **run from it, never write to it.** Read the
89
- matched files from the absolute paths the hook appends as arguments, and use
90
- [`{root}`](../reference/hooks.md#on-file) to reach the user's project
91
- directory. Write any cache to `{root}` or a real cache dir,
92
- never next to the fragment.
93
- - **The paths are absolute and `{root}` is the index root**, so a command is
91
+ matched files from the absolute paths the hook appends as arguments. Write any cache to a real cache dir, never next to
92
+ the fragment.
93
+ - **The paths are absolute and `{root}` is the table's glob anchor** (the
94
+ fragment's directory, or the literal prefix of an absolute / `~/` glob), so a command is
94
95
  self-sufficient from any working directory — it works whether the plugin
95
96
  lives in the project or in site-packages.
96
97
 
@@ -244,7 +244,7 @@ Config flags are subcommand-local: pass them after `server`
244
244
 
245
245
  | Flag | Default | Description |
246
246
  |---|---|---|
247
- | `-c, --config <path>` | none | Path to a [config file](./config.md). **Repeatable** (`-c a -c b`): the configs load and merge in argv order — see [Composing multiple configs](./config.md#composing-multiple-configs). The index is always rooted at the **invocation directory** (the current working directory), regardless of where a config lives — so `--config /elsewhere/.dirsql.toml` still indexes the directory you ran `dirsql server` from. With none given, **no named tables are defined** — query the filesystem with a [path-table](./path-tables.md) (`FROM './'`). A `./.dirsql.toml` on disk is **not** auto-loaded; pass it explicitly. A `-c` naming a file that does not exist is an [error](#degraded-mode). |
247
+ | `-c, --config <path>` | none | Path to a [config file](./config.md). **Repeatable** (`-c a -c b`): the configs load and merge in argv order — see [Composing multiple configs](./config.md#composing-multiple-configs). The index root is the **invocation directory** (the current working directory) and governs path-tables; a config's `[[table]]` globs anchor at **that config's own directory** (see [glob anchor](./config.md#glob-anchor)), so `--config /elsewhere/.dirsql.toml` indexes `/elsewhere`, from any working directory. With none given, **no named tables are defined** — query the filesystem with a [path-table](./path-tables.md) (`FROM './'`). A `./.dirsql.toml` on disk is **not** auto-loaded; pass it explicitly. A `-c` naming a file that does not exist is an [error](#degraded-mode). |
248
248
  | `--host <addr>` | `localhost` | Bind address. |
249
249
  | `--port <n>` | `7117` | TCP port to bind. |
250
250
  | `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Also available on [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
@@ -14,17 +14,19 @@ with none given [no named tables](./cli.md#configless-mode) are defined (a
14
14
  `./.dirsql.toml` on disk is **not** auto-loaded). The [SDKs](./sdk.md) load a
15
15
  config via the `config` constructor parameter.
16
16
 
17
- **Path resolution.** Relative paths in the config (`[[dirsql.extension]]`
18
- `path`) resolve against the config file's parent
19
- directory. The **index root is not a config concern** — it is decided by the
20
- runner (the CLI's invocation directory, or an SDK's explicit root), never by
21
- the config file's location. See [`--config`](./cli.md#flags).
17
+ **Path resolution.** A path written in a config resolves against the config
18
+ file's parent directory: a `[[table]]` `glob` (see [anchoring](#glob-anchor)),
19
+ `ignore`, and `[[dirsql.extension]]` `path`. A config therefore works from any
20
+ working directory. The **index root is not a config concern** — it is decided
21
+ by the runner (the CLI's invocation directory, or an SDK's explicit root) and
22
+ governs only path-tables and programmatic tables. See
23
+ [`--config`](./cli.md#flags).
22
24
 
23
25
  ## `[dirsql]` keys
24
26
 
25
27
  | Key | Type | Default | Description |
26
28
  |---|---|---|---|
27
- | `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
29
+ | `ignore` | array of strings | `[]` | Glob patterns matched against paths relative to the config file's directory, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. They apply only to this config's `[[table]]` entries (not to path-tables, and not to another config's tables). Matched files are skipped entirely — excluded from the initial scan and from watch events. |
28
30
 
29
31
  There is no timeout key. `on-file` hook runs are unbounded; to bound one, wrap
30
32
  its command in `timeout(1)` (see [Command hooks](./hooks.md#bounding-a-hook)).
@@ -230,7 +232,7 @@ what its required `on-file` command emits — dirsql injects nothing (see
230
232
  |---|---|---|
231
233
  | `name` | yes | The table's SQL name — the name you query it by. Declared, never derived from `ddl`: dirsql does not read the DDL text. The `ddl` must create a table by this name; if it doesn't, loading fails. |
232
234
  | `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (keys the `on-file` command emits that are not declared are dropped). The rest of the batch is yours: indexes, virtual tables, triggers. See [Batch `ddl`](#batch-ddl). |
233
- | `glob` | yes | Glob pattern matched against root-relative paths, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` segment is rewritten to `*` (it matches one path segment but captures nothing). |
235
+ | `glob` | yes | Glob pattern, [anchored](#glob-anchor) at the config file's directory, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` segment is rewritten to `*` (it matches one path segment but captures nothing). |
234
236
  | `on-file` | **yes** | A command run once per table, with every matched file's absolute path appended as a trailing argument; its stdout (one JSON array of row objects) is the table's rows. Must be non-empty. A `[[table]]` with no `on-file` is a load error (see [parse errors](#parse-errors)). See [Command hooks](./hooks.md#on-file). |
235
237
  | `strict` | no (default `false`) | When `true`, rows whose keys do not exactly match the declared columns are rejected with an error: extra keys error, and every declared column must be supplied by the `on-file` output. When `false`, extra keys are dropped and missing columns become `NULL`. |
236
238
 
@@ -256,6 +258,26 @@ on-file = "uv run python extract_papers.py"
256
258
  strict = true
257
259
  ```
258
260
 
261
+ ### Glob anchor
262
+
263
+ A table's `glob` is matched beneath its **anchor**, never the index root:
264
+
265
+ | `glob` starts with | Anchor |
266
+ |---|---|
267
+ | nothing special, or `./` | the config file's directory |
268
+ | `/` (or a drive / UNC root) | the literal directory chain before the first glob character |
269
+ | `~/` | your home directory, then the literal chain |
270
+ | `../` | resolved against the config file's directory, then the literal chain |
271
+
272
+ So `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes
273
+ `~/.claude/projects` from any working directory, and a shared config elsewhere
274
+ writes `glob = "~/.claude/projects/*/*.jsonl"`. A table's `path` and `dir`
275
+ columns, `{root}`, and `ignore` are all relative to its anchor.
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
+
259
281
  ### Batch `ddl`
260
282
 
261
283
  `ddl` is handed to SQLite whole, so a table declaration is not limited to one
@@ -346,7 +368,7 @@ dirsql -c ./.dirsql.toml -c ~/team/embeddings.toml -c ./local.toml
346
368
 
347
369
  The configs load and merge in **argv order**:
348
370
 
349
- - **`[[table]]`, `ignore`, `[[dirsql.extension]]`, and `[[dirsql.function]]`
371
+ - **`[[table]]`, `[[dirsql.extension]]`, and `[[dirsql.function]]`
350
372
  entries accumulate** across all configs, in order.
351
373
  - **Each config's `on-file` hooks and `[[dirsql.function]]` workers run from
352
374
  that config file's own directory** — so a relative command like
@@ -360,7 +382,8 @@ The configs load and merge in **argv order**:
360
382
  silent last-writer-wins.
361
383
 
362
384
  The index [root](./cli.md#flags) is the invocation directory regardless of where
363
- any config lives. With no `-c`, [no named tables](./cli.md#configless-mode) are
385
+ any config lives; each config's `[[table]]` globs anchor at that config's own
386
+ directory, and its `ignore` applies to its own tables only. With no `-c`, [no named tables](./cli.md#configless-mode) are
364
387
  defined (no `./.dirsql.toml` auto-discovery); a single `-c` behaves exactly as
365
388
  before.
366
389
 
@@ -42,7 +42,8 @@ relative paths in the command resolve predictably regardless of where
42
42
  `dirsql` was launched. A command named by the `--on-file` flag has no config
43
43
  file: it runs in the **index root**, the directory `dirsql query` was run in,
44
44
  which is also the directory a `./` path-table is relative to. In both forms
45
- `{root}` is the index root. The command inherits `dirsql`'s environment, so
45
+ `{root}` is where the table's glob is anchored: the index root for `--on-file`,
46
+ the [glob anchor](./config.md#glob-anchor) for a `[[table]]`. The command inherits `dirsql`'s environment, so
46
47
  tools like `uvx --with …` / `npx …` resolve their dependencies as usual.
47
48
 
48
49
  ### stdout protocol
@@ -143,7 +144,7 @@ the path or stat metadata emits it (it has the paths).
143
144
 
144
145
  | Placeholder | Value |
145
146
  |---|---|
146
- | `{root}` | The index root directory. Derive a root-relative path with `relpath(path, {root})`. |
147
+ | `{root}` | The directory the table's glob is anchored at (the index root for `--on-file`; the config file's directory, or the literal prefix of an absolute / `~/` glob, for a `[[table]]`). Derive an anchor-relative path with `relpath(path, {root})`. |
147
148
 
148
149
  The matched files' **absolute** paths are not placeholders: they are appended
149
150
  to the command as trailing arguments, after everything written in the
@@ -98,7 +98,9 @@ DirSQL::builder()
98
98
 
99
99
  Creates a SQLite index over a directory. The index root is the explicit
100
100
  `root` when given, else the **process cwd** — the `config` file's location
101
- never sets the root.
101
+ never sets the root. A config's `[[table]]` globs anchor at the config file's
102
+ own directory instead (see [glob anchor](./config.md#glob-anchor)); `root`
103
+ governs programmatic tables and path-tables.
102
104
 
103
105
  Constructing with **neither a `config` nor programmatic `tables`** defines
104
106
  **no named tables** — the same as the CLI with no
@@ -127,7 +129,9 @@ shortcut was removed in #603 — use
127
129
  entries are appended after any programmatic `tables`; its `ignore`
128
130
  patterns and `[[dirsql.extension]]` entries are appended likewise. The
129
131
  config file does **not** set the index root: with no explicit `root`, the
130
- index roots at the process cwd. **Multiple configs merge in order** on
132
+ index roots at the process cwd. Its `[[table]]` globs anchor at the config
133
+ file's directory (or at the literal prefix of an absolute / `~/` glob), not
134
+ at `root`; its `ignore` applies to its own tables only. **Multiple configs merge in order** on
131
135
  every SDK — **Python** `config` accepts a `str` or a `list[str]`, the
132
136
  **Rust** builder's `.config()` is repeatable (call it once per file), and
133
137
  **TypeScript** `config` accepts a `string` or a `string[]`; the configs
@@ -297,6 +301,10 @@ under the root. The watcher starts on first iteration (Python/TypeScript)
297
301
  or at the `watch()` call (Rust). The stream never terminates on its own;
298
302
  stop consuming it to stop.
299
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
+
300
308
  Rust: `watch()` may be called once per instance and is mutually exclusive
301
309
  with the polling API below — mixing them returns an error, since both drain
302
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.82"
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
+ **Changed**
2
+
3
+ - **A config `[[table]]` `glob` now anchors at its config file's directory, not the index root.** `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes `~/.claude/projects` from any working directory. A glob may also start with `/`, `~/` or `../` (the path-table prefix grammar): it anchors at the literal directory chain before its first glob character. `{root}` in an `on-file` command, a table's `path`/`dir` columns, and `ignore` are all relative to the table's anchor. A config's `ignore` now applies to that config's tables only, no longer to path-tables or to other configs' tables. The index root (cwd, or `root=`) is unchanged and still governs path-tables and programmatic tables. (#1232)
@@ -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)
@@ -62,7 +62,9 @@ and [`ignore`](../reference/config.md#dirsql-keys).
62
62
  There are **no plugin-specific keys and no plugin-specific restrictions**. The
63
63
  config schema is content-only: the index root and persistence are
64
64
  [runner-owned](../reference/config.md#dirsql-keys) — the root is the directory
65
- `dirsql` is run from (or an SDK's explicit `root`), persistence is the
65
+ `dirsql` is run from (or an SDK's explicit `root`) and governs path-tables,
66
+ while a fragment's own `[[table]]` globs anchor at the fragment's directory
67
+ (see [glob anchor](../reference/config.md#glob-anchor)); persistence is the
66
68
  `--persist [PATH]` flag — decided by whoever runs `dirsql`, never by a config
67
69
  file, so a plugin has nothing to say about them. Whatever you can put in your
68
70
  own `.dirsql.toml`, a plugin can put in its fragment, and vice-versa.
@@ -86,11 +88,10 @@ matter most for a published plugin:
86
88
  - **A hook runs in its declaring config's directory.** For a plugin that is
87
89
  the installed fragment's directory — inside **site-packages**. That is a
88
90
  read-only, shared location: **run from it, never write to it.** Read the
89
- matched files from the absolute paths the hook appends as arguments, and use
90
- [`{root}`](../reference/hooks.md#on-file) to reach the user's project
91
- directory. Write any cache to `{root}` or a real cache dir,
92
- never next to the fragment.
93
- - **The paths are absolute and `{root}` is the index root**, so a command is
91
+ matched files from the absolute paths the hook appends as arguments. Write any cache to a real cache dir, never next to
92
+ the fragment.
93
+ - **The paths are absolute and `{root}` is the table's glob anchor** (the
94
+ fragment's directory, or the literal prefix of an absolute / `~/` glob), so a command is
94
95
  self-sufficient from any working directory — it works whether the plugin
95
96
  lives in the project or in site-packages.
96
97
 
@@ -244,7 +244,7 @@ Config flags are subcommand-local: pass them after `server`
244
244
 
245
245
  | Flag | Default | Description |
246
246
  |---|---|---|
247
- | `-c, --config <path>` | none | Path to a [config file](./config.md). **Repeatable** (`-c a -c b`): the configs load and merge in argv order — see [Composing multiple configs](./config.md#composing-multiple-configs). The index is always rooted at the **invocation directory** (the current working directory), regardless of where a config lives — so `--config /elsewhere/.dirsql.toml` still indexes the directory you ran `dirsql server` from. With none given, **no named tables are defined** — query the filesystem with a [path-table](./path-tables.md) (`FROM './'`). A `./.dirsql.toml` on disk is **not** auto-loaded; pass it explicitly. A `-c` naming a file that does not exist is an [error](#degraded-mode). |
247
+ | `-c, --config <path>` | none | Path to a [config file](./config.md). **Repeatable** (`-c a -c b`): the configs load and merge in argv order — see [Composing multiple configs](./config.md#composing-multiple-configs). The index root is the **invocation directory** (the current working directory) and governs path-tables; a config's `[[table]]` globs anchor at **that config's own directory** (see [glob anchor](./config.md#glob-anchor)), so `--config /elsewhere/.dirsql.toml` indexes `/elsewhere`, from any working directory. With none given, **no named tables are defined** — query the filesystem with a [path-table](./path-tables.md) (`FROM './'`). A `./.dirsql.toml` on disk is **not** auto-loaded; pass it explicitly. A `-c` naming a file that does not exist is an [error](#degraded-mode). |
248
248
  | `--host <addr>` | `localhost` | Bind address. |
249
249
  | `--port <n>` | `7117` | TCP port to bind. |
250
250
  | `--persist [<path>]` | off | Keep the SQLite index on disk between runs so a restart only re-parses files that actually changed. Bare `--persist` caches at `<root>/.dirsql/cache.db`; `--persist <path>` caches at `<path>`. Off by default (the index is ephemeral). Also available on [`dirsql query`](#dirsql-query). See [Keep the index across restarts](../howto/persist.md). |
@@ -14,17 +14,19 @@ with none given [no named tables](./cli.md#configless-mode) are defined (a
14
14
  `./.dirsql.toml` on disk is **not** auto-loaded). The [SDKs](./sdk.md) load a
15
15
  config via the `config` constructor parameter.
16
16
 
17
- **Path resolution.** Relative paths in the config (`[[dirsql.extension]]`
18
- `path`) resolve against the config file's parent
19
- directory. The **index root is not a config concern** — it is decided by the
20
- runner (the CLI's invocation directory, or an SDK's explicit root), never by
21
- the config file's location. See [`--config`](./cli.md#flags).
17
+ **Path resolution.** A path written in a config resolves against the config
18
+ file's parent directory: a `[[table]]` `glob` (see [anchoring](#glob-anchor)),
19
+ `ignore`, and `[[dirsql.extension]]` `path`. A config therefore works from any
20
+ working directory. The **index root is not a config concern** — it is decided
21
+ by the runner (the CLI's invocation directory, or an SDK's explicit root) and
22
+ governs only path-tables and programmatic tables. See
23
+ [`--config`](./cli.md#flags).
22
24
 
23
25
  ## `[dirsql]` keys
24
26
 
25
27
  | Key | Type | Default | Description |
26
28
  |---|---|---|---|
27
- | `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
29
+ | `ignore` | array of strings | `[]` | Glob patterns matched against paths relative to the config file's directory, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. They apply only to this config's `[[table]]` entries (not to path-tables, and not to another config's tables). Matched files are skipped entirely — excluded from the initial scan and from watch events. |
28
30
 
29
31
  There is no timeout key. `on-file` hook runs are unbounded; to bound one, wrap
30
32
  its command in `timeout(1)` (see [Command hooks](./hooks.md#bounding-a-hook)).
@@ -230,7 +232,7 @@ what its required `on-file` command emits — dirsql injects nothing (see
230
232
  |---|---|---|
231
233
  | `name` | yes | The table's SQL name — the name you query it by. Declared, never derived from `ddl`: dirsql does not read the DDL text. The `ddl` must create a table by this name; if it doesn't, loading fails. |
232
234
  | `ddl` | yes | A SQL batch, run verbatim — any number of statements. It must create a table called `name`; that table holds the file rows, and only the columns it declares are kept (keys the `on-file` command emits that are not declared are dropped). The rest of the batch is yours: indexes, virtual tables, triggers. See [Batch `ddl`](#batch-ddl). |
233
- | `glob` | yes | Glob pattern matched against root-relative paths, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` segment is rewritten to `*` (it matches one path segment but captures nothing). |
235
+ | `glob` | yes | Glob pattern, [anchored](#glob-anchor) at the config file's directory, under the [one glob rule](#glob-rule): `*` matches one level, `**` any depth. Every table whose glob matches a file receives that file's rows — a file can populate multiple tables. A `{name}` segment is rewritten to `*` (it matches one path segment but captures nothing). |
234
236
  | `on-file` | **yes** | A command run once per table, with every matched file's absolute path appended as a trailing argument; its stdout (one JSON array of row objects) is the table's rows. Must be non-empty. A `[[table]]` with no `on-file` is a load error (see [parse errors](#parse-errors)). See [Command hooks](./hooks.md#on-file). |
235
237
  | `strict` | no (default `false`) | When `true`, rows whose keys do not exactly match the declared columns are rejected with an error: extra keys error, and every declared column must be supplied by the `on-file` output. When `false`, extra keys are dropped and missing columns become `NULL`. |
236
238
 
@@ -256,6 +258,26 @@ on-file = "uv run python extract_papers.py"
256
258
  strict = true
257
259
  ```
258
260
 
261
+ ### Glob anchor
262
+
263
+ A table's `glob` is matched beneath its **anchor**, never the index root:
264
+
265
+ | `glob` starts with | Anchor |
266
+ |---|---|
267
+ | nothing special, or `./` | the config file's directory |
268
+ | `/` (or a drive / UNC root) | the literal directory chain before the first glob character |
269
+ | `~/` | your home directory, then the literal chain |
270
+ | `../` | resolved against the config file's directory, then the literal chain |
271
+
272
+ So `glob = "projects/*/*.jsonl"` in `~/.claude/.dirsql.toml` indexes
273
+ `~/.claude/projects` from any working directory, and a shared config elsewhere
274
+ writes `glob = "~/.claude/projects/*/*.jsonl"`. A table's `path` and `dir`
275
+ columns, `{root}`, and `ignore` are all relative to its anchor.
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
+
259
281
  ### Batch `ddl`
260
282
 
261
283
  `ddl` is handed to SQLite whole, so a table declaration is not limited to one
@@ -346,7 +368,7 @@ dirsql -c ./.dirsql.toml -c ~/team/embeddings.toml -c ./local.toml
346
368
 
347
369
  The configs load and merge in **argv order**:
348
370
 
349
- - **`[[table]]`, `ignore`, `[[dirsql.extension]]`, and `[[dirsql.function]]`
371
+ - **`[[table]]`, `[[dirsql.extension]]`, and `[[dirsql.function]]`
350
372
  entries accumulate** across all configs, in order.
351
373
  - **Each config's `on-file` hooks and `[[dirsql.function]]` workers run from
352
374
  that config file's own directory** — so a relative command like
@@ -360,7 +382,8 @@ The configs load and merge in **argv order**:
360
382
  silent last-writer-wins.
361
383
 
362
384
  The index [root](./cli.md#flags) is the invocation directory regardless of where
363
- any config lives. With no `-c`, [no named tables](./cli.md#configless-mode) are
385
+ any config lives; each config's `[[table]]` globs anchor at that config's own
386
+ directory, and its `ignore` applies to its own tables only. With no `-c`, [no named tables](./cli.md#configless-mode) are
364
387
  defined (no `./.dirsql.toml` auto-discovery); a single `-c` behaves exactly as
365
388
  before.
366
389
 
@@ -42,7 +42,8 @@ relative paths in the command resolve predictably regardless of where
42
42
  `dirsql` was launched. A command named by the `--on-file` flag has no config
43
43
  file: it runs in the **index root**, the directory `dirsql query` was run in,
44
44
  which is also the directory a `./` path-table is relative to. In both forms
45
- `{root}` is the index root. The command inherits `dirsql`'s environment, so
45
+ `{root}` is where the table's glob is anchored: the index root for `--on-file`,
46
+ the [glob anchor](./config.md#glob-anchor) for a `[[table]]`. The command inherits `dirsql`'s environment, so
46
47
  tools like `uvx --with …` / `npx …` resolve their dependencies as usual.
47
48
 
48
49
  ### stdout protocol
@@ -143,7 +144,7 @@ the path or stat metadata emits it (it has the paths).
143
144
 
144
145
  | Placeholder | Value |
145
146
  |---|---|
146
- | `{root}` | The index root directory. Derive a root-relative path with `relpath(path, {root})`. |
147
+ | `{root}` | The directory the table's glob is anchored at (the index root for `--on-file`; the config file's directory, or the literal prefix of an absolute / `~/` glob, for a `[[table]]`). Derive an anchor-relative path with `relpath(path, {root})`. |
147
148
 
148
149
  The matched files' **absolute** paths are not placeholders: they are appended
149
150
  to the command as trailing arguments, after everything written in the
@@ -98,7 +98,9 @@ DirSQL::builder()
98
98
 
99
99
  Creates a SQLite index over a directory. The index root is the explicit
100
100
  `root` when given, else the **process cwd** — the `config` file's location
101
- never sets the root.
101
+ never sets the root. A config's `[[table]]` globs anchor at the config file's
102
+ own directory instead (see [glob anchor](./config.md#glob-anchor)); `root`
103
+ governs programmatic tables and path-tables.
102
104
 
103
105
  Constructing with **neither a `config` nor programmatic `tables`** defines
104
106
  **no named tables** — the same as the CLI with no
@@ -127,7 +129,9 @@ shortcut was removed in #603 — use
127
129
  entries are appended after any programmatic `tables`; its `ignore`
128
130
  patterns and `[[dirsql.extension]]` entries are appended likewise. The
129
131
  config file does **not** set the index root: with no explicit `root`, the
130
- index roots at the process cwd. **Multiple configs merge in order** on
132
+ index roots at the process cwd. Its `[[table]]` globs anchor at the config
133
+ file's directory (or at the literal prefix of an absolute / `~/` glob), not
134
+ at `root`; its `ignore` applies to its own tables only. **Multiple configs merge in order** on
131
135
  every SDK — **Python** `config` accepts a `str` or a `list[str]`, the
132
136
  **Rust** builder's `.config()` is repeatable (call it once per file), and
133
137
  **TypeScript** `config` accepts a `string` or a `string[]`; the configs
@@ -297,6 +301,10 @@ under the root. The watcher starts on first iteration (Python/TypeScript)
297
301
  or at the `watch()` call (Rust). The stream never terminates on its own;
298
302
  stop consuming it to stop.
299
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
+
300
308
  Rust: `watch()` may be called once per instance and is mutually exclusive
301
309
  with the polling API below — mixing them returns an error, since both drain
302
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": 1791304886,
4
+ "exit_code": 0,
5
+ "commit": "f34d689dd854cb17c0daad87be0efebb4a45fdb6",
6
+ "branch": "claude/1232-config-anchor"
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 tests/e2e/on_file_query_test.py -x -q",
3
+ "ran_at": 1791304050,
4
+ "exit_code": 0,
5
+ "commit": "8618c31f0280a80e7d09550fdb931c6460741db7",
6
+ "branch": "claude/1232-multi-watch"
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/fanout_test.py tests/e2e/cli_version_test.py tests/e2e/extension_package_test.py tests/e2e/on_file_query_test.py tests/e2e/sigint_interrupt_test.py tests/e2e/plugin_extension_discovery_test.py tests/e2e/plugin_discovery_test.py tests/e2e/query_contract_test.py -x -q",
3
+ "ran_at": 1791302302,
4
+ "exit_code": 0,
5
+ "commit": "97413988a4b984de31f96d190d2164d61279d7c5",
6
+ "branch": "claude/1330-python-extensions-patch"
7
+ }
@@ -0,0 +1,33 @@
1
+ ### Config globs anchor at the config file's directory (#1232)
2
+
3
+ #### Summary
4
+
5
+ A `[[table]]` `glob` is matched beneath the directory of the config file that wrote it (or, for a `/`, `~/` or `../` glob, beneath its literal prefix), no longer beneath the index root. A config that relied on running from the directory it describes still works when that is also the config's directory; a config kept apart from its data, or one given an explicit root, now indexes the config's directory and needs its globs rewritten.
6
+
7
+ #### Required changes
8
+
9
+ | Surface | Before | After |
10
+ | ------- | ------ | ----- |
11
+ | `DirSQL(root="/data", config="/cfg/.dirsql.toml")` with `glob = "**/*.md"` | indexes `/data` | indexes `/cfg`; write `glob = "/data/**/*.md"` to index `/data` |
12
+ | `dirsql -c /cfg/.dirsql.toml` run from `/data` | indexes `/data` | indexes `/cfg` |
13
+ | `ignore` in a config | applied to every table and to path-tables | applies to that config's tables, relative to their anchor |
14
+ | A table over a directory other than the config's | `glob = "docs/*.md"` with the root elsewhere | `glob = "/data/docs/*.md"` or `glob = "~/data/docs/*.md"` |
15
+ | `{root}` in an `on-file` command | the index root | the table's anchor (the config's directory, or the literal prefix of an absolute glob) |
16
+
17
+ #### Deprecations removed
18
+
19
+ _None._
20
+
21
+ #### Behavior changes without code changes
22
+
23
+ - A config table's `path` column is relative to its anchor.
24
+ - A programmatic table and a path-table still use the index root.
25
+
26
+ #### Verification
27
+
28
+ ```bash
29
+ mkdir -p /tmp/cfg/projects/p /tmp/elsewhere
30
+ echo '{}' > /tmp/cfg/projects/p/a.jsonl
31
+ printf '[[table]]\nname = "sessions"\nddl = "CREATE TABLE sessions (n TEXT)"\nglob = "projects/*/*.jsonl"\non-file = "echo [{}]"\n' > /tmp/cfg/.dirsql.toml
32
+ cd /tmp/elsewhere && dirsql query "SELECT COUNT(*) AS n FROM sessions" -c /tmp/cfg/.dirsql.toml # [{"n":1}]
33
+ ```
@@ -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
+ ```