From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 62827433AC;
	Thu, 23 Nov 2023 16:16:19 +0100 (CET)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 260A743293;
	Thu, 23 Nov 2023 16:14:25 +0100 (CET)
Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com
 [209.85.221.50]) by mails.dpdk.org (Postfix) with ESMTP id 07A2743003
 for <dev@dpdk.org>; Thu, 23 Nov 2023 16:14:08 +0100 (CET)
Received: by mail-wr1-f50.google.com with SMTP id
 ffacd0b85a97d-332e40315bdso379153f8f.1
 for <dev@dpdk.org>; Thu, 23 Nov 2023 07:14:08 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=pantheon.tech; s=google; t=1700752447; x=1701357247; darn=dpdk.org;
 h=content-transfer-encoding:mime-version:references:in-reply-to
 :message-id:date:subject:cc:to:from:from:to:cc:subject:date
 :message-id:reply-to;
 bh=t6KeZaLHiysMT+K7nNxDXG0i4w3eJCHNkMFr/vP4ebc=;
 b=BObjpgOynFcf6IIYdRZfCQr2EZqKj+mNKXLBgmsAiDe7oGeAkzoeL5CZi+tssmXgIv
 OIy+KK6201xugWSMw3ZlzRvdW1DfK5WK+TcUERikCn9HMIZfpYXgTvoVn4DjqIQ+Kf/d
 Xnw9cbdUUqIR0CyHooQscMzwYS8WZ32l1HFKa+eE/hBLyu8n2MgiMVRupys1dcqMAnre
 Asnd1tyqY8bOb0XvjrJt7dWk1PifQZUVwhLOg1jEq/QINPkcmpLUzSRQ7omENqLGHUto
 3Nx8GYMP97WB4pcfVtLJ+5eEk5jzUfsywLharkNZEmnY8k7+G/woDailMc6yRgBOfCmT
 6sEA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20230601; t=1700752447; x=1701357247;
 h=content-transfer-encoding:mime-version:references:in-reply-to
 :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc
 :subject:date:message-id:reply-to;
 bh=t6KeZaLHiysMT+K7nNxDXG0i4w3eJCHNkMFr/vP4ebc=;
 b=E76oEUk6p1lGodjIqjeFUIyhvQH4EsgxR459sqH33CKZGEp+Mjr7/XDsIAF+OiGzTU
 RRSbfhIWdd84xC0brXceu2OkP/5SydmD4WNHUcVy7nWeGEHOvmJC2iTT0D+n48MyhEHS
 /bDd9cTKSr7ZJL023FPqez61tOHmzePIMNZy3Gw5WKM7waenDodnLzrEOCDM9BRmUkw2
 DpHbYo5mMz6Qm0V0i3ccA9q2oqcFZLix2YfoVWEnOrxY380Xxvr4G2anMVANSyNb6k31
 VqhPQRMVEChFp4m0bEgpFxRa8w03ZPaKMGr8MZJUWm2nP4aZRg+jNiKVgWGaNVdTKUCF
 SuiQ==
X-Gm-Message-State: AOJu0YxfF79PPJBkx6oZAtNLmSnGkovHuiTLEX1BY9sgtlxKVcu7DV/s
 p0ruWXvXsA8oCpfWgWIQ/tiXgA==
X-Google-Smtp-Source: AGHT+IEXjmFEdxeZnk2zjZUKxCGRw3IdEyWDN0pFWG1hNlRi3h4Bqo3CRPCSF2SojrwrAWTDgRtRSA==
X-Received: by 2002:adf:cc82:0:b0:331:6976:c8c7 with SMTP id
 p2-20020adfcc82000000b003316976c8c7mr3874544wrj.38.1700752447666; 
 Thu, 23 Nov 2023 07:14:07 -0800 (PST)
Received: from jlinkes-PT-Latitude-5530.. ([84.245.121.10])
 by smtp.gmail.com with ESMTPSA id
 q4-20020adfea04000000b003296b488961sm1870143wrm.31.2023.11.23.07.14.06
 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
 Thu, 23 Nov 2023 07:14:07 -0800 (PST)
From: =?UTF-8?q?Juraj=20Linke=C5=A1?= <juraj.linkes@pantheon.tech>
To: thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, jspewock@iol.unh.edu,
 probb@iol.unh.edu, paul.szczepanek@arm.com, yoan.picchi@foss.arm.com,
 Luca.Vizzarro@arm.com
Cc: dev@dpdk.org, =?UTF-8?q?Juraj=20Linke=C5=A1?= <juraj.linkes@pantheon.tech>
Subject: [PATCH v8 16/21] dts: posix and linux sessions docstring update
Date: Thu, 23 Nov 2023 16:13:39 +0100
Message-Id: <20231123151344.162812-17-juraj.linkes@pantheon.tech>
X-Mailer: git-send-email 2.34.1
In-Reply-To: <20231123151344.162812-1-juraj.linkes@pantheon.tech>
References: <20231115130959.39420-1-juraj.linkes@pantheon.tech>
 <20231123151344.162812-1-juraj.linkes@pantheon.tech>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

Format according to the Google format and PEP257, with slight
deviations.

Signed-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech>
---
 dts/framework/testbed_model/linux_session.py | 64 +++++++++++-----
 dts/framework/testbed_model/posix_session.py | 81 +++++++++++++++++---
 2 files changed, 114 insertions(+), 31 deletions(-)

diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index 055765ba2d..0ab59cef85 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -2,6 +2,13 @@
 # Copyright(c) 2023 PANTHEON.tech s.r.o.
 # Copyright(c) 2023 University of New Hampshire
 
+"""Linux OS translator.
+
+Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
+compliant with POSIX standards, so this module only implements the parts that aren't.
+This intermediate module implements the common parts of mostly POSIX compliant distributions.
+"""
+
 import json
 from ipaddress import IPv4Interface, IPv6Interface
 from typing import TypedDict, Union
@@ -17,43 +24,52 @@
 
 
 class LshwConfigurationOutput(TypedDict):
+    """The relevant parts of ``lshw``'s ``configuration`` section."""
+
+    #:
     link: str
 
 
 class LshwOutput(TypedDict):
-    """
-    A model of the relevant information from json lshw output, e.g.:
-    {
-    ...
-    "businfo" : "pci@0000:08:00.0",
-    "logicalname" : "enp8s0",
-    "version" : "00",
-    "serial" : "52:54:00:59:e1:ac",
-    ...
-    "configuration" : {
-      ...
-      "link" : "yes",
-      ...
-    },
-    ...
+    """A model of the relevant information from ``lshw``'s json output.
+
+    Example:
+        ::
+
+            {
+            ...
+            "businfo" : "pci@0000:08:00.0",
+            "logicalname" : "enp8s0",
+            "version" : "00",
+            "serial" : "52:54:00:59:e1:ac",
+            ...
+            "configuration" : {
+              ...
+              "link" : "yes",
+              ...
+            },
+            ...
     """
 
+    #:
     businfo: str
+    #:
     logicalname: NotRequired[str]
+    #:
     serial: NotRequired[str]
+    #:
     configuration: LshwConfigurationOutput
 
 
 class LinuxSession(PosixSession):
-    """
-    The implementation of non-Posix compliant parts of Linux remote sessions.
-    """
+    """The implementation of non-Posix compliant parts of Linux."""
 
     @staticmethod
     def _get_privileged_command(command: str) -> str:
         return f"sudo -- sh -c '{command}'"
 
     def get_remote_cpus(self, use_first_core: bool) -> list[LogicalCore]:
+        """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
         cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
         lcores = []
         for cpu_line in cpu_info.splitlines():
@@ -65,18 +81,20 @@ def get_remote_cpus(self, use_first_core: bool) -> list[LogicalCore]:
         return lcores
 
     def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
+        """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
         return dpdk_prefix
 
-    def setup_hugepages(self, hugepage_amount: int, force_first_numa: bool) -> None:
+    def setup_hugepages(self, hugepage_count: int, force_first_numa: bool) -> None:
+        """Overrides :meth:`~.os_session.OSSession.setup_hugepages`."""
         self._logger.info("Getting Hugepage information.")
         hugepage_size = self._get_hugepage_size()
         hugepages_total = self._get_hugepages_total()
         self._numa_nodes = self._get_numa_nodes()
 
-        if force_first_numa or hugepages_total != hugepage_amount:
+        if force_first_numa or hugepages_total != hugepage_count:
             # when forcing numa, we need to clear existing hugepages regardless
             # of size, so they can be moved to the first numa node
-            self._configure_huge_pages(hugepage_amount, hugepage_size, force_first_numa)
+            self._configure_huge_pages(hugepage_count, hugepage_size, force_first_numa)
         else:
             self._logger.info("Hugepages already configured.")
         self._mount_huge_pages()
@@ -132,6 +150,7 @@ def _configure_huge_pages(self, amount: int, size: int, force_first_numa: bool)
         self.send_command(f"echo {amount} | tee {hugepage_config_path}", privileged=True)
 
     def update_ports(self, ports: list[Port]) -> None:
+        """Overrides :meth:`~.os_session.OSSession.update_ports`."""
         self._logger.debug("Gathering port info.")
         for port in ports:
             assert port.node == self.name, "Attempted to gather port info on the wrong node"
@@ -161,6 +180,7 @@ def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str)
             )
 
     def configure_port_state(self, port: Port, enable: bool) -> None:
+        """Overrides :meth:`~.os_session.OSSession.configure_port_state`."""
         state = "up" if enable else "down"
         self.send_command(f"ip link set dev {port.logical_name} {state}", privileged=True)
 
@@ -170,6 +190,7 @@ def configure_port_ip_address(
         port: Port,
         delete: bool,
     ) -> None:
+        """Overrides :meth:`~.os_session.OSSession.configure_port_ip_address`."""
         command = "del" if delete else "add"
         self.send_command(
             f"ip address {command} {address} dev {port.logical_name}",
@@ -178,5 +199,6 @@ def configure_port_ip_address(
         )
 
     def configure_ipv4_forwarding(self, enable: bool) -> None:
+        """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
         state = 1 if enable else 0
         self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index 5657cc0bc9..d279bb8b53 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -2,6 +2,15 @@
 # Copyright(c) 2023 PANTHEON.tech s.r.o.
 # Copyright(c) 2023 University of New Hampshire
 
+"""POSIX compliant OS translator.
+
+Translates OS-unaware calls into POSIX compliant calls/utilities. POSIX is a set of standards
+for portability between Unix operating systems which not all Linux distributions
+(or the tools most frequently bundled with said distributions) adhere to. Most of Linux
+distributions are mostly compliant though.
+This intermediate module implements the common parts of mostly POSIX compliant distributions.
+"""
+
 import re
 from collections.abc import Iterable
 from pathlib import PurePath, PurePosixPath
@@ -15,13 +24,21 @@
 
 
 class PosixSession(OSSession):
-    """
-    An intermediary class implementing the Posix compliant parts of
-    Linux and other OS remote sessions.
-    """
+    """An intermediary class implementing the POSIX standard."""
 
     @staticmethod
     def combine_short_options(**opts: bool) -> str:
+        """Combine shell options into one argument.
+
+        These are options such as ``-x``, ``-v``, ``-f`` which are combined into ``-xvf``.
+
+        Args:
+            opts: The keys are option names (usually one letter) and the bool values indicate
+                whether to include the option in the resulting argument.
+
+        Returns:
+            The options combined into one argument.
+        """
         ret_opts = ""
         for opt, include in opts.items():
             if include:
@@ -33,17 +50,19 @@ def combine_short_options(**opts: bool) -> str:
         return ret_opts
 
     def guess_dpdk_remote_dir(self, remote_dir: str | PurePath) -> PurePosixPath:
+        """Overrides :meth:`~.os_session.OSSession.guess_dpdk_remote_dir`."""
         remote_guess = self.join_remote_path(remote_dir, "dpdk-*")
         result = self.send_command(f"ls -d {remote_guess} | tail -1")
         return PurePosixPath(result.stdout)
 
     def get_remote_tmp_dir(self) -> PurePosixPath:
+        """Overrides :meth:`~.os_session.OSSession.get_remote_tmp_dir`."""
         return PurePosixPath("/tmp")
 
     def get_dpdk_build_env_vars(self, arch: Architecture) -> dict:
-        """
-        Create extra environment variables needed for i686 arch build. Get information
-        from the node if needed.
+        """Overrides :meth:`~.os_session.OSSession.get_dpdk_build_env_vars`.
+
+        Supported architecture: ``i686``.
         """
         env_vars = {}
         if arch == Architecture.i686:
@@ -63,6 +82,7 @@ def get_dpdk_build_env_vars(self, arch: Architecture) -> dict:
         return env_vars
 
     def join_remote_path(self, *args: str | PurePath) -> PurePosixPath:
+        """Overrides :meth:`~.os_session.OSSession.join_remote_path`."""
         return PurePosixPath(*args)
 
     def copy_from(
@@ -70,6 +90,7 @@ def copy_from(
         source_file: str | PurePath,
         destination_file: str | PurePath,
     ) -> None:
+        """Overrides :meth:`~.os_session.OSSession.copy_from`."""
         self.remote_session.copy_from(source_file, destination_file)
 
     def copy_to(
@@ -77,6 +98,7 @@ def copy_to(
         source_file: str | PurePath,
         destination_file: str | PurePath,
     ) -> None:
+        """Overrides :meth:`~.os_session.OSSession.copy_to`."""
         self.remote_session.copy_to(source_file, destination_file)
 
     def remove_remote_dir(
@@ -85,6 +107,7 @@ def remove_remote_dir(
         recursive: bool = True,
         force: bool = True,
     ) -> None:
+        """Overrides :meth:`~.os_session.OSSession.remove_remote_dir`."""
         opts = PosixSession.combine_short_options(r=recursive, f=force)
         self.send_command(f"rm{opts} {remote_dir_path}")
 
@@ -93,6 +116,7 @@ def extract_remote_tarball(
         remote_tarball_path: str | PurePath,
         expected_dir: str | PurePath | None = None,
     ) -> None:
+        """Overrides :meth:`~.os_session.OSSession.extract_remote_tarball`."""
         self.send_command(
             f"tar xfm {remote_tarball_path} -C {PurePosixPath(remote_tarball_path).parent}",
             60,
@@ -109,6 +133,7 @@ def build_dpdk(
         rebuild: bool = False,
         timeout: float = SETTINGS.compile_timeout,
     ) -> None:
+        """Overrides :meth:`~.os_session.OSSession.build_dpdk`."""
         try:
             if rebuild:
                 # reconfigure, then build
@@ -138,10 +163,12 @@ def build_dpdk(
             raise DPDKBuildError(f"DPDK build failed when doing '{e.command}'.")
 
     def get_dpdk_version(self, build_dir: str | PurePath) -> str:
+        """Overrides :meth:`~.os_session.OSSession.get_dpdk_version`."""
         out = self.send_command(f"cat {self.join_remote_path(build_dir, 'VERSION')}", verify=True)
         return out.stdout
 
     def kill_cleanup_dpdk_apps(self, dpdk_prefix_list: Iterable[str]) -> None:
+        """Overrides :meth:`~.os_session.OSSession.kill_cleanup_dpdk_apps`."""
         self._logger.info("Cleaning up DPDK apps.")
         dpdk_runtime_dirs = self._get_dpdk_runtime_dirs(dpdk_prefix_list)
         if dpdk_runtime_dirs:
@@ -153,6 +180,14 @@ def kill_cleanup_dpdk_apps(self, dpdk_prefix_list: Iterable[str]) -> None:
             self._remove_dpdk_runtime_dirs(dpdk_runtime_dirs)
 
     def _get_dpdk_runtime_dirs(self, dpdk_prefix_list: Iterable[str]) -> list[PurePosixPath]:
+        """Find runtime directories DPDK apps are currently using.
+
+        Args:
+              dpdk_prefix_list: The prefixes DPDK apps were started with.
+
+        Returns:
+            The paths of DPDK apps' runtime dirs.
+        """
         prefix = PurePosixPath("/var", "run", "dpdk")
         if not dpdk_prefix_list:
             remote_prefixes = self._list_remote_dirs(prefix)
@@ -164,9 +199,13 @@ def _get_dpdk_runtime_dirs(self, dpdk_prefix_list: Iterable[str]) -> list[PurePo
         return [PurePosixPath(prefix, dpdk_prefix) for dpdk_prefix in dpdk_prefix_list]
 
     def _list_remote_dirs(self, remote_path: str | PurePath) -> list[str] | None:
-        """
-        Return a list of directories of the remote_dir.
-        If remote_path doesn't exist, return None.
+        """Contents of remote_path.
+
+        Args:
+            remote_path: List the contents of this path.
+
+        Returns:
+            The contents of remote_path. If remote_path doesn't exist, return None.
         """
         out = self.send_command(f"ls -l {remote_path} | awk '/^d/ {{print $NF}}'").stdout
         if "No such file or directory" in out:
@@ -175,6 +214,17 @@ def _list_remote_dirs(self, remote_path: str | PurePath) -> list[str] | None:
             return out.splitlines()
 
     def _get_dpdk_pids(self, dpdk_runtime_dirs: Iterable[str | PurePath]) -> list[int]:
+        """Find PIDs of running DPDK apps.
+
+        Look at each "config" file found in dpdk_runtime_dirs and find the PIDs of processes
+        that opened those file.
+
+        Args:
+            dpdk_runtime_dirs: The paths of DPDK apps' runtime dirs.
+
+        Returns:
+            The PIDs of running DPDK apps.
+        """
         pids = []
         pid_regex = r"p(\d+)"
         for dpdk_runtime_dir in dpdk_runtime_dirs:
@@ -193,6 +243,14 @@ def _remote_files_exists(self, remote_path: PurePath) -> bool:
         return not result.return_code
 
     def _check_dpdk_hugepages(self, dpdk_runtime_dirs: Iterable[str | PurePath]) -> None:
+        """Check there aren't any leftover hugepages.
+
+        If any hugepages are found, emit a warning. The hugepages are investigated in the
+        "hugepage_info" file of dpdk_runtime_dirs.
+
+        Args:
+            dpdk_runtime_dirs: The paths of DPDK apps' runtime dirs.
+        """
         for dpdk_runtime_dir in dpdk_runtime_dirs:
             hugepage_info = PurePosixPath(dpdk_runtime_dir, "hugepage_info")
             if self._remote_files_exists(hugepage_info):
@@ -208,9 +266,11 @@ def _remove_dpdk_runtime_dirs(self, dpdk_runtime_dirs: Iterable[str | PurePath])
             self.remove_remote_dir(dpdk_runtime_dir)
 
     def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
+        """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
         return ""
 
     def get_compiler_version(self, compiler_name: str) -> str:
+        """Overrides :meth:`~.os_session.OSSession.get_compiler_version`."""
         match compiler_name:
             case "gcc":
                 return self.send_command(
@@ -228,6 +288,7 @@ def get_compiler_version(self, compiler_name: str) -> str:
                 raise ValueError(f"Unknown compiler {compiler_name}")
 
     def get_node_info(self) -> NodeInfo:
+        """Overrides :meth:`~.os_session.OSSession.get_node_info`."""
         os_release_info = self.send_command(
             "awk -F= '$1 ~ /^NAME$|^VERSION$/ {print $2}' /etc/os-release",
             SETTINGS.timeout,
-- 
2.34.1