anod.context
============

.. py:module:: anod.context


Attributes
----------

.. autoapisummary::

   anod.context.CacheKeyType
   anod.context.logger


Classes
-------

.. autoapisummary::

   anod.context.SchedulingError
   anod.context.AnodContext


Module Contents
---------------

.. py:data:: CacheKeyType

.. py:data:: logger

.. py:class:: SchedulingError(message: str | list[str], origin: str | None = None, uid: e3.collection.dag.VertexID | None = None, initiators: list[e3.collection.dag.VertexID] | None = None)

   Bases: :py:obj:`e3.error.E3Error`


   Exception raised by scheduling algorithm.


   .. py:attribute:: uid
      :value: None



   .. py:attribute:: initiators


.. py:class:: AnodContext(spec_repository: e3.anod.loader.AnodSpecRepository, default_env: e3.env.BaseEnv | None = None, reject_duplicates: bool = False, spec_load_hook: SpecLoadHook | None = None)

   Anod context.

   :ivar repo: an anod spec repository
   :vartype repo: e3.anod.loader.AnodSpecRepository
   :ivar tree: a DAG containing the list of possible actions
   :ivar root: root node of the DAG
   :ivar cache: cache of anod instances, indexed by the spec's name.
   :vartype cache: dict[e3.anod.spec.Anod]
   :ivar sources: list of available sources in the current context,
       indexed by the source's name.
   :vartype sources: list[e3.anod.package.SourceBuilder]
   :ivar default_env: default environment (used to override build='default')
       when simulating a list of action from another machine.

   :ivar plan: maintain a link between a plan line and the generated actions
       which is useful for setting parameters such as weather or process that
       are conveyed by the plan and not by the specs


   .. py:attribute:: repo


   .. py:attribute:: reject_duplicates
      :value: False



   .. py:attribute:: tree


   .. py:attribute:: root


   .. py:attribute:: dependencies
      :type:  dict[str, dict[str, tuple[e3.anod.deps.Dependency, e3.anod.spec.Anod]]]


   .. py:attribute:: cache
      :type:  dict[CacheKeyType, e3.anod.spec.Anod]


   .. py:attribute:: sources
      :type:  dict[str, tuple[str, e3.anod.package.SourceBuilder]]


   .. py:attribute:: spec_load_hook
      :value: None



   .. py:method:: load(name: str, env: e3.env.BaseEnv | None, qualifier: str | dict[str, str | bool | Iterable[str]] | None, kind: e3.anod.spec.PRIMITIVE, sandbox: e3.anod.sandbox.SandBox | None = None, source_name: str | None = None) -> e3.anod.spec.Anod

      Load a spec instance.

      :param name: spec name
      :param env: environment to use for the spec instance
      :param qualifier: spec qualifier
      :param kind: primitive used for the loaded spec
      :param sandbox: is not None bind the anod instances to a sandbox
      :param source_name: when the primitive is "source" we create a specific
          instance for each source package we have to create.
      :return: a spec instance



   .. py:method:: add(data: e3.anod.action.Action, *args: e3.anod.action.Action) -> None

      Add node to context tree.

      :param data: node data
      :param args: list of predecessors



   .. py:method:: add_decision(decision_class: collections.abc.Callable[Ellipsis, e3.anod.action.Decision], root: e3.anod.action.Action, left: e3.anod.action.Action, right: e3.anod.action.Action) -> e3.anod.action.Decision

      Add a decision node.

      This create the following subtree inside the dag::

          root --> decision --> left
                            |-> right

      :param decision_class: Decision subclass to use
      :param root: parent node of the decision node
      :param left: left decision (child of Decision node)
      :param right: right decision (child of Decision node)



   .. py:method:: connect(action: e3.anod.action.Action, *args: e3.anod.action.Action) -> None

      Add predecessors to a node.

      :param action: parent node
      :param args: list of predecessors



   .. py:method:: __contains__(data: e3.anod.action.Action) -> bool

      Check if a given action is already in the internal DAG.

      :param data: an Action



   .. py:method:: __getitem__(key: str) -> e3.anod.action.Action

      Retrieve action from the internal DAG based on its key.

      :param key: action uid
      :return: an Action



   .. py:method:: predecessors(action: e3.anod.action.Action) -> list[e3.anod.action.Action]

      Retrieve predecessors of a given action.

      :param action: the parent action
      :return: the predecessor list



   .. py:method:: link_to_plan(vertex_id: str, plan_line: str, plan_args: dict) -> None

      Tag the vertex with plan info.

      :param vertex_id: ID of the vertex
      :param plan_line: corresponding line:linenumber in the plan
      :param plan_args: action args after plan execution, taking into
          account plan context (such as with defaults(XXX):)



   .. py:method:: add_plan_action(plan_action_env: e3.electrolyt.plan.PlanActionEnv, sandbox: e3.anod.sandbox.SandBox | None = None) -> e3.anod.action.Action | None

      Add an Anod action to the context.

      :param plan_action_env: the PlanActionEnv object as returned by PlanContext
      :param sandbox: the SandBox object that will be used to run commands
      :return: the root added action or None if this is not an anod action



   .. py:method:: add_anod_action(name: str, env: e3.env.BaseEnv, primitive: e3.anod.spec.PRIMITIVE, qualifier: dict[str, str | bool | Iterable[str]] | None = None, source_packages: list[str] | None = None, upload: bool = True, plan_line: str | None = None, plan_args: dict | None = None, sandbox: e3.anod.sandbox.SandBox | None = None) -> e3.anod.action.Action

      Add an Anod action to the context (internal function).

      Note that using add_anod_action should be avoided when possible
      and replaced by a call to add_plan_action.

      :param name: spec name
      :param env: context in which to load the spec
      :param primitive: spec primitive
      :param qualifier: qualifier
      :param source_packages: if not empty only create the specified list of
          source packages and not all source packages defined in the anod
          specification file
      :param upload: if True consider uploading to the store
      :param plan_line: corresponding line:linenumber in the plan
      :param plan_args: action args after plan execution, taking into
          account plan context (such as with defaults(XXX):)
      :param sandbox: the SandBox object that will be used to run commands
      :return: the root added action



   .. py:method:: add_spec(name: str, env: e3.env.BaseEnv, primitive: e3.anod.spec.PRIMITIVE, qualifier: str | dict[str, str | bool | Iterable[str]] | None = None, source_packages: list[str] | None = None, expand_build: bool = True, source_name: str | None = None, plan_line: str | None = None, plan_args: dict | None = None, sandbox: e3.anod.sandbox.SandBox | None = None, upload: bool = False, force_download: bool = False) -> e3.anod.action.Build | e3.anod.action.CreateSources | e3.anod.action.CreateSource | e3.anod.action.Install | e3.anod.action.Test

      Expand an anod action into a tree (internal).

      :param name: spec name
      :param env: context in which to load the spec
      :param primitive: spec primitive
      :param qualifier: qualifier
      :param source_packages: if not empty only create the specified list of
          source packages and not all source packages defined in the anod
          specification file
      :param expand_build: should build primitive be expanded
      :param source_name: source name associated with the source
          primitive
      :param plan_line: corresponding line:linenumber in the plan
      :param plan_args: action args after plan execution, taking into
          account plan context (such as with defaults(XXX):)
      :param sandbox: if not None, anod instance are automatically bind to
          the given sandbox
      :param upload: if True consider uploads to the store (sources and
          binaries)
      :param force_download: if True force a download



   .. py:method:: decision_error(action: e3.anod.action.Action, decision: e3.anod.action.Decision) -> NoReturn
      :classmethod:


      Raise SchedulingError.

      :param action: action to consider
      :param decision: decision to resolve
      :raise: SchedulingError



   .. py:method:: always_download_source_resolver(action: e3.anod.action.Action, decision: e3.anod.action.Decision) -> bool
      :classmethod:


      Force source download when scheduling a plan.

      The resolver takes the following decision:
      * sources are always downloaded
      * any build that produces a package should be added explicitly

      :param action: action to consider
      :param decision: decision to resolve
      :return: True if the action should be scheduled, False otherwise
      :raise SchedulingError: in case no decision can be taken



   .. py:method:: always_create_source_resolver(action: e3.anod.action.Action, decision: e3.anod.action.Decision) -> bool
      :classmethod:


      Force source creation when scheduling a plan.



   .. py:method:: schedule(resolver: ResolverType) -> e3.collection.dag.DAG

      Compute a DAG of scheduled actions.

      :param resolver: a function that helps the scheduler resolve cases
          for which a decision should be taken



