diff --git a/papyri/rich_render.py b/papyri/rich_render.py index 3ce9c6d1..3b66cb18 100644 --- a/papyri/rich_render.py +++ b/papyri/rich_render.py @@ -2,17 +2,29 @@ Attempt to render using the rich protocol. """ +from __future__ import annotations + from .myst_ast import MThematicBreak, MHeading from dataclasses import dataclass from rich.segment import Segment from typing import Any, Optional from rich.console import Console, ConsoleOptions, RenderResult, Group -from rich.panel import Panel, Box +from rich.panel import Panel +from rich.box import Box from rich.padding import Padding from rich import print import rich import json +from rich.table import Table + +from typing import TYPE_CHECKING + +from .myst_ast import MText + +if TYPE_CHECKING: + from .myst_ast import MAdmonition, MAdmonitionTitle + def pad(arg): return Padding(arg, (0, 0, 0, 2)) @@ -186,19 +198,28 @@ def visit_Directive(self, node): def visit_MLink(self, node): return self.generic_visit(node.children) - def visit_MAdmonitionTitle(self, node): - return [Panel(Unimp(str(node.to_dict())))] + def visit_MAdmonitionTitle(self, node: MAdmonitionTitle): return self.generic_visit(node.children) - def visit_MAdmonition(self, node): + def visit_MAdmonition(self, node: MAdmonition): + COLOR = {"warning": "yellow", "deprecated": "red", "note": "blue"} + # TODO, there seem to be some error with the printing of wide characters + SYMBOL = {"warning": "⚠", "deprecated": "ⓧ ", "note": "ⓘ "} + SYMBOL = {"warning": "/!\\", "deprecated": "[x]", "note": "(i)"} title, *other = node.children - assert title.type == "admonitionTitle" - acc = self.generic_visit([title]) + table: Table + color = COLOR.get(node.kind, "purple") + symbol = SYMBOL.get(node.kind, "|?|") if other: - rd = self.generic_visit(other) - - acc.append(Panel(Group(*rd))) - return acc + table = Table(border_style=color) + table.add_column( + Group(*self.generic_visit([MText(symbol + ": ")] + [title])) + ) + table.add_row(Group(*self.generic_visit(other))) + else: + table = Table(border_style=color, show_header=False) + table.add_row(Group(*self.generic_visit([MText(symbol + ": ")] + [title]))) + return [table] def visit_MHeading(self, node: MHeading): cs = [RToken("#" * (node.depth + 1) + " ")] + self.generic_visit(node.children) diff --git a/papyri/tests/expected/numpy:einsum.expected b/papyri/tests/expected/numpy:einsum.expected index ab5ecd8f..bc18ec9b 100644 --- a/papyri/tests/expected/numpy:einsum.expected +++ b/papyri/tests/expected/numpy:einsum.expected @@ -73,9 +73,9 @@ output : ndarray ## Notes -╭──────────────────────────────────────────────────────────────────────────────╮ -│ {'type': 'admonitionTitle', 'children': [{'type': 'text', 'value': 'versiona │ -╰──────────────────────────────────────────────────────────────────────────────╯ +┌──────────────────────────────────────────────────────────────────────────────┐ +│ (i): versionadded 1.6.0 │ +└──────────────────────────────────────────────────────────────────────────────┘ The Einstein summation convention can be used to compute many multi-dimensional, linear algebraic array operations. `einsum` provides a succinct way of representing these. @@ -148,17 +148,17 @@ output shape is not provided in this format `einsum` will be calculated in implicit mode, otherwise it will be performed explicitly. The examples below have corresponding `einsum` calls with the two parameter methods. -╭──────────────────────────────────────────────────────────────────────────────╮ -│ {'type': 'admonitionTitle', 'children': [{'type': 'text', 'value': 'versiona │ -╰──────────────────────────────────────────────────────────────────────────────╯ +┌──────────────────────────────────────────────────────────────────────────────┐ +│ (i): versionadded 1.10.0 │ +└──────────────────────────────────────────────────────────────────────────────┘ Views returned from einsum are now writeable whenever the input array is writeable. For example, np.einsum('ijk...->kji...', a) will now have the same effect as np.swapaxes(a, 0, 2) and np.einsum('ii->i', a) will return a writeable view of the diagonal of a 2D array. -╭──────────────────────────────────────────────────────────────────────────────╮ -│ {'type': 'admonitionTitle', 'children': [{'type': 'text', 'value': 'versiona │ -╰──────────────────────────────────────────────────────────────────────────────╯ +┌──────────────────────────────────────────────────────────────────────────────┐ +│ (i): versionadded 1.12.0 │ +└──────────────────────────────────────────────────────────────────────────────┘ Added the optimize argument which will optimize the contraction order of an einsum expression. For a contraction with three or more operands this can greatly increase the computational efficiency at the cost of a larger memory diff --git a/papyri/tests/expected/numpy:linspace.expected b/papyri/tests/expected/numpy:linspace.expected index 34eca357..ccdbea9a 100644 --- a/papyri/tests/expected/numpy:linspace.expected +++ b/papyri/tests/expected/numpy:linspace.expected @@ -11,22 +11,20 @@ Returns num evenly spaced samples, calculated over the interval [`start`, stop The endpoint of the interval can optionally be excluded. -╭──────────────────────────────────────────────────────────────────────────────╮ -│ {'type': 'admonitionTitle', 'children': [{'type': 'text', 'value': 'versionc │ -╰──────────────────────────────────────────────────────────────────────────────╯ -╭──────────────────────────────────────────────────────────────────────────────╮ -│ Non-scalar `start` and `stop` are now supported. │ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ (i): versionchanged 1.16.0 ┃ +┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ +│ Non-scalar start and stop are now supported. │ │ │ -╰──────────────────────────────────────────────────────────────────────────────╯ -╭──────────────────────────────────────────────────────────────────────────────╮ -│ {'type': 'admonitionTitle', 'children': [{'type': 'text', 'value': 'versionc │ -╰──────────────────────────────────────────────────────────────────────────────╯ -╭──────────────────────────────────────────────────────────────────────────────╮ +└──────────────────────────────────────────────────────────────────────────────┘ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ (i): versionchanged 1.20.0 ┃ +┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ │ Values are rounded towards -inf instead of 0 when an integer dtype is │ │ specified. The old behavior can still be obtained with np.linspace(start, │ │ stop, num).astype(int) │ │ │ -╰──────────────────────────────────────────────────────────────────────────────╯ +└──────────────────────────────────────────────────────────────────────────────┘ ## Parameters start : array_like @@ -53,17 +51,17 @@ dtype : dtype, optional inferred from start and stop. The inferred dtype will never be an integer; `float` is chosen even if the arguments would produce an array of integers. - ╭────────────────────────────────────────────────────────────────────────────╮ - │ {'type': 'admonitionTitle', 'children': [{'type': 'text', 'value': 'versio │ - ╰────────────────────────────────────────────────────────────────────────────╯ + ┌────────────────────────────────────────────────────────────────────────────┐ + │ (i): versionadded 1.9.0 │ + └────────────────────────────────────────────────────────────────────────────┘ axis : int, optional The axis in the result to store the samples. Relevant only if start or stop are array-like. By default (0), the samples will be along a new axis inserted at the beginning. Use -1 to get an axis at the end. - ╭────────────────────────────────────────────────────────────────────────────╮ - │ {'type': 'admonitionTitle', 'children': [{'type': 'text', 'value': 'versio │ - ╰────────────────────────────────────────────────────────────────────────────╯ + ┌────────────────────────────────────────────────────────────────────────────┐ + │ (i): versionadded 1.16.0 │ + └────────────────────────────────────────────────────────────────────────────┘ ## Returns samples : ndarray diff --git a/papyri/tests/expected/papyri.examples.expected b/papyri/tests/expected/papyri.examples.expected index 604b7f27..8ef89ae2 100644 --- a/papyri/tests/expected/papyri.examples.expected +++ b/papyri/tests/expected/papyri.examples.expected @@ -94,13 +94,12 @@ Unordered list ## Admonitions -╭──────────────────────────────────────────────────────────────────────────────╮ -│ {'type': 'admonitionTitle', 'children': [{'type': 'text', 'value': 'note '}] │ -╰──────────────────────────────────────────────────────────────────────────────╯ -╭──────────────────────────────────────────────────────────────────────────────╮ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ (i): note ┃ +┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ │ An admonition note ! │ │ │ -╰──────────────────────────────────────────────────────────────────────────────╯ +└──────────────────────────────────────────────────────────────────────────────┘ This is a link to `Jupyter website ` ## Code (title 2) diff --git a/papyri/tree.py b/papyri/tree.py index 3e2da512..350ffdc5 100644 --- a/papyri/tree.py +++ b/papyri/tree.py @@ -571,12 +571,13 @@ def _admonition_handler_x(self, name, argument, options, content): MAdmonition( [MAdmonitionTitle([MText(f"{name} {argument}")])] + inner[0].children, + kind=name, ) ] else: return [ MAdmonition( - [MAdmonitionTitle([MText(f"{name} {argument}")])], + [MAdmonitionTitle([MText(f"{name} {argument}")])], kind=name ) ]