Support edge labels for one-to-one and through relations 🩷 - #5
Conversation
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
test/edge-labels.test.js (1)
5-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRestore
Module._loadafter the test to avoid global side effects.The
vscodemock replacesModule._loadglobally but never restores it. Whilenode --testtypically runs each file in its own process, restoring the original loader is good hygiene and prevents interference if test isolation changes.♻️ Proposed fix
const originalLoad = Module._load; Module._load = function (request, parent, isMain) { if (request === 'vscode') { return {}; } return originalLoad.call(this, request, parent, isMain); }; + +// Restore the original loader after all tests in this file complete. +test.after(() => { + Module._load = originalLoad; +});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/edge-labels.test.js` around lines 5 - 11, Restore Module._load to originalLoad after the test completes, ensuring the temporary vscode mock in the Module._load override does not persist globally. Use the existing originalLoad symbol and the test’s teardown mechanism rather than changing the mock behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/parser.ts`:
- Around line 112-117: Update the regular expression in extractThroughModel to
require a word boundary immediately before “through”, preventing matches within
longer argument names while preserving the existing value-capture behavior.
---
Nitpick comments:
In `@test/edge-labels.test.js`:
- Around line 5-11: Restore Module._load to originalLoad after the test
completes, ensuring the temporary vscode mock in the Module._load override does
not persist globally. Use the existing originalLoad symbol and the test’s
teardown mechanism rather than changing the mock behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 42da5480-f993-45a1-beac-3b80f1c70598
📒 Files selected for processing (5)
package.jsonsrc/graphWebview.tssrc/parser.tssrc/types.tstest/edge-labels.test.js
|
Thanks for the contribution! The through-model handling with the |
Mirrors the throughModel field added to the TypeScript parser in #5 (thanks @kingrubic). Extracts `through=` from ManyToManyField args and emits the intermediate model name in the JSON schema under `throughModel`, keeping the CLI and the VS Code extension in lock-step. Version bump + publish deferred to the next automated firing.
- Python parser: emit throughModel on M2M fields (parity with TS) - Bump extension 0.3.0 -> 0.3.1 - Bump CLI 1.0.3 -> 1.0.4 - server.json aligned to 1.0.4 for MCP Registry - CHANGELOG: credit @kingrubic (PR #5) for throughModel Co-authored-by: kingrubic <baozidoge2@gmail.com>
* fix: label one-to-one and through relations * test: harden through relation parsing
Mirrors the throughModel field added to the TypeScript parser in #5 (thanks @kingrubic). Extracts `through=` from ManyToManyField args and emits the intermediate model name in the JSON schema under `throughModel`, keeping the CLI and the VS Code extension in lock-step. Version bump + publish deferred to the next automated firing.
- Python parser: emit throughModel on M2M fields (parity with TS) - Bump extension 0.3.0 -> 0.3.1 - Bump CLI 1.0.3 -> 1.0.4 - server.json aligned to 1.0.4 for MCP Registry - CHANGELOG: credit @kingrubic (PR #5) for throughModel Co-authored-by: kingrubic <baozidoge2@gmail.com>
Pick a models.py, pick two commits, get a typed diff rendered as a
copy-paste-ready markdown fragment for PR descriptions.
Blueprint distilled from proven prior art (research-first):
Atlas (ariga/atlas) — analyzer/fixer divorce, typed events grouped
by table, color-coded chips. Copied: structured event model,
grouping, first-class renames.
Prisma migrate diff — renames as their own event, never as
drop+add. Copied verbatim.
Community pattern (git log --follow + AST diff on models.py) —
packaged for the first time.
Structured events, not text
AddModel / DropModel / RenameModel (confidence-scored)
ModifyModel
AddField / DropField / RenameField (confidence-scored)
ChangeFieldType (AutoField -> BigAutoField)
ChangeFieldOption (whitelisted: null/blank/unique/default/db_index/
primary_key/max_length/max_digits/decimal_places/on_delete/
related_name/auto_now/auto_now_add — verbose_name/help_text are
excluded as noise)
ChangeRelation (FK target/kind switch)
Rename detection heuristic
Field: same type + name-similarity Levenshtein greater than 0.7
Model: 0.5 * field-shape-Jaccard + 0.35 * field-name-Jaccard +
0.15 * name-Levenshtein-similarity
Both use "top-of-both" matching so ambiguous pairs are held back.
Confidence is returned on every rename event for a confirm-UI later.
Git wrapper (src/git.ts)
execFile-based, no shell interpolation
gitLogFollow / blobShaFor / gitShowFile
BlobCache LRU keyed on BLOB SHA (not commit SHA) so history walks
with no models.py churn share parsed snapshots for free
Command djangoOrmLens.showDiff
If more than one models.py, QuickPick to choose target
Two QuickPicks for from-commit / to-commit (last 200 commits touching
the file, most-recent first)
Diff runs on parsed models, not text
Result opens as an untitled markdown buffer with commit metadata header
Tests
13 new schema-diff snapshot cases including rename detection, option
whitelist, ordering guarantees, and markdown export.
Full suite 66/66 green.
Deferred to follow-up
ER-diagram overlay (Mermaid classDef added/dropped/renamed)
Rename confirmation chips in a webview drawer
CLI parity (django-orm-lens diff --from <ref> --to <ref> --json)
Right-click a field or model, pick a template, get a Django ORM snippet
inserted at the cursor (with tab-stops) or in a fresh untitled Python
buffer if no editor is focused.
Blueprint distilled from proven prior art (research-first):
DataGrip / DBeaver Right-click submenu of templates; output
goes into an editable buffer, not
clipboard-silently. Copied verbatim.
Prisma Studio Best filter UX but zero code export.
Their gap is exactly what we fill.
django-silk Cluster N+1: pick a template on an FK,
we automatically add .select_related.
Django docs Grammar gotchas we honour:
related_name overrides <lower>_set
.select_related for FK/O2O only
.prefetch_related for M2M/reverse FK
.values().distinct() before .distinct()
MVP templates (grouped filter -> perf -> aggregate -> projection)
.filter(field=<value>) scalar or FK; FK auto-appends
.select_related for the FK
.select_related(fk) focused N+1 fix for FK/O2O
.prefetch_related(m2m) M2M fetch batching
.annotate(rel_count=Count(access)) reverse-FK count with order_by;
honours related_name
.values(field).distinct() distinct scalar values
.only(field) column pruning
.objects.all() base QuerySet for a model target
Insertion strategy (VS Code convention)
active Python editor SnippetString insertSnippet at cursor with
tab-stops on placeholders (${1:value})
no active editor new untitled Python doc with a `from ... import`
boilerplate line, then insert the snippet
Deferred to follow-up (v2 of this feature)
Multi-hop path picker in the ER-diagram webview
Prefetch(...) with a nested filter
Q() OR-composition toggle
Subquery + OuterRef wizard
Tests: +8 pure snapshot cases (85/85 total, up from 77). Full suite
green, tsc clean.
All five WOW features from Discussion #27 now shipped:
#1 Impact Analysis 53e51f2
#2 Query Builder HEAD
#3 Inline Fixes b99899a
#4 Factory Generator 473d3ff
#5 Schema Diff 040f2bd
Summary
through=arguments and include the intermediate model in edge labelsTests
npm testnpm run buildnpm run package -- --out /tmp/django-orm-lens-issue-2.vsixgit diff --checkCloses #2
Summary by CodeRabbit
testscript to build the extension and run the Node test runner.