node-walk 0.4.0__tar.gz → 0.5.0__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 (59) hide show
  1. {node_walk-0.4.0 → node_walk-0.5.0}/.github/workflows/ci.yml +8 -0
  2. {node_walk-0.4.0 → node_walk-0.5.0}/CHANGELOG.md +28 -0
  3. {node_walk-0.4.0 → node_walk-0.5.0}/PKG-INFO +1 -1
  4. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/resolution/calls.py +1 -1
  5. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/resolution/receiver.py +30 -9
  6. {node_walk-0.4.0 → node_walk-0.5.0}/.github/workflows/release.yml +0 -0
  7. {node_walk-0.4.0 → node_walk-0.5.0}/.gitignore +0 -0
  8. {node_walk-0.4.0 → node_walk-0.5.0}/LICENSE +0 -0
  9. {node_walk-0.4.0 → node_walk-0.5.0}/README.md +0 -0
  10. {node_walk-0.4.0 → node_walk-0.5.0}/plans/binding-and-receiver-resolution-plan.md +0 -0
  11. {node_walk-0.4.0 → node_walk-0.5.0}/plans/graph-explorer-ux-plan.md +0 -0
  12. {node_walk-0.4.0 → node_walk-0.5.0}/plans/plan.md +0 -0
  13. {node_walk-0.4.0 → node_walk-0.5.0}/plans/receiver-resolution-plan.md +0 -0
  14. {node_walk-0.4.0 → node_walk-0.5.0}/plans/relationship-resolution-redesign.md +0 -0
  15. {node_walk-0.4.0 → node_walk-0.5.0}/plans/traversable-graph.md +0 -0
  16. {node_walk-0.4.0 → node_walk-0.5.0}/pyproject.toml +0 -0
  17. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/__init__.py +0 -0
  18. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/analysis/__init__.py +0 -0
  19. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/analysis/base.py +0 -0
  20. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/analysis/python/__init__.py +0 -0
  21. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/analysis/python/analyzer.py +0 -0
  22. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/analysis/python/scope.py +0 -0
  23. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/analysis/python/visitor.py +0 -0
  24. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/analysis/python_analyzer.py +0 -0
  25. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/cli/__init__.py +0 -0
  26. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/cli/main.py +0 -0
  27. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/indexer.py +0 -0
  28. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/ir/__init__.py +0 -0
  29. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/ir/enums.py +0 -0
  30. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/ir/models.py +0 -0
  31. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/query/__init__.py +0 -0
  32. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/query/engine.py +0 -0
  33. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/query/tree_formatter.py +0 -0
  34. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/resolution/__init__.py +0 -0
  35. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/resolution/base.py +0 -0
  36. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/resolution/bindings.py +0 -0
  37. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/resolution/imports.py +0 -0
  38. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/resolution/inheritance.py +0 -0
  39. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/storage/__init__.py +0 -0
  40. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/storage/base.py +0 -0
  41. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/storage/repository.py +0 -0
  42. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/storage/schema.py +0 -0
  43. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/storage/sqlite_store.py +0 -0
  44. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/web/__init__.py +0 -0
  45. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/web/app.js +0 -0
  46. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/web/index.html +0 -0
  47. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/web/server.py +0 -0
  48. {node_walk-0.4.0 → node_walk-0.5.0}/src/node_walk/web/style.css +0 -0
  49. {node_walk-0.4.0 → node_walk-0.5.0}/tests/fixtures/nested_project/base.py +0 -0
  50. {node_walk-0.4.0 → node_walk-0.5.0}/tests/fixtures/nested_project/impl.py +0 -0
  51. {node_walk-0.4.0 → node_walk-0.5.0}/tests/fixtures/simple_project/services.py +0 -0
  52. {node_walk-0.4.0 → node_walk-0.5.0}/tests/test_indexer.py +0 -0
  53. {node_walk-0.4.0 → node_walk-0.5.0}/tests/test_ir.py +0 -0
  54. {node_walk-0.4.0 → node_walk-0.5.0}/tests/test_python_analyzer.py +0 -0
  55. {node_walk-0.4.0 → node_walk-0.5.0}/tests/test_query_engine.py +0 -0
  56. {node_walk-0.4.0 → node_walk-0.5.0}/tests/test_resolution.py +0 -0
  57. {node_walk-0.4.0 → node_walk-0.5.0}/tests/test_resolution_bindings.py +0 -0
  58. {node_walk-0.4.0 → node_walk-0.5.0}/tests/test_storage.py +0 -0
  59. {node_walk-0.4.0 → node_walk-0.5.0}/tests/test_web_server.py +0 -0
@@ -3,8 +3,16 @@ name: CI
3
3
  on:
4
4
  push:
5
5
  branches: [ "main", "master" ]
6
+ paths-ignore:
7
+ - "plans/**"
8
+ - "README.md"
9
+ - "CHANGELOG.md"
6
10
  pull_request:
7
11
  branches: [ "main", "master" ]
12
+ paths-ignore:
13
+ - "plans/**"
14
+ - "README.md"
15
+ - "CHANGELOG.md"
8
16
 
9
17
  jobs:
10
18
  test:
@@ -11,15 +11,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ---
13
13
 
14
+ ## [0.5.0] - 2026-08-27
15
+ ### Added
16
+ - **Inheritance Traversal in Member Resolution**: Enabled the receiver resolution service to traverse class inheritance (checking both `EXTENDS` and `IMPLEMENTS` edges) when looking up methods, allowing inherited methods to resolve correctly.
17
+
18
+ ### Changed
19
+ - **Refactoring**: Cleaned up inline imports in the resolution modules (`calls.py` and `receiver.py`) by moving them to the top-level module scope.
20
+
21
+ ---
22
+
14
23
  ## [0.4.0] - 2026-08-26
24
+ ### Added
25
+ - **Chained Receiver Resolution**: Introduced `ReceiverService` and `BindingIndex` to resolve complex, nested receiver chains (e.g. `self.repo.session.get()`) segment by segment.
26
+ - **FastAPI Dependency Injection**: Enhanced parameter and assignment extraction to support FastAPI `Depends(...)` patterns, recording provider references and annotations without creating false call edges to the `Depends` wrapper.
27
+ - **Constructor & Attribute Propagation**: Added logic to trace type contracts established in class initializers (`__init__`) and pass bindings down constructor parameter boundaries.
15
28
 
16
29
  ---
17
30
 
18
31
  ## [0.3.1] - 2026-08-25
32
+ ### Added
33
+ - **Fact-Based Resolution Pipeline**: Shifted the resolution model from direct AST evaluation to a two-phase pipeline using a new `RelationshipFact` SQLite storage layer. Decoupled extraction from graph-edge materialization.
34
+ - **Modular Resolvers**: Implemented specialized fact resolvers:
35
+ - `ImportResolver` for mapping module imports.
36
+ - `BindingResolver` for typed annotations and assignments.
37
+ - `ClassMemberCallResolver` for same-class member resolution.
38
+ - `InFileCallResolver` for local file calls.
39
+ - `ConstructorCallResolver` to map constructor invocations to `__init__` methods.
40
+ - `CrossFileCallResolver` for cross-file call resolution.
41
+ - `InheritanceResolver` for resolving inheritance relationships.
42
+
43
+ ### Changed
44
+ - **CI/CD Security**: Migrated PyPI deployment workflow to utilize PyPI Trusted Publishers (environments) and GitHub App authentication.
19
45
 
20
46
  ---
21
47
 
22
48
  ## [0.3.0] - 2026-08-23
49
+ ### Added
50
+ - **Automated Releases**: Implemented hatch-vcs for automatic versioning. Configured automated tagging, release workflow, and package publication to PyPI.
23
51
 
24
52
  ---
25
53
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: node-walk
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Semantic code intelligence — local-first graph of your codebase for humans and LLMs
5
5
  Author: CodeGraph Contributors
6
6
  License: MIT
@@ -4,6 +4,7 @@ from node_walk.ir.enums import FactStatus, FactType, SymbolKind
4
4
  from node_walk.ir.models import RelationshipFact, Symbol
5
5
  from node_walk.storage.base import GraphStore
6
6
  from node_walk.resolution.base import FactResolver, ResolutionResult
7
+ from node_walk.resolution.receiver import BindingIndex, ReceiverService
7
8
 
8
9
 
9
10
  _BUILTINS = {
@@ -220,7 +221,6 @@ class CrossFileCallResolver(FactResolver):
220
221
  return "CrossFileCallResolver"
221
222
 
222
223
  def run(self, store: GraphStore, facts: list[RelationshipFact]) -> int:
223
- from node_walk.resolution.receiver import BindingIndex, ReceiverService
224
224
  self._index = BindingIndex(store)
225
225
  self._service = ReceiverService(store, self._index)
226
226
  return super().run(store, facts)
@@ -1,7 +1,7 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import Optional
3
3
 
4
- from node_walk.ir.enums import FactStatus, FactType, SymbolKind
4
+ from node_walk.ir.enums import FactStatus, FactType, SymbolKind, RelationshipType
5
5
  from node_walk.ir.models import RelationshipFact, Symbol
6
6
  from node_walk.storage.base import GraphStore
7
7
 
@@ -171,18 +171,39 @@ class ReceiverService:
171
171
  )
172
172
 
173
173
  def resolve_member(self, receiver_res: ReceiverResolution, member_name: str) -> SymbolResolution | None:
174
+
174
175
  receiver_sym = self._store.get_symbol(receiver_res.resolved_symbol_id)
175
176
  if not receiver_sym:
176
177
  return None
177
178
 
178
- target_qname = f"{receiver_sym.qualified_name}.{member_name}"
179
- candidates = self._store.find_symbols_by_qualified_name(target_qname)
180
- if candidates:
181
- return SymbolResolution(
182
- resolved_symbol_id=candidates[0].id,
183
- confidence=receiver_res.confidence,
184
- diagnostics={"strategy": "member_lookup"}
185
- )
179
+ queue = [receiver_sym.id]
180
+ seen = set()
181
+
182
+ while queue:
183
+ current_id = queue.pop(0)
184
+ if current_id in seen:
185
+ continue
186
+ seen.add(current_id)
187
+
188
+ current_sym = self._store.get_symbol(current_id)
189
+ if not current_sym:
190
+ continue
191
+
192
+ target_qname = f"{current_sym.qualified_name}.{member_name}"
193
+ candidates = self._store.find_symbols_by_qualified_name(target_qname)
194
+ if candidates:
195
+ return SymbolResolution(
196
+ resolved_symbol_id=candidates[0].id,
197
+ confidence=receiver_res.confidence,
198
+ diagnostics={"strategy": "member_lookup", "class": current_sym.name}
199
+ )
200
+
201
+ # If not found, check base classes
202
+ extends = self._store.get_relationships_from(current_id, RelationshipType.EXTENDS)
203
+ implements = self._store.get_relationships_from(current_id, RelationshipType.IMPLEMENTS)
204
+ for rel in extends + implements:
205
+ if rel.target_id:
206
+ queue.append(rel.target_id)
186
207
 
187
208
  return None
188
209
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes