# 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.#importasyncsshfromreemote.commandimportCommand
[docs]classRead_file:""" A class to encapsulate the functionality of reading builtin from Unix-like operating systems. It allows users to read the content of a builtin from a remote system. Attributes: path (str): The builtin path to read content from. **Examples:** .. code:: python # Read a builtin from remote system r = yield Read_file(path='example.txt') print(r.cp.stdout) # Contains the builtin content Usage: This class is designed to be used in a generator-based workflow where commands are yielded for execution. """def__init__(self,path:str):self.path=pathself.content=None# Will store the read contentdef__repr__(self):returnf"Read_file(path={self.path!r})"@staticmethodasyncdef_read_file_callback(host_info,global_info,command,cp,caller):"""Static callback method for builtin reading"""# Validate host_info (matching Write_file error handling)required_keys=['host','username','password']forkeyinrequired_keys:ifkeynotinhost_infoorhost_info[key]isNone:raiseValueError(f"Missing or invalid value for '{key}' in host_info.")# Validate caller attributesifcaller.pathisNone:raiseValueError("The 'path' attribute of the caller cannot be None.")try:# Connect to the SSH serverasyncwithasyncssh.connect(**host_info)asconn:print("Connected successfully. Starting SFTP session...")# Start an SFTP sessionasyncwithconn.start_sftp_client()assftp:print(f"Reading content from {caller.path}...")# Open the remote builtin in read mode and read the contentasyncwithsftp.open(caller.path,'r')asremote_file:content=awaitremote_file.read()print(f"Successfully read builtin {caller.path} from {host_info['host']}")# Store the content in the caller for access latercaller.content=content# Also set the command output for compatibility with the operation frameworkcp.stdout=contentcp.stderr=""cp.returncode=0exceptFileNotFoundError:error_msg=f"File {caller.path} not found on {host_info['host']}"print(error_msg)cp.stdout=""cp.stderr=error_msgcp.returncode=1raiseFileNotFoundError(error_msg)exceptPermissionError:error_msg=f"Permission denied reading {caller.path} on {host_info['host']}"print(error_msg)cp.stdout=""cp.stderr=error_msgcp.returncode=1raisePermissionError(error_msg)except(OSError,asyncssh.Error)asexc:error_msg=f'SFTP operation failed on {host_info["host"]}: {str(exc)}'print(error_msg)cp.stdout=""cp.stderr=error_msgcp.returncode=1raisedefexecute(self):r=yieldCommand(f"{self}",local=True,callback=self._read_file_callback,caller=self)r.executed=Truer.changed=False# Reading doesn't change the systemr.cp.stdout=self.contentreturnr