graphlint 0.3.3__tar.gz → 0.3.4__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 (116) hide show
  1. {graphlint-0.3.3 → graphlint-0.3.4}/CHANGELOG.md +7 -0
  2. {graphlint-0.3.3/graphlint.egg-info → graphlint-0.3.4}/PKG-INFO +1 -1
  3. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/__init__.py +1 -1
  4. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/graph.py +26 -7
  5. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/incremental/_db_ops.py +75 -3
  6. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/incremental/indexer.py +6 -1
  7. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/storage/schema.py +13 -0
  8. {graphlint-0.3.3 → graphlint-0.3.4/graphlint.egg-info}/PKG-INFO +1 -1
  9. {graphlint-0.3.3 → graphlint-0.3.4}/pyproject.toml +1 -1
  10. {graphlint-0.3.3 → graphlint-0.3.4}/CONTRIBUTING.md +0 -0
  11. {graphlint-0.3.3 → graphlint-0.3.4}/LICENSE +0 -0
  12. {graphlint-0.3.3 → graphlint-0.3.4}/MANIFEST.in +0 -0
  13. {graphlint-0.3.3 → graphlint-0.3.4}/README.md +0 -0
  14. {graphlint-0.3.3 → graphlint-0.3.4}/README_PYPI.md +0 -0
  15. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/api/build.md +0 -0
  16. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/api/configure.md +0 -0
  17. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/api/exceptions.md +0 -0
  18. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/api/query.md +0 -0
  19. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/architecture/overview.md +0 -0
  20. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/cli/usage.md +0 -0
  21. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/guide/agent-integration.md +0 -0
  22. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/guide/configuration.md +0 -0
  23. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/guide/entry-detection.md +0 -0
  24. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/guide/getting-started.md +0 -0
  25. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/guide/warnings.md +0 -0
  26. {graphlint-0.3.3 → graphlint-0.3.4}/docs/en/index.md +0 -0
  27. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/README.md +0 -0
  28. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/api/build.md +0 -0
  29. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/api/configure.md +0 -0
  30. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/api/exceptions.md +0 -0
  31. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/api/query.md +0 -0
  32. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/architecture/overview.md +0 -0
  33. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/cli/usage.md +0 -0
  34. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/guide/agent-integration.md +0 -0
  35. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/guide/configuration.md +0 -0
  36. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/guide/entry-detection.md +0 -0
  37. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/guide/getting-started.md +0 -0
  38. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/guide/warnings.md +0 -0
  39. {graphlint-0.3.3 → graphlint-0.3.4}/docs/zh/index.md +0 -0
  40. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/agent_tools.py +0 -0
  41. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/__init__.py +0 -0
  42. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/_graph_algo.py +0 -0
  43. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/_types.py +0 -0
  44. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/__init__.py +0 -0
  45. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/base.py +0 -0
  46. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/python/__init__.py +0 -0
  47. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/python/constants.py +0 -0
  48. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/python/decorators.py +0 -0
  49. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/python/entry.py +0 -0
  50. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/python/imports.py +0 -0
  51. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/python/parser.py +0 -0
  52. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/python/visitor.py +0 -0
  53. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/registry.py +0 -0
  54. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/rust/__init__.py +0 -0
  55. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/rust/constants.py +0 -0
  56. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/rust/entry.py +0 -0
  57. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/rust/imports.py +0 -0
  58. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/rust/parser.py +0 -0
  59. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/language/rust/visitor.py +0 -0
  60. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/analyzer/warnings.py +0 -0
  61. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/api.py +0 -0
  62. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/cli.py +0 -0
  63. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/config/__init__.py +0 -0
  64. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/config/defaults.py +0 -0
  65. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/config/manager.py +0 -0
  66. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/exceptions.py +0 -0
  67. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/i18n/__init__.py +0 -0
  68. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/i18n/en.py +0 -0
  69. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/i18n/zh_CN.py +0 -0
  70. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/incremental/__init__.py +0 -0
  71. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/params.py +0 -0
  72. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/query/__init__.py +0 -0
  73. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/query/engine.py +0 -0
  74. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/query/formatter.py +0 -0
  75. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/query/volume.py +0 -0
  76. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/storage/__init__.py +0 -0
  77. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/storage/db.py +0 -0
  78. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint/storage/hashing.py +0 -0
  79. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint.egg-info/SOURCES.txt +0 -0
  80. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint.egg-info/dependency_links.txt +0 -0
  81. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint.egg-info/entry_points.txt +0 -0
  82. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint.egg-info/requires.txt +0 -0
  83. {graphlint-0.3.3 → graphlint-0.3.4}/graphlint.egg-info/top_level.txt +0 -0
  84. {graphlint-0.3.3 → graphlint-0.3.4}/setup.cfg +0 -0
  85. {graphlint-0.3.3 → graphlint-0.3.4}/tests/__init__.py +0 -0
  86. {graphlint-0.3.3 → graphlint-0.3.4}/tests/integration/__init__.py +0 -0
  87. {graphlint-0.3.3 → graphlint-0.3.4}/tests/integration/test_api.py +0 -0
  88. {graphlint-0.3.3 → graphlint-0.3.4}/tests/integration/test_cli.py +0 -0
  89. {graphlint-0.3.3 → graphlint-0.3.4}/tests/integration/test_data_transfer.py +0 -0
  90. {graphlint-0.3.3 → graphlint-0.3.4}/tests/integration/test_dead_code_query.py +0 -0
  91. {graphlint-0.3.3 → graphlint-0.3.4}/tests/integration/test_full_pipeline.py +0 -0
  92. {graphlint-0.3.3 → graphlint-0.3.4}/tests/integration/test_incremental.py +0 -0
  93. {graphlint-0.3.3 → graphlint-0.3.4}/tests/integration/test_json_output.py +0 -0
  94. {graphlint-0.3.3 → graphlint-0.3.4}/tests/performance/__init__.py +0 -0
  95. {graphlint-0.3.3 → graphlint-0.3.4}/tests/performance/test_large_codebase.py +0 -0
  96. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/__init__.py +0 -0
  97. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_auto_build.py +0 -0
  98. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_config.py +0 -0
  99. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_db.py +0 -0
  100. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_db_ops.py +0 -0
  101. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_decorators.py +0 -0
  102. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_engine.py +0 -0
  103. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_entry_detect.py +0 -0
  104. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_exceptions.py +0 -0
  105. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_formatter.py +0 -0
  106. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_graph.py +0 -0
  107. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_graph_algo.py +0 -0
  108. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_hashing.py +0 -0
  109. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_i18n.py +0 -0
  110. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_imports.py +0 -0
  111. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_mock_boundary.py +0 -0
  112. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_params.py +0 -0
  113. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_parser.py +0 -0
  114. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_schema.py +0 -0
  115. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_volume.py +0 -0
  116. {graphlint-0.3.3 → graphlint-0.3.4}/tests/unit/test_warnings.py +0 -0
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.3.4] - 2026-07-27
6
+
7
+ ### Changed
8
+ - Incremental entry detection: entry point results are now persisted to DB
9
+ and only re-scanned for changed files in incremental builds, reducing
10
+ redundant computation when most files are unchanged
11
+
5
12
  ## [0.3.3] - 2026-07-25
6
13
 
7
14
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphlint
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: A static analysis tool for identifying dead code in a codebase. It provides Python API and CLI for use by agents.
5
5
  Author-email: Yutong Zou <yutong.zou.24@alumni.ucl.ac.uk>
6
6
  License-Expression: MIT
@@ -3,7 +3,7 @@
3
3
 
4
4
  from typing import Any
5
5
 
6
- __version__ = "0.3.3"
6
+ __version__ = "0.3.4"
7
7
 
8
8
  __all__ = ["query", "build", "configure", "__version__"]
9
9
 
@@ -259,6 +259,7 @@ class GraphBuilder:
259
259
  parse_results: dict[str, ParseResult],
260
260
  changed_files: Optional[set[str]] = None,
261
261
  prebuilt_edges: Optional[list[EdgeInfo]] = None,
262
+ prebuilt_entries: Optional[list[EntryInfo]] = None,
262
263
  old_changed_node_ids: dict[int, tuple[str, str]] | None = None,
263
264
  ) -> GraphBuildResult:
264
265
  """Build the complete dependency graph from parse results.
@@ -267,6 +268,9 @@ class GraphBuilder:
267
268
  old_changed_node_ids: Maps old global node ID → (qualified_name, file_path)
268
269
  for nodes in changed files. Used to remap parent_node_id when a
269
270
  child in an unchanged file references a parent in a changed file.
271
+ prebuilt_entries: Pre-loaded EntryInfo from DB for unchanged files
272
+ (incremental mode). When provided, entry detection only scans
273
+ changed files and merges these prebuilt entries.
270
274
  """
271
275
  fid_map: dict[str, int] = {}
272
276
  fid_cnt = 1
@@ -332,15 +336,30 @@ class GraphBuilder:
332
336
  if fid and fid in file_nodes_by_fid:
333
337
  fnodes_map[fp] = {n.qualified_name: n.id for n in file_nodes_by_fid[fid]}
334
338
 
335
- # Detect entries via language adapters
339
+ # Detect entries via language adapters.
340
+ # In incremental mode, only scan changed files and merge prebuilt
341
+ # entries loaded from DB for unchanged files.
336
342
  entries: list[EntryInfo] = []
337
- if self.registry:
338
- for adapter in self.registry.all_adapters():
339
- entries.extend(
340
- adapter.detect_entries(
341
- parse_results, self._nodes, self._node_id_map, self.config
343
+ if prebuilt_entries is not None and changed_files and len(changed_files) < len(parse_results):
344
+ changed_pr = {
345
+ fp: pr for fp, pr in parse_results.items() if fp in changed_files
346
+ }
347
+ if self.registry:
348
+ for adapter in self.registry.all_adapters():
349
+ entries.extend(
350
+ adapter.detect_entries(
351
+ changed_pr, self._nodes, self._node_id_map, self.config
352
+ )
353
+ )
354
+ entries.extend(prebuilt_entries)
355
+ else:
356
+ if self.registry:
357
+ for adapter in self.registry.all_adapters():
358
+ entries.extend(
359
+ adapter.detect_entries(
360
+ parse_results, self._nodes, self._node_id_map, self.config
361
+ )
342
362
  )
343
- )
344
363
  for e in entries:
345
364
  if e.node_id and e.node_id in self._node_id_map:
346
365
  self._node_id_map[e.node_id].is_entry = True
@@ -9,7 +9,7 @@ import json
9
9
  import os
10
10
  from typing import Any, Optional
11
11
 
12
- from graphlint.analyzer._types import EdgeInfo, NodeInfo, GraphBuildResult
12
+ from graphlint.analyzer._types import EdgeInfo, EntryInfo, NodeInfo, GraphBuildResult
13
13
  from graphlint.storage.db import Database
14
14
  from graphlint.storage.hashing import compute_file_hash, is_test_file
15
15
 
@@ -96,13 +96,14 @@ def update_db(
96
96
  else:
97
97
  # Full build: unconditionally clear all data tables (keep files table)
98
98
  # files table is updated by subsequent _upsert_files INSERT OR REPLACE
99
- for tbl in ("edges", "nodes", "imports", "warnings", "graph_snapshots"):
99
+ for tbl in ("edges", "nodes", "imports", "warnings", "graph_snapshots", "entries"):
100
100
  db.execute(f"DELETE FROM {tbl}")
101
101
  _upsert_files(db, build_result, root_dir, test_patterns, changed)
102
102
  fid_map = _load_fid_map(db)
103
103
  _insert_nodes(db, build_result, fid_map, changed_files=changed_set)
104
104
  _do_insert_edges(db, build_result, fid_map, changed_files=changed_set)
105
105
  _insert_warnings(db, build_result, fid_map, changed_files=changed_set)
106
+ _insert_entries(db, build_result, fid_map, changed_files=changed_set)
106
107
  if incremental:
107
108
  update_snapshots(db, build_result)
108
109
  else:
@@ -115,7 +116,7 @@ def _delete_old(db: Database, removed: list[str], changed: list[str]) -> None:
115
116
  if not paths:
116
117
  continue
117
118
  ph = ",".join("?" for _ in paths)
118
- for tbl in ("edges", "nodes", "imports", "warnings"):
119
+ for tbl in ("edges", "nodes", "imports", "warnings", "entries"):
119
120
  db.execute(
120
121
  f"DELETE FROM {tbl} WHERE file_id IN "
121
122
  f"(SELECT id FROM files WHERE path IN ({ph}))",
@@ -302,6 +303,77 @@ def _insert_warnings(
302
303
  )
303
304
 
304
305
 
306
+ def _insert_entries(
307
+ db: Database,
308
+ build_result: GraphBuildResult,
309
+ fid_map: dict[str, int],
310
+ changed_files: Optional[set[str]] = None,
311
+ ) -> None:
312
+ """Insert entry point detection results."""
313
+ batch: list[tuple[Any, ...]] = []
314
+ for entry in build_result.entry_info_list:
315
+ fp = entry.file_path
316
+ if changed_files is not None and fp not in changed_files:
317
+ continue
318
+ fid = fid_map.get(fp, 0)
319
+ if not fid:
320
+ continue
321
+ batch.append(
322
+ (
323
+ fid,
324
+ entry.node_id or 0,
325
+ entry.rule_name,
326
+ entry.line,
327
+ entry.description or "",
328
+ 1 if entry.no_propagate else 0,
329
+ )
330
+ )
331
+ if len(batch) >= 5000:
332
+ db.executemany(
333
+ "INSERT INTO entries (file_id, node_id, rule_name, "
334
+ "line, description, no_propagate) VALUES (?,?,?,?,?,?)",
335
+ batch,
336
+ )
337
+ batch.clear()
338
+ if batch:
339
+ db.executemany(
340
+ "INSERT INTO entries (file_id, node_id, rule_name, "
341
+ "line, description, no_propagate) VALUES (?,?,?,?,?,?)",
342
+ batch,
343
+ )
344
+
345
+
346
+ def load_unchanged_entries(
347
+ db: Database,
348
+ unchanged_files: set[str],
349
+ ) -> list[EntryInfo]:
350
+ """Load entry points for unchanged files from DB (incremental build)."""
351
+ if not unchanged_files:
352
+ return []
353
+ ph = ",".join("?" for _ in unchanged_files)
354
+ rows = db.fetchall(
355
+ f"SELECT e.*, f.path FROM entries e "
356
+ f"JOIN files f ON e.file_id = f.id "
357
+ f"WHERE f.path IN ({ph})",
358
+ tuple(unchanged_files),
359
+ )
360
+ entries: list[EntryInfo] = []
361
+ for r in rows:
362
+ file_path = r["path"]
363
+ node_id = r["node_id"] or 0
364
+ entries.append(
365
+ EntryInfo(
366
+ rule_name=r["rule_name"],
367
+ file_path=file_path,
368
+ line=r["line"],
369
+ node_id=node_id,
370
+ description=r["description"] or "",
371
+ no_propagate=bool(r["no_propagate"]),
372
+ )
373
+ )
374
+ return entries
375
+
376
+
305
377
  def _precompute_edge_counts(
306
378
  component_map: dict[int, int],
307
379
  edges: list[EdgeInfo],
@@ -20,6 +20,7 @@ from graphlint.incremental._db_ops import (
20
20
  build_snapshots,
21
21
  load_old_changed_node_ids,
22
22
  load_prebuilt_edges,
23
+ load_unchanged_entries,
23
24
  persist_unchanged_parent_node_ids,
24
25
  update_db,
25
26
  update_snapshots,
@@ -140,7 +141,7 @@ class IncrementalIndexer:
140
141
 
141
142
  if needs_full:
142
143
  with self.db.transaction():
143
- for t in ("edges", "nodes", "imports", "warnings", "graph_snapshots", "files"):
144
+ for t in ("edges", "nodes", "imports", "warnings", "graph_snapshots", "entries", "files"):
144
145
  self.db.execute(f"DELETE FROM {t}")
145
146
  all_results = self._parse_batch(disk_files)
146
147
  for fp, pr in all_results:
@@ -186,11 +187,15 @@ class IncrementalIndexer:
186
187
  prebuilt = load_prebuilt_edges(self.db, unchanged, sql_to_mem)
187
188
 
188
189
  # ------ Phase 4: Rebuild graph (upstream + downstream + analysis) --
190
+ prebuilt_entries: Optional[list[Any]] = None
191
+ if unchanged:
192
+ prebuilt_entries = load_unchanged_entries(self.db, unchanged)
189
193
  builder = self._create_builder(wc)
190
194
  br = builder.build(
191
195
  pr_map,
192
196
  changed_files=set(changed),
193
197
  prebuilt_edges=prebuilt,
198
+ prebuilt_entries=prebuilt_entries,
194
199
  old_changed_node_ids=old_ids if old_ids else None,
195
200
  )
196
201
 
@@ -117,6 +117,19 @@ CREATE TABLE IF NOT EXISTS graph_snapshots (
117
117
 
118
118
  CREATE INDEX IF NOT EXISTS idx_snapshots_time ON graph_snapshots(snapshot_time);
119
119
 
120
+ -- Entry points: persisted detection results for incremental rebuild reuse
121
+ CREATE TABLE IF NOT EXISTS entries (
122
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
123
+ file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
124
+ node_id INTEGER DEFAULT 0,
125
+ rule_name TEXT NOT NULL,
126
+ line INTEGER NOT NULL DEFAULT 0,
127
+ description TEXT NOT NULL DEFAULT '',
128
+ no_propagate INTEGER NOT NULL DEFAULT 0
129
+ );
130
+
131
+ CREATE INDEX IF NOT EXISTS idx_entries_file ON entries(file_id);
132
+
120
133
  -- Component members: maps node_id to component_id for incremental connectivity analysis
121
134
  CREATE TABLE IF NOT EXISTS component_members (
122
135
  component_id INTEGER NOT NULL,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphlint
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: A static analysis tool for identifying dead code in a codebase. It provides Python API and CLI for use by agents.
5
5
  Author-email: Yutong Zou <yutong.zou.24@alumni.ucl.ac.uk>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "graphlint"
7
- version = "0.3.3"
7
+ version = "0.3.4"
8
8
  description = "A static analysis tool for identifying dead code in a codebase. It provides Python API and CLI for use by agents."
9
9
  readme = "README_PYPI.md"
10
10
  license = "MIT"
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