plesty.lib.ui
GUI framework: one home window, many rearrangeable sub-windows.
The framework is generic — a Panel is anything
worth a sub-window. MonitorPanel shows a
live view and DevicePanel drives an
instrument; a run status board is the same contract again.
Theme carries the plesty.net design tokens so
every PLESTY GUI looks like the platform it belongs to.
The Qt-dependent names (Shell, PlotRenderer, run())
are resolved lazily, so import plesty.lib.ui works on a headless host
without PySide6 installed; only using them requires the gui extra:
uv add "plesty-lib[gui]"
Submodules
Attributes
Classes
The four things a panel asks of a device, wherever the device is. |
|
Runs a handle's calls on one thread and hands the results back by queue. |
|
A |
|
One finished call, waiting to be applied on the GUI thread. |
|
One rendered control, as derived from the device's own declaration. |
|
Sub-window holding one device's controls. |
|
Sub-window rendering one monitor. |
|
Sub-window showing one plot of a run. |
|
Base class for the dockable units of a |
|
Resolved design tokens plus the stylesheet built from them. |
Functions
|
Derive a device's controls from its serialized doc model. |
Package Contents
- class plesty.lib.ui.DeviceHandle
Bases:
ProtocolThe four things a panel asks of a device, wherever the device is.
DeviceTCPIPClientsatisfies this as written; an in-process device reaches it throughLocalHandle; a remote bench relays the same four calls through its agent.- describe() dict[str, Any]
Return
{"methods": [...], "doc": {...} | None}for the device.- Return type:
dict[str, Any]
- query(key: str) Any
Read configuration parameter key from the device.
- Parameters:
key (str)
- Return type:
Any
- write(key: str, value: Any) Any
Write value to configuration parameter key.
- Parameters:
key (str)
value (Any)
- Return type:
Any
- call(op: str, **kwargs: Any) Any
Run operation op with keyword arguments.
- Parameters:
op (str)
kwargs (Any)
- Return type:
Any
- class plesty.lib.ui.DeviceWorker(handle: DeviceHandle, name: str = 'device')
Runs a handle’s calls on one thread and hands the results back by queue.
One worker per panel, not one per shell. A device server that has died answers nothing until its client times out, and a shared worker would make that one device stall every panel in the window; a worker of its own means the dead device’s panel goes stale and the rest keep their clock.
Requests are coalesced by tag: asking again for something already queued or in flight is dropped rather than appended. Without it a device slower than the shell’s refresh accumulates a poll backlog it can never work off, and the panel ends up showing readings from minutes ago.
Prepare a worker over handle; it starts on
start().- Parameters:
handle (DeviceHandle) – What the worker calls.
name (str) – Used for the thread name and log lines.
- handle
- name = 'device'
- _inflight: set[Any]
- _lock
- _thread: threading.Thread | None = None
- start() None
Start the worker thread; calling it twice is harmless.
- Return type:
None
- stop(timeout: float = JOIN_TIMEOUT_S) None
Ask the worker to finish and wait briefly for it.
The thread is a daemon and the wait is short on purpose: a call already carries the device’s own timeout, and closing a window must not hang on an instrument that stopped answering.
- Parameters:
timeout (float) – Seconds to wait for the thread to end.
- Return type:
None
- property running: bool
Whether the worker thread is alive.
- Return type:
bool
- submit(tag: Any, verb: str, *args: Any, **kwargs: Any) bool
Queue a call, unless one with the same tag is already outstanding.
- Parameters:
tag (Any) – Label the matching
Resultcarries back, and the key requests are coalesced on.verb (str) –
"describe","query","write"or"call".*args (Any) – Positional arguments for the verb.
**kwargs (Any) – Keyword arguments for the verb.
- Returns:
Truewhen the request was queued,Falsewhen an identical tag was already outstanding and this one was dropped.- Return type:
bool
- results() list[Result]
Take every finished call off the queue without blocking.
- Returns:
The results that arrived since the last drain, in order.
- Return type:
list[Result]
- property pending: int
How many calls are queued or in flight.
- Return type:
int
- _run() None
Take requests until asked to stop.
- Return type:
None
- class plesty.lib.ui.LocalHandle(device: Any)
A
DeviceHandleover a device object in this process.The device already answers
query()andwrite(); what it does not have is the other two, because in-process callers usedoc_model()and call operations as attributes. Going through the same serialized doc payload the wire uses is deliberate — a module’s own GUI then exercises exactly what the console and a remote client will see, so a hole in the payload shows up at the bench and not only across a network.Wrap device.
- Parameters:
device (Any) – A
BaseDeviceSyncModel.
- device
- describe() dict[str, Any]
Return the device’s methods and its serialized doc model.
- Returns:
The same shape the device server’s
describereply carries.- Return type:
dict[str, Any]
- query(key: str) Any
Read parameter key.
- Parameters:
key (str) – Configuration key.
- Returns:
The value the device reported.
- Return type:
Any
- write(key: str, value: Any) Any
Write value to parameter key.
- Parameters:
key (str) – Configuration key.
value (Any) – The value to set.
- Returns:
Whatever the device’s
writereturns.- Return type:
Any
- call(op: str, **kwargs: Any) Any
Run operation op.
- Parameters:
op (str) – Operation name.
**kwargs (Any) – The operation’s arguments.
- Returns:
The operation’s result.
- Return type:
Any
- class plesty.lib.ui.Result
One finished call, waiting to be applied on the GUI thread.
- Variables:
tag – What the panel asked for, as it labelled the request.
value – The return value, or
Nonewhen the call raised.error – The exception message, or
""when the call succeeded.duration – How long the call took, in milliseconds.
- tag: Any
- value: Any = None
- error: str = ''
- duration: float = 0.0
- property ok: bool
Whether the call returned rather than raised.
- Return type:
bool
- plesty.lib.ui.CONTROL_KINDS: tuple[str, Ellipsis] = ('number', 'choice', 'toggle', 'text', 'readout', 'action')
- plesty.lib.ui.DEFAULT_SKIP_KINDS: tuple[str, Ellipsis] = ('lifecycle',)
- class plesty.lib.ui.Control
One rendered control, as derived from the device’s own declaration.
- Variables:
key – Configuration key or operation name.
kind – One of
CONTROL_KINDS.label – Text shown beside the control.
dtype – Declared type name, as it crossed the wire.
group – Configuration group the parameter belongs to.
unit – Physical unit, shown as the editor’s suffix.
minimum – Lower bound, or
Nonewhen the device declares none.maximum – Upper bound, or
Nonewhen the device declares none.options – Allowed values, which make the control a drop-down.
default – Declared default.
tooltip – The declaration’s description.
read_only – The device reports it; the operator cannot set it.
write_only – The operator sets it; it cannot be read back, so it is never polled.
arguments – For an
action, the operation’s arguments as controls of their own — the same rules, one level down.outputs – For an
action, what it returns — name, type and unit — which is what lets a result be shown as a reading rather than as the mapping it arrives in.op_kind – For an
action, itsOpKindkind.
- key: str
- kind: str
- label: str
- dtype: str = 'Any'
- group: str = 'default'
- unit: str | None = None
- minimum: float | None = None
- maximum: float | None = None
- options: tuple[Any, Ellipsis] | None = None
- default: Any = None
- tooltip: str = ''
- read_only: bool = False
- write_only: bool = False
- op_kind: str = ''
- required: bool = True
- property types: frozenset[str]
The types this declaration allows, a union split into its members.
Noneis not among them: it is not a type an editor can offer, and what is left is what the control has to be able to send. Switch on this rather than ondtype, which is one string and may be a union.- Return type:
frozenset[str]
- property omittable: bool
Whether leaving this argument alone means sending nothing.
An optional argument the device gives no default for has an answer already — its own — and the panel has no way to show one. A spin box always holds a number, so an untouched one said
0, and0is a real value:wait_settledread it as a zero-second budget and timed out at once. Such an argument is shown as unset and left out of the call instead.- Return type:
bool
- property repeatable: bool
Whether holding this control should keep asking the device.
Any readable parameter. An operation only when the module declares it
REPEATABLE_OP_KINDS— a reading or an acquisition, never a move or a stop.- Return type:
bool
- property readable: bool
Whether polling this control makes sense.
- Return type:
bool
- property writable: bool
Whether the operator can send this control anywhere.
- Return type:
bool
- class plesty.lib.ui.DevicePanel(handle: plesty.lib.ui.device_link.DeviceHandle, *, doc: dict[str, Any] | None = None, include: Sequence[str] | None = None, exclude: Iterable[str] = (), operations: Sequence[str] | None = None, skip_kinds: Iterable[str] = DEFAULT_SKIP_KINDS, writable: bool = False, poll_s: float = DEFAULT_POLL_S, theme: plesty.lib.ui.theme.Theme | None = None, **kwargs: Any)
Bases:
plesty.lib.ui.panel.PanelSub-window holding one device’s controls.
Constructing the panel touches neither a toolkit nor the device: it is built when a shell adds it, and it asks the device what it offers on its own worker thread, so a slow or absent instrument delays nothing. Until that answer arrives the panel says so.
The panel starts read-only. It may be pointed at an instrument an experiment is driving, and a stray write into a running measurement is worse than a click:
set_writable()is what a Take control toggle calls.Wrap handle into a dockable control panel.
- Parameters:
handle (plesty.lib.ui.device_link.DeviceHandle) – What the panel drives — see
DeviceHandle.doc (Optional[dict[str, Any]]) – The device’s serialized doc model when the caller already has it (a console that just called
describe);Nonemakes the panel fetch it.include (Optional[Sequence[str]]) – Parameter keys to show, in order.
exclude (Iterable[str]) – Parameter keys to leave out.
operations (Optional[Sequence[str]]) – Operations to offer, in order.
skip_kinds (Iterable[str]) – Operation kinds left out by default.
writable (bool) – Start with writes and operations enabled. The default is read-only.
poll_s (float) – Seconds between re-reads of the device.
theme (Optional[plesty.lib.ui.theme.Theme]) – Palette;
Noneloads the packaged one.**kwargs (Any) – Forwarded to
Panel.
- kind: ClassVar[str] = 'device'
Panel category, used for layout keys and styling hooks.
- handle
- theme = None
- writable = False
- poll_s = 1.0
- live: dict[str, dict[str, Any]]
- values: dict[str, Any]
- worker
- form: Any = None
- _selection
- _doc = None
- _note = ''
- _tone = 'idle'
- _latency = 0.0
- _polled_at = 0.0
- _selection_kwargs() dict[str, Any]
Return the selection arguments
controls_for()was configured with.- Return type:
dict[str, Any]
- open() None
Start the worker and ask the device what it offers.
Separate from
build()so the device-facing half of the panel — which is all of the interesting behaviour — can be driven with no display and no toolkit: open it,tick()it, and readcontrolsandvalues.- Return type:
None
- build(parent: Any = None) Any
Create the form, then open the device.
- Parameters:
parent (Any) – The parent widget provided by the shell.
- Returns:
The form widget.
- Return type:
Any
- tick() None
Apply whatever the worker finished, then poll if polling is on.
Both halves run on the shell’s clock and neither blocks: this is the only place results cross back to the GUI thread, and the coalescing in
DeviceWorkeris what keeps a slow device from building a backlog it can never work off.Polling is off until it is asked for — see
set_live().- Return type:
None
- control(key: str) Control | None
The control named key, or
None.- Parameters:
key (str)
- Return type:
Optional[Control]
- _read(key: str, arguments: dict[str, Any] | None = None) None
Ask the device about one control: a parameter’s value, or an operation.
- Parameters:
key (str)
arguments (Optional[dict[str, Any]])
- Return type:
None
- read_once(key: str | None = None, arguments: Any = None) None
Ask the device once: for key, or for every value the panel shows.
- Parameters:
key (Optional[str]) – The control to read;
Nonereads every readable one.arguments (Any) – For an operation, what to call it with.
- Return type:
None
- set_live(key: str, live: bool, arguments: Any = None) None
Start or stop re-reading one control on the shell’s clock.
- Parameters:
key (str) – The control to keep reading.
live (bool) – Whether to keep reading it.
arguments (Any) – For an operation, what to keep calling it with. Taken once, when it starts: an operation repeating on a timer should go on asking the same question, not whatever the form happens to hold when the timer next fires.
- Return type:
None
- is_live(key: str) bool
Whether key is being re-read.
- Parameters:
key (str)
- Return type:
bool
- status() str
Return the line shown in the panel’s title bar.
- Returns:
What the panel is doing, or what went wrong.
- Return type:
str
- tone() str
Return the state colour for the panel’s dot.
- Returns:
errorwhen the last call failed,warningwhen the device offered no schema,runningonce controls are on screen.- Return type:
str
- close() None
Stop the worker thread.
- Return type:
None
- describe() dict[str, Any]
Return the panel description including what it drives.
- Returns:
The panel’s placement plus its controls and whether it is writable.
- Return type:
dict[str, Any]
- set_writable(writable: bool) None
Enable or disable every editor and button.
- Parameters:
writable (bool) – Whether the operator may drive the device.
- Return type:
None
- request_write(key: str, value: Any) None
Send a parameter change to the device.
- Parameters:
key (str) – Configuration key.
value (Any) – The value the operator entered.
- Return type:
None
- request_call(op: str, arguments: dict[str, Any] | None = None) None
Run an operation on the device.
- Parameters:
op (str) – Operation name.
arguments (Optional[dict[str, Any]]) – The operation’s arguments.
- Return type:
None
- _apply(result: plesty.lib.ui.device_link.Result) None
Fold one finished call into the panel’s state and its form.
- Parameters:
result (plesty.lib.ui.device_link.Result) – What the worker handed back.
- Return type:
None
- _receive_doc(describe: Any) None
Derive the controls from a
describereply and fill the form.- Parameters:
describe (Any) – The reply, or
None.- Return type:
None
- _fail(result: plesty.lib.ui.device_link.Result) None
Record a failed call in the title bar.
- Parameters:
result (plesty.lib.ui.device_link.Result) – The failed result.
- Return type:
None
- plesty.lib.ui.controls_for(doc: dict[str, Any] | None, *, include: Sequence[str] | None = None, exclude: Iterable[str] = (), operations: Sequence[str] | None = None, skip_kinds: Iterable[str] = DEFAULT_SKIP_KINDS) list[Control]
Derive a device’s controls from its serialized doc model.
This is the whole schema-to-widget mapping, and it is deliberately free of any toolkit: it is where the bounds, units and options come from, so it is where a drifting panel would be caught, and a plain test can catch it.
- Parameters:
doc (Optional[dict[str, Any]]) – A
to_dict()payload — from adescribereply or from the device itself.None(an older server, or a device whose model failed to build) yields no controls rather than an error.include (Optional[Sequence[str]]) – Parameter keys to show, in this order.
Noneshows every declared parameter. A grouped parameter is named as the device addresses it,group.parameter.exclude (Iterable[str]) – Parameter keys to leave out, applied after include.
operations (Optional[Sequence[str]]) – Operation names to offer, in this order.
Noneoffers every operation whose kind is not in skip_kinds; naming one overrides that, so an operation can always be asked for explicitly.skip_kinds (Iterable[str]) – Operation kinds left out when operations is
None.
- Returns:
The parameters in declaration order, then the operations.
- Return type:
list[Control]
- class plesty.lib.ui.MonitorPanel(monitor: plesty.lib.monitor.base_monitor.Monitor, *, theme: plesty.lib.ui.theme.Theme | None = None, **kwargs: Any)
Bases:
plesty.lib.ui.panel.PanelSub-window rendering one monitor.
The panel is toolkit-free until it is built: constructing and describing it needs no GUI, which is what lets a headless test cover a shell’s composition.
Wrap monitor into a dockable panel.
- Parameters:
monitor (plesty.lib.monitor.base_monitor.Monitor) – The live view to render; its name and title become the panel’s unless overridden.
theme (Optional[plesty.lib.ui.theme.Theme]) – Palette for the plot;
Noneloads the packaged theme.**kwargs (Any) – Forwarded to
Panel(name,title,area,floating,closable,min_width,min_height).
- kind: ClassVar[str] = 'monitor'
Panel category, used for layout keys and styling hooks.
- monitor
- theme = None
- renderer: Any = None
- build(parent: Any = None) Any
Create the plot widget and attach it to the monitor.
- Parameters:
parent (Any) – The parent widget provided by the shell.
- Returns:
The plot widget.
- Return type:
Any
- tick() None
Drain the monitor’s source; every new frame redraws immediately.
- Return type:
None
- status() str
Return the monitor’s status line.
- Returns:
The text the monitor wants shown in the title bar.
- Return type:
str
- close() None
Detach the renderer and close the monitor’s source.
- Return type:
None
- describe() dict[str, Any]
Return the panel description including the monitor it shows.
- Returns:
The panel’s placement plus
describe().- Return type:
dict[str, Any]
- class plesty.lib.ui.PlotPanel(plot: plesty.lib.monitor.plots.Plot, data: Any, *, theme: plesty.lib.ui.theme.Theme | None = None, **kwargs: Any)
Bases:
plesty.lib.ui.panel.PanelSub-window showing one plot of a run.
Toolkit-free until it is built, like every panel: constructing and describing it needs no GUI, which is what lets a headless test cover a viewer’s composition.
Show plot over data.
- Parameters:
plot (plesty.lib.monitor.plots.Plot) – The view to draw.
data (Any) – The run’s store, shared with this viewer’s other panels.
theme (Optional[plesty.lib.ui.theme.Theme]) – Palette for the plot;
Noneloads the packaged theme.**kwargs (Any) – Forwarded to
Panel.
- kind = 'plot'
Panel category, used for layout keys and styling hooks.
- plot
- data
- theme = None
- renderer: Any = None
- _shape: tuple[Any, Ellipsis] = ()
- _own_widget: Any = None
- _failure = ''
- _drawing: concurrent.futures.Future[list[plesty.lib.monitor.plots.Drawable]] | None = None
- build(parent: Any = None) Any
Create the widget this panel shows.
A plot that overrides
build()supplies its own widget and is never drawn as a plot — the escape hatch for a view that is a table or an image browser rather than a curve.- Parameters:
parent (Any) – The parent widget provided by the shell.
- Returns:
The widget.
- Return type:
Any
- tick() None
Show what the last draw produced, and set the next one going.
The work a draw does is not this thread’s to do. Reading what has committed and asking the plot what to draw are a file read and, for a view that fits its lines, a least-squares solve per spectrum — and this runs on the thread that answers clicks and repaints. Done here it stopped a console following a live run for seconds at a time, which is a window that looks hung while the measurement it is showing is perfectly fine.
So a tick renders whatever the drawing thread has finished and then asks it for the next, and the window is never inside a draw. A panel has at most one in flight: ticks that arrive while one is running start nothing, which is also what keeps a slow plot from queueing up work it will never catch up with. The cost is that a drawing appears on the tick after the one that asked for it — a poll interval late, on a view that is watching a measurement unfold.
- Return type:
None
- _begin_drawing() None
Ask the drawing thread for the next drawing, if it is free of this panel.
- Return type:
None
- _compute_drawing() list[plesty.lib.monitor.plots.Drawable]
Poll the data and ask the plot what to draw. Runs off the GUI thread.
The poll is shared: whichever panel gets here first brings the store up to date and the rest find it already so, which is why one run is read once however many plots watch it.
- Return type:
- _show_finished_drawing() None
Render the drawing the thread has finished, if it has finished one.
- Return type:
None
- status() str
Return what the title bar shows beside the plot’s name.
- Returns:
How far the run has got, which is the same question for every plot of it, so no plot has to answer it — or why this view stopped drawing, which is the one thing only this panel knows.
- Return type:
str
- close() None
Drop the renderer; the store is shared and is not closed here.
- Return type:
None
- describe() dict[str, Any]
Return the panel’s placement plus what it draws.
- Returns:
The panel description, with the plot’s title and class.
- Return type:
dict[str, Any]
- plesty.lib.ui.DOCK_AREAS: tuple[str, Ellipsis] = ('left', 'right', 'top', 'bottom')
- class plesty.lib.ui.Panel(*, name: str | None = None, title: str | None = None, area: str = 'right', floating: bool = False, closable: bool = True, weight: float = 1.0, min_width: int | None = None, min_height: int | None = None)
Bases:
abc.ABCBase class for the dockable units of a
Shell.Subclasses implement
build()and usuallytick(). The panel owns its widget; the shell owns where the widget sits, and remembers that placement between sessions throughname.Configure how the shell should place this panel.
- Parameters:
name (Optional[str]) – Stable identifier used as the layout key; must be unique within a shell. Defaults to the class name.
title (Optional[str]) – Title shown in the panel’s bar; defaults to name.
area (str) – Initial docking area — one of
DOCK_AREAS.floating (bool) – Start as a free-floating window instead of docked.
closable (bool) – Allow the operator to close the panel (it can always be brought back from the shell’s Panels menu).
weight (float) – Share of the area’s space this panel starts with, relative to its neighbours: a plot 3, a readout strip 1. Only the initial arrangement — the operator resizes from there, and a saved layout overrides it.
min_width (Optional[int]) – Minimum widget width in pixels.
min_height (Optional[int]) – Minimum widget height in pixels.
- Raises:
ValueError – If area is not a known docking area.
- kind: ClassVar[str] = 'panel'
Panel category, used for layout keys and styling hooks.
- name = 'Panel'
- title = 'Panel'
- area = 'right'
- floating = False
- closable = True
- weight = 1.0
- min_width = None
- min_height = None
- _widget: Any = None
- abstractmethod build(parent: Any = None) Any
Create and return the panel’s widget.
Called once, when the panel is added to a shell. Toolkit imports belong inside this method, so that constructing a panel — and describing it, and testing it — needs no GUI installed.
- Parameters:
parent (Any) – The parent widget the shell provides.
- Returns:
The widget to show inside the sub-window.
- Return type:
Any
- tick() None
Advance the panel on the shell’s clock.
Called at the shell’s refresh interval on the GUI thread. Implementations must return quickly: drain a source, redraw, and nothing more.
- Return type:
None
- status() str
Return the one-line status shown in the panel’s title bar.
- Returns:
The status text; empty by default.
- Return type:
str
- tone() str
Return the state colour of the panel’s dot.
One of the theme’s state names —
running,idle,warning,error. The default reads the panel as working whenever it has something to say, which is right for a view that only ever draws. A panel that can fail while still running — a device that stopped answering, a source that went stale — overrides this, because a red dot is how the operator learns from across the room.- Returns:
The state name.
- Return type:
str
- close() None
Release whatever the panel holds; called when the shell shuts down.
- Return type:
None
- property widget: Any
The built widget, or
Nonebefore the panel was added to a shell.- Return type:
Any
- ensure_widget(parent: Any = None) Any
Build the widget on first use and return it.
- Parameters:
parent (Any) – The parent widget passed to
build().- Returns:
The panel’s widget.
- Return type:
Any
- describe() dict[str, Any]
Return a JSON-serializable description of this panel.
- Returns:
Identity and placement, as stored in a saved layout.
- Return type:
dict[str, Any]
- plesty.lib.ui.ASSETS = 'plesty.lib.ui.assets'
- class plesty.lib.ui.Theme
Resolved design tokens plus the stylesheet built from them.
- Variables:
name – Theme identifier, e.g.
"plesty-dark".tokens – Token name → hex colour.
series – Token names cycled for successive traces of a view.
colormap – Hex stops of the image/heatmap colour map, dark to bright.
state – Semantic state name → token name (running, idle, error, …).
- name: str = 'plesty-dark'
- tokens: dict[str, str]
- series: list[str] = []
- colormap: list[str] = []
- state: dict[str, str]
- classmethod load(palette: str | pathlib.Path | None = None) Theme
Load the packaged palette, or a custom one from disk.
- Parameters:
palette (Optional[str | pathlib.Path]) – Path to a JSON palette with the same keys as the packaged
palette.json;Noneloads the packaged one.- Returns:
The resolved theme.
- Return type:
- color(token: str, default: str | None = None) str
Return the hex colour of a design token.
- Parameters:
token (str) – Token name (
"cyan","violet","muted", …) or a literal#rrggbbvalue, which is passed through.default (Optional[str]) – Returned when the token is unknown; without it an unknown token resolves to a glaring magenta rather than failing silently mid-experiment.
- Returns:
The hex colour.
- Return type:
str
- series_color(index: int) str
Return the colour of the index-th trace of a view.
- Parameters:
index (int) – Zero-based trace index; wraps around the series list.
- Returns:
The hex colour.
- Return type:
str
- state_color(state: str) str
Return the colour marking a run or device state.
- Parameters:
state (str) – State name, e.g.
"running","error","idle".- Returns:
The hex colour; unknown states fall back to the muted text colour.
- Return type:
str
- stylesheet(source: str | pathlib.Path | None = None) str
Return the Qt stylesheet with every
{{token}}substituted.- Parameters:
source (Optional[str | pathlib.Path]) – Path to a custom
.qsstemplate;Noneuses the packagedshell.qss.- Returns:
The rendered stylesheet.
- Return type:
str