On this page

Cleanable๏ƒ

Use md.Cleanable from the public package namespace.

Implementation source

class Cleanable[source]๏ƒ
Purpose:

Abstract base class for objects that own an explicit cleanup lifecycle. This is the single teardown contract shared across the entire runtime.

Responsibilities:

  • Own the canonical _cleaned lifecycle flag.

  • Provide check_cleaned() as the one guard for rejecting use-after-clean.

  • Provide using_cleanup() as a context manager that guarantees exactly one cleanup call on exit.

  • Require subclasses to implement deterministic teardown.

Contract:

  • cleanup() must be idempotent.

  • Subclasses must set _cleaned = True when cleanup completes.

  • check_cleaned() is the canonical guard for rejecting use-after-clean.

  • using_cleanup() provides a separate helper context that guarantees one cleanup call on exit.

  • Every Cleanable starts live: _cleaned is False after __init__.

Owned State:

  • _cleaned: the live/cleaned flag. The only state this base owns.

Threading:

The base itself holds no lock; _cleaned is a plain bool. Subclasses that can race cleanup against active work are responsible for their own lock, and the established pattern is to check _cleaned, acquire, then re-check inside the lock. On free-threaded builds that double-check is not optional.

Lifecycle / Cleanup:

Live on construction, cleaned exactly once. The repository teardown order for subclasses is: clean children, delete owned field references, then clean the logger last. Post-cleanup, an object is assumed unused; prefer letting check_cleaned() raise over silently returning.

Registration:

Your subclasses bind normally: manifest lookup is an EXACT (module, qualname) match and does not inherit. A regression asserting that a user subclass of Cleanable still binds guards that property.

Subsystem Context:

One of three utilities/general_base/ base classes, alongside Sync (synchronization base) and AbstractElasticPool (pooling base). This is the most widely inherited type in the codebase: the crystals, the conduit runtime, the spellbook registries, the Nexus/Rift surfaces, and most utilities all descend from it. It hands off to nothing - it is the floor.

System Context:

Beneath every layer of the DGR and outside the boot order entirely. Cleanup ordering across the runtime (Conduit tears down Meld, Ward, then Creations; Aether cleans frames then resets singleton state) is expressed through this one contract, which is why its idempotence guarantee is load-bearing for the whole system rather than a local convenience.

AGENT_ACCESS: public

AGENT_PURPOSE:

access: public. Base cleanup contract. Subclass this when your object owns resources that need deterministic teardown; implement cleanup() idempotently and guard live-only methods with check_cleaned(). Your subclasses stay bindable.

property cleaned: bool๏ƒ

Return whether the object has already been cleaned.

Contract:

  • MONOTONIC latch: reads the _cleaned flag, which only ever moves False -> True. Once this returns True it never returns False again for the object's life.

Returns:

True when _cleaned has been set.

Return type:

bool

property is_cleaned: bool๏ƒ

Alias for cleaned.

Contract:

  • Exact alias: reads the same _cleaned flag as cleaned, with the same monotonic semantics. Both spellings exist because call sites across the runtime use both.

Returns:

Current cleaned-state flag.

Return type:

bool

check_cleaned() → None[source]๏ƒ

Raise when the object has already been cleaned.

Contract:

  • Subclasses use this as the standard use-after-clean guard.

  • No-op while the object is still live.

Raises:

RuntimeError -- If the object has already been cleaned.

Returns:

None.

abstractmethod cleanup() → None[source]๏ƒ

Release owned resources and mark the object cleaned.

Subclass contract:

  • Release all resources.

  • Deregister or finalize any allocations.

  • Be idempotent (safe to call multiple times).

  • Set _cleaned = True when teardown completes.

Raises:

NotImplementedError -- Always on the base; every concrete subclass overrides it.

Returns:

None.

async async_cleanup() → None[source]๏ƒ

Async cleanup hook for subclasses that support asynchronous teardown.

Subclass contract:

  • Release all resources.

  • Deregister or finalize any allocations.

  • Be idempotent (safe to call multiple times).

  • Preserve the same lifecycle semantics as cleanup() once async teardown completes.

Raises:

NotImplementedError -- Always on the base; subclasses that support async teardown override it.

Returns:

None.

using_cleanup() → _CleanupContext[source]๏ƒ

Return a helper context manager that guarantees cleanup() on exit.

Contract:

  • Independent of any context-manager behavior implemented by the owner.

  • Intended for callers that want deterministic cleanup without relying on the object's own __enter__ / __exit__.

  • Cleanup runs at most once on exit and its errors propagate; the block's own exception is never suppressed.

Returns:

Helper context manager bound to this object.

Return type:

Cleanable._CleanupContext

async_using_cleanup() → _AsyncCleanupContext[source]๏ƒ

Return an async context manager that awaits async_cleanup() on exit.

This method itself is NOT async. It returns an object implementing __aenter__ / __aexit__, which is what async with requires.

Contract:

  • Independent of any context-manager behavior implemented by the owner.

  • Mirrors using_cleanup() exactly, but drives the async teardown hook.

Returns:

Async helper context manager bound to this object.

Return type:

Cleanable._AsyncCleanupContext

Topic reference ยท Full contents