# 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.commandimportCommandfromtypingimportOptional
[docs]classGet_lstat:""" A class to encapsulate the functionality of lstat for getting builtin attributes using SFTP lstat in Unix-like operating systems. Unlike stat, lstat returns attributes of symlinks themselves rather than their targets. Attributes: file_path (str): The path of the builtin to get attributes for. **Examples:** .. code:: python yield Get_lstat(file_path="/path/to/symlink.txt") Usage: This class is designed to be used in a generator-based workflow where commands are yielded for execution. The builtin attributes for each host will be returned in the operation result. Notes: The operation will execute on all hosts in the current execution context. Unlike stat, lstat returns attributes of symlinks themselves rather than the builtin they point to. """def__init__(self,path:str):self.path=pathdef__repr__(self):returnf"Get_lstat(file_path={self.path!r})"@staticmethoddef_sftp_attrs_to_dict(attrs):"""Convert SFTPAttrs object to a JSON-serializable dictionary"""ifattrsisNone:returnNoneresult={}# Add all available attributesifhasattr(attrs,'size')andattrs.sizeisnotNone:result['size']=attrs.sizeifhasattr(attrs,'permissions')andattrs.permissionsisnotNone:result['permissions']=oct(attrs.permissions)# Convert to octal stringifhasattr(attrs,'uid')andattrs.uidisnotNone:result['uid']=attrs.uidifhasattr(attrs,'gid')andattrs.gidisnotNone:result['gid']=attrs.gidifhasattr(attrs,'atime')andattrs.atimeisnotNone:result['atime']=attrs.atimeifhasattr(attrs,'mtime')andattrs.mtimeisnotNone:result['mtime']=attrs.mtimeifhasattr(attrs,'nlink')andattrs.nlinkisnotNone:result['nlink']=attrs.nlinkifhasattr(attrs,'type')andattrs.typeisnotNone:result['type']=str(attrs.type)ifhasattr(attrs,'extended')andattrs.extendedisnotNone:result['extended']=dict(attrs.extended)ifattrs.extendedelse{}returnresult@staticmethodasyncdef_get_lstat_callback(host_info,global_info,command,cp,caller):"""Static callback method for getting builtin status using lstat"""asyncwithasyncssh.connect(**host_info)asconn:asyncwithconn.start_sftp_client()assftp:# Check if the path is providedifcaller.path:# Use lstat instead of stat to get symlink attributeslstat_result=awaitsftp.lstat(caller.path)# Convert SFTPAttrs to dictionary for JSON serializationreturncaller._sftp_attrs_to_dict(lstat_result)else:raiseValueError("Path must be provided for lstat operation")defexecute(self):r=yieldCommand(f"{self}",local=True,callback=self._get_lstat_callback,caller=self)r.executed=Truer.changed=Falsereturnr