[Python-checkins] cpython (merge default -> default): Merge.

larry.hastings python-checkins at python.org
Mon Jan 27 07:28:54 CET 2014


http://hg.python.org/cpython/rev/a45ad55ea3da
changeset:   88762:a45ad55ea3da
parent:      88761:8397134b25df
parent:      88757:c6b4a5354c23
user:        Larry Hastings <larry at hastings.org>
date:        Sun Jan 26 22:28:06 2014 -0800
summary:
  Merge.

files:
  Doc/c-api/exceptions.rst               |   10 +
  Doc/library/concurrent.futures.rst     |    3 +-
  Doc/reference/expressions.rst          |   99 +-
  Doc/reference/simple_stmts.rst         |   57 +-
  Doc/whatsnew/3.4.rst                   |    8 +
  Lib/asyncio/base_subprocess.py         |    1 -
  Lib/asyncio/unix_events.py             |    3 -
  Lib/asyncio/windows_events.py          |    3 -
  Lib/codecs.py                          |   13 +-
  Lib/concurrent/futures/_base.py        |    6 +-
  Lib/idlelib/CallTips.py                |   15 +-
  Lib/idlelib/configDialog.py            |    9 +-
  Lib/idlelib/idle_test/test_calltips.py |   56 +-
  Lib/test/imghdrdata/python.bmp         |  Bin 
  Lib/test/imghdrdata/python.gif         |  Bin 
  Lib/test/imghdrdata/python.jpg         |  Bin 
  Lib/test/imghdrdata/python.pbm         |    3 +
  Lib/test/imghdrdata/python.pgm         |  Bin 
  Lib/test/imghdrdata/python.png         |  Bin 
  Lib/test/imghdrdata/python.ppm         |  Bin 
  Lib/test/imghdrdata/python.ras         |  Bin 
  Lib/test/imghdrdata/python.sgi         |  Bin 
  Lib/test/imghdrdata/python.tiff        |  Bin 
  Lib/test/imghdrdata/python.xbm         |    6 +
  Lib/test/test_codecs.py                |   37 +-
  Lib/test/test_concurrent_futures.py    |    7 +
  Lib/test/test_imghdr.py                |  131 +++
  Lib/test/test_sundry.py                |    2 +-
  Lib/wsgiref/__init__.py                |    2 +-
  Misc/ACKS                              |    1 +
  Misc/NEWS                              |   22 +-
  Modules/_pickle.c                      |    2 +-
  Modules/audioop.c                      |   14 +-
  Modules/binascii.c                     |    5 +
  Modules/clinic/binascii.c.h            |   32 +-
  Modules/clinic/zlibmodule.c.h          |  411 ++++++++++
  Modules/zlibmodule.c                   |  503 +++++-------
  Objects/exceptions.c                   |    7 +-
  38 files changed, 1003 insertions(+), 465 deletions(-)


diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -90,6 +90,16 @@
    the class in that case.  If the values are already normalized, nothing happens.
    The delayed normalization is implemented to improve performance.
 
+   .. note::
+
+      This function *does not* implicitly set the ``__traceback__``
+      attribute on the exception value. If setting the traceback
+      appropriately is desired, the following additional snippet is needed::
+
+         if (tb != NULL) {
+           PyException_SetTraceback(val, tb);
+         }
+
 
 .. c:function:: void PyErr_Clear()
 
diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst
--- a/Doc/library/concurrent.futures.rst
+++ b/Doc/library/concurrent.futures.rst
@@ -371,7 +371,8 @@
 
    Returns an iterator over the :class:`Future` instances (possibly created by
    different :class:`Executor` instances) given by *fs* that yields futures as
-   they complete (finished or were cancelled).  Any futures that completed
+   they complete (finished or were cancelled). Any futures given by *fs* that
+   are duplicated will be returned once. Any futures that completed
    before :func:`as_completed` is called will be yielded first.  The returned
    iterator raises a :exc:`TimeoutError` if :meth:`~iterator.__next__` is
    called and the result isn't available after *timeout* seconds from the
diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst
--- a/Doc/reference/expressions.rst
+++ b/Doc/reference/expressions.rst
@@ -319,27 +319,25 @@
    yield_atom: "(" `yield_expression` ")"
    yield_expression: "yield" [`expression_list` | "from" `expression`]
 
-The :keyword:`yield` expression is only used when defining a :term:`generator`
-function,
-and can only be used in the body of a function definition.  Using a
-:keyword:`yield` expression in a function definition is sufficient to cause that
-definition to create a generator function instead of a normal function.
+The yield expression is only used when defining a :term:`generator` function and
+thus can only be used in the body of a function definition.  Using a yield
+expression in a function's body causes that function to be a generator.
 
 When a generator function is called, it returns an iterator known as a
 generator.  That generator then controls the execution of a generator function.
 The execution starts when one of the generator's methods is called.  At that
-time, the execution proceeds to the first :keyword:`yield` expression, where it
-is suspended again, returning the value of :token:`expression_list` to
-generator's caller.  By suspended we mean that all local state is retained,
-including the current bindings of local variables, the instruction pointer, and
-the internal evaluation stack.  When the execution is resumed by calling one of
-the generator's methods, the function can proceed exactly as if the
-:keyword:`yield` expression was just another external call.  The value of the
-:keyword:`yield` expression after resuming depends on the method which resumed
-the execution. If :meth:`~generator.__next__` is used (typically via either a
-:keyword:`for` or the :func:`next` builtin) then the result is :const:`None`,
-otherwise, if :meth:`~generator.send` is used, then the result will be the
-value passed in to that method.
+time, the execution proceeds to the first yield expression, where it is
+suspended again, returning the value of :token:`expression_list` to generator's
+caller.  By suspended, we mean that all local state is retained, including the
+current bindings of local variables, the instruction pointer, and the internal
+evaluation stack.  When the execution is resumed by calling one of the
+generator's methods, the function can proceed exactly as if the yield expression
+was just another external call.  The value of the yield expression after
+resuming depends on the method which resumed the execution.  If
+:meth:`~generator.__next__` is used (typically via either a :keyword:`for` or
+the :func:`next` builtin) then the result is :const:`None`.  Otherwise, if
+:meth:`~generator.send` is used, then the result will be the value passed in to
+that method.
 
 .. index:: single: coroutine
 
@@ -349,11 +347,11 @@
 where should the execution continue after it yields; the control is always
 transferred to the generator's caller.
 
-:keyword:`yield` expressions are allowed in the :keyword:`try` clause of a
-:keyword:`try` ...  :keyword:`finally` construct.  If the generator is not
-resumed before it is finalized (by reaching a zero reference count or by being
-garbage collected), the generator-iterator's :meth:`~generator.close` method
-will be called, allowing any pending :keyword:`finally` clauses to execute.
+yield expressions are allowed in the :keyword:`try` clause of a :keyword:`try`
+...  :keyword:`finally` construct.  If the generator is not resumed before it is
+finalized (by reaching a zero reference count or by being garbage collected),
+the generator-iterator's :meth:`~generator.close` method will be called,
+allowing any pending :keyword:`finally` clauses to execute.
 
 When ``yield from <expr>`` is used, it treats the supplied expression as
 a subiterator. All values produced by that subiterator are passed directly
@@ -373,12 +371,24 @@
    .. versionchanged:: 3.3
       Added ``yield from <expr>`` to delegate control flow to a subiterator
 
-The parentheses can be omitted when the :keyword:`yield` expression is the
-sole expression on the right hand side of an assignment statement.
+The parentheses may be omitted when the yield expression is the sole expression
+on the right hand side of an assignment statement.
+
+.. seealso::
+
+   :pep:`0255` - Simple Generators
+      The proposal for adding generators and the :keyword:`yield` statement to Python.
+
+   :pep:`0342` - Coroutines via Enhanced Generators
+      The proposal to enhance the API and syntax of generators, making them
+      usable as simple coroutines.
+
+   :pep:`0380` - Syntax for Delegating to a Subgenerator
+      The proposal to introduce the :token:`yield_from` syntax, making delegation
+      to sub-generators easy.
 
 .. index:: object: generator
 
-
 Generator-iterator methods
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -395,13 +405,12 @@
 .. method:: generator.__next__()
 
    Starts the execution of a generator function or resumes it at the last
-   executed :keyword:`yield` expression.  When a generator function is resumed
-   with a :meth:`~generator.__next__` method, the current :keyword:`yield`
-   expression always evaluates to :const:`None`.  The execution then continues
-   to the next :keyword:`yield` expression, where the generator is suspended
-   again, and the value of the :token:`expression_list` is returned to
-   :meth:`next`'s caller.
-   If the generator exits without yielding another value, a :exc:`StopIteration`
+   executed yield expression.  When a generator function is resumed with a
+   :meth:`~generator.__next__` method, the current yield expression always
+   evaluates to :const:`None`.  The execution then continues to the next yield
+   expression, where the generator is suspended again, and the value of the
+   :token:`expression_list` is returned to :meth:`next`'s caller.  If the
+   generator exits without yielding another value, a :exc:`StopIteration`
    exception is raised.
 
    This method is normally called implicitly, e.g. by a :keyword:`for` loop, or
@@ -411,12 +420,12 @@
 .. method:: generator.send(value)
 
    Resumes the execution and "sends" a value into the generator function.  The
-   ``value`` argument becomes the result of the current :keyword:`yield`
-   expression.  The :meth:`send` method returns the next value yielded by the
-   generator, or raises :exc:`StopIteration` if the generator exits without
-   yielding another value.  When :meth:`send` is called to start the generator,
-   it must be called with :const:`None` as the argument, because there is no
-   :keyword:`yield` expression that could receive the value.
+   *value* argument becomes the result of the current yield expression.  The
+   :meth:`send` method returns the next value yielded by the generator, or
+   raises :exc:`StopIteration` if the generator exits without yielding another
+   value.  When :meth:`send` is called to start the generator, it must be called
+   with :const:`None` as the argument, because there is no yield expression that
+   could receive the value.
 
 
 .. method:: generator.throw(type[, value[, traceback]])
@@ -478,20 +487,6 @@
 Python."
 
 
-.. seealso::
-
-   :pep:`0255` - Simple Generators
-      The proposal for adding generators and the :keyword:`yield` statement to Python.
-
-   :pep:`0342` - Coroutines via Enhanced Generators
-      The proposal to enhance the API and syntax of generators, making them
-      usable as simple coroutines.
-
-   :pep:`0380` - Syntax for Delegating to a Subgenerator
-      The proposal to introduce the :token:`yield_from` syntax, making delegation
-      to sub-generators easy.
-
-
 .. _primaries:
 
 Primaries
diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst
--- a/Doc/reference/simple_stmts.rst
+++ b/Doc/reference/simple_stmts.rst
@@ -445,53 +445,26 @@
 .. productionlist::
    yield_stmt: `yield_expression`
 
-The :keyword:`yield` statement is only used when defining a generator function,
-and is only used in the body of the generator function. Using a :keyword:`yield`
-statement in a function definition is sufficient to cause that definition to
-create a generator function instead of a normal function.
+A :keyword:`yield` statement is semantically equivalent to a :ref:`yield
+expression <yieldexpr>`. The yield statement can be used to omit the parentheses
+that would otherwise be required in the equivalent yield expression
+statement. For example, the yield statements ::
 
-When a generator function is called, it returns an iterator known as a generator
-iterator, or more commonly, a generator.  The body of the generator function is
-executed by calling the :func:`next` function on the generator repeatedly until
-it raises an exception.
+  yield <expr>
+  yield from <expr>
 
-When a :keyword:`yield` statement is executed, the state of the generator is
-frozen and the value of :token:`expression_list` is returned to :meth:`next`'s
-caller.  By "frozen" we mean that all local state is retained, including the
-current bindings of local variables, the instruction pointer, and the internal
-evaluation stack: enough information is saved so that the next time :func:`next`
-is invoked, the function can proceed exactly as if the :keyword:`yield`
-statement were just another external call.
+are equivalent to the yield expression statements ::
 
-The :keyword:`yield` statement is allowed in the :keyword:`try` clause of a
-:keyword:`try` ...  :keyword:`finally` construct.  If the generator is not
-resumed before it is finalized (by reaching a zero reference count or by being
-garbage collected), the generator-iterator's :meth:`close` method will be
-called, allowing any pending :keyword:`finally` clauses to execute.
+  (yield <expr>)
+  (yield from <expr>)
 
-When ``yield from <expr>`` is used, it treats the supplied expression as
-a subiterator, producing values from it until the underlying iterator is
-exhausted.
+Yield expressions and statements are only used when defining a :term:`generator`
+function, and are only used in the body of the generator function.  Using yield
+in a function definition is sufficient to cause that definition to create a
+generator function instead of a normal function.
 
-   .. versionchanged:: 3.3
-      Added ``yield from <expr>`` to delegate control flow to a subiterator
-
-For full details of :keyword:`yield` semantics, refer to the :ref:`yieldexpr`
-section.
-
-.. seealso::
-
-   :pep:`0255` - Simple Generators
-      The proposal for adding generators and the :keyword:`yield` statement to Python.
-
-   :pep:`0342` - Coroutines via Enhanced Generators
-      The proposal to enhance the API and syntax of generators, making them
-      usable as simple coroutines.
-
-   :pep:`0380` - Syntax for Delegating to a Subgenerator
-      The proposal to introduce the :token:`yield_from` syntax, making delegation
-      to sub-generators easy.
-
+For full details of :keyword:`yield` semantics, refer to the
+:ref:`yieldexpr` section.
 
 .. _raise:
 
diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst
--- a/Doc/whatsnew/3.4.rst
+++ b/Doc/whatsnew/3.4.rst
@@ -264,6 +264,9 @@
     >>> import codecs
 
     >>> codecs.decode(b"abcdefgh", "hex")
+    Traceback (most recent call last):
+      File "/usr/lib/python3.4/encodings/hex_codec.py", line 20, in hex_decode
+        return (binascii.a2b_hex(input), len(input))
     binascii.Error: Non-hexadecimal digit found
 
     The above exception was the direct cause of the following exception:
@@ -273,6 +276,11 @@
     binascii.Error: decoding with 'hex' codec failed (Error: Non-hexadecimal digit found)
 
     >>> codecs.encode("hello", "bz2")
+    Traceback (most recent call last):
+      File "/usr/lib/python3.4/encodings/bz2_codec.py", line 17, in bz2_encode
+        return (bz2.compress(input), len(input))
+      File "/usr/lib/python3.4/bz2.py", line 498, in compress
+        return comp.compress(data) + comp.flush()
     TypeError: 'str' does not support the buffer interface
 
     The above exception was the direct cause of the following exception:
diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py
--- a/Lib/asyncio/base_subprocess.py
+++ b/Lib/asyncio/base_subprocess.py
@@ -114,7 +114,6 @@
         assert returncode is not None, returncode
         assert self._returncode is None, self._returncode
         self._returncode = returncode
-        self._loop._subprocess_closed(self)
         self._call(self._protocol.process_exited)
         self._try_finish()
 
diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
--- a/Lib/asyncio/unix_events.py
+++ b/Lib/asyncio/unix_events.py
@@ -169,9 +169,6 @@
     def _child_watcher_callback(self, pid, returncode, transp):
         self.call_soon_threadsafe(transp._process_exited, returncode)
 
-    def _subprocess_closed(self, transp):
-        pass
-
 
 def _set_nonblocking(fd):
     flags = fcntl.fcntl(fd, fcntl.F_GETFL)
diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py
--- a/Lib/asyncio/windows_events.py
+++ b/Lib/asyncio/windows_events.py
@@ -178,9 +178,6 @@
         yield from transp._post_init()
         return transp
 
-    def _subprocess_closed(self, transport):
-        pass
-
 
 class IocpProactor:
     """Proactor implementation using IOCP."""
diff --git a/Lib/codecs.py b/Lib/codecs.py
--- a/Lib/codecs.py
+++ b/Lib/codecs.py
@@ -475,14 +475,11 @@
         # read until we get the required number of characters (if available)
         while True:
             # can the request be satisfied from the character buffer?
-            if chars < 0:
-                if size < 0:
-                    if self.charbuffer:
-                        break
-                elif len(self.charbuffer) >= size:
+            if chars >= 0:
+                if len(self.charbuffer) >= chars:
                     break
-            else:
-                if len(self.charbuffer) >= chars:
+            elif size >= 0:
+                if len(self.charbuffer) >= size:
                     break
             # we need more data
             if size < 0:
@@ -491,6 +488,8 @@
                 newdata = self.stream.read(size)
             # decode bytes (those remaining from the last call included)
             data = self.bytebuffer + newdata
+            if not data:
+                break
             try:
                 newchars, decodedbytes = self.decode(data, self.errors)
             except UnicodeDecodeError as exc:
diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py
--- a/Lib/concurrent/futures/_base.py
+++ b/Lib/concurrent/futures/_base.py
@@ -181,7 +181,8 @@
 
     Returns:
         An iterator that yields the given Futures as they complete (finished or
-        cancelled).
+        cancelled). If any given Futures are duplicated, they will be returned
+        once.
 
     Raises:
         TimeoutError: If the entire result iterator could not be generated
@@ -190,11 +191,12 @@
     if timeout is not None:
         end_time = timeout + time.time()
 
+    fs = set(fs)
     with _AcquireFutures(fs):
         finished = set(
                 f for f in fs
                 if f._state in [CANCELLED_AND_NOTIFIED, FINISHED])
-        pending = set(fs) - finished
+        pending = fs - finished
         waiter = _create_and_install_waiters(fs, _AS_COMPLETED)
 
     try:
diff --git a/Lib/idlelib/CallTips.py b/Lib/idlelib/CallTips.py
--- a/Lib/idlelib/CallTips.py
+++ b/Lib/idlelib/CallTips.py
@@ -5,16 +5,16 @@
 which disappear when you type a closing parenthesis.
 
 """
+import __main__
+import inspect
 import re
 import sys
+import textwrap
 import types
-import inspect
 
 from idlelib import CallTipWindow
 from idlelib.HyperParser import HyperParser
 
-import __main__
-
 class CallTips:
 
     menudefs = [
@@ -117,8 +117,9 @@
             return None
 
 # The following are used in get_argspec and some in tests
-_MAX_COLS = 79
+_MAX_COLS = 85
 _MAX_LINES = 5  # enough for bytes
+_INDENT = ' '*4  # for wrapped signatures
 _first_param = re.compile('(?<=\()\w*\,?\s*')
 _default_callable_argspec = "See source or doc"
 
@@ -149,13 +150,15 @@
                 isinstance(ob_call, types.MethodType)):
             argspec = _first_param.sub("", argspec)
 
+    lines = (textwrap.wrap(argspec, _MAX_COLS, subsequent_indent=_INDENT)
+            if len(argspec) > _MAX_COLS else [argspec] if argspec else [])
+
     if isinstance(ob_call, types.MethodType):
         doc = ob_call.__doc__
     else:
         doc = getattr(ob, "__doc__", "")
     if doc:
-        lines = [argspec] if argspec else []
-        for line in doc.split('\n', 5)[:_MAX_LINES]:
+        for line in doc.split('\n', _MAX_LINES)[:_MAX_LINES]:
             line = line.strip()
             if not line:
                 break
diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -82,9 +82,10 @@
         else:
             extraKwds=dict(padx=6, pady=3)
 
-        self.buttonHelp = Button(frameActionButtons,text='Help',
-                command=self.Help,takefocus=FALSE,
-                **extraKwds)
+# Comment out button creation and packing until implement self.Help
+##        self.buttonHelp = Button(frameActionButtons,text='Help',
+##                command=self.Help,takefocus=FALSE,
+##                **extraKwds)
         self.buttonOk = Button(frameActionButtons,text='Ok',
                 command=self.Ok,takefocus=FALSE,
                 **extraKwds)
@@ -98,7 +99,7 @@
         self.CreatePageHighlight()
         self.CreatePageKeys()
         self.CreatePageGeneral()
-        self.buttonHelp.pack(side=RIGHT,padx=5)
+##        self.buttonHelp.pack(side=RIGHT,padx=5)
         self.buttonOk.pack(side=LEFT,padx=5)
         self.buttonApply.pack(side=LEFT,padx=5)
         self.buttonCancel.pack(side=LEFT,padx=5)
diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py
--- a/Lib/idlelib/idle_test/test_calltips.py
+++ b/Lib/idlelib/idle_test/test_calltips.py
@@ -1,5 +1,6 @@
 import unittest
 import idlelib.CallTips as ct
+import textwrap
 import types
 
 default_tip = ct._default_callable_argspec
@@ -55,32 +56,45 @@
         gtest(list.__new__,
                'T.__new__(S, ...) -> a new object with type S, a subtype of T')
         gtest(list.__init__,
-               'Initializes self.  See help(type(self)) for accurate signature.')
+               'x.__init__(...) initializes x; see help(type(x)) for signature')
         append_doc =  "L.append(object) -> None -- append object to end"
         gtest(list.append, append_doc)
         gtest([].append, append_doc)
         gtest(List.append, append_doc)
 
-        gtest(types.MethodType, "Create a bound instance method object.")
+        gtest(types.MethodType, "method(function, instance)")
         gtest(SB(), default_tip)
 
+    def test_signature_wrap(self):
+        self.assertEqual(signature(textwrap.TextWrapper), '''\
+(width=70, initial_indent='', subsequent_indent='', expand_tabs=True,
+    replace_whitespace=True, fix_sentence_endings=False, break_long_words=True,
+    drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None,
+    placeholder=' [...]')''')
+
+    def test_docline_truncation(self):
+        def f(): pass
+        f.__doc__ = 'a'*300
+        self.assertEqual(signature(f), '()\n' + 'a' * (ct._MAX_COLS-3) + '...')
+
     def test_multiline_docstring(self):
         # Test fewer lines than max.
-        self.assertEqual(signature(dict),
-                "dict(mapping) -> new dictionary initialized from a mapping object's\n"
-                "(key, value) pairs\n"
-                "dict(iterable) -> new dictionary initialized as if via:\n"
-                "d = {}\n"
-                "for k, v in iterable:"
-                )
+        self.assertEqual(signature(list),
+                "list() -> new empty list\n"
+                "list(iterable) -> new list initialized from iterable's items")
 
-        # Test max lines and line (currently) too long.
-        self.assertEqual(signature(bytes),
-"bytes(string, encoding[, errors]) -> bytes\n"
-"bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer\n"
-#bytes(int) -> bytes object of size given by the parameter initialized with null bytes
-"bytes(int) -> bytes object of size given by the parameter initialized with n...\n"
-"bytes() -> empty bytes object")
+        # Test max lines
+        self.assertEqual(signature(bytes), '''\
+bytes(iterable_of_ints) -> bytes
+bytes(string, encoding[, errors]) -> bytes
+bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
+bytes(int) -> bytes object of size given by the parameter initialized with null bytes
+bytes() -> empty bytes object''')
+
+        # Test more than max lines
+        def f(): pass
+        f.__doc__ = 'a\n' * 15
+        self.assertEqual(signature(f), '()' + '\na' * ct._MAX_LINES)
 
     def test_functions(self):
         def t1(): 'doc'
@@ -109,6 +123,16 @@
                             (tc.__call__, '(ci)'), (tc, '(ci)'), (TC.cm, "(a)"),):
             self.assertEqual(signature(meth), mtip + "\ndoc")
 
+    def test_starred_parameter(self):
+        # test that starred first parameter is *not* removed from argspec
+        class C:
+            def m1(*args): pass
+            def m2(**kwds): pass
+        c = C()
+        for meth, mtip  in ((C.m1, '(*args)'), (c.m1, "(*args)"),
+                                      (C.m2, "(**kwds)"), (c.m2, "(**kwds)"),):
+            self.assertEqual(signature(meth), mtip)
+
     def test_non_ascii_name(self):
         # test that re works to delete a first parameter name that
         # includes non-ascii chars, such as various forms of A.
diff --git a/Lib/test/imghdrdata/python.bmp b/Lib/test/imghdrdata/python.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..675f95191a45fdb3ae845996d6871b86286f848a
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.gif b/Lib/test/imghdrdata/python.gif
new file mode 100644
index 0000000000000000000000000000000000000000..96fd9fef76b10899807d3724c97335f35a03743a
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.jpg b/Lib/test/imghdrdata/python.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..21222c09f5a71d9d86a0323e49ebc5da6639b22f
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.pbm b/Lib/test/imghdrdata/python.pbm
new file mode 100644
--- /dev/null
+++ b/Lib/test/imghdrdata/python.pbm
@@ -0,0 +1,3 @@
+P4
+16 16
+ûñ¿úßÕ­±[ñ¥a_ÁX°°ðððð?ÿÿ
\ No newline at end of file
diff --git a/Lib/test/imghdrdata/python.pgm b/Lib/test/imghdrdata/python.pgm
new file mode 100644
index 0000000000000000000000000000000000000000..8349f2a53a9be1d895a561cc0fd31f91d7d42b33
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.png b/Lib/test/imghdrdata/python.png
new file mode 100644
index 0000000000000000000000000000000000000000..1a987f79fcd248a94fcd1c45934136919cc0ffdd
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.ppm b/Lib/test/imghdrdata/python.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..7d9cdb3215877b4604de4c177fc81ebb645b8290
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.ras b/Lib/test/imghdrdata/python.ras
new file mode 100644
index 0000000000000000000000000000000000000000..130e96f817ed9dd45f411f2f93e0749a4b33ba49
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.sgi b/Lib/test/imghdrdata/python.sgi
new file mode 100644
index 0000000000000000000000000000000000000000..ffe9081c7a5b67ed14285041fd0650f4010bc36d
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.tiff b/Lib/test/imghdrdata/python.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..39d0bfcec02533ade8934a8796aebb8990c9d389
GIT binary patch
[stripped]
diff --git a/Lib/test/imghdrdata/python.xbm b/Lib/test/imghdrdata/python.xbm
new file mode 100644
--- /dev/null
+++ b/Lib/test/imghdrdata/python.xbm
@@ -0,0 +1,6 @@
+#define python_width 16
+#define python_height 16
+static char python_bits[] = {
+  0xDF, 0xFE, 0x8F, 0xFD, 0x5F, 0xFB, 0xAB, 0xFE, 0xB5, 0x8D, 0xDA, 0x8F, 
+  0xA5, 0x86, 0xFA, 0x83, 0x1A, 0x80, 0x0D, 0x80, 0x0D, 0x80, 0x0F, 0xE0, 
+  0x0F, 0xF8, 0x0F, 0xF8, 0x0F, 0xFC, 0xFF, 0xFF, };
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -175,6 +175,40 @@
                         size*"a",
                     )
 
+    def test_mixed_readline_and_read(self):
+        lines = ["Humpty Dumpty sat on a wall,\n",
+                 "Humpty Dumpty had a great fall.\r\n",
+                 "All the king's horses and all the king's men\r",
+                 "Couldn't put Humpty together again."]
+        data = ''.join(lines)
+        def getreader():
+            stream = io.BytesIO(data.encode(self.encoding))
+            return codecs.getreader(self.encoding)(stream)
+
+        # Issue #8260: Test readline() followed by read()
+        f = getreader()
+        self.assertEqual(f.readline(), lines[0])
+        self.assertEqual(f.read(), ''.join(lines[1:]))
+        self.assertEqual(f.read(), '')
+
+        # Issue #16636: Test readline() followed by readlines()
+        f = getreader()
+        self.assertEqual(f.readline(), lines[0])
+        self.assertEqual(f.readlines(), lines[1:])
+        self.assertEqual(f.read(), '')
+
+        # Test read() followed by read()
+        f = getreader()
+        self.assertEqual(f.read(size=40, chars=5), data[:5])
+        self.assertEqual(f.read(), data[5:])
+        self.assertEqual(f.read(), '')
+
+        # Issue #12446: Test read() followed by readlines()
+        f = getreader()
+        self.assertEqual(f.read(size=40, chars=5), data[:5])
+        self.assertEqual(f.readlines(), [lines[0][5:]] + lines[1:])
+        self.assertEqual(f.read(), '')
+
     def test_bug1175396(self):
         s = [
             '<%!--===================================================\r\n',
@@ -2370,8 +2404,6 @@
 
     def test_readline(self):
         for encoding in bytes_transform_encodings:
-            if encoding in ['uu_codec', 'zlib_codec']:
-                continue
             with self.subTest(encoding=encoding):
                 sin = codecs.encode(b"\x80", encoding)
                 reader = codecs.getreader(encoding)(io.BytesIO(sin))
@@ -2522,6 +2554,7 @@
         with self.assertRaisesRegex(exc_type, full_msg) as caught:
             yield caught
         self.assertIsInstance(caught.exception.__cause__, exc_type)
+        self.assertIsNotNone(caught.exception.__cause__.__traceback__)
 
     def raise_obj(self, *args, **kwds):
         # Helper to dynamically change the object raised by a test codec
diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py
--- a/Lib/test/test_concurrent_futures.py
+++ b/Lib/test/test_concurrent_futures.py
@@ -350,6 +350,13 @@
                               SUCCESSFUL_FUTURE]),
                          completed_futures)
 
+    def test_duplicate_futures(self):
+        # Issue 20367. Duplicate futures should not raise exceptions or give
+        # duplicate responses.
+        future1 = self.executor.submit(time.sleep, 2)
+        completed = [f for f in futures.as_completed([future1,future1])]
+        self.assertEqual(len(completed), 1)
+
 
 class ThreadPoolAsCompletedTests(ThreadPoolMixin, AsCompletedTests, unittest.TestCase):
     pass
diff --git a/Lib/test/test_imghdr.py b/Lib/test/test_imghdr.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/test_imghdr.py
@@ -0,0 +1,131 @@
+import imghdr
+import io
+import os
+import unittest
+import warnings
+from test.support import findfile, TESTFN, unlink
+
+TEST_FILES = (
+    ('python.png', 'png'),
+    ('python.gif', 'gif'),
+    ('python.bmp', 'bmp'),
+    ('python.ppm', 'ppm'),
+    ('python.pgm', 'pgm'),
+    ('python.pbm', 'pbm'),
+    ('python.jpg', 'jpeg'),
+    ('python.ras', 'rast'),
+    ('python.sgi', 'rgb'),
+    ('python.tiff', 'tiff'),
+    ('python.xbm', 'xbm')
+)
+
+class UnseekableIO(io.FileIO):
+    def tell(self):
+        raise io.UnsupportedOperation
+
+    def seek(self, *args, **kwargs):
+        raise io.UnsupportedOperation
+
+class TestImghdr(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.testfile = findfile('python.png', subdir='imghdrdata')
+        with open(cls.testfile, 'rb') as stream:
+            cls.testdata = stream.read()
+
+    def tearDown(self):
+        unlink(TESTFN)
+
+    def test_data(self):
+        for filename, expected in TEST_FILES:
+            filename = findfile(filename, subdir='imghdrdata')
+            self.assertEqual(imghdr.what(filename), expected)
+            with open(filename, 'rb') as stream:
+                self.assertEqual(imghdr.what(stream), expected)
+            with open(filename, 'rb') as stream:
+                data = stream.read()
+            self.assertEqual(imghdr.what(None, data), expected)
+            self.assertEqual(imghdr.what(None, bytearray(data)), expected)
+
+    def test_register_test(self):
+        def test_jumbo(h, file):
+            if h.startswith(b'eggs'):
+                return 'ham'
+        imghdr.tests.append(test_jumbo)
+        self.addCleanup(imghdr.tests.pop)
+        self.assertEqual(imghdr.what(None, b'eggs'), 'ham')
+
+    def test_file_pos(self):
+        with open(TESTFN, 'wb') as stream:
+            stream.write(b'ababagalamaga')
+            pos = stream.tell()
+            stream.write(self.testdata)
+        with open(TESTFN, 'rb') as stream:
+            stream.seek(pos)
+            self.assertEqual(imghdr.what(stream), 'png')
+            self.assertEqual(stream.tell(), pos)
+
+    def test_bad_args(self):
+        with self.assertRaises(TypeError):
+            imghdr.what()
+        with self.assertRaises(AttributeError):
+            imghdr.what(None)
+        with self.assertRaises(TypeError):
+            imghdr.what(self.testfile, 1)
+        with self.assertRaises(AttributeError):
+            imghdr.what(os.fsencode(self.testfile))
+        with open(self.testfile, 'rb') as f:
+            with self.assertRaises(AttributeError):
+                imghdr.what(f.fileno())
+
+    def test_invalid_headers(self):
+        for header in (b'\211PN\r\n',
+                       b'\001\331',
+                       b'\x59\xA6',
+                       b'cutecat',
+                       b'000000JFI',
+                       b'GIF80'):
+            self.assertIsNone(imghdr.what(None, header))
+
+    def test_string_data(self):
+        with warnings.catch_warnings():
+            warnings.simplefilter("ignore", BytesWarning)
+            for filename, _ in TEST_FILES:
+                filename = findfile(filename, subdir='imghdrdata')
+                with open(filename, 'rb') as stream:
+                    data = stream.read().decode('latin1')
+                with self.assertRaises(TypeError):
+                    imghdr.what(io.StringIO(data))
+                with self.assertRaises(TypeError):
+                    imghdr.what(None, data)
+
+    def test_missing_file(self):
+        with self.assertRaises(FileNotFoundError):
+            imghdr.what('missing')
+
+    def test_closed_file(self):
+        stream = open(self.testfile, 'rb')
+        stream.close()
+        with self.assertRaises(ValueError) as cm:
+            imghdr.what(stream)
+        stream = io.BytesIO(self.testdata)
+        stream.close()
+        with self.assertRaises(ValueError) as cm:
+            imghdr.what(stream)
+
+    def test_unseekable(self):
+        with open(TESTFN, 'wb') as stream:
+            stream.write(self.testdata)
+        with UnseekableIO(TESTFN, 'rb') as stream:
+            with self.assertRaises(io.UnsupportedOperation):
+                imghdr.what(stream)
+
+    def test_output_stream(self):
+        with open(TESTFN, 'wb') as stream:
+            stream.write(self.testdata)
+            stream.seek(0)
+            with self.assertRaises(OSError) as cm:
+                imghdr.what(stream)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py
--- a/Lib/test/test_sundry.py
+++ b/Lib/test/test_sundry.py
@@ -6,7 +6,7 @@
 
 class TestUntestedModules(unittest.TestCase):
     def test_untested_modules_can_be_imported(self):
-        untested = ('bdb', 'encodings', 'formatter', 'imghdr',
+        untested = ('bdb', 'encodings', 'formatter',
                     'nturl2path', 'tabnanny')
         with support.check_warnings(quiet=True):
             for name in untested:
diff --git a/Lib/wsgiref/__init__.py b/Lib/wsgiref/__init__.py
--- a/Lib/wsgiref/__init__.py
+++ b/Lib/wsgiref/__init__.py
@@ -1,4 +1,4 @@
-"""wsgiref -- a WSGI (PEP 333) Reference Library
+"""wsgiref -- a WSGI (PEP 3333) Reference Library
 
 Current Contents:
 
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -725,6 +725,7 @@
 Torsten Landschoff
 Łukasz Langa
 Tino Lange
+Glenn Langford
 Andrew Langmead
 Detlef Lannert
 Soren Larsen
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -48,6 +48,16 @@
 Library
 -------
 
+- Issue #20367: Fix behavior of concurrent.futures.as_completed() for
+  duplicate arguments.  Patch by Glenn Langford.
+
+- Issue #8260: The read(), readline() and readlines() methods of
+  codecs.StreamReader returned incomplete data when were called after
+  readline() or read(size).  Based on patch by Amaury Forgeot d'Arc.
+
+- Issue #20105: the codec exception chaining now correctly sets the
+  traceback of the original exception as its __traceback__ attribute.
+
 - asyncio: Various improvements and small changes not all covered by
   issues listed below.  E.g. wait_for() now cancels the inner task if
   the timeout occcurs; tweaked the set of exported symbols; renamed
@@ -145,6 +155,9 @@
 IDLE
 ----
 
+- Issue #17721: Remove non-functional configuration dialog help button until we
+  make it actually gives some help when clicked. Patch by Guilherme Simões.
+
 - Issue #17390: Add Python version to Idle editor window title bar.
   Original patches by Edmond Burnett and Kent Johnson.
 
@@ -154,9 +167,15 @@
 Tests
 -----
 
+- Issue #19990: Added tests for the imghdr module.  Based on patch by
+  Claudiu Popa.
+
 - Issue #20358: Tests for curses.window.overlay and curses.window.overwrite
   no longer specify min{row,col} > max{row,col}.
 
+- Issue #19804: The test_find_mac test in test_uuid is now skipped if the
+  ifconfig executable is not available.
+
 - Issue #19886: Use better estimated memory requirements for bigmem tests.
 
 Tools/Demos
@@ -553,9 +572,6 @@
 Tests
 -----
 
-- Issue #19804: The test_find_mac test in test_uuid is now skipped if the
-  ifconfig executable is not available.
-
 - Issue #20055: Fix test_shutil under Windows with symlink privileges held.
   Patch by Vajrasky Kok.
 
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -6149,7 +6149,7 @@
 load(UnpicklerObject *self)
 {
     PyObject *value = NULL;
-    char *s;
+    char *s = NULL;
 
     self->num_marks = 0;
     self->proto = 0;
diff --git a/Modules/audioop.c b/Modules/audioop.c
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -1304,6 +1304,7 @@
             "weightA should be >= 1, weightB should be >= 0");
         return NULL;
     }
+    assert(fragment->len >= 0);
     if (fragment->len % bytes_per_frame != 0) {
         PyErr_SetString(AudioopError, "not a whole number of frames");
         return NULL;
@@ -1370,7 +1371,7 @@
            case ceiling(len/inrate) * outrate. */
 
         /* compute ceiling(len/inrate) without overflow */
-        Py_ssize_t q = len > 0 ? 1 + (len - 1) / inrate : 0;
+        Py_ssize_t q = 1 + (len - 1) / inrate;
         if (outrate > PY_SSIZE_T_MAX / q / bytes_per_frame)
             str = NULL;
         else
@@ -1608,7 +1609,7 @@
     Py_ssize_t i;
     int step, valpred, delta,
         index, sign, vpdiff, diff;
-    PyObject *rv, *str;
+    PyObject *rv = NULL, *str;
     int outputbuffer = 0, bufferstep;
 
     if (!audioop_check_parameters(fragment->len, width))
@@ -1626,9 +1627,10 @@
         index = 0;
     } else if (!PyTuple_Check(state)) {
         PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
-        return NULL;
-    } else if (!PyArg_ParseTuple(state, "ii", &valpred, &index))
-        return NULL;
+        goto exit;
+    } else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) {
+        goto exit;
+    }
 
     step = stepsizeTable[index];
     bufferstep = 1;
@@ -1704,6 +1706,8 @@
         bufferstep = !bufferstep;
     }
     rv = Py_BuildValue("(O(ii))", str, valpred, index);
+
+  exit:
     Py_DECREF(str);
     return rv;
 }
diff --git a/Modules/binascii.c b/Modules/binascii.c
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -195,6 +195,11 @@
     type = 'Py_buffer'
     converter = 'ascii_buffer_converter'
     impl_by_reference = True
+    c_default = "{NULL, NULL}"
+
+    def cleanup(self):
+        name = self.name
+        return "".join(["if (", name, ".obj)\n   PyBuffer_Release(&", name, ");\n"])
 
 [python start generated code]*/
 /*[python end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h
--- a/Modules/clinic/binascii.c.h
+++ b/Modules/clinic/binascii.c.h
@@ -16,7 +16,7 @@
 binascii_a2b_uu(PyModuleDef *module, PyObject *args)
 {
     PyObject *return_value = NULL;
-    Py_buffer data;
+    Py_buffer data = {NULL, NULL};
 
     if (!PyArg_ParseTuple(args,
         "O&:a2b_uu",
@@ -25,6 +25,10 @@
     return_value = binascii_a2b_uu_impl(module, &data);
 
 exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
     return return_value;
 }
 
@@ -72,7 +76,7 @@
 binascii_a2b_base64(PyModuleDef *module, PyObject *args)
 {
     PyObject *return_value = NULL;
-    Py_buffer data;
+    Py_buffer data = {NULL, NULL};
 
     if (!PyArg_ParseTuple(args,
         "O&:a2b_base64",
@@ -81,6 +85,10 @@
     return_value = binascii_a2b_base64_impl(module, &data);
 
 exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
     return return_value;
 }
 
@@ -128,7 +136,7 @@
 binascii_a2b_hqx(PyModuleDef *module, PyObject *args)
 {
     PyObject *return_value = NULL;
-    Py_buffer data;
+    Py_buffer data = {NULL, NULL};
 
     if (!PyArg_ParseTuple(args,
         "O&:a2b_hqx",
@@ -137,6 +145,10 @@
     return_value = binascii_a2b_hqx_impl(module, &data);
 
 exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
     return return_value;
 }
 
@@ -350,7 +362,7 @@
 binascii_a2b_hex(PyModuleDef *module, PyObject *args)
 {
     PyObject *return_value = NULL;
-    Py_buffer hexstr;
+    Py_buffer hexstr = {NULL, NULL};
 
     if (!PyArg_ParseTuple(args,
         "O&:a2b_hex",
@@ -359,6 +371,10 @@
     return_value = binascii_a2b_hex_impl(module, &hexstr);
 
 exit:
+    /* Cleanup for hexstr */
+    if (hexstr.obj)
+       PyBuffer_Release(&hexstr);
+
     return return_value;
 }
 
@@ -377,7 +393,7 @@
 {
     PyObject *return_value = NULL;
     static char *_keywords[] = {"data", "header", NULL};
-    Py_buffer data;
+    Py_buffer data = {NULL, NULL};
     int header = 0;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
@@ -387,6 +403,10 @@
     return_value = binascii_a2b_qp_impl(module, &data, header);
 
 exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
     return return_value;
 }
 
@@ -427,4 +447,4 @@
 
     return return_value;
 }
-/*[clinic end generated code: checksum=abe48ca8020fa3ec25e13bd9fa7414f6b3ee2946]*/
+/*[clinic end generated code: checksum=8180e5be47a110ae8c89263a7c12a91d80754f60]*/
diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h
new file mode 100644
--- /dev/null
+++ b/Modules/clinic/zlibmodule.c.h
@@ -0,0 +1,411 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(zlib_compress__doc__,
+"compress(module, bytes, level=Z_DEFAULT_COMPRESSION)\n"
+"Returns a bytes object containing compressed data.\n"
+"\n"
+"  bytes\n"
+"    Binary data to be compressed.\n"
+"  level\n"
+"    Compression level, in 0-9.");
+
+#define ZLIB_COMPRESS_METHODDEF    \
+    {"compress", (PyCFunction)zlib_compress, METH_VARARGS, zlib_compress__doc__},
+
+static PyObject *
+zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int level);
+
+static PyObject *
+zlib_compress(PyModuleDef *module, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    Py_buffer bytes = {NULL, NULL};
+    int level = Z_DEFAULT_COMPRESSION;
+
+    if (!PyArg_ParseTuple(args,
+        "y*|i:compress",
+        &bytes, &level))
+        goto exit;
+    return_value = zlib_compress_impl(module, &bytes, level);
+
+exit:
+    /* Cleanup for bytes */
+    if (bytes.obj)
+       PyBuffer_Release(&bytes);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_decompress__doc__,
+"decompress(module, data, wbits=MAX_WBITS, bufsize=DEF_BUF_SIZE)\n"
+"Returns a bytes object containing the uncompressed data.\n"
+"\n"
+"  data\n"
+"    Compressed data.\n"
+"  wbits\n"
+"    The window buffer size.\n"
+"  bufsize\n"
+"    The initial output buffer size.");
+
+#define ZLIB_DECOMPRESS_METHODDEF    \
+    {"decompress", (PyCFunction)zlib_decompress, METH_VARARGS, zlib_decompress__doc__},
+
+static PyObject *
+zlib_decompress_impl(PyModuleDef *module, Py_buffer *data, int wbits, unsigned int bufsize);
+
+static PyObject *
+zlib_decompress(PyModuleDef *module, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    Py_buffer data = {NULL, NULL};
+    int wbits = MAX_WBITS;
+    unsigned int bufsize = DEF_BUF_SIZE;
+
+    if (!PyArg_ParseTuple(args,
+        "y*|iO&:decompress",
+        &data, &wbits, uint_converter, &bufsize))
+        goto exit;
+    return_value = zlib_decompress_impl(module, &data, wbits, bufsize);
+
+exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_compressobj__doc__,
+"compressobj(module, level=Z_DEFAULT_COMPRESSION, method=DEFLATED, wbits=MAX_WBITS, memLevel=DEF_MEM_LEVEL, strategy=Z_DEFAULT_STRATEGY, zdict=None)\n"
+"Return a compressor object.\n"
+"\n"
+"  level\n"
+"    The compression level (an integer in the range 0-9; default is 6).\n"
+"    Higher compression levels are slower, but produce smaller results.\n"
+"  method\n"
+"    The compression algorithm.  If given, this must be DEFLATED.\n"
+"  wbits\n"
+"    The base two logarithm of the window size (range: 8..15).\n"
+"  memLevel\n"
+"    Controls the amount of memory used for internal compression state.\n"
+"    Valid values range from 1 to 9.  Higher values result in higher memory\n"
+"    usage, faster compression, and smaller output.\n"
+"  strategy\n"
+"    Used to tune the compression algorithm.  Possible values are\n"
+"    Z_DEFAULT_STRATEGY, Z_FILTERED, and Z_HUFFMAN_ONLY.\n"
+"  zdict\n"
+"    The predefined compression dictionary - a sequence of bytes\n"
+"    containing subsequences that are likely to occur in the input data.");
+
+#define ZLIB_COMPRESSOBJ_METHODDEF    \
+    {"compressobj", (PyCFunction)zlib_compressobj, METH_VARARGS|METH_KEYWORDS, zlib_compressobj__doc__},
+
+static PyObject *
+zlib_compressobj_impl(PyModuleDef *module, int level, int method, int wbits, int memLevel, int strategy, Py_buffer *zdict);
+
+static PyObject *
+zlib_compressobj(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"level", "method", "wbits", "memLevel", "strategy", "zdict", NULL};
+    int level = Z_DEFAULT_COMPRESSION;
+    int method = DEFLATED;
+    int wbits = MAX_WBITS;
+    int memLevel = DEF_MEM_LEVEL;
+    int strategy = Z_DEFAULT_STRATEGY;
+    Py_buffer zdict = {NULL, NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+        "|iiiiiy*:compressobj", _keywords,
+        &level, &method, &wbits, &memLevel, &strategy, &zdict))
+        goto exit;
+    return_value = zlib_compressobj_impl(module, level, method, wbits, memLevel, strategy, &zdict);
+
+exit:
+    /* Cleanup for zdict */
+    if (zdict.obj)
+       PyBuffer_Release(&zdict);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_decompressobj__doc__,
+"decompressobj(module, wbits=MAX_WBITS, zdict=b\'\')\n"
+"Return a decompressor object.\n"
+"\n"
+"  wbits\n"
+"    The window buffer size.\n"
+"  zdict\n"
+"    The predefined compression dictionary.  This must be the same\n"
+"    dictionary as used by the compressor that produced the input data.");
+
+#define ZLIB_DECOMPRESSOBJ_METHODDEF    \
+    {"decompressobj", (PyCFunction)zlib_decompressobj, METH_VARARGS|METH_KEYWORDS, zlib_decompressobj__doc__},
+
+static PyObject *
+zlib_decompressobj_impl(PyModuleDef *module, int wbits, PyObject *zdict);
+
+static PyObject *
+zlib_decompressobj(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"wbits", "zdict", NULL};
+    int wbits = MAX_WBITS;
+    PyObject *zdict = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+        "|iO:decompressobj", _keywords,
+        &wbits, &zdict))
+        goto exit;
+    return_value = zlib_decompressobj_impl(module, wbits, zdict);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_Compress_compress__doc__,
+"compress(self, data)\n"
+"Returns a bytes object containing compressed data.\n"
+"\n"
+"  data\n"
+"    Binary data to be compressed.\n"
+"\n"
+"After calling this function, some of the input data may still\n"
+"be stored in internal buffers for later processing.\n"
+"Call the flush() method to clear these buffers.");
+
+#define ZLIB_COMPRESS_COMPRESS_METHODDEF    \
+    {"compress", (PyCFunction)zlib_Compress_compress, METH_VARARGS, zlib_Compress_compress__doc__},
+
+static PyObject *
+zlib_Compress_compress_impl(compobject *self, Py_buffer *data);
+
+static PyObject *
+zlib_Compress_compress(compobject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    Py_buffer data = {NULL, NULL};
+
+    if (!PyArg_ParseTuple(args,
+        "y*:compress",
+        &data))
+        goto exit;
+    return_value = zlib_Compress_compress_impl(self, &data);
+
+exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_Decompress_decompress__doc__,
+"decompress(self, data, max_length=0)\n"
+"Return a bytes object containing the decompressed version of the data.\n"
+"\n"
+"  data\n"
+"    The binary data to decompress.\n"
+"  max_length\n"
+"    The maximum allowable length of the decompressed data.\n"
+"    Unconsumed input data will be stored in\n"
+"    the unconsumed_tail attribute.\n"
+"\n"
+"After calling this function, some of the input data may still be stored in\n"
+"internal buffers for later processing.\n"
+"Call the flush() method to clear these buffers.");
+
+#define ZLIB_DECOMPRESS_DECOMPRESS_METHODDEF    \
+    {"decompress", (PyCFunction)zlib_Decompress_decompress, METH_VARARGS, zlib_Decompress_decompress__doc__},
+
+static PyObject *
+zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, unsigned int max_length);
+
+static PyObject *
+zlib_Decompress_decompress(compobject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    Py_buffer data = {NULL, NULL};
+    unsigned int max_length = 0;
+
+    if (!PyArg_ParseTuple(args,
+        "y*|O&:decompress",
+        &data, uint_converter, &max_length))
+        goto exit;
+    return_value = zlib_Decompress_decompress_impl(self, &data, max_length);
+
+exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_Compress_flush__doc__,
+"flush(self, mode=Z_FINISH)\n"
+"Return a bytes object containing any remaining compressed data.\n"
+"\n"
+"  mode\n"
+"    One of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH.\n"
+"    If mode == Z_FINISH, the compressor object can no longer be\n"
+"    used after calling the flush() method.  Otherwise, more data\n"
+"    can still be compressed.");
+
+#define ZLIB_COMPRESS_FLUSH_METHODDEF    \
+    {"flush", (PyCFunction)zlib_Compress_flush, METH_VARARGS, zlib_Compress_flush__doc__},
+
+static PyObject *
+zlib_Compress_flush_impl(compobject *self, int mode);
+
+static PyObject *
+zlib_Compress_flush(compobject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    int mode = Z_FINISH;
+
+    if (!PyArg_ParseTuple(args,
+        "|i:flush",
+        &mode))
+        goto exit;
+    return_value = zlib_Compress_flush_impl(self, mode);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_Compress_copy__doc__,
+"copy(self)\n"
+"Return a copy of the compression object.");
+
+#define ZLIB_COMPRESS_COPY_METHODDEF    \
+    {"copy", (PyCFunction)zlib_Compress_copy, METH_NOARGS, zlib_Compress_copy__doc__},
+
+static PyObject *
+zlib_Compress_copy_impl(compobject *self);
+
+static PyObject *
+zlib_Compress_copy(compobject *self, PyObject *Py_UNUSED(ignored))
+{
+    return zlib_Compress_copy_impl(self);
+}
+
+PyDoc_STRVAR(zlib_Decompress_copy__doc__,
+"copy(self)\n"
+"Return a copy of the decompression object.");
+
+#define ZLIB_DECOMPRESS_COPY_METHODDEF    \
+    {"copy", (PyCFunction)zlib_Decompress_copy, METH_NOARGS, zlib_Decompress_copy__doc__},
+
+static PyObject *
+zlib_Decompress_copy_impl(compobject *self);
+
+static PyObject *
+zlib_Decompress_copy(compobject *self, PyObject *Py_UNUSED(ignored))
+{
+    return zlib_Decompress_copy_impl(self);
+}
+
+PyDoc_STRVAR(zlib_Decompress_flush__doc__,
+"flush(self, length=DEF_BUF_SIZE)\n"
+"Return a bytes object containing any remaining decompressed data.\n"
+"\n"
+"  length\n"
+"    the initial size of the output buffer.");
+
+#define ZLIB_DECOMPRESS_FLUSH_METHODDEF    \
+    {"flush", (PyCFunction)zlib_Decompress_flush, METH_VARARGS, zlib_Decompress_flush__doc__},
+
+static PyObject *
+zlib_Decompress_flush_impl(compobject *self, unsigned int length);
+
+static PyObject *
+zlib_Decompress_flush(compobject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    unsigned int length = DEF_BUF_SIZE;
+
+    if (!PyArg_ParseTuple(args,
+        "|O&:flush",
+        uint_converter, &length))
+        goto exit;
+    return_value = zlib_Decompress_flush_impl(self, length);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_adler32__doc__,
+"adler32(module, data, value=1)\n"
+"Compute an Adler-32 checksum of data.\n"
+"\n"
+"  value\n"
+"    Starting value of the checksum.\n"
+"\n"
+"The returned checksum is an integer.");
+
+#define ZLIB_ADLER32_METHODDEF    \
+    {"adler32", (PyCFunction)zlib_adler32, METH_VARARGS, zlib_adler32__doc__},
+
+static PyObject *
+zlib_adler32_impl(PyModuleDef *module, Py_buffer *data, unsigned int value);
+
+static PyObject *
+zlib_adler32(PyModuleDef *module, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    Py_buffer data = {NULL, NULL};
+    unsigned int value = 1;
+
+    if (!PyArg_ParseTuple(args,
+        "y*|I:adler32",
+        &data, &value))
+        goto exit;
+    return_value = zlib_adler32_impl(module, &data, value);
+
+exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(zlib_crc32__doc__,
+"crc32(module, data, value=0)\n"
+"Compute a CRC-32 checksum of data.\n"
+"\n"
+"  value\n"
+"    Starting value of the checksum.\n"
+"\n"
+"The returned checksum is an integer.");
+
+#define ZLIB_CRC32_METHODDEF    \
+    {"crc32", (PyCFunction)zlib_crc32, METH_VARARGS, zlib_crc32__doc__},
+
+static PyObject *
+zlib_crc32_impl(PyModuleDef *module, Py_buffer *data, unsigned int value);
+
+static PyObject *
+zlib_crc32(PyModuleDef *module, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    Py_buffer data = {NULL, NULL};
+    unsigned int value = 0;
+
+    if (!PyArg_ParseTuple(args,
+        "y*|I:crc32",
+        &data, &value))
+        goto exit;
+    return_value = zlib_crc32_impl(module, &data, value);
+
+exit:
+    /* Cleanup for data */
+    if (data.obj)
+       PyBuffer_Release(&data);
+
+    return return_value;
+}
+/*[clinic end generated code: checksum=04f94bbaf2652717753e237e4021bf6c92ddffdd]*/
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -28,10 +28,9 @@
 #else
 #  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
 #endif
-#define DEF_WBITS MAX_WBITS
 
-/* The output buffer will be increased in chunks of DEFAULTALLOC bytes. */
-#define DEFAULTALLOC (16*1024)
+/* Initial buffer size. */
+#define DEF_BUF_SIZE (16*1024)
 
 static PyTypeObject Comptype;
 static PyTypeObject Decomptype;
@@ -82,42 +81,13 @@
 }
 
 /*[clinic input]
+output preset file
 module zlib
 class zlib.Compress "compobject *" "&Comptype"
 class zlib.Decompress "compobject *" "&Decomptype"
 [clinic start generated code]*/
 /*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
 
-PyDoc_STRVAR(compressobj__doc__,
-"compressobj(level=-1, method=DEFLATED, wbits=15, memlevel=8,\n"
-"            strategy=Z_DEFAULT_STRATEGY[, zdict])\n"
-" -- Return a compressor object.\n"
-"\n"
-"level is the compression level (an integer in the range 0-9; default is 6).\n"
-"Higher compression levels are slower, but produce smaller results.\n"
-"\n"
-"method is the compression algorithm. If given, this must be DEFLATED.\n"
-"\n"
-"wbits is the base two logarithm of the window size (range: 8..15).\n"
-"\n"
-"memlevel controls the amount of memory used for internal compression state.\n"
-"Valid values range from 1 to 9. Higher values result in higher memory usage,\n"
-"faster compression, and smaller output.\n"
-"\n"
-"strategy is used to tune the compression algorithm. Possible values are\n"
-"Z_DEFAULT_STRATEGY, Z_FILTERED, and Z_HUFFMAN_ONLY.\n"
-"\n"
-"zdict is the predefined compression dictionary - a sequence of bytes\n"
-"containing subsequences that are likely to occur in the input data.");
-
-PyDoc_STRVAR(decompressobj__doc__,
-"decompressobj([wbits[, zdict]]) -- Return a decompressor object.\n"
-"\n"
-"Optional arg wbits is the window buffer size.\n"
-"\n"
-"Optional arg zdict is the predefined compression dictionary. This must be\n"
-"the same dictionary as used by the compressor that produced the input data.");
-
 static compobject *
 newcompobject(PyTypeObject *type)
 {
@@ -165,70 +135,20 @@
 }
 
 /*[clinic input]
+zlib.compress
 
-zlib.compress
     bytes: Py_buffer
         Binary data to be compressed.
-    [
-    level: int
+    level: int(c_default="Z_DEFAULT_COMPRESSION") = Z_DEFAULT_COMPRESSION
         Compression level, in 0-9.
-    ]
     /
 
-Returns compressed string.
-
+Returns a bytes object containing compressed data.
 [clinic start generated code]*/
 
-PyDoc_STRVAR(zlib_compress__doc__,
-"compress(module, bytes, [level])\n"
-"Returns compressed string.\n"
-"\n"
-"  bytes\n"
-"    Binary data to be compressed.\n"
-"  level\n"
-"    Compression level, in 0-9.");
-
-#define ZLIB_COMPRESS_METHODDEF    \
-    {"compress", (PyCFunction)zlib_compress, METH_VARARGS, zlib_compress__doc__},
-
 static PyObject *
-zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int group_right_1, int level);
-
-static PyObject *
-zlib_compress(PyModuleDef *module, PyObject *args)
-{
-    PyObject *return_value = NULL;
-    Py_buffer bytes = {NULL, NULL};
-    int group_right_1 = 0;
-    int level = 0;
-
-    switch (PyTuple_GET_SIZE(args)) {
-        case 1:
-            if (!PyArg_ParseTuple(args, "y*:compress", &bytes))
-                goto exit;
-            break;
-        case 2:
-            if (!PyArg_ParseTuple(args, "y*i:compress", &bytes, &level))
-                goto exit;
-            group_right_1 = 1;
-            break;
-        default:
-            PyErr_SetString(PyExc_TypeError, "zlib.compress requires 1 to 2 arguments");
-            goto exit;
-    }
-    return_value = zlib_compress_impl(module, &bytes, group_right_1, level);
-
-exit:
-    /* Cleanup for bytes */
-    if (bytes.obj)
-       PyBuffer_Release(&bytes);
-
-    return return_value;
-}
-
-static PyObject *
-zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int group_right_1, int level)
-/*[clinic end generated code: checksum=ce8d4c0a17ecd79c3ffcc032dcdf8ac6830ded1e]*/
+zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int level)
+/*[clinic end generated code: checksum=5d7dd4588788efd3516e5f4225050d6413632601]*/
 {
     PyObject *ReturnVal = NULL;
     Byte *input, *output = NULL;
@@ -236,9 +156,6 @@
     int err;
     z_stream zst;
 
-    if (!group_right_1)
-        level = Z_DEFAULT_COMPRESSION;
-
     if ((size_t)bytes->len > UINT_MAX) {
         PyErr_SetString(PyExc_OverflowError,
                         "Size does not fit in an unsigned int");
@@ -312,6 +229,7 @@
 class uint_converter(CConverter):
     type = 'unsigned int'
     converter = 'uint_converter'
+    c_ignored_default = "0"
 
 [python start generated code]*/
 /*[python end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
@@ -347,35 +265,38 @@
     return 1;
 }
 
-PyDoc_STRVAR(decompress__doc__,
-"decompress(string[, wbits[, bufsize]]) -- Return decompressed string.\n"
-"\n"
-"Optional arg wbits is the window buffer size.  Optional arg bufsize is\n"
-"the initial output buffer size.");
+/*[clinic input]
+zlib.decompress
+
+    data: Py_buffer
+        Compressed data.
+    wbits: int(c_default="MAX_WBITS") = MAX_WBITS
+        The window buffer size.
+    bufsize: uint(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE
+        The initial output buffer size.
+    /
+
+Returns a bytes object containing the uncompressed data.
+[clinic start generated code]*/
 
 static PyObject *
-PyZlib_decompress(PyObject *self, PyObject *args)
+zlib_decompress_impl(PyModuleDef *module, Py_buffer *data, int wbits, unsigned int bufsize)
+/*[clinic end generated code: checksum=9e5464e72df9cb5fee73df662dbcaed867e01d32]*/
 {
     PyObject *result_str = NULL;
-    Py_buffer pinput;
     Byte *input;
     unsigned int length;
     int err;
-    int wsize=DEF_WBITS;
-    unsigned int bufsize = DEFAULTALLOC, new_bufsize;
+    unsigned int new_bufsize;
     z_stream zst;
 
-    if (!PyArg_ParseTuple(args, "y*|iO&:decompress",
-                          &pinput, &wsize, uint_converter, &bufsize))
-        return NULL;
-
-    if ((size_t)pinput.len > UINT_MAX) {
+    if ((size_t)data->len > UINT_MAX) {
         PyErr_SetString(PyExc_OverflowError,
                         "Size does not fit in an unsigned int");
         goto error;
     }
-    input = pinput.buf;
-    length = (unsigned int)pinput.len;
+    input = data->buf;
+    length = (unsigned int)data->len;
 
     if (bufsize == 0)
         bufsize = 1;
@@ -391,7 +312,7 @@
     zst.zfree = PyZlib_Free;
     zst.next_out = (Byte *)PyBytes_AS_STRING(result_str);
     zst.next_in = (Byte *)input;
-    err = inflateInit2(&zst, wsize);
+    err = inflateInit2(&zst, wbits);
 
     switch(err) {
     case(Z_OK):
@@ -457,32 +378,45 @@
     if (_PyBytes_Resize(&result_str, zst.total_out) < 0)
         goto error;
 
-    PyBuffer_Release(&pinput);
     return result_str;
 
  error:
-    PyBuffer_Release(&pinput);
     Py_XDECREF(result_str);
     return NULL;
 }
 
+/*[clinic input]
+zlib.compressobj
+
+    level: int(c_default="Z_DEFAULT_COMPRESSION") = Z_DEFAULT_COMPRESSION
+        The compression level (an integer in the range 0-9; default is 6).
+        Higher compression levels are slower, but produce smaller results.
+    method: int(c_default="DEFLATED") = DEFLATED
+        The compression algorithm.  If given, this must be DEFLATED.
+    wbits: int(c_default="MAX_WBITS") = MAX_WBITS
+        The base two logarithm of the window size (range: 8..15).
+    memLevel: int(c_default="DEF_MEM_LEVEL") = DEF_MEM_LEVEL
+        Controls the amount of memory used for internal compression state.
+        Valid values range from 1 to 9.  Higher values result in higher memory
+        usage, faster compression, and smaller output.
+    strategy: int(c_default="Z_DEFAULT_STRATEGY") = Z_DEFAULT_STRATEGY
+        Used to tune the compression algorithm.  Possible values are
+        Z_DEFAULT_STRATEGY, Z_FILTERED, and Z_HUFFMAN_ONLY.
+    zdict: Py_buffer = None
+        The predefined compression dictionary - a sequence of bytes
+        containing subsequences that are likely to occur in the input data.
+
+Return a compressor object.
+[clinic start generated code]*/
+
 static PyObject *
-PyZlib_compressobj(PyObject *selfptr, PyObject *args, PyObject *kwargs)
+zlib_compressobj_impl(PyModuleDef *module, int level, int method, int wbits, int memLevel, int strategy, Py_buffer *zdict)
+/*[clinic end generated code: checksum=89e5a6c1449caa9ed76f1baad066600e985151a9]*/
 {
     compobject *self = NULL;
-    int level=Z_DEFAULT_COMPRESSION, method=DEFLATED;
-    int wbits=MAX_WBITS, memLevel=DEF_MEM_LEVEL, strategy=0, err;
-    Py_buffer zdict;
-    static char *kwlist[] = {"level", "method", "wbits",
-                             "memLevel", "strategy", "zdict", NULL};
+    int err;
 
-    zdict.buf = NULL; /* Sentinel, so we can tell whether zdict was supplied. */
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iiiiiy*:compressobj",
-                                     kwlist, &level, &method, &wbits,
-                                     &memLevel, &strategy, &zdict))
-        return NULL;
-
-    if (zdict.buf != NULL && (size_t)zdict.len > UINT_MAX) {
+    if (zdict->buf != NULL && (size_t)zdict->len > UINT_MAX) {
         PyErr_SetString(PyExc_OverflowError,
                         "zdict length does not fit in an unsigned int");
         goto error;
@@ -500,11 +434,11 @@
     switch(err) {
     case (Z_OK):
         self->is_initialised = 1;
-        if (zdict.buf == NULL) {
+        if (zdict->buf == NULL) {
             goto success;
         } else {
             err = deflateSetDictionary(&self->zst,
-                                       zdict.buf, (unsigned int)zdict.len);
+                                       zdict->buf, (unsigned int)zdict->len);
             switch (err) {
             case (Z_OK):
                 goto success;
@@ -532,22 +466,28 @@
     Py_XDECREF(self);
     self = NULL;
  success:
-    if (zdict.buf != NULL)
-        PyBuffer_Release(&zdict);
     return (PyObject*)self;
 }
 
+/*[clinic input]
+zlib.decompressobj
+
+    wbits: int(c_default="MAX_WBITS") = MAX_WBITS
+        The window buffer size.
+    zdict: object(c_default="NULL") = b''
+        The predefined compression dictionary.  This must be the same
+        dictionary as used by the compressor that produced the input data.
+
+Return a decompressor object.
+[clinic start generated code]*/
+
 static PyObject *
-PyZlib_decompressobj(PyObject *selfptr, PyObject *args, PyObject *kwargs)
+zlib_decompressobj_impl(PyModuleDef *module, int wbits, PyObject *zdict)
+/*[clinic end generated code: checksum=8ccd583fbd631798566d415933cd44440c8a74b5]*/
 {
-    static char *kwlist[] = {"wbits", "zdict", NULL};
-    int wbits=DEF_WBITS, err;
+    int err;
     compobject *self;
-    PyObject *zdict=NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:decompressobj",
-                                     kwlist, &wbits, &zdict))
-        return NULL;
     if (zdict != NULL && !PyObject_CheckBuffer(zdict)) {
         PyErr_SetString(PyExc_TypeError,
                         "zdict argument must support the buffer protocol");
@@ -615,37 +555,41 @@
     Dealloc(self);
 }
 
-PyDoc_STRVAR(comp_compress__doc__,
-"compress(data) -- Return a string containing data compressed.\n"
-"\n"
-"After calling this function, some of the input data may still\n"
-"be stored in internal buffers for later processing.\n"
-"Call the flush() method to clear these buffers.");
+/*[clinic input]
+zlib.Compress.compress
 
+    data: Py_buffer
+        Binary data to be compressed.
+    /
+
+Returns a bytes object containing compressed data.
+
+After calling this function, some of the input data may still
+be stored in internal buffers for later processing.
+Call the flush() method to clear these buffers.
+[clinic start generated code]*/
 
 static PyObject *
-PyZlib_objcompress(compobject *self, PyObject *args)
+zlib_Compress_compress_impl(compobject *self, Py_buffer *data)
+/*[clinic end generated code: checksum=5d5cd791cbc6a7f4b6de4ec12c085c88d4d3e31c]*/
 {
     int err;
     unsigned int inplen;
-    unsigned int length = DEFAULTALLOC, new_length;
-    PyObject *RetVal = NULL;
-    Py_buffer pinput;
+    unsigned int length = DEF_BUF_SIZE, new_length;
+    PyObject *RetVal;
     Byte *input;
     unsigned long start_total_out;
 
-    if (!PyArg_ParseTuple(args, "y*:compress", &pinput))
-        return NULL;
-    if ((size_t)pinput.len > UINT_MAX) {
+    if ((size_t)data->len > UINT_MAX) {
         PyErr_SetString(PyExc_OverflowError,
                         "Size does not fit in an unsigned int");
-        goto error_outer;
+        return NULL;
     }
-    input = pinput.buf;
-    inplen = (unsigned int)pinput.len;
+    input = data->buf;
+    inplen = (unsigned int)data->len;
 
     if (!(RetVal = PyBytes_FromStringAndSize(NULL, length)))
-        goto error_outer;
+        return NULL;
 
     ENTER_ZLIB(self);
 
@@ -668,7 +612,7 @@
             new_length = UINT_MAX;
         if (_PyBytes_Resize(&RetVal, new_length) < 0) {
             Py_CLEAR(RetVal);
-            goto error;
+            goto done;
         }
         self->zst.next_out =
             (unsigned char *)PyBytes_AS_STRING(RetVal) + length;
@@ -686,18 +630,15 @@
 
     if (err != Z_OK && err != Z_BUF_ERROR) {
         zlib_error(self->zst, err, "while compressing data");
-        Py_DECREF(RetVal);
-        RetVal = NULL;
-        goto error;
+        Py_CLEAR(RetVal);
+        goto done;
     }
     if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) {
         Py_CLEAR(RetVal);
     }
 
- error:
+ done:
     LEAVE_ZLIB(self);
- error_outer:
-    PyBuffer_Release(&pinput);
     return RetVal;
 }
 
@@ -745,7 +686,6 @@
 }
 
 /*[clinic input]
-
 zlib.Decompress.decompress
 
     data: Py_buffer
@@ -756,61 +696,19 @@
         the unconsumed_tail attribute.
     /
 
-Return a string containing the decompressed version of the data.
+Return a bytes object containing the decompressed version of the data.
 
 After calling this function, some of the input data may still be stored in
 internal buffers for later processing.
 Call the flush() method to clear these buffers.
 [clinic start generated code]*/
 
-PyDoc_STRVAR(zlib_Decompress_decompress__doc__,
-"decompress(self, data, max_length=0)\n"
-"Return a string containing the decompressed version of the data.\n"
-"\n"
-"  data\n"
-"    The binary data to decompress.\n"
-"  max_length\n"
-"    The maximum allowable length of the decompressed data.\n"
-"    Unconsumed input data will be stored in\n"
-"    the unconsumed_tail attribute.\n"
-"\n"
-"After calling this function, some of the input data may still be stored in\n"
-"internal buffers for later processing.\n"
-"Call the flush() method to clear these buffers.");
-
-#define ZLIB_DECOMPRESS_DECOMPRESS_METHODDEF    \
-    {"decompress", (PyCFunction)zlib_Decompress_decompress, METH_VARARGS, zlib_Decompress_decompress__doc__},
-
-static PyObject *
-zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, unsigned int max_length);
-
-static PyObject *
-zlib_Decompress_decompress(compobject *self, PyObject *args)
-{
-    PyObject *return_value = NULL;
-    Py_buffer data = {NULL, NULL};
-    unsigned int max_length = 0;
-
-    if (!PyArg_ParseTuple(args,
-        "y*|O&:decompress",
-        &data, uint_converter, &max_length))
-        goto exit;
-    return_value = zlib_Decompress_decompress_impl(self, &data, max_length);
-
-exit:
-    /* Cleanup for data */
-    if (data.obj)
-       PyBuffer_Release(&data);
-
-    return return_value;
-}
-
 static PyObject *
 zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, unsigned int max_length)
-/*[clinic end generated code: checksum=b7fd2e3b23430f57f5a84817189575bc46464901]*/
+/*[clinic end generated code: checksum=755cccc9087bfe55486b7e15fa7e2ab60b4c86d6]*/
 {
     int err;
-    unsigned int old_length, length = DEFAULTALLOC;
+    unsigned int old_length, length = DEF_BUF_SIZE;
     PyObject *RetVal = NULL;
     unsigned long start_total_out;
 
@@ -927,29 +825,31 @@
     return RetVal;
 }
 
-PyDoc_STRVAR(comp_flush__doc__,
-"flush( [mode] ) -- Return a string containing any remaining compressed data.\n"
-"\n"
-"mode can be one of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH; the\n"
-"default value used when mode is not specified is Z_FINISH.\n"
-"If mode == Z_FINISH, the compressor object can no longer be used after\n"
-"calling the flush() method.  Otherwise, more data can still be compressed.");
+/*[clinic input]
+zlib.Compress.flush
+
+    mode: int(c_default="Z_FINISH") = Z_FINISH
+        One of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH.
+        If mode == Z_FINISH, the compressor object can no longer be
+        used after calling the flush() method.  Otherwise, more data
+        can still be compressed.
+    /
+
+Return a bytes object containing any remaining compressed data.
+[clinic start generated code]*/
 
 static PyObject *
-PyZlib_flush(compobject *self, PyObject *args)
+zlib_Compress_flush_impl(compobject *self, int mode)
+/*[clinic end generated code: checksum=a203f4cefc9de727aa1d2ea39d11c0a16c32041a]*/
 {
     int err;
-    unsigned int length = DEFAULTALLOC, new_length;
+    unsigned int length = DEF_BUF_SIZE, new_length;
     PyObject *RetVal;
-    int flushmode = Z_FINISH;
     unsigned long start_total_out;
 
-    if (!PyArg_ParseTuple(args, "|i:flush", &flushmode))
-        return NULL;
-
     /* Flushing with Z_NO_FLUSH is a no-op, so there's no point in
        doing any work at all; just return an empty string. */
-    if (flushmode == Z_NO_FLUSH) {
+    if (mode == Z_NO_FLUSH) {
         return PyBytes_FromStringAndSize(NULL, 0);
     }
 
@@ -964,7 +864,7 @@
     self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
 
     Py_BEGIN_ALLOW_THREADS
-    err = deflate(&(self->zst), flushmode);
+    err = deflate(&(self->zst), mode);
     Py_END_ALLOW_THREADS
 
     /* while Z_OK and the output buffer is full, there might be more output,
@@ -984,14 +884,14 @@
         length = new_length;
 
         Py_BEGIN_ALLOW_THREADS
-        err = deflate(&(self->zst), flushmode);
+        err = deflate(&(self->zst), mode);
         Py_END_ALLOW_THREADS
     }
 
-    /* If flushmode is Z_FINISH, we also have to call deflateEnd() to free
+    /* If mode is Z_FINISH, we also have to call deflateEnd() to free
        various data structures. Note we should only get Z_STREAM_END when
-       flushmode is Z_FINISH, but checking both for safety*/
-    if (err == Z_STREAM_END && flushmode == Z_FINISH) {
+       mode is Z_FINISH, but checking both for safety*/
+    if (err == Z_STREAM_END && mode == Z_FINISH) {
         err = deflateEnd(&(self->zst));
         if (err != Z_OK) {
             zlib_error(self->zst, err, "while finishing compression");
@@ -1031,25 +931,9 @@
 Return a copy of the compression object.
 [clinic start generated code]*/
 
-PyDoc_STRVAR(zlib_Compress_copy__doc__,
-"copy(self)\n"
-"Return a copy of the compression object.");
-
-#define ZLIB_COMPRESS_COPY_METHODDEF    \
-    {"copy", (PyCFunction)zlib_Compress_copy, METH_NOARGS, zlib_Compress_copy__doc__},
-
-static PyObject *
-zlib_Compress_copy_impl(compobject *self);
-
-static PyObject *
-zlib_Compress_copy(compobject *self, PyObject *Py_UNUSED(ignored))
-{
-    return zlib_Compress_copy_impl(self);
-}
-
 static PyObject *
 zlib_Compress_copy_impl(compobject *self)
-/*[clinic end generated code: checksum=7aa841ad51297eb83250f511a76872e88fdc737e]*/
+/*[clinic end generated code: checksum=5144aa153c21e805afa5c19e5b48cf8e6480b5da]*/
 {
     compobject *retval = NULL;
     int err;
@@ -1099,11 +983,15 @@
     return NULL;
 }
 
-PyDoc_STRVAR(decomp_copy__doc__,
-"copy() -- Return a copy of the decompression object.");
+/*[clinic input]
+zlib.Decompress.copy
+
+Return a copy of the decompression object.
+[clinic start generated code]*/
 
 static PyObject *
-PyZlib_uncopy(compobject *self)
+zlib_Decompress_copy_impl(compobject *self)
+/*[clinic end generated code: checksum=02a883a2a510c8ccfeef3f89e317a275bfe8c094]*/
 {
     compobject *retval = NULL;
     int err;
@@ -1155,24 +1043,26 @@
 }
 #endif
 
-PyDoc_STRVAR(decomp_flush__doc__,
-"flush( [length] ) -- Return a string containing any remaining\n"
-"decompressed data. length, if given, is the initial size of the\n"
-"output buffer.\n"
-"\n"
-"The decompressor object can no longer be used after this call.");
+/*[clinic input]
+zlib.Decompress.flush
+
+    length: uint(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE
+        the initial size of the output buffer.
+    /
+
+Return a bytes object containing any remaining decompressed data.
+[clinic start generated code]*/
 
 static PyObject *
-PyZlib_unflush(compobject *self, PyObject *args)
+zlib_Decompress_flush_impl(compobject *self, unsigned int length)
+/*[clinic end generated code: checksum=db6fb753ab698e22afe3957c9da9e5e77f4bfc08]*/
 {
     int err;
-    unsigned int length = DEFAULTALLOC, new_length;
+    unsigned int new_length;
     PyObject * retval = NULL;
     unsigned long start_total_out;
     Py_ssize_t size;
 
-    if (!PyArg_ParseTuple(args, "|O&:flush", uint_converter, &length))
-        return NULL;
     if (length == 0) {
         PyErr_SetString(PyExc_ValueError, "length must be greater than zero");
         return NULL;
@@ -1248,12 +1138,12 @@
     return retval;
 }
 
+#include "clinic/zlibmodule.c.h"
+
 static PyMethodDef comp_methods[] =
 {
-    {"compress", (binaryfunc)PyZlib_objcompress, METH_VARARGS,
-                 comp_compress__doc__},
-    {"flush", (binaryfunc)PyZlib_flush, METH_VARARGS,
-              comp_flush__doc__},
+    ZLIB_COMPRESS_COMPRESS_METHODDEF
+    ZLIB_COMPRESS_FLUSH_METHODDEF
 #ifdef HAVE_ZLIB_COPY
     ZLIB_COMPRESS_COPY_METHODDEF
 #endif
@@ -1263,11 +1153,9 @@
 static PyMethodDef Decomp_methods[] =
 {
     ZLIB_DECOMPRESS_DECOMPRESS_METHODDEF
-    {"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS,
-              decomp_flush__doc__},
+    ZLIB_DECOMPRESS_FLUSH_METHODDEF
 #ifdef HAVE_ZLIB_COPY
-    {"copy",  (PyCFunction)PyZlib_uncopy, METH_NOARGS,
-              decomp_copy__doc__},
+    ZLIB_DECOMPRESS_COPY_METHODDEF
 #endif
     {NULL, NULL}
 };
@@ -1280,95 +1168,95 @@
     {NULL},
 };
 
-PyDoc_STRVAR(adler32__doc__,
-"adler32(string[, start]) -- Compute an Adler-32 checksum of string.\n"
-"\n"
-"An optional starting value can be specified.  The returned checksum is\n"
-"an integer.");
+/*[clinic input]
+zlib.adler32
+
+    data: Py_buffer
+    value: unsigned_int(bitwise=True) = 1
+        Starting value of the checksum.
+    /
+
+Compute an Adler-32 checksum of data.
+
+The returned checksum is an integer.
+[clinic start generated code]*/
 
 static PyObject *
-PyZlib_adler32(PyObject *self, PyObject *args)
+zlib_adler32_impl(PyModuleDef *module, Py_buffer *data, unsigned int value)
+/*[clinic end generated code: checksum=51d6d75ee655c78af8c968fdb4c11d97e62c67d5]*/
 {
-    unsigned int adler32val = 1;  /* adler32(0L, Z_NULL, 0) */
-    Py_buffer pbuf;
-
-    if (!PyArg_ParseTuple(args, "y*|I:adler32", &pbuf, &adler32val))
-        return NULL;
     /* Releasing the GIL for very small buffers is inefficient
        and may lower performance */
-    if (pbuf.len > 1024*5) {
-        unsigned char *buf = pbuf.buf;
-        Py_ssize_t len = pbuf.len;
+    if (data->len > 1024*5) {
+        unsigned char *buf = data->buf;
+        Py_ssize_t len = data->len;
 
         Py_BEGIN_ALLOW_THREADS
         /* Avoid truncation of length for very large buffers. adler32() takes
            length as an unsigned int, which may be narrower than Py_ssize_t. */
         while ((size_t)len > UINT_MAX) {
-            adler32val = adler32(adler32val, buf, UINT_MAX);
+            value = adler32(value, buf, UINT_MAX);
             buf += (size_t) UINT_MAX;
             len -= (size_t) UINT_MAX;
         }
-        adler32val = adler32(adler32val, buf, (unsigned int)len);
+        value = adler32(value, buf, (unsigned int)len);
         Py_END_ALLOW_THREADS
     } else {
-        adler32val = adler32(adler32val, pbuf.buf, (unsigned int)pbuf.len);
+        value = adler32(value, data->buf, (unsigned int)data->len);
     }
-    PyBuffer_Release(&pbuf);
-    return PyLong_FromUnsignedLong(adler32val & 0xffffffffU);
+    return PyLong_FromUnsignedLong(value & 0xffffffffU);
 }
 
-PyDoc_STRVAR(crc32__doc__,
-"crc32(string[, start]) -- Compute a CRC-32 checksum of string.\n"
-"\n"
-"An optional starting value can be specified.  The returned checksum is\n"
-"an integer.");
+/*[clinic input]
+zlib.crc32
+
+    data: Py_buffer
+    value: unsigned_int(bitwise=True) = 0
+        Starting value of the checksum.
+    /
+
+Compute a CRC-32 checksum of data.
+
+The returned checksum is an integer.
+[clinic start generated code]*/
 
 static PyObject *
-PyZlib_crc32(PyObject *self, PyObject *args)
+zlib_crc32_impl(PyModuleDef *module, Py_buffer *data, unsigned int value)
+/*[clinic end generated code: checksum=c1e986e74fe7b62369998a71a81ebeb9b73e8d4c]*/
 {
-    unsigned int crc32val = 0;  /* crc32(0L, Z_NULL, 0) */
-    Py_buffer pbuf;
     int signed_val;
 
-    if (!PyArg_ParseTuple(args, "y*|I:crc32", &pbuf, &crc32val))
-        return NULL;
     /* Releasing the GIL for very small buffers is inefficient
        and may lower performance */
-    if (pbuf.len > 1024*5) {
-        unsigned char *buf = pbuf.buf;
-        Py_ssize_t len = pbuf.len;
+    if (data->len > 1024*5) {
+        unsigned char *buf = data->buf;
+        Py_ssize_t len = data->len;
 
         Py_BEGIN_ALLOW_THREADS
         /* Avoid truncation of length for very large buffers. crc32() takes
            length as an unsigned int, which may be narrower than Py_ssize_t. */
         while ((size_t)len > UINT_MAX) {
-            crc32val = crc32(crc32val, buf, UINT_MAX);
+            value = crc32(value, buf, UINT_MAX);
             buf += (size_t) UINT_MAX;
             len -= (size_t) UINT_MAX;
         }
-        signed_val = crc32(crc32val, buf, (unsigned int)len);
+        signed_val = crc32(value, buf, (unsigned int)len);
         Py_END_ALLOW_THREADS
     } else {
-        signed_val = crc32(crc32val, pbuf.buf, (unsigned int)pbuf.len);
+        signed_val = crc32(value, data->buf, (unsigned int)data->len);
     }
-    PyBuffer_Release(&pbuf);
     return PyLong_FromUnsignedLong(signed_val & 0xffffffffU);
 }
 
 
 static PyMethodDef zlib_methods[] =
 {
-    {"adler32", (PyCFunction)PyZlib_adler32, METH_VARARGS,
-                adler32__doc__},
+    ZLIB_ADLER32_METHODDEF
     ZLIB_COMPRESS_METHODDEF
-    {"compressobj", (PyCFunction)PyZlib_compressobj, METH_VARARGS|METH_KEYWORDS,
-                    compressobj__doc__},
-    {"crc32", (PyCFunction)PyZlib_crc32, METH_VARARGS,
-              crc32__doc__},
-    {"decompress", (PyCFunction)PyZlib_decompress, METH_VARARGS,
-                   decompress__doc__},
-    {"decompressobj", (PyCFunction)PyZlib_decompressobj, METH_VARARGS|METH_KEYWORDS,
-                   decompressobj__doc__},
+    ZLIB_COMPRESSOBJ_METHODDEF
+    ZLIB_CRC32_METHODDEF
+    ZLIB_DECOMPRESS_METHODDEF
+    ZLIB_DECOMPRESSOBJ_METHODDEF
     {NULL, NULL}
 };
 
@@ -1482,6 +1370,7 @@
     PyModule_AddIntMacro(m, MAX_WBITS);
     PyModule_AddIntMacro(m, DEFLATED);
     PyModule_AddIntMacro(m, DEF_MEM_LEVEL);
+    PyModule_AddIntMacro(m, DEF_BUF_SIZE);
     PyModule_AddIntMacro(m, Z_BEST_SPEED);
     PyModule_AddIntMacro(m, Z_BEST_COMPRESSION);
     PyModule_AddIntMacro(m, Z_DEFAULT_COMPRESSION);
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -2689,8 +2689,11 @@
      * types as well, but that's quite a bit trickier due to the extra
      * state potentially stored on OSError instances.
      */
-
-    Py_XDECREF(tb);
+    /* Ensure the traceback is set correctly on the existing exception */
+    if (tb != NULL) {
+        PyException_SetTraceback(val, tb);
+        Py_DECREF(tb);
+    }
 
 #ifdef HAVE_STDARG_PROTOTYPES
     va_start(vargs, format);

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list