From f226478ee15ed9bcd302c1edb8afcf96fb84ca79 Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Mon, 20 Apr 2026 12:11:04 +0100 Subject: [PATCH] feat(python-scope): nested tuple destructuring for enumerate(d.items()) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two more for-loop typeBinding patterns: - `for i, (k, v) in enumerate(d.items())` — nested tuple destructuring where v is the value of the dict's items() yield. - `for v in d.values()` — explicit values() form (companion to items). Both bind the loop var to the dict identifier; the chain-follow unwraps via the dict-aware stripGeneric to the value type. Verification: - Flag-off: 191/191 (identical baseline). - Flag-on: 5 fail / 186 pass (was 6/185; +1 nested tuple test). - tsc --noEmit clean. --- .../core/ingestion/languages/python/query.ts | 27 +++++++++++++++++++ .../ingestion/languages/python/scopes.scm | 26 ++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/gitnexus/src/core/ingestion/languages/python/query.ts b/gitnexus/src/core/ingestion/languages/python/query.ts index b5f7a0d0e..fa6e07687 100644 --- a/gitnexus/src/core/ingestion/languages/python/query.ts +++ b/gitnexus/src/core/ingestion/languages/python/query.ts @@ -167,6 +167,33 @@ export const PYTHON_SCOPE_QUERY = ` attribute: (identifier) @_items)) (#eq? @_items "items")) @type-binding.alias +;; for i, (k, v) in enumerate(d.items()) — nested tuple destructuring. +;; Bind v (last id of the nested tuple) to d (the dict). +(for_statement + left: (pattern_list + (identifier) + (tuple_pattern + (identifier) + (identifier) @type-binding.name)) + right: (call + function: (identifier) @_enum + arguments: (argument_list + (call + function: (attribute + object: (identifier) @type-binding.type + attribute: (identifier) @_items)))) + (#eq? @_enum "enumerate") + (#eq? @_items "items")) @type-binding.alias + +;; for v in d.values() — bind v to d (dict-strip yields value type). +(for_statement + left: (identifier) @type-binding.name + right: (call + function: (attribute + object: (identifier) @type-binding.type + attribute: (identifier) @_values)) + (#eq? @_values "values")) @type-binding.alias + ;; Type bindings (variable annotations: \`u: User\` / \`u: User = x\`) (assignment left: (identifier) @type-binding.name diff --git a/gitnexus/src/core/ingestion/languages/python/scopes.scm b/gitnexus/src/core/ingestion/languages/python/scopes.scm index f30907819..2961a0eeb 100644 --- a/gitnexus/src/core/ingestion/languages/python/scopes.scm +++ b/gitnexus/src/core/ingestion/languages/python/scopes.scm @@ -180,6 +180,32 @@ attribute: (identifier) @_items)) (#eq? @_items "items")) @type-binding.alias +; for i, (k, v) in enumerate(d.items()) — nested tuple destructuring. +(for_statement + left: (pattern_list + (identifier) + (tuple_pattern + (identifier) + (identifier) @type-binding.name)) + right: (call + function: (identifier) @_enum + arguments: (argument_list + (call + function: (attribute + object: (identifier) @type-binding.type + attribute: (identifier) @_items)))) + (#eq? @_enum "enumerate") + (#eq? @_items "items")) @type-binding.alias + +; for v in d.values() — bind v to d (dict-strip yields value type). +(for_statement + left: (identifier) @type-binding.name + right: (call + function: (attribute + object: (identifier) @type-binding.type + attribute: (identifier) @_values)) + (#eq? @_values "values")) @type-binding.alias + ; ─── Type bindings: function return-type annotations ───────────────────── ; ; `def get_user() -> User:` — binds the function's NAME to its return