yggdrasil.path.proxy¶
proxy ¶
ProxyPathMixin — be a :class:Path by delegating to an inner one.
A mixin for objects that are a filesystem path conceptually but aren't
constructed like one — their real backing :class:Path is built lazily from
other state (credentials, a fetched URL, a remote handle). Implement the single
abstract :meth:_internal_path hook and the whole :class:Path surface
(ls / read_bytes / write_bytes / stat / exists / parent /
iterdir / / / open / context-manager / iteration / …) is mirrored
straight to that inner path, so every call lands on the inner path's own
(possibly overridden) implementation::
class ExternalLocation(DatabricksResource, ProxyPathMixin, Singleton):
def _internal_path(self) -> Path:
return self._build_credential_backed_s3_path()
el.ls() # → inner_path.ls()
el / "sub/file.txt" # → inner_path / "sub/file.txt" (an inner-typed Path)
el.read_bytes() # → inner_path.read_bytes()
The mixin owns only delegation. Identity (__repr__ / __eq__ /
__hash__) and any domain metadata are left to the consuming class — keep
this mixin before the identity-bearing base in the MRO only for the path
surface, never for identity. Navigation (parent / joinpath / /)
returns inner-typed paths: stepping off the proxy leaves the wrapper behind and
hands back the plain inner :class:Path, which is usually what you want.
Delegation works through :meth:__getattr__ (so every non-dunder attribute the
consuming class doesn't define itself forwards to the inner path) plus explicit
mirrors for the protocol/operator dunders Python resolves on the type and
therefore never routes through __getattr__ (__truediv__, __fspath__,
__iter__, with support, …). A consuming class keeps full control: any
attribute it defines (a url / name / info metadata property) shadows
the delegated one, so domain state stays on the wrapper while I/O flows through.
ProxyPathMixin ¶
Bases: ABC
Mirror the full :class:Path surface onto an inner path.
Implement :meth:_internal_path; everything else delegates. The
inner path is resolved on every access (the implementation is free
to cache it) so a refreshed / rebuilt inner path is picked up
transparently.