yggdrasil.environ.userinfo¶
userinfo ¶
UserInfo ¶
UserInfo(
hostname: str = "",
*,
_key: Any = ...,
_email: Any = ...,
_first_name: Any = ...,
_last_name: Any = ...,
_product: Any = ...,
_product_version: Any = ...,
singleton_ttl: Any = ...
)
Bases: Singleton
Snapshot of the user identity for the current process.
hostname is populated eagerly (socket.gethostname() is
cheap and answers reliably without I/O fan-out). Every other
identity field is a lazy, memoized property:
key/emailconsult the Databricks notebook context (free, in-process) and AWS-managed env vars before shelling out towhoami/whoami /UPNor calling the Databricks IAM SDK.first_name/last_nameare derived fromemail— free once email has been resolved, but pulling them eagerly forces email resolution.product/product_versionwalk parent directories looking forpyproject.toml/setup.pyand parse TOML.cwd/url/git_urlprobe the runtime, dbutils context, and the on-disk.gittree.
All of those firing at construction would tax callers that only
care about a subset (typical of request/response sanitization on
the hot path). Each cache fires at most once per instance, and
once a value is resolved — or supplied via :meth:from_struct_dict
or constructor kwargs — it persists for the life of the instance.
:class:Singleton integration:
- The constructor caches one instance per
(cls, hostname, key, email, first/last name, product, product version). TwoUserInfo.current()calls collapse to the same instance; :meth:with_email/ :meth:from_struct_dictproduce different identities and live as separate instances under the same hostname. - Per-process derived caches (
_cwd_cache/_url_cache/_git_url_cache) are listed in :attr:_TRANSIENT_STATE_ATTRSso cross-process pickle drops them; the receiver re-derives from its own context.
Construction:
- :meth:
currentreturns the singleton for the local hostname. - :meth:
from_struct_dictrebuilds an instance from a wire payload, with every supplied field pre-populated so no resolution fires on the receiver. - The constructor accepts the underscore-prefixed cache fields
directly — useful for tests and for :meth:
with_email.
url
property
¶
Compute URL (Databricks link or local:// for the cwd) lazily.
Result is memoized per instance — the resolution probes the Databricks runtime / dbutils context and does a path normalization, neither of which should fire repeatedly on the request hot path.
git_url
property
¶
Compute the git remote URL lazily (walks parents of cwd).
Memoized — the walk hits the filesystem (HEAD, packed-refs,
config) and UserInfo.git_url is read once per request in
sanitization paths.
to_struct_dict ¶
Flatten into the dict shape that matches :data:USERINFO_STRUCT.
cwd / url / git_url are intentionally excluded —
they're per-process derived values, not part of the wire
contract; the receiver re-derives them from its own context.
Reading the lazy properties here forces resolution and pins
the result on the cache slots so subsequent reads are free.
from_struct_dict
classmethod
¶
Inverse of :meth:to_struct_dict — drops derived fields.
Wire values land directly in the lazy cache slots so the
receiver never re-resolves them. hash is recomputed by
the property; cwd / url / git_url are
per-process and are ignored if present on the input —
reconstructing them from the struct would defeat the lazy
contract on the receiving side, which re-derives them
locally.
to_singleton ¶
Promote this instance into the per-class _INSTANCES cache.
Hot listing paths (iterdir / _ls / glob) build
children with singleton_ttl=False so the bounded cache
doesn't fill up with thousands of short-lived entries. When a
caller decides one of those children is worth keeping around
(handing it to a long-running worker, returning it from an
API), :meth:to_singleton registers self into the cache
so the next constructor call with the same key collapses to
the same instance.
ttl defaults to the subclass's _SINGLETON_TTL
(... = no caching, None = process lifetime, or a
seconds count). When a different instance is already cached
under this key, that pre-existing one wins and is returned
unchanged — the cache is the source of truth.
invalidate_singleton ¶
Pop self from the per-class _INSTANCES cache.
Mutating ops on a Singleton-cached object (writes, deletes,
schema invalidations on a Databricks table, put_object on
an :class:S3Path) want to make sure the next caller asking
for the same key gets a fresh build rather than collapsing
onto this stale handle — that's what remove_global=True
(the default) does. The pop is :meth:identity-guarded:
only an entry that still points at self is removed, so
a concurrent re-construction that already raced past this
thread is left alone.
remove_global=False is a no-op. The keyword exists so
subclass invalidators (invalidate_singleton,
_invalidate_entity_tag_cache, …) can offer the same
switch without branching at the call site.
get_user_info ¶
Return the cached :class:UserInfo for the current process.
Only hostname is resolved eagerly — every other field is a
lazy property on the instance that fires once on first access
and persists. refresh=True drops the cached singleton and
rebuilds, which also abandons any previously memoized lazy
fields (the new instance starts unresolved).
The cache is the per-class :attr:UserInfo._INSTANCES slot
inherited from :class:Singleton — same primitive every other
config-keyed singleton in the codebase uses.
normalize_abs_path_for_url ¶
Normalize an absolute filesystem path into a URL-safe POSIX string.
Examples::
/a//b///c -> /a/b/c
C:\Users\me\proj -> /C:/Users/me/proj
\\server\share\dir -> //server/share/dir