giampaolo / pyftpdlib

Extremely fast and scalable Python FTP server library
MIT License
1.65k stars 266 forks source link

feat: support use with statement to create a ftpserver temporarily #567

Open ramwin opened 2 years ago

ramwin commented 2 years ago

@giampaolo the continuous-integration test failed. But the log shows that this is caused by pyftpdlib.test.test_servers.TestCornerCasesThreadMixin.test_quick_connect. I think it's not caused by my code. Could you review this pull request when you have spare time?

ramwin commented 2 years ago

@giampaolo , Please review this pull request when you have any free time. Thanks a lot.

gliptak commented 1 year ago

consider rerunning with current CI

ramwin commented 1 year ago

Hello, @gliptak . I rebase my branch onto the master branch. Review this pull request again when you are free.

giampaolo commented 1 year ago

I don't think this is necessary (or at least not in this form). Do you need this to have a test FTP server to connect to during unit tests? If that's the case, then I think it may make more sense to add __enter__ / __exit__ to the test FTP server class: https://github.com/giampaolo/pyftpdlib/blob/278466048b5f1612ba178b35243925be2e6717ac/pyftpdlib/test/__init__.py#L430

ramwin commented 1 year ago

I have a simple script that need to start a ftpserver and call other web service to connect the ftpserver. It was inconvinent to first start a ftpserver and than run the simple script. I want to achieve this using with statement

with FtpServer(ftpusername, ftppassword) as tmp_ftpserver:
    requests.post("http://otherserver/download", json={
        ftpusername, ftppassword, filepath
    })

after the script, the ftpserver can be closed automatically.

ramwin commented 1 year ago

Other wise, I will have to open two terminal.

First terminal

python -m ftpdlib --username=admin --password

Second terminal

python3 main.py

and I can only stop the ftpserver after the main script finished.

giampaolo commented 1 year ago

I forgot I added it, but FTPServer class already supports the context manager protocol: https://github.com/giampaolo/pyftpdlib/commit/327f3e0 That is different than your context manager though: on __enter__ it does NOT automatically call server_forever() in a thread.

ramwin commented 1 year ago

I forgot I added it, but FTPServer class already supports the context manager protocol: 327f3e0 That is different than your context manager though: on __enter__ it does NOT automatically call server_forever() in a thread.

The function automatically call server_forever() in a thread is what I really want. That's why I create the FTPServerContext. I want to create a ftpserver temporally and use it in afterword scripts.

ramwin commented 1 year ago

I tried use the blocking=False parameter, It didn't work as I wanted. My code looks like this:

with FTPServer(("localhost", 2121), handler) as f:
    f.serve_forever(blocking=False)
    print("start success")
    with FTP() as ftp:
        ftp.connect(host='localhost', port=2121)
        ftp.login()
        print(ftp.dir())

there is no start success printed on the screen, neither will the later code been executed.