On Wed, Dec 28, 2016 at 3:57 PM, Ivan Pozdeev <v...@mail.mipt.ru> wrote:

> On 25.12.2016 17:21, Giampaolo Rodola' wrote:
>
> From what I understand the problem should be fixed in urllib so that it
> always closes the FTP connection. I understand this is what happens in
> recent 3.x versions but not on 2.7.
>
> urllib in 2.7 should indeed be fixed to close FTP connections rather than
> leave them dangling, no question about that.
>

To me it looks like this is the only issue (currently tracked in
http://bugs.python.org/issue28931).


> I tried to fix urllib so that it's guaranteed to call voidresp(), and
> failed. Too complicated, effectively reimplementing a sizable part of FTP
> client logic is required, perhaps even monkey-patching ftplib to be able to
> set flags in the right places.
>

Why did you fail? Why urllib can't close() -> voidresp() the FTP session
once it's done with it?


> With simple commands (voidcmd) and self-contained transfer commands
> (retrlines/retrbinary), ftplib does incapsulate statefulness, by handling
> them atomically. But with transfercmd(), it returns control to the user
> halfway through.
>

That's by design. ftplib's transfercmd() just works like that: it's a low
level method returning a "data" socket and it's just up to you to cleanly
close the session (close() -> voidresp()) once you're done with it. Most of
the times you don't even want to use transfercmd() in the first place, as
you just use stor* and retr* methods.


> At this point, if ftplib doesn't itself keep track that the control
> connection is currently in invalid state for the next command, the user is
> forced to do that themselves instead.
>

Hence why I suggested a docfix.


> And guess what - urllib has to use ftplib through a wrapper class that
> does exactly that. That's definitely a "stock logic part" 'cuz it's an
> integral part of FTP rather than something specific to user logic.
>

That wrapper should just cleanly close the session.


> The other "stock logic part" currently missing is error handling during
> transfer. If the error's cause is local (like a local exception that
> results in closing the data socket prematurely, or the user closing it by
> hand, or an ABOR they sent midway), the error code from the end-of-transfer
> response should be ignored, otherwise, it shouldn't.
>

Absolutely not. Base ftplib should NOT take any deliberate decision such as
ignoring an error.
I can even come up with use cases: use ftplib to test FTP servers so that
they *do* reply with an error code in certain conditions. Here's a couple
examples in pyftpdlib:

https://github.com/giampaolo/pyftpdlib/blob/17bebe3714752b01e43ab60d2771308f4594bd99/pyftpdlib/test/test_functional.py#L1354-L1369

https://github.com/giampaolo/pyftpdlib/blob/17bebe3714752b01e43ab60d2771308f4594bd99/pyftpdlib/test/test_functional.py#L1973-L1980


> Other than making ftplib keep track of the session's internal state while
> the user has control and providing the custom error handling logic to them,
> another solution is to never release control to the user midway, i.e. ban
> transfercmd() entirely and only provide self-contained
> retr*()/dir()/whatever, but let the callback signal them to abort the
> transfer. That way, the state would be kept implicitly - in the execution
> pointer.
>

Banning transfercmd() means renaming it to _transfercmd() which is a no-no
for backward compatibility. Also, as I've shown above, transfercmd() does
have a use case which relies on it behaving like that (return control
midway).


-- 
Giampaolo - http://grodola.blogspot.com
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to