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
