import ftplib import posixpath from typing import AsyncIterator from async_generator import aclosing from ._aftplib import AFTP async def download_text(server: str, user: str, password: str, path: str, encoding='cp1252', n_attempts: int = 10) -> AsyncIterator[str]: nlines_sent = 0 for attempt in range(n_attempts): ftp = AFTP(server, user, password) await ftp.connect() filename = posixpath.basename(path) path = posixpath.dirname(path) if path: await ftp.cwd(path) nlines_captured = 0 try: async with aclosing(ftp.iretrlines(f"RETR '{filename}'")) as _iterator: async for line in _iterator: nlines_captured += 1 if nlines_captured <= nlines_sent: continue nlines_sent += 1 yield line.decode(encoding) except ftplib.error_temp as e: if '426-Data transfer timeout, aborted' not in e.args[0]: raise else: break else: raise Exception(f'Failed {n_attempts} attempts, cancelling')