From e7f3d77711fe8c9c5f629f31e76d9c4bb9e9f576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Mon, 18 Aug 2025 11:31:26 +0200 Subject: [PATCH 1/3] Remove skimage specific array expression syntax Which was somewhat ambiguious and more complicated than necessary. Instead let's go with the convention used by scikit-learn. --- docs/typing_syntax.md | 34 ++++++++++++++++++---------------- src/docstub/doctype.lark | 4 ---- tests/test_docstrings.py | 6 +----- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/docs/typing_syntax.md b/docs/typing_syntax.md index 4849ccb..981bc85 100644 --- a/docs/typing_syntax.md +++ b/docs/typing_syntax.md @@ -75,26 +75,28 @@ and **mappings** exist. This expression allows adding shape and datatype information for data structures like [NumPy arrays](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html). -`array` and `ndarray`, and `array-like` and `array_like` can be used interchange-ably. +`array` and `ndarray`, and `array-like` and `array_like` can be used interchange-ably for the variable `ARRAY` below. + +| Docstring type | Python type annotation | +|----------------------------------------|------------------------| +| `ARRAY of dtype DTYPE` | `ARRAY[DTYPE]` | +| `ARRAY of dtype DTYPE and shape SHAPE` | `ARRAY[DTYPE]` | +| `ARRAY of shape SHAPE` | `ARRAY[DTYPE]` | +| `ARRAY of shape SHAPE and dtype DTYPE` | `ARRAY[DTYPE]` | + +E.g. + +| Docstring type | Python type annotation | +|------------------------------------------|------------------------| +| `array of dtype int` | `ndarray[int]` | +| `ndarray of dtype bool and shape (4, 4)` | `ndarray[bool]` | +| `array-like of dtype float` | `ArrayLike[float]` | +| `array_like of shape (M, 2)` | `ArrayLike` | -| Docstring type | Python type annotation | -|-----------------------------|------------------------| -| `array of DTYPE` | `ndarray[DTYPE]` | -| `ndarray of dtype DTYPE` | `ndarray[DTYPE]` | -| `array-like of DTYPE` | `ArrayLike[DTYPE]` | -| `array_like of dtype DTYPE` | `ArrayLike[DTYPE]` | > [!NOTE] > Noting the **shape** of an array in the docstring is supported. -> However, Python's typing system is not yet able to express this information. -> It is therefore not included in the resulting type annotation. - -| Docstring type | Python type annotation | -|--------------------------|------------------------| -| `(3,) array of DTYPE` | `ndarray[DTYPE]` | -| `(X, Y) array of DTYPE` | `ndarray[DTYPE]` | -| `([P,] M, N) array-like` | `ArrayLike` | -| `(M, ...) ndarray` | `ArrayLike` | +> However, [support for including shapes in generated stubs](https://github.com/scientific-python/docstub/issues/76) is not yet included in docstub. ## Literals diff --git a/src/docstub/doctype.lark b/src/docstub/doctype.lark index 9a621e1..d114272 100644 --- a/src/docstub/doctype.lark +++ b/src/docstub/doctype.lark @@ -89,10 +89,6 @@ _natlang_mapping: qualname "of" "{" type ":" type "}" // A natural language alternative to describe arrays with a dtype and shape. natlang_array: array_name "of dtype" dtype ("and shape" shape)? | array_name "of shape" shape ("and dtype" dtype)? - | shape array_name ("of" dtype)? - | shape? array_name "of" dtype - | shape dtype array_name - | dtype array_name // Currently a bit of a hack. Since the `array_expression` is ambiguous, we diff --git a/tests/test_docstrings.py b/tests/test_docstrings.py index 5763230..ffc4192 100644 --- a/tests/test_docstrings.py +++ b/tests/test_docstrings.py @@ -228,12 +228,9 @@ def test_rst_role(self, doctype, expected): @pytest.mark.parametrize( ("fmt", "expected_fmt"), [ - ("{shape} {name}", "{name}"), - ("{shape} {name} of {dtype}", "{name}[{dtype}]"), - ("{shape} {dtype} {name}", "{name}[{dtype}]"), - ("{dtype} {name}", "{name}[{dtype}]"), ("{name} of shape {shape} and dtype {dtype}", "{name}[{dtype}]"), ("{name} of dtype {dtype} and shape {shape}", "{name}[{dtype}]"), + ("{name} of {dtype}", "{name}[{dtype}]"), ], ) @pytest.mark.parametrize("name", ["array", "ndarray", "array-like", "array_like"]) @@ -261,7 +258,6 @@ def escape(name: str) -> str: ("doctype", "expected"), [ ("ndarray of dtype (int or float)", "ndarray[int | float]"), - ("([P,] M, N) (int or float) array", "array[int | float]"), ], ) def test_natlang_array_specific(self, doctype, expected): From 375b8b3ea19578ec4823efc5c73380100df79fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Mon, 18 Aug 2025 11:41:57 +0200 Subject: [PATCH 2/3] Remove skimage array forms from example package --- examples/example_pkg/_numpy.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/example_pkg/_numpy.py b/examples/example_pkg/_numpy.py index 33fa9ca..fd7f031 100644 --- a/examples/example_pkg/_numpy.py +++ b/examples/example_pkg/_numpy.py @@ -20,12 +20,12 @@ def func_ndarray(a1, a2, a3, a4=None): ---------- a1 : ndarray a2 : np.NDArray - a3 : (N, 3) ndarray of float + a3 : ndarray of dtype float and shape (N, 3) a4 : ndarray of shape (1,) and dtype uint8 Returns ------- - r1 : uint8 array + r1 : array of dtype uint8 r2 : array of dtype complex and shape (1, ..., 3) """ @@ -37,11 +37,11 @@ def func_array_like(a1, a2, a3, a4): ---------- a1 : array-like a2 : array_like - a3 : (N, 3) array-like of float + a3 : array-like of dtype float and shape (N, 3) a4 : array-like of shape (1,) and dtype uint8 Returns ------- - r1 : uint8 array-like + r1 : array-like of dtype uint8 r2 : array_like of dtype complex and shape (1, ..., 3) """ From 71b7c689714cdcd80035f31c9cfd147e4c77f15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Sat, 25 Oct 2025 20:48:18 +0200 Subject: [PATCH 3/3] Replace "e.g." with "for example" The latter is clearer and easier to understand language. --- docs/introduction.md | 6 +++--- docs/typing_syntax.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/introduction.md b/docs/introduction.md index 5d81f29..d789a81 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -110,7 +110,7 @@ ski = "skimage" "sklearn.tree" = "sklearn.tree" ``` -which will enable any type that is prefixed with `ski.` or `sklearn.tree.`, e.g. `ski.transform.AffineTransform` or `sklearn.tree.DecisionTreeClassifier`. +which will enable any type that is prefixed with `ski.` or `sklearn.tree.`, for example `ski.transform.AffineTransform` or `sklearn.tree.DecisionTreeClassifier`. :::{important} Docstub doesn't check that types actually exist or if a symbol is a valid type. @@ -162,7 +162,7 @@ In those cases, you docstub provides a few approaches to dealing with this. Docstub will always preserve inline type annotations, regardless of what the docstring contains. This is useful for example, if you want to express something that isn't yet supported by Python's type system. -E.g., consider the docstring type of `ord` parameter in [`numpy.linalg.matrix_norm`](https://numpy.org/doc/stable/reference/generated/numpy.linalg.matrix_norm.html) +For example, consider the docstring type of `ord` parameter in [`numpy.linalg.matrix_norm`](https://numpy.org/doc/stable/reference/generated/numpy.linalg.matrix_norm.html) ```rst ord : {1, -1, 2, -2, inf, -inf, ‘fro’, ‘nuc’}, optional ``` @@ -181,7 +181,7 @@ At its heart, docstub transforms Python source files into stub files. You can tell docstub to temporarily stop that transformation for a specific area with a comment directive. Wrapping lines of code with `docstub: off` and `docstub: on` comments will preserve these lines completely. -E.g., consider the following example: +For example, consider the following example: ```python class Foo: # docstub: off diff --git a/docs/typing_syntax.md b/docs/typing_syntax.md index ef24f44..3d0e780 100644 --- a/docs/typing_syntax.md +++ b/docs/typing_syntax.md @@ -45,7 +45,7 @@ This extends the basic subscription syntax for [generics](https://typing.python. | `CONTAINER of (X or Y)` | `CONTAINER[X \| Y]` | For the simple case `CONTAINER of X`, where `X` is a name, you can append `(s)` to indicate the plural form. -E.g., `list of float(s)`. +For example, `list of float(s)`. Variants of for [**tuples**](https://typing.python.org/en/latest/spec/tuples.html) @@ -82,7 +82,7 @@ This expression allows adding shape and datatype information for data structures | `ARRAY of shape SHAPE` | `ARRAY[DTYPE]` | | `ARRAY of shape SHAPE and dtype DTYPE` | `ARRAY[DTYPE]` | -E.g. +For example | Docstring type | Python type annotation | |------------------------------------------|------------------------| @@ -115,7 +115,7 @@ However, `Literal[X]` is more explicit. :::{warning} Python's `typing.Literal` only supports a restricted set of parameters. -E.g., `float` literals are not yet supported by the type system but are allowed by docstub. +For example, `float` literals are not yet supported by the type system but are allowed by docstub. Addressing this use case is on the roadmap. See [issue 47](https://github.com/scientific-python/docstub/issues/47) for more details. :::