Permalink
Browse files

merge with master

  • Loading branch information...
giampaolo committed Sep 7, 2017
2 parents d38094b + 4c1b590 commit 85d8254b72e9710d667b52c7d32dd0da69b16dee
Showing with 239 additions and 57 deletions.
  1. +7 −3 .ci/travis/run.sh
  2. +4 −11 .travis.yml
  3. +9 −0 CREDITS
  4. +13 −1 HISTORY.rst
  5. +28 −2 Makefile
  6. +23 −17 README.rst
  7. +3 −3 docs/benchmarks.rst
  8. +3 −6 docs/faqs.rst
  9. +1 −1 docs/tutorial.rst
  10. +0 −2 make.bat
  11. +1 −1 pyftpdlib/__init__.py
  12. +20 −2 pyftpdlib/__main__.py
  13. +8 −5 pyftpdlib/handlers.py
  14. +12 −3 pyftpdlib/test/test_functional_ssl.py
  15. +107 −0 scripts/print_announce.py
View
@@ -12,7 +12,11 @@ fi
python setup.py install
python pyftpdlib/test/runner.py
if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]] || [[ $PYVER == 'py26' ]]; then
exit 0;
# run linter only on Linux and on latest python versions
if [ "$PYVER" == "2.7" ] || [ "$PYVER" == "3.6" ]; then
if [[ "$(uname -s)" != 'Darwin' ]]; then
rm -rf build
python -m flake8
fi
fi
flake8
View
@@ -9,25 +9,18 @@ matrix:
- python: 3.4
- python: 3.5
- python: 3.6
# - language: generic
# os: osx
# env: PYVER=py26
- language: generic
os: osx
env: PYVER=py27
# - language: generic
# os: osx
# env: PYVER=py33
- language: generic
os: osx
env: PYVER=py34
# XXX - not supported yet
# - language: generic
# os: osx
# env: PYVER=py35
install:
- ./.ci/travis/install.sh
script:
- ./.ci/travis/run.sh
after_success:
- coveralls # upload reports to coveralls.io
- |
if [ "$(uname -s)" != 'Darwin' ]; then
coveralls
fi
View
@@ -178,3 +178,12 @@ N: Dmitry Panov
C: UK
E: dop251@gmail.com
D: issue 262
M: PonyPC
W: https://github.com/PonyPC
D: issue 403
N: Tory Law
E: git@torypages.com
C: Canada
D: Command line argument enhancements
View
@@ -1,6 +1,18 @@
Bug tracker at https://github.com/giampaolo/pyftpdlib/issues
Version: 1.6.0 - XXXX-XX-XX
Version: 1.5.3 - XXXX-XX-XX
===========================
**Enhancements**
- #327: add username and password command line options
**Bug fixes**
- #403: fix duplicated output log. (path by PonyPC)
- #414: Respond successfully to STOR only after closing file handle.
Version: 1.5.2 - 2017-04-06
===========================
**Enhancements**
View
@@ -9,7 +9,6 @@ ARGS=
DEPS=coverage \
check-manifest \
flake8 \
ipdb \
mock==1.0.1 \
nose \
pep8 \
@@ -18,7 +17,6 @@ DEPS=coverage \
pysendfile \
setuptools \
sphinx \
sphinx-pypi-upload \
unittest2
# In not in a virtualenv, add --user options for install commands.
@@ -156,3 +154,31 @@ install-git-hooks:
grep-todos:
git grep -EIn "TODO|FIXME|XXX"
# All the necessary steps before making a release.
pre-release:
${MAKE} clean
$(PYTHON) -c \
"from pyftpdlib import __ver__ as ver; \
doc = open('docs/index.rst').read(); \
history = open('HISTORY.rst').read(); \
assert ver in history, '%r not in HISTORY.rst' % ver; \
assert 'XXXX' not in history; \
"
$(PYTHON) setup.py sdist
# Create a release: creates tar.gz, uploads it, git tag release.
release:
${MAKE} pre-release
$(PYTHON) -m twine upload dist/* # upload tar on PYPI
${MAKE} git-tag-release
# Print announce of new release.
print-announce:
@$(PYTHON) scripts/print_announce.py
# generate a doc.zip file and manually upload it to PYPI.
doc:
cd docs && make html && cd _build/html/ && zip doc.zip -r .
mv docs/_build/html/doc.zip .
@echo "done; now manually upload doc.zip from here: https://pypi.python.org/pypi?:action=pkg_edit&name=pyftpdlib"
View
@@ -1,26 +1,30 @@
.. image:: https://img.shields.io/pypi/dm/pyftpdlib.svg
:target: https://pypi.python.org/pypi/pyftpdlib/
:alt: Download this month
.. image:: https://img.shields.io/travis/giampaolo/pyftpdlib/master.svg?maxAge=3600&label=Linux%20/%20OSX
:target: https://travis-ci.org/giampaolo/pyftpdlib
:alt: Linux tests (Travis)
.. image:: https://img.shields.io/pypi/v/pyftpdlib.svg
:target: https://pypi.python.org/pypi/pyftpdlib/
:alt: Latest version
.. image:: https://img.shields.io/appveyor/ci/giampaolo/pyftpdlib/master.svg?maxAge=3600&label=Windows
:target: https://ci.appveyor.com/project/giampaolo/pyftpdlib
:alt: Windows tests (Appveyor)
.. image:: https://img.shields.io/pypi/l/pyftpdlib.svg
:target: https://pypi.python.org/pypi/pyftpdlib/
:alt: License
.. image:: https://coveralls.io/repos/github/giampaolo/pyftpdlib/badge.svg?branch=master
:target: https://coveralls.io/github/giampaolo/pyftpdlib?branch=master
:alt: Test coverage (coverall.io)
.. image:: https://readthedocs.org/projects/pyftpdlib/badge/?version=latest
:target: http://pyftpdlib.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: https://img.shields.io/travis/giampaolo/pyftpdlib/master.svg
:target: https://travis-ci.org/giampaolo/pyftpdlib
:alt: Travis
.. image:: https://img.shields.io/pypi/v/pyftpdlib.svg?label=pypi
:target: https://pypi.python.org/pypi/pyftpdlib/
:alt: Latest version
.. image:: https://coveralls.io/repos/giampaolo/pyftpdlib/badge.svg?branch=master&service=github
:target: https://coveralls.io/github/giampaolo/pyftpdlib?branch=master
:alt: Test coverage (coverall.io)
.. image:: https://img.shields.io/github/stars/giampaolo/pyftpdlib.svg
:target: https://github.com/giampaolo/pyftpdlib/
:alt: Github stars
.. image:: https://img.shields.io/pypi/l/pyftpdlib.svg
:target: https://pypi.python.org/pypi/pyftpdlib/
:alt: License
Quick links
===========
@@ -76,12 +80,12 @@ Features
Performances
============
Depite being written in an intepreted language, pyftpdlib has transfer rates
Despite being written in an intepreted language, pyftpdlib has transfer rates
superior to most common UNIX FTP servers. It also scales better since whereas
vsftpd and proftpd use multiple processes to achieve concurrency, pyftpdlib
will only use one process and handle concurrency asynchronously (see
`the C10K problem <http://www.kegel.com/c10k.html>`__). Here are some
`benchmarks <https://github.com/giampaolo/pyftpdlib/blob/master/test/bench.py>`__
`benchmarks <https://github.com/giampaolo/pyftpdlib/blob/master/scripts/ftpbench>`__
made against my Linux 3.0.0 box, Intel core-duo 3.1 Ghz:
pyftpdlib vs. proftpd 1.3.4
@@ -185,6 +189,8 @@ software to the
Timeline
========
- 2017-04-06: version `1.5.2 <https://pypi.python.org/packages/source/p/pyftpdlib/pyftpdlib-1.5.2.tar.gz>`__ released.
- 2016-05-02: version `1.5.1 <https://pypi.python.org/packages/source/p/pyftpdlib/pyftpdlib-1.5.1.tar.gz>`__ released.
- 2015-12-13: version `1.5.0 <https://pypi.python.org/packages/source/p/pyftpdlib/pyftpdlib-1.5.0.tar.gz>`__ released.
- 2014-06-03: version `1.4.0 <https://pypi.python.org/packages/source/p/pyftpdlib/pyftpdlib-1.4.0.tar.gz>`__ released.
- 2014-04-12: version `1.3.1 <https://pypi.python.org/packages/source/p/pyftpdlib/pyftpdlib-1.3.1.tar.gz>`__ released.
View
@@ -259,16 +259,16 @@ The following patch was applied first:
$ sudo python demo/unix_daemon.py
The `benchmark script <https://github.com/giampaolo/pyftpdlib/blob/master/test/bench.py>`__
The `benchmark script <https://github.com/giampaolo/pyftpdlib/blob/master/scripts/ftpbench>`__
was run as:
::
python test/bench.py -u USERNAME -p PASSWORD -b all -n 300
python scripts/ftpbench -u USERNAME -p PASSWORD -b all -n 300
...and for the memory test:
::
python test/bench.py -u USERNAME -p PASSWORD -b all -n 300 -k FTP_SERVER_PID
python scripts/ftpbench -u USERNAME -p PASSWORD -b all -n 300 -k FTP_SERVER_PID
View
@@ -142,16 +142,13 @@ avoid race conditions, dead locks etc.
class MyHandler(FTPHandler):
def on_file_received(self, file):
"""Called every time a file has been received"""
def blocking_task():
time.sleep(5)
self.add_channel()
def blocking_task():
time.sleep(5)
self.add_channel()
self.del_channel()
threading.Thread(target=blocking_task).start()
Another possibility is to
`change the default concurrency model <tutorial.html#changing-the-concurrency-model>`__.
View
@@ -410,7 +410,7 @@ module, which is required in order to run the code below.
`TLS_FTPHandler <api.html#pyftpdlib.handlers.TLS_FTPHandler>`__
class requires at least a ``certfile`` to be specified and optionally a
``keyfile``.
`Apache FAQs <http://www.modssl.org/docs/2.7/ssl*faq.html#ToC24>`__ provide
`Apache FAQs <https://httpd.apache.org/docs/2.4/ssl/ssl_faq.html#selfcert>`__ provide
instructions on how to generate them. If you don't care about having your
personal self-signed certificates you can use the one in the demo directory
which include both and is available
View
@@ -89,8 +89,6 @@ if "%1" == "setup-dev-env" (
@echo ------------------------------------------------
rem mandatory / for unittests
%PYTHON% -m pip install unittest2 ipaddress mock wmi pypiwin32 pyopenssl --upgrade
rem nice to have
rem %PYTHON% -m pip install ipdb nose --upgrade
goto :eof
)
View
@@ -68,6 +68,6 @@ class used to interact with the file system, providing a high level,
"""
__ver__ = '1.6.0'
__ver__ = '1.5.3'
__author__ = "Giampaolo Rodola' <g.rodola@gmail.com>"
__web__ = 'https://github.com/giampaolo/pyftpdlib/'
View
@@ -45,7 +45,7 @@ def main():
parser.add_option('-p', '--port', type="int", default=2121, metavar="PORT",
help="specify port number to run on (default 2121)")
parser.add_option('-w', '--write', action="store_true", default=False,
help="grants write access for the anonymous user "
help="grants write access for logged in user "
"(default read-only)")
parser.add_option('-d', '--directory', default=getcwdu(), metavar="FOLDER",
help="specify the directory to share (default current "
@@ -59,6 +59,15 @@ def main():
help="enable DEBUG logging evel")
parser.add_option('-v', '--version', action='store_true',
help="print pyftpdlib version and exit")
parser.add_option('-V', '--verbose', action='store_true',
help="activate a more verbose logging")
parser.add_option('-u', '--username', type=str, default=None,
help="specify username to login with (anonymous login "
"will be disabled and password required "
"if supplied)")
parser.add_option('-P', '--password', type=str, default=None,
help="specify a password to login with (username "
"required to be useful)")
options, args = parser.parse_args()
if options.version:
@@ -84,7 +93,16 @@ def main():
authorizer = DummyAuthorizer()
perm = options.write and "elradfmwM" or "elr"
authorizer.add_anonymous(options.directory, perm=perm)
if options.username:
if not options.password:
parser.error(
"if username (-u) is supplied, password ('-P') is required")
authorizer.add_user(options.username,
options.password,
options.directory,
perm=perm)
else:
authorizer.add_anonymous(options.directory, perm=perm)
handler = FTPHandler
handler.authorizer = authorizer
handler.masquerade_address = options.nat_address
View
@@ -406,7 +406,7 @@ def handle_accepted(self, sock, addr):
def handle_timeout(self):
if self.cmd_channel.connected:
self.cmd_channel.respond("421 Passive data channel timed out.",
logfun=logging.info)
logfun=logger.info)
self.close()
def handle_error(self):
@@ -872,11 +872,14 @@ def close(self):
if not self._closed:
# RFC-959 says we must close the connection before replying
AsyncChat.close(self)
if self._resp:
self.cmd_channel.respond(self._resp[0], logfun=self._resp[1])
# Close file object before responding successfully to client
if self.file_obj is not None and not self.file_obj.closed:
self.file_obj.close()
if self._resp:
self.cmd_channel.respond(self._resp[0], logfun=self._resp[1])
if self._idler is not None and not self._idler.cancelled:
self._idler.cancel()
if self.file_obj is not None:
@@ -2439,7 +2442,7 @@ def ftp_ABOR(self, line):
self.data_channel.close()
self.data_channel = None
self.respond("426 Transfer aborted via ABOR.",
logfun=logging.info)
logfun=logger.info)
resp = "226 ABOR command successful."
else:
self.data_channel.close()
@@ -2466,7 +2469,7 @@ def ftp_USER(self, line):
# login sequence again.
self.flush_account()
msg = 'Previous account information was flushed'
self.respond('331 %s, send password.' % msg, logfun=logging.info)
self.respond('331 %s, send password.' % msg, logfun=logger.info)
self.username = line
def handle_auth_failed(self, msg, password):
@@ -15,6 +15,7 @@
from pyftpdlib.handlers import TLS_FTPHandler
from pyftpdlib.test import configure_logging
from pyftpdlib.test import OSX
from pyftpdlib.test import PASSWD
from pyftpdlib.test import remove_test_files
from pyftpdlib.test import ThreadedTestFTPd
@@ -359,6 +360,8 @@ def try_protocol_combo(self, server_protocol, client_protocol):
# for proto in protos:
# self.try_protocol_combo(ssl.PROTOCOL_TLSv1, proto)
# On OSX TLS_FTPHandler.get_ssl_context()._context does not exist.
@unittest.skipIf(OSX, "can't get options on OSX")
def test_ssl_options(self):
from OpenSSL import SSL
from OpenSSL._util import lib
@@ -393,9 +396,15 @@ def test_ssl_options(self):
def test_sslv2(self):
self.client.ssl_version = ssl.PROTOCOL_SSLv2
self.client.close()
with self.server.lock:
self.client.connect(self.server.host, self.server.port)
self.assertRaises(socket.error, self.client.login)
if not OSX:
with self.server.lock:
self.client.connect(self.server.host, self.server.port)
self.assertRaises(socket.error, self.client.login)
else:
with self.server.lock:
with self.assertRaises(socket.error):
self.client.connect(self.server.host, self.server.port,
timeout=0.1)
self.client.ssl_version = ssl.PROTOCOL_SSLv2
Oops, something went wrong.

0 comments on commit 85d8254

Please sign in to comment.