# Copyright (c) 2025 Kim Jarvis TPF Software Services S.A. kim.jarvis@tpfsystems.com # This software is licensed under the MIT License. See the LICENSE file for details.#fromreemote.operations.server.shellimportShellfromreemote.executeimportexecute
[docs]defparse_dnf_list_installed(output):"""Parses the output of 'dnf list installed' into a structured list. This function processes the raw string output from commands like `dnf list installed` or `yum list installed`. It extracts the package name and version for each entry, producing a clean, structured list. Key transformations include: - Skipping header lines (e.g., "Installed Packages") and empty lines. - Handling package names that may contain spaces. - Identifying the version by locating the repository field, which starts with an '@' symbol, to reliably separate it from the name. - Assembling a list of dictionaries, each with 'name' and 'version' keys. Args: output (str): The raw standard output from the dnf/yum command. Returns: list[dict]: A list of dictionaries, where each dictionary represents an installed package and contains 'name' and 'version' keys. """packages=[]lines=output.strip().splitlines()# Skip header line(s) - look for first line that doesn't start with "Installed"start_processing=Falseforlineinlines:line=line.strip()ifnotline:continueifline.startswith("Installed Packages"):start_processing=Truecontinueifnotstart_processing:continue# Split line by whitespace, but we need to be careful because name and version can have spaces# The format is: NAME VERSION REPO# We know repo starts with @, so we can find the last field that starts with @parts=line.split()iflen(parts)<3:continue# Find the index where the repo (starting with @) beginsrepo_index=-1foriinrange(len(parts)-1,-1,-1):ifparts[i].startswith('@'):repo_index=ibreakifrepo_index==-1:continue# Version is the part just before the repoversion=parts[repo_index-1]# Name is everything from the start up to (but not including) the versionname_parts=parts[:repo_index-1]name=' '.join(name_parts)iflen(name_parts)>1elsename_parts[0]packages.append({"name":name,"version":version})returnpackages
[docs]classGet_packages:""" Returns a dictionary of installed packages. **Examples:** .. code:: python yield Get_packages() """defexecute(self):fromreemote.operations.server.shellimportShellr=yieldShell("yum list installed")r.cp.stdout=parse_dnf_list_installed(r.cp.stdout)