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

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

@ -3,7 +3,7 @@
import inspect import inspect
import shutil import shutil
import socket import socket
from collections.abc import Callable, Iterator from collections.abc import Callable, Iterator, Mapping
from datetime import datetime from datetime import datetime
from math import cos, floor, pi from math import cos, floor, pi
from pathlib import Path from pathlib import Path
@ -22,7 +22,7 @@ from rich.style import Style
from rich.syntax import Syntax from rich.syntax import Syntax
from rich.text import Text 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.deck import Deck
from spiel.renderables.image import Image 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)) 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?") @deck.slide(title="What is Spiel?")
def what() -> RenderableType: def what() -> RenderableType:
upper_left = pad_markdown( 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 import inspect
from dataclasses import dataclass, field 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.console import RenderableType
from rich.text import Text from rich.text import Text
@ -12,6 +12,7 @@ from spiel.transitions.swipe import Swipe
from spiel.triggers import Triggers from spiel.triggers import Triggers
TRIGGERS = "triggers" TRIGGERS = "triggers"
EXAMPLES = "examples"
Content = Callable[..., RenderableType] Content = Callable[..., RenderableType]
@ -50,6 +51,8 @@ class Slide:
of the deck this slide is in. of the deck this slide is in.
""" """
examples: MutableMapping[str, Callable[[], None]] = field(default_factory=dict)
def render(self, triggers: Triggers) -> RenderableType: def render(self, triggers: Triggers) -> RenderableType:
signature = inspect.signature(self.content) signature = inspect.signature(self.content)
@ -57,4 +60,7 @@ class Slide:
if TRIGGERS in signature.parameters: if TRIGGERS in signature.parameters:
kwargs[TRIGGERS] = triggers kwargs[TRIGGERS] = triggers
if EXAMPLES in signature.parameters:
kwargs[EXAMPLES] = self.examples
return self.content(**kwargs) return self.content(**kwargs)

Loading…
Cancel
Save