:py:mod:`anod.action` ===================== .. py:module:: anod.action .. autoapi-nested-parse:: Anod build actions. Package Contents ---------------- Classes ~~~~~~~ .. autoapisummary:: anod.action.Action anod.action.Root anod.action.GetSource anod.action.Download anod.action.DownloadSource anod.action.InstallSource anod.action.CreateSource anod.action.CreateSources anod.action.Checkout anod.action.AnodAction anod.action.Build anod.action.Test anod.action.Install anod.action.DownloadBinary anod.action.Upload anod.action.UploadComponent anod.action.UploadBinaryComponent anod.action.UploadSourceComponent anod.action.UploadSource anod.action.CheckVirus anod.action.Decision anod.action.CreateSourceOrDownload anod.action.BuildOrDownload Attributes ~~~~~~~~~~ .. autoapisummary:: anod.action.Choice .. py:data:: Choice .. py:class:: Action(uid: str, data: Any) Action object. Action objects are used as node in DAG produced by anod scheduler. Only child classes are used directly. .. py:property:: run_method :type: str Return the name of the method to execute for this action. .. py:attribute:: __slots__ :value: ('data', 'uid') .. py:class:: Root Bases: :py:obj:`Action` Root action. This action does not correspond to any real activity. It's only used as the root of the DAG and can be "executed" only once all the scheduled Actions are completed. .. py:attribute:: __slots__ :value: ('data', 'uid') .. py:method:: __str__() -> str Return string representation of root node. .. py:class:: GetSource(builder: e3.anod.package.SourceBuilder) Bases: :py:obj:`Action` GetSource Action. This action means that we need to retrieve a given source package. In the anod DAG context it can either have one child node: DownloadSource (read access to a store) or provide the choice between DownloadSource or CreateSource using a Decision node. .. py:attribute:: __slots__ :value: ('builder', 'uid') .. py:method:: __str__() -> str Return string representation of GetSource action. .. py:class:: Download(uid: str, data: Any) Bases: :py:obj:`Action` General root class for all download actions. .. py:class:: DownloadSource(builder: e3.anod.package.SourceBuilder) Bases: :py:obj:`Download` DownloadSource Action. This action means the we need to download from the store a given source. DownloadSource is always a leaf of the DAG. .. py:attribute:: __slots__ :value: ('builder', 'uid') .. py:method:: __str__() -> str Return string representation of DownloadSource action. .. py:class:: InstallSource(uid: str, spec: e3.anod.spec.Anod, source: e3.anod.package.Source) Bases: :py:obj:`Action` InstallSource Action. This means that a source should be installed. Child action is always a GetSource Action. .. py:attribute:: __slots__ :value: ('source', 'spec', 'uid') .. py:method:: __str__() -> str Return string representation of InstallSource action. .. py:class:: CreateSource(anod_instance: e3.anod.spec.Anod, source_name: str) Bases: :py:obj:`Action` CreateSource Action. This means that we need to assemble the source package from a repositories checkouts. CreateSource has at least one Checkout child node. .. py:attribute:: __slots__ :value: ('anod_instance', 'source_name', 'uid') .. py:method:: __str__() -> str Return string representation of CreateSource action. .. py:class:: CreateSources(anod_instance: e3.anod.spec.Anod) Bases: :py:obj:`Action` CreateSources Action. This action does not correspond to any real activity. It's only used to group all CreateSource action corresponding to the same anod spec. .. py:attribute:: __slots__ :value: ('anod_instance', 'uid') .. py:method:: __str__() -> str Return string representation of CreateSources action. .. py:class:: Checkout(repo_name: str, repo_data: dict[str, Any]) Bases: :py:obj:`Action` Checkout Action. This means that we need to perform the checkout/update of a given repository. .. py:attribute:: __slots__ :value: ('repo_data', 'repo_name', 'uid') .. py:method:: __str__() -> str Return string representation of Checkout action. .. py:class:: AnodAction(anod_instance: e3.anod.spec.Anod) Bases: :py:obj:`Action` AnodAction Action. Correspond to an Anod primitive call. Only subclasses should be used. .. py:attribute:: __slots__ :value: ('anod_instance', 'uid') .. py:method:: __str__() -> str Return string representation of Anod action. .. py:class:: Build(anod_instance: e3.anod.spec.Anod) Bases: :py:obj:`AnodAction` Anod build primitive. .. py:class:: Test(anod_instance: e3.anod.spec.Anod) Bases: :py:obj:`AnodAction` Anod test primitive. .. py:class:: Install(anod_instance: e3.anod.spec.Anod) Bases: :py:obj:`AnodAction` Anod install primitive. .. py:class:: DownloadBinary(data: e3.anod.spec.Anod) Bases: :py:obj:`Download` DownloadBinary Action. Download a binary package from the store. .. py:attribute:: __slots__ :value: ('data', 'uid') .. py:method:: __str__() -> str Return string representation of DownloadBinary action. .. py:class:: Upload(uid: str, data: Any) Bases: :py:obj:`Action` General root class for all upload actions. .. py:class:: UploadComponent(data: e3.anod.spec.Anod) Bases: :py:obj:`Upload` UploadComponent Action. Upload a component to the store. .. py:attribute:: __slots__ :value: ('anod_instance', 'data', 'uid') .. py:attribute:: str_prefix :value: '' .. py:method:: __str__() -> str Return string representation of UploadComponent action. .. py:class:: UploadBinaryComponent(data: e3.anod.spec.Anod) Bases: :py:obj:`UploadComponent` Upload binary component. .. py:attribute:: str_prefix :value: 'binary package' .. py:class:: UploadSourceComponent(data: e3.anod.spec.Anod) Bases: :py:obj:`UploadComponent` Upload source only component. .. py:attribute:: str_prefix :value: 'source metadata' .. py:class:: UploadSource(anod_instance: e3.anod.spec.Anod, source_name: str) Bases: :py:obj:`Upload` Upload a source package. .. py:attribute:: __slots__ :value: ('anod_instance', 'source_name', 'uid') .. py:method:: __str__() -> str Return string representation. .. py:class:: CheckVirus(data: e3.anod.spec.Anod) Bases: :py:obj:`Action` CheckVirus Action. Check virus on uploaded component. .. py:attribute:: __slots__ :value: ('anod_instance', 'data', 'uid') .. py:method:: __str__() -> str Return string representation of CheckVirus action. .. py:class:: Decision(root: Action, left: Action, right: Action, choice: Choice | None = None) Bases: :py:obj:`Action` Decision Action. Decision nodes correspond to Action nodes where the end result can be obtained using multiple methods. For instance, sources can be obtained either by downloading them from the store, but also by getting them from repositories. Each child of Decision nodes represents one way to obtain the desired end result (a "choice"). The current implementation only supports 2 choices, called "left" and "right". The DAG we first create when reading the plan includes these Decision nodes. Then, as part of scheduling the plan, we create a new DAG where all Decision nodes are removed, and only one child of each Decision is chosen by the scheduler, then taking the place of its Decision node in the DAG. Therefore, once scheduling of the DAG is complete, there should no longer be any Decision node left. It important to know that this class does not actually decide which choice to make. It just records some information about the plan, and the associated specs. It then uses that information to determine if a choice has actually been made, be it implicitly or explicitly. :ivar initiator: The UID of the parent node of the decision. :vartype initiator: str :ivar left_action: The first possible choice for our decision. :vartype left_action: Action. :ivar right_action: The second possible choice for our decision. :vartype right_action: Action. :ivar choice: If not None, the choice made by the plan itself. It can be Decision.LEFT, meaning that the plan contains an entry to perform the self.left_action; If set to Decision.RIGHT, it means the plan contains an entry to perform the self.right_action; and if set to BOTH, it means the plan contains entries to perform both self.left_action and self.right_action (which may or may not be an issue). :vartype choice: Decision.LEFT | Decision.RIGHT | Decision.BOTH :ivar expected_choice: If not None, the choice implicitly made by the way the specs involved in the decision are written. In practice, this attribute records the constraints we have in terms of the choices in the plan which are valid. :ivar triggers: A list of actions that, if present in a DAG being created while scheduling the plan (from which this Decision originates), causes a specific choice to be expected for this decision. Each element of this list consists of a tuple with the uid of the Action triggering the choice, the expected choice, and a plan_line (if the action comes from the plan, otherwise None). :vartype triggers: list[(str, LEFT | RIGHT, str | None)] :ivar decision_maker: If not None, the plan_line where an entry in the plan is performing an action corresponding to one of our choices. :ivar: str .. py:property:: left :type: str Return self.left_action.uid (this is a convenience property). .. py:property:: right :type: str Return self.right_action.uid (this is a convenience property). .. py:attribute:: LEFT :type: Final :value: 0 .. py:attribute:: RIGHT :type: Final :value: 1 .. py:attribute:: BOTH :type: Final :value: 2 .. py:method:: add_trigger(trigger: Action, decision: Choice, plan_line: str) -> None Add a trigger to self.triggers. See the description of the "triggers" attribute for more information as to what these triggers are used for. :param trigger: The action which, when scheduled, causes the given decision (which is actually more aptly described as a choice) to be recorded as the expected choice for our Decision. :param decision: The expected choice when the trigger Action is scheduled. :param plan_line: plan line associated with this action .. py:method:: apply_triggers(dag: e3.collection.dag.DAG) -> None Apply triggers to the given dag. :param dag: a dag of scheduled actions .. py:method:: get_decision() -> str | None Return uid of the choice made by the plan, or None. This function returns the choice made by the plan, if any. This means that if the plan doesn't include an action that implements any of the choices, we return None. Similarly, if the plan has actions implementing more than one of the choices, the plan hasn't made any decision because the decision is ambiguous. And finally, if the plan made a choice, but that choice contradicts this decision's expected_choice, then the decision is incorrect, and we also return None in that case. :return: None if the decision cannot be made; otherwise, return uid of the choice that was made. .. py:method:: get_expected_decision() -> str | None Get expected decision. :return: uid of the expected action or None if no specific decision is expected. .. py:method:: set_decision(which: Choice, decision_maker: str | None) -> None Record a choice made by an action in a plan. This method should be caused when an entry in our plan performs an action corresponding to one of the choices for our decision. This method records which of the choices that action performs. :param which: Decision.LEFT or Decision.RIGHT :param decision_maker: Record who the decision maker is. This is typically the plan line of the action performing the choice being recorded. .. py:method:: description(decision: Choice) -> str :classmethod: :abstractmethod: Return a description of the decision (actually a choice). :param decision: The decision (actually a choice). :return: A description of the given parameter (named "decision", but actually a choice). .. py:method:: suggest_plan_fix(choice: Choice) -> str | None Suggest a plan line that would fix the conflict. :param choice: Decision.LEFT or Decision.RIGHT :return: a line to add to the plan or None if no fix can be proposed .. py:class:: CreateSourceOrDownload(root: Action, left: CreateSource, right: DownloadSource) Bases: :py:obj:`Decision` Decision between creating or downloading a source package. .. py:attribute:: CREATE :type: Final .. py:attribute:: DOWNLOAD :type: Final .. py:method:: description(decision: Choice) -> str :classmethod: Return the action description for the given decision. :param decision: LEFT for CreateSource, RIGHT for DownloadSource :return: action name as string .. py:class:: BuildOrDownload(root: Install, left: Build, right: DownloadBinary) Bases: :py:obj:`Decision` Decision between building or downloading a component. .. py:attribute:: BUILD :type: Final .. py:attribute:: INSTALL :type: Final .. py:method:: description(decision: Choice) -> str :classmethod: Return the action description for the given decision. :param decision: LEFT for Build, RIGHT for DownloadBinary :return: action name as string .. py:method:: suggest_plan_fix(choice: Choice) -> str Suggest an anod command to fix the plan based on the chosen action. :param choice: which action to use (LEFT or RIGHT) :return: anod command string with spec name, qualifier, and platforms