Conversation
| def cleanup(callback: Callable[[], Any]) -> None: | ||
| try: | ||
| callback() | ||
| except BaseException as error: |
| def _cleanup_after_failure(self) -> None: | ||
| try: | ||
| self.close() | ||
| except BaseException: |
| def release(callback: Callable[[], Any]) -> None: | ||
| try: | ||
| callback() | ||
| except BaseException as error: |
| for packet in self._stream.encode(): | ||
| self._container.mux(packet) | ||
| except Exception as error: | ||
| except BaseException as error: |
| try: | ||
| self._container.close() | ||
| except Exception as error: | ||
| except BaseException as error: |
| try: | ||
| self._container.close() | ||
| except Exception as error: | ||
| except BaseException as error: |
| try: | ||
| self.target.unlink(missing_ok=True) | ||
| except Exception as error: | ||
| except BaseException as error: |
nikolajmunk
left a comment
There was a problem hiding this comment.
Looks pretty good! I've added a bunch of suggestions for increased clarity in the docs. I suspect that once all these PRs are merged it would be a good idea to rewrite the entire deep dive section, but hopefully this helps for now.
|
Question: I also note that there are quite a few catches of For the record, I have no idea if there are better ways of going about it. It's entirely possible that |
| @@ -304,6 +303,18 @@ frames or using media and cache resources. In contrast, ``format = none`` only | |||
| suppresses the primary artifact; an OpenGL live preview with automatic output | |||
| still rasterizes and displays frames without writing a file. Both requests have | |||
| an effective output format of ``none``, so the session's ``dry_run`` field | |||
There was a problem hiding this comment.
Oops, I must have selected the wrong range of lines last time. Let's remove this part.
Keep control-flow exceptions unwrapped during open and encode. Preserve the first failure when finish or abort cleanup also fails, retaining contextual wrapping for ordinary exceptions.
Add acceptance probes for allocation-free construction and lifecycle-wide cleanup. Nine strict xfails explicitly mark unfinished 3B1 boundaries; no Manager behavior changes in this commit.
Extend Manager's existing failure cleanup to setup, teardown, finalization, preview opening, and failed rerun handling. Preserve the primary exception if abort itself fails, without changing construction-control-flow handling or timed execution.
Keep resolved raster settings separate from optional target storage. Preserve initial readback, close guards, and snapshot isolation without changing settings resolution or animation scheduling.
Release acquired standalone attachments before their context, or close the owning window for a borrowed context. Preserve the primary exception while attempting every cleanup, and publish renderer state only after configuration succeeds.
Cover failures during parent context setup and later window configuration, preserving the constructor exception if close also fails. Exercise actual native windows with deterministic event delegates and cleanup even when a regression fails the test.
Explicit image or output requests may already attach a Manager before the CLI invokes a scene. Preserve that owner instead of trying to attach a second one, while retaining custom render overrides.
Construct the writer on explicit output demand or before setup, not during Scene construction. Keep renderer access as a single-owner compatibility view, preserve constructor-resolved settings and direct-play output, and never create a writer while cleaning up failed preflight or creation.
Capture concrete sizing and placement inputs once, and allow the opener to consume supplied immutable settings without rereading global configuration. Keep normal construction-time resolution and existing placement/HiDPI behavior; defer the later Manager opening cutover.
Keep Scene construction free of contexts/windows, open before setup or explicit GPU demand, and use a temporary headless host for cold snapshots. Retire owned targets, textures and cached programs on the owning thread, preserve legacy scene rebinding, and allow failed host cleanup to be retried.
Remove constructor-time log files, close the exact owned handler at render end, and retire backend resources on propagated failures or explicit Manager scope exit. Preserve primary failures, allow cleanup retries, protect newer backend bindings, and drain a replaced writer before transferring ownership.
Use fresh Scene-owned rendering state for each CLI scene or rerun. Remove backend rebinding and writer replacement, and abort failed direct plays without relying on an outer render scope. Consolidate lifecycle tests around fixed ownership and actual resource boundaries.
Co-authored-by: nikolajmunk <28557236+nikolajmunk@users.noreply.github.com>
c3f055a to
7d4d2bb
Compare
Overview: What does this pull request change?
Stacked on #4989.
This PR makes
Managerresponsible for creating a scene's file writer and closing its rendering resources. Cairo and OpenGL follow the same cleanup rules for successful renders, failures, and CLI reruns.setup()during rendering. Image inspection does not create a writer.play()calls also clean up, even outsiderender().Motivation and Explanation: Why and how do your changes improve the library?
An exception after encoding started could leave a worker waiting for more frames and prevent Python from exiting. Resource creation and cleanup were also spread across scene construction, renderers, and the CLI. Bringing cleanup together makes failures safer and allows scene construction and image inspection without opening unnecessary output resources.
Changes for callers
A renderer is used for one scene.
Scene.rendererandrenderer.file_writerare read-only; create a new renderer for another scene, and choose a custom writer through the renderer'sfile_writer_classconstructor argument. Successive plays within a scene reuse the same renderer and writer.Successful rendering normally closes the renderer before returning. To inspect its last-rendered frame, keep it open with an explicit manager context:
For a fresh image of the current mobjects,
scene.get_image()remains available after rendering. Raw OpenGL meshes require their original live context and must be inspected on its rendering thread.Output and window settings are still saved during scene construction. Moving animation scheduling and the clock into
Manageris left for the next PR; this branch does not add no-raster evaluation or timeline export.Links to added or changed documentation pages
docs/source/guides/deep_dive.rst.Manager, renderer, andScene.rendererAPI docstrings.