Repository: pallets/click
Pull request #1468 (2020-02-10 14:55:54)

fix: always use parameter UTF-8 fallback
Even when the filesystem encoding and sys.argv encoding are the same we
should still fall back to trying UTF-8 for decoding command line
arguments.

davidism: This *seems* ok, but I can't tell what it might affect. Can you add a test case?

Patch:
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index d88465a..00e732d 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -1,35 +1,35 @@
 trigger:
   - master
-  - '*.x'
+  - "*.x"
 
 variables:
   vmImage: ubuntu-latest
-  python.version: '3.8'
-  TOXENV: py
+  python.version: "3.7"
+  TOXENV: py,coverage-ci
+  hasTestResults: true
 
 strategy:
   matrix:
-    Python 3.8 Linux:
+    Python 3.7 Linux:
       vmImage: ubuntu-latest
-    Python 3.8 Windows:
+    Python 3.7 Windows:
       vmImage: windows-latest
-    Python 3.8 Mac:
+    Python 3.7 Mac:
       vmImage: macos-latest
     PyPy 3 Linux:
       python.version: pypy3
-    Python 3.7 Linux:
-      python.version: '3.7'
     Python 3.6 Linux:
-      python.version: '3.6'
+      python.version: 3.6
     Python 3.5 Linux:
-      python.version: '3.5'
+      python.version: 3.5
     Python 2.7 Linux:
-      python.version: '2.7'
+      python.version: 2.7
     Python 2.7 Windows:
+      python.version: 2.7
       vmImage: windows-latest
-      python.version: '2.7'
     Docs:
       TOXENV: docs
+      hasTestResults: false
 
 pool:
   vmImage: $(vmImage)
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
deleted file mode 100644
index 8f31ae9..0000000
--- a/.github/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,33 +0,0 @@
-**This issue tracker is a tool to address bugs in Click itself.
-Please use the #pocoo IRC channel on freenode, the Discord server or 
-Stack Overflow for general questions about using Flask or issues
-not related to Click.**
-
-If you'd like to report a bug in Click, fill out the template below. Provide
-any extra information that may be useful / related to your problem.
-Ideally, create an [MCVE](https://stackoverflow.com/help/mcve), which helps us
-understand the problem and helps check that it is not caused by something in
-your code.
-
----
-
-### Expected Behavior
-
-Tell us what should happen.
-
-```python
-Paste a minimal example that causes the problem.
-```
-
-### Actual Behavior
-
-Tell us what happens instead.
-
-```pytb
-Paste the full traceback if there was an exception.
-```
-
-### Environment
-
-* Python version:
-* Click version:
diff --git a/.gitignore b/.gitignore
index fc5a65f..33ed830 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,18 @@
-/.idea/
-/.vscode/
-/env/
-/venv/
-__pycache__/
 *.pyc
+*.pyo
+__pycache__/
+.idea/
+.ropeproject
+.DS_Store
+env/
+venv/
 *.egg-info/
-/build/
-/dist/
-/.pytest_cache/
-/.tox/
+*.eggs/
+build/
+dist/
+docs/_build/
+.pytest_cache/
+.tox/
 .coverage
 .coverage.*
-/htmlcov/
-/docs/_build/
+htmlcov/
diff --git a/CHANGES.rst b/CHANGES.rst
index 73e4e67..b65346b 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -5,64 +5,18 @@ Version 7.1
 
 Unreleased
 
--   Fix PyPI package name, "click" is lowercase again.
+-   Add ``no_args_is_help`` option to ``click.Command``, defaults to
+    False :pr:`1167`
 -   Fix link in ``unicode_literals`` error message. :pr:`1151`
 -   Add support for colored output on UNIX Jupyter notebooks.
     :issue:`1185`
--   Operations that strip ANSI controls will strip the cursor hide/show
-    sequences. :issue:`1216`
 -   Remove unused compat shim for ``bytes``. :pr:`1195`
--   Expand testing around termui, especially getchar on Windows.
+-   Expand unit testing around termui, especially getchar (Windows).
     :issue:`1116`
 -   Fix output on Windows Python 2.7 built with MSVC 14. :pr:`1342`
--   Fix ``OSError`` when running in MSYS2. :issue:`1338`
--   Fix ``OSError`` when redirecting to ``NUL`` stream on Windows.
-    :issue:`1065`
--   Fix memory leak when parsing Unicode arguments on Windows.
-    :issue:`1136`
--   Fix error in new AppEngine environments. :issue:`1462`
--   Always return one of the passed choices for ``click.Choice``
+-   Always return of of the passed choices for ``click.Choice``
     :issue:`1277`, :pr:`1318`
--   Add ``no_args_is_help`` option to ``click.Command``, defaults to
-    False :pr:`1167`
--   Add ``show_defaults`` parameter to ``Context`` to enable showing
-    defaults globally. :issue:`1018`
--   Handle ``env MYPATH=''`` as though the option were not passed.
-    :issue:`1196`
--   It is once again possible to call ``next(bar)`` on an active
-    progress bar instance. :issue:`1125`
--   ``open_file`` with ``atomic=True`` retains permissions of existing
-    files and respects the current umask for new files. :issue:`1376`
--   When using the test ``CliRunner`` with ``mix_stderr=False``, if
-    ``result.stderr`` is empty it will not raise a ``ValueError``.
-    :issue:`1193`
--   Remove the unused ``mix_stderr`` parameter from
-    ``CliRunner.invoke``. :issue:`1435`
--   Fix ``TypeError`` raised when using bool flags and specifying
-    ``type=bool``. :issue:`1287`
--   Newlines in option help text are replaced with spaces before
-    re-wrapping to avoid uneven line breaks. :issue:`834`
--   ``MissingParameter`` exceptions are printable in the Python
-    interpreter. :issue:`1139`
--   Fix how default values for file-type options are shown during
-    prompts. :issue:`914`
--   Fix environment variable automatic generation for commands
-    containing ``-``. :issue:`1253`
--   Option help text replaces newlines with spaces when rewrapping, but
-    preserves paragraph breaks, fixing multiline formatting.
-    :issue:`834, 1066, 1397`
--   Option help text that is wrapped adds an extra newline at the end to
-    distinguish it from the next option. :issue:`1075`
--   Consider ``sensible-editor`` when determining the editor to use for
-    ``click.edit()``. :pr:`1469`
--   Arguments to system calls such as the executable path passed to
-    ``click.edit`` can contains spaces. :pr:`1470`
--   Add ZSH completion autoloading and error handling. :issue:`1348`
--   Add a repr to ``Command``, ``Group``, ``Option``, and ``Argument``,
-    showing the name for friendlier debugging. :issue:`1267`
--   Completion doesn't consider option names if a value starts with
-    ``-`` after the ``--`` separator. :issue:`1247`
--   ZSH Completion escapes special characters in values. :pr:`1418`
+-   Fix ``OSError`` when running in MSYS2. :issue:`1338`
 
 
 Version 7.0
diff --git a/LICENSE.rst b/LICENSE.rst
index d12a849..87ce152 100644
--- a/LICENSE.rst
+++ b/LICENSE.rst
@@ -1,28 +1,39 @@
-Copyright 2014 Pallets
+Copyright © 2014 by the Pallets team.
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
+Some rights reserved.
 
-1.  Redistributions of source code must retain the above copyright
+Redistribution and use in source and binary forms of the software as
+well as documentation, with or without modification, are permitted
+provided that the following conditions are met:
+
+-   Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
 
-2.  Redistributions in binary form must reproduce the above copyright
+-   Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
 
-3.  Neither the name of the copyright holder nor the names of its
+-   Neither the name of the copyright holder nor the names of its
     contributors may be used to endorse or promote products derived from
     this software without specific prior written permission.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+----
+
+Click uses parts of optparse written by Gregory P. Ward and maintained
+by the Python Software Foundation. This is limited to code in parser.py.
+
+Copyright © 2001-2006 Gregory P. Ward. All rights reserved.
+Copyright © 2002-2006 Python Software Foundation. All rights reserved.
diff --git a/MANIFEST.in b/MANIFEST.in
index b130d04..33a336f 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,8 +1,11 @@
 include CHANGES.rst
+include CONTRIBUTING.rst
+include LICENSE.rst
+include README.rst
 include tox.ini
 graft artwork
 graft docs
 prune docs/_build
 graft examples
 graft tests
-global-exclude *.pyc
+global-exclude *.py[co] .DS_Store
diff --git a/README.rst b/README.rst
index 4cade9e..41fb712 100644
--- a/README.rst
+++ b/README.rst
@@ -24,7 +24,9 @@ Install and update using `pip`_:
 
 .. code-block:: text
 
-    $ pip install -U click
+    $ pip install click
+
+Click supports Python 3.4 and newer, Python 2.7, and PyPy.
 
 .. _pip: https://pip.pypa.io/en/stable/quickstart/
 
@@ -32,6 +34,8 @@ Install and update using `pip`_:
 A Simple Example
 ----------------
 
+What does it look like? Here is an example of a simple Click program:
+
 .. code-block:: python
 
     import click
@@ -48,6 +52,8 @@ A Simple Example
     if __name__ == '__main__':
         hello()
 
+And what it looks like when run:
+
 .. code-block:: text
 
     $ python hello.py --count=3
@@ -71,10 +77,11 @@ donate today`_.
 Links
 -----
 
--   Website: https://palletsprojects.com/p/click/
--   Documentation: https://click.palletsprojects.com/
--   Releases: https://pypi.org/project/click/
--   Code: https://github.com/pallets/click
--   Issue tracker: https://github.com/pallets/click/issues
--   Test status: https://dev.azure.com/pallets/click/_build
--   Official chat: https://discord.gg/t6rrQZH
+*   Website: https://palletsprojects.com/p/click/
+*   Documentation: https://click.palletsprojects.com/
+*   License: `BSD <https://github.com/pallets/click/blob/master/LICENSE.rst>`_
+*   Releases: https://pypi.org/project/click/
+*   Code: https://github.com/pallets/click
+*   Issue tracker: https://github.com/pallets/click/issues
+*   Test status: https://dev.azure.com/pallets/click/_build
+*   Official chat: https://discord.gg/t6rrQZH
diff --git a/click/__init__.py b/click/__init__.py
index 02807b0..0fa5e3b 100644
--- a/click/__init__.py
+++ b/click/__init__.py
@@ -1,9 +1,15 @@
 # -*- coding: utf-8 -*-
 """
+click
+~~~~~
+
 Click is a simple Python module inspired by the stdlib optparse to make
 writing command line scripts fun. Unlike other modules, it's based
 around a simple API that does not come with too much magic and is
 composable.
+
+:copyright: © 2014 by the Pallets team.
+:license: BSD, see LICENSE.rst for more details.
 """
 
 # Core classes
diff --git a/click/_bashcomplete.py b/click/_bashcomplete.py
index 7619361..a5f1084 100644
--- a/click/_bashcomplete.py
+++ b/click/_bashcomplete.py
@@ -39,14 +39,10 @@ COMPLETION_SCRIPT_BASH = '''
 '''
 
 COMPLETION_SCRIPT_ZSH = '''
-#compdef %(script_names)s
-
 %(complete_func)s() {
     local -a completions
     local -a completions_with_descriptions
     local -a response
-    (( ! $+commands[%(script_names)s] )) && return 1
-
     response=("${(@f)$( env COMP_WORDS=\"${words[*]}\" \\
                         COMP_CWORD=$((CURRENT-1)) \\
                         %(autocomplete_var)s=\"complete_zsh\" \\
@@ -61,11 +57,11 @@ COMPLETION_SCRIPT_ZSH = '''
     done
 
     if [ -n "$completions_with_descriptions" ]; then
-        _describe -V unsorted completions_with_descriptions -U
+        _describe -V unsorted completions_with_descriptions -U -Q
     fi
 
     if [ -n "$completions" ]; then
-        compadd -U -V unsorted -a completions
+        compadd -U -V unsorted -Q -a completions
     fi
     compstate[insert]="automenu"
 }
@@ -237,8 +233,6 @@ def get_choices(cli, prog_name, args, incomplete):
     if ctx is None:
         return []
 
-    has_double_dash = "--" in all_args
-
     # In newer versions of bash long opts with '='s are partitioned, but it's easier to parse
     # without the '='
     if start_of_option(incomplete) and WORDBREAK in incomplete:
@@ -249,7 +243,7 @@ def get_choices(cli, prog_name, args, incomplete):
         incomplete = ''
 
     completions = []
-    if not has_double_dash and start_of_option(incomplete):
+    if start_of_option(incomplete):
         # completions for partial options
         for param in ctx.command.params:
             if isinstance(param, Option) and not param.hidden:
diff --git a/click/_compat.py b/click/_compat.py
index 6762854..d4dbbe4 100644
--- a/click/_compat.py
+++ b/click/_compat.py
@@ -11,12 +11,12 @@ CYGWIN = sys.platform.startswith('cygwin')
 MSYS2 = sys.platform.startswith('win') and ('GCC' in sys.version)
 # Determine local App Engine environment, per Google's own suggestion
 APP_ENGINE = ('APPENGINE_RUNTIME' in os.environ and
-              'Development/' in os.environ.get('SERVER_SOFTWARE', ''))
+              'Development/' in os.environ['SERVER_SOFTWARE'])
 WIN = sys.platform.startswith('win') and not APP_ENGINE and not MSYS2
 DEFAULT_COLUMNS = 80
 
 
-_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]")
+_ansi_re = re.compile(r'\033\[((?:\d|;)*)([a-zA-Z])')
 
 
 def get_filesystem_encoding():
@@ -162,8 +162,6 @@ if PY2:
     iteritems = lambda x: x.iteritems()
     range_type = xrange
 
-    from pipes import quote as shlex_quote
-
     def is_bytes(x):
         return isinstance(x, (buffer, bytearray))
 
@@ -270,8 +268,6 @@ else:
     isidentifier = lambda x: x.isidentifier()
     iteritems = lambda x: iter(x.items())
 
-    from shlex import quote as shlex_quote
-
     def is_bytes(x):
         return isinstance(x, (bytes, memoryview, bytearray))
 
@@ -333,88 +329,80 @@ else:
         # but this at least will force Click to recover somehow.
         return is_ascii_encoding(getattr(stream, 'encoding', None) or 'ascii')
 
-    def _is_compat_stream_attr(stream, attr, value):
-        """A stream attribute is compatible if it is equal to the
-        desired value or the desired value is unset and the attribute
-        has a value.
-        """
-        stream_value = getattr(stream, attr, None)
-        return stream_value == value or (value is None and stream_value is not None)
-
     def _is_compatible_text_stream(stream, encoding, errors):
-        """Check if a stream's encoding and errors attributes are
-        compatible with the desired values.
-        """
-        return (
-            _is_compat_stream_attr(stream, "encoding", encoding)
-            and _is_compat_stream_attr(stream, "errors", errors)
-        )
+        stream_encoding = getattr(stream, 'encoding', None)
+        stream_errors = getattr(stream, 'errors', None)
+
+        # Perfect match.
+        if stream_encoding == encoding and stream_errors == errors:
+            return True
+
+        # Otherwise, it's only a compatible stream if we did not ask for
+        # an encoding.
+        if encoding is None:
+            return stream_encoding is not None
+
+        return False
 
-    def _force_correct_text_stream(
-        text_stream,
-        encoding,
-        errors,
-        is_binary,
-        find_binary,
-        force_readable=False,
-        force_writable=False,
-    ):
-        if is_binary(text_stream, False):
-            binary_reader = text_stream
+    def _force_correct_text_reader(text_reader, encoding, errors,
+                                   force_readable=False):
+        if _is_binary_reader(text_reader, False):
+            binary_reader = text_reader
         else:
-            # If the stream looks compatible, and won't default to a
-            # misconfigured ascii encoding, return it as-is.
-            if (
-                _is_compatible_text_stream(text_stream, encoding, errors)
-                and not (
-                    encoding is None
-                    and _stream_is_misconfigured(text_stream)
-                )
-            ):
-                return text_stream
-
-            # Otherwise, get the underlying binary reader.
-            binary_reader = find_binary(text_stream)
-
-            # If that's not possible, silently use the original reader
-            # and get mojibake instead of exceptions.
+            # If there is no target encoding set, we need to verify that the
+            # reader is not actually misconfigured.
+            if encoding is None and not _stream_is_misconfigured(text_reader):
+                return text_reader
+
+            if _is_compatible_text_stream(text_reader, encoding, errors):
+                return text_reader
+
+            # If the reader has no encoding, we try to find the underlying
+            # binary reader for it.  If that fails because the environment is
+            # misconfigured, we silently go with the same reader because this
+            # is too common to happen.  In that case, mojibake is better than
+            # exceptions.
+            binary_reader = _find_binary_reader(text_reader)
             if binary_reader is None:
-                return text_stream
+                return text_reader
 
-        # Default errors to replace instead of strict in order to get
-        # something that works.
+        # At this point, we default the errors to replace instead of strict
+        # because nobody handles those errors anyways and at this point
+        # we're so fundamentally fucked that nothing can repair it.
         if errors is None:
-            errors = "replace"
-
-        # Wrap the binary stream in a text stream with the correct
-        # encoding parameters.
-        return _make_text_stream(
-            binary_reader,
-            encoding,
-            errors,
-            force_readable=force_readable,
-            force_writable=force_writable,
-        )
-
-    def _force_correct_text_reader(text_reader, encoding, errors, force_readable=False):
-        return _force_correct_text_stream(
-            text_reader,
-            encoding,
-            errors,
-            _is_binary_reader,
-            _find_binary_reader,
-            force_readable=force_readable,
-        )
-
-    def _force_correct_text_writer(text_writer, encoding, errors, force_writable=False):
-        return _force_correct_text_stream(
-            text_writer,
-            encoding,
-            errors,
-            _is_binary_writer,
-            _find_binary_writer,
-            force_writable=force_writable,
-        )
+            errors = 'replace'
+        return _make_text_stream(binary_reader, encoding, errors,
+                                 force_readable=force_readable)
+
+    def _force_correct_text_writer(text_writer, encoding, errors,
+                                   force_writable=False):
+        if _is_binary_writer(text_writer, False):
+            binary_writer = text_writer
+        else:
+            # If there is no target encoding set, we need to verify that the
+            # writer is not actually misconfigured.
+            if encoding is None and not _stream_is_misconfigured(text_writer):
+                return text_writer
+
+            if _is_compatible_text_stream(text_writer, encoding, errors):
+                return text_writer
+
+            # If the writer has no encoding, we try to find the underlying
+            # binary writer for it.  If that fails because the environment is
+            # misconfigured, we silently go with the same writer because this
+            # is too common to happen.  In that case, mojibake is better than
+            # exceptions.
+            binary_writer = _find_binary_writer(text_writer)
+            if binary_writer is None:
+                return text_writer
+
+        # At this point, we default the errors to replace instead of strict
+        # because nobody handles those errors anyways and at this point
+        # we're so fundamentally fucked that nothing can repair it.
+        if errors is None:
+            errors = 'replace'
+        return _make_text_stream(binary_writer, encoding, errors,
+                                 force_writable=force_writable)
 
     def get_binary_stdin():
         reader = _find_binary_reader(sys.stdin)
@@ -480,45 +468,24 @@ def get_streerror(e, default=None):
     return msg
 
 
-def _wrap_io_open(file, mode, encoding, errors):
-    """On Python 2, :func:`io.open` returns a text file wrapper that
-    requires passing ``unicode`` to ``write``. Need to open the file in
-    binary mode then wrap it in a subclass that can write ``str`` and
-    ``unicode``.
-
-    Also handles not passing ``encoding`` and ``errors`` in binary mode.
-    """
-    binary = "b" in mode
-
-    if binary:
-        kwargs = {}
-    else:
-        kwargs = {"encoding": encoding, "errors": errors}
-
-    if not PY2 or binary:
-        return io.open(file, mode, **kwargs)
-
-    f = io.open(file, "b" + mode.replace("t", ""))
-    return _make_text_stream(f, **kwargs)
-
-
-def open_stream(filename, mode='r', encoding=None, errors='strict', atomic=False):
-    binary = "b" in mode
-
+def open_stream(filename, mode='r', encoding=None, errors='strict',
+                atomic=False):
     # Standard streams first.  These are simple because they don't need
     # special handling for the atomic flag.  It's entirely ignored.
     if filename == '-':
         if any(m in mode for m in ['w', 'a', 'x']):
-            if binary:
+            if 'b' in mode:
                 return get_binary_stdout(), False
             return get_text_stdout(encoding=encoding, errors=errors), False
-        if binary:
+        if 'b' in mode:
             return get_binary_stdin(), False
         return get_text_stdin(encoding=encoding, errors=errors), False
 
     # Non-atomic writes directly go out through the regular open functions.
     if not atomic:
-        return _wrap_io_open(filename, mode, encoding, errors), True
+        if encoding is None:
+            return open(filename, mode), True
+        return io.open(filename, mode, encoding=encoding, errors=errors), True
 
     # Some usability stuff for atomic writes
     if 'a' in mode:
@@ -537,41 +504,15 @@ def open_stream(filename, mode='r', encoding=None, errors='strict', atomic=False
     # as a proxy in the same folder and then using the fdopen
     # functionality to wrap it in a Python file.  Then we wrap it in an
     # atomic file that moves the file over on close.
-    import errno
-    import random
-
-    try:
-        perm = os.stat(filename).st_mode
-    except OSError:
-        perm = None
-
-    flags = os.O_RDWR | os.O_CREAT | os.O_EXCL
+    import tempfile
+    fd, tmp_filename = tempfile.mkstemp(dir=os.path.dirname(filename),
+                                        prefix='.__atomic-write')
 
-    if binary:
-        flags |= getattr(os, 'O_BINARY', 0)
+    if encoding is not None:
+        f = io.open(fd, mode, encoding=encoding, errors=errors)
+    else:
+        f = os.fdopen(fd, mode)
 
-    while True:
-        tmp_filename = os.path.join(
-            os.path.dirname(filename),
-            '.__atomic-write%08x' % (random.randrange(1 << 32),),
-        )
-        try:
-            fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm)
-            break
-        except OSError as e:
-            if e.errno == errno.EEXIST or (
-                os.name == "nt"
-                and e.errno == errno.EACCES
-                and os.path.isdir(e.filename)
-                and os.access(e.filename, os.W_OK)
-            ):
-                continue
-            raise
-
-    if perm is not None:
-        os.chmod(tmp_filename, perm)  # in case perm includes bits in umask
-
-    f = _wrap_io_open(fd, mode, encoding, errors)
     return _AtomicFile(f, tmp_filename, os.path.realpath(filename)), True
 
 
diff --git a/click/_termui_impl.py b/click/_termui_impl.py
index 3fbf477..00a8e5e 100644
--- a/click/_termui_impl.py
+++ b/click/_termui_impl.py
@@ -1,8 +1,14 @@
 # -*- coding: utf-8 -*-
 """
+click._termui_impl
+~~~~~~~~~~~~~~~~~~
+
 This module contains implementations for the termui module. To keep the
 import time of Click down, some infrequently used functionality is
 placed in this module and only imported as needed.
+
+:copyright: © 2014 by the Pallets team.
+:license: BSD, see LICENSE.rst for more details.
 """
 
 import os
@@ -10,9 +16,9 @@ import sys
 import time
 import math
 import contextlib
-from ._compat import _default_text_stdout, range_type, isatty, \
-     open_stream, shlex_quote, strip_ansi, term_len, get_best_encoding, WIN, \
-     int_types, CYGWIN
+from ._compat import _default_text_stdout, range_type, PY2, isatty, \
+     open_stream, strip_ansi, term_len, get_best_encoding, WIN, int_types, \
+     CYGWIN
 from .utils import echo
 from .exceptions import ClickException
 
@@ -102,17 +108,6 @@ class ProgressBar(object):
         self.render_progress()
         return self.generator()
 
-    def __next__(self):
-        # Iteration is defined in terms of a generator function,
-        # returned by iter(self); use that to define next(). This works
-        # because `self.iter` is an iterable consumed by that generator,
-        # so it is re-entry safe. Calling `next(self.generator())`
-        # twice works and does "what you want".
-        return next(iter(self))
-
-    # Python 2 compat
-    next = __next__
-
     def is_fast(self):
         return time.time() - self.start <= self.short_limit
 
@@ -275,17 +270,11 @@ class ProgressBar(object):
         self.finished = True
 
     def generator(self):
-        """Return a generator which yields the items added to the bar
-        during construction, and updates the progress bar *after* the
-        yielded block returns.
         """
-        # WARNING: the iterator interface for `ProgressBar` relies on
-        # this and only works because this is a simple generator which
-        # doesn't create or manage additional state. If this function
-        # changes, the impact should be evaluated both against
-        # `iter(bar)` and `next(bar)`. `next()` in particular may call
-        # `self.generator()` repeatedly, and this must remain safe in
-        # order for that interface to work.
+        Returns a generator which yields the items added to the bar during
+        construction, and updates the progress bar *after* the yielded block
+        returns.
+        """
         if not self.entered:
             raise RuntimeError('You need to use progress bars in a with block.')
 
@@ -322,7 +311,7 @@ def pager(generator, color=None):
     fd, filename = tempfile.mkstemp()
     os.close(fd)
     try:
-        if hasattr(os, 'system') and os.system("more %s" % shlex_quote(filename)) == 0:
+        if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
             return _pipepager(generator, 'more', color)
         return _nullpager(stdout, generator, color)
     finally:
@@ -390,7 +379,7 @@ def _tempfilepager(generator, cmd, color):
     with open_stream(filename, 'wb')[0] as f:
         f.write(text.encode(encoding))
     try:
-        os.system("%s %s" % (shlex_quote(cmd), shlex_quote(filename)))
+        os.system(cmd + ' "' + filename + '"')
     finally:
         os.unlink(filename)
 
@@ -421,7 +410,7 @@ class Editor(object):
                 return rv
         if WIN:
             return 'notepad'
-        for editor in 'sensible-editor', 'vim', 'nano':
+        for editor in 'vim', 'nano':
             if os.system('which %s >/dev/null 2>&1' % editor) == 0:
                 return editor
         return 'vi'
@@ -435,11 +424,8 @@ class Editor(object):
         else:
             environ = None
         try:
-            c = subprocess.Popen(
-                "%s %s" % (shlex_quote(editor), shlex_quote(filename)),
-                env=environ,
-                shell=True
-            )
+            c = subprocess.Popen('%s "%s"' % (editor, filename),
+                                 env=environ, shell=True)
             exit_code = c.wait()
             if exit_code != 0:
                 raise ClickException('%s: Editing failed!' % editor)
@@ -510,16 +496,19 @@ def open_url(url, wait=False, locate=False):
     elif WIN:
         if locate:
             url = _unquote_file(url)
-            args = "explorer /select,%s" % (shlex_quote(url),)
+            args = 'explorer /select,"%s"' % _unquote_file(
+                url.replace('"', ''))
         else:
-            args = 'start %s "" %s' % ("/WAIT" if wait else "", shlex_quote(url))
+            args = 'start %s "" "%s"' % (
+                wait and '/WAIT' or '', url.replace('"', ''))
         return os.system(args)
     elif CYGWIN:
         if locate:
             url = _unquote_file(url)
-            args = "cygstart %s" % (shlex_quote(os.path.dirname(url)),)
+            args = 'cygstart "%s"' % (os.path.dirname(url).replace('"', ''))
         else:
-            args = "cygstart %s %s" % ("-w" if wait else "", shlex_quote(url))
+            args = 'cygstart %s "%s"' % (
+                wait and '-w' or '', url.replace('"', ''))
         return os.system(args)
 
     try:
diff --git a/click/_winconsole.py b/click/_winconsole.py
index 5458c30..2bc0cfb 100644
--- a/click/_winconsole.py
+++ b/click/_winconsole.py
@@ -17,15 +17,14 @@ import ctypes
 import msvcrt
 from ._compat import _NonClosingTextIOWrapper, text_type, PY2
 from ctypes import byref, POINTER, c_int, c_char, c_char_p, \
-     c_void_p, py_object, c_ssize_t, c_ulong, windll, WINFUNCTYPE, \
-     WinError
+     c_void_p, py_object, c_ssize_t, c_ulong, windll, WINFUNCTYPE
 try:
     from ctypes import pythonapi
     PyObject_GetBuffer = pythonapi.PyObject_GetBuffer
     PyBuffer_Release = pythonapi.PyBuffer_Release
 except ImportError:
     pythonapi = None
-from ctypes.wintypes import DWORD, LPWSTR, LPCWSTR, HANDLE
+from ctypes.wintypes import LPWSTR, LPCWSTR, HANDLE
 
 
 c_ssize_p = POINTER(c_ssize_t)
@@ -34,15 +33,12 @@ kernel32 = windll.kernel32
 GetStdHandle = kernel32.GetStdHandle
 ReadConsoleW = kernel32.ReadConsoleW
 WriteConsoleW = kernel32.WriteConsoleW
-GetConsoleMode = kernel32.GetConsoleMode
 GetLastError = kernel32.GetLastError
 GetCommandLineW = WINFUNCTYPE(LPWSTR)(
     ('GetCommandLineW', windll.kernel32))
 CommandLineToArgvW = WINFUNCTYPE(
     POINTER(LPWSTR), LPCWSTR, POINTER(c_int))(
         ('CommandLineToArgvW', windll.shell32))
-LocalFree = WINFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)(
-    ('LocalFree', windll.kernel32))
 
 
 STDIN_HANDLE = GetStdHandle(-10)
@@ -269,13 +265,7 @@ if PY2:
     def _get_windows_argv():
         argc = c_int(0)
         argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc))
-        if not argv_unicode:
-            raise WinError()
-        try:
-            argv = [argv_unicode[i] for i in range(0, argc.value)]
-        finally:
-            LocalFree(argv_unicode)
-            del argv_unicode
+        argv = [argv_unicode[i] for i in range(0, argc.value)]
 
         if not hasattr(sys, 'frozen'):
             argv = argv[1:]
@@ -297,24 +287,11 @@ _stream_factories = {
 }
 
 
-def _is_console(f):
-    if not hasattr(f, 'fileno'):
-        return False
-
-    try:
-        fileno = f.fileno()
-    except OSError:
-        return False
-
-    handle = msvcrt.get_osfhandle(fileno)
-    return bool(GetConsoleMode(handle, byref(DWORD())))
-
-
 def _get_windows_console_stream(f, encoding, errors):
     if get_buffer is not None and \
        encoding in ('utf-16-le', None) \
        and errors in ('strict', None) and \
-       _is_console(f):
+       hasattr(f, 'isatty') and f.isatty():
         func = _stream_factories.get(f.fileno())
         if func is not None:
             if not PY2:
diff --git a/click/core.py b/click/core.py
index 7066cac..3c57a36 100644
--- a/click/core.py
+++ b/click/core.py
@@ -154,9 +154,6 @@ class Context(object):
        Added the `color`, `ignore_unknown_options`, and
        `max_content_width` parameters.
 
-    .. versionadded:: 7.1
-       Added the `show_default` parameter.
-
     :param command: the command class for this context.
     :param parent: the parent context.
     :param info_name: the info name for this invocation.  Generally this
@@ -335,8 +332,6 @@ class Context(object):
                                            self.info_name.upper())
         else:
             auto_envvar_prefix = auto_envvar_prefix.upper()
-        if auto_envvar_prefix is not None:
-            auto_envvar_prefix = auto_envvar_prefix.replace("-", "_")
         self.auto_envvar_prefix = auto_envvar_prefix
 
         if color is None and parent is not None:
@@ -622,9 +617,6 @@ class BaseCommand(object):
         #: an optional dictionary with defaults passed to the context.
         self.context_settings = context_settings
 
-    def __repr__(self):
-        return "<%s %s>" % (self.__class__.__name__, self.name)
-
     def get_usage(self, ctx):
         raise NotImplementedError('Base commands cannot get usage')
 
@@ -1328,6 +1320,12 @@ class Parameter(object):
 
     Some settings are supported by both options and arguments.
 
+    .. versionchanged:: 2.0
+       Changed signature for parameter callback to also be passed the
+       parameter.  In Click 2.0, the old callback format will still work,
+       but it will raise a warning to give you change to migrate the
+       code easier.
+
     :param param_decls: the parameter declarations for this option or
                         argument.  This is a list of flags or argument
                         names.
@@ -1355,16 +1353,6 @@ class Parameter(object):
                      order of processing.
     :param envvar: a string or list of strings that are environment variables
                    that should be checked.
-
-    .. versionchanged:: 7.1
-        Empty environment variables are ignored rather than taking the
-        empty string value. This makes it possible for scripts to clear
-        variables if they can't unset them.
-
-    .. versionchanged:: 2.0
-        Changed signature for parameter callback to also be passed the
-        parameter. The old callback format will still work, but it will
-        raise a warning to give you a chance to migrate the code easier.
     """
     param_type_name = 'parameter'
 
@@ -1396,9 +1384,6 @@ class Parameter(object):
         self.envvar = envvar
         self.autocompletion = autocompletion
 
-    def __repr__(self):
-        return "<%s %s>" % (self.__class__.__name__, self.name)
-
     @property
     def human_readable_name(self):
         """Returns the human readable name of this parameter.  This is the
@@ -1495,10 +1480,7 @@ class Parameter(object):
                 if rv is not None:
                     return rv
         else:
-            rv = os.environ.get(self.envvar)
-
-            if rv != "":
-                return rv
+            return os.environ.get(self.envvar)
 
     def value_from_envvar(self, ctx):
         rv = self.resolve_envvar_value(ctx)
@@ -1614,7 +1596,7 @@ class Option(Parameter):
         self.is_flag = is_flag
         self.flag_value = flag_value
         if self.is_flag and isinstance(self.flag_value, bool) \
-           and type in [None, bool]:
+           and type is None:
             self.type = BOOL
             self.is_bool_flag = True
         else:
@@ -1778,7 +1760,7 @@ class Option(Parameter):
         return ((any_prefix_is_slash and '; ' or ' / ').join(rv), help)
 
     def get_default(self, ctx):
-        # If we're a non boolean flag our default is more complex because
+        # If we're a non boolean flag out default is more complex because
         # we need to look at all flags in the same group to figure out
         # if we're the the default one in which case we return the flag
         # value as default.
diff --git a/click/decorators.py b/click/decorators.py
index 1f10e73..c57c530 100644
--- a/click/decorators.py
+++ b/click/decorators.py
@@ -94,9 +94,9 @@ def command(name=None, cls=None, **attrs):
     callback.  This will also automatically attach all decorated
     :func:`option`\s and :func:`argument`\s as parameters to the command.
 
-    The name of the command defaults to the name of the function with
-    underscores replaced by dashes.  If you want to change that, you can
-    pass the intended name as the first argument.
+    The name of the command defaults to the name of the function.  If you
+    want to change that, you can pass the intended name as the first
+    argument.
 
     All keyword arguments are forwarded to the underlying command class.
 
diff --git a/click/exceptions.py b/click/exceptions.py
index 21db907..6fa1765 100644
--- a/click/exceptions.py
+++ b/click/exceptions.py
@@ -152,19 +152,6 @@ class MissingParameter(BadParameter):
             msg or '',
         )
 
-    def __str__(self):
-        if self.message is None:
-            param_name = self.param.name if self.param else None
-            return "missing parameter: {}".format(param_name)
-        else:
-            return self.message
-
-    if PY2:
-        __unicode__ = __str__
-
-        def __str__(self):
-            return self.__unicode__().encode("utf-8")
-
 
 class NoSuchOption(UsageError):
     """Raised if click attempted to handle an option that does not
diff --git a/click/formatting.py b/click/formatting.py
index 4ae5f07..a3d6a4d 100644
--- a/click/formatting.py
+++ b/click/formatting.py
@@ -198,18 +198,12 @@ class HelpFormatter(object):
                 self.write(' ' * (first_col + self.current_indent))
 
             text_width = max(self.width - first_col - 2, 10)
-            wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True)
-            lines = wrapped_text.splitlines()
-
+            lines = iter(wrap_text(second, text_width).splitlines())
             if lines:
-                self.write(lines[0] + '\n')
-
-                for line in lines[1:]:
-                    self.write('%*s%s\n' % (first_col + self.current_indent, '', line))
-
-                if len(lines) > 1:
-                    # separate long help from next option
-                    self.write("\n")
+                self.write(next(lines) + '\n')
+                for line in lines:
+                    self.write('%*s%s\n' % (
+                        first_col + self.current_indent, '', line))
             else:
                 self.write('\n')
 
diff --git a/click/parser.py b/click/parser.py
index 6f2600f..1c3ae9c 100644
--- a/click/parser.py
+++ b/click/parser.py
@@ -1,5 +1,8 @@
 # -*- coding: utf-8 -*-
 """
+click.parser
+~~~~~~~~~~~~
+
 This module started out as largely a copy paste from the stdlib's
 optparse module with the features removed that we do not need from
 optparse because we implement them in Click on a higher level (for
@@ -11,12 +14,6 @@ The reason this is a different module and not optparse from the stdlib
 is that there are differences in 2.x and 3.x about the error messages
 generated and optparse in the stdlib uses gettext for no good reason
 and might cause us issues.
-
-Click uses parts of optparse written by Gregory P. Ward and maintained
-by the Python Software Foundation. This is limited to code in parser.py.
-
-Copyright 2001-2006 Gregory P. Ward. All rights reserved.
-Copyright 2002-2006 Python Software Foundation. All rights reserved.
 """
 
 import re
diff --git a/click/termui.py b/click/termui.py
index fa2727a..0e8e84c 100644
--- a/click/termui.py
+++ b/click/termui.py
@@ -1,4 +1,3 @@
-import io
 import os
 import sys
 import struct
@@ -6,12 +5,11 @@ import inspect
 import itertools
 
 from ._compat import raw_input, text_type, string_types, \
-    isatty, strip_ansi, get_winterm_size, DEFAULT_COLUMNS, WIN
+     isatty, strip_ansi, get_winterm_size, DEFAULT_COLUMNS, WIN
 from .utils import echo
 from .exceptions import Abort, UsageError
 from .types import convert_type, Choice, Path
 from .globals import resolve_color_default
-from .utils import LazyFile
 
 
 # The prompt functions to use.  The doc tools currently override these
@@ -50,17 +48,10 @@ def _build_prompt(text, suffix, show_default=False, default=None, show_choices=T
     if type is not None and show_choices and isinstance(type, Choice):
         prompt += ' (' + ", ".join(map(str, type.choices)) + ')'
     if default is not None and show_default:
-        prompt = '%s [%s]' % (prompt, _format_default(default))
+        prompt = '%s [%s]' % (prompt, default)
     return prompt + suffix
 
 
-def _format_default(default):
-    if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"):
-        return default.name
-
-    return default
-
-
 def prompt(text, default=None, hide_input=False, confirmation_prompt=False,
            type=None, value_proc=None, prompt_suffix=': ', show_default=True,
            err=False, show_choices=True):
diff --git a/click/types.py b/click/types.py
index b88d15e..f5d06a1 100644
--- a/click/types.py
+++ b/click/types.py
@@ -119,6 +119,8 @@ class StringParamType(ParamType):
                         value = value.decode(fs_enc)
                     except UnicodeError:
                         value = value.decode('utf-8', 'replace')
+                else:
+                    value = value.decode('utf-8', 'replace')
             return value
         return value
 
diff --git a/docs/bashcomplete.rst b/docs/bashcomplete.rst
index 64eede8..bff38fa 100644
--- a/docs/bashcomplete.rst
+++ b/docs/bashcomplete.rst
@@ -18,10 +18,10 @@ only supports completion for Bash and Zsh.
 What it Completes
 -----------------
 
-Generally, the Bash completion support will complete subcommands,
-options, and any option or argument values where the type is
-:class:`click.Choice`. Subcommands and choices are always listed whereas
-options are only listed if at least a dash has been provided. ::
+Generally, the Bash completion support will complete subcommands, options
+and any option or argument values where the type is click.Choice.
+Subcommands and choices are always listed whereas options only if at
+least a dash has been provided.  Example::
 
     $ repo <TAB><TAB>
     clone    commit   copy     delete   setuser
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 955deaf..218fe33 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -1,4 +1,4 @@
-Changes
-=======
+Changelog
+=========
 
 .. include:: ../CHANGES.rst
diff --git a/docs/commands.rst b/docs/commands.rst
index c32e917..378fa73 100644
--- a/docs/commands.rst
+++ b/docs/commands.rst
@@ -88,7 +88,7 @@ script like this:
     @click.pass_context
     def cli(ctx, debug):
         # ensure that ctx.obj exists and is a dict (in case `cli()` is called
-        # by means other than the `if` block below)
+        # by means other than the `if` block below
         ctx.ensure_object(dict)
 
         ctx.obj['DEBUG'] = debug
@@ -317,8 +317,7 @@ When using multi command chaining you can only have one command (the last)
 use ``nargs=-1`` on an argument.  It is also not possible to nest multi
 commands below chained multicommands.  Other than that there are no
 restrictions on how they work.  They can accept options and arguments as
-normal. The order between options and arguments is limited for chained
-commands. Currently only ``--options argument`` order is allowed.
+normal.
 
 Another note: the :attr:`Context.invoked_subcommand` attribute is a bit
 useless for multi commands as it will give ``'*'`` as value if more than
@@ -440,18 +439,10 @@ defaults.
 This is useful if you plug in some commands from another package but
 you're not satisfied with the defaults.
 
-The default map can be nested arbitrarily for each subcommand:
-
-.. code-block:: python
-
-    default_map = {
-        "debug": True,  # default for a top level option
-        "runserver": {"port": 5000}  # default for a subcommand
-    }
-
-The default map can be provided when the script is invoked, or
-overridden at any point by commands. For instance, a top-level command
-could load the defaults from a configuration file.
+The default map can be nested arbitrarily for each subcommand and
+provided when the script is invoked.  Alternatively, it can also be
+overridden at any point by commands.  For instance, a top-level command could
+load the defaults from a configuration file.
 
 Example usage:
 
diff --git a/docs/license.rst b/docs/license.rst
index a53a98c..13eb726 100644
--- a/docs/license.rst
+++ b/docs/license.rst
@@ -1,4 +1,14 @@
-BSD-3-Clause License
-====================
+License
+=======
+
+Click is licensed under a three-clause BSD License.  It basically means:
+do whatever you want with it as long as the copyright in Click sticks
+around, the conditions are not modified and the disclaimer is present.
+Furthermore, you must not use the names of the authors to promote derivatives
+of the software without written consent.
+
+License Text
+------------
 
 .. include:: ../LICENSE.rst
+
diff --git a/docs/options.rst b/docs/options.rst
index c60b45f..095041e 100644
--- a/docs/options.rst
+++ b/docs/options.rst
@@ -145,13 +145,11 @@ used.  The above example is thus equivalent to this:
     def putitem(item):
         click.echo('name=%s id=%d' % item)
 
-.. _multiple-options:
-
 Multiple Options
 ----------------
 
 Similarly to ``nargs``, there is also the case of wanting to support a
-parameter being provided multiple times and have all the values recorded --
+parameter being provided multiple times to and have all values recorded --
 not just the last one.  For instance, ``git commit -m foo -m bar`` would
 record two lines for the commit message: ``foo`` and ``bar``. This can be
 accomplished with the ``multiple`` flag:
@@ -171,15 +169,6 @@ And on the command line:
 
     invoke(commit, args=['-m', 'foo', '-m', 'bar'])
 
-When passing a ``default`` with ``multiple=True``, the default value
-must be a list or tuple, otherwise it will be interpreted as a list of
-single characters.
-
-.. code-block:: python
-
-    @click.option("--format", multiple=True, default=["json"])
-
-
 Counting
 --------
 
@@ -352,15 +341,13 @@ What it looks like:
     println()
     invoke(digest, args=['--help'])
 
-Only pass the choices as list or tuple. Other iterables (like
-generators) may lead to unexpected results.
+.. note::
 
-Choices work with options that have ``multiple=True``. If a ``default``
-value is given with ``multiple=True``, it should be a list or tuple of
-valid choices.
+    You should only pass the choices as list or tuple.  Other iterables (like
+    generators) may lead to surprising results.
 
-Choices should be unique after considering the effects of
-``case_sensitive`` and any specified token normalization function.
+    Choices should be unique after considering the effects of
+    ``case_sensitive`` and any specified token normalization function.
 
 .. versionchanged:: 7.1
     The resulting value from an option will always be on the of the
@@ -407,10 +394,6 @@ What it looks like:
 
     invoke(hello, input=['John'])
 
-It is advised that prompt not be used in conjunction with the multiple
-flag set to True. Instead, prompt in the function interactively.
-
-
 Password Prompts
 ----------------
 
@@ -595,8 +578,8 @@ environment variables which is supported for options only.  To enable this
 feature, the ``auto_envvar_prefix`` parameter needs to be passed to the
 script that is invoked.  Each command and parameter is then added as an
 uppercase underscore-separated variable.  If you have a subcommand
-called ``run`` taking an option called ``reload`` and the prefix is
-``WEB``, then the variable is ``WEB_RUN_RELOAD``.
+called ``foo`` taking an option called ``bar`` and the prefix is
+``MY_TOOL``, then the variable is ``MY_TOOL_FOO_BAR``.
 
 Example usage:
 
@@ -617,11 +600,8 @@ And from the command line:
     invoke(greet, env={'GREETER_USERNAME': 'john'},
            auto_envvar_prefix='GREETER')
 
-When using ``auto_envvar_prefix`` with command groups, the command name
-needs to be included in the environment variable, between the prefix and
-the parameter name, *i.e.* ``PREFIX_COMMAND_VARIABLE``. If you have a
-subcommand called ``run-server`` taking an option called ``host`` and
-the prefix is ``WEB``, then the variable is ``WEB_RUN_SERVER_HOST``.
+When using ``auto_envvar_prefix`` with command groups, the command name needs
+to be included in the environment variable, between the prefix and the parameter name, *i.e.* *PREFIX_COMMAND_VARIABLE*.
 
 Example:
 
diff --git a/docs/parameters.rst b/docs/parameters.rst
index 7ee145c..856e277 100644
--- a/docs/parameters.rst
+++ b/docs/parameters.rst
@@ -28,8 +28,7 @@ available for options:
 
 On the other hand arguments, unlike options, can accept an arbitrary number
 of arguments.  Options can strictly ever only accept a fixed number of
-arguments (defaults to 1), or they may be specified multiple times using
-:ref:`multiple-options`.
+arguments (defaults to 1).
 
 Parameter Types
 ---------------
diff --git a/docs/python3.rst b/docs/python3.rst
index c1736a8..b68da64 100644
--- a/docs/python3.rst
+++ b/docs/python3.rst
@@ -120,12 +120,6 @@ If you see something like this error in Python 3::
       to Python 2 or consult the Python 3 section of the docs for
       mitigation steps.
 
-.. note::
-
-    In Python 3.7 and later you will no longer get a ``RuntimeError`` in
-    many cases thanks to :pep:`538` and :pep:`540`, which changed the
-    default assumption in unconfigured environments.
-
 You are dealing with an environment where Python 3 thinks you are
 restricted to ASCII data.  The solution to these problems is different
 depending on which locale your computer is running in.
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
index 3644509..c5ee8c6 100644
--- a/docs/quickstart.rst
+++ b/docs/quickstart.rst
@@ -39,7 +39,7 @@ commands will work for you::
 
 or even better::
 
-    $ pip install virtualenv --user
+    $ sudo pip install virtualenv
 
 One of these will probably install virtualenv on your system.  Maybe it's even
 in your package manager.  If you use Ubuntu, try::
diff --git a/docs/upgrading.rst b/docs/upgrading.rst
index ea082bb..7c4cccd 100644
--- a/docs/upgrading.rst
+++ b/docs/upgrading.rst
@@ -6,37 +6,6 @@ this is not entirely possible.  In case we need to break backwards
 compatibility this document gives you information about how to upgrade or
 handle backwards compatibility properly.
 
-.. _upgrade-to-7.0:
-
-Upgrading to 7.0
-----------------
-
-Commands that take their name from the decorated function now replace
-underscores with dashes. For example, the Python function ``run_server``
-will get the command name ``run-server`` now. There are a few options
-to address this:
-
--   To continue with the new behavior, pin your dependency to
-    ``Click>=7`` and update any documentation to use dashes.
--   To keep existing behavior, add an explicit command name with
-    underscores, like ``@click.command("run_server")``.
--   To try a name with dashes if the name with underscores was not
-    found, pass a ``token_normalize_func`` to the context:
-
-    .. code-block:: python
-
-        def normalize(name):
-            return name.replace("_", "-")
-
-        @click.group(context_settings={"token_normalize_func": normalize})
-        def group():
-            ...
-
-        @group.command()
-        def run_server():
-            ...
-
-
 .. _upgrade-to-3.2:
 
 Upgrading to 3.2
diff --git a/docs/utils.rst b/docs/utils.rst
index 902e5fd..7250d84 100644
--- a/docs/utils.rst
+++ b/docs/utils.rst
@@ -33,7 +33,7 @@ suppressed by passing ``nl=False``::
 Last but not least :func:`echo` uses click's intelligent internal output
 streams to stdout and stderr which support unicode output on the Windows
 console.  This means for as long as you are using `click.echo` you can
-output unicode characters (there are some limitations on the default font
+output unicode character (there are some limitations on the default font
 with regards to which characters can be displayed).  This functionality is
 new in Click 6.0.
 
@@ -211,7 +211,7 @@ Click supports launching editors automatically through :func:`edit`.  This
 is very useful for asking users for multi-line input.  It will
 automatically open the user's defined editor or fall back to a sensible
 default.  If the user closes the editor without saving, the return value
-will be ``None``, otherwise the entered text.
+will be `None` otherwise the entered text.
 
 Example usage::
 
@@ -389,16 +389,6 @@ but you know the length, you can explicitly provide it::
         for user in bar:
             modify_the_user(user)
 
-Note that :func:`progressbar` updates the bar *after* each iteration of the
-loop. So code like this will render correctly::
-
-    import time
-
-    with click.progressbar([1, 2, 3]) as bar:
-        for x in bar:
-            print('sleep({})...'.format(x))
-            time.sleep(x)
-
 Another useful feature is to associate a label with the progress bar which
 will be shown preceding the progress bar::
 
diff --git a/docs/why.rst b/docs/why.rst
index 9418bfe..75c1980 100644
--- a/docs/why.rst
+++ b/docs/why.rst
@@ -10,7 +10,7 @@ line utility for Python out there which ticks the following boxes:
 *   is lazily composable without restrictions
 *   supports implementation of Unix/POSIX command line conventions
 *   supports loading values from environment variables out of the box
-*   support for prompting of custom values
+*   supports for prompting of custom values
 *   is fully nestable and composable
 *   works the same in Python 2 and 3
 *   supports file handling out of the box
@@ -18,9 +18,9 @@ line utility for Python out there which ticks the following boxes:
     ANSI colors, fetching direct keyboard input, screen clearing,
     finding config paths, launching apps and editors, etc.)
 
-There are many alternatives to Click; the obvious ones are ``optparse``
-and ``argparse`` from the standard library. Have a look to see if something
-else resonates with you.
+There are many alternatives to Click and you can have a look at them if
+you enjoy them better.  The obvious ones are ``optparse`` and ``argparse``
+from the standard library.
 
 Click actually implements its own parsing of arguments and does not use
 ``optparse`` or ``argparse`` following the ``optparse`` parsing behavior.
@@ -28,10 +28,13 @@ The reason it's not based on ``argparse`` is that ``argparse`` does not
 allow proper nesting of commands by design and has some deficiencies when
 it comes to POSIX compliant argument handling.
 
-Click is designed to be fun and customizable but not overly flexible.
-For instance, the customizability of help pages is constrained. This
-constraint is intentional because Click promises multiple Click instances
-will continue to function as intended when strung together.
+Click is designed to be fun to work with and at the same time not stand in
+your way.  It's not overly flexible either.  Currently, for instance, it
+does not allow you to customize the help pages too much. This is intentional
+because Click is designed to allow you to nest command line utilities.  The
+idea is that you can have a system that works together with another system by
+tacking two Click instances together and they will continue working as they
+should.
 
 Too much customizability would break this promise.
 
@@ -40,29 +43,31 @@ microframework ecosystem because no tool could provide it with the
 functionality it needed.
 
 To get an understanding of what Click is all about, I strongly recommend
-looking at the :ref:`complex-guide` chapter.
+looking at the :ref:`complex-guide` chapter to see what it's useful for.
 
 Why not Argparse?
 -----------------
 
-Click is internally based on ``optparse`` instead of ``argparse``. This
+Click is internally based on optparse instead of argparse.  This however
 is an implementation detail that a user does not have to be concerned
-with. Click is not based on argparse because it has some behaviors that
-make handling arbitrary command line interfaces hard:
-
-*   argparse has built-in behavior to guess if something is an
-    argument or an option. This becomes a problem when dealing with
-    incomplete command lines; the behaviour becomes unpredictable
-    without full knowledge of a command line. This goes against Click's
-    ambitions of dispatching to subparsers.
-*   argparse does not support disabling interspersed arguments. Without
-    this feature, it's not possible to safely implement Click's nested
-    parsing.
+with.  The reason however Click is not using argparse is that it has some
+problematic behaviors that make handling arbitrary command line interfaces
+hard:
+
+*   argparse has built-in magic behavior to guess if something is an
+    argument or an option.  This becomes a problem when dealing with
+    incomplete command lines as it's not possible to know without having a
+    full understanding of the command line how the parser is going to
+    behave.  This goes against Click's ambitions of dispatching to
+    subparsers.
+*   argparse currently does not support disabling of interspersed
+    arguments.  Without this feature it's not possible to safely implement
+    Click's nested parsing nature.
 
 Why not Docopt etc.?
 --------------------
 
-Docopt, and many tools like it, are cool in how they work, but very few of
+Docopt and many tools like it are cool in how they work, but very few of
 these tools deal with nesting of commands and composability in a way like
 Click.  To the best of the developer's knowledge, Click is the first
 Python library that aims to create a level of composability of applications
@@ -73,13 +78,13 @@ according to those rules.  The side effect of this is that docopt is quite
 rigid in how it handles the command line interface.  The upside of docopt
 is that it gives you strong control over your help page; the downside is
 that due to this it cannot rewrap your output for the current terminal
-width, and it makes translations hard.  On top of that, docopt is restricted
+width and it makes translations hard.  On top of that docopt is restricted
 to basic parsing.  It does not handle argument dispatching and callback
 invocation or types.  This means there is a lot of code that needs to be
 written in addition to the basic help page to handle the parsing results.
 
 Most of all, however, it makes composability hard.  While docopt does
-support dispatching to subcommands, it, for instance, does not directly
+support dispatching to subcommands, it for instance does not directly
 support any kind of automatic subcommand enumeration based on what's
 available or it does not enforce subcommands to work in a consistent way.
 
@@ -90,25 +95,25 @@ following:
 -   Click does not just parse, it also dispatches to the appropriate code.
 -   Click has a strong concept of an invocation context that allows
     subcommands to respond to data from the parent command.
--   Click has strong information available for all parameters and commands,
-    so it can generate unified help pages for the full CLI and
+-   Click has strong information available for all parameters and commands
+    so that it can generate unified help pages for the full CLI and to
     assist the user in converting the input data as necessary.
--   Click has a strong understanding of what types are, and it can give the user
+-   Click has a strong understanding of what types are and can give the user
     consistent error messages if something goes wrong.  A subcommand
     written by a different developer will not suddenly die with a
     different error message because it's manually handled.
 -   Click has enough meta information available for its whole program
-    to evolve over time and improve the user experience without
+    that it can evolve over time to improve the user experience without
     forcing developers to adjust their programs.  For instance, if Click
     decides to change how help pages are formatted, all Click programs
     will automatically benefit from this.
 
-The aim of Click is to make composable systems. Whereas, the aim of docopt
+The aim of Click is to make composable systems, whereas the aim of docopt
 is to build the most beautiful and hand-crafted command line interfaces.
 These two goals conflict with one another in subtle ways.  Click
 actively prevents people from implementing certain patterns in order to
-achieve unified command line interfaces.  For instance, as a developer, you
-are given very little choice in formatting your help pages.
+achieve unified command line interfaces.  You have very little input on
+reformatting your help pages for instance.
 
 
 Why Hardcoded Behaviors?
@@ -139,7 +144,7 @@ even optparse and argparse support automatic expansion of long arguments.
 The reason for this is that it's a liability for backwards compatibility.
 If people start relying on automatically modified parameters and someone
 adds a new parameter in the future, the script might stop working.  These
-kinds of problems are hard to find, so Click does not attempt to be magical
+kinds of problems are hard to find so Click does not attempt to be magical
 about this.
 
 This sort of behavior however can be implemented on a higher level to
diff --git a/setup.cfg b/setup.cfg
index a675115..d4c2343 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -6,8 +6,6 @@ universal = 1
 
 [tool:pytest]
 testpaths = tests
-filterwarnings =
-    error
 
 [coverage:run]
 branch = True
@@ -18,4 +16,5 @@ source =
 [coverage:paths]
 source =
     click
-    */site-packages
+    .tox/*/lib/python*/site-packages/click
+    .tox/pypy/site-packages/click
diff --git a/setup.py b/setup.py
index b038a5c..a6e0a94 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ with io.open("README.rst", "rt", encoding="utf8") as f:
     readme = f.read()
 
 with io.open("click/__init__.py", "rt", encoding="utf8") as f:
-    version = re.search(r"__version__ = '(.*?)'", f.read()).group(1)
+    version = re.search(r"__version__ = \'(.*?)\'", f.read()).group(1)
 
 setup(
     name="click",
@@ -17,14 +17,16 @@ setup(
         "Code": "https://github.com/pallets/click",
         "Issue tracker": "https://github.com/pallets/click/issues",
     },
-    license="BSD-3-Clause",
-    maintainer="Pallets",
+    license="BSD",
+    author="Armin Ronacher",
+    author_email="armin.ronacher@active-4.com",
+    maintainer="Pallets Team",
     maintainer_email="contact@palletsprojects.com",
     description="Composable command line interface toolkit",
     long_description=readme,
     packages=["click"],
     include_package_data=True,
-    python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*",
+    python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
     classifiers=[
         "Development Status :: 5 - Production/Stable",
         "Intended Audience :: Developers",
@@ -32,6 +34,11 @@ setup(
         "Operating System :: OS Independent",
         "Programming Language :: Python",
         "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 2.7",
         "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.4",
+        "Programming Language :: Python :: 3.5",
+        "Programming Language :: Python :: 3.6",
+        "Programming Language :: Python :: 3.7",
     ],
 )
diff --git a/tox.ini b/tox.ini
index 30c16da..51ba92a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,15 +1,32 @@
 [tox]
 envlist =
-    py{38,37,36,35,27,py3,py}
+    py{37,36,35,27,py3,py}
     docs
+    coverage
 skip_missing_interpreters = true
 
 [testenv]
 deps =
     pytest
+    coverage
     colorama
-commands = pytest --tb=short --basetemp={envtmpdir} {posargs}
+commands = coverage run -p -m pytest --tb=short -Werror --basetemp={envtmpdir} {posargs}
 
 [testenv:docs]
 deps = -r docs/requirements.txt
 commands = sphinx-build -W -b html -d {envtmpdir}/doctrees docs {envtmpdir}/html
+
+[testenv:coverage]
+deps = coverage
+skip_install = true
+commands =
+    coverage combine
+    coverage html
+    coverage report
+
+[testenv:coverage-ci]
+deps = codecov
+skip_install = true
+commands =
+    coverage combine
+    coverage xml


Test patch:
diff --git a/click/testing.py b/click/testing.py
index 343b007..1b2924e 100644
--- a/click/testing.py
+++ b/click/testing.py
@@ -79,7 +79,7 @@ class Result(object):
         self.runner = runner
         #: The standard output as bytes.
         self.stdout_bytes = stdout_bytes
-        #: The standard error as bytes, or None if not available
+        #: The standard error as bytes, or False(y) if not available
         self.stderr_bytes = stderr_bytes
         #: The exit code as integer.
         self.exit_code = exit_code
@@ -102,7 +102,7 @@ class Result(object):
     @property
     def stderr(self):
         """The standard error as unicode string."""
-        if self.stderr_bytes is None:
+        if not self.stderr_bytes:
             raise ValueError("stderr not separately captured")
         return self.stderr_bytes.decode(self.runner.charset, 'replace') \
             .replace('\r\n', '\n')
@@ -278,7 +278,7 @@ class CliRunner(object):
             clickpkg.formatting.FORCED_WIDTH = old_forced_width
 
     def invoke(self, cli, args=None, input=None, env=None,
-               catch_exceptions=True, color=False, **extra):
+               catch_exceptions=True, color=False, mix_stderr=False, **extra):
         """Invokes a command in an isolated environment.  The arguments are
         forwarded directly to the command line script, the `extra` keyword
         arguments are passed to the :meth:`~clickpkg.Command.main` function of
@@ -347,10 +347,7 @@ class CliRunner(object):
             finally:
                 sys.stdout.flush()
                 stdout = outstreams[0].getvalue()
-                if self.mix_stderr:
-                    stderr = None
-                else:
-                    stderr = outstreams[1].getvalue()
+                stderr = outstreams[1] and outstreams[1].getvalue()
 
         return Result(runner=self,
                       stdout_bytes=stdout,
diff --git a/docs/testing.rst b/docs/testing.rst
index 52a888d..4d9ed67 100644
--- a/docs/testing.rst
+++ b/docs/testing.rst
@@ -82,9 +82,9 @@ For example, if you want to run your tests against a fixed terminal width you ca
 File System Isolation
 ---------------------
 
-For basic command line tools with file system operations, the
-:meth:`CliRunner.isolated_filesystem` method is useful for setting the
-current working directory to a new, empty folder.
+For basic command line tools that want to operate with the file system, the
+:meth:`CliRunner.isolated_filesystem` method comes in useful which sets up
+an empty folder and changes the current working directory to:
 
 .. code-block:: python
    :caption: cat.py
diff --git a/tests/test_arguments.py b/tests/test_arguments.py
index 4428042..fb2f75b 100644
--- a/tests/test_arguments.py
+++ b/tests/test_arguments.py
@@ -1,7 +1,8 @@
 # -*- coding: utf-8 -*-
 import pytest
 import click
-from click._compat import PY2
+import sys
+from click._compat import PY2, text_type
 
 
 def test_nargs_star(runner):
@@ -84,6 +85,26 @@ def test_nargs_err(runner):
     assert 'Got unexpected extra argument (bar)' in result.output
 
 
+def test_bytes_args(runner, monkeypatch):
+    @click.command()
+    @click.argument('arg')
+    def from_bytes(arg):
+        assert isinstance(arg, text_type), "UTF-8 encoded argument should be implicitly converted to Unicode"
+
+    # Simulate empty locale environment variables
+    if PY2:
+        monkeypatch.setattr(sys.stdin, 'encoding', 'ANSI_X3.4-1968')
+        monkeypatch.setattr(sys, 'getfilesystemencoding', lambda: 'ANSI_X3.4-1968')
+        monkeypatch.setattr(sys, 'getdefaultencoding', lambda: 'ascii')
+    else:
+        monkeypatch.setattr(sys.stdin, 'encoding', 'utf-8')
+        monkeypatch.setattr(sys, 'getfilesystemencoding', lambda: 'utf-8')
+        monkeypatch.setattr(sys, 'getdefaultencoding', lambda: 'utf-8')
+
+    runner.invoke(from_bytes, [u'Something outside of ASCII range: 林'.encode('UTF-8')],
+            catch_exceptions=False)
+
+
 def test_file_args(runner):
     @click.command()
     @click.argument('input', type=click.File('rb'))
@@ -203,15 +224,6 @@ def test_missing_arg(runner):
     assert 'Missing argument "ARG".' in result.output
 
 
-def test_missing_argument_string_cast():
-    ctx = click.Context(click.Command(""))
-
-    with pytest.raises(click.MissingParameter) as excinfo:
-        click.Argument(["a"], required=True).full_process_value(ctx, None)
-
-    assert str(excinfo.value) == "missing parameter: a"
-
-
 def test_implicit_non_required(runner):
     @click.command()
     @click.argument('f', default='test')
diff --git a/tests/test_bashcomplete.py b/tests/test_bashcomplete.py
index 5eb4068..7214d1a 100644
--- a/tests/test_bashcomplete.py
+++ b/tests/test_bashcomplete.py
@@ -1,7 +1,5 @@
 # -*- coding: utf-8 -*-
 
-import pytest
-
 import click
 from click._bashcomplete import get_choices
 
@@ -409,28 +407,3 @@ def test_hidden():
     # If the user exactly types out the hidden command, complete its subcommands.
     assert choices_without_help(cli, ['hgroup'], '') == ['hgroupsub']
     assert choices_without_help(cli, ['hsub'], '--h') == ['--hname']
-
-
-@pytest.mark.parametrize(
-    ("args", "part", "expect"),
-    [
-        ([], "-", ["--opt"]),
-        (["value"], "--", ["--opt"]),
-        ([], "-o", []),
-        (["--opt"], "-o", []),
-        (["--"], "", ["name", "-o", "--opt", "--"]),
-        (["--"], "--o", ["--opt"]),
-    ],
-)
-def test_args_with_double_dash_complete(args, part, expect):
-    def _complete(ctx, args, incomplete):
-        values = ["name", "-o", "--opt", "--"]
-        return [x for x in values if x.startswith(incomplete)]
-
-    @click.command()
-    @click.option("--opt")
-    @click.argument("args", nargs=-1, autocompletion=_complete)
-    def cli(opt, args):
-        pass
-
-    assert choices_without_help(cli, args, part) == expect
diff --git a/tests/test_basic.py b/tests/test_basic.py
index f800b4d..8de6301 100644
--- a/tests/test_basic.py
+++ b/tests/test_basic.py
@@ -23,24 +23,6 @@ def test_basic_functionality(runner):
     assert result.exit_code == 0
 
 
-def test_repr():
-    @click.command()
-    def command():
-        pass
-
-    @click.group()
-    def group():
-        pass
-
-    @group.command()
-    def subcommand():
-        pass
-
-    assert repr(command) == '<Command command>'
-    assert repr(group) == '<Group group>'
-    assert repr(subcommand) == '<Command subcommand>'
-
-
 def test_return_values():
     @click.command()
     def cli():
diff --git a/tests/test_compat.py b/tests/test_compat.py
index 674cded..abc733b 100644
--- a/tests/test_compat.py
+++ b/tests/test_compat.py
@@ -25,14 +25,6 @@ def test_bash_func_name():
     assert '_COMPLETE_VAR=complete $1' in script
 
 
-def test_zsh_func_name():
-    from click._bashcomplete import get_completion_script
-    script = get_completion_script('foo-bar', '_COMPLETE_VAR', 'zsh').strip()
-    assert script.startswith('#compdef foo-bar')
-    assert 'compdef _foo_bar_completion foo-bar;' in script
-    assert '(( ! $+commands[foo-bar] )) && return 1' in script
-
-
 @pytest.mark.xfail(WIN, reason="Jupyter not tested/supported on Windows")
 def test_is_jupyter_kernel_output():
     class JupyterKernelFakeStream(object):
diff --git a/tests/test_formatting.py b/tests/test_formatting.py
index e4d2571..566f316 100644
--- a/tests/test_formatting.py
+++ b/tests/test_formatting.py
@@ -312,40 +312,4 @@ def test_global_show_default(runner):
         'Options:',
         '  -f TEXT  Output file name  [default: out.txt]',
         '  --help   Show this message and exit.  [default: False]'
-    ]
-
-
-def test_formatting_usage_multiline_option_padding(runner):
-    @click.command('foo')
-    @click.option('--bar', help='This help message will be padded if it wraps.')
-    def cli():
-        pass
-
-    result = runner.invoke(cli, '--help', terminal_width=45)
-    assert not result.exception
-    assert result.output.splitlines() == [
-        'Usage: foo [OPTIONS]',
-        '',
-        'Options:',
-        '  --bar TEXT  This help message will be',
-        '              padded if it wraps.',
-        '',
-        '  --help      Show this message and exit.'
-    ]
-
-
-def test_formatting_usage_no_option_padding(runner):
-    @click.command('foo')
-    @click.option('--bar', help='This help message will be padded if it wraps.')
-    def cli():
-        pass
-
-    result = runner.invoke(cli, '--help', terminal_width=80)
-    assert not result.exception
-    assert result.output.splitlines() == [
-        'Usage: foo [OPTIONS]',
-        '',
-        'Options:',
-        '  --bar TEXT  This help message will be padded if it wraps.',
-        '  --help      Show this message and exit.'
-    ]
+    ]
\ No newline at end of file
diff --git a/tests/test_imports.py b/tests/test_imports.py
index 268c606..8e9a97d 100644
--- a/tests/test_imports.py
+++ b/tests/test_imports.py
@@ -32,7 +32,7 @@ click.echo(json.dumps(rv))
 ALLOWED_IMPORTS = set([
     'weakref', 'os', 'struct', 'collections', 'sys', 'contextlib',
     'functools', 'stat', 're', 'codecs', 'inspect', 'itertools', 'io',
-    'threading', 'colorama', 'errno', 'fcntl', 'datetime', 'pipes', 'shlex'
+    'threading', 'colorama', 'errno', 'fcntl', 'datetime'
 ])
 
 if WIN:
diff --git a/tests/test_options.py b/tests/test_options.py
index 4a13a0a..14a7a17 100644
--- a/tests/test_options.py
+++ b/tests/test_options.py
@@ -113,17 +113,6 @@ def test_multiple_required(runner):
     assert 'Error: Missing option "-m" / "--message".' in result.output
 
 
-def test_empty_envvar(runner):
-    @click.command()
-    @click.option('--mypath', type=click.Path(exists=True), envvar='MYPATH')
-    def cli(mypath):
-        click.echo('mypath: %s' % mypath)
-
-    result = runner.invoke(cli, [], env={'MYPATH': ''})
-    assert result.exit_code == 0
-    assert result.output == 'mypath: None\n'
-
-
 def test_multiple_envvar(runner):
     @click.command()
     @click.option('--arg', multiple=True)
@@ -273,22 +262,6 @@ def test_show_envvar_auto_prefix(runner):
     assert 'TEST_ARG1' in result.output
 
 
-def test_show_envvar_auto_prefix_dash_in_command(runner):
-    @click.group()
-    def cli():
-        pass
-
-    @cli.command()
-    @click.option('--baz', show_envvar=True)
-    def foo_bar(baz):
-        pass
-
-    result = runner.invoke(cli, ['foo-bar', '--help'],
-                           auto_envvar_prefix='TEST')
-    assert not result.exception
-    assert 'TEST_FOO_BAR_BAZ' in result.output
-
-
 def test_custom_validation(runner):
     def validate_pos_int(ctx, param, value):
         if value < 0:
@@ -337,15 +310,6 @@ def test_legacy_options(runner):
     assert result.output == '23\n'
 
 
-def test_missing_option_string_cast():
-    ctx = click.Context(click.Command(""))
-
-    with pytest.raises(click.MissingParameter) as excinfo:
-        click.Option(['-a'], required=True).full_process_value(ctx, None)
-
-    assert str(excinfo.value) == "missing parameter: a"
-
-
 def test_missing_choice(runner):
     @click.command()
     @click.option('--foo', type=click.Choice(['foo', 'bar']),
@@ -408,30 +372,24 @@ def test_case_insensitive_choice_returned_exactly(runner):
     assert result.output == 'Apple\n'
 
 
-def test_option_help_preserve_paragraphs(runner):
+def test_multiline_help(runner):
     @click.command()
-    @click.option(
-        "-C",
-        "--config",
-        type=click.Path(),
-        help="""Configuration file to use.
-        
-        If not given, the environment variable CONFIG_FILE is consulted
-        and used if set. If neither are given, a default configuration
-        file is loaded.""",
-    )
-    def cmd(config):
-        pass
+    @click.option('--foo', help="""
+        hello
+
+        i am
 
-    result = runner.invoke(cmd, ['--help'], )
+        multiline
+    """)
+    def cmd(foo):
+        click.echo(foo)
+
+    result = runner.invoke(cmd, ['--help'])
     assert result.exit_code == 0
-    assert (
-        "  -C, --config PATH  Configuration file to use.\n"
-        "{i}\n"
-        "{i}If not given, the environment variable CONFIG_FILE is\n"
-        "{i}consulted and used if set. If neither are given, a default\n"
-        "{i}configuration file is loaded.".format(i=" " * 21)
-    ) in result.output
+    out = result.output.splitlines()
+    assert '  --foo TEXT  hello' in out
+    assert '              i am' in out
+    assert '              multiline' in out
 
 def test_argument_custom_class(runner):
     class CustomArgument(click.Argument):
@@ -494,16 +452,6 @@ def test_option_custom_class_reusable(runner):
         assert 'you wont see me' not in result.output
 
 
-def test_bool_flag_with_type(runner):
-    @click.command()
-    @click.option('--shout/--no-shout', default=False, type=bool)
-    def cmd(shout):
-        pass
-
-    result = runner.invoke(cmd)
-    assert not result.exception
-
-
 def test_aliases_for_flags(runner):
     @click.command()
     @click.option('--warnings/--no-warnings', ' /-W', default=True)
diff --git a/tests/test_termui.py b/tests/test_termui.py
index c6e06b6..79fb7c6 100644
--- a/tests/test_termui.py
+++ b/tests/test_termui.py
@@ -185,26 +185,6 @@ def test_progressbar_iter_outside_with_exceptions(runner):
         assert False, 'Expected an exception because of abort-related inputs.'
 
 
-def test_progressbar_is_iterator(runner, monkeypatch):
-    fake_clock = FakeClock()
-
-    @click.command()
-    def cli():
-        with click.progressbar(range(10), label='test') as progress:
-            while True:
-                try:
-                    next(progress)
-                    fake_clock.advance_time()
-                except StopIteration:
-                    break
-
-    monkeypatch.setattr(time, 'time', fake_clock.time)
-    monkeypatch.setattr(click._termui_impl, 'isatty', lambda _: True)
-
-    result = runner.invoke(cli, [])
-    assert result.exception is None
-
-
 def test_choices_list_in_prompt(runner, monkeypatch):
     @click.command()
     @click.option('-g', type=click.Choice(['none', 'day', 'week', 'month']),
@@ -225,24 +205,6 @@ def test_choices_list_in_prompt(runner, monkeypatch):
     assert '(none, day, week, month)' not in result.output
 
 
-@pytest.mark.parametrize(
-    "file_kwargs",
-    [
-        {"mode": "rt"},
-        {"mode": "rb"},
-        {"lazy": True},
-    ]
-)
-def test_file_prompt_default_format(runner, file_kwargs):
-    @click.command()
-    @click.option("-f", default=__file__, prompt="file", type=click.File(**file_kwargs))
-    def cli(f):
-        click.echo(f.name)
-
-    result = runner.invoke(cli)
-    assert result.output == "file [{0}]: \n{0}\n".format(__file__)
-
-
 def test_secho(runner):
     with runner.isolation() as outstreams:
         click.secho(None, nl=False)
diff --git a/tests/test_testing.py b/tests/test_testing.py
index 7b03947..b8565ad 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -257,18 +257,6 @@ def test_stderr():
     with pytest.raises(ValueError):
         result_mix.stderr
 
-    @click.command()
-    def cli_empty_stderr():
-        click.echo("stdout")
-
-    runner = CliRunner(mix_stderr=False)
-
-    result = runner.invoke(cli_empty_stderr)
-
-    assert result.output == 'stdout\n'
-    assert result.stdout == 'stdout\n'
-    assert result.stderr == ''
-
 
 @pytest.mark.parametrize('args, expected_output', [
     (None, 'bar\n'),
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 93f1ca0..4fd7cbb 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,5 +1,4 @@
 import os
-import stat
 import sys
 
 import pytest
@@ -51,45 +50,32 @@ def test_echo_custom_file():
     assert f.getvalue() == u'hello\n'
 
 
-@pytest.mark.parametrize(
-    ("styles", "ref"),
-    [
-        ({"fg": "black"}, "\x1b[30mx y\x1b[0m"),
-        ({"fg": "red"}, "\x1b[31mx y\x1b[0m"),
-        ({"fg": "green"}, "\x1b[32mx y\x1b[0m"),
-        ({"fg": "yellow"}, "\x1b[33mx y\x1b[0m"),
-        ({"fg": "blue"}, "\x1b[34mx y\x1b[0m"),
-        ({"fg": "magenta"}, "\x1b[35mx y\x1b[0m"),
-        ({"fg": "cyan"}, "\x1b[36mx y\x1b[0m"),
-        ({"fg": "white"}, "\x1b[37mx y\x1b[0m"),
-        ({"bg": "black"}, "\x1b[40mx y\x1b[0m"),
-        ({"bg": "red"}, "\x1b[41mx y\x1b[0m"),
-        ({"bg": "green"}, "\x1b[42mx y\x1b[0m"),
-        ({"bg": "yellow"}, "\x1b[43mx y\x1b[0m"),
-        ({"bg": "blue"}, "\x1b[44mx y\x1b[0m"),
-        ({"bg": "magenta"}, "\x1b[45mx y\x1b[0m"),
-        ({"bg": "cyan"}, "\x1b[46mx y\x1b[0m"),
-        ({"bg": "white"}, "\x1b[47mx y\x1b[0m"),
-        ({"blink": True}, "\x1b[5mx y\x1b[0m"),
-        ({"underline": True}, "\x1b[4mx y\x1b[0m"),
-        ({"bold": True}, "\x1b[1mx y\x1b[0m"),
-        ({"dim": True}, "\x1b[2mx y\x1b[0m"),
-    ],
-)
-def test_styling(styles, ref):
-    assert click.style("x y", **styles) == ref
-    assert click.unstyle(ref) == "x y"
-
-
-@pytest.mark.parametrize(
-    ("text", "expect"),
-    [
-        ("\x1b[?25lx y\x1b[?25h", "x y"),
+def test_styling():
+    examples = [
+        ('x', dict(fg='black'), '\x1b[30mx\x1b[0m'),
+        ('x', dict(fg='red'), '\x1b[31mx\x1b[0m'),
+        ('x', dict(fg='green'), '\x1b[32mx\x1b[0m'),
+        ('x', dict(fg='yellow'), '\x1b[33mx\x1b[0m'),
+        ('x', dict(fg='blue'), '\x1b[34mx\x1b[0m'),
+        ('x', dict(fg='magenta'), '\x1b[35mx\x1b[0m'),
+        ('x', dict(fg='cyan'), '\x1b[36mx\x1b[0m'),
+        ('x', dict(fg='white'), '\x1b[37mx\x1b[0m'),
+        ('x', dict(bg='black'), '\x1b[40mx\x1b[0m'),
+        ('x', dict(bg='red'), '\x1b[41mx\x1b[0m'),
+        ('x', dict(bg='green'), '\x1b[42mx\x1b[0m'),
+        ('x', dict(bg='yellow'), '\x1b[43mx\x1b[0m'),
+        ('x', dict(bg='blue'), '\x1b[44mx\x1b[0m'),
+        ('x', dict(bg='magenta'), '\x1b[45mx\x1b[0m'),
+        ('x', dict(bg='cyan'), '\x1b[46mx\x1b[0m'),
+        ('x', dict(bg='white'), '\x1b[47mx\x1b[0m'),
+        ('foo bar', dict(blink=True), '\x1b[5mfoo bar\x1b[0m'),
+        ('foo bar', dict(underline=True), '\x1b[4mfoo bar\x1b[0m'),
+        ('foo bar', dict(bold=True), '\x1b[1mfoo bar\x1b[0m'),
+        ('foo bar', dict(dim=True), '\x1b[2mfoo bar\x1b[0m'),
     ]
-)
-def test_unstyle_other_ansi(text, expect):
-    assert click.unstyle(text) == expect
-
+    for text, styles, ref in examples:
+        assert click.style(text, **styles) == ref
+        assert click.unstyle(ref) == text
 
 
 def test_filename_formatting():
@@ -279,120 +265,41 @@ def test_echo_writing_to_standard_error(capfd, monkeypatch):
 
 
 def test_open_file(runner):
-    @click.command()
-    @click.argument('filename')
-    def cli(filename):
-        with click.open_file(filename) as f:
-            click.echo(f.read())
-
-        click.echo('meep')
-
     with runner.isolated_filesystem():
         with open('hello.txt', 'w') as f:
             f.write('Cool stuff')
 
-        result = runner.invoke(cli, ['hello.txt'])
-        assert result.exception is None
-        assert result.output == 'Cool stuff\nmeep\n'
-
-        result = runner.invoke(cli, ['-'], input='foobar')
-        assert result.exception is None
-        assert result.output == 'foobar\nmeep\n'
-
-
-def test_open_file_ignore_errors_stdin(runner):
-    @click.command()
-    @click.argument("filename")
-    def cli(filename):
-        with click.open_file(filename, errors="ignore") as f:
-            click.echo(f.read())
-
-    result = runner.invoke(cli, ["-"], input=os.urandom(16))
-    assert result.exception is None
-
-
-def test_open_file_respects_ignore(runner):
-    with runner.isolated_filesystem():
-        with open("test.txt", "w") as f:
-            f.write("Hello world!")
-
-        with click.open_file("test.txt", encoding="utf8", errors="ignore") as f:
-            assert f.errors == "ignore"
-
-
-def test_open_file_ignore_invalid_utf8(runner):
-    with runner.isolated_filesystem():
-        with open("test.txt", "wb") as f:
-            f.write(b"\xe2\x28\xa1")
-
-        with click.open_file("test.txt", encoding="utf8", errors="ignore") as f:
-            f.read()
-
-
-def test_open_file_ignore_no_encoding(runner):
-    with runner.isolated_filesystem():
-        with open("test.bin", "wb") as f:
-            f.write(os.urandom(16))
-
-        with click.open_file("test.bin", errors="ignore") as f:
-            f.read()
-
-
-@pytest.mark.skipif(WIN, reason='os.chmod() is not fully supported on Windows.')
-@pytest.mark.parametrize('permissions', [
-    0o400,
-    0o444,
-    0o600,
-    0o644,
- ])
-def test_open_file_atomic_permissions_existing_file(runner, permissions):
-    with runner.isolated_filesystem():
-        with open('existing.txt', 'w') as f:
-            f.write('content')
-        os.chmod('existing.txt', permissions)
-
         @click.command()
         @click.argument('filename')
         def cli(filename):
-           click.open_file(filename, 'w', atomic=True).close()
+            with click.open_file(filename) as f:
+                click.echo(f.read())
+            click.echo('meep')
 
-        result = runner.invoke(cli, ['existing.txt'])
+        result = runner.invoke(cli, ['hello.txt'])
         assert result.exception is None
-        assert stat.S_IMODE(os.stat('existing.txt').st_mode) == permissions
-
-
-@pytest.mark.skipif(WIN, reason='os.stat() is not fully supported on Windows.')
-def test_open_file_atomic_permissions_new_file(runner):
-    with runner.isolated_filesystem():
-        @click.command()
-        @click.argument('filename')
-        def cli(filename):
-            click.open_file(filename, 'w', atomic=True).close()
-
-        # Create a test file to get the expected permissions for new files
-        # according to the current umask.
-        with open('test.txt', 'w'):
-            pass
-        permissions = stat.S_IMODE(os.stat('test.txt').st_mode)
+        assert result.output == 'Cool stuff\nmeep\n'
 
-        result = runner.invoke(cli, ['new.txt'])
+        result = runner.invoke(cli, ['-'], input='foobar')
         assert result.exception is None
-        assert stat.S_IMODE(os.stat('new.txt').st_mode) == permissions
+        assert result.output == 'foobar\nmeep\n'
 
 
+@pytest.mark.xfail(WIN and not PY2, reason='God knows ...')
 def test_iter_keepopenfile(tmpdir):
     expected = list(map(str, range(10)))
     p = tmpdir.mkdir('testdir').join('testfile')
-    p.write("\n".join(expected))
+    p.write(os.linesep.join(expected))
     with p.open() as f:
         for e_line, a_line in zip(expected, click.utils.KeepOpenFile(f)):
             assert e_line == a_line.strip()
 
 
+@pytest.mark.xfail(WIN and not PY2, reason='God knows ...')
 def test_iter_lazyfile(tmpdir):
     expected = list(map(str, range(10)))
     p = tmpdir.mkdir('testdir').join('testfile')
-    p.write("\n".join(expected))
+    p.write(os.linesep.join(expected))
     with p.open() as f:
         with click.utils.LazyFile(f.name) as lf:
             for e_line, a_line in zip(expected, lf):