"""Functions for managing context in the client."""importloggingfromcontextlibimportcontextmanagerfromcontextvarsimportContextVar,TokenfromfunctoolsimportwrapsfromtypingimportAny,Callable,Generator,ParamSpec,TypeVarfromqnexus.models.annotationsimportPropertiesDictfromqnexus.models.referencesimportProjectReflogger=logging.getLogger(__name__)_QNEXUS_PROJECT:ContextVar[ProjectRef|None]=ContextVar("qnexus_project",default=None)_QNEXUS_PROPERTIES:ContextVar[PropertiesDict|None]=ContextVar("qnexus_properties",default=None)
[docs]defdeactivate_project(token:Token[ProjectRef|None])->None:"""Deactivate a project from the current context."""_QNEXUS_PROJECT.reset(token)
[docs]defdeactivate_properties(token:Token[PropertiesDict|None])->None:"""Deactivate the current properties."""_QNEXUS_PROPERTIES.reset(token)
[docs]defget_active_project(project_required:bool=False)->ProjectRef|None:"""Get a reference to the active project if set. >>> get_active_project() >>> from qnexus.models.annotations import Annotations >>> token = set_active_project_token( ... ProjectRef(id="dca33f7f-9619-4cf7-a3fb-56256b117d6e", ... annotations=Annotations(name="example"))) >>> get_active_project() ProjectRef( id=UUID('dca33f7f-9619-4cf7-a3fb-56256b117d6e'), annotations=Annotations(name='example', description=None, properties=OrderedDict()) ) >>> deactivate_project(token) """active_project=_QNEXUS_PROJECT.get(None)ifactive_projectisNoneandproject_required:raiseUnboundLocalError("No Project set.")returnactive_project
[docs]defget_active_properties()->PropertiesDict:"""Get the keys and values of the currently active properties. >>> get_active_properties() OrderedDict() >>> token = update_active_properties_token(foo=3, bar=True) >>> get_active_properties() OrderedDict([('foo', 3), ('bar', True)]) >>> deactivate_properties(token) """properties=_QNEXUS_PROPERTIES.get()ifpropertiesisNone:returnPropertiesDict()returnproperties
[docs]defset_active_project_token(project:ProjectRef)->Token[ProjectRef|None]:"""Globally set a project as active, returning a Token to the ProjectRef in the context."""return_QNEXUS_PROJECT.set(project)
[docs]defset_active_project(project:ProjectRef)->None:"""Globally set a project as active."""set_active_project_token(project)
[docs]defupdate_active_properties_token(**properties:int|float|str|bool,)->Token[PropertiesDict|None]:"""Globally update and merge properties with the existing ones, returning a token to the PropertiesDict in the context."""current_properties=_QNEXUS_PROPERTIES.get()ifcurrent_propertiesisNone:current_properties=PropertiesDict({})else:current_properties=current_properties.copy()current_properties.update(properties)return_QNEXUS_PROPERTIES.set(current_properties)
[docs]defupdate_active_properties(**properties:int|float|str|bool,)->None:"""Globally update and merge properties with the existing ones."""update_active_properties_token(**properties)
[docs]@contextmanagerdefusing_project(project:ProjectRef)->Generator[None,None,None]:"""Attach a ProjectRef to the current context. All operations in the context will make use of the project. >>> from qnexus.models.annotations import Annotations >>> project = ProjectRef( ... id="cd325b9c-d4a2-4b6e-ae58-8fad89749fac", ... annotations=Annotations(name="example")) >>> with using_project(project): ... get_active_project() ProjectRef( id=UUID('cd325b9c-d4a2-4b6e-ae58-8fad89749fac'), annotations=Annotations(name='example', description=None, properties=OrderedDict()) ) >>> get_active_project() """token=set_active_project_token(project)try:yieldfinally:return_QNEXUS_PROJECT.reset(token)
[docs]@contextmanagerdefusing_properties(**properties:int|float|str|bool,)->Generator[None,None,None]:"""Attach properties to the current context."""token=update_active_properties_token(**properties)try:yieldfinally:_QNEXUS_PROPERTIES.reset(token)
P=ParamSpec("P")T=TypeVar("T")
[docs]defmerge_project_from_context(func:Callable[P,T])->Callable[P,T]:"""Decorator to merge a project from the context. ProjectRef in kwargs takes precedence (will be selected)."""@wraps(func)defget_project_from_context(*args:Any,**kwargs:Any)->T:kwargs["project"]=kwargs.get("project",None)ifkwargs["project"]isNone:kwargs["project"]=get_active_project()returnfunc(*args,**kwargs)returnget_project_from_context
[docs]defmerge_properties_from_context(func:Callable[P,T])->Callable[P,T]:"""Decorator to take the union of properties from the context with any provided in kwargs. Properties in kwargs take precendence."""@wraps(func)def_merge_properties_from_context(*args:Any,**kwargs:Any)->T:ifkwargs.get("properties")isNone:kwargs["properties"]=PropertiesDict()kwargs["properties"]=get_active_properties()|kwargs["properties"]returnfunc(*args,**kwargs)return_merge_properties_from_context