[docs]classFTP(Application[Data_FTP,Schema_FTP],data=Data_FTP,schema=Schema_FTP):"""This class implements File Transfer Protocol."""########################################################################### Properties.##########################################################################@propertydefname(self)->'Literal["File Transfer Protocol"]':"""Name of current protocol."""return'File Transfer Protocol'@propertydeflength(self)->'NoReturn':"""Header length of current protocol. Raises: UnsupportedCall: This protocol doesn't support :attr:`length`. """raiseUnsupportedCall(f"'{self.__class__.__name__}' object has no attribute 'length'")########################################################################### Methods.##########################################################################
[docs]defread(self,length:'Optional[int]'=None,**kwargs:'Any')->'Data_FTP':# pylint: disable=unused-argument"""Read File Transfer Protocol (FTP). Args: length: Length of packet data. **kwargs: Arbitrary keyword arguments. Returns: Parsed packet data. Raises: ProtocolError: If the packet is malformed. """iflengthisNone:length=len(self)schema=self.__header__data=schema.dataif(match:=FTP_REQUEST.match(data))isnotNone:cmmd=match.group('cmmd').decode()args=match.group('args')cmmd_val=Enum_Command.get(cmmd)args_val=self.decode(args)ftp=Data_Request(type=Type.REQUEST,cmmd=cmmd_val,args=args_val,)# type: Data_FTPelif(match:=FTP_RESPONSE.match(data))isnotNone:code=int(match.group('code'))more=bool(match.group('more'))args=match.group('args')code_val=Enum_ReturnCode.get(code)args_val=self.decode(args)ftp=Data_Response(type=Type.RESPONSE,code=code_val,more=more,args=args_val,)else:raiseProtocolError('FTP: invalid packet format')returnftp
[docs]defmake(self,cmmd:'Optional[Enum_Command | str | bytes]'=None,code:'Optional[Enum_ReturnCode | int | str | bytes]'=None,args:'Optional[str | bytes]'=None,more:'bool'=False,**kwargs:'Any')->'Schema_FTP':"""Make (construct) packet data. Args: cmmd: FTP command. code: FTP status code. args: Optional FTP command arguments and/or status messages. more: More status messages to follow for response packets. **kwargs: Arbitrary keyword arguments. Returns: Constructed packet data. """ifcmmdisnotNoneandcodeisNone:ifisinstance(cmmd,bytes):prefix=cmmdelifisinstance(cmmd,str):prefix=cmmd.encode()else:prefix=cmmd.valuemf=b''elifcmmdisNoneandcodeisnotNone:code_val=int(code)prefix=str(code_val).encode()mf=b'-'ifmoreelseb''else:raiseProtocolError('FTP: invalid packet type')ifargsisNone:suffix=b''elifisinstance(args,bytes):suffix=argselse:suffix=args.encode()returnSchema_FTP(data=b'%s%s%s'%(prefix,mf,suffix),)
[docs]@classmethoddef_make_data(cls,data:'Data_FTP')->'dict[str, Any]':# type: ignore[override]"""Create key-value pairs from ``data`` for protocol construction. Args: data: protocol data Returns: Key-value pairs for protocol construction. """return{'cmmd':getattr(data,'cmmd',None),'code':getattr(data,'code',None),'args':getattr(data,'args',None),'more':getattr(data,'more',False),}
[docs]classFTP_DATA(Raw):"""This class implements FTP data channel transmission."""########################################################################### Properties.########################################################################### name of current protocol@propertydefname(self)->'Literal["FTP_DATA"]':# type: ignore[override]"""Name of current protocol."""return'FTP_DATA'