playing around with first-class examples

examples
Josh Karpel 1 year ago
parent 16e844d2ca
commit 032b5f8982

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 194 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 54 KiB

@ -1,6 +1,7 @@
from spiel.app import SuspendType, present
from spiel.constants import __version__
from spiel.deck import Deck
from spiel.example import Example, example
from spiel.slide import Slide
from spiel.transitions.protocol import Direction, Transition
from spiel.transitions.swipe import Swipe
@ -9,6 +10,8 @@ from spiel.triggers import Triggers
__all__ = [
"Deck",
"Direction",
"example",
"Example",
"Slide",
"SuspendType",
"Swipe",

@ -4,6 +4,7 @@ from collections.abc import Callable, Iterator, Mapping, Sequence
from dataclasses import dataclass, field
from typing import Type, overload
from spiel.example import Example
from spiel.slide import Content, Slide
from spiel.transitions.protocol import Transition
from spiel.transitions.swipe import Swipe
@ -32,6 +33,7 @@ class Deck(Sequence[Slide]):
self,
title: str = "",
bindings: Mapping[str, Callable[..., None]] | None = None,
examples: Mapping[str, Example] | None = None,
transition: Type[Transition] | None = None,
) -> Callable[[Content], Content]:
"""
@ -56,6 +58,7 @@ class Deck(Sequence[Slide]):
title=title,
content=content,
bindings=bindings or {},
examples=examples or {},
transition=transition,
)
)

@ -3,7 +3,7 @@
import inspect
import shutil
import socket
from collections.abc import Callable, Iterator
from collections.abc import Callable, Iterator, Mapping
from datetime import datetime
from math import cos, floor, pi
from pathlib import Path
@ -22,7 +22,7 @@ from rich.style import Style
from rich.syntax import Syntax
from rich.text import Text
from spiel import Slide, SuspendType, Triggers, present
from spiel import Example, Slide, SuspendType, Triggers, example, present
from spiel.deck import Deck
from spiel.renderables.image import Image
@ -41,6 +41,24 @@ def pad_markdown(markup: str) -> RenderableType:
return Padding(Markdown(dedent(markup), justify="center"), pad=(0, 5))
@example(name="foo")
def foo():
print("foo")
@deck.slide(title="Executable Examples", examples={"foo": foo})
def examples(triggers: Triggers, examples: Mapping[str, Example]) -> RenderableType:
e = examples["foo"]
if triggers.triggered:
e.run()
return Group(
Align.center(e.source_panel()),
Align.center(e.results_panel()),
)
@deck.slide(title="What is Spiel?")
def what() -> RenderableType:
upper_left = pad_markdown(

@ -0,0 +1,46 @@
import inspect
from collections.abc import Callable
from contextlib import redirect_stdout
from dataclasses import dataclass
from io import StringIO
from rich.console import RenderableType
from rich.panel import Panel
from rich.syntax import Syntax
def example(**kwargs):
def deco(func):
return Example(**kwargs, func=func)
return deco
@dataclass
class Example:
name: str
func: Callable[[], None]
result: str | None = None
return_value: object = None
def source_panel(self) -> RenderableType:
source_lines, _ = inspect.getsourcelines(self.func)
return Panel.fit(
Syntax(
"\n".join(source_lines).rstrip(),
lexer="python",
),
)
def results_panel(self) -> RenderableType:
return Panel.fit(self.result or "")
def run(self):
if self.result is not None:
return
cap = StringIO()
with redirect_stdout(cap):
self.return_value = self.func()
self.result = cap.getvalue()

@ -2,7 +2,7 @@ from __future__ import annotations
import inspect
from dataclasses import dataclass, field
from typing import Callable, Mapping, Type
from typing import Callable, Mapping, MutableMapping, Type
from rich.console import RenderableType
from rich.text import Text
@ -12,6 +12,7 @@ from spiel.transitions.swipe import Swipe
from spiel.triggers import Triggers
TRIGGERS = "triggers"
EXAMPLES = "examples"
Content = Callable[..., RenderableType]
@ -50,6 +51,8 @@ class Slide:
of the deck this slide is in.
"""
examples: MutableMapping[str, Callable[[], None]] = field(default_factory=dict)
def render(self, triggers: Triggers) -> RenderableType:
signature = inspect.signature(self.content)
@ -57,4 +60,7 @@ class Slide:
if TRIGGERS in signature.parameters:
kwargs[TRIGGERS] = triggers
if EXAMPLES in signature.parameters:
kwargs[EXAMPLES] = self.examples
return self.content(**kwargs)

Loading…
Cancel
Save