36 lines
1.2 KiB
Python
36 lines
1.2 KiB
Python
|
|
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')
|