summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lord <davidism@gmail.com>2020-04-19 21:44:28 -0700
committerDavid Lord <davidism@gmail.com>2020-04-19 23:58:27 -0700
commit20fddf68e85ca98eff368aa171965754f9f446b5 (patch)
treef2dad9ecc3f62bc6ff38e3ceaac5615aaaa37543
parent9df61f821079bd623acf911532b4e529ee7293c1 (diff)
downloadclick-20fddf68e85ca98eff368aa171965754f9f446b5.tar.gz
remove py2 parts of _compat module
-rw-r--r--docs/conf.py5
-rw-r--r--src/click/__init__.py6
-rw-r--r--src/click/_compat.py545
-rw-r--r--src/click/_termui_impl.py22
-rw-r--r--src/click/_unicodefun.py49
-rw-r--r--src/click/_winconsole.py75
-rw-r--r--src/click/core.py26
-rw-r--r--src/click/decorators.py5
-rw-r--r--src/click/exceptions.py21
-rw-r--r--src/click/termui.py9
-rw-r--r--src/click/testing.py53
-rw-r--r--src/click/types.py26
-rw-r--r--src/click/utils.py54
-rw-r--r--tests/test_arguments.py23
-rw-r--r--tests/test_options.py7
-rw-r--r--tests/test_testing.py12
16 files changed, 283 insertions, 655 deletions
diff --git a/docs/conf.py b/docs/conf.py
index f04804c..54c7a4d 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,6 +1,11 @@
from pallets_sphinx_themes import get_version
from pallets_sphinx_themes import ProjectLink
+import click._compat
+
+# compat until pallets-sphinx-themes is updated
+click._compat.text_type = str
+
# Project --------------------------------------------------------------
project = "Click"
diff --git a/src/click/__init__.py b/src/click/__init__.py
index a033e8b..9cd0129 100644
--- a/src/click/__init__.py
+++ b/src/click/__init__.py
@@ -72,8 +72,4 @@ from .utils import get_os_args
from .utils import get_text_stream
from .utils import open_file
-# Controls if click should emit the warning about the use of unicode
-# literals.
-disable_unicode_literals_warning = False
-
-__version__ = "8.0.dev"
+__version__ = "8.0.0.dev"
diff --git a/src/click/_compat.py b/src/click/_compat.py
index cbc64a1..63bebef 100644
--- a/src/click/_compat.py
+++ b/src/click/_compat.py
@@ -1,4 +1,3 @@
-# flake8: noqa
import codecs
import io
import os
@@ -6,7 +5,6 @@ import re
import sys
from weakref import WeakKeyDictionary
-PY2 = sys.version_info[0] == 2
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
@@ -15,8 +13,9 @@ APP_ENGINE = "APPENGINE_RUNTIME" in os.environ and "Development/" in os.environ.
)
WIN = sys.platform.startswith("win") and not APP_ENGINE and not MSYS2
DEFAULT_COLUMNS = 80
-
-
+auto_wrap_for_ansi = None
+colorama = None
+get_winterm_size = None
_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]")
@@ -68,25 +67,7 @@ class _NonClosingTextIOWrapper(io.TextIOWrapper):
**extra
):
self._stream = stream = _FixupStream(stream, force_readable, force_writable)
- io.TextIOWrapper.__init__(self, stream, encoding, errors, **extra)
-
- # The io module is a place where the Python 3 text behavior
- # was forced upon Python 2, so we need to unbreak
- # it to look like Python 2.
- if PY2:
-
- def write(self, x):
- if isinstance(x, str) or is_bytes(x):
- try:
- self.flush()
- except Exception:
- pass
- return self.buffer.write(str(x))
- return io.TextIOWrapper.write(self, x)
-
- def writelines(self, lines):
- for line in lines:
- self.write(line)
+ super().__init__(stream, encoding, errors, **extra)
def __del__(self):
try:
@@ -121,11 +102,7 @@ class _FixupStream(object):
f = getattr(self._stream, "read1", None)
if f is not None:
return f(size)
- # We only dispatch to readline instead of read in Python 2 as we
- # do not want cause problems with the different implementation
- # of line buffering.
- if PY2:
- return self._stream.readline(size)
+
return self._stream.read(size)
def readable(self):
@@ -166,320 +143,207 @@ class _FixupStream(object):
return True
-if PY2:
- text_type = unicode
- raw_input = raw_input
- string_types = (str, unicode)
- int_types = (int, long)
- iteritems = lambda x: x.iteritems()
- range_type = xrange
-
- from pipes import quote as shlex_quote
-
- def is_bytes(x):
- return isinstance(x, (buffer, bytearray))
-
- _identifier_re = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")
-
- # For Windows, we need to force stdout/stdin/stderr to binary if it's
- # fetched for that. This obviously is not the most correct way to do
- # it as it changes global state. Unfortunately, there does not seem to
- # be a clear better way to do it as just reopening the file in binary
- # mode does not change anything.
- #
- # An option would be to do what Python 3 does and to open the file as
- # binary only, patch it back to the system, and then use a wrapper
- # stream that converts newlines. It's not quite clear what's the
- # correct option here.
- #
- # This code also lives in _winconsole for the fallback to the console
- # emulation stream.
- #
- # There are also Windows environments where the `msvcrt` module is not
- # available (which is why we use try-catch instead of the WIN variable
- # here), such as the Google App Engine development server on Windows. In
- # those cases there is just nothing we can do.
- def set_binary_mode(f):
- return f
+def is_bytes(x):
+ return isinstance(x, (bytes, memoryview, bytearray))
+
+def _is_binary_reader(stream, default=False):
try:
- import msvcrt
- except ImportError:
- pass
- else:
+ return isinstance(stream.read(0), bytes)
+ except Exception:
+ return default
+ # This happens in some cases where the stream was already
+ # closed. In this case, we assume the default.
- def set_binary_mode(f):
- try:
- fileno = f.fileno()
- except Exception:
- pass
- else:
- msvcrt.setmode(fileno, os.O_BINARY)
- return f
+def _is_binary_writer(stream, default=False):
try:
- import fcntl
- except ImportError:
- pass
- else:
+ stream.write(b"")
+ except Exception:
+ try:
+ stream.write("")
+ return False
+ except Exception:
+ pass
+ return default
+ return True
- def set_binary_mode(f):
- try:
- fileno = f.fileno()
- except Exception:
- pass
- else:
- flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
- fcntl.fcntl(fileno, fcntl.F_SETFL, flags & ~os.O_NONBLOCK)
- return f
- def isidentifier(x):
- return _identifier_re.search(x) is not None
+def _find_binary_reader(stream):
+ # We need to figure out if the given stream is already binary.
+ # This can happen because the official docs recommend detaching
+ # the streams to get binary streams. Some code might do this, so
+ # we need to deal with this case explicitly.
+ if _is_binary_reader(stream, False):
+ return stream
- def get_binary_stdin():
- return set_binary_mode(sys.stdin)
+ buf = getattr(stream, "buffer", None)
- def get_binary_stdout():
- _wrap_std_stream("stdout")
- return set_binary_mode(sys.stdout)
+ # Same situation here; this time we assume that the buffer is
+ # actually binary in case it's closed.
+ if buf is not None and _is_binary_reader(buf, True):
+ return buf
- def get_binary_stderr():
- _wrap_std_stream("stderr")
- return set_binary_mode(sys.stderr)
- def get_text_stdin(encoding=None, errors=None):
- rv = _get_windows_console_stream(sys.stdin, encoding, errors)
- if rv is not None:
- return rv
- return _make_text_stream(sys.stdin, encoding, errors, force_readable=True)
+def _find_binary_writer(stream):
+ # We need to figure out if the given stream is already binary.
+ # This can happen because the official docs recommend detaching
+ # the streams to get binary streams. Some code might do this, so
+ # we need to deal with this case explicitly.
+ if _is_binary_writer(stream, False):
+ return stream
- def get_text_stdout(encoding=None, errors=None):
- _wrap_std_stream("stdout")
- rv = _get_windows_console_stream(sys.stdout, encoding, errors)
- if rv is not None:
- return rv
- return _make_text_stream(sys.stdout, encoding, errors, force_writable=True)
+ buf = getattr(stream, "buffer", None)
- def get_text_stderr(encoding=None, errors=None):
- _wrap_std_stream("stderr")
- rv = _get_windows_console_stream(sys.stderr, encoding, errors)
- if rv is not None:
- return rv
- return _make_text_stream(sys.stderr, encoding, errors, force_writable=True)
+ # Same situation here; this time we assume that the buffer is
+ # actually binary in case it's closed.
+ if buf is not None and _is_binary_writer(buf, True):
+ return buf
- def filename_to_ui(value):
- if isinstance(value, bytes):
- value = value.decode(get_filesystem_encoding(), "replace")
- return value
+def _stream_is_misconfigured(stream):
+ """A stream is misconfigured if its encoding is ASCII."""
+ # If the stream does not have an encoding set, we assume it's set
+ # to ASCII. This appears to happen in certain unittest
+ # environments. It's not quite clear what the correct behavior is
+ # but this at least will force Click to recover somehow.
+ return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii")
-else:
- import io
- text_type = str
- raw_input = input
- string_types = (str,)
- int_types = (int,)
- range_type = range
- isidentifier = lambda x: x.isidentifier()
- iteritems = lambda x: iter(x.items())
+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)
- from shlex import quote as shlex_quote
- def is_bytes(x):
- return isinstance(x, (bytes, memoryview, bytearray))
+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)
+
+
+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
+ 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 binary_reader is None:
+ return text_stream
+
+ # Default errors to replace instead of strict in order to get
+ # something that works.
+ if errors is None:
+ errors = "replace"
- def _is_binary_reader(stream, default=False):
- try:
- return isinstance(stream.read(0), bytes)
- except Exception:
- return default
- # This happens in some cases where the stream was already
- # closed. In this case, we assume the default.
+ # 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 _is_binary_writer(stream, default=False):
- try:
- stream.write(b"")
- except Exception:
- try:
- stream.write("")
- return False
- except Exception:
- pass
- return default
- return True
- def _find_binary_reader(stream):
- # We need to figure out if the given stream is already binary.
- # This can happen because the official docs recommend detaching
- # the streams to get binary streams. Some code might do this, so
- # we need to deal with this case explicitly.
- if _is_binary_reader(stream, False):
- return stream
-
- buf = getattr(stream, "buffer", None)
-
- # Same situation here; this time we assume that the buffer is
- # actually binary in case it's closed.
- if buf is not None and _is_binary_reader(buf, True):
- return buf
-
- def _find_binary_writer(stream):
- # We need to figure out if the given stream is already binary.
- # This can happen because the official docs recommend detaching
- # the streams to get binary streams. Some code might do this, so
- # we need to deal with this case explicitly.
- if _is_binary_writer(stream, False):
- return stream
-
- buf = getattr(stream, "buffer", None)
-
- # Same situation here; this time we assume that the buffer is
- # actually binary in case it's closed.
- if buf is not None and _is_binary_writer(buf, True):
- return buf
-
- def _stream_is_misconfigured(stream):
- """A stream is misconfigured if its encoding is ASCII."""
- # If the stream does not have an encoding set, we assume it's set
- # to ASCII. This appears to happen in certain unittest
- # environments. It's not quite clear what the correct behavior is
- # 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)
-
- def _force_correct_text_stream(
- text_stream,
+def _force_correct_text_reader(text_reader, encoding, errors, force_readable=False):
+ return _force_correct_text_stream(
+ text_reader,
encoding,
errors,
- is_binary,
- find_binary,
- force_readable=False,
- force_writable=False,
- ):
- if is_binary(text_stream, False):
- binary_reader = text_stream
- 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 binary_reader is None:
- return text_stream
-
- # Default errors to replace instead of strict in order to get
- # something that works.
- 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,
- )
+ _is_binary_reader,
+ _find_binary_reader,
+ force_readable=force_readable,
+ )
- 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,
- )
+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,
+ )
- def get_binary_stdin():
- reader = _find_binary_reader(sys.stdin)
- if reader is None:
- raise RuntimeError("Was not able to determine binary stream for sys.stdin.")
- return reader
-
- def get_binary_stdout():
- writer = _find_binary_writer(sys.stdout)
- if writer is None:
- raise RuntimeError(
- "Was not able to determine binary stream for sys.stdout."
- )
- return writer
-
- def get_binary_stderr():
- writer = _find_binary_writer(sys.stderr)
- if writer is None:
- raise RuntimeError(
- "Was not able to determine binary stream for sys.stderr."
- )
- return writer
-
- def get_text_stdin(encoding=None, errors=None):
- rv = _get_windows_console_stream(sys.stdin, encoding, errors)
- if rv is not None:
- return rv
- return _force_correct_text_reader(
- sys.stdin, encoding, errors, force_readable=True
- )
- def get_text_stdout(encoding=None, errors=None):
- rv = _get_windows_console_stream(sys.stdout, encoding, errors)
- if rv is not None:
- return rv
- return _force_correct_text_writer(
- sys.stdout, encoding, errors, force_writable=True
- )
+def get_binary_stdin():
+ reader = _find_binary_reader(sys.stdin)
+ if reader is None:
+ raise RuntimeError("Was not able to determine binary stream for sys.stdin.")
+ return reader
- def get_text_stderr(encoding=None, errors=None):
- rv = _get_windows_console_stream(sys.stderr, encoding, errors)
- if rv is not None:
- return rv
- return _force_correct_text_writer(
- sys.stderr, encoding, errors, force_writable=True
- )
- def filename_to_ui(value):
- if isinstance(value, bytes):
- value = value.decode(get_filesystem_encoding(), "replace")
- else:
- value = value.encode("utf-8", "surrogateescape").decode("utf-8", "replace")
- return value
+def get_binary_stdout():
+ writer = _find_binary_writer(sys.stdout)
+ if writer is None:
+ raise RuntimeError("Was not able to determine binary stream for sys.stdout.")
+ return writer
+
+
+def get_binary_stderr():
+ writer = _find_binary_writer(sys.stderr)
+ if writer is None:
+ raise RuntimeError("Was not able to determine binary stream for sys.stderr.")
+ return writer
+
+
+def get_text_stdin(encoding=None, errors=None):
+ rv = _get_windows_console_stream(sys.stdin, encoding, errors)
+ if rv is not None:
+ return rv
+ return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True)
-def get_streerror(e, default=None):
+def get_text_stdout(encoding=None, errors=None):
+ rv = _get_windows_console_stream(sys.stdout, encoding, errors)
+ if rv is not None:
+ return rv
+ return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True)
+
+
+def get_text_stderr(encoding=None, errors=None):
+ rv = _get_windows_console_stream(sys.stderr, encoding, errors)
+ if rv is not None:
+ return rv
+ return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True)
+
+
+def filename_to_ui(value):
+ if isinstance(value, bytes):
+ value = value.decode(get_filesystem_encoding(), "replace")
+ else:
+ value = value.encode("utf-8", "surrogateescape").decode("utf-8", "replace")
+ return value
+
+
+def get_strerror(e, default=None):
if hasattr(e, "strerror"):
msg = e.strerror
else:
@@ -493,25 +357,11 @@ def get_streerror(e, default=None):
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)
+ """Handles not passing ``encoding`` and ``errors`` in binary mode."""
+ if "b" in mode:
+ return io.open(file, mode)
- f = io.open(file, "{}b".format(mode.replace("t", "")))
- return _make_text_stream(f, **kwargs)
+ return io.open(file, mode, encoding=encoding, errors=errors)
def open_stream(filename, mode="r", encoding=None, errors="strict", atomic=False):
@@ -587,15 +437,6 @@ def open_stream(filename, mode="r", encoding=None, errors="strict", atomic=False
return _AtomicFile(f, tmp_filename, os.path.realpath(filename)), True
-# Used in a destructor call, needs extra protection from interpreter cleanup.
-if hasattr(os, "replace"):
- _replace = os.replace
- _can_replace = True
-else:
- _replace = os.rename
- _can_replace = not WIN
-
-
class _AtomicFile(object):
def __init__(self, f, tmp_filename, real_filename):
self._f = f
@@ -611,12 +452,7 @@ class _AtomicFile(object):
if self.closed:
return
self._f.close()
- if not _can_replace:
- try:
- os.remove(self._real_filename)
- except OSError:
- pass
- _replace(self._tmp_filename, self._real_filename)
+ os.replace(self._tmp_filename, self._real_filename)
self.closed = True
def __getattr__(self, name):
@@ -632,11 +468,6 @@ class _AtomicFile(object):
return repr(self._f)
-auto_wrap_for_ansi = None
-colorama = None
-get_winterm_size = None
-
-
def strip_ansi(value):
return _ansi_re.sub("", value)
@@ -668,23 +499,13 @@ if WIN:
# Windows has a smaller terminal
DEFAULT_COLUMNS = 79
- from ._winconsole import _get_windows_console_stream, _wrap_std_stream
+ from ._winconsole import _get_windows_console_stream
def _get_argv_encoding():
import locale
return locale.getpreferredencoding()
- if PY2:
-
- def raw_input(prompt=""):
- sys.stderr.flush()
- if prompt:
- stdout = _default_text_stdout()
- stdout.write(prompt)
- stdin = _default_text_stdin()
- return stdin.readline().rstrip("\r\n")
-
try:
import colorama
except ImportError:
@@ -712,7 +533,7 @@ if WIN:
def _safe_write(s):
try:
return _write(s)
- except:
+ except BaseException:
ansi_wrapper.reset_all()
raise
@@ -735,8 +556,8 @@ else:
def _get_argv_encoding():
return getattr(sys.stdin, "encoding", None) or get_filesystem_encoding()
- _get_windows_console_stream = lambda *x: None
- _wrap_std_stream = lambda *x: None
+ def _get_windows_console_stream(f, encoding, errors):
+ return None
def term_len(x):
diff --git a/src/click/_termui_impl.py b/src/click/_termui_impl.py
index cdc6fab..1a6adf1 100644
--- a/src/click/_termui_impl.py
+++ b/src/click/_termui_impl.py
@@ -7,17 +7,15 @@ placed in this module and only imported as needed.
import contextlib
import math
import os
+import shlex
import sys
import time
from ._compat import _default_text_stdout
from ._compat import CYGWIN
from ._compat import get_best_encoding
-from ._compat import int_types
from ._compat import isatty
from ._compat import open_stream
-from ._compat import range_type
-from ._compat import shlex_quote
from ._compat import strip_ansi
from ._compat import term_len
from ._compat import WIN
@@ -45,7 +43,7 @@ def _length_hint(obj):
hint = get_hint(obj)
except TypeError:
return None
- if hint is NotImplemented or not isinstance(hint, int_types) or hint < 0:
+ if hint is NotImplemented or not isinstance(hint, int) or hint < 0:
return None
return hint
@@ -89,7 +87,7 @@ class ProgressBar(object):
if iterable is None:
if length is None:
raise TypeError("iterable or length is required")
- iterable = range_type(length)
+ iterable = range(length)
self.iter = iter(iterable)
self.length = length
self.length_known = length is not None
@@ -361,7 +359,7 @@ def pager(generator, color=None):
try:
if (
hasattr(os, "system")
- and os.system("more {}".format(shlex_quote(filename))) == 0
+ and os.system("more {}".format(shlex.quote(filename))) == 0
):
return _pipepager(generator, "more", color)
return _nullpager(stdout, generator, color)
@@ -431,7 +429,7 @@ def _tempfilepager(generator, cmd, color):
with open_stream(filename, "wb")[0] as f:
f.write(text.encode(encoding))
try:
- os.system("{} {}".format(shlex_quote(cmd), shlex_quote(filename)))
+ os.system("{} {}".format(shlex.quote(cmd), shlex.quote(filename)))
finally:
os.unlink(filename)
@@ -476,7 +474,7 @@ class Editor(object):
environ = None
try:
c = subprocess.Popen(
- "{} {}".format(shlex_quote(editor), shlex_quote(filename)),
+ "{} {}".format(shlex.quote(editor), shlex.quote(filename)),
env=environ,
shell=True,
)
@@ -553,16 +551,16 @@ def open_url(url, wait=False, locate=False):
elif WIN:
if locate:
url = _unquote_file(url)
- args = "explorer /select,{}".format(shlex_quote(url))
+ args = "explorer /select,{}".format(shlex.quote(url))
else:
- args = 'start {} "" {}'.format("/WAIT" if wait else "", shlex_quote(url))
+ args = 'start {} "" {}'.format("/WAIT" if wait else "", shlex.quote(url))
return os.system(args)
elif CYGWIN:
if locate:
url = _unquote_file(url)
- args = "cygstart {}".format(shlex_quote(os.path.dirname(url)))
+ args = "cygstart {}".format(shlex.quote(os.path.dirname(url)))
else:
- args = "cygstart {} {}".format("-w" if wait else "", shlex_quote(url))
+ args = "cygstart {} {}".format("-w" if wait else "", shlex.quote(url))
return os.system(args)
try:
diff --git a/src/click/_unicodefun.py b/src/click/_unicodefun.py
index 781c365..57545e0 100644
--- a/src/click/_unicodefun.py
+++ b/src/click/_unicodefun.py
@@ -1,58 +1,9 @@
import codecs
import os
-import sys
-
-from ._compat import PY2
-
-
-def _find_unicode_literals_frame():
- import __future__
-
- if not hasattr(sys, "_getframe"): # not all Python implementations have it
- return 0
- frm = sys._getframe(1)
- idx = 1
- while frm is not None:
- if frm.f_globals.get("__name__", "").startswith("click."):
- frm = frm.f_back
- idx += 1
- elif frm.f_code.co_flags & __future__.unicode_literals.compiler_flag:
- return idx
- else:
- break
- return 0
-
-
-def _check_for_unicode_literals():
- if not __debug__:
- return
-
- from . import disable_unicode_literals_warning
-
- if not PY2 or disable_unicode_literals_warning:
- return
- bad_frame = _find_unicode_literals_frame()
- if bad_frame <= 0:
- return
- from warnings import warn
-
- warn(
- Warning(
- "Click detected the use of the unicode_literals __future__"
- " import. This is heavily discouraged because it can"
- " introduce subtle bugs in your code. You should instead"
- ' use explicit u"" literals for your unicode strings. For'
- " more information see"
- " https://click.palletsprojects.com/python3/"
- ),
- stacklevel=bad_frame,
- )
def _verify_python3_env():
"""Ensures that the environment is good for unicode on Python 3."""
- if PY2:
- return
try:
import locale
diff --git a/src/click/_winconsole.py b/src/click/_winconsole.py
index cae8ded..18310ad 100644
--- a/src/click/_winconsole.py
+++ b/src/click/_winconsole.py
@@ -9,10 +9,7 @@
# echo and prompt.
import ctypes
import io
-import os
-import sys
import time
-import zlib
from ctypes import byref
from ctypes import c_char
from ctypes import c_char_p
@@ -23,7 +20,6 @@ from ctypes import c_void_p
from ctypes import POINTER
from ctypes import py_object
from ctypes import windll
-from ctypes import WinError
from ctypes import WINFUNCTYPE
from ctypes.wintypes import DWORD
from ctypes.wintypes import HANDLE
@@ -33,8 +29,6 @@ from ctypes.wintypes import LPWSTR
import msvcrt
from ._compat import _NonClosingTextIOWrapper
-from ._compat import PY2
-from ._compat import text_type
try:
from ctypes import pythonapi
@@ -97,9 +91,6 @@ class Py_buffer(ctypes.Structure):
("internal", c_void_p),
]
- if PY2:
- _fields_.insert(-1, ("smalltable", c_ssize_t * 2))
-
# On PyPy we cannot get buffers so our ability to operate here is
# severely limited.
@@ -204,7 +195,7 @@ class ConsoleStream(object):
return self.buffer.name
def write(self, x):
- if isinstance(x, text_type):
+ if isinstance(x, str):
return self._text_stream.write(x)
try:
self.flush()
@@ -253,20 +244,6 @@ class WindowsChunkedWriter(object):
written += to_write
-_wrapped_std_streams = set()
-
-
-def _wrap_std_stream(name):
- # Python 2 & Windows 7 and below
- if (
- PY2
- and sys.getwindowsversion()[:2] <= (6, 1)
- and name not in _wrapped_std_streams
- ):
- setattr(sys, name, WindowsChunkedWriter(getattr(sys, name)))
- _wrapped_std_streams.add(name)
-
-
def _get_text_stdin(buffer_stream):
text_stream = _NonClosingTextIOWrapper(
io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)),
@@ -297,37 +274,6 @@ def _get_text_stderr(buffer_stream):
return ConsoleStream(text_stream, buffer_stream)
-if PY2:
-
- def _hash_py_argv():
- return zlib.crc32("\x00".join(sys.argv[1:]))
-
- _initial_argv_hash = _hash_py_argv()
-
- 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
-
- if not hasattr(sys, "frozen"):
- argv = argv[1:]
- while len(argv) > 0:
- arg = argv[0]
- if not arg.startswith("-") or arg == "-":
- break
- argv = argv[1:]
- if arg.startswith(("-c", "-m")):
- break
-
- return argv[1:]
-
-
_stream_factories = {
0: _get_text_stdin,
1: _get_text_stdout,
@@ -351,20 +297,15 @@ def _is_console(f):
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 encoding in {"utf-16-le", None}
+ and errors in {"strict", None}
and _is_console(f)
):
func = _stream_factories.get(f.fileno())
if func is not None:
- if not PY2:
- f = getattr(f, "buffer", None)
- if f is None:
- return None
- else:
- # If we are on Python 2 we need to set the stream that we
- # deal with to binary mode as otherwise the exercise if a
- # bit moot. The same problems apply as for
- # get_binary_stdin and friends from _compat.
- msvcrt.setmode(f.fileno(), os.O_BINARY)
+ f = getattr(f, "buffer", None)
+
+ if f is None:
+ return None
+
return func(f)
diff --git a/src/click/core.py b/src/click/core.py
index 5e8bf6c..1f88902 100644
--- a/src/click/core.py
+++ b/src/click/core.py
@@ -6,11 +6,6 @@ from contextlib import contextmanager
from functools import update_wrapper
from itertools import repeat
-from ._compat import isidentifier
-from ._compat import iteritems
-from ._compat import PY2
-from ._compat import string_types
-from ._unicodefun import _check_for_unicode_literals
from ._unicodefun import _verify_python3_env
from .exceptions import Abort
from .exceptions import BadParameter
@@ -31,7 +26,6 @@ from .types import BOOL
from .types import convert_type
from .types import IntRange
from .utils import echo
-from .utils import get_os_args
from .utils import make_default_short_help
from .utils import make_str
from .utils import PacifyFlushWrapper
@@ -736,7 +730,7 @@ class BaseCommand(object):
:param extra: extra keyword arguments forwarded to the context
constructor.
"""
- for key, value in iteritems(self.context_settings):
+ for key, value in self.context_settings.items():
if key not in extra:
extra[key] = value
ctx = Context(self, info_name=info_name, parent=parent, **extra)
@@ -797,16 +791,12 @@ class BaseCommand(object):
:param extra: extra keyword arguments are forwarded to the context
constructor. See :class:`Context` for more information.
"""
- # If we are in Python 3, we will verify that the environment is
- # sane at this point or reject further execution to avoid a
- # broken script.
- if not PY2:
- _verify_python3_env()
- else:
- _check_for_unicode_literals()
+ # Verify that the environment is configured correctly, or reject
+ # further execution to avoid a broken script.
+ _verify_python3_env()
if args is None:
- args = get_os_args()
+ args = sys.argv[1:]
else:
args = list(args)
@@ -1841,7 +1831,7 @@ class Option(Parameter):
possible_names = []
for decl in decls:
- if isidentifier(decl):
+ if decl.isidentifier():
if name is not None:
raise TypeError("Name defined twice")
name = decl
@@ -1863,7 +1853,7 @@ class Option(Parameter):
if name is None and possible_names:
possible_names.sort(key=lambda x: -len(x[0])) # group long options first
name = possible_names[0][1].replace("-", "_").lower()
- if not isidentifier(name):
+ if not name.isidentifier():
name = None
if name is None:
@@ -1942,7 +1932,7 @@ class Option(Parameter):
)
)
if self.default is not None and (self.show_default or ctx.show_default):
- if isinstance(self.show_default, string_types):
+ if isinstance(self.show_default, str):
default_string = "({})".format(self.show_default)
elif isinstance(self.default, (list, tuple)):
default_string = ", ".join(str(d) for d in self.default)
diff --git a/src/click/decorators.py b/src/click/decorators.py
index c7b5af6..e0596c8 100644
--- a/src/click/decorators.py
+++ b/src/click/decorators.py
@@ -2,8 +2,6 @@ import inspect
import sys
from functools import update_wrapper
-from ._compat import iteritems
-from ._unicodefun import _check_for_unicode_literals
from .core import Argument
from .core import Command
from .core import Group
@@ -94,7 +92,6 @@ def _make_command(f, name, attrs, cls):
else:
help = inspect.cleandoc(help)
attrs["help"] = help
- _check_for_unicode_literals()
return cls(
name=name or f.__name__.lower().replace("_", "-"),
callback=f,
@@ -287,7 +284,7 @@ def version_option(version=None, *param_decls, **attrs):
else:
for dist in pkg_resources.working_set:
scripts = dist.get_entry_map().get("console_scripts") or {}
- for _, entry_point in iteritems(scripts):
+ for entry_point in scripts.values():
if entry_point.module_name == module:
ver = dist.version
break
diff --git a/src/click/exceptions.py b/src/click/exceptions.py
index 592ee38..f75f4db 100644
--- a/src/click/exceptions.py
+++ b/src/click/exceptions.py
@@ -1,6 +1,5 @@
from ._compat import filename_to_ui
from ._compat import get_text_stderr
-from ._compat import PY2
from .utils import echo
@@ -13,15 +12,11 @@ def _join_param_hints(param_hint):
class ClickException(Exception):
"""An exception that Click can handle and show to the user."""
- #: The exit code for this exception
+ #: The exit code for this exception.
exit_code = 1
def __init__(self, message):
- ctor_msg = message
- if PY2:
- if ctor_msg is not None:
- ctor_msg = ctor_msg.encode("utf-8")
- Exception.__init__(self, ctor_msg)
+ super().__init__(message)
self.message = message
def format_message(self):
@@ -30,12 +25,6 @@ class ClickException(Exception):
def __str__(self):
return self.message
- if PY2:
- __unicode__ = __str__
-
- def __str__(self):
- return self.message.encode("utf-8")
-
def show(self, file=None):
if file is None:
file = get_text_stderr()
@@ -162,12 +151,6 @@ class MissingParameter(BadParameter):
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/src/click/termui.py b/src/click/termui.py
index 7f29eb6..73f35f5 100644
--- a/src/click/termui.py
+++ b/src/click/termui.py
@@ -8,10 +8,7 @@ import sys
from ._compat import DEFAULT_COLUMNS
from ._compat import get_winterm_size
from ._compat import isatty
-from ._compat import raw_input
-from ._compat import string_types
from ._compat import strip_ansi
-from ._compat import text_type
from ._compat import WIN
from .exceptions import Abort
from .exceptions import UsageError
@@ -24,7 +21,7 @@ from .utils import LazyFile
# The prompt functions to use. The doc tools currently override these
# functions to customize how they work.
-visible_prompt_func = raw_input
+visible_prompt_func = input
_ansi_colors = {
"black": 30,
@@ -278,13 +275,13 @@ def echo_via_pager(text_or_generator, color=None):
if inspect.isgeneratorfunction(text_or_generator):
i = text_or_generator()
- elif isinstance(text_or_generator, string_types):
+ elif isinstance(text_or_generator, str):
i = [text_or_generator]
else:
i = iter(text_or_generator)
# convert every element of i to a text type if necessary
- text_generator = (el if isinstance(el, string_types) else text_type(el) for el in i)
+ text_generator = (el if isinstance(el, str) else str(el) for el in i)
from ._termui_impl import pager
diff --git a/src/click/testing.py b/src/click/testing.py
index a3dba3b..9c3c012 100644
--- a/src/click/testing.py
+++ b/src/click/testing.py
@@ -1,4 +1,5 @@
import contextlib
+import io
import os
import shlex
import shutil
@@ -8,16 +9,7 @@ import tempfile
from . import formatting
from . import termui
from . import utils
-from ._compat import iteritems
-from ._compat import PY2
-from ._compat import string_types
-
-
-if PY2:
- from cStringIO import StringIO
-else:
- import io
- from ._compat import _find_binary_reader
+from ._compat import _find_binary_reader
class EchoingStdin(object):
@@ -51,19 +43,18 @@ class EchoingStdin(object):
def make_input_stream(input, charset):
# Is already an input stream.
if hasattr(input, "read"):
- if PY2:
- return input
rv = _find_binary_reader(input)
+
if rv is not None:
return rv
+
raise TypeError("Could not find binary reader for input stream.")
if input is None:
input = b""
elif not isinstance(input, bytes):
input = input.encode(charset)
- if PY2:
- return StringIO(input)
+
return io.BytesIO(input)
@@ -184,23 +175,17 @@ class CliRunner(object):
env = self.make_env(env)
- if PY2:
- bytes_output = StringIO()
- if self.echo_stdin:
- input = EchoingStdin(input, bytes_output)
- sys.stdout = bytes_output
- if not self.mix_stderr:
- bytes_error = StringIO()
- sys.stderr = bytes_error
- else:
- bytes_output = io.BytesIO()
- if self.echo_stdin:
- input = EchoingStdin(input, bytes_output)
- input = io.TextIOWrapper(input, encoding=self.charset)
- sys.stdout = io.TextIOWrapper(bytes_output, encoding=self.charset)
- if not self.mix_stderr:
- bytes_error = io.BytesIO()
- sys.stderr = io.TextIOWrapper(bytes_error, encoding=self.charset)
+ bytes_output = io.BytesIO()
+
+ if self.echo_stdin:
+ input = EchoingStdin(input, bytes_output)
+
+ input = io.TextIOWrapper(input, encoding=self.charset)
+ sys.stdout = io.TextIOWrapper(bytes_output, encoding=self.charset)
+
+ if not self.mix_stderr:
+ bytes_error = io.BytesIO()
+ sys.stderr = io.TextIOWrapper(bytes_error, encoding=self.charset)
if self.mix_stderr:
sys.stderr = sys.stdout
@@ -244,7 +229,7 @@ class CliRunner(object):
old_env = {}
try:
- for key, value in iteritems(env):
+ for key, value in env.items():
old_env[key] = os.environ.get(key)
if value is None:
try:
@@ -255,7 +240,7 @@ class CliRunner(object):
os.environ[key] = value
yield (bytes_output, not self.mix_stderr and bytes_error)
finally:
- for key, value in iteritems(old_env):
+ for key, value in old_env.items():
if value is None:
try:
del os.environ[key]
@@ -317,7 +302,7 @@ class CliRunner(object):
exception = None
exit_code = 0
- if isinstance(args, string_types):
+ if isinstance(args, str):
args = shlex.split(args)
try:
diff --git a/src/click/types.py b/src/click/types.py
index 505c39f..5647df5 100644
--- a/src/click/types.py
+++ b/src/click/types.py
@@ -5,10 +5,8 @@ from datetime import datetime
from ._compat import _get_argv_encoding
from ._compat import filename_to_ui
from ._compat import get_filesystem_encoding
-from ._compat import get_streerror
+from ._compat import get_strerror
from ._compat import open_stream
-from ._compat import PY2
-from ._compat import text_type
from .exceptions import BadParameter
from .utils import LazyFile
from .utils import safecall
@@ -94,9 +92,10 @@ class FuncParamType(ParamType):
return self.func(value)
except ValueError:
try:
- value = text_type(value)
+ value = str(value)
except UnicodeError:
- value = str(value).decode("utf-8", "replace")
+ value = value.decode("utf-8", "replace")
+
self.fail(value, param, ctx)
@@ -179,14 +178,9 @@ class Choice(ParamType):
}
if not self.case_sensitive:
- if PY2:
- lower = str.lower
- else:
- lower = str.casefold
-
- normed_value = lower(normed_value)
+ normed_value = normed_value.casefold()
normed_choices = {
- lower(normed_choice): original
+ normed_choice.casefold(): original
for normed_choice, original in normed_choices.items()
}
@@ -427,8 +421,6 @@ class UUIDParameterType(ParamType):
import uuid
try:
- if PY2 and isinstance(value, text_type):
- value = value.encode("ascii")
return uuid.UUID(value)
except ValueError:
self.fail("{} is not a valid UUID value".format(value), param, ctx)
@@ -517,7 +509,7 @@ class File(ParamType):
except (IOError, OSError) as e: # noqa: B014
self.fail(
"Could not open file: {}: {}".format(
- filename_to_ui(value), get_streerror(e)
+ filename_to_ui(value), get_strerror(e)
),
param,
ctx,
@@ -589,7 +581,7 @@ class Path(ParamType):
def coerce_path_result(self, rv):
if self.type is not None and not isinstance(rv, self.type):
- if self.type is text_type:
+ if self.type is str:
rv = rv.decode(get_filesystem_encoding())
else:
rv = rv.encode(get_filesystem_encoding())
@@ -701,7 +693,7 @@ def convert_type(ty, default=None):
return Tuple(ty)
if isinstance(ty, ParamType):
return ty
- if ty is text_type or ty is str or ty is None:
+ if ty is str or ty is None:
return STRING
if ty is int:
return INT
diff --git a/src/click/utils.py b/src/click/utils.py
index 79265e7..f5aac49 100644
--- a/src/click/utils.py
+++ b/src/click/utils.py
@@ -3,30 +3,22 @@ import sys
from ._compat import _default_text_stderr
from ._compat import _default_text_stdout
+from ._compat import _find_binary_writer
from ._compat import auto_wrap_for_ansi
from ._compat import binary_streams
from ._compat import filename_to_ui
from ._compat import get_filesystem_encoding
-from ._compat import get_streerror
+from ._compat import get_strerror
from ._compat import is_bytes
from ._compat import open_stream
-from ._compat import PY2
from ._compat import should_strip_ansi
-from ._compat import string_types
from ._compat import strip_ansi
from ._compat import text_streams
-from ._compat import text_type
from ._compat import WIN
from .globals import resolve_color_default
-if not PY2:
- from ._compat import _find_binary_writer
-elif WIN:
- from ._winconsole import _get_windows_argv
- from ._winconsole import _hash_py_argv
- from ._winconsole import _initial_argv_hash
-echo_native_types = string_types + (bytes, bytearray)
+echo_native_types = (str, bytes, bytearray)
def _posixify(name):
@@ -52,7 +44,7 @@ def make_str(value):
return value.decode(get_filesystem_encoding())
except UnicodeError:
return value.decode("utf-8", "replace")
- return text_type(value)
+ return str(value)
def make_default_short_help(help, max_length=45):
@@ -129,7 +121,7 @@ class LazyFile(object):
except (IOError, OSError) as e: # noqa: E402
from .exceptions import FileError
- raise FileError(self.name, hint=get_streerror(e))
+ raise FileError(self.name, hint=get_strerror(e))
self._f = rv
return rv
@@ -231,11 +223,11 @@ def echo(message=None, file=None, nl=True, err=False, color=None):
# Convert non bytes/text into the native string type.
if message is not None and not isinstance(message, echo_native_types):
- message = text_type(message)
+ message = str(message)
if nl:
message = message or u""
- if isinstance(message, text_type):
+ if isinstance(message, str):
message += u"\n"
else:
message += b"\n"
@@ -245,7 +237,7 @@ def echo(message=None, file=None, nl=True, err=False, color=None):
# message in there. This is done separately so that most stream
# types will work as you would expect. Eg: you can write to StringIO
# for other cases.
- if message and not PY2 and is_bytes(message):
+ if message and is_bytes(message):
binary_file = _find_binary_writer(file)
if binary_file is not None:
file.flush()
@@ -340,23 +332,21 @@ def open_file(
def get_os_args():
- """This returns the argument part of sys.argv in the most appropriate
- form for processing. What this means is that this return value is in
- a format that works for Click to process but does not necessarily
- correspond well to what's actually standard for the interpreter.
-
- On most environments the return value is ``sys.argv[:1]`` unchanged.
- However if you are on Windows and running Python 2 the return value
- will actually be a list of unicode strings instead because the
- default behavior on that platform otherwise will not be able to
- carry all possible values that sys.argv can have.
-
- .. versionadded:: 6.0
+ """Returns the argument part of ``sys.argv``, removing the first
+ value which is the name of the script.
+
+ .. deprecated:: 8.0
+ Will be removed in 8.1. Access ``sys.argv[1:]`` directly
+ instead.
"""
- # We can only extract the unicode argv if sys.argv has not been
- # changed since the startup of the application.
- if PY2 and WIN and _initial_argv_hash == _hash_py_argv():
- return _get_windows_argv()
+ import warnings
+
+ warnings.warn(
+ "'get_os_args' is deprecated and will be removed in 8.1. Access"
+ " 'sys.argv[1:]' directly instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
return sys.argv[1:]
diff --git a/tests/test_arguments.py b/tests/test_arguments.py
index 0b510c0..bb580fc 100644
--- a/tests/test_arguments.py
+++ b/tests/test_arguments.py
@@ -4,8 +4,6 @@ import sys
import pytest
import click
-from click._compat import PY2
-from click._compat import text_type
def test_nargs_star(runner):
@@ -83,18 +81,13 @@ def test_bytes_args(runner, monkeypatch):
@click.argument("arg")
def from_bytes(arg):
assert isinstance(
- arg, text_type
+ arg, str
), "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")
+ 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,
@@ -268,7 +261,7 @@ def test_nargs_star_ordering(runner):
click.echo(arg)
result = runner.invoke(cmd, ["a", "b", "c"])
- assert result.output.splitlines() == ["(u'a',)" if PY2 else "('a',)", "b", "c"]
+ assert result.output.splitlines() == ["('a',)", "b", "c"]
def test_nargs_specified_plus_star_ordering(runner):
@@ -281,11 +274,7 @@ def test_nargs_specified_plus_star_ordering(runner):
click.echo(arg)
result = runner.invoke(cmd, ["a", "b", "c", "d", "e", "f"])
- assert result.output.splitlines() == [
- "(u'a', u'b', u'c')" if PY2 else "('a', 'b', 'c')",
- "d",
- "(u'e', u'f')" if PY2 else "('e', 'f')",
- ]
+ assert result.output.splitlines() == ["('a', 'b', 'c')", "d", "('e', 'f')"]
def test_defaults_for_nargs(runner):
diff --git a/tests/test_options.py b/tests/test_options.py
index 4baa374..3eea5e6 100644
--- a/tests/test_options.py
+++ b/tests/test_options.py
@@ -5,7 +5,6 @@ import re
import pytest
import click
-from click._compat import text_type
def test_prefixes(runner):
@@ -170,11 +169,11 @@ def test_multiple_default_type(runner):
@click.option("--arg1", multiple=True, default=("foo", "bar"))
@click.option("--arg2", multiple=True, default=(1, "a"))
def cmd(arg1, arg2):
- assert all(isinstance(e[0], text_type) for e in arg1)
- assert all(isinstance(e[1], text_type) for e in arg1)
+ assert all(isinstance(e[0], str) for e in arg1)
+ assert all(isinstance(e[1], str) for e in arg1)
assert all(isinstance(e[0], int) for e in arg2)
- assert all(isinstance(e[1], text_type) for e in arg2)
+ assert all(isinstance(e[1], str) for e in arg2)
result = runner.invoke(
cmd, "--arg1 a b --arg1 test 1 --arg2 2 two --arg2 4 four".split()
diff --git a/tests/test_testing.py b/tests/test_testing.py
index 22a285d..99701b5 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -1,19 +1,13 @@
import os
import sys
+from io import BytesIO
import pytest
import click
-from click._compat import PY2
from click._compat import WIN
from click.testing import CliRunner
-# Use the most reasonable io that users would use for the python version.
-if PY2:
- from cStringIO import StringIO as ReasonableBytesIO
-else:
- from io import BytesIO as ReasonableBytesIO
-
def test_runner():
@click.command()
@@ -51,12 +45,12 @@ def test_runner_with_stream():
o.flush()
runner = CliRunner()
- result = runner.invoke(test, input=ReasonableBytesIO(b"Hello World!\n"))
+ result = runner.invoke(test, input=BytesIO(b"Hello World!\n"))
assert not result.exception
assert result.output == "Hello World!\n"
runner = CliRunner(echo_stdin=True)
- result = runner.invoke(test, input=ReasonableBytesIO(b"Hello World!\n"))
+ result = runner.invoke(test, input=BytesIO(b"Hello World!\n"))
assert not result.exception
assert result.output == "Hello World!\nHello World!\n"