[docs]classSetting(HasNarratorKnowledge,Dependency):"""Setting() Story-specific dependency edge that binds a location provider into gathered scope. Why ---- ``Setting`` specializes generic dependency resolution for location-like providers so story blocks and scenes can expose a stable place contract without hard-coding provider lookup rules. Key Features ------------ * Extends :class:`~tangl.vm.provision.requirement.Dependency` so settings use the same provisioning mechanics as other frontier edges. * Publishes the resolved provider under the setting label plus derived metadata keys during namespace gathering. * Publishes additive aliases such as ``place_setting`` and ``setting_edges`` so setting-level epistemic state remains distinct from provider-level knowledge. * Contributes a merged ``settings`` mapping for render/provision helpers. API --- - :meth:`provide_setting_symbols` returns the local symbol payload reused by gather-time assembly. """@staticmethoddef_invoke_provider_ns(provider:Any)->dict[str,Any]:get_ns=getattr(provider,"get_ns",None)ifnotcallable(get_ns):return{}value=get_ns()ifvalueisNone:return{}ifnotisinstance(value,Mapping):raiseTypeError(f"{type(provider).__name__}.get_ns must return Mapping | None",)payload=dict(value)return{key:itemforkey,iteminpayload.items()ifitemisnotprovider}defprovide_setting_symbols(self)->dict[str,Any]:"""Publish setting/provider symbols for gather-time namespace assembly."""provider=self.providerlabel=self.get_label()ifproviderisNoneornotlabel:return{}payload:dict[str,Any]={label:provider}provider_ns=self._invoke_provider_ns(provider)forkey,valueinprovider_ns.items():payload[f"{label}_{key}"]=valuereturnpayload
def_setting_sort_key(setting:Setting)->tuple[str,str]:returnsetting.get_label()or"",str(setting.uid)@on_gather_nsdefcontribute_settings(*,caller,ctx,**_kw):"""Inject setting providers and setting metadata into assembled scoped namespaces."""ifnothasattr(caller,"edges_out"):returnNonescope_nodes=list(caller.ancestors)ifhasattr(caller,"ancestors")else[caller]contributions:dict[str,Any]={}settings:dict[str,Any]={}setting_edges:dict[str,Setting]={}forscopeinreversed(scope_nodes):scope_settings=sorted(scope.edges_out(Selector(has_kind=Setting)),key=_setting_sort_key)forsettinginscope_settings:setting_payload=setting.provide_setting_symbols()ifsetting_payload:contributions.update(setting_payload)provider=setting.providerlabel=setting.get_label()ifproviderisnotNoneandlabel:settings[label]=provideriflabel:contributions[f"{label}_setting"]=settingsetting_edges[label]=settingifsettings:contributions["settings"]=settingsifsetting_edges:contributions["setting_edges"]=setting_edgesreturncontributionsorNone