From 32bdd54f7819632b05ae6ac90c0539a074889f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Mon, 9 Nov 2026 15:46:04 +0100 Subject: [PATCH 1/4] Use simple unions in dtypes and rename grammar rule --- REMINDERS.md | 11 +++++++++-- src/docstub-stubs/doctype.pyi | 2 ++ src/docstub/_app_generate_stubs.py | 14 +++++++++++++- src/docstub/doctype.lark | 10 +++++++--- src/docstub/doctype.py | 12 ++++++++++++ tests/test_doctype.py | 16 +++++++--------- 6 files changed, 50 insertions(+), 15 deletions(-) diff --git a/REMINDERS.md b/REMINDERS.md index b904406..8090e81 100644 --- a/REMINDERS.md +++ b/REMINDERS.md @@ -1,10 +1,17 @@ # Reminders +## v0.8.0 + +- Complete deprecation of grammar rule `dtype_to_expand`. + Remove rule in `doctype.lark` and `DoctypeTranformer`. + Remove warning in `_app_generate_stubs::generate_stubs`. + + ## With Python >=3.13 -Remove vendored `glob_translate` in `docstub._vendored.stdlib`. +- Remove vendored `glob_translate` in `docstub._vendored.stdlib`. ## With Python >=3.14 -Remove vendored `ProcessPoolExecutor` in `docstub._vendored.stdlib`. +- Remove vendored `ProcessPoolExecutor` in `docstub._vendored.stdlib`. diff --git a/src/docstub-stubs/doctype.pyi b/src/docstub-stubs/doctype.pyi index e15111b..5ef600d 100644 --- a/src/docstub-stubs/doctype.pyi +++ b/src/docstub-stubs/doctype.pyi @@ -3,6 +3,7 @@ import enum import keyword import logging +import warnings from collections.abc import Callable, Generator, Iterable, Sequence from dataclasses import dataclass from functools import cached_property @@ -101,6 +102,7 @@ class DoctypeTransformer(lark.visitors.Transformer): def natlang_array(self, tree: lark.Tree) -> Expr: ... def array_name(self, tree: lark.Tree) -> Term: ... def dtype(self, tree: lark.Tree) -> Expr: ... + def dtype_union(self, tree: lark.Tree) -> Expr: ... def dtype_to_expand(self, tree: lark.Tree) -> Expr: ... def shape(self, tree: lark.Tree) -> Expr: ... def optional_info(self, tree: lark.Tree) -> lark.visitors._DiscardType: ... diff --git a/src/docstub/_app_generate_stubs.py b/src/docstub/_app_generate_stubs.py index 541b5b1..a244a6c 100644 --- a/src/docstub/_app_generate_stubs.py +++ b/src/docstub/_app_generate_stubs.py @@ -31,7 +31,7 @@ walk_source_package, ) from ._report import Stats, setup_logging -from ._stubs import Py2StubTransformer, try_format_stub +from ._stubs import Py2StubTransformer, try_format_stub, CstTreeSerializer from ._utils import escape_qualname from ._version import __version__ @@ -386,6 +386,18 @@ def generate_stubs( grammar = plugin_hooks.docstub_load_doctype_grammar() doctype_transformer = plugin_hooks.docstub_load_doctype_transformer() + if (doctype_transformer and hasattr(doctype_transformer, "dtype_to_expand")) or ( + grammar and "dtype_to_expand" in grammar + ): + logger.warning( + "The grammar rule 'dtype_to_expand' is deprecated in favor of 'dtype_union'", + extra={ + "details": "It will be removed in v0.8.0. Since `numpy.dtype` supports " + "unions, the rule was renamed. Use the rule 'dtype_union' if you want " + "to modify this expression in a plugin." + }, + ) + doctype_transpiler = doctype.DoctypeTranspiler( grammar=grammar, transformer=doctype_transformer ) diff --git a/src/docstub/doctype.lark b/src/docstub/doctype.lark index 65015ac..7d72d94 100644 --- a/src/docstub/doctype.lark +++ b/src/docstub/doctype.lark @@ -126,11 +126,15 @@ ARRAY_NAME: "array" | "ndarray" | "array-like" | "array_like" // The dtype used in an array expression. -dtype: qualname | dtype_to_expand +dtype: qualname | dtype_union | dtype_to_expand -// Dtypes may be specified as a union. But I'm not sure if `np.dtype` accepts -// a union. So we use expansion here instead. +// Dtypes may be specified as a union. But we don't want to allow any `_type`, +// so we define a dtype-specific union. +dtype_union.1: "(" qualname (_OR qualname)+ ")" + + +// DEPRECATED in favor of `dtype_union`, will be removed in v0.8.0. dtype_to_expand: "(" qualname (_OR qualname)+ ")" diff --git a/src/docstub/doctype.py b/src/docstub/doctype.py index 610c07a..bd306f7 100644 --- a/src/docstub/doctype.py +++ b/src/docstub/doctype.py @@ -709,6 +709,18 @@ def dtype(self, tree): expr = self._create_subscription_expr(children, rule="dtype") return expr + def dtype_union(self, tree): + """ + Parameters + ---------- + tree : lark.Tree + + Returns + ------- + out : Expr + """ + return self.union(tree) + def dtype_to_expand(self, tree): """ Parameters diff --git a/tests/test_doctype.py b/tests/test_doctype.py index dd794da..f457a66 100644 --- a/tests/test_doctype.py +++ b/tests/test_doctype.py @@ -357,20 +357,20 @@ def test_malformed_shape(self, shape): ("ndarray of dtype int", "ndarray[tuple[Any, ...], np.dtype[int]]"), ( "ndarray of dtype (int or float)", - "ndarray[tuple[Any, ...], np.dtype[int]]" - " | ndarray[tuple[Any, ...], np.dtype[float]]", + "ndarray[tuple[Any, ...], np.dtype[int | float]]", ), ( "ndarray of dtype (int | float | complex)", - "ndarray[tuple[Any, ...], np.dtype[int]]" - " | ndarray[tuple[Any, ...], np.dtype[float]]" - " | ndarray[tuple[Any, ...], np.dtype[complex]]", + "ndarray[tuple[Any, ...], np.dtype[int | float | complex]]", ), ], ) def test_dtype(self, doctype, expected): expr = DoctypeTranspiler()(doctype) assert expr.as_code() == expected + assert expr.find_one(rule="dtype") + if " or " in doctype: + assert expr.find_one(rule="union") @pytest.mark.parametrize( ("doctype", "expected"), @@ -381,10 +381,8 @@ def test_dtype(self, doctype, expected): ), ( "ndarray of dtype (int or float) and shape ([N,] M)", - "ndarray[tuple[int], np.dtype[int]]" - " | ndarray[tuple[int], np.dtype[float]]" - " | ndarray[tuple[int, int], np.dtype[int]]" - " | ndarray[tuple[int, int], np.dtype[float]]", + "ndarray[tuple[int], np.dtype[int | float]]" + " | ndarray[tuple[int, int], np.dtype[int | float]]", ), ], ) From fc63bc6e5f8bce4ddc25e2cc74af36e2a17d9b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Mon, 9 Nov 2026 15:53:36 +0100 Subject: [PATCH 2/4] Remove accidental inclusion in commit --- src/docstub/_app_generate_stubs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docstub/_app_generate_stubs.py b/src/docstub/_app_generate_stubs.py index a244a6c..23732c3 100644 --- a/src/docstub/_app_generate_stubs.py +++ b/src/docstub/_app_generate_stubs.py @@ -31,7 +31,7 @@ walk_source_package, ) from ._report import Stats, setup_logging -from ._stubs import Py2StubTransformer, try_format_stub, CstTreeSerializer +from ._stubs import Py2StubTransformer, try_format_stub from ._utils import escape_qualname from ._version import __version__ From c85e75343e4e6a2949acb3483ec768d2db3e90b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Mon, 9 Nov 2026 15:54:23 +0100 Subject: [PATCH 3/4] Sync stubs --- src/docstub-stubs/doctype.pyi | 1 - 1 file changed, 1 deletion(-) diff --git a/src/docstub-stubs/doctype.pyi b/src/docstub-stubs/doctype.pyi index 5ef600d..37c77d0 100644 --- a/src/docstub-stubs/doctype.pyi +++ b/src/docstub-stubs/doctype.pyi @@ -3,7 +3,6 @@ import enum import keyword import logging -import warnings from collections.abc import Callable, Generator, Iterable, Sequence from dataclasses import dataclass from functools import cached_property From c836be2e76178299f637735c2d79c71e079d4c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Mon, 9 Nov 2026 16:07:11 +0100 Subject: [PATCH 4/4] Start deprecation in v0.8.0 --- REMINDERS.md | 2 +- src/docstub/_app_generate_stubs.py | 2 +- src/docstub/doctype.lark | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/REMINDERS.md b/REMINDERS.md index 8090e81..32db423 100644 --- a/REMINDERS.md +++ b/REMINDERS.md @@ -1,6 +1,6 @@ # Reminders -## v0.8.0 +## v0.9.0 - Complete deprecation of grammar rule `dtype_to_expand`. Remove rule in `doctype.lark` and `DoctypeTranformer`. diff --git a/src/docstub/_app_generate_stubs.py b/src/docstub/_app_generate_stubs.py index 23732c3..fb5fcf0 100644 --- a/src/docstub/_app_generate_stubs.py +++ b/src/docstub/_app_generate_stubs.py @@ -392,7 +392,7 @@ def generate_stubs( logger.warning( "The grammar rule 'dtype_to_expand' is deprecated in favor of 'dtype_union'", extra={ - "details": "It will be removed in v0.8.0. Since `numpy.dtype` supports " + "details": "It will be removed in v0.9.0. Since `numpy.dtype` supports " "unions, the rule was renamed. Use the rule 'dtype_union' if you want " "to modify this expression in a plugin." }, diff --git a/src/docstub/doctype.lark b/src/docstub/doctype.lark index 7d72d94..30d8962 100644 --- a/src/docstub/doctype.lark +++ b/src/docstub/doctype.lark @@ -134,7 +134,7 @@ dtype: qualname | dtype_union | dtype_to_expand dtype_union.1: "(" qualname (_OR qualname)+ ")" -// DEPRECATED in favor of `dtype_union`, will be removed in v0.8.0. +// DEPRECATED in favor of `dtype_union`, will be removed in v0.9.0. dtype_to_expand: "(" qualname (_OR qualname)+ ")"