=================================
**Enhancements**
- 76: python 3.x porting.
- 198: full unicode support (RFC-2640).
- 203: asyncore IO loop has been rewritten from scratch and now supports
epoll() on Linux and kqueue() on OSX/BSD.
Also select() (Windows) and poll() pollers have been rewritten
resulting in pyftpdlib being an order of magnitude faster and more
scalable than ever.
- 204: a new FilesystemError exception class is available in order send
custom error strings to client from an AbstracteFS subclass.
- 207: added on_connect() and on_disconnect() callback methods to FTPHandler
class.
- 212: provided two new classes:
Logging_managementpyftpdlib.servers.ThreadedFTPServer and
pyftpdlib.servers.MultiprocessFTPServer (POSIX only).
They can be used to change the base async-based concurrecy model and
use a multiple threads / processes based approach instead.
Your FTPHandler subclasses will finally be free to block! ;)
- 219: it is not possible to instantiate different FPTS classes using
different SSL certificates.
- 213: DummyAuthorizer.validate_authentication() has changed in that it
no longer returns a bool but instead raises AuthenticationFailed()
exception to signal a failed authentication.
This has been done in order allow customized error messages on failed
auth. Also it now expects a third 'handler' argument which is passed in
order to allow IP-based authentication logic. Existing code overriding
validate_authentication() must be changed in accordance.
- 223: ftpserver.py has been split in submodules.
- 225: logging module is now used for logging. ftpserver.py's log(), logline()
and logerror() functions are deprecated.
- 231: FTPHandler.ftp_* methods implementing filesystem-related commands
now return a meaningful value on success (tipically the path name).
- 234: FTPHandler and DTPHandler class provide a nice __repr__.
- 235: FTPServer.serve_forever() has a new handle_exit parameter which
can be set to False in order to avoid handling SIGTERM/SIGINT signals
and logging server start and stop.
- 236: big logging refactoring; by default only useful messages are logged
(as opposed to *all* commands and responses exchanged by client and
server). Also, FTPHandler has a new 'log_prefix' attribute which can
be used to format every line logged.
**Bug fixes**
- 131: IPv6 dual-stack support was broken.
- 206: can't change directory (CWD) when using UnixAuthorizer and process
cwd is == "/root".
- 211: pyftpdlib doesn't work if deprecated py-sendfile 1.2.4 module is
installed.
- 215: usage of FTPHandler.sleeping attribute could lead to 100% CPU usage.
FTPHandler.sleeping is now removed. self.add_channel() /
self.del_channel() should be used instead.
- 222: an unhandled exception in handle_error() or close() can cause server
to crash.
- 229: backslashes on UNIX are not handled properly.
- 232: hybrid IPv4/IPv6 support is broken. (patch by Claus Klein)
**New modules**
All the code contained in pyftpdlib/ftpserver.py and pyftpdlib/contrib
namespaces has been moved here:
- pyftpdlib.authorizers
- pyftpdlib.filesystems
- pyftpdlib.servers
- pyftpdlib.handlers
- pyftpdlib.log
**New APIs**
- pyftpdlib.authorizers.AuthenticationFailed
- pyftpdlib.filesystems.FilesystemError
- pyftpdlib.servers.ThreadedFTPServer
- pyftpdlib.servers.MultiprocessFTPServer
- pyftpdlib.handlers.FTPHandler's on_connect() and on_disconnect() callbacks.
- pyftpdlib.handlers.FTPHandler.ftp_* methods return a meaningful value on
success.
- FTPServer, FTPHandler, DTPHandler new ioloop attribute.
- pyftpdlib.lib.ioloop.IOLoop class (not supposed to be used directly)
- pyftpdlib.handlers.FTPHandler.log_prefix
**Deprecated name spaces**
- pyftpdlib.ftpserver
- pyftpdlib.contrib.*
**Incompatible API changes**
- All the main classes have been extracted from ftpserver.py and split into sub
modules.
+-------------------------------------+---------------------------------------+
| Before | After |
+=====================================+=======================================+
| pyftpdlib.ftpserver.FTPServer | pyftpdlib.servers.FTPServer |
+-------------------------------------+---------------------------------------+
| pyftpdlib.ftpserver.FTPHandler | pyftpdlib.handlers.FTPHandler |
+-------------------------------------+---------------------------------------+
| pyftpdlib.ftpserver.DTPHandler | pyftpdlib.handlers.DTPHandler |
+-------------------------------------+---------------------------------------+
| pyftpdlib.ftpserver.DummyAuthorizer | pyftpdlib.authorizers.DummyAuthorizer |
+-------------------------------------+---------------------------------------+
| pyftpdlib.ftpserver.AbstractedFS | pyftpdlib.filesystems.AbstractedFS |
+-------------------------------------+---------------------------------------+
Same for pyftpflib.contribs namespace which is deprecated.
+-------------------------------------------------+-----------------------------------------+
| Before | After |
+=================================================+=========================================+
| pyftpdlib.contrib.handlers.TLS_FTPHandler | pyftpdlib.handlers.TLS_FTPHandler |
+-------------------------------------------------+-----------------------------------------+
| pyftpdlib.contrib.authorizers.UnixAuthorizer | pyftpdlib.authorizers.UnixAuthorizer |
+-------------------------------------------------+-----------------------------------------+
| pyftpdlib.contrib.authorizers.WindowsAuthorizer | pyftpdlib.authorizers.WindowsAuthorizer |
+-------------------------------------------------+-----------------------------------------+
| pyftpdlib.contrib.filesystems.UnixFilesystem | pyftpdlib.filesystems.UnixFilesystem |
+-------------------------------------------------+-----------------------------------------+
Both imports from pyftpdlib.ftpserver and pyftpdlib.contrib.* will still work
though and will raise a DeprecationWarning exception.
**Other incompatible API changes**
- DummyAuthorizer.validate_authentication() signature has changed. A third
'handler' argument is now expected.
- DummyAuthorizer.validate_authentication() is no longer expected to return a
bool. Instead it is supposed to raise AuthenticationFailed(msg) in case of
failed authentication and return None otherwise.
(see issue 213)
- ftpserver.py's log(), logline() and logerror() functions are deprecated.
logging module is now used instead. See:
https://pyftpdlib.readthedocs.io/en/latest/tutorial.html#logging-management
- Unicode is now used instead of bytes pretty much everywhere.
- FTPHandler.__init__() and TLS_FTPHandler.__init__() signatures have changed:
from __init__(conn, server)
to __init__(conn, server, ioloop=None)
- FTPServer.server_forever() signature has changed:
from serve_forever(timeout=1.0, use_poll=False, count=None)
to serve_forever(timeout=1.0, blocking=True, handle_exit=True)
- FTPServer.close_all() signature has changed:
from close_all(ignore_all=False)
to close_all()
- FTPServer.serve_forever() and FTPServer.close_all() are no longer class
methods.
- asyncore.dispatcher and asynchat.async_chat classes has been replaced by:
pyftpdlib.ioloop.Acceptor
pyftpdlib.ioloop.Connector
pyftpdlib.ioloop.AsyncChat
Any customization relying on asyncore (e.g. use of asyncore.socket_map to
figure out the number of connected clients) will no longer work.
- pyftpdlib.ftpserver.CallLater and pyftpdlib.ftpserver.CallEvery are
deprecated. Instead, use self.ioloop.call_later() and self.ioloop.call_every()
from within the FTPHandler. Also delay() method of the returned object has
been removed.
- FTPHandler.sleeping attribute is removed. self.add_channel() and
self.del_channel() should be used to pause and restart the handler.
**Minor incompatible API changes**
- FTPHandler.respond(resp) -> FTPHandler.respond(resp, logfun=logger.debug)
- FTPHandler.log(resp) -> FTPHandler.log(resp, logfun=logger.info)
- FTPHandler.logline(resp) -> FTPHandler.logline(resp, logfun=logger.debug)