Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,17 @@ That single command:
one-shot indexing is never a problem.
5. Validates the graph scope: no `test_*` addon modules indexed, no missing and no extra module
roots compared to the expected module list, and **every indexed file carrying one of the
configured extensions** (`SOURCE_GLOBS`: `.py .xml .js .rst .md .css .scss .csv`) — anything
configured extensions** (`SOURCE_GLOBS`: `.py .xml .js .scss .csv .sql`) — anything
else means `.cbmignore` did not apply. Counts per extension are logged, unexpected ones marked
`(!)`:

```text
extensions_configured=.css,.csv,.js,.md,.py,.rst,.scss,.xml
extensions_configured=.csv,.js,.py,.scss,.sql,.xml
extensions_indexed=5 files=12057
extension .py files=4949
extension .xml files=3276
extension .json files=39 (!)
unexpected_extensions=1 files=39 (not in SOURCE_GLOBS: .json)
unexpected_extensions=1 files=39 (not in the configured extensions: .json)
```

Both checks read the graph with `query_graph` over its `File` nodes, not with `search_code`:
Expand Down
23 changes: 22 additions & 1 deletion src/codebase_memory_deployv/indexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,28 @@
DEFAULT_PROJECT = "odoo_instance"
CORE_DIRS = ("odoo/odoo",)
CORE_PREFIX = "odoo/odoo/"
SOURCE_GLOBS = ("*.py", "*.xml", "*.js", "*.rst", "*.md", "*.css", "*.scss", "*.csv", "*.sql")
# Prose formats are deliberately absent. Measured on a real Odoo instance (188 modules,
# 77935 DEFINES edges), every extension earns its place by how much of the graph it builds:
#
# .py 2755 files 55603 definitions 20.2 per file 71.3% of the graph
# .xml 1883 files 14844 definitions 7.9 per file 19.0%
# .js 890 files 6368 definitions 7.2 per file 8.2%
# .scss 232 files 912 definitions 3.9 per file 1.2%
# .csv 86 files 86 definitions 1.0 per file 0.1%
# .sql 20 files 35 definitions 1.8 per file 0.0%
# .rst 73 files 73 definitions 1.0 per file 0.1% <- dropped
# .css 8 files 8 definitions 1.0 per file 0.0% <- dropped
# .md 2 files 6 definitions 3.0 per file 0.0% <- dropped
#
# ".rst" and ".css" build exactly one node each — the File node itself, nothing inside it —
# and ".md" only adds the headings of a README (every Section node in that graph came from
# two markdown files). They are module prose, so the graph gains a path and no structure.
#
# ".csv" scores the same 1.0 and stays anyway: an indexed file is also greppable through
# search_code, and ir.model.access.csv is a file people really do search. Extensions are a
# weak lever on memory in any case (these three are 1.4% of the files, where .js is 15%),
# so this is about keeping the graph free of prose, not about making a scope fit.
SOURCE_GLOBS = ("*.py", "*.xml", "*.js", "*.scss", "*.csv", "*.sql")
# What .cbmignore lets through, so what the graph is expected to hold: ".py", ".xml", ...
SOURCE_EXTENSIONS = tuple(sorted(pattern[1:] for pattern in SOURCE_GLOBS))
MANIFEST_NAMES = ("__manifest__.py", "__openerp__.py")
Expand Down
23 changes: 23 additions & 0 deletions tests/test_indexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,3 +480,26 @@ def test_check_layout_requires_odoo_bin(tmp_path):
odoo_dir.mkdir()
(odoo_dir / "odoo-bin").write_text("")
assert indexer.check_layout(str(tmp_path)) == os.path.join(str(tmp_path), "odoo", "odoo-bin")


def test_source_globs_exclude_module_prose():
""".rst/.md/.css build a File node and nothing inside it; the graph gains no structure."""
assert ".rst" not in indexer.SOURCE_EXTENSIONS
assert ".md" not in indexer.SOURCE_EXTENSIONS
assert ".css" not in indexer.SOURCE_EXTENSIONS


def test_source_globs_keep_csv_for_text_search():
"""ir.model.access.csv builds no structure either, but an indexed file stays greppable."""
assert ".csv" in indexer.SOURCE_EXTENSIONS


def test_render_cbmignore_stops_letting_prose_through():
content = indexer.render_cbmignore(["extra_addons/vauxoo/sale_extended"])
assert "!extra_addons/vauxoo/sale_extended/**/*.py" in content
assert "!extra_addons/vauxoo/sale_extended/**/*.csv" in content
assert "*.rst" not in content
assert "*.md" not in content
assert "*.css" not in content
# ".scss" must survive a naive "*.css" removal: it ends with the same three letters.
assert "!extra_addons/vauxoo/sale_extended/**/*.scss" in content