Errors#
Every exception Scenet raises, under one root.
scenet.errors#
.. py:module:: scenet.errors
Every exception Scenet raises, in one place.
A library that scatters its exception types across the modules that happen to raise
them forces callers to import from six places to write one except clause. Everything
Scenet can raise is defined here instead, under a single root, so that
except ScenetError:
catches all of it and nothing else.
The hierarchy is three deep and the middle tier answers the question a caller actually has, which is whose fault is it:
ScenetError
|-- SourceError the document is wrong -- report it to whoever wrote the panel
|-- SolverError the document is fine, but no layout satisfies it
`-- AssetError a puppet is missing or malformed
Each also inherits the built-in exception a caller would have reached for before this
module existed – SourceError is a ValueError, UnknownPuppetError is a KeyError
– so pre-existing except ValueError handlers keep working unchanged.
.. py:exception:: AssetError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.ScenetErrorA puppet asset that is missing, unreadable or self-inconsistent.
.. py:exception:: BalloonPlacementError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.SolverErrorNo legal position exists for a balloon.
Every candidate position was rejected: it covered a face, left the panel, overlapped a balloon already placed, or would have broken reading order. Usually this means too much dialogue for the panel size – widen the panel, shorten the line, or split it across two panels.
.. py:exception:: CompositionError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.SourceErrorA
panels:document whoseover:inheritance cannot be resolved.Raised for a panel inheriting from one that does not exist, and for a cycle –
aoverbovera– which has no fixed point to resolve to... admonition:: Example
from scenet import CompositionError, compile_scene try: … compile_scene(“panels: {a: {over: b}, b: {over: a}}”) … except CompositionError as exc: … print(exc) ‘over’ chain is cyclic: a -> b -> a
.. py:exception:: LayoutError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.SolverErrorA panel whose required constraints cannot all be satisfied.
Actor placement runs a Cassowary solver in which non-overlap and declared left-to-right ordering are required constraints. If those genuinely conflict – two actors each required to be left of the other – there is no solution and this is raised. Panel bounds are deliberately not required, so a merely crowded panel lets figures bleed off the edge instead of failing.
.. py:exception:: PanelSyntaxError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.SourceErrorA panel document that could not be parsed or validated.
Carries the source path when one is known, so the message reads
path/to/duel.panel.yaml: invalid panel: ...rather than losing the file it came from... admonition:: Example
from scenet import PanelSyntaxError, compile_source try: … compile_source(“panel: {size: [0, 100]}”) … except PanelSyntaxError as exc: … print(exc) invalid panel: at panel: panel size must be positive
.. py:exception:: ScenetError
- module:
scenet.errors
Bases: :py:class:
ExceptionRoot of every error Scenet raises.
Catch this to handle anything the compiler can go wrong with, without having to enumerate the specific cases or accidentally swallowing unrelated
ValueErrors from elsewhere in your program... admonition:: Example
from scenet import ScenetError, compile_source try: … compile_source(“{panel: {size: [1000, 1000]}, cast: {ghost: {reference: nobody}}}”) … except ScenetError as exc: … print(type(exc).name) UnknownPuppetError
.. seealso::
- exc:
SourceError <scenet.errors.SourceError>, for the “bad document” branch.- exc:
SolverError <scenet.errors.SolverError>, for the “impossible layout” branch.
.. py:exception:: ScriptSyntaxError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.PanelSyntaxErrorA comic script that could not be parsed.
A subclass of :exc:
PanelSyntaxError <scenet.errors.PanelSyntaxError>rather than a sibling, because both frontends produce the same IR and a caller handling “bad input” should not have to care which syntax it was written in.
.. py:exception:: SolverError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.ScenetError, :py:class:ValueErrorA document that is valid but cannot be laid out.
The distinction from :exc:
SourceError <scenet.errors.SourceError>matters: nothing is misspelled and nothing is missing, but the panel as described has no solution – a cast with nowhere left to stand, or a balloon with no legal position. The fix is an editorial change to the panel, not a correction to its syntax.Also a
ValueError.
.. py:exception:: SourceError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.ScenetError, :py:class:ValueErrorA document that could not be understood.
Raised whenever the input is at fault: malformed YAML, an unknown predicate, a reference to a panel that does not exist, a negative panel size. The message names the location and the reason, and is written to be shown directly to whoever wrote the document – no traceback required.
Also a
ValueError, since that is what a malformed value has always been... attribute:: source
Path the document was read from, or
Nonefor a string compiled in memory. Prefixed to the message when present, so a diagnostic never loses the file it came from... py:method:: SourceError.init(message, *, source=None)
- module:
scenet.errors
Build the error, prefixing the source path when there is one.
- type message:
- sphinx_autodoc_typehints_type:
\:py\:class\:\str``
- param message:
What went wrong, phrased for the person who wrote the document.
- type source:
- sphinx_autodoc_typehints_type:
\:py\:class\:\~pathlib.Path` | :py:obj:`None``
- param source:
Path the document came from, if it was read from disk.
.. py:exception:: UnknownPuppetError
- module:
scenet.errors
Bases: :py:class:
~scenet.errors.AssetError, :py:class:KeyErrorA cast member referencing a puppet the library does not contain.
Also a
KeyError, because that is what a lookup miss has always been, and because the library is a mapping in all but name... note::
KeyErrorstringifies asrepr(args[0]), sostr(exc)comes out quoted. Readexc.args[0]for the bare message – which is what the CLI does.