coderag-ai 0.3.1__tar.gz → 0.3.2__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 (139) hide show
  1. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/PKG-INFO +1 -1
  2. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/pyproject.toml +1 -1
  3. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/localdb.py +21 -2
  4. coderag_ai-0.3.2/tests/test_phase14_localdb.py +72 -0
  5. coderag_ai-0.3.1/tests/test_phase14_localdb.py +0 -35
  6. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/.env.example +0 -0
  7. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/.gitignore +0 -0
  8. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/CODE_OF_CONDUCT.md +0 -0
  9. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/CONTRIBUTING.md +0 -0
  10. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/Dockerfile +0 -0
  11. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/LICENSE +0 -0
  12. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/Makefile +0 -0
  13. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/NOTICE +0 -0
  14. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/README.md +0 -0
  15. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/SECURITY.md +0 -0
  16. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/alembic.ini +0 -0
  17. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docker/entrypoint.sh +0 -0
  18. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docker-compose.yml +0 -0
  19. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/adding-language.md +0 -0
  20. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/adr/001-postgres-pgvector.md +0 -0
  21. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/adr/002-structural-chunks.md +0 -0
  22. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/adr/003-hybrid-search.md +0 -0
  23. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/adr/004-tree-sitter.md +0 -0
  24. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/adr/005-llm-provider-independence.md +0 -0
  25. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/adr/006-repository-authorization.md +0 -0
  26. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/adr/007-token-budgeting.md +0 -0
  27. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/architecture.md +0 -0
  28. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/claude-code.md +0 -0
  29. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/evaluation.md +0 -0
  30. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/install-macos.md +0 -0
  31. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/licenses.md +0 -0
  32. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/llm-providers.md +0 -0
  33. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/retrieval.md +0 -0
  34. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/security.md +0 -0
  35. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/docs/vscode-extension.md +0 -0
  36. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/__init__.py +0 -0
  37. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/api.py +0 -0
  38. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/auth.py +0 -0
  39. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/checkout_service.py +0 -0
  40. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/models.py +0 -0
  41. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/payment_repository.py +0 -0
  42. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/payment_service.py +0 -0
  43. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/retry_policy.py +0 -0
  44. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/payments/users.py +0 -0
  45. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/tests/test_payment_service.py +0 -0
  46. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/demo-repository/tests/test_retry_policy.py +0 -0
  47. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/examples/eval/eval_dataset.json +0 -0
  48. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/scripts/gen_initial_migration.py +0 -0
  49. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/__init__.py +0 -0
  50. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/analyzers/__init__.py +0 -0
  51. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/analyzers/base.py +0 -0
  52. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/analyzers/flake8_adapter.py +0 -0
  53. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/analyzers/pylint_adapter.py +0 -0
  54. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/analyzers/workflow.py +0 -0
  55. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/api/__init__.py +0 -0
  56. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/api/app.py +0 -0
  57. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/api/dashboard.py +0 -0
  58. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/api/schemas.py +0 -0
  59. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/cli/__init__.py +0 -0
  60. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/cli/main.py +0 -0
  61. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/context/__init__.py +0 -0
  62. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/context/builder.py +0 -0
  63. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/context/package.py +0 -0
  64. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/core/__init__.py +0 -0
  65. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/core/config.py +0 -0
  66. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/core/logging.py +0 -0
  67. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/core/text.py +0 -0
  68. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/core/tokens.py +0 -0
  69. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/db/__init__.py +0 -0
  70. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/db/base.py +0 -0
  71. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/db/migrations/env.py +0 -0
  72. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/db/migrations/script.py.mako +0 -0
  73. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/db/migrations/versions/.gitkeep +0 -0
  74. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/db/migrations/versions/9a973932b94d_measure_baseline_tokens.py +0 -0
  75. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/db/migrations/versions/c8a40feeda41_initial_schema.py +0 -0
  76. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/db/models.py +0 -0
  77. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/embeddings/__init__.py +0 -0
  78. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/embeddings/base.py +0 -0
  79. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/embeddings/hashing.py +0 -0
  80. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/embeddings/pipeline.py +0 -0
  81. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/embeddings/registry.py +0 -0
  82. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/embeddings/sentence_transformer.py +0 -0
  83. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/evaluation/__init__.py +0 -0
  84. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/evaluation/datasets.py +0 -0
  85. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/evaluation/harness.py +0 -0
  86. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/git/__init__.py +0 -0
  87. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/git/repo.py +0 -0
  88. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/indexing/__init__.py +0 -0
  89. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/indexing/ignore.py +0 -0
  90. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/indexing/indexer.py +0 -0
  91. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/llm/__init__.py +0 -0
  92. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/llm/anthropic.py +0 -0
  93. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/llm/base.py +0 -0
  94. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/llm/null.py +0 -0
  95. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/llm/registry.py +0 -0
  96. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/mcp_server.py +0 -0
  97. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/parsing/__init__.py +0 -0
  98. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/parsing/base.py +0 -0
  99. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/parsing/python.py +0 -0
  100. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/parsing/registry.py +0 -0
  101. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/__init__.py +0 -0
  102. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/base.py +0 -0
  103. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/engine.py +0 -0
  104. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/fusion.py +0 -0
  105. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/graph.py +0 -0
  106. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/lexical.py +0 -0
  107. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/reranking.py +0 -0
  108. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/semantic.py +0 -0
  109. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/retrieval/symbol.py +0 -0
  110. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/security/__init__.py +0 -0
  111. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/security/authz.py +0 -0
  112. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/security/secrets.py +0 -0
  113. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/service.py +0 -0
  114. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/src/coderag/telemetry.py +0 -0
  115. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/__init__.py +0 -0
  116. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/conftest.py +0 -0
  117. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase0_db.py +0 -0
  118. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase0_migrations.py +0 -0
  119. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase10_analyzers.py +0 -0
  120. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase11_dashboard.py +0 -0
  121. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase12_mcp.py +0 -0
  122. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase13_measure.py +0 -0
  123. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase1_indexer.py +0 -0
  124. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase1_parser.py +0 -0
  125. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase2_cli.py +0 -0
  126. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase2_retrieval.py +0 -0
  127. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase3_embeddings.py +0 -0
  128. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase3_semantic.py +0 -0
  129. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase3_sentence_transformer.py +0 -0
  130. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase4_graph.py +0 -0
  131. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase5_context_db.py +0 -0
  132. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase5_context_unit.py +0 -0
  133. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase6_api.py +0 -0
  134. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase6_ask.py +0 -0
  135. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase6_llm.py +0 -0
  136. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase7_eval.py +0 -0
  137. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase8_incremental.py +0 -0
  138. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_phase9_rerank.py +0 -0
  139. {coderag_ai-0.3.1 → coderag_ai-0.3.2}/tests/test_security_secrets.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: coderag-ai
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Token-efficient, structure-aware Code Intelligence + RAG for private source repositories.
5
5
  Project-URL: Homepage, https://github.com/galacticsurfer/coderag
6
6
  Project-URL: Repository, https://github.com/galacticsurfer/coderag
@@ -7,7 +7,7 @@ build-backend = "hatchling.build"
7
7
  # command are both `coderag`. Plain "coderag" is taken on PyPI by an unrelated project,
8
8
  # and "code-rag" is rejected as too similar (PyPI collapses -/_/. when comparing names).
9
9
  name = "coderag-ai"
10
- version = "0.3.1"
10
+ version = "0.3.2"
11
11
  description = "Token-efficient, structure-aware Code Intelligence + RAG for private source repositories."
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.12"
@@ -49,8 +49,27 @@ def start(pgdata: Path | str | None = None) -> str:
49
49
  path.parent.mkdir(parents=True, exist_ok=True)
50
50
  # cleanup_mode=None -> the postmaster keeps running after we exit.
51
51
  server = pgserver.get_server(str(path), cleanup_mode=None)
52
- server.psql("CREATE EXTENSION IF NOT EXISTS vector;")
53
- return sqlalchemy_url(server.get_uri())
52
+ url = sqlalchemy_url(server.get_uri())
53
+ _ensure_vector_extension(url)
54
+ return url
55
+
56
+
57
+ def _ensure_vector_extension(url: str) -> None:
58
+ """Create the pgvector extension over a normal connection.
59
+
60
+ Deliberately does NOT use pgserver's bundled ``psql`` binary: on macOS that
61
+ executable can fail to run (exit 127), which would break `localdb start` even
62
+ though the server itself is healthy. psycopg is already a dependency, so we
63
+ talk to the server the same way the rest of the application does.
64
+ """
65
+ from sqlalchemy import create_engine, text
66
+
67
+ engine = create_engine(url)
68
+ try:
69
+ with engine.begin() as conn:
70
+ conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
71
+ finally:
72
+ engine.dispose()
54
73
 
55
74
 
56
75
  def stop(pgdata: Path | str | None = None, timeout: float = 15.0) -> None:
@@ -0,0 +1,72 @@
1
+ """Rootless local Postgres helper (no Docker/sudo) — lifecycle correctness."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import pytest
6
+
7
+ pytest.importorskip("pgserver")
8
+
9
+ from coderag import localdb # noqa: E402
10
+
11
+
12
+ def test_status_does_not_start_the_server(tmp_path):
13
+ """A status check must never start a server (regression: it used to)."""
14
+ pgdata = tmp_path / "pgdata"
15
+ assert localdb.status(pgdata) is None # not running, nothing created
16
+ assert not (pgdata / "postmaster.pid").exists()
17
+
18
+
19
+ def test_start_status_stop_lifecycle(tmp_path):
20
+ pgdata = tmp_path / "pgdata"
21
+ url = localdb.start(pgdata)
22
+ try:
23
+ assert url.startswith("postgresql+psycopg://")
24
+ pid = localdb.status(pgdata)
25
+ assert pid and pid > 0
26
+ finally:
27
+ localdb.stop(pgdata)
28
+ assert localdb.status(pgdata) is None # stays stopped
29
+
30
+
31
+ def test_stale_pidfile_reports_not_running(tmp_path):
32
+ pgdata = tmp_path / "pgdata"
33
+ pgdata.mkdir()
34
+ (pgdata / "postmaster.pid").write_text("999999999\n") # impossible pid
35
+ assert localdb.status(pgdata) is None
36
+
37
+
38
+ def test_start_does_not_shell_out_to_psql(tmp_path, monkeypatch):
39
+ """Regression: the bundled `psql` binary can fail on macOS (exit 127).
40
+
41
+ `start()` must create the pgvector extension over a normal DB connection, so
42
+ the command works even when that executable is unusable.
43
+ """
44
+ import pgserver
45
+
46
+ real_get_server = pgserver.get_server
47
+
48
+ def guarded(pgdata, cleanup_mode=None):
49
+ server = real_get_server(pgdata, cleanup_mode=cleanup_mode)
50
+
51
+ def boom(*a, **k):
52
+ raise AssertionError("start() must not invoke the bundled psql binary")
53
+
54
+ monkeypatch.setattr(server, "psql", boom, raising=False)
55
+ return server
56
+
57
+ monkeypatch.setattr(pgserver, "get_server", guarded)
58
+
59
+ pgdata = tmp_path / "pgdata"
60
+ url = localdb.start(pgdata)
61
+ try:
62
+ from sqlalchemy import create_engine, text
63
+
64
+ engine = create_engine(url)
65
+ with engine.connect() as conn:
66
+ got = conn.execute(
67
+ text("SELECT extversion FROM pg_extension WHERE extname='vector'")
68
+ ).scalar()
69
+ engine.dispose()
70
+ assert got, "pgvector extension should have been created"
71
+ finally:
72
+ localdb.stop(pgdata)
@@ -1,35 +0,0 @@
1
- """Rootless local Postgres helper (no Docker/sudo) — lifecycle correctness."""
2
-
3
- from __future__ import annotations
4
-
5
- import pytest
6
-
7
- pytest.importorskip("pgserver")
8
-
9
- from coderag import localdb # noqa: E402
10
-
11
-
12
- def test_status_does_not_start_the_server(tmp_path):
13
- """A status check must never start a server (regression: it used to)."""
14
- pgdata = tmp_path / "pgdata"
15
- assert localdb.status(pgdata) is None # not running, nothing created
16
- assert not (pgdata / "postmaster.pid").exists()
17
-
18
-
19
- def test_start_status_stop_lifecycle(tmp_path):
20
- pgdata = tmp_path / "pgdata"
21
- url = localdb.start(pgdata)
22
- try:
23
- assert url.startswith("postgresql+psycopg://")
24
- pid = localdb.status(pgdata)
25
- assert pid and pid > 0
26
- finally:
27
- localdb.stop(pgdata)
28
- assert localdb.status(pgdata) is None # stays stopped
29
-
30
-
31
- def test_stale_pidfile_reports_not_running(tmp_path):
32
- pgdata = tmp_path / "pgdata"
33
- pgdata.mkdir()
34
- (pgdata / "postmaster.pid").write_text("999999999\n") # impossible pid
35
- assert localdb.status(pgdata) is None
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes