1import posixpath
2
3from ftplib import error_perm, FTP
4from posixpath import dirname
5
6
7def ftp_makedirs_cwd(ftp, path, first_call=True):
8    """Set the current directory of the FTP connection given in the ``ftp``
9    argument (as a ftplib.FTP object), creating all parent directories if they
10    don't exist. The ftplib.FTP object must be already connected and logged in.
11    """
12    try:
13        ftp.cwd(path)
14    except error_perm:
15        ftp_makedirs_cwd(ftp, dirname(path), False)
16        ftp.mkd(path)
17        if first_call:
18            ftp.cwd(path)
19
20
21def ftp_store_file(
22        *, path, file, host, port,
23        username, password, use_active_mode=False, overwrite=True):
24    """Opens a FTP connection with passed credentials,sets current directory
25    to the directory extracted from given path, then uploads the file to server
26    """
27    with FTP() as ftp:
28        ftp.connect(host, port)
29        ftp.login(username, password)
30        if use_active_mode:
31            ftp.set_pasv(False)
32        file.seek(0)
33        dirname, filename = posixpath.split(path)
34        ftp_makedirs_cwd(ftp, dirname)
35        command = 'STOR' if overwrite else 'APPE'
36        ftp.storbinary(f'{command} {filename}', file)
37        file.close()
38