Changelog¶
What changed in each release, grouped as in
Keep a Changelog. This project follows
Semantic Versioning, and dates are
written DD-MM-YYYY.
Each entry links the pull request that made it. A change that breaks existing code is listed under Breaking, and a migration guide such as How to migrate from 0.13 shows how to move code across it. Releases up to 0.13.2 are in the previous changelog.
0.16.0 - 31-10-2026¶
Breaking¶
redsun.session.BUILD_STEPSis removed. Code reading it iteratesBuildStep, which lists the same steps in order. (#214)- A view whose class answers
placementfrom a property, and whose declaration gives none, is refused and left out; setplacementas a class attribute or give it in the declaration. (#214) redsun.presenter.PositionerPresentergroups axes by the device holding them directly. A device whose axes sit below one of its children, such asstage.motors.x, shows them in the box of that child,stage-motors, so positions saved understageno longer match andinclude: [stage]keeps no box. (#219)redsun.utils.devices.find_axesandwalk_axesare removed. Code using them walks the device withwalk_devicesofophyd-asyncand keeps eachAxisthat is not a signal. (#219)- A device declared with
service=whoseprefixargument defaults toNoneis built without a prefix when its service does not start, where it was skipped before. (#221) - A session with
strictset stops when any service does not start, whether or not a device names it. (#221) - A keyboard shortcut declared with
redsun.shortcutruns its method once per press, however long the key is held, unless it is givenrepeat=True. (#223) redsun.testing.keep_application_as_found, and the setting that gives Qt'soffscreenplatform the system fonts on Windows, move toredsun.testing.qt. A suite testing Qt components installs thetesting-qtextra and loads-p redsun.testing.qtas well as-p redsun.testing. (#233)redsun.presenter.AcquisitionPresenter.sig_plan_doneno longer reports a plan stopped withstop, whichsig_plan_stoppedreports instead. A session file writing out the links of the acquisition stack underwiringaddsacquisition.sig_plan_stopped: acquisition_view.set_stopped. (#235)PlanProgress.watchtakes aWatcherofophyd-async, and a fraction reported alone reaches watchers withcurrent,initialandtargetleftNone. A followed status that reports no unit givesunitasNoneinstead of"unit".redsun.engine.ProgressStateis removed.RunEngine.sig_progresscarries the openPlanProgressscopes, whoseupdateholds the lastWatcherUpdateofophyd-async.
Added¶
redsun.Session.buildwarns when components ask for two protocols with the same members, which the same components satisfy. (#218)redsun.utils.devices.DevicePath,device_pathandheld_bygive where a device sits in its tree, such asmicroscope / xy.x, and whether a plan holds it or a device above it.AxisInfo.path,LightInfo.path,Configuration.pathsandParamDescription.labelscarry those paths to views, which title boxes, rows and device choices with them. (#219)redsun.Declare(services={...})and theserviceskey of a device's entry give each constructor keyword the prefix of the service it names. A keyword whose service does not start is left out when its default isNone, and the device is built without that piece. (#221)redsun.shortcuttakesrepeat=Trueto run its method again at the keyboard's repeat rate while the key is held, andredsun.Shortcut.repeatrecords it. (#223)redsun.Frontend.view_coroutinessays whether a key can run a view's coroutine method. It is false by default and in the Qt frontend, which leave such a key out and log it. (#226)redsun.shortcuttakes a coroutine method. A presenter's runs on the session's loop without blocking the key press, a press while it still runs is ignored, what it raises is logged, and it is cancelled when the session shuts down, which waits up to 5 seconds for it to stop. (#226)redsun.qt.styles.qlementine.QlementineStyletakesdarkandlight, paths toqlementinetheme files used in place of its built-in themes, andanimations=Falseto turn its animations off. A key a theme file gives thatqlementinedoes not know, or a value of the wrong kind, is logged. (#227)redsun.services.sharedbox.BoxTransportserves afastcscontroller as one box per controller and an index box describing them, and answers each write with the service's error when the put fails. (#232)redsun.services.serve_controllerruns afastcscontroller as a launched service over the transport it is given, under the session's prefix, and reports the service ready once the transport can be reached. (#232)redsun.device.sharedbox.BoxDeviceConnectorfills anophyd-asyncdevice from the index of asharedboxservice, withBoxSignalBackendandBoxCommandBackendbehind its signals and commands. A refused write or a failed command raisesredsun.device.sharedbox.BoxPutError, andredsun.device.sharedbox.stream_namenames a stream the service makes itself. (#232)
class MyDetector(Device):
exposure: SignalRW[float]
def __init__(self, prefix: str, name: str = "") -> None:
super().__init__(name=name, connector=BoxDeviceConnector(prefix))
sharedbox is a new value of services.transport: a session reaches its services through sharedbox boxes in shared memory on the same computer, with no network server. The sharedbox extra installs sharedbox and fastcs for it. (#232)
- redsun.testing.qt is a pytest plugin for testing Qt components, installed with the testing-qt extra. It defines a qapp fixture. emit_queued_on_main_thread delivers on the main thread the psygnal emissions queued from other threads, whichever plugin supplies qapp. release_slots_after_module releases the slots of the widgets freed after each test module, which pyqt6 otherwise holds until the process exits. application_state returns the stylesheet, style, font and hand-set palette that keep_application_as_found compares. (#233)
- redsun.presenter.AcquisitionPresenter.sig_plan_stopped reports a plan stopped with stop, and redsun.view.qt.builtins.AcquisitionView.set_stopped shows the plan stopped until it runs again. (#235)
- redsun.path_provider.SessionPathProvider.set_label leads the file names of every later plan with a label, as <label>_<plan>_<counter>. redsun.view.qt.builtins.AcquisitionView has a field for the label, which reaches the provider through the new redsun.presenter.AcquisitionPresenter.set_label. (#236)
- redsun.device.sharedbox.BoxDeviceConnector takes declared_only=True to fill a device with only the signals, commands and children it declares, so several devices can share one service. (#238)
class MyCamera(Device):
exposure: SignalRW[float]
def __init__(self, prefix: str, name: str = "") -> None:
super().__init__(
name=name, connector=BoxDeviceConnector(prefix, declared_only=True)
)
redsun.AsStack and a stacks section in a session file and a plugin manifest declare a presenter and its views as one stack, which the session builds as <stack> and <stack>_<role> and pairs. redsun.view.qt.builtins ships AcquisitionStack, PositionerStack and LightStack, listed in redsun's manifest as acquisition, positioner and lights. (#239)
class MyStack:
presenter: AsPresenter[MyController]
view: AsView[MyView]
class MyApp(QtSession):
my_ctrl: AsStack[MyStack]
acquisition: AsStack[AcquisitionStack]
PlanProgress is generic over the type of the values it reports, and PlanProgress.update returns its last update. monitor_progress returns a PlanProgress[T] for a WatchableAsyncStatus[T].
Changed¶
- The built-in positioner, light stack and Configuration tabs treat a device a plan locks as locking every device below it, and none above it. (#219)
redsun.DeviceMappingandredsun.DevicesOfhold every device of each declared tree, signals and commands left out, under the namesophyd-asyncgives them, such asmicroscope-xy-x.DevicesOfchecks each device against its protocol on its own. Two devices with one name, or a device with no name, stop the build with aBuildError. (#219)- The build summary lists the devices built without a piece, under
Built without, and the services that did not start, underServices not started. (#221) redsun.qt.QtSessioncounts the hook providers it skipped in the failures button of its status bar, which reads2 failed, and lists each with the hook points it served. (#224)redsun.testing.qt.keep_application_as_foundalso fails a test that leaves a palette set by hand on the application, and puts the palette back. (#225)redsun.Session.shutdowncancels a component's asyncshutdownstill running after 5 seconds, logs it, and goes on with the rest. (#226)redsunrequiresannotated-types>=0.8.0,platformdirs>=4.13.5andpydantic>=2.14.1. Its Qt extras requiresuperqt>=0.9.0, and itstiledextra requirestiled>=0.2.20. (#229)redsun'stiledextra installstiledandome-tiledon Python 3.14, and requiresome-tiled>=0.2.1. (#230)redsun.testing.buildfails a test with an error at teardown when a session it built is still alive once the test is over. A test that raised is not checked. (#234)
Removed¶
redsun.session.BUILD_STEPS; useBuildStep. (#214)- Reading a view's
placementfrom a property of the built view. (#214) redsun.utils.devices.find_axesandredsun.utils.devices.walk_axes. (#219)
Fixed¶
- A
redsun.injection.providesmember annotatedX | Noneshares its value asX. The session now refuses a second component sharingX, and no longer logs the value as one no component asks for. (#217) redsun.DevicesOf[Axis]holds the axes built onophyd-async'sStandardMovable, whosesetnames its parameternew_position.redsun.utils.devices.Axis.settakes its value by position only. (#220)redsun.Declare(services={...})refuses to mapnameorpath_provider, which the session gives the device itself, when the configuration is read, instead of skipping the device at build. (#222)- Window -> Keyboard shortcuts opens no editor in the second key cell of a command with no key. (#223)
- Window -> Keyboard shortcuts clears the message refusing a key at the next key pressed in a cell and at Reset to defaults. (#223)
redsun.Session.resolve_shortcutslogs each conflict between keys the first time it settles it, not at every call. (#223)- Escape pressed in a key cell of Window -> Keyboard shortcuts leaves the key as it was, instead of binding Escape. (#223)
redsun.ConfigurationErrorlocates a problem in a hook entry that a session file lists at a hook point by its index, such ashooks.configure_application[1].kwargs. (#224)- The step box of
redsun.view.qt.builtins.PositionerGrouptakes its width from the style, so the step still shows beside a wider arrow, such as theqlementinestyle's. (#225) - A task still pending on the shared event loop of
redsun.aio, such as one started withredsun.aio.run_coro, is cancelled when the process exits, and the loop is then stopped and closed. (#232) redsun.qt.QtSession.shutdowndeletes the actions of the session's menus and releases the slots connected to its widgets, underpyqt6too, so neither keeps the session and what it built alive until the process exits. (#232)redsun.log.BufferHandlerretains each record with its message and traceback as text, and no longer keeps alive the arguments and the exception the record was logged with. (#234)redsun.services.sharedbox.BoxTransportbuilds its controller boxes withsharedbox0.8.0, and thesharedboxextra requiressharedbox0.8.0 or later. (#240)redsun.Session.shutdownforgets the build when a component'sshutdownraises, after running every other release, and then raises that error. (#242)redsun.qt.QtSession.rundelivers the signals queued for the GUI thread every 16 ms, so an idle window leaves the processor idle. (#242)redsun.view.qt.builtins.AcquisitionViewsends the label in its field when a plan is launched, so a run started while the field still has focus takes the label typed. (#242)redsun.services.serve_controllerkeeps the watchdog that logs every thread's stack when stopping takes over 10 seconds, also when the service is stopped before it is ready. (#242)redsun.path_provider.SessionPathProviderresumes the counter of a labelled plan past its files on disk when the label holds a dot, such ascell1.5. (#242)- A waveform signal of
redsun.device.sharedbox.BoxDeviceConnector, and a waveform attribute served byredsun.services.sharedbox.BoxTransport, raiseValueErrorfor a value with another number of dimensions than the waveform, or longer than it. (#242) - The
scan_id_sourceparameter ofredsun.engine.RunEngineis annotated withoutNone, which failed at the first run.
0.15.0 - 23-10-2026¶
Breaking¶
- A view whose constructor takes a
placementkeyword is refused, a view declaration reservingplacementfor the session; rename the keyword. (#172) - The
pysideextra installspyside6-essentialsinstead of the wholepyside6, so the PySide6 add-on modules (QtCharts, QtMultimedia, QtSerialPort, QtWebEngine and others) are no longer installed with it; a project using one addspyside6to its own dependencies. A uv-managed environment that hadpyside6loses filespyside6-essentialsshares whenuv syncremoves it, and then finds no Qt binding: repair it withuv sync --reinstall-package pyside6-essentials, orpip install --force-reinstall --no-deps pyside6-essentials. (#188) - A test run with
redsun.testingfails a test that leaves automatic garbage collection on (keep_automatic_collection_off); a test ending in an unconditionalgc.enable()restores the state it found instead. (#191) Session.hooksmaps every hook point the session calls to a tuple of providers, in the order they run, in place of one provider per installed point. Code reading one provider, such as a frontend calling its own hook point, becomes(provider,) = session.hooks[point];session.hooks.get(point)now returns a tuple, so a check of its type against the point's protocol no longer matches. (#193)ColorSchemeMode.glyphis removed. Code that showed a mode as text uses the mode itself, which is the textsystem,lightordark. (#194)
Added¶
- Add
profile="start"orprofile="run", withprofile_dir=, toSession,redsun.qt.QtSessionandSession.from_config, which write apyinstrumenttimeline of the session's start or run as an HTML file beside its logs. (#156) - Add the
profileextra, withpyinstrumentandpy-spy. (#156) - Add
timeout=toredsun.aio.run_coro, which cancels the coroutine when the wait ends without a result. (#161) - Add
redsun.utils.devices, withAxis,AxisInfo,Configuration,limits,walk_axes,find_axes,describe_axisandread_configuration. (#162) - Add
redsun.view.qt.treeview.DescriptorTreeView.set_enabled. (#162) - Add
redsun.presenter.PositionerPresenter,redsun.presenter.DescribesAxes,redsun.view.qt.builtins.PositionerViewandredsun.view.qt.builtins.PositionerGroup, registered as thepositionerpresenter and view, which move the axes of any device by hand: steps, a go-to field per axis, Stop, saved positions and a Configuration tab. (#162) - Add
redsun.aio.cancel_task, which cancels a task from any thread and leaves alone a task that has finished its work. (#163) - Add
Readback,readbackandConfiguration.ownerstoredsun.utils.devices, and anownerskeyword toredsun.view.qt.treeview.DescriptorTreeView. (#164) - Add
redsun.presenter.DeviceConfigurationandredsun.view.qt.treeview.ConfigurationTab, which read, follow and edit a device's configuration. (#164) - Add
redsun.presenter.LightPresenter,redsun.presenter.DescribesLights,redsun.view.qt.builtins.LightViewandredsun.view.qt.builtins.LightGroup, registered as thelightspresenter and view, which switch lights on and off and set their intensity. (#164) - Add the
LightandDimmableLightprotocols toredsun.utils.devices, a device whoseenabledis a boolean signal it can write, with an optional numericintensity, andLightInfo,describe_light,dimmableandis_lightbeside them. (#164) - Add the
HasActionsprotocol. (#165) - Add
redsun.engine.RunEngine.cancel_pause, which withdraws a deferred pause no checkpoint has reached. (#165) - Add
redsun.presenter.AcquisitionPresenter,redsun.presenter.DescribesPlansandredsun.view.qt.builtins.AcquisitionView, registered as theacquisitionpresenter and view, which run the plans the session's components offer and share the presenter'sRunEngineandDeferralswith any component that asks for them. (#165) - Add
redsun.presenter.utils.device_class. (#165) - Add a
pairs:section to the session file, where[a, b]connects every link between two components, in both directions. (#168) - Add
links_between, inredsun.portsandredsun, which yields the links between two components for awiremethod. (#168) - Add
signal=toslot, naming the signals of another component that reach the slot in a pairing. (#168) - Add plan widget inputs for mappings, sets, fixed-length tuples, optional values and unions, nested to any depth. (#169)
- Add a
placementkey to a view's declaration and its session file entry; Qt readsleft,right,top,bottom,central,{dock: <edge>, group: <name>},{menu: <name>}and{toolbar: <name>}. (#172) - Add
group=toredsun.qt.Dock, which tabs the docks of one edge and group together. (#172) - Add checks of plan parameter values against their
annotated-typeslimits, at any level: a plan whose default breaks its limits is refused, so is a launch with a value outside them, and the plan widget's inputs keep to the limits. (#173) - Add a Window menu to the Qt window,
redsun.qt.WINDOW_MENU, with a toggle for each dock and Reset layout. (#178) - Add
Session.resolve_layout(), andFrontend.regions,Frontend.hides,Frontend.region_ofandFrontend.layout_problems. (#179) - Add
WindowLayout,Row,ColumnandTabs, declared throughSession.window_layout()or alayout:section of the session file, to set a window's first layout: what fills each region, shares of the window, and docks that start hidden. (#179) - Add
redsun.qt.QtSession.show(), whichruncalls, andlayout=toredsun.qt.attach; the Qt session saves the centre's splitters and tabs aswindow.center. (#179) - Add
redsun.session.BuildStep, the steps a build reports, in order. (#180) - Add a
shortcuts:section to the session file, giving a command named<component>.<method>, or a session file action, other keys or none; a key two commands ask for in one place stays with the first declared, andstrictstops the build instead. (#184) - Add Window -> Keyboard shortcuts to the Qt window, listing every bound key by view, and
Frontend.key_problemsandFrontend.canonical_key. (#184) - Add
redsun.shortcut, a decorator marking a presenter or view method that a key runs, in the whole window or withscope="view"only while the component's view has focus. (#184) - Add
AcquisitionView.run_planonCtrl+RandAcquisitionView.stop_planonCtrl+.. (#185) - Add
PositionerView.step_downandPositionerView.step_upon Left and Right, acting on the focused axis, andPositionerGroup.focused_axisandPositionerGroup.step. (#185) - Add
when=toredsun.shortcut: the key acts only while a function of the component returns true, and otherwise goes to the focused widget. (#185) - Window -> Keyboard shortcuts edits keys: double-click a key cell and press the new key, Backspace or Delete to clear it; a key another command holds moves after the user agrees; Reset to defaults forgets the changes. (#186)
- Add
Session.set_shortcutsandSession.reset_shortcuts, keeping the user's keys in the session's settings and applying them over the session file'sshortcuts:section; a saved key wins over a component's default. (#186) - Add
redsun.qt.QtSession.garbage_interval, the milliseconds between two checks of Python's garbage while a Qt session runs, 100 by default. (#187) - Add
redsun.qt.styles.napari.NapariStyle, aconfigure_applicationhook provider giving the window the stylesheet and icons ofnapari0.9.2, dark or light as the colour scheme reads, and switching with it; a session file installs it asconfigure_application: napari. (#190) - Add short names for the hook providers
redsunships: ahooksentry in a session file names one alone (configure_application: napari) or asprovider: napari, andredsun's manifest lists them under a newhookskey. (#190) - Add
redsun.Many: a hook point declared with it takes several providers, run in order, the class's first and then the session file's;configure_application,configure_main_viewandduring_buildofredsun.qt.QtSessiontake several, and a hook point in a session file holds one entry or a list. (#193) - Add
Session.call_hooksandSession.skip_hook, for a frontend calling its hook points. (#193) - Add
redsun.testing.keep_application_as_found, failing a test usingqappthat leaves the application's stylesheet, style or font changed. (#193) - Add
font_sizetoredsun.qt.styles.napari.NapariStyle, the base size of its stylesheet in points. (#193) - Add the
redsuncommand, installed with the package:redsun --exampleopens a session holding every built-in component over simulated devices, andredsun --example napariopens it in thenaparistyle.redsun.examples.ExampleAppis that session. (#195) - Add
redsun.qt.styles.qlementine.QlementineStyle, aconfigure_applicationhook provider giving a Qt sessionqlementine's look, in its dark or light theme as the colour scheme reads; a session file names itqlementine, andredsun --example qlementineshows it. Theqlementine-pyqtandqlementine-pysideextras install the package it needs. (#196) - Add
redsun.view.qt.icons:set_icon,set_item_icon,collapsible_sectionandset_collapsible_iconsput the icons of the built-in views on a view of your own, following its palette through a change of colour scheme. (#197) - Add
redsun.view.qt.builtins.LogWindowAction, a Logs entry in the View menu that opens the log view in a window of its own, offered by theredsunplugin aslog-window. (#211)
Changed¶
redsun.aio.run_cororefuses to block on the shared loop's own thread, and accepts any awaitable, not only a coroutine. (#161)- The Qt extras install
superqt. (#162) - A
create_applicationhook that returns anything but aQApplicationis refused with aHookErrornaming its provider. (#167) - The
config_homefixture ofredsun.testingapplies to every test, undertmp_path / "config". (#167) - A plan parameter no input can show is hidden and given its default, and Run stays disabled while an input is invalid, with the reason shown. (#169)
- A number input with no limit takes any value, not only 0 to 999. (#173)
- A saved dock layout is skipped, with a log line saying why, once a view's placement changes; the settings file records the placements as
window.layout. (#178) - The positioner's Left and Right are keyboard shortcuts, listed under Window -> Keyboard shortcuts and changed in the session file's
shortcuts:section. (#185) - The
pysideextra accepts PySide6 from 6.10.2, and both Qt extras skip Qt 6.11.0 and 6.11.1, which resize dock widgets wrongly. (#188) - The plan, positioner and light buttons of the built-in views and the colour scheme control show icons from the Material Design icon font in place of text, coloured from the palette so they follow light and dark, with their words in the tooltip and the accessible name; the log view's level selector shows an icon beside each level.
fonticon-materialdesignicons7is a new dependency of the Qt extras. (#189) redsun.testingturns Python's automatic garbage collection off for the whole test run (no_automatic_collection) and collects after each test module on the main thread (collect_after_module); a test that needs an object in a reference cycle freed callsgc.collect()itself. (#191)- A hook provider that cannot be built, or whose hook raises, is logged, skipped and listed in the build summary; a failed
create_applicationprovider still stops the build, andstrictstops it on any. (#193) - A plugin manifest with a
hookssection is left out: onlyredsunships short hook names. (#193) Sessionlogs a shared value no component asks for at debug level, not as a warning. (#210)
Deprecated¶
- A view class answering
placementfrom a property, removed in 0.16; giveplacementin the declaration instead. (#172) redsun.session.BUILD_STEPS, removed in 0.16; useBuildStep. (#180)
Removed¶
- The log lines naming the docks a saved layout kept away from their placements. (#178)
ColorSchemeMode.glyph, the character that stood for a mode in plain text. (#194)
Fixed¶
Settingsrefuses a value it cannot store as JSON, and keeps its other values. (#158)- An edit in
redsun.view.qt.treeview.DescriptorTreeViewto a setting that belongs to no device no longer raises. (#158) - A cancelled deferred change is dropped, and the changes queued after it are still applied. (#158)
- A session can be built again after
shutdown. (#158) - A malformed
providersentry in a session file is refused, and one naming no plugin is logged. (#158) - A failed write of
Settingskeeps the previous settings. (#162) - A component that subclasses a dataclass from another module no longer fails to resolve its fields' annotations. (#162)
- Closing a session that launched services no longer prints a Channel Access circuit disconnect. (#162)
- A plan parameter annotated with a protocol given type arguments, such as
Readable[Any], is matched to devices. (#165) - The
buildfixture ofredsun.testingshuts down every session it made when one refuses, raising every error together. (#167) redsun.view.qt.builtins.LogViewredraws in the colours of the palette just applied, its console included. (#167)- A link that
wireandwiring:both name is made once. (#168) - The plan widget keeps list, tuple and
Nonedefaults, and readsAnnotatedmetadata at every level without refusing the plan. (#169) - On POSIX, a service blocked in a system call stops at once when the session asks it to stop. (#171)
- A settings file whose saved layout cannot be read is logged, and the docks start from their placements. (#179)
- Locking a positioner device keeps the focus on its own row, so a held arrow key no longer steps another device. (#185)
Session.shutdownreturns once the background dispatch of coroutine slots has stopped and cancelled its pending callbacks, so nothing it logs or runs comes after it returns. (#187)- A Qt session runs Python's automatic garbage collection on the GUI thread only, so a widget freed by an automatic collection on a background thread no longer aborts a
pyside6application. (#187) - The positioner view's Saved positions header redraws its arrow when the colour scheme changes, so the arrow stays visible after switching between light and dark. (#190)
redsun.view.qt.builtins.LogViewdrops the redraw a palette change asked for when the view is deleted first. Underpyside6that redraw ran on the deleted view and raised an error. (#195)- The positioner view's Saved positions section is built without Qt's
QPainterwarnings under a font sized in pixels, which theqlementinestyle sets. (#197) collect_arguments(redsun.presenter.plan_spec) gives a positional parameter with no value its default when a later positional argument is given, and raisesValueErrorwhen it has no default. A plan launched with only some of its values had every later positional value one place to the left. (#202)QtSession.showgrows the window on its first show to the size its views ask for once the style has reached them, so a dock no longer opens narrower than its content. (#210)
0.14.3 - 01-10-2026¶
Added¶
- Add service process functions, args mapping and Attach address (#153)
0.14.2 - 30-09-2026¶
Added¶
- Show plan progress, following device statuses (#151)
Fixed¶
- Name the accepted transports, accept pytest 8 in the testing extra (#149)
- Log the configuration sources and hook points one per line (#150)
0.14.1 - 30-09-2026¶
Added¶
- Add
redsun.testing, fixtures for testing a plugin (#147)
Fixed¶
- List a service again once its address list is cleared (#145)
0.14.0 - 29-09-2026¶
Changed¶
- Breaking: Replace the container layer with sessions (#85)