Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-tree-sitter for 
openSUSE:Factory checked in at 2025-01-28 14:59:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tree-sitter (Old)
 and      /work/SRC/openSUSE:Factory/.python-tree-sitter.new.2316 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-tree-sitter"

Tue Jan 28 14:59:50 2025 rev:2 rq:1240757 version:0.24.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-tree-sitter/python-tree-sitter.changes    
2024-12-03 20:49:11.164006114 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-tree-sitter.new.2316/python-tree-sitter.changes
  2025-01-28 15:00:47.554061405 +0100
@@ -1,0 +2,21 @@
+Tue Jan 28 09:15:06 UTC 2025 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to 0.24.0
+  * Additions:
+    - Language.copy()
+    - Language.node_kind_is_supertype(id)
+    - Language.__copy__()
+    - LogType (enum)
+    - Node.child_with_descendant(descendant)
+    - Node.field_name_for_named_child(descendant)
+    - Parser.print_dot_graphs(file)
+    - Parser.logger (getter + setter)
+    - Tree.copy()
+    - Tree.print_dot_graph(file)
+    - Tree.__copy__()
+  * Deprecations:
+    - Language(ptr: int)
+    - Node.child_containing_descendant(descendant):
+      use Node.child_with_descendant(descendant)
+
+-------------------------------------------------------------------

Old:
----
  tree-sitter-0.23.2.tar.gz

New:
----
  tree-sitter-0.24.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-tree-sitter.spec ++++++
--- /var/tmp/diff_new_pack.chiHft/_old  2025-01-28 15:00:47.962078273 +0100
+++ /var/tmp/diff_new_pack.chiHft/_new  2025-01-28 15:00:47.962078273 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-tree-sitter
 #
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2025 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-tree-sitter
-Version:        0.23.2
+Version:        0.24.0
 Release:        0
 Summary:        Python bindings to the Tree-sitter parsing library
 License:        MIT

++++++ tree-sitter-0.23.2.tar.gz -> tree-sitter-0.24.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/PKG-INFO 
new/tree-sitter-0.24.0/PKG-INFO
--- old/tree-sitter-0.23.2/PKG-INFO     2024-10-24 17:09:15.495078300 +0200
+++ new/tree-sitter-0.24.0/PKG-INFO     2025-01-17 05:57:38.271043500 +0100
@@ -1,11 +1,12 @@
 Metadata-Version: 2.1
 Name: tree-sitter
-Version: 0.23.2
+Version: 0.24.0
 Summary: Python bindings to the Tree-sitter parsing library
 Author-email: Max Brunsfeld <[email protected]>
 Project-URL: Homepage, https://tree-sitter.github.io/tree-sitter/
 Project-URL: Source, https://github.com/tree-sitter/py-tree-sitter
 Project-URL: Documentation, https://tree-sitter.github.io/py-tree-sitter/
+Project-URL: Discord, https://discord.gg/w7nTvsVJhm
 Keywords: incremental,parsing,tree-sitter
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
@@ -15,7 +16,7 @@
 Classifier: Topic :: Software Development :: Compilers
 Classifier: Topic :: Text Processing :: Linguistic
 Classifier: Typing :: Typed
-Requires-Python: >=3.9
+Requires-Python: >=3.10
 Description-Content-Type: text/markdown
 Provides-Extra: docs
 Provides-Extra: tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/pyproject.toml 
new/tree-sitter-0.24.0/pyproject.toml
--- old/tree-sitter-0.23.2/pyproject.toml       2024-10-24 17:09:11.000000000 
+0200
+++ new/tree-sitter-0.24.0/pyproject.toml       2025-01-17 05:57:33.000000000 
+0100
@@ -4,7 +4,7 @@
 
 [project]
 name = "tree-sitter"
-version = "0.23.2"
+version = "0.24.0"
 description = "Python bindings to the Tree-sitter parsing library"
 keywords = ["incremental", "parsing", "tree-sitter"]
 classifiers = [
@@ -17,30 +17,31 @@
     "Topic :: Text Processing :: Linguistic",
     "Typing :: Typed",
 ]
-requires-python = ">=3.9"
+requires-python = ">=3.10"
 readme = "README.md"
 
 [project.urls]
 Homepage = "https://tree-sitter.github.io/tree-sitter/";
 Source = "https://github.com/tree-sitter/py-tree-sitter";
 Documentation = "https://tree-sitter.github.io/py-tree-sitter/";
+Discord = "https://discord.gg/w7nTvsVJhm";
 
 [[project.authors]]
 name = "Max Brunsfeld"
 email = "[email protected]"
 
 [project.optional-dependencies]
-docs = ["sphinx~=7.3", "sphinx-book-theme"]
+docs = ["sphinx~=8.1", "sphinx-book-theme"]
 tests = [
-    "tree-sitter-html>=0.23.0",
-    "tree-sitter-javascript>=0.23.0",
-    "tree-sitter-json>=0.23.0",
-    "tree-sitter-python>=0.23.0",
-    "tree-sitter-rust>=0.23.0",
+    "tree-sitter-html>=0.23.2",
+    "tree-sitter-javascript>=0.23.1",
+    "tree-sitter-json>=0.24.8",
+    "tree-sitter-python>=0.23.6",
+    "tree-sitter-rust>=0.23.2",
 ]
 
 [tool.ruff]
-target-version = "py39"
+target-version = "py310"
 line-length = 100
 indent-width = 4
 extend-exclude = [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/__init__.py 
new/tree-sitter-0.24.0/tree_sitter/__init__.py
--- old/tree-sitter-0.23.2/tree_sitter/__init__.py      2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/__init__.py      2025-01-17 
05:57:33.000000000 +0100
@@ -4,6 +4,7 @@
 
 from ._binding import (
     Language,
+    LogType,
     LookaheadIterator,
     Node,
     Parser,
@@ -17,10 +18,13 @@
     MIN_COMPATIBLE_LANGUAGE_VERSION,
 )
 
+LogType.__doc__ = "The type of a log message."
+
 Point.__doc__ = "A position in a multi-line text document, in terms of rows 
and columns."
 Point.row.__doc__ = "The zero-based row of the document."
 Point.column.__doc__ = "The zero-based column of the document."
 
+
 class QueryPredicate(_Protocol):
     """A custom query predicate that runs on a pattern."""
     def __call__(self, predicate, args, pattern_index, captures):
@@ -49,6 +53,7 @@
 
 __all__ = [
     "Language",
+    "LogType",
     "LookaheadIterator",
     "Node",
     "Parser",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/__init__.pyi 
new/tree-sitter-0.24.0/tree_sitter/__init__.pyi
--- old/tree-sitter-0.23.2/tree_sitter/__init__.pyi     2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/__init__.pyi     2025-01-17 
05:57:33.000000000 +0100
@@ -1,15 +1,28 @@
+from enum import IntEnum
 from collections.abc import ByteString, Callable, Iterator, Sequence
 from typing import Annotated, Any, Final, Literal, NamedTuple, Protocol, Self, 
final, overload
+from typing_extensions import deprecated
+
+class _SupportsFileno(Protocol):
+    def fileno(self) -> int: ...
 
 class Point(NamedTuple):
     row: int
     column: int
 
+class LogType(IntEnum):
+    PARSE: int
+    LEX: int
+
 @final
 class Language:
-    def __init__(self, ptr: Annotated[int | object, "TSLanguage *"], /) -> 
None: ...
+    @overload
+    @deprecated("int argument support is deprecated")
+    def __init__(self, ptr: Annotated[int, "TSLanguage *"], /) -> None: ...
+    @overload
+    def __init__(self, ptr: Annotated[object, "TSLanguage *"], /) -> None: ...
 
-    # TODO(0.24): implement name
+    # TODO(0.25): implement name
     # @property
     # def name(self) -> str | None: ...
 
@@ -25,15 +38,18 @@
     def id_for_node_kind(self, kind: str, named: bool, /) -> int | None: ...
     def node_kind_is_named(self, id: int, /) -> bool: ...
     def node_kind_is_visible(self, id: int, /) -> bool: ...
+    def node_kind_is_supertype(self, id: int, /) -> bool: ...
     def field_name_for_id(self, field_id: int, /) -> str | None: ...
     def field_id_for_name(self, name: str, /) -> int | None: ...
     def next_state(self, state: int, id: int, /) -> int: ...
     def lookahead_iterator(self, state: int, /) -> LookaheadIterator | None: 
...
     def query(self, source: str, /) -> Query: ...
+    def copy(self) -> Language: ...
     def __repr__(self) -> str: ...
     def __eq__(self, other: Any, /) -> bool: ...
     def __ne__(self, other: Any, /) -> bool: ...
     def __hash__(self) -> int: ...
+    def __copy__(self) -> Language: ...
 
 @final
 class Node:
@@ -111,10 +127,13 @@
     def named_child(self, index: int, /) -> Node | None: ...
     def child_by_field_id(self, id: int, /) -> Node | None: ...
     def child_by_field_name(self, name: str, /) -> Node | None: ...
+    @deprecated("Use child_with_descendant instead")
     def child_containing_descendant(self, descendant: Node, /) -> Node | None: 
...
+    def child_with_descendant(self, descendant: Node, /) -> Node | None: ...
     def children_by_field_id(self, id: int, /) -> list[Node]: ...
     def children_by_field_name(self, name: str, /) -> list[Node]: ...
     def field_name_for_child(self, child_index: int, /) -> str | None: ...
+    def field_name_for_named_child(self, child_index: int, /) -> str | None: 
...
     def descendant_for_byte_range(
         self,
         start_byte: int,
@@ -159,6 +178,7 @@
         offset_extent: Point | tuple[int, int],
         /,
     ) -> Node | None: ...
+    def copy(self) -> Tree: ...
     def edit(
         self,
         start_byte: int,
@@ -170,8 +190,8 @@
     ) -> None: ...
     def walk(self) -> TreeCursor: ...
     def changed_ranges(self, new_tree: Tree) -> list[Range]: ...
-    # TODO(0.24): add print_dot_graph
-    # TODO(0.24): add copy methods
+    def print_dot_graph(self, file: _SupportsFileno) -> None: ...
+    def __copy__(self) -> Tree: ...
 
 @final
 class TreeCursor:
@@ -206,6 +226,7 @@
         *,
         included_ranges: Sequence[Range] | None = None,
         timeout_micros: int | None = None,
+        logger: Callable[[LogType, str], None] | None = None,
     ) -> None: ...
     @property
     def language(self) -> Language | None: ...
@@ -225,6 +246,12 @@
     def timeout_micros(self, timeout: int) -> None: ...
     @timeout_micros.deleter
     def timeout_micros(self) -> None: ...
+    @property
+    def logger(self) -> Callable[[LogType, str], None] | None: ...
+    @logger.setter
+    def logger(self, logger: Callable[[LogType, str], None]) -> None: ...
+    @logger.deleter
+    def logger(self) -> None: ...
     @overload
     def parse(
         self,
@@ -242,8 +269,7 @@
         encoding: Literal["utf8", "utf16"] = "utf8",
     ) -> Tree: ...
     def reset(self) -> None: ...
-    # TODO(0.24): add set_logger
-    # TODO(0.24): add print_dot_graphs
+    def print_dot_graphs(self, file: _SupportsFileno | None) -> None: ...
 
 class QueryError(ValueError): ...
 
@@ -253,7 +279,7 @@
         predicate: str,
         args: list[tuple[str, Literal["capture", "string"]]],
         pattern_index: int,
-        captures: dict[str, list[Node]]
+        captures: dict[str, list[Node]],
     ) -> bool: ...
 
 @final
@@ -275,7 +301,7 @@
     def set_byte_range(self, byte_range: tuple[int, int]) -> Self: ...
     def set_point_range(
         self,
-        point_range: tuple[Point | tuple[int, int], Point | tuple[int, int]]
+        point_range: tuple[Point | tuple[int, int], Point | tuple[int, int]],
     ) -> Self: ...
     def disable_pattern(self, index: int) -> Self: ...
     def disable_capture(self, capture: str) -> Self: ...
@@ -283,13 +309,13 @@
         self,
         node: Node,
         /,
-        predicate: QueryPredicate | None = None
+        predicate: QueryPredicate | None = None,
     ) -> dict[str, list[Node]]: ...
     def matches(
         self,
         node: Node,
         /,
-        predicate: QueryPredicate | None = None
+        predicate: QueryPredicate | None = None,
     ) -> list[tuple[int, dict[str, list[Node]]]]: ...
     def pattern_settings(self, index: int) -> dict[str, str | None]: ...
     def pattern_assertions(self, index: int) -> dict[str, tuple[str | None, 
bool]]: ...
@@ -307,14 +333,14 @@
     @property
     def current_symbol_name(self) -> str: ...
 
-    # TODO(0.24): rename to reset
+    # TODO(0.25): rename to reset
     def reset_state(self, state: int, language: Language | None = None) -> 
bool: ...
     def iter_names(self) -> Iterator[str]: ...
 
-    # TODO(0.24): implement iter_symbols
+    # TODO(0.25): implement iter_symbols
     # def iter_symbols(self) -> Iterator[int]: ...
 
-    # TODO(0.24): return tuple[int, str]
+    # TODO(0.25): return tuple[int, str]
     def __next__(self) -> int: ...
 
 @final
@@ -338,6 +364,7 @@
     def __ne__(self, other: Any, /) -> bool: ...
     def __repr__(self) -> str: ...
     def __hash__(self) -> int: ...
+    # TODO(0.25): __replace__
 
 LANGUAGE_VERSION: Final[int]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/binding/language.c 
new/tree-sitter-0.24.0/tree_sitter/binding/language.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/language.c       2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/language.c       2025-01-17 
05:57:33.000000000 +0100
@@ -16,6 +16,9 @@
             }
             return -1;
         }
+        if (DEPRECATE("int argument support is deprecated") < 0) {
+            return -1;
+        }
         self->language = PyLong_AsVoidPtr(language);
     }
 
@@ -126,6 +129,15 @@
     return PyBool_FromLong(symbol_type <= TSSymbolTypeAnonymous);
 }
 
+PyObject *language_node_kind_is_supertype(Language *self, PyObject *args) {
+    TSSymbol symbol;
+    if (!PyArg_ParseTuple(args, "H:node_kind_is_supertype", &symbol)) {
+        return NULL;
+    }
+    TSSymbolType symbol_type = ts_language_symbol_type(self->language, symbol);
+    return PyBool_FromLong(symbol_type <= TSSymbolTypeSupertype);
+}
+
 PyObject *language_field_name_for_id(Language *self, PyObject *args) {
     uint16_t field_id;
     if (!PyArg_ParseTuple(args, "H:field_name_for_id", &field_id)) {
@@ -174,8 +186,7 @@
     if (iter == NULL) {
         return NULL;
     }
-    Py_INCREF(self);
-    iter->language = (PyObject *)self;
+    iter->language = Py_NewRef(self);
     iter->lookahead_iterator = lookahead_iterator;
     return PyObject_Init((PyObject *)iter, state->lookahead_iterator_type);
 }
@@ -190,6 +201,17 @@
     return PyObject_CallFunction((PyObject *)state->query_type, "Os#", self, 
source, length);
 }
 
+PyObject *language_copy(Language *self, PyObject *Py_UNUSED(args)) {
+    ModuleState *state = GET_MODULE_STATE(self);
+    Language *copied = PyObject_New(Language, state->language_type);
+    if (copied == NULL) {
+        return NULL;
+    }
+
+    copied->language = (TSLanguage *)ts_language_copy(self->language);
+    return PyObject_Init((PyObject *)copied, state->language_type);
+}
+
 PyDoc_STRVAR(language_node_kind_for_id_doc,
              "node_kind_for_id(self, id, /)\n--\n\n"
              "Get the name of the node kind for the given numerical id.");
@@ -202,6 +224,10 @@
              "node_kind_is_visible(self, id, /)\n--\n\n"
              "Check if the node type for the given numerical id "
              "is visible (as opposed to an auxiliary node type).");
+PyDoc_STRVAR(language_node_kind_is_supertype_doc,
+             "node_kind_is_supertype(self, id, /)\n--\n\n"
+             "Check if the node type for the given numerical id is a 
supertype.\n\nSupertype "
+             "nodes represent abstract categories of syntax nodes (e.g. 
\"expression\").");
 PyDoc_STRVAR(language_field_name_for_id_doc, "field_name_for_id(self, 
field_id, /)\n--\n\n"
                                              "Get the field name for the given 
numerical id.");
 PyDoc_STRVAR(language_field_id_for_name_doc, "field_id_for_name(self, name, 
/)\n--\n\n"
@@ -218,6 +244,10 @@
     language_query_doc,
     "query(self, source, /)\n--\n\n"
     "Create a new :class:`Query` from a string containing one or more 
S-expression patterns.");
+PyDoc_STRVAR(language_copy_doc, "copy(self, /)\n--\n\n"
+                                "Create a copy of the language.");
+PyDoc_STRVAR(language_copy2_doc, "__copy__(self, /)\n--\n\n"
+                                 "Use :func:`copy.copy` to create a copy of 
the language.");
 
 static PyMethodDef language_methods[] = {
     {
@@ -245,6 +275,12 @@
         .ml_doc = language_node_kind_is_visible_doc,
     },
     {
+        .ml_name = "node_kind_is_supertype",
+        .ml_meth = (PyCFunction)language_node_kind_is_supertype,
+        .ml_flags = METH_VARARGS,
+        .ml_doc = language_node_kind_is_supertype_doc,
+    },
+    {
         .ml_name = "field_name_for_id",
         .ml_meth = (PyCFunction)language_field_name_for_id,
         .ml_flags = METH_VARARGS,
@@ -274,6 +310,16 @@
         .ml_flags = METH_VARARGS,
         .ml_doc = language_query_doc,
     },
+    {
+        .ml_name = "copy",
+        .ml_meth = (PyCFunction)language_copy,
+        .ml_flags = METH_NOARGS,
+        .ml_doc = language_copy_doc,
+    },
+    {.ml_name = "__copy__",
+     .ml_meth = (PyCFunction)language_copy,
+     .ml_flags = METH_NOARGS,
+     .ml_doc = language_copy2_doc},
     {NULL},
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tree-sitter-0.23.2/tree_sitter/binding/lookahead_iterator.c 
new/tree-sitter-0.24.0/tree_sitter/binding/lookahead_iterator.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/lookahead_iterator.c     
2024-10-24 17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/lookahead_iterator.c     
2025-01-17 05:57:33.000000000 +0100
@@ -25,8 +25,7 @@
         language->version = ts_language_version(language->language);
         self->language = PyObject_Init((PyObject *)language, 
state->language_type);
     }
-    Py_INCREF(self->language);
-    return self->language;
+    return Py_NewRef(self->language);
 }
 
 PyObject *lookahead_iterator_get_current_symbol(LookaheadIterator *self, void 
*Py_UNUSED(payload)) {
@@ -62,8 +61,7 @@
 }
 
 PyObject *lookahead_iterator_iter(LookaheadIterator *self) {
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *lookahead_iterator_next(LookaheadIterator *self) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tree-sitter-0.23.2/tree_sitter/binding/lookahead_names_iterator.c 
new/tree-sitter-0.24.0/tree_sitter/binding/lookahead_names_iterator.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/lookahead_names_iterator.c       
2024-10-24 17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/lookahead_names_iterator.c       
2025-01-17 05:57:33.000000000 +0100
@@ -9,8 +9,7 @@
 }
 
 PyObject *lookahead_names_iterator_iter(LookaheadNamesIterator *self) {
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *lookahead_names_iterator_next(LookaheadNamesIterator *self) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/binding/module.c 
new/tree-sitter-0.24.0/tree_sitter/binding/module.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/module.c 2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/module.c 2025-01-17 
05:57:33.000000000 +0100
@@ -15,23 +15,6 @@
 extern PyType_Spec tree_cursor_type_spec;
 extern PyType_Spec tree_type_spec;
 
-// TODO(0.24): drop Python 3.9 support
-#if PY_MINOR_VERSION > 9
-#define AddObjectRef PyModule_AddObjectRef
-#else
-static int AddObjectRef(PyObject *module, const char *name, PyObject *value) {
-    if (value == NULL) {
-        PyErr_Format(PyExc_SystemError, "PyModule_AddObjectRef() %s == NULL", 
name);
-        return -1;
-    }
-    int ret = PyModule_AddObject(module, name, value);
-    if (ret == 0) {
-        Py_INCREF(value);
-    }
-    return ret;
-}
-#endif
-
 static inline PyObject *import_attribute(const char *mod, const char *attr) {
     PyObject *module = PyImport_ImportModule(mod);
     if (module == NULL) {
@@ -46,6 +29,7 @@
     ModuleState *state = PyModule_GetState((PyObject *)self);
     ts_tree_cursor_delete(&state->default_cursor);
     Py_XDECREF(state->language_type);
+    Py_XDECREF(state->log_type_type);
     Py_XDECREF(state->lookahead_iterator_type);
     Py_XDECREF(state->lookahead_names_iterator_type);
     Py_XDECREF(state->node_type);
@@ -106,27 +90,27 @@
         (PyTypeObject *)PyType_FromModuleAndSpec(module, 
&tree_cursor_type_spec, NULL);
     state->tree_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, 
&tree_type_spec, NULL);
 
-    if ((AddObjectRef(module, "Language", (PyObject *)state->language_type) < 
0) ||
-        (AddObjectRef(module, "LookaheadIterator", (PyObject 
*)state->lookahead_iterator_type) <
-         0) ||
-        (AddObjectRef(module, "LookaheadNamesIterator",
-                      (PyObject *)state->lookahead_names_iterator_type) < 0) ||
-        (AddObjectRef(module, "Node", (PyObject *)state->node_type) < 0) ||
-        (AddObjectRef(module, "Parser", (PyObject *)state->parser_type) < 0) ||
-        (AddObjectRef(module, "Query", (PyObject *)state->query_type) < 0) ||
-        (AddObjectRef(module, "QueryPredicateAnyof",
-                      (PyObject *)state->query_predicate_anyof_type) < 0) ||
-        (AddObjectRef(module, "QueryPredicateEqCapture",
-                      (PyObject *)state->query_predicate_eq_capture_type) < 0) 
||
-        (AddObjectRef(module, "QueryPredicateEqString",
-                      (PyObject *)state->query_predicate_eq_string_type) < 0) 
||
-        (AddObjectRef(module, "QueryPredicateGeneric",
-                      (PyObject *)state->query_predicate_generic_type) < 0) ||
-        (AddObjectRef(module, "QueryPredicateMatch",
-                      (PyObject *)state->query_predicate_match_type) < 0) ||
-        (AddObjectRef(module, "Range", (PyObject *)state->range_type) < 0) ||
-        (AddObjectRef(module, "Tree", (PyObject *)state->tree_type) < 0) ||
-        (AddObjectRef(module, "TreeCursor", (PyObject 
*)state->tree_cursor_type) < 0)) {
+    if ((PyModule_AddObjectRef(module, "Language", (PyObject 
*)state->language_type) < 0) ||
+        (PyModule_AddObjectRef(module, "LookaheadIterator",
+                               (PyObject *)state->lookahead_iterator_type) < 
0) ||
+        (PyModule_AddObjectRef(module, "LookaheadNamesIterator",
+                               (PyObject 
*)state->lookahead_names_iterator_type) < 0) ||
+        (PyModule_AddObjectRef(module, "Node", (PyObject *)state->node_type) < 
0) ||
+        (PyModule_AddObjectRef(module, "Parser", (PyObject 
*)state->parser_type) < 0) ||
+        (PyModule_AddObjectRef(module, "Query", (PyObject *)state->query_type) 
< 0) ||
+        (PyModule_AddObjectRef(module, "QueryPredicateAnyof",
+                               (PyObject *)state->query_predicate_anyof_type) 
< 0) ||
+        (PyModule_AddObjectRef(module, "QueryPredicateEqCapture",
+                               (PyObject 
*)state->query_predicate_eq_capture_type) < 0) ||
+        (PyModule_AddObjectRef(module, "QueryPredicateEqString",
+                               (PyObject 
*)state->query_predicate_eq_string_type) < 0) ||
+        (PyModule_AddObjectRef(module, "QueryPredicateGeneric",
+                               (PyObject 
*)state->query_predicate_generic_type) < 0) ||
+        (PyModule_AddObjectRef(module, "QueryPredicateMatch",
+                               (PyObject *)state->query_predicate_match_type) 
< 0) ||
+        (PyModule_AddObjectRef(module, "Range", (PyObject *)state->range_type) 
< 0) ||
+        (PyModule_AddObjectRef(module, "Tree", (PyObject *)state->tree_type) < 
0) ||
+        (PyModule_AddObjectRef(module, "TreeCursor", (PyObject 
*)state->tree_cursor_type) < 0)) {
         goto cleanup;
     }
 
@@ -134,7 +118,8 @@
         "tree_sitter.QueryError",
         PyDoc_STR("An error that occurred while attempting to create a 
:class:`Query`."),
         PyExc_ValueError, NULL);
-    if (state->query_error == NULL || AddObjectRef(module, "QueryError", 
state->query_error) < 0) {
+    if (state->query_error == NULL ||
+        PyModule_AddObjectRef(module, "QueryError", state->query_error) < 0) {
         goto cleanup;
     }
 
@@ -155,10 +140,22 @@
     Py_DECREF(point_kwargs);
     Py_DECREF(namedtuple);
     if (state->point_type == NULL ||
-        AddObjectRef(module, "Point", (PyObject *)state->point_type) < 0) {
+        PyModule_AddObjectRef(module, "Point", (PyObject *)state->point_type) 
< 0) {
         goto cleanup;
     }
 
+    PyObject *int_enum = import_attribute("enum", "IntEnum");
+    if (int_enum == NULL) {
+        goto cleanup;
+    }
+    state->log_type_type = (PyTypeObject *)PyObject_CallFunction(
+        int_enum, "s{sisi}", "LogType", "PARSE", TSLogTypeParse, "LEX", 
TSLogTypeLex);
+    if (state->log_type_type == NULL ||
+        PyModule_AddObjectRef(module, "LogType", (PyObject 
*)state->log_type_type) < 0) {
+        goto cleanup;
+    };
+    Py_DECREF(int_enum);
+
     PyModule_AddIntConstant(module, "LANGUAGE_VERSION", 
TREE_SITTER_LANGUAGE_VERSION);
     PyModule_AddIntConstant(module, "MIN_COMPATIBLE_LANGUAGE_VERSION",
                             TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/binding/node.c 
new/tree-sitter-0.24.0/tree_sitter/binding/node.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/node.c   2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/node.c   2025-01-17 
05:57:33.000000000 +0100
@@ -6,8 +6,7 @@
         return NULL;
     }
     self->node = node;
-    Py_INCREF(tree);
-    self->tree = tree;
+    self->tree = Py_NewRef(tree);
     self->children = NULL;
     return PyObject_Init((PyObject *)self, state->node_type);
 }
@@ -53,8 +52,7 @@
         return NULL;
     }
 
-    Py_INCREF(self->tree);
-    tree_cursor->tree = self->tree;
+    tree_cursor->tree = Py_NewRef(self->tree);
     tree_cursor->node = NULL;
     tree_cursor->cursor = ts_tree_cursor_new(self->node);
     return PyObject_Init((PyObject *)tree_cursor, state->tree_cursor_type);
@@ -223,6 +221,27 @@
     return PyUnicode_FromString(field_name);
 }
 
+PyObject *node_field_name_for_named_child(Node *self, PyObject *args) {
+    long index;
+    if (!PyArg_ParseTuple(args, "l:field_name_for_named_child", &index)) {
+        return NULL;
+    }
+    if (index < 0) {
+        PyErr_SetString(PyExc_ValueError, "child index must be positive");
+        return NULL;
+    }
+    if ((uint32_t)index >= ts_node_child_count(self->node)) {
+        PyErr_SetString(PyExc_IndexError, "child index out of range");
+        return NULL;
+    }
+
+    const char *field_name = ts_node_field_name_for_named_child(self->node, 
index);
+    if (field_name == NULL) {
+        Py_RETURN_NONE;
+    }
+    return PyUnicode_FromString(field_name);
+}
+
 PyObject *node_descendant_for_byte_range(Node *self, PyObject *args) {
     ModuleState *state = GET_MODULE_STATE(self);
     uint32_t start_byte, end_byte;
@@ -285,6 +304,9 @@
     if (!PyArg_ParseTuple(args, "O!:child_containing_descendant", &descendant, 
state->node_type)) {
         return NULL;
     }
+    if (REPLACE("child_containing_descendant", "child_with_descendant") < 0) {
+        return NULL;
+    }
 
     TSNode child = ts_node_child_containing_descendant(self->node, descendant);
     if (ts_node_is_null(child)) {
@@ -293,6 +315,20 @@
     return node_new_internal(state, child, self->tree);
 }
 
+PyObject *node_child_with_descendant(Node *self, PyObject *args) {
+    ModuleState *state = GET_MODULE_STATE(self);
+    TSNode descendant;
+    if (!PyArg_ParseTuple(args, "O!:child_with_descendant", &descendant, 
state->node_type)) {
+        return NULL;
+    }
+
+    TSNode child = ts_node_child_with_descendant(self->node, descendant);
+    if (ts_node_is_null(child)) {
+        Py_RETURN_NONE;
+    }
+    return node_new_internal(state, child, self->tree);
+}
+
 PyObject *node_get_id(Node *self, void *Py_UNUSED(payload)) {
     return PyLong_FromVoidPtr((void *)self->node.id);
 }
@@ -399,8 +435,7 @@
 PyObject *node_get_children(Node *self, void *Py_UNUSED(payload)) {
     ModuleState *state = GET_MODULE_STATE(self);
     if (self->children) {
-        Py_INCREF(self->children);
-        return self->children;
+        return Py_NewRef(self->children);
     }
 
     uint32_t length = ts_node_child_count(self->node);
@@ -421,9 +456,8 @@
             }
         } while (ts_tree_cursor_goto_next_sibling(&state->default_cursor));
     }
-    Py_INCREF(result);
-    self->children = result;
-    return result;
+    self->children = Py_NewRef(result);
+    return self->children;
 }
 
 PyObject *node_get_named_children(Node *self, void *payload) {
@@ -444,8 +478,7 @@
     for (uint32_t i = 0, j = 0; i < length; ++i) {
         PyObject *child = PyList_GetItem(self->children, i);
         if (ts_node_is_named(((Node *)child)->node)) {
-            Py_INCREF(child);
-            if (PyList_SetItem(result, j++, child)) {
+            if (PyList_SetItem(result, j++, Py_NewRef(child))) {
                 Py_DECREF(result);
                 return NULL;
             }
@@ -600,6 +633,9 @@
 PyDoc_STRVAR(node_field_name_for_child_doc,
              "field_name_for_child(self, child_index, /)\n--\n\n"
              "Get the field name of this node's child at the given index.");
+PyDoc_STRVAR(node_field_name_for_named_child_doc,
+             "field_name_for_child(self, child_index, /)\n--\n\n"
+             "Get the field name of this node's *named* child at the given 
index.");
 PyDoc_STRVAR(node_descendant_for_byte_range_doc,
              "descendant_for_byte_range(self, start_byte, end_byte, /)\n--\n\n"
              "Get the smallest node within this node that spans the given byte 
range.");
@@ -614,7 +650,11 @@
              "Get the smallest *named* node within this node that spans the 
given point range.");
 PyDoc_STRVAR(node_child_containing_descendant_doc,
              "child_containing_descendant(self, descendant, /)\n--\n\n"
-             "Get the child of the node that contains the given descendant.");
+             "Get the child of the node that contains the given descendant." 
DOC_ATTENTION
+             "This will not return the descendant if it is a direct child of 
this node.");
+PyDoc_STRVAR(node_child_with_descendant_doc,
+             "child_with_descendant(self, descendant, /)\n--\n\n"
+             "Get the node that contains the given descendant.");
 
 static PyMethodDef node_methods[] = {
     {
@@ -672,6 +712,12 @@
         .ml_doc = node_field_name_for_child_doc,
     },
     {
+        .ml_name = "field_name_for_named_child",
+        .ml_meth = (PyCFunction)node_field_name_for_named_child,
+        .ml_flags = METH_VARARGS,
+        .ml_doc = node_field_name_for_named_child_doc,
+    },
+    {
         .ml_name = "descendant_for_byte_range",
         .ml_meth = (PyCFunction)node_descendant_for_byte_range,
         .ml_flags = METH_VARARGS,
@@ -701,6 +747,12 @@
         .ml_flags = METH_VARARGS,
         .ml_doc = node_child_containing_descendant_doc,
     },
+    {
+        .ml_name = "child_with_descendant",
+        .ml_meth = (PyCFunction)node_child_with_descendant,
+        .ml_flags = METH_VARARGS,
+        .ml_doc = node_child_with_descendant_doc,
+    },
     {NULL},
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/binding/parser.c 
new/tree-sitter-0.24.0/tree_sitter/binding/parser.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/parser.c 2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/parser.c 2025-01-17 
05:57:33.000000000 +0100
@@ -9,18 +9,33 @@
     ModuleState *state;
 } ReadWrapperPayload;
 
+typedef struct {
+    PyObject *callback;
+    PyTypeObject *log_type_type;
+} LoggerPayload;
+
+static void free_logger(const TSParser *parser) {
+    TSLogger logger = ts_parser_logger(parser);
+    if (logger.payload != NULL) {
+        PyMem_Free(logger.payload);
+    }
+}
+
 PyObject *parser_new(PyTypeObject *cls, PyObject *Py_UNUSED(args), PyObject 
*Py_UNUSED(kwargs)) {
     Parser *self = (Parser *)cls->tp_alloc(cls, 0);
     if (self != NULL) {
         self->parser = ts_parser_new();
         self->language = NULL;
+        self->logger = NULL;
     }
     return (PyObject *)self;
 }
 
 void parser_dealloc(Parser *self) {
+    free_logger(self->parser);
     ts_parser_delete(self->parser);
     Py_XDECREF(self->language);
+    Py_XDECREF(self->logger);
     Py_TYPE(self)->tp_free(self);
 }
 
@@ -190,6 +205,19 @@
     Py_RETURN_NONE;
 }
 
+PyObject *parser_print_dot_graphs(Parser *self, PyObject *arg) {
+    if (arg == Py_None) {
+        ts_parser_print_dot_graphs(self->parser, -1);
+    } else {
+        int fd = PyObject_AsFileDescriptor(arg);
+        if (fd < 0) {
+            return NULL;
+        }
+        ts_parser_print_dot_graphs(self->parser, fd);
+    }
+    Py_RETURN_NONE;
+}
+
 PyObject *parser_get_timeout_micros(Parser *self, void *Py_UNUSED(payload)) {
     return PyLong_FromUnsignedLong(ts_parser_timeout_micros(self->parser));
 }
@@ -273,8 +301,49 @@
     if (!self->language) {
         Py_RETURN_NONE;
     }
-    Py_INCREF(self->language);
-    return self->language;
+    return Py_NewRef(self->language);
+}
+
+PyObject *parser_get_logger(Parser *self, void *Py_UNUSED(payload)) {
+    if (!self->logger) {
+        Py_RETURN_NONE;
+    }
+    return Py_NewRef(self->logger);
+}
+
+static void log_callback(void *payload, TSLogType log_type, const char 
*buffer) {
+    LoggerPayload *logger_payload = (LoggerPayload *)payload;
+    PyObject *log_type_enum =
+        PyObject_CallFunction((PyObject *)logger_payload->log_type_type, "i", 
log_type);
+    PyObject_CallFunction(logger_payload->callback, "Os", log_type_enum, 
buffer);
+}
+
+int parser_set_logger(Parser *self, PyObject *arg, void *Py_UNUSED(payload)) {
+    free_logger(self->parser);
+
+    if (arg == NULL || arg == Py_None) {
+        Py_XDECREF(self->logger);
+        self->logger = NULL;
+        TSLogger logger = {NULL, NULL};
+        ts_parser_set_logger(self->parser, logger);
+        return 0;
+    }
+    if (!PyCallable_Check(arg)) {
+        PyErr_Format(PyExc_TypeError, "logger must be assigned a Callable 
object, not %s",
+                     arg->ob_type->tp_name);
+        return -1;
+    }
+
+    Py_XSETREF(self->logger, Py_NewRef(arg));
+
+    ModuleState *state = GET_MODULE_STATE(self);
+    LoggerPayload *payload = PyMem_Malloc(sizeof(LoggerPayload));
+    payload->callback = self->logger;
+    payload->log_type_type = state->log_type_type;
+    TSLogger logger = {payload, log_callback};
+    ts_parser_set_logger(self->parser, logger);
+
+    return 0;
 }
 
 int parser_set_language(Parser *self, PyObject *arg, void *Py_UNUSED(payload)) 
{
@@ -304,18 +373,17 @@
         return -1;
     }
 
-    Py_INCREF(language);
-    Py_XSETREF(self->language, (PyObject *)language);
+    Py_XSETREF(self->language, Py_NewRef(language));
     return 0;
 }
 
 int parser_init(Parser *self, PyObject *args, PyObject *kwargs) {
     ModuleState *state = GET_MODULE_STATE(self);
-    PyObject *language = NULL, *included_ranges = NULL, *timeout_micros = NULL;
-    char *keywords[] = {"language", "included_ranges", "timeout_micros", NULL};
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O!$OO:__init__", keywords,
+    PyObject *language = NULL, *included_ranges = NULL, *timeout_micros = 
NULL, *logger = NULL;
+    char *keywords[] = {"language", "included_ranges", "timeout_micros", 
"logger", NULL};
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O!$OOO:__init__", 
keywords,
                                      state->language_type, &language, 
&included_ranges,
-                                     &timeout_micros)) {
+                                     &timeout_micros, &logger)) {
         return -1;
     }
 
@@ -328,6 +396,9 @@
     if (SET_ATTRIBUTE_ERROR(timeout_micros)) {
         return -1;
     }
+    if (SET_ATTRIBUTE_ERROR(logger)) {
+        return -1;
+    }
     return 0;
 }
 
@@ -347,6 +418,11 @@
     "If the parser previously failed because of a timeout, then by default, it 
will resume where "
     "it left off on the next call to :meth:`parse`.\nIf you don't want to 
resume, and instead "
     "intend to use this parser to parse some other document, you must call 
:meth:`reset` first.");
+PyDoc_STRVAR(parser_print_dot_graphs_doc,
+             "print_dot_graphs(self, /, file)\n--\n\n"
+             "Set the file descriptor to which the parser should write 
debugging "
+             "graphs during parsing. The graphs are formatted in the DOT 
language. "
+             "You can turn off this logging by passing ``None``.");
 
 static PyMethodDef parser_methods[] = {
     {
@@ -361,6 +437,12 @@
         .ml_flags = METH_NOARGS,
         .ml_doc = parser_reset_doc,
     },
+    {
+        .ml_name = "print_dot_graphs",
+        .ml_meth = (PyCFunction)parser_print_dot_graphs,
+        .ml_flags = METH_O,
+        .ml_doc = parser_print_dot_graphs_doc,
+    },
     {NULL},
 };
 
@@ -371,6 +453,8 @@
      PyDoc_STR("The ranges of text that the parser will include when 
parsing."), NULL},
     {"timeout_micros", (getter)parser_get_timeout_micros, 
(setter)parser_set_timeout_micros,
      PyDoc_STR("The duration in microseconds that parsing is allowed to 
take."), NULL},
+    {"logger", (getter)parser_get_logger, (setter)parser_set_logger,
+     PyDoc_STR("The logger that the parser should use during parsing."), NULL},
     {NULL},
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/binding/query.c 
new/tree-sitter-0.24.0/tree_sitter/binding/query.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/query.c  2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/query.c  2025-01-17 
05:57:33.000000000 +0100
@@ -351,6 +351,7 @@
 
                 QueryPredicateAnyOf *predicate =
                     PyObject_New(QueryPredicateAnyOf, 
state->query_predicate_anyof_type);
+                predicate->capture_id = (predicate_step + 1)->value_id;
                 predicate->is_positive = is_positive;
                 predicate->values = values;
                 PyObject *predicate_obj =
@@ -558,6 +559,9 @@
         if (!query_satisfies_predicates(self, match, (Tree *)node->tree, 
predicate)) {
             continue;
         }
+        if (PyErr_Occurred()) {
+            return NULL;
+        }
 
         TSQueryCapture capture = match.captures[capture_index];
         PyObject *capture_name = PyList_GetItem(self->capture_names, 
capture.index);
@@ -592,8 +596,7 @@
         return NULL;
     }
     PyObject *item = PyList_GetItem(self->settings, pattern_index);
-    Py_INCREF(item);
-    return item;
+    return Py_NewRef(item);
 }
 
 PyObject *query_pattern_assertions(Query *self, PyObject *args) {
@@ -607,8 +610,7 @@
         return NULL;
     }
     PyObject *item = PyList_GetItem(self->assertions, pattern_index);
-    Py_INCREF(item);
-    return item;
+    return Py_NewRef(item);
 }
 
 PyObject *query_set_timeout_micros(Query *self, PyObject *args) {
@@ -617,8 +619,7 @@
         return NULL;
     }
     ts_query_cursor_set_timeout_micros(self->cursor, timeout_micros);
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *query_set_match_limit(Query *self, PyObject *args) {
@@ -631,8 +632,7 @@
         return NULL;
     }
     ts_query_cursor_set_match_limit(self->cursor, match_limit);
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *query_set_max_start_depth(Query *self, PyObject *args) {
@@ -641,8 +641,7 @@
         return NULL;
     }
     ts_query_cursor_set_max_start_depth(self->cursor, max_start_depth);
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *query_set_byte_range(Query *self, PyObject *args) {
@@ -651,8 +650,7 @@
         return NULL;
     }
     ts_query_cursor_set_byte_range(self->cursor, start_byte, end_byte);
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *query_set_point_range(Query *self, PyObject *args) {
@@ -662,8 +660,7 @@
         return NULL;
     }
     ts_query_cursor_set_point_range(self->cursor, start_point, end_point);
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *query_disable_pattern(Query *self, PyObject *args) {
@@ -672,8 +669,7 @@
         return NULL;
     }
     ts_query_disable_pattern(self->query, pattern_index);
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *query_disable_capture(Query *self, PyObject *args) {
@@ -683,8 +679,7 @@
         return NULL;
     }
     ts_query_disable_capture(self->query, capture_name, length);
-    Py_INCREF(self);
-    return (PyObject *)self;
+    return Py_NewRef(self);
 }
 
 PyObject *query_start_byte_for_pattern(Query *self, PyObject *args) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tree-sitter-0.23.2/tree_sitter/binding/query_predicates.c 
new/tree-sitter-0.24.0/tree_sitter/binding/query_predicates.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/query_predicates.c       
2024-10-24 17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/query_predicates.c       
2025-01-17 05:57:33.000000000 +0100
@@ -48,17 +48,25 @@
     PyObject *nodes = nodes_for_capture_index(state, predicate->capture_id, 
match, tree);
     for (size_t i = 0, l = (size_t)PyList_Size(nodes); i < l; ++i) {
         Node *node = (Node *)PyList_GetItem(nodes, i);
-        PyObject *text1 = node_get_text(node, NULL), *text2;
+        PyObject *text1 = node_get_text(node, NULL);
+        bool found_match = false;
+
         for (size_t j = 0, k = (size_t)PyList_Size(predicate->values); j < k; 
++j) {
-            text2 = PyList_GetItem(predicate->values, j);
-            if (PREDICATE_CMP(text1, text2, predicate) != 1) {
-                Py_DECREF(text1);
-                Py_DECREF(nodes);
-                return false;
+            PyObject *text2 = PyList_GetItem(predicate->values, j);
+            if (PREDICATE_CMP(text1, text2, predicate) == 1) {
+                found_match = true;
+                break;
             }
         }
+
         Py_DECREF(text1);
+
+        if (!found_match) {
+            Py_DECREF(nodes);
+            return false;
+        }
     }
+
     Py_DECREF(nodes);
     return true;
 }
@@ -107,7 +115,7 @@
         text = node_get_text((Node *)PyList_GetItem(nodes, i), NULL);
         search_result =
             PyObject_CallMethod(predicate->pattern, "search", "s", 
PyBytes_AsString(text));
-        result = search_result != NULL && search_result != Py_None;
+        result = (search_result != NULL && search_result != Py_None) == 
predicate->is_positive;
         Py_DECREF(text);
         Py_XDECREF(search_result);
         PREDICATE_BREAK(predicate, result);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/binding/tree.c 
new/tree-sitter-0.24.0/tree_sitter/binding/tree.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/tree.c   2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/tree.c   2025-01-17 
05:57:33.000000000 +0100
@@ -37,8 +37,7 @@
         return NULL;
     }
 
-    Py_INCREF(self);
-    tree_cursor->tree = (PyObject *)self;
+    tree_cursor->tree = Py_NewRef(self);
     tree_cursor->node = NULL;
     tree_cursor->cursor = ts_tree_cursor_new(ts_tree_root_node(self->tree));
     return PyObject_Init((PyObject *)tree_cursor, state->tree_cursor_type);
@@ -75,6 +74,24 @@
     Py_RETURN_NONE;
 }
 
+PyObject *tree_copy(Tree *self, PyObject *Py_UNUSED(args)) {
+    ModuleState *state = GET_MODULE_STATE(self);
+    Tree *copied = PyObject_New(Tree, state->tree_type);
+    if (copied == NULL) {
+        return NULL;
+    }
+
+    copied->tree = ts_tree_copy(self->tree);
+    return PyObject_Init((PyObject *)copied, state->tree_type);
+}
+
+PyObject *tree_print_dot_graph(Tree *self, PyObject *arg) {
+    int fd = PyObject_AsFileDescriptor(arg);
+    if (fd < 0) return NULL;
+    ts_tree_print_dot_graph(self->tree, fd);
+    Py_RETURN_NONE;
+}
+
 PyObject *tree_changed_ranges(Tree *self, PyObject *args, PyObject *kwargs) {
     ModuleState *state = GET_MODULE_STATE(self);
     PyObject *new_tree;
@@ -128,8 +145,7 @@
 }
 
 PyObject *tree_get_language(Tree *self, PyObject *Py_UNUSED(args)) {
-    Py_INCREF(self->language);
-    return self->language;
+    return Py_NewRef(self->language);
 }
 
 PyDoc_STRVAR(tree_root_node_with_offset_doc,
@@ -152,6 +168,13 @@
     "ranges match up to the new tree.\n\nGenerally, you'll want to call this 
method "
     "right after calling the :meth:`Parser.parse` method. Call it on the old 
tree that "
     "was passed to the method, and pass the new tree that was returned from 
it.");
+PyDoc_STRVAR(tree_print_dot_graph_doc,
+             "print_dot_graph(self, /, file)\n--\n\n"
+             "Write a DOT graph describing the syntax tree to the given 
file.");
+PyDoc_STRVAR(tree_copy_doc, "copy(self, /)\n--\n\n"
+                            "Create a shallow copy of the tree.");
+PyDoc_STRVAR(tree_copy2_doc, "__copy__(self, /)\n--\n\n"
+                             "Use :func:`copy.copy` to create a copy of the 
tree.");
 
 static PyMethodDef tree_methods[] = {
     {
@@ -178,6 +201,22 @@
         .ml_flags = METH_KEYWORDS | METH_VARARGS,
         .ml_doc = tree_changed_ranges_doc,
     },
+    {
+        .ml_name = "print_dot_graph",
+        .ml_meth = (PyCFunction)tree_print_dot_graph,
+        .ml_flags = METH_O,
+        .ml_doc = tree_print_dot_graph_doc,
+    },
+    {
+        .ml_name = "copy",
+        .ml_meth = (PyCFunction)tree_copy,
+        .ml_flags = METH_NOARGS,
+        .ml_doc = tree_copy_doc,
+    },
+    {.ml_name = "__copy__",
+     .ml_meth = (PyCFunction)tree_copy,
+     .ml_flags = METH_NOARGS,
+     .ml_doc = tree_copy2_doc},
     {NULL},
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/binding/tree_cursor.c 
new/tree-sitter-0.24.0/tree_sitter/binding/tree_cursor.c
--- old/tree-sitter-0.23.2/tree_sitter/binding/tree_cursor.c    2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/tree_cursor.c    2025-01-17 
05:57:33.000000000 +0100
@@ -18,8 +18,7 @@
         ModuleState *state = GET_MODULE_STATE(self);
         self->node = node_new_internal(state, current_node, self->tree);
     }
-    Py_INCREF(self->node);
-    return self->node;
+    return Py_NewRef(self->node);
 }
 
 PyObject *tree_cursor_get_field_id(TreeCursor *self, void *Py_UNUSED(payload)) 
{
@@ -169,8 +168,7 @@
         return NULL;
     }
 
-    Py_INCREF(self->tree);
-    copied->tree = self->tree;
+    copied->tree = Py_NewRef(self->tree);
     copied->cursor = ts_tree_cursor_copy(&self->cursor);
     return PyObject_Init((PyObject *)copied, state->tree_cursor_type);
 }
@@ -183,7 +181,7 @@
     tree_cursor_goto_last_child_doc,
     "goto_last_child(self, /)\n--\n\n"
     "Move this cursor to the last child of its current node." DOC_RETURNS 
"``True`` "
-    "if the cursor successfully moved, or ``False`` if there were no 
children." DOC_ATTENTION
+    "if the cursor successfully moved, or ``False`` if there were no 
children." DOC_CAUTION
     "This method may be slower than :meth:`goto_first_child` because it needs "
     "to iterate through all the children to compute the child's position.");
 PyDoc_STRVAR(tree_cursor_goto_parent_doc,
@@ -199,7 +197,7 @@
              "goto_previous_sibling(self, /)\n--\n\n"
              "Move this cursor to the previous sibling of its current node." 
DOC_RETURNS
              "``True`` if the cursor successfully moved, or ``False`` if there 
was no previous "
-             "sibling." DOC_ATTENTION
+             "sibling." DOC_CAUTION
              "This method may be slower than :meth:`goto_next_sibling` due to 
how node positions "
              "are stored.\nIn the worst case, this will need to iterate 
through all the children "
              "up to the previous sibling node to recalculate its position.");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/binding/types.h 
new/tree-sitter-0.24.0/tree_sitter/binding/types.h
--- old/tree-sitter-0.23.2/tree_sitter/binding/types.h  2024-10-24 
17:09:11.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/binding/types.h  2025-01-17 
05:57:33.000000000 +0100
@@ -6,11 +6,6 @@
 
 #define HAS_LANGUAGE_NAMES (TREE_SITTER_LANGUAGE_VERSION >= 15)
 
-#if PY_MINOR_VERSION < 10
-#define Py_TPFLAGS_DISALLOW_INSTANTIATION 0
-#define Py_TPFLAGS_IMMUTABLETYPE 0
-#endif
-
 // Types
 
 typedef struct {
@@ -40,6 +35,7 @@
     PyObject_HEAD
     TSParser *parser;
     PyObject *language;
+    PyObject *logger;
 } Parser;
 
 typedef struct {
@@ -114,6 +110,7 @@
     PyObject *re_compile;
     PyObject *query_error;
     PyTypeObject *language_type;
+    PyTypeObject *log_type_type;
     PyTypeObject *lookahead_iterator_type;
     PyTypeObject *lookahead_names_iterator_type;
     PyTypeObject *node_type;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/core/lib/src/array.h 
new/tree-sitter-0.24.0/tree_sitter/core/lib/src/array.h
--- old/tree-sitter-0.23.2/tree_sitter/core/lib/src/array.h     2024-10-24 
17:09:12.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/core/lib/src/array.h     2025-01-17 
05:57:34.000000000 +0100
@@ -14,6 +14,7 @@
 #include <string.h>
 
 #ifdef _MSC_VER
+#pragma warning(push)
 #pragma warning(disable : 4101)
 #elif defined(__GNUC__) || defined(__clang__)
 #pragma GCC diagnostic push
@@ -278,7 +279,7 @@
 #define _compare_int(a, b) ((int)*(a) - (int)(b))
 
 #ifdef _MSC_VER
-#pragma warning(default : 4101)
+#pragma warning(pop)
 #elif defined(__GNUC__) || defined(__clang__)
 #pragma GCC diagnostic pop
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/core/lib/src/clock.h 
new/tree-sitter-0.24.0/tree_sitter/core/lib/src/clock.h
--- old/tree-sitter-0.23.2/tree_sitter/core/lib/src/clock.h     2024-10-24 
17:09:12.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/core/lib/src/clock.h     2025-01-17 
05:57:34.000000000 +0100
@@ -49,9 +49,9 @@
   return self > other;
 }
 
-#elif defined(CLOCK_MONOTONIC) && !defined(__APPLE__)
+#elif defined(CLOCK_MONOTONIC)
 
-// POSIX with monotonic clock support (Linux)
+// POSIX with monotonic clock support (Linux, macOS)
 // * Represent a time as a monotonic (seconds, nanoseconds) pair.
 // * Represent a duration as a number of microseconds.
 //
@@ -102,7 +102,7 @@
 
 #else
 
-// macOS or POSIX without monotonic clock support
+// POSIX without monotonic clock support
 // * Represent a time as a process clock value.
 // * Represent a duration as a number of process clock ticks.
 //
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/core/lib/src/node.c 
new/tree-sitter-0.24.0/tree_sitter/core/lib/src/node.c
--- old/tree-sitter-0.23.2/tree_sitter/core/lib/src/node.c      2024-10-24 
17:09:12.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/core/lib/src/node.c      2025-01-17 
05:57:34.000000000 +0100
@@ -103,21 +103,6 @@
   return true;
 }
 
-// This will return true if the next sibling is a zero-width token that is 
adjacent to the current node and is relevant
-static inline bool 
ts_node_child_iterator_next_sibling_is_empty_adjacent(NodeChildIterator *self, 
TSNode previous) {
-  if (!self->parent.ptr || ts_node_child_iterator_done(self)) return false;
-  if (self->child_index == 0) return false;
-  const Subtree *child = &ts_subtree_children(self->parent)[self->child_index];
-  TSSymbol alias = 0;
-  if (!ts_subtree_extra(*child)) {
-    if (self->alias_sequence) {
-      alias = self->alias_sequence[self->structural_child_index];
-    }
-  }
-  TSNode next = ts_node_new(self->tree, child, self->position, alias);
-  return ts_node_end_byte(previous) == ts_node_end_byte(next) && 
ts_node__is_relevant(next, true);
-}
-
 // TSNode - private
 
 static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) {
@@ -277,8 +262,16 @@
     TSNode child;
     NodeChildIterator iterator = ts_node_iterate_children(&node);
     while (ts_node_child_iterator_next(&iterator, &child)) {
-      if (iterator.position.bytes < target_end_byte) continue;
-      if (ts_node_start_byte(child) <= ts_node_start_byte(self)) {
+      if (iterator.position.bytes <= target_end_byte) continue;
+      uint32_t start_byte = ts_node_start_byte(self);
+      uint32_t child_start_byte = ts_node_start_byte(child);
+
+      bool is_empty = start_byte == target_end_byte;
+      bool contains_target = is_empty ?
+        child_start_byte < start_byte :
+        child_start_byte <= start_byte;
+
+      if (contains_target) {
         if (ts_node__subtree(child).ptr != ts_node__subtree(self).ptr) {
           child_containing_target = child;
         }
@@ -549,9 +542,9 @@
   if (node.id == self.id) return ts_node__null();
 
   while (true) {
-   TSNode next_node = ts_node_child_containing_descendant(node, self);
-   if (ts_node_is_null(next_node)) break;
-   node = next_node;
+    TSNode next_node = ts_node_child_with_descendant(node, self);
+    if (next_node.id == self.id || ts_node_is_null(next_node)) break;
+    node = next_node;
   }
 
   return node;
@@ -560,6 +553,7 @@
 TSNode ts_node_child_containing_descendant(TSNode self, TSNode descendant) {
   uint32_t start_byte = ts_node_start_byte(descendant);
   uint32_t end_byte = ts_node_end_byte(descendant);
+  bool is_empty = start_byte == end_byte;
 
   do {
     NodeChildIterator iter = ts_node_iterate_children(&self);
@@ -572,24 +566,16 @@
         return ts_node__null();
       }
 
-      // Here we check the current self node and *all* of its zero-width token 
siblings that follow.
-      // If any of these nodes contain the target subnode, we return that 
node. Otherwise, we restore the node we started at
-      // for the loop condition, and that will continue with the next 
*non-zero-width* sibling.
-      TSNode old = self;
-      // While the next sibling is a zero-width token
-      while (ts_node_child_iterator_next_sibling_is_empty_adjacent(&iter, 
self)) {
-        TSNode current_node = ts_node_child_containing_descendant(self, 
descendant);
-        // If the target child is in self, return it
-        if (!ts_node_is_null(current_node)) {
-          return current_node;
-        }
-        ts_node_child_iterator_next(&iter, &self);
-        if (self.id == descendant.id) {
-          return ts_node__null();
+      // If the descendant is empty, and the end byte is within `self`,
+      // we check whether `self` contains it or not.
+      if (is_empty && iter.position.bytes >= end_byte && 
ts_node_child_count(self) > 0) {
+        TSNode child = ts_node_child_with_descendant(self, descendant);
+        // If the child is not null, return self if it's relevant, else return 
the child
+        if (!ts_node_is_null(child)) {
+          return ts_node__is_relevant(self, true) ? self : child;
         }
       }
-      self = old;
-    } while (iter.position.bytes < end_byte || ts_node_child_count(self) == 0);
+    } while ((is_empty ? iter.position.bytes <= end_byte : iter.position.bytes 
< end_byte) || ts_node_child_count(self) == 0);
   } while (!ts_node__is_relevant(self, true));
 
   return self;
@@ -598,6 +584,7 @@
 TSNode ts_node_child_with_descendant(TSNode self, TSNode descendant) {
   uint32_t start_byte = ts_node_start_byte(descendant);
   uint32_t end_byte = ts_node_end_byte(descendant);
+  bool is_empty = start_byte == end_byte;
 
   do {
     NodeChildIterator iter = ts_node_iterate_children(&self);
@@ -612,24 +599,16 @@
         return self;
       }
 
-      // Here we check the current self node and *all* of its zero-width token 
siblings that follow.
-      // If any of these nodes contain the target subnode, we return that 
node. Otherwise, we restore the node we started at
-      // for the loop condition, and that will continue with the next 
*non-zero-width* sibling.
-      TSNode old = self;
-      // While the next sibling is a zero-width token
-      while (ts_node_child_iterator_next_sibling_is_empty_adjacent(&iter, 
self)) {
-        TSNode current_node = ts_node_child_with_descendant(self, descendant);
-        // If the target child is in self, return it
-        if (!ts_node_is_null(current_node)) {
-          return current_node;
-        }
-        ts_node_child_iterator_next(&iter, &self);
-        if (self.id == descendant.id) {
-          return self;
+      // If the descendant is empty, and the end byte is within `self`,
+      // we check whether `self` contains it or not.
+      if (is_empty && iter.position.bytes >= end_byte && 
ts_node_child_count(self) > 0) {
+        TSNode child = ts_node_child_with_descendant(self, descendant);
+        // If the child is not null, return self if it's relevant, else return 
the child
+        if (!ts_node_is_null(child)) {
+          return ts_node__is_relevant(self, true) ? self : child;
         }
       }
-      self = old;
-    } while (iter.position.bytes < end_byte || ts_node_child_count(self) == 0);
+    } while ((is_empty ? iter.position.bytes <= end_byte : iter.position.bytes 
< end_byte) || ts_node_child_count(self) == 0);
   } while (!ts_node__is_relevant(self, true));
 
   return self;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter/core/lib/src/parser.c 
new/tree-sitter-0.24.0/tree_sitter/core/lib/src/parser.c
--- old/tree-sitter-0.23.2/tree_sitter/core/lib/src/parser.c    2024-10-24 
17:09:12.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/core/lib/src/parser.c    2025-01-17 
05:57:34.000000000 +0100
@@ -350,7 +350,7 @@
   }
 }
 
-static bool ts_parser__call_keyword_lex_fn(TSParser *self, TSLexMode lex_mode) 
{
+static bool ts_parser__call_keyword_lex_fn(TSParser *self) {
   if (ts_language_is_wasm(self->language)) {
     return ts_wasm_store_call_lex_keyword(self->wasm_store, 0);
   } else {
@@ -651,7 +651,7 @@
       ts_lexer_reset(&self->lexer, self->lexer.token_start_position);
       ts_lexer_start(&self->lexer);
 
-      is_keyword = ts_parser__call_keyword_lex_fn(self, lex_mode);
+      is_keyword = ts_parser__call_keyword_lex_fn(self);
 
       if (
         is_keyword &&
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tree-sitter-0.23.2/tree_sitter/core/lib/src/tree_cursor.c 
new/tree-sitter-0.24.0/tree_sitter/core/lib/src/tree_cursor.c
--- old/tree-sitter-0.23.2/tree_sitter/core/lib/src/tree_cursor.c       
2024-10-24 17:09:12.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/core/lib/src/tree_cursor.c       
2025-01-17 05:57:34.000000000 +0100
@@ -1,5 +1,4 @@
 #include "tree_sitter/api.h"
-#include "./alloc.h"
 #include "./tree_cursor.h"
 #include "./language.h"
 #include "./tree.h"
@@ -212,7 +211,6 @@
         return false;
     }
   }
-  return false;
 }
 
 TreeCursorStep ts_tree_cursor_goto_last_child_internal(TSTreeCursor *_self) {
@@ -253,7 +251,6 @@
         return false;
     }
   }
-  return false;
 }
 
 static inline int64_t ts_tree_cursor_goto_first_child_for_byte_and_point(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tree-sitter-0.23.2/tree_sitter/core/lib/src/wasm_store.c 
new/tree-sitter-0.24.0/tree_sitter/core/lib/src/wasm_store.c
--- old/tree-sitter-0.23.2/tree_sitter/core/lib/src/wasm_store.c        
2024-10-24 17:09:12.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter/core/lib/src/wasm_store.c        
2025-01-17 05:57:34.000000000 +0100
@@ -16,6 +16,14 @@
 #include <wasm.h>
 #include <wasmtime.h>
 
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4100)
+#elif defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
 #define array_len(a) (sizeof(a) / sizeof(a[0]))
 
 // The following symbols from the C and C++ standard libraries are available
@@ -159,8 +167,6 @@
   int32_t eof;
 } LexerInWasmMemory;
 
-static volatile uint32_t NEXT_LANGUAGE_ID;
-
 // Linear memory layout:
 // [ <-- stack | stdlib statics | lexer | language statics --> | 
serialization_buffer | heap --> ]
 #define MAX_MEMORY_SIZE (128 * 1024 * 1024 / MEMORY_PAGE_SIZE)
@@ -169,7 +175,7 @@
  * WasmDylinkMemoryInfo
  ***********************/
 
-static uint8_t read_u8(const uint8_t **p, const uint8_t *end) {
+static uint8_t read_u8(const uint8_t **p) {
   return *(*p)++;
 }
 
@@ -204,7 +210,7 @@
   p += 4;
 
   while (p < end) {
-    uint8_t section_id = read_u8(&p, end);
+    uint8_t section_id = read_u8(&p);
     uint32_t section_length = read_uleb128(&p, end);
     const uint8_t *section_end = p + section_length;
     if (section_end > end) return false;
@@ -217,7 +223,7 @@
       if (name_length == 8 && memcmp(p, "dylink.0", 8) == 0) {
         p = name_end;
         while (p < section_end) {
-          uint8_t subsection_type = read_u8(&p, section_end);
+          uint8_t subsection_type = read_u8(&p);
           uint32_t subsection_size = read_uleb128(&p, section_end);
           const uint8_t *subsection_end = p + subsection_size;
           if (subsection_end > section_end) return false;
@@ -545,6 +551,7 @@
   wasm_trap_t *trap = NULL;
   wasm_message_t message = WASM_EMPTY_VEC;
   wasm_exporttype_vec_t export_types = WASM_EMPTY_VEC;
+  wasm_importtype_vec_t import_types = WASM_EMPTY_VEC;
   wasmtime_extern_t *imports = NULL;
   wasmtime_module_t *stdlib_module = NULL;
   wasm_memorytype_t *memory_type = NULL;
@@ -660,11 +667,10 @@
   }
 
   // Retrieve the stdlib module's imports.
-  wasm_importtype_vec_t import_types = WASM_EMPTY_VEC;
   wasmtime_module_imports(stdlib_module, &import_types);
 
   // Find the initial number of memory pages needed by the stdlib.
-  const wasm_memorytype_t *stdlib_memory_type;
+  const wasm_memorytype_t *stdlib_memory_type = NULL;
   for (unsigned i = 0; i < import_types.size; i++) {
     wasm_importtype_t *import_type = import_types.data[i];
     const wasm_name_t *import_name = wasm_importtype_name(import_type);
@@ -1743,6 +1749,12 @@
   }
 }
 
+#ifdef _MSC_VER
+#pragma warning(pop)
+#elif defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
 #else
 
 // If the WASM feature is not enabled, define dummy versions of all of the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter.egg-info/PKG-INFO 
new/tree-sitter-0.24.0/tree_sitter.egg-info/PKG-INFO
--- old/tree-sitter-0.23.2/tree_sitter.egg-info/PKG-INFO        2024-10-24 
17:09:15.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter.egg-info/PKG-INFO        2025-01-17 
05:57:38.000000000 +0100
@@ -1,11 +1,12 @@
 Metadata-Version: 2.1
 Name: tree-sitter
-Version: 0.23.2
+Version: 0.24.0
 Summary: Python bindings to the Tree-sitter parsing library
 Author-email: Max Brunsfeld <[email protected]>
 Project-URL: Homepage, https://tree-sitter.github.io/tree-sitter/
 Project-URL: Source, https://github.com/tree-sitter/py-tree-sitter
 Project-URL: Documentation, https://tree-sitter.github.io/py-tree-sitter/
+Project-URL: Discord, https://discord.gg/w7nTvsVJhm
 Keywords: incremental,parsing,tree-sitter
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
@@ -15,7 +16,7 @@
 Classifier: Topic :: Software Development :: Compilers
 Classifier: Topic :: Text Processing :: Linguistic
 Classifier: Typing :: Typed
-Requires-Python: >=3.9
+Requires-Python: >=3.10
 Description-Content-Type: text/markdown
 Provides-Extra: docs
 Provides-Extra: tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tree-sitter-0.23.2/tree_sitter.egg-info/requires.txt 
new/tree-sitter-0.24.0/tree_sitter.egg-info/requires.txt
--- old/tree-sitter-0.23.2/tree_sitter.egg-info/requires.txt    2024-10-24 
17:09:15.000000000 +0200
+++ new/tree-sitter-0.24.0/tree_sitter.egg-info/requires.txt    2025-01-17 
05:57:38.000000000 +0100
@@ -1,11 +1,11 @@
 
 [docs]
-sphinx~=7.3
+sphinx~=8.1
 sphinx-book-theme
 
 [tests]
-tree-sitter-html>=0.23.0
-tree-sitter-javascript>=0.23.0
-tree-sitter-json>=0.23.0
-tree-sitter-python>=0.23.0
-tree-sitter-rust>=0.23.0
+tree-sitter-html>=0.23.2
+tree-sitter-javascript>=0.23.1
+tree-sitter-json>=0.24.8
+tree-sitter-python>=0.23.6
+tree-sitter-rust>=0.23.2

Reply via email to