New Upstream Snapshot - pysendfile

Ready changes

Summary

Merged new upstream version: 2.0.1+git20210730.2.2ffdd45 (was: 2.0.1+git20210730.1.2ffdd45).

Resulting package

Built on 2022-12-18T17:50 (took 4m34s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots python3-sendfile-dbgsymapt install -t fresh-snapshots python3-sendfile

Lintian Result

Diff

diff --git a/.ci/travis/README b/.ci/travis/README
new file mode 100644
index 0000000..a2179f0
--- /dev/null
+++ b/.ci/travis/README
@@ -0,0 +1,2 @@
+This directory contains support files for Travis, a continuous integration
+service which runs tests on Linux and OSX on every GIT commit.
diff --git a/.ci/travis/install.sh b/.ci/travis/install.sh
new file mode 100755
index 0000000..6d6f874
--- /dev/null
+++ b/.ci/travis/install.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+set -e
+set -x
+
+uname -a
+python -c "import sys; print(sys.version)"
+
+if [[ "$(uname -s)" == 'Darwin' ]]; then
+    brew update || brew update
+    brew outdated pyenv || brew upgrade pyenv
+    brew install pyenv-virtualenv
+
+    if which pyenv > /dev/null; then
+        eval "$(pyenv init -)"
+    fi
+
+    case "${PYVER}" in
+        # py26)
+        #     pyenv install 2.6.9
+        #     pyenv virtualenv 2.6.9 pysendfile
+        #     ;;
+        py27)
+            pyenv install 2.7.10
+            pyenv virtualenv 2.7.10 pysendfile
+            ;;
+        # py32)
+        #     pyenv install 3.2.6
+        #     pyenv virtualenv 3.2.6 pysendfile
+        #     ;;
+        # py33)
+        #     pyenv install 3.3.6
+        #     pyenv virtualenv 3.3.6 pysendfile
+        #     ;;
+        py34)
+            pyenv install 3.4.3
+            pyenv virtualenv 3.4.3 pysendfile
+            ;;
+        py36)
+            pyenv install 3.6.6
+            pyenv virtualenv 3.6.6 pysendfile
+            ;;
+    esac
+    pyenv rehash
+    pyenv activate pysendfile
+fi
+
+if [[ $TRAVIS_PYTHON_VERSION == '2.5' ]]; then pip install unittest2; fi
+if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi
+pip install flake8
+python setup.py build
+python setup.py install
diff --git a/.ci/travis/run.sh b/.ci/travis/run.sh
new file mode 100755
index 0000000..eb92ee8
--- /dev/null
+++ b/.ci/travis/run.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -e
+set -x
+
+if [[ "$(uname -s)" == 'Darwin' ]]; then
+    if which pyenv > /dev/null; then
+        eval "$(pyenv init -)"
+    fi
+    pyenv activate pysendfile
+fi
+
+python setup.py build
+python setup.py develop
+python test/test_sendfile.py
+flake8
diff --git a/.travis.yml b/.travis.yml
index ebc45e8..623ff2f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,21 +1,26 @@
+sudo: false
 language: python
-python:
-    - 2.6
-    - 2.7
-    - 3.2
-    - 3.3
-    - 3.4
-    - pypy
+cache: pip
+matrix:
+    include:
+        # Linux
+        - python: 2.7
+        - python: 3.6
+        - python: 3.7
+        - python: 3.8
+        - python: 3.9
+          dist: xenial
+          sudo: true
+        - python: pypy
+        - python: pypy3
+        # OSX
+        - language: generic
+          os: osx
+          env: PYVER=py27
+        - language: generic
+          os: osx
+          env: PYVER=py39
 install:
-    - if [[ $TRAVIS_PYTHON_VERSION == '2.5' ]]; then pip install unittest2; fi
-    - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi
+    - ./.ci/travis/install.sh
 script:
-    - pip install flake8
-    - python setup.py build
-    - python setup.py install
-    - python test/test_sendfile.py
-    - make flake8
-os:
-    - linux
-    - osx
-
+    - ./.ci/travis/run.sh
diff --git a/LICENSE b/LICENSE
index 2df1b74..9d2c3df 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,30 +1,25 @@
-======================================================================
-This software is distributed under the MIT license reproduced below:
+MIT License
 
-Original author:
-    Copyright (C) 2005-2008  Ben Woolley <user tautolog at gmail>
+Copyright (c) 2005-2008  Ben Woolley <user tautolog at gmail> (original author)
 
-AIX support code by:
-    Copyright (C) 2008-2009  Niklas Edmundsson <nikke@acc.umu.se>
+Copyright (c) 2008-2009  Niklas Edmundsson <nikke@acc.umu.se> (AIX support)
 
-Rewritten from scratch and maintained by:
-    Copyright (C) 2009-2014  Giampaolo Rodola' <g.rodola@gmail.com>
+Copyright (c) 2009  Giampaolo Rodola <g.rodola@gmail.com> (rewrite + current maintainer)
 
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that copyright notice and this permission
-notice appear in supporting documentation, and that the name of
-Giampaolo Rodola' not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
 
-Ben Woolley, Niklas Edmundsson and Giampaolo Rodola' DISCLAIM ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
-NO EVENT Giampaolo Rodola' BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-======================================================================
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
index b2ef742..884b6fb 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -7,3 +7,4 @@ include README.rst
 include sendfilemodule.c
 include setup.py
 recursive-include test *.py
+recursive-include .ci *
diff --git a/Makefile b/Makefile
index 137e8ad..df2dd18 100644
--- a/Makefile
+++ b/Makefile
@@ -38,18 +38,15 @@ uninstall:
 test: install
 	$(PYTHON) $(TSCRIPT)
 
-# requires "pip install pep8"
 pep8:
-	@git ls-files | grep \\.py$ | xargs pep8
+	@git ls-files | grep \\.py$ | xargs $(PYTHON) -m pep8
 
-# requires "pip install pyflakes"
 pyflakes:
 	@export PYFLAKES_NODOCTEST=1 && \
-		git ls-files | grep \\.py$ | xargs pyflakes
+		git ls-files | grep \\.py$ | xargs $(PYTHON) -m pyflakes
 
-# requires "pip install flake8"
 flake8:
-	@git ls-files | grep \\.py$ | xargs flake8
+	@git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8
 
 # upload source tarball on https://pypi.python.org/pypi/pysendfile.
 upload-src: clean
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..b080e9a
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,264 @@
+Metadata-Version: 2.1
+Name: pysendfile
+Version: 2.0.1
+Summary: A Python interface to sendfile(2)
+Home-page: https://github.com/giampaolo/pysendfile
+Author: Giampaolo Rodola
+Author-email: g.rodola@gmail.com
+License: MIT
+Keywords: sendfile,python,performance,ftp
+Platform: UNIX
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: POSIX :: BSD
+Classifier: Operating System :: POSIX :: BSD :: FreeBSD
+Classifier: Operating System :: POSIX :: SunOS/Solaris
+Classifier: Operating System :: POSIX :: AIX
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Python :: 2.5
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.0
+Classifier: Programming Language :: Python :: 3.1
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Topic :: System :: Networking
+Classifier: Topic :: System :: Operating System
+Classifier: Topic :: Internet :: File Transfer Protocol (FTP)
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: License :: OSI Approved :: MIT License
+License-File: LICENSE
+
+.. image:: http://pepy.tech/badge/pysendfile
+    :target: http://pepy.tech/project/pysendfile
+    :alt: Downloads
+
+.. image:: https://api.travis-ci.org/giampaolo/pysendfile.png?branch=master
+    :target: https://travis-ci.org/giampaolo/pysendfile
+    :alt: Linux tests (Travis)
+
+.. image:: https://img.shields.io/pypi/v/pysendfile.svg
+    :target: https://pypi.python.org/pypi/pysendfile/
+    :alt: Latest version
+
+.. image:: https://img.shields.io/github/stars/giampaolo/pysendfile.svg
+    :target: https://github.com/giampaolo/pysendfile/
+    :alt: Github stars
+
+.. image:: https://img.shields.io/pypi/l/pysendfile.svg
+    :target: https://pypi.python.org/pypi/pysendfile/
+    :alt: License
+
+=====
+About
+=====
+
+A backport of `os.sendfile() <https://docs.python.org/3/library/os.html#os.sendfile>`__
+for Python 2.6 and 2.7 (see `BPO-10882 <https://bugs.python.org/issue10882>`__).
+
+===========
+Explanation
+===========
+
+`sendfile(2) <http://linux.die.net/man/2/sendfile>`__ is a system call which
+provides a "zero-copy" way of copying data from one file descriptor to another
+(a socket). The phrase "zero-copy" refers to the fact that all of the copying
+of data between the two descriptors is done entirely by the kernel, with no
+copying of data into userspace buffers. This is particularly useful when
+sending a file over a socket (e.g. FTP).
+The normal way of sending a file over a socket involves reading data from the
+file into a userspace buffer, then write that buffer to the socket via
+`send() <http://docs.python.org/library/socket.html#socket.socket.send>`__ or
+`sendall() <http://docs.python.org/library/socket.html#socket.socket.sendall>`__:
+
+.. code-block:: python
+
+    # how a file is typically sent
+
+    import socket
+
+    file = open("somefile", "rb")
+    sock = socket.socket()
+    sock.connect(("127.0.0.1", 8021))
+
+    while True:
+        chunk = file.read(65536)
+        if not chunk:
+            break  # EOF
+        sock.sendall(chunk)
+
+This copying of the data twice (once into the userland buffer, and once out
+from that userland buffer) imposes some performance and resource penalties.
+`sendfile(2) <http://linux.die.net/man/2/sendfile>`__ syscall avoids these
+penalties by avoiding any use of userland buffers; it also results in a single
+system call (and thus only one context switch), rather than the series of
+`read(2) <http://linux.die.net/man/2/read>`__ /
+`write(2) <http://linux.die.net/man/2/write>`__ system calls (each system call
+requiring a context switch) used internally for the data copying.
+
+.. code-block:: python
+
+    import socket
+    import os
+    from sendfile import sendfile
+
+    file = open("somefile", "rb")
+    blocksize = os.path.getsize("somefile")
+    sock = socket.socket()
+    sock.connect(("127.0.0.1", 8021))
+    offset = 0
+
+    while True:
+        sent = sendfile(sock.fileno(), file.fileno(), offset, blocksize)
+        offset += sent
+        if sent == 0:
+            break  # EOF
+
+==================
+A simple benchmark
+==================
+
+This `benchmark script <https://github.com/giampaolo/pysendfile/blob/master/test/benchmark.py>`__
+implements the two examples above and compares plain socket.send() and
+sendfile() performances in terms of CPU time spent and bytes transmitted per
+second resulting in sendfile() being about **2.5x faster**. These are the
+results I get on my Linux 2.6.38 box, AMD dual-core 1.6 GHz:
+
+*send()*
+
++---------------+-----------------+
+| CPU time      | 28.84 usec/pass |
++---------------+-----------------+
+| transfer rate | 359.38 MB/sec   |
++---------------+-----------------+
+
+*sendfile()*
+
++---------------+-----------------+
+| CPU time      | 11.28 usec/pass |
++---------------+-----------------+
+| transfer rate | 860.88 MB/sec   |
++---------------+-----------------+
+
+===========================
+When do you want to use it?
+===========================
+
+Basically any application sending files over the network can take advantage of
+sendfile(2). HTTP and FTP servers are a typical example.
+`proftpd <http://www.proftpd.org/>`__ and
+`vsftpd <https://security.appspot.com/vsftpd.html>`__ are known to use it, so is
+`pyftpdlib <http://code.google.com/p/pyftpdlib/>`__.
+
+=================
+API documentation
+=================
+
+sendfile module provides a single function: sendfile().
+
+- ``sendfile.sendfile(out, in, offset, nbytes, header="", trailer="", flags=0)``
+
+  Copy *nbytes* bytes from file descriptor *in* (a regular file) to file
+  descriptor *out* (a socket) starting at *offset*. Return the number of
+  bytes just being sent. When the end of file is reached return 0.
+  On Linux, if *offset* is given as *None*, the bytes are read from the current
+  position of *in* and the position of *in* is updated.
+  *headers* and *trailers* are strings that are written before and after the
+  data from *in* is written. In cross platform applications their usage is
+  discouraged
+  (`send() <http://docs.python.org/library/socket.html#socket.socket.send>`__ or
+  `sendall() <http://docs.python.org/library/socket.html#socket.socket.sendall>`__
+  can be used instead). On Solaris, *out* may be the file descriptor of a
+  regular file or the file descriptor of a socket. On all other platforms,
+  *out* must be the file descriptor of an open socket.
+  *flags* argument is only supported on FreeBSD.
+
+- ``sendfile.SF_NODISKIO``
+- ``sendfile.SF_MNOWAIT``
+- ``sendfile.SF_SYNC``
+
+  Parameters for the *flags* argument, if the implementation supports it. They
+  are available on FreeBSD platforms. See `FreeBSD's man sendfile(2) <http://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2>`__.
+
+=======================
+Differences with send()
+=======================
+
+- sendfile(2) works with regular (mmap-like) files only (e.g. you can't use it
+  with a `StringIO <https://docs.python.org/2/library/stringio.html>`__ object).
+- Also, it must be clear that the file can only be sent "as is" (e.g. you
+  can't modify the content while transmitting).
+  There might be problems with non regular filesystems such as NFS,
+  SMBFS/Samba and CIFS. For this please refer to
+  `proftpd documentation <http://www.proftpd.org/docs/howto/Sendfile.html>`__.
+- since the file is sent "as is" sendfile(2) can only be used with clear-text
+  sockets (meaning `SSL <https://docs.python.org/2/library/ssl.html>`__
+  is not supported).
+- `OSError <http://docs.python.org/library/exceptions.html#exceptions.OSError>`__
+  is raised instead of `socket.error <http://docs.python.org/library/socket.html#socket.error>`__.
+  The accompaining `error codes <http://docs.python.org/library/errno.html>`__
+  have the same meaning though: EAGAIN, EWOULDBLOCK, EBUSY meaning you are
+  supposed to retry, ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED in case of
+  disconnection. Some examples:
+  `benchmark script <https://github.com/giampaolo/pysendfile/blob/release-2.0.1/test/benchmark.py#L182>`__,
+  `test suite <https://github.com/giampaolo/pysendfile/blob/release-2.0.1/test/test_sendfile.py#L202>`__,
+  `pyftpdlib wrapper <http://code.google.com/p/pyftpdlib/source/browse/tags/release-0.7.0/pyftpdlib/ftpserver.py#1035>`__.
+
+===============
+Non-blocking IO
+===============
+
+- sendfile(2) can be used with non-blocking sockets, meaning if you try to
+  send a chunk of data over a socket fd which is not "ready" you'll immediately
+  get EAGAIN (then you can retry later by using `select()`, `epoll()` or
+  whatever).
+- the regular file fd, on the other hand, *can* block.
+
+===================
+Supported platforms
+===================
+
+This module works with Python versions from **2.5** to **3.X** and later on it
+was integrated into Python 3 as
+`os.sendfile() <https://docs.python.org/3/library/os.html#os.sendfile>`__
+and `socket.socket().sendfile() <https://docs.python.org/3/library/socket.html#socket.socket.sendfile>`__
+(see `bpo-10882 <http://bugs.python.org/issue10882>`__ and
+`bpo-17552 <https://bugs.python.org/issue17552>`__).
+The supported platforms are:
+
+- **Linux**
+- **Mac OSX**
+- **FreeBSD**
+- **Dragon Fly BSD**
+- **Sun OS**
+- **AIX** (not properly tested)
+
+=======
+Authors
+=======
+
+pysendfile was originally written by *Ben Woolley* including Linux, FreeBSD and
+DragonFly BSD support. Later on *Niklas Edmundsson* took over maintenance and
+added AIX support. After a couple of years of project stagnation
+`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`__ took over
+maintenance and rewrote it from scratch adding support for:
+
+- Python 3
+- non-blocking sockets
+- `large file <http://docs.python.org/library/posix.html#large-file-support>`__ support
+- Mac OSX
+- Sun OS
+- FreeBSD flag argument
+- multiple threads (release GIL)
+- a simple benchmark suite
+- unit tests
+- documentation
diff --git a/README.rst b/README.rst
index cc24a42..060ba2f 100644
--- a/README.rst
+++ b/README.rst
@@ -1,32 +1,34 @@
-.. image:: https://pypip.in/d/pysendfile/badge.png
-    :target: https://crate.io/packages/pysendfile/
-    :alt: Download this month
+.. image:: http://pepy.tech/badge/pysendfile
+    :target: http://pepy.tech/project/pysendfile
+    :alt: Downloads
 
-.. image:: https://pypip.in/v/pysendfile/badge.png
+.. image:: https://api.travis-ci.org/giampaolo/pysendfile.png?branch=master
+    :target: https://travis-ci.org/giampaolo/pysendfile
+    :alt: Linux tests (Travis)
+
+.. image:: https://img.shields.io/pypi/v/pysendfile.svg
     :target: https://pypi.python.org/pypi/pysendfile/
     :alt: Latest version
 
-.. image:: https://pypip.in/license/pysendfile/badge.png
+.. image:: https://img.shields.io/github/stars/giampaolo/pysendfile.svg
+    :target: https://github.com/giampaolo/pysendfile/
+    :alt: Github stars
+
+.. image:: https://img.shields.io/pypi/l/pysendfile.svg
     :target: https://pypi.python.org/pypi/pysendfile/
     :alt: License
 
-.. image:: https://api.travis-ci.org/giampaolo/pysendfile.png?branch=master
-    :target: https://travis-ci.org/giampaolo/pysendfile
-    :alt: Travis
-
-===========
-Quick links
-===========
-
-- `Home page <https://github.com/giampaolo/pysendfile>`_
-- `Mailing list <http://groups.google.com/group/py-sendfile>`_
-- `Blog <http://grodola.blogspot.com/search/label/pysendfile>`_
-- `What's new <https://github.com/giampaolo/pysendfile/blob/master/HISTORY.rst>`_
-
 =====
 About
 =====
 
+A backport of `os.sendfile() <https://docs.python.org/3/library/os.html#os.sendfile>`__
+for Python 2.6 and 2.7 (see `BPO-10882 <https://bugs.python.org/issue10882>`__).
+
+===========
+Explanation
+===========
+
 `sendfile(2) <http://linux.die.net/man/2/sendfile>`__ is a system call which
 provides a "zero-copy" way of copying data from one file descriptor to another
 (a socket). The phrase "zero-copy" refers to the fact that all of the copying
@@ -40,7 +42,7 @@ file into a userspace buffer, then write that buffer to the socket via
 
 .. code-block:: python
 
-    # how a file is tipically sent
+    # how a file is typically sent
 
     import socket
 
@@ -66,6 +68,7 @@ requiring a context switch) used internally for the data copying.
 .. code-block:: python
 
     import socket
+    import os
     from sendfile import sendfile
 
     file = open("somefile", "rb")
@@ -76,9 +79,9 @@ requiring a context switch) used internally for the data copying.
 
     while True:
         sent = sendfile(sock.fileno(), file.fileno(), offset, blocksize)
+        offset += sent
         if sent == 0:
             break  # EOF
-        offset += sent
 
 ==================
 A simple benchmark
@@ -134,7 +137,7 @@ sendfile module provides a single function: sendfile().
   discouraged
   (`send() <http://docs.python.org/library/socket.html#socket.socket.send>`__ or
   `sendall() <http://docs.python.org/library/socket.html#socket.socket.sendall>`__
-  can be used instead). On Solaris, _out_ may be the file descriptor of a
+  can be used instead). On Solaris, *out* may be the file descriptor of a
   regular file or the file descriptor of a socket. On all other platforms,
   *out* must be the file descriptor of an open socket.
   *flags* argument is only supported on FreeBSD.
@@ -143,7 +146,7 @@ sendfile module provides a single function: sendfile().
 - ``sendfile.SF_MNOWAIT``
 - ``sendfile.SF_SYNC``
 
-  Parameters for the _flags_ argument, if the implementation supports it. They
+  Parameters for the *flags* argument, if the implementation supports it. They
   are available on FreeBSD platforms. See `FreeBSD's man sendfile(2) <http://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2>`__.
 
 =======================
@@ -151,12 +154,15 @@ Differences with send()
 =======================
 
 - sendfile(2) works with regular (mmap-like) files only (e.g. you can't use it
-  with a `StringIO <http://docs.python.org/library/stringio.html>`__ object).
+  with a `StringIO <https://docs.python.org/2/library/stringio.html>`__ object).
 - Also, it must be clear that the file can only be sent "as is" (e.g. you
   can't modify the content while transmitting).
   There might be problems with non regular filesystems such as NFS,
   SMBFS/Samba and CIFS. For this please refer to
   `proftpd documentation <http://www.proftpd.org/docs/howto/Sendfile.html>`__.
+- since the file is sent "as is" sendfile(2) can only be used with clear-text
+  sockets (meaning `SSL <https://docs.python.org/2/library/ssl.html>`__
+  is not supported).
 - `OSError <http://docs.python.org/library/exceptions.html#exceptions.OSError>`__
   is raised instead of `socket.error <http://docs.python.org/library/socket.html#socket.error>`__.
   The accompaining `error codes <http://docs.python.org/library/errno.html>`__
@@ -167,11 +173,27 @@ Differences with send()
   `test suite <https://github.com/giampaolo/pysendfile/blob/release-2.0.1/test/test_sendfile.py#L202>`__,
   `pyftpdlib wrapper <http://code.google.com/p/pyftpdlib/source/browse/tags/release-0.7.0/pyftpdlib/ftpserver.py#1035>`__.
 
+===============
+Non-blocking IO
+===============
+
+- sendfile(2) can be used with non-blocking sockets, meaning if you try to
+  send a chunk of data over a socket fd which is not "ready" you'll immediately
+  get EAGAIN (then you can retry later by using `select()`, `epoll()` or
+  whatever).
+- the regular file fd, on the other hand, *can* block.
+
 ===================
 Supported platforms
 ===================
 
-This module works with Python versions from **2.5** to **3.4**. The supported platforms are:
+This module works with Python versions from **2.5** to **3.X** and later on it
+was integrated into Python 3 as
+`os.sendfile() <https://docs.python.org/3/library/os.html#os.sendfile>`__
+and `socket.socket().sendfile() <https://docs.python.org/3/library/socket.html#socket.socket.sendfile>`__
+(see `bpo-10882 <http://bugs.python.org/issue10882>`__ and
+`bpo-17552 <https://bugs.python.org/issue17552>`__).
+The supported platforms are:
 
 - **Linux**
 - **Mac OSX**
@@ -180,22 +202,6 @@ This module works with Python versions from **2.5** to **3.4**. The supported pl
 - **Sun OS**
 - **AIX** (not properly tested)
 
-=======
-Support
-=======
-
-Feel free to mail me at *g.rodola [AT] gmail [DOT] com* or post on the the
-mailing list: http://groups.google.com/group/py-sendfile.
-
-======
-Status
-======
-
-As of now the code includes a solid `test suite <https://github.com/giampaolo/pysendfile/blob/master/test/test_sendfile.py>`__ and its ready for production use.
-It's been included in `pyftpdlib <http://code.google.com/p/pyftpdlib/>`__
-project and used in production environments for almost a year now without any
-problem being reported so far.
-
 =======
 Authors
 =======
diff --git a/debian/changelog b/debian/changelog
index 561b28b..97a6d19 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+pysendfile (2.0.1+git20210730.2.2ffdd45-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sun, 18 Dec 2022 17:46:57 -0000
+
 pysendfile (2.0.1-4) unstable; urgency=medium
 
   * Team upload.
diff --git a/pysendfile.egg-info/PKG-INFO b/pysendfile.egg-info/PKG-INFO
new file mode 100644
index 0000000..b080e9a
--- /dev/null
+++ b/pysendfile.egg-info/PKG-INFO
@@ -0,0 +1,264 @@
+Metadata-Version: 2.1
+Name: pysendfile
+Version: 2.0.1
+Summary: A Python interface to sendfile(2)
+Home-page: https://github.com/giampaolo/pysendfile
+Author: Giampaolo Rodola
+Author-email: g.rodola@gmail.com
+License: MIT
+Keywords: sendfile,python,performance,ftp
+Platform: UNIX
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: POSIX :: BSD
+Classifier: Operating System :: POSIX :: BSD :: FreeBSD
+Classifier: Operating System :: POSIX :: SunOS/Solaris
+Classifier: Operating System :: POSIX :: AIX
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Python :: 2.5
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.0
+Classifier: Programming Language :: Python :: 3.1
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Topic :: System :: Networking
+Classifier: Topic :: System :: Operating System
+Classifier: Topic :: Internet :: File Transfer Protocol (FTP)
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: License :: OSI Approved :: MIT License
+License-File: LICENSE
+
+.. image:: http://pepy.tech/badge/pysendfile
+    :target: http://pepy.tech/project/pysendfile
+    :alt: Downloads
+
+.. image:: https://api.travis-ci.org/giampaolo/pysendfile.png?branch=master
+    :target: https://travis-ci.org/giampaolo/pysendfile
+    :alt: Linux tests (Travis)
+
+.. image:: https://img.shields.io/pypi/v/pysendfile.svg
+    :target: https://pypi.python.org/pypi/pysendfile/
+    :alt: Latest version
+
+.. image:: https://img.shields.io/github/stars/giampaolo/pysendfile.svg
+    :target: https://github.com/giampaolo/pysendfile/
+    :alt: Github stars
+
+.. image:: https://img.shields.io/pypi/l/pysendfile.svg
+    :target: https://pypi.python.org/pypi/pysendfile/
+    :alt: License
+
+=====
+About
+=====
+
+A backport of `os.sendfile() <https://docs.python.org/3/library/os.html#os.sendfile>`__
+for Python 2.6 and 2.7 (see `BPO-10882 <https://bugs.python.org/issue10882>`__).
+
+===========
+Explanation
+===========
+
+`sendfile(2) <http://linux.die.net/man/2/sendfile>`__ is a system call which
+provides a "zero-copy" way of copying data from one file descriptor to another
+(a socket). The phrase "zero-copy" refers to the fact that all of the copying
+of data between the two descriptors is done entirely by the kernel, with no
+copying of data into userspace buffers. This is particularly useful when
+sending a file over a socket (e.g. FTP).
+The normal way of sending a file over a socket involves reading data from the
+file into a userspace buffer, then write that buffer to the socket via
+`send() <http://docs.python.org/library/socket.html#socket.socket.send>`__ or
+`sendall() <http://docs.python.org/library/socket.html#socket.socket.sendall>`__:
+
+.. code-block:: python
+
+    # how a file is typically sent
+
+    import socket
+
+    file = open("somefile", "rb")
+    sock = socket.socket()
+    sock.connect(("127.0.0.1", 8021))
+
+    while True:
+        chunk = file.read(65536)
+        if not chunk:
+            break  # EOF
+        sock.sendall(chunk)
+
+This copying of the data twice (once into the userland buffer, and once out
+from that userland buffer) imposes some performance and resource penalties.
+`sendfile(2) <http://linux.die.net/man/2/sendfile>`__ syscall avoids these
+penalties by avoiding any use of userland buffers; it also results in a single
+system call (and thus only one context switch), rather than the series of
+`read(2) <http://linux.die.net/man/2/read>`__ /
+`write(2) <http://linux.die.net/man/2/write>`__ system calls (each system call
+requiring a context switch) used internally for the data copying.
+
+.. code-block:: python
+
+    import socket
+    import os
+    from sendfile import sendfile
+
+    file = open("somefile", "rb")
+    blocksize = os.path.getsize("somefile")
+    sock = socket.socket()
+    sock.connect(("127.0.0.1", 8021))
+    offset = 0
+
+    while True:
+        sent = sendfile(sock.fileno(), file.fileno(), offset, blocksize)
+        offset += sent
+        if sent == 0:
+            break  # EOF
+
+==================
+A simple benchmark
+==================
+
+This `benchmark script <https://github.com/giampaolo/pysendfile/blob/master/test/benchmark.py>`__
+implements the two examples above and compares plain socket.send() and
+sendfile() performances in terms of CPU time spent and bytes transmitted per
+second resulting in sendfile() being about **2.5x faster**. These are the
+results I get on my Linux 2.6.38 box, AMD dual-core 1.6 GHz:
+
+*send()*
+
++---------------+-----------------+
+| CPU time      | 28.84 usec/pass |
++---------------+-----------------+
+| transfer rate | 359.38 MB/sec   |
++---------------+-----------------+
+
+*sendfile()*
+
++---------------+-----------------+
+| CPU time      | 11.28 usec/pass |
++---------------+-----------------+
+| transfer rate | 860.88 MB/sec   |
++---------------+-----------------+
+
+===========================
+When do you want to use it?
+===========================
+
+Basically any application sending files over the network can take advantage of
+sendfile(2). HTTP and FTP servers are a typical example.
+`proftpd <http://www.proftpd.org/>`__ and
+`vsftpd <https://security.appspot.com/vsftpd.html>`__ are known to use it, so is
+`pyftpdlib <http://code.google.com/p/pyftpdlib/>`__.
+
+=================
+API documentation
+=================
+
+sendfile module provides a single function: sendfile().
+
+- ``sendfile.sendfile(out, in, offset, nbytes, header="", trailer="", flags=0)``
+
+  Copy *nbytes* bytes from file descriptor *in* (a regular file) to file
+  descriptor *out* (a socket) starting at *offset*. Return the number of
+  bytes just being sent. When the end of file is reached return 0.
+  On Linux, if *offset* is given as *None*, the bytes are read from the current
+  position of *in* and the position of *in* is updated.
+  *headers* and *trailers* are strings that are written before and after the
+  data from *in* is written. In cross platform applications their usage is
+  discouraged
+  (`send() <http://docs.python.org/library/socket.html#socket.socket.send>`__ or
+  `sendall() <http://docs.python.org/library/socket.html#socket.socket.sendall>`__
+  can be used instead). On Solaris, *out* may be the file descriptor of a
+  regular file or the file descriptor of a socket. On all other platforms,
+  *out* must be the file descriptor of an open socket.
+  *flags* argument is only supported on FreeBSD.
+
+- ``sendfile.SF_NODISKIO``
+- ``sendfile.SF_MNOWAIT``
+- ``sendfile.SF_SYNC``
+
+  Parameters for the *flags* argument, if the implementation supports it. They
+  are available on FreeBSD platforms. See `FreeBSD's man sendfile(2) <http://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2>`__.
+
+=======================
+Differences with send()
+=======================
+
+- sendfile(2) works with regular (mmap-like) files only (e.g. you can't use it
+  with a `StringIO <https://docs.python.org/2/library/stringio.html>`__ object).
+- Also, it must be clear that the file can only be sent "as is" (e.g. you
+  can't modify the content while transmitting).
+  There might be problems with non regular filesystems such as NFS,
+  SMBFS/Samba and CIFS. For this please refer to
+  `proftpd documentation <http://www.proftpd.org/docs/howto/Sendfile.html>`__.
+- since the file is sent "as is" sendfile(2) can only be used with clear-text
+  sockets (meaning `SSL <https://docs.python.org/2/library/ssl.html>`__
+  is not supported).
+- `OSError <http://docs.python.org/library/exceptions.html#exceptions.OSError>`__
+  is raised instead of `socket.error <http://docs.python.org/library/socket.html#socket.error>`__.
+  The accompaining `error codes <http://docs.python.org/library/errno.html>`__
+  have the same meaning though: EAGAIN, EWOULDBLOCK, EBUSY meaning you are
+  supposed to retry, ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED in case of
+  disconnection. Some examples:
+  `benchmark script <https://github.com/giampaolo/pysendfile/blob/release-2.0.1/test/benchmark.py#L182>`__,
+  `test suite <https://github.com/giampaolo/pysendfile/blob/release-2.0.1/test/test_sendfile.py#L202>`__,
+  `pyftpdlib wrapper <http://code.google.com/p/pyftpdlib/source/browse/tags/release-0.7.0/pyftpdlib/ftpserver.py#1035>`__.
+
+===============
+Non-blocking IO
+===============
+
+- sendfile(2) can be used with non-blocking sockets, meaning if you try to
+  send a chunk of data over a socket fd which is not "ready" you'll immediately
+  get EAGAIN (then you can retry later by using `select()`, `epoll()` or
+  whatever).
+- the regular file fd, on the other hand, *can* block.
+
+===================
+Supported platforms
+===================
+
+This module works with Python versions from **2.5** to **3.X** and later on it
+was integrated into Python 3 as
+`os.sendfile() <https://docs.python.org/3/library/os.html#os.sendfile>`__
+and `socket.socket().sendfile() <https://docs.python.org/3/library/socket.html#socket.socket.sendfile>`__
+(see `bpo-10882 <http://bugs.python.org/issue10882>`__ and
+`bpo-17552 <https://bugs.python.org/issue17552>`__).
+The supported platforms are:
+
+- **Linux**
+- **Mac OSX**
+- **FreeBSD**
+- **Dragon Fly BSD**
+- **Sun OS**
+- **AIX** (not properly tested)
+
+=======
+Authors
+=======
+
+pysendfile was originally written by *Ben Woolley* including Linux, FreeBSD and
+DragonFly BSD support. Later on *Niklas Edmundsson* took over maintenance and
+added AIX support. After a couple of years of project stagnation
+`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`__ took over
+maintenance and rewrote it from scratch adding support for:
+
+- Python 3
+- non-blocking sockets
+- `large file <http://docs.python.org/library/posix.html#large-file-support>`__ support
+- Mac OSX
+- Sun OS
+- FreeBSD flag argument
+- multiple threads (release GIL)
+- a simple benchmark suite
+- unit tests
+- documentation
diff --git a/pysendfile.egg-info/SOURCES.txt b/pysendfile.egg-info/SOURCES.txt
new file mode 100644
index 0000000..f670706
--- /dev/null
+++ b/pysendfile.egg-info/SOURCES.txt
@@ -0,0 +1,17 @@
+.travis.yml
+HISTORY.rst
+LICENSE
+MANIFEST.in
+Makefile
+README.rst
+sendfilemodule.c
+setup.py
+.ci/travis/README
+.ci/travis/install.sh
+.ci/travis/run.sh
+pysendfile.egg-info/PKG-INFO
+pysendfile.egg-info/SOURCES.txt
+pysendfile.egg-info/dependency_links.txt
+pysendfile.egg-info/top_level.txt
+test/benchmark.py
+test/test_sendfile.py
\ No newline at end of file
diff --git a/pysendfile.egg-info/dependency_links.txt b/pysendfile.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pysendfile.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/pysendfile.egg-info/top_level.txt b/pysendfile.egg-info/top_level.txt
new file mode 100644
index 0000000..981c721
--- /dev/null
+++ b/pysendfile.egg-info/top_level.txt
@@ -0,0 +1 @@
+sendfile
diff --git a/sendfilemodule.c b/sendfilemodule.c
index fd69af6..b1ed55b 100644
--- a/sendfilemodule.c
+++ b/sendfilemodule.c
@@ -6,12 +6,11 @@
  * Original author:
  *     Copyright (C) 2005 Ben Woolley <user tautolog at gmail>
  *
- * The AIX support code is:
- *     Copyright (C) 2008,2009 Niklas Edmundsson <nikke@acc.umu.se>
- *
- * Rewritten from scratch and maintained by Giampaolo Rodola'
- *     Copyright (C) 2009,2014 <g.rodola@gmail.com>
+ * AIX implementation:
+ *     Copyright (C) 2008, 2009 Niklas Edmundsson <nikke@acc.umu.se>
  *
+ * Rewritten from scratch and maintained Giampaolo Rodola';
+ *     Copyright (C) 2009, present day Giampaolo Rodola' <g.rodola@gmail.com>
  *
  *  The MIT License
  *
@@ -159,11 +158,11 @@ method_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
     goto done;
 
 done:
-    #if defined(HAVE_LARGEFILE_SUPPORT)
-        return Py_BuildValue("L", sent);
-    #else
-        return Py_BuildValue("l", sent);
-    #endif
+#if defined(HAVE_LARGEFILE_SUPPORT)
+    return Py_BuildValue("L", sent);
+#else
+    return Py_BuildValue("l", sent);
+#endif
 }
 /* --- end OSX / FreeBSD / Dragonfly --- */
 
@@ -223,11 +222,11 @@ method_sendfile(PyObject *self, PyObject *args)
         return NULL;
     }
     else {
-    #if defined(HAVE_LARGEFILE_SUPPORT)
+#if defined(HAVE_LARGEFILE_SUPPORT)
         return Py_BuildValue("L", sts);
-    #else
+#else
         return Py_BuildValue("l", sts);
-    #endif
+#endif
     }
 }
 /* --- end AIX --- */
@@ -312,7 +311,6 @@ struct module_state {
 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
 #else
 #define GETSTATE(m) (&_state)
-static struct module_state _state;
 #endif
 
 static PyMethodDef sendfile_methods[] = {
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..8bfd5a1
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,4 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+
diff --git a/setup.py b/setup.py
index 566067f..54a991a 100644
--- a/setup.py
+++ b/setup.py
@@ -24,10 +24,11 @@
 # ======================================================================
 
 import sys
+
 try:
-    from setuptools import setup, Extension
+    from setuptools import Extension, setup
 except ImportError:
-    from distutils.core import setup, Extension
+    from distutils.core import Extension, setup
 
 
 NAME = 'pysendfile'
@@ -72,6 +73,11 @@ def main():
               'Programming Language :: Python :: 3.2',
               'Programming Language :: Python :: 3.3',
               'Programming Language :: Python :: 3.4',
+              'Programming Language :: Python :: 3.5',
+              'Programming Language :: Python :: 3.6',
+              'Programming Language :: Python :: 3.7',
+              'Programming Language :: Python :: 3.8',
+              'Programming Language :: Python :: 3.9',
               'Topic :: System :: Networking',
               'Topic :: System :: Operating System',
               'Topic :: Internet :: File Transfer Protocol (FTP)',
@@ -82,5 +88,6 @@ def main():
                                  sources=['sendfilemodule.c'],
                                  libraries=libraries)])
 
+
 if __name__ == '__main__':
     main()
diff --git a/test/test_sendfile.py b/test/test_sendfile.py
index ce223b1..2d688f0 100644
--- a/test/test_sendfile.py
+++ b/test/test_sendfile.py
@@ -55,6 +55,7 @@ def b(x):
         return bytes(x, 'ascii')
     return x
 
+
 TESTFN = "$testfile"
 TESTFN2 = TESTFN + "2"
 TESTFN3 = TESTFN + "3"
@@ -543,6 +544,7 @@ def cleanup():
     safe_remove(TESTFN)
     safe_remove(TESTFN2)
 
+
 atexit.register(cleanup)
 
 
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index 72dc6e2..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,27 +0,0 @@
-# Tox (http://tox.testrun.org/) is a tool for running tests
-# in multiple virtualenvs. This configuration file will run the
-# test suite on all supported python versions.
-# To use it run "pip install tox" and then run "tox" from this
-# directory.
-
-[tox]
-envlist = py26, py27, py32, py33, py34
-
-[testenv]
-deps =
-    pytest
-    flake8
-setenv =
-    PYTHONPATH = {toxinidir}/test
-commands =
-    python test/test_sendfile.py
-    flake8 --exclude=build,.tox,.git
-
-[testenv:py26]
-deps =
-    flake8
-    pytest
-    unittest2
-commands =
-    python test/test_sendfile.py
-    flake8 --exclude=build,.tox,.git

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/debug/.build-id/f8/e20cca5a467e38c0f054168be2f4e9709c220c.debug
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sendfile.cpython-310-x86_64-linux-gnu.so

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/debug/.build-id/7b/f0449115cfce13184d1ccddb2d683c14668c0f.debug
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sendfile.cpython-311-x86_64-linux-gnu.so

Control files of package python3-sendfile: lines which differ (wdiff format)

  • Depends: libc6 (>= 2.4), python3 (<< 3.12), 3.11), python3 (>= 3.11~) 3.10~)

Control files of package python3-sendfile-dbgsym: lines which differ (wdiff format)

  • Build-Ids: 7bf0449115cfce13184d1ccddb2d683c14668c0f f8e20cca5a467e38c0f054168be2f4e9709c220c

More details

Full run details