commit:     e645712580e245615099ca4138ebc8d1647b6a1f
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Sun Sep  1 20:46:08 2024 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Sun Sep  1 21:14:10 2024 +0000
URL:        
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=e6457125

fix with tree-sitter 0.23

Once again they broke the API, this time around the .captures() call.
They changed it by a lot, returning a dict of capture names to captures.

Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 pyproject.toml                     |  4 +--
 src/pkgcheck/bash/__init__.py      |  8 +++---
 src/pkgcheck/checks/codingstyle.py | 57 +++++++++++++++++++-------------------
 src/pkgcheck/checks/eclass.py      | 14 +++++-----
 src/pkgcheck/checks/python.py      | 14 ++++------
 src/pkgcheck/checks/reserved.py    |  8 +++---
 src/pkgcheck/checks/rust.py        |  4 +--
 7 files changed, 53 insertions(+), 56 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index 0b7e20fd..bf20ce94 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ requires = [
        "lazy-object-proxy",
        "lxml",
        "pathspec",
-       "tree-sitter>=0.21.0",
+       "tree-sitter>=0.23.0",
        "tree-sitter-bash>=0.21.0",
        "snakeoil~=0.10.8",
        "pkgcore~=0.12.25",
@@ -46,7 +46,7 @@ dependencies = [
        "lazy-object-proxy",
        "lxml",
        "pathspec",
-       "tree-sitter>=0.22.2",
+       "tree-sitter>=0.23.2",
        "tree-sitter-bash>=0.21.0",
        "snakeoil~=0.10.8",
        "pkgcore~=0.12.25",

diff --git a/src/pkgcheck/bash/__init__.py b/src/pkgcheck/bash/__init__.py
index 0c8a7a13..1b47881c 100644
--- a/src/pkgcheck/bash/__init__.py
+++ b/src/pkgcheck/bash/__init__.py
@@ -1,5 +1,7 @@
 """bash parsing support"""
 
+from itertools import chain
+
 import tree_sitter_bash
 from tree_sitter import Language, Parser, Query
 
@@ -31,13 +33,11 @@ class ParseTree:
         for x in self.tree.root_node.children:
             # skip nodes in function scope
             if x.type != "function_definition":
-                for node, _ in query.captures(x):
-                    yield node
+                yield from chain.from_iterable(query.captures(x).values())
 
     def func_query(self, query: Query):
         """Run a given parse tree query returning only those nodes in function 
scope."""
         for x in self.tree.root_node.children:
             # only return nodes in function scope
             if x.type == "function_definition":
-                for node, _ in query.captures(x):
-                    yield node
+                yield from chain.from_iterable(query.captures(x).values())

diff --git a/src/pkgcheck/checks/codingstyle.py 
b/src/pkgcheck/checks/codingstyle.py
index 42bd0004..20628481 100644
--- a/src/pkgcheck/checks/codingstyle.py
+++ b/src/pkgcheck/checks/codingstyle.py
@@ -89,8 +89,8 @@ class BadCommandsCheck(Check):
     )
 
     def feed(self, pkg):
-        for func_node, _ in bash.func_query.captures(pkg.tree.root_node):
-            for node, _ in bash.cmd_query.captures(func_node):
+        for func_node in 
bash.func_query.captures(pkg.tree.root_node).get("func", ()):
+            for node in bash.cmd_query.captures(func_node).get("call", ()):
                 call = pkg.node_str(node)
                 name = pkg.node_str(node.child_by_field_name("name"))
                 lineno, _colno = node.start_point
@@ -134,8 +134,8 @@ class EendMissingArgCheck(Check):
     known_results = frozenset([EendMissingArg])
 
     def feed(self, pkg):
-        for func_node, _ in bash.func_query.captures(pkg.tree.root_node):
-            for node, _ in bash.cmd_query.captures(func_node):
+        for func_node in 
bash.func_query.captures(pkg.tree.root_node).get("func", ()):
+            for node in bash.cmd_query.captures(func_node).get("call", ()):
                 line = pkg.node_str(node)
                 if line == "eend":
                     lineno, _ = node.start_point
@@ -639,7 +639,7 @@ class MetadataVarCheck(Check):
     @verify_vars("HOMEPAGE", "KEYWORDS")
     def _raw_text(self, var, node, value, pkg):
         matches = []
-        for var_node, _ in bash.var_query.captures(node):
+        for var_node in bash.var_query.captures(node).get("var", ()):
             matches.append(pkg.node_str(var_node.parent))
         if matches:
             yield ReferenceInMetadataVar(var, stable_unique(matches), pkg=pkg)
@@ -647,7 +647,7 @@ class MetadataVarCheck(Check):
     @verify_vars("LICENSE")
     def _raw_text_license(self, var, node, value, pkg):
         matches = []
-        for var_node, _ in bash.var_query.captures(node):
+        for var_node in bash.var_query.captures(node).get("var", ()):
             var_str = pkg.node_str(var_node.parent).strip()
             if var_str in ["$LICENSE", "${LICENSE}"]:
                 continue  # LICENSE in LICENSE is ok
@@ -718,7 +718,7 @@ class MetadataVarCheck(Check):
                             line=pkg.node_str(node), lineno=lineno + 1, pkg=pkg
                         )
                 elif pkg.node_str(value_node.prev_sibling) == "=":
-                    for var_node, _ in bash.var_query.captures(value_node):
+                    for var_node in 
bash.var_query.captures(value_node).get("var", ()):
                         if (
                             pkg.node_str(var_node) == name
                             and 
self.canonicalize_assign(pkg.node_str(var_node.parent)) == value_str
@@ -878,12 +878,12 @@ class InheritsCheck(Check):
         # collect globally defined functions in ebuild
         defined_funcs = {
             pkg.node_str(func_node.child_by_field_name("name"))
-            for func_node, _ in bash.func_query.captures(pkg.tree.root_node)
+            for func_node in 
bash.func_query.captures(pkg.tree.root_node).get("func", ())
         }
 
         # register variables assigned in ebuilds
         assigned_vars = dict()
-        for node, _ in bash.var_assign_query.captures(pkg.tree.root_node):
+        for node in 
bash.var_assign_query.captures(pkg.tree.root_node).get("assign", ()):
             name = pkg.node_str(node.child_by_field_name("name"))
             if eclass := self.get_eclass(name, pkg):
                 assigned_vars[name] = eclass
@@ -892,7 +892,7 @@ class InheritsCheck(Check):
         weak_used_eclasses = set()
         # match captured commands with eclasses
         used = defaultdict(list)
-        for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
+        for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", 
()):
             call = pkg.node_str(node)
             name = pkg.node_str(node.child_by_field_name("name"))
             if name == "inherit":
@@ -914,7 +914,7 @@ class InheritsCheck(Check):
                     weak_used_eclasses.add(eclass)
 
         # match captured variables with eclasses
-        for node, _ in bash.var_query.captures(pkg.tree.root_node):
+        for node in bash.var_query.captures(pkg.tree.root_node).get("var", ()):
             name = pkg.node_str(node)
             if node.parent.type == "unset_command":
                 continue
@@ -1114,12 +1114,12 @@ class VariableScopeCheck(Check):
                     scoped_vars.setdefault(eapi, {}).setdefault(phase, 
set()).add(variable)
     scoped_vars = ImmutableDict(scoped_vars)
 
-    def feed(self, pkg):
-        for func_node, _ in bash.func_query.captures(pkg.tree.root_node):
+    def feed(self, pkg: bash.ParseTree):
+        for func_node in 
bash.func_query.captures(pkg.tree.root_node).get("func", ()):
             func_name = pkg.node_str(func_node.child_by_field_name("name"))
             if variables := self.scoped_vars[pkg.eapi].get(func_name):
                 usage = defaultdict(set)
-                for var_node, _ in bash.var_query.captures(func_node):
+                for var_node in bash.var_query.captures(func_node).get("var", 
()):
                     var_name = pkg.node_str(var_node)
                     if var_name in variables:
                         lineno, _colno = var_node.start_point
@@ -1130,7 +1130,7 @@ class VariableScopeCheck(Check):
         global_usage = defaultdict(set)
         for global_node in pkg.tree.root_node.children:
             if global_node.type not in ("function_definition", "ERROR"):
-                for var_node, _ in bash.var_query.captures(global_node):
+                for var_node in 
bash.var_query.captures(global_node).get("var", ()):
                     var_name = pkg.node_str(var_node)
                     if var_name in self.not_global_scope:
                         lineno, _colno = var_node.start_point
@@ -1271,14 +1271,14 @@ class _UnquotedVariablesCheck(Check):
         # Default: The variable should be quoted
         return True
 
-    def _feed(self, item):
+    def _feed(self, item: bash.ParseTree):
         if item.tree.root_node.has_error:
             # Do not run this check if the parse tree contains errors, as it
             # might result in false positives. This check appears to be quite
             # expensive though...
             return
         hits = defaultdict(set)
-        for var_node, _ in bash.var_query.captures(item.tree.root_node):
+        for var_node in 
bash.var_query.captures(item.tree.root_node).get("var", ()):
             var_name = item.node_str(var_node)
             if var_name in self.var_names:
                 if self._var_needs_quotes(item, var_node):
@@ -1390,7 +1390,7 @@ class DoCompressedFilesCheck(Check):
     )
 
     def feed(self, pkg):
-        for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
+        for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", 
()):
             call_name = pkg.node_str(node.child_by_field_name("name"))
             if call_name not in self.functions:
                 continue
@@ -1446,7 +1446,7 @@ class NonPosixCheck(Check):
             prev_arg = arg
 
     def feed(self, pkg):
-        for call_node, _ in bash.cmd_query.captures(pkg.tree.root_node):
+        for call_node in 
bash.cmd_query.captures(pkg.tree.root_node).get("call", ()):
             call_name = pkg.node_str(call_node.child_by_field_name("name"))
             if call_name in ("head", "tail"):
                 yield from self.check_head_tail(pkg, call_node, call_name)
@@ -1476,14 +1476,13 @@ class GlobCheck(Check):
         self.glob_query = bash.query('(concatenation (word) @word (.match? 
@word "[*?]")) @usage')
 
     def feed(self, pkg):
-        for node, capture in self.glob_query.captures(pkg.tree.root_node):
-            if capture == "usage":
-                for var_node, _ in bash.var_query.captures(node):
-                    var_name = pkg.node_str(var_node)
-                    if var_name == "DISTDIR":
-                        lineno, _colno = node.start_point
-                        yield GlobDistdir(line=pkg.node_str(node), 
lineno=lineno + 1, pkg=pkg)
-                        break
+        for node in self.glob_query.captures(pkg.tree.root_node).get("usage", 
()):
+            for var_node in bash.var_query.captures(node).get("var", ()):
+                var_name = pkg.node_str(var_node)
+                if var_name == "DISTDIR":
+                    lineno, _colno = node.start_point
+                    yield GlobDistdir(line=pkg.node_str(node), lineno=lineno + 
1, pkg=pkg)
+                    break
 
 
 class VariableShadowed(results.LinesResult, results.Warning):
@@ -1528,7 +1527,7 @@ class DeclarationShadowedCheck(Check):
                 if value_node := node.child_by_field_name("value"):
                     if any(
                         pkg.node_str(node) == used_name
-                        for node, _ in bash.var_query.captures(value_node)
+                        for node in 
bash.var_query.captures(value_node).get("var", ())
                     ):
                         continue
                 var_assigns[used_name].append(node)
@@ -1570,7 +1569,7 @@ class SandboxCallCheck(Check):
     functions = frozenset({"addread", "addwrite", "adddeny", "addpredict"})
 
     def feed(self, pkg: bash.ParseTree):
-        for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
+        for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", 
()):
             name = pkg.node_str(node.child_by_field_name("name"))
             if name in self.functions:
                 args = node.children_by_field_name("argument")

diff --git a/src/pkgcheck/checks/eclass.py b/src/pkgcheck/checks/eclass.py
index 394ef192..52bcea6e 100644
--- a/src/pkgcheck/checks/eclass.py
+++ b/src/pkgcheck/checks/eclass.py
@@ -164,7 +164,7 @@ class EclassUsageCheck(Check):
 
         # scan for any misplaced @PRE_INHERIT variables
         if pre_inherits:
-            for node, _ in bash.var_assign_query.captures(pkg.tree.root_node):
+            for node in 
bash.var_assign_query.captures(pkg.tree.root_node).get("assign", ()):
                 var_name = pkg.node_str(node.child_by_field_name("name"))
                 lineno, _colno = node.start_point
                 if var_name in pre_inherits and lineno > 
pre_inherits[var_name]:
@@ -184,7 +184,7 @@ class EclassUsageCheck(Check):
 
         # scan for usage of @USER_VARIABLE variables
         if user_variables:
-            for node, _ in bash.var_assign_query.captures(pkg.tree.root_node):
+            for node in 
bash.var_assign_query.captures(pkg.tree.root_node).get("assign", ()):
                 var_name = pkg.node_str(node.child_by_field_name("name"))
                 if var_name in user_variables:
                     lineno, _colno = node.start_point
@@ -205,7 +205,7 @@ class EclassUsageCheck(Check):
 
         # scan for usage of @DEPRECATED variables
         if deprecated:
-            for node, _ in bash.var_query.captures(pkg.tree.root_node):
+            for node in bash.var_query.captures(pkg.tree.root_node).get("var", 
()):
                 var_name = pkg.node_str(node)
                 if var_name in deprecated:
                     lineno, _colno = node.start_point
@@ -230,7 +230,7 @@ class EclassUsageCheck(Check):
 
         # scan for usage of @DEPRECATED functions
         if deprecated:
-            for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
+            for node in 
bash.cmd_query.captures(pkg.tree.root_node).get("call", ()):
                 func_name = pkg.node_str(node.child_by_field_name("name"))
                 if func_name in deprecated:
                     lineno, _colno = node.start_point
@@ -258,7 +258,7 @@ class EclassUsageCheck(Check):
         if pkg.inherit:
             inherited: set[str] = set()
             inherits: list[tuple[list[str], int]] = []
-            for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
+            for node in 
bash.cmd_query.captures(pkg.tree.root_node).get("call", ()):
                 name = pkg.node_str(node.child_by_field_name("name"))
                 if name == "inherit":
                     call = pkg.node_str(node)
@@ -342,14 +342,14 @@ class EclassParseCheck(Check):
 
     def feed(self, eclass):
         func_prefix = f"{eclass.name}_"
-        for func_node, _ in bash.func_query.captures(eclass.tree.root_node):
+        for func_node in 
bash.func_query.captures(eclass.tree.root_node).get("func", ()):
             func_name = eclass.node_str(func_node.child_by_field_name("name"))
             if not func_name.startswith(func_prefix):
                 continue
             phase = func_name[len(func_prefix) :]
             if variables := self.eclass_phase_vars(eclass, phase):
                 usage = defaultdict(set)
-                for var_node, _ in bash.var_query.captures(func_node):
+                for var_node in bash.var_query.captures(func_node).get("var", 
()):
                     var_name = eclass.node_str(var_node)
                     if var_name in variables:
                         lineno, _colno = var_node.start_point

diff --git a/src/pkgcheck/checks/python.py b/src/pkgcheck/checks/python.py
index 13ec6311..2c46885a 100644
--- a/src/pkgcheck/checks/python.py
+++ b/src/pkgcheck/checks/python.py
@@ -1,7 +1,7 @@
-import itertools
 import re
 import typing
 from collections import defaultdict
+from itertools import takewhile
 from operator import attrgetter
 
 from pkgcore import fetch
@@ -358,7 +358,7 @@ class PythonCheck(Check):
         uses_setuptools_scm = False
         pep517_value = None
 
-        for var_node, _ in bash.var_assign_query.captures(pkg.tree.root_node):
+        for var_node in 
bash.var_assign_query.captures(pkg.tree.root_node).get("assign", ()):
             var_name = pkg.node_str(var_node.child_by_field_name("name"))
 
             if var_name == "DISTUTILS_OPTIONAL":
@@ -407,7 +407,7 @@ class PythonCheck(Check):
         for var_node in pkg.global_query(bash.var_assign_query):
             name = pkg.node_str(var_node.child_by_field_name("name"))
             if name in {"DEPEND", "BDEPEND"}:
-                for call_node, _ in bash.cmd_query.captures(var_node):
+                for call_node in bash.cmd_query.captures(var_node).get("call", 
()):
                     call_name = 
pkg.node_str(call_node.child_by_field_name("name"))
                     if call_name == any_dep_func and len(call_node.children) > 
1:
                         check_deps[name].update(
@@ -457,7 +457,7 @@ class PythonCheck(Check):
     def check_python_check_deps(self, pkg, func_node, python_check_deps, 
any_dep_func):
         has_version_checked_deps = defaultdict(set)
         has_version_lines = set()
-        for node, _ in bash.cmd_query.captures(func_node):
+        for node in bash.cmd_query.captures(func_node).get("call", ()):
             call_name = pkg.node_str(node.child_by_field_name("name"))
             if call_name == "has_version":
                 lineno, _ = node.start_point
@@ -548,7 +548,7 @@ class PythonCheck(Check):
 
         any_dep_func = self.eclass_any_dep_func[eclass]
         python_check_deps = self.build_python_gen_any_dep_calls(pkg, 
any_dep_func)
-        for func_node, _ in bash.func_query.captures(pkg.tree.root_node):
+        for func_node in 
bash.func_query.captures(pkg.tree.root_node).get("func", ()):
             func_name = pkg.node_str(func_node.child_by_field_name("name"))
             if func_name == "python_check_deps":
                 yield from self.check_python_check_deps(
@@ -664,9 +664,7 @@ class PythonCompatCheck(Check):
             return
 
         # determine python impls to target
-        targets = set(
-            itertools.takewhile(lambda x: x != latest_target, 
reversed(available_targets))
-        )
+        targets = set(takewhile(lambda x: x != latest_target, 
reversed(available_targets)))
 
         if targets:
             try:

diff --git a/src/pkgcheck/checks/reserved.py b/src/pkgcheck/checks/reserved.py
index f99a9050..78f4e357 100644
--- a/src/pkgcheck/checks/reserved.py
+++ b/src/pkgcheck/checks/reserved.py
@@ -42,14 +42,14 @@ class _ReservedNameCheck(Check):
             "function",
             {
                 item.node_str(node.child_by_field_name("name")): 
node.start_point
-                for node, _ in bash.func_query.captures(item.tree.root_node)
+                for node in 
bash.func_query.captures(item.tree.root_node).get("func", ())
             },
         )
         used_variables = {
             item.node_str(node.child_by_field_name("name")): node.start_point
-            for node, _ in bash.var_assign_query.captures(item.tree.root_node)
+            for node in 
bash.var_assign_query.captures(item.tree.root_node).get("assign", ())
         }
-        for node, _ in bash.var_query.captures(item.tree.root_node):
+        for node in bash.var_query.captures(item.tree.root_node).get("var", 
()):
             if (name := item.node_str(node)) not in 
self.variables_usage_whitelist:
                 used_variables.setdefault(name, node.start_point)
         yield from self._check("variable", used_variables)
@@ -144,7 +144,7 @@ class EbuildReservedCheck(_ReservedNameCheck):
         for used_name, *args, lineno in self._feed(pkg):
             yield EbuildReservedName(*args, lineno=lineno, line=used_name, 
pkg=pkg)
 
-        for node, _ in bash.func_query.captures(pkg.tree.root_node):
+        for node in bash.func_query.captures(pkg.tree.root_node).get("func", 
()):
             used_name = pkg.node_str(node.child_by_field_name("name"))
             if used_name in self.phases_hooks[str(pkg.eapi)]:
                 lineno, _ = node.start_point

diff --git a/src/pkgcheck/checks/rust.py b/src/pkgcheck/checks/rust.py
index 397738b9..7a5cbdad 100644
--- a/src/pkgcheck/checks/rust.py
+++ b/src/pkgcheck/checks/rust.py
@@ -60,7 +60,7 @@ class RustCheck(Check):
                             return
 
     def _verify_cargo_crate_uris(self, pkg: bash.ParseTree):
-        for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
+        for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", 
()):
             call_name = pkg.node_str(node.child_by_field_name("name"))
             if call_name == "cargo_crate_uris":
                 row, _ = node.start_point
@@ -69,7 +69,7 @@ class RustCheck(Check):
                     node.child_count == 2
                     and any(
                         pkg.node_str(var_node) == "CRATES"
-                        for var_node, _ in 
bash.var_query.captures(node.children[1])
+                        for var_node in 
bash.var_query.captures(node.children[1]).get("var", ())
                     )
                 ):
                     yield SuboptimalCratesURICall(

Reply via email to