<div dir="ltr">Acked-by: Jeremy Spweock <<a href="mailto:jspweock@iol.unh.edu">jspweock@iol.unh.edu</a>></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 23, 2023 at 6:40 AM Juraj Linkeš <juraj.linkes@pantheon.tech> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">WIP: only one module is reformatted to serve as a demonstration.<br>
<br>
The google format is documented here [0].<br>
<br>
[0]: <a href="https://google.github.io/styleguide/pyguide.html" rel="noreferrer" target="_blank">https://google.github.io/styleguide/pyguide.html</a><br>
<br>
Signed-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech><br>
---<br>
 dts/framework/testbed_model/node.py | 152 +++++++++++++++++++---------<br>
 1 file changed, 103 insertions(+), 49 deletions(-)<br>
<br>
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py<br>
index 90467981c3..ad8ef442af 100644<br>
--- a/dts/framework/testbed_model/node.py<br>
+++ b/dts/framework/testbed_model/node.py<br>
@@ -3,8 +3,13 @@<br>
 # Copyright(c) 2022-2023 PANTHEON.tech s.r.o.<br>
 # Copyright(c) 2022-2023 University of New Hampshire<br>
<br>
-"""<br>
-A node is a generic host that DTS connects to and manages.<br>
+"""Common functionality for node management.<br>
+<br>
+There's a base class, Node, that's supposed to be extended by other classes<br>
+with functionality specific to that node type.<br>
+The only part that can be used standalone is the Node.skip_setup static method,<br>
+which is a decorator used to skip method execution<br>
+if skip_setup is passed by the user on the cmdline or in an env variable.<br>
 """<br>
<br>
 from typing import Any, Callable<br>
@@ -26,10 +31,25 @@<br>
<br>
<br>
 class Node(object):<br>
-    """<br>
-    Basic class for node management. This class implements methods that<br>
-    manage a node, such as information gathering (of CPU/PCI/NIC) and<br>
-    environment setup.<br>
+    """The base class for node management.<br>
+<br>
+    It shouldn't be instantiated, but rather extended.<br>
+    It implements common methods to manage any node:<br>
+<br>
+       * connection to the node<br>
+       * information gathering of CPU<br>
+       * hugepages setup<br>
+<br>
+    Arguments:<br>
+        node_config: The config from the input configuration file.<br>
+<br>
+    Attributes:<br>
+        main_session: The primary OS-agnostic remote session used<br>
+            to communicate with the node.<br>
+        config: The configuration used to create the node.<br>
+        name: The name of the node.<br>
+        lcores: The list of logical cores that DTS can use on the node.<br>
+            It's derived from logical cores present on the node and user configuration.<br>
     """<br>
<br>
     main_session: OSSession<br>
@@ -56,65 +76,89 @@ def __init__(self, node_config: NodeConfiguration):<br>
         self._<a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>(f"Created node: {<a href="http://self.name" rel="noreferrer" target="_blank">self.name</a>}")<br>
<br>
     def set_up_execution(self, execution_config: ExecutionConfiguration) -> None:<br>
-        """<br>
-        Perform the execution setup that will be done for each execution<br>
-        this node is part of.<br>
+        """Execution setup steps.<br>
+<br>
+        Configure hugepages and call self._set_up_execution where<br>
+        the rest of the configuration steps (if any) are implemented.<br>
+<br>
+        Args:<br>
+            execution_config: The execution configuration according to which<br>
+                the setup steps will be taken.<br>
         """<br>
         self._setup_hugepages()<br>
         self._set_up_execution(execution_config)<br>
<br>
     def _set_up_execution(self, execution_config: ExecutionConfiguration) -> None:<br>
-        """<br>
-        This method exists to be optionally overwritten by derived classes and<br>
-        is not decorated so that the derived class doesn't have to use the decorator.<br>
+        """Optional additional execution setup steps for derived classes.<br>
+<br>
+        Derived classes should overwrite this<br>
+        if they want to add additional execution setup steps.<br>
         """<br>
<br>
     def tear_down_execution(self) -> None:<br>
-        """<br>
-        Perform the execution teardown that will be done after each execution<br>
-        this node is part of concludes.<br>
+        """Execution teardown steps.<br>
+<br>
+        There are currently no common execution teardown steps<br>
+        common to all DTS node types.<br>
         """<br>
         self._tear_down_execution()<br>
<br>
     def _tear_down_execution(self) -> None:<br>
-        """<br>
-        This method exists to be optionally overwritten by derived classes and<br>
-        is not decorated so that the derived class doesn't have to use the decorator.<br>
+        """Optional additional execution teardown steps for derived classes.<br>
+<br>
+        Derived classes should overwrite this<br>
+        if they want to add additional execution teardown steps.<br>
         """<br>
<br>
     def set_up_build_target(<br>
         self, build_target_config: BuildTargetConfiguration<br>
     ) -> None:<br>
-        """<br>
-        Perform the build target setup that will be done for each build target<br>
-        tested on this node.<br>
+        """Build target setup steps.<br>
+<br>
+        There are currently no common build target setup steps<br>
+        common to all DTS node types.<br>
+<br>
+        Args:<br>
+            build_target_config: The build target configuration according to which<br>
+                the setup steps will be taken.<br>
         """<br>
         self._set_up_build_target(build_target_config)<br>
<br>
     def _set_up_build_target(<br>
         self, build_target_config: BuildTargetConfiguration<br>
     ) -> None:<br>
-        """<br>
-        This method exists to be optionally overwritten by derived classes and<br>
-        is not decorated so that the derived class doesn't have to use the decorator.<br>
+        """Optional additional build target setup steps for derived classes.<br>
+<br>
+        Derived classes should optionally overwrite this<br>
+        if they want to add additional build target setup steps.<br>
         """<br>
<br>
     def tear_down_build_target(self) -> None:<br>
-        """<br>
-        Perform the build target teardown that will be done after each build target<br>
-        tested on this node.<br>
+        """Build target teardown steps.<br>
+<br>
+        There are currently no common build target teardown steps<br>
+        common to all DTS node types.<br>
         """<br>
         self._tear_down_build_target()<br>
<br>
     def _tear_down_build_target(self) -> None:<br>
-        """<br>
-        This method exists to be optionally overwritten by derived classes and<br>
-        is not decorated so that the derived class doesn't have to use the decorator.<br>
+        """Optional additional build target teardown steps for derived classes.<br>
+<br>
+        Derived classes should overwrite this<br>
+        if they want to add additional build target teardown steps.<br>
         """<br>
<br>
     def create_session(self, name: str) -> OSSession:<br>
-        """<br>
-        Create and return a new OSSession tailored to the remote OS.<br>
+        """Create and return a new OS-agnostic remote session.<br>
+<br>
+        The returned session won't be used by the object creating it.<br>
+        Will be cleaned up automatically.<br>
+<br>
+        Args:<br>
+            name: The name of the session.<br>
+<br>
+        Returns:<br>
+            A new OS-agnostic remote session.<br>
         """<br>
         session_name = f"{<a href="http://self.name" rel="noreferrer" target="_blank">self.name</a>} {name}"<br>
         connection = create_session(<br>
@@ -130,14 +174,24 @@ def filter_lcores(<br>
         filter_specifier: LogicalCoreCount | LogicalCoreList,<br>
         ascending: bool = True,<br>
     ) -> list[LogicalCore]:<br>
-        """<br>
-        Filter the LogicalCores found on the Node according to<br>
-        a LogicalCoreCount or a LogicalCoreList.<br>
+        """Filter the node's logical cores that DTS can use.<br>
<br>
-        If ascending is True, use cores with the lowest numerical id first<br>
-        and continue in ascending order. If False, start with the highest<br>
-        id and continue in descending order. This ordering affects which<br>
-        sockets to consider first as well.<br>
+        Logical cores that DTS can use are ones that are present on the node,<br>
+        but filtered according to user config.<br>
+        The filter_specifier will filter cores from those logical cores.<br>
+<br>
+        Args:<br>
+            filter_specifier: Two different filters can be used, one that specifies<br>
+                the number of logical cores per core, cores per socket and<br>
+                the number of sockets,<br>
+                the other that specifies a logical core list.<br>
+            ascending: If True, use cores with the lowest numerical id first<br>
+                and continue in ascending order. If False, start with the highest<br>
+                id and continue in descending order. This ordering affects which<br>
+                sockets to consider first as well.<br>
+<br>
+        Returns:<br>
+            A list of logical cores.<br>
         """<br>
         self._logger.debug(f"Filtering {filter_specifier} from {self.lcores}.")<br>
         return lcore_filter(<br>
@@ -147,17 +201,14 @@ def filter_lcores(<br>
         ).filter()<br>
<br>
     def _get_remote_cpus(self) -> None:<br>
-        """<br>
-        Scan CPUs in the remote OS and store a list of LogicalCores.<br>
-        """<br>
+        """Scan CPUs in the remote OS and store a list of LogicalCores."""<br>
         self._<a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>("Getting CPU information.")<br>
         self.lcores = self.main_session.get_remote_cpus(self.config.use_first_core)<br>
<br>
     def _setup_hugepages(self):<br>
-        """<br>
-        Setup hugepages on the Node. Different architectures can supply different<br>
-        amounts of memory for hugepages and numa-based hugepage allocation may need<br>
-        to be considered.<br>
+        """Setup hugepages on the Node.<br>
+<br>
+        Configure the hugepages only if they're specified in user configuration.<br>
         """<br>
         if self.config.hugepages:<br>
             self.main_session.setup_hugepages(<br>
@@ -165,9 +216,7 @@ def _setup_hugepages(self):<br>
             )<br>
<br>
     def close(self) -> None:<br>
-        """<br>
-        Close all connections and free other resources.<br>
-        """<br>
+        """Close all connections and free other resources."""<br>
         if self.main_session:<br>
             self.main_session.close()<br>
         for session in self._other_sessions:<br>
@@ -176,6 +225,11 @@ def close(self) -> None:<br>
<br>
     @staticmethod<br>
     def skip_setup(func: Callable[..., Any]) -> Callable[..., Any]:<br>
+        """A decorator that skips the decorated function.<br>
+<br>
+        When used, the decorator executes an empty lambda function<br>
+        instead of the decorated function.<br>
+        """<br>
         if SETTINGS.skip_setup:<br>
             return lambda *args: None<br>
         else:<br>
-- <br>
2.30.2<br>
<br>
</blockquote></div>