remove _compat module

This commit is contained in:
David Lord 2020-04-03 18:33:40 -07:00
parent 1263d3bd14
commit 662c245795
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
20 changed files with 68 additions and 274 deletions

View file

@ -1,115 +0,0 @@
# -*- coding: utf-8 -*-
"""
flask._compat
~~~~~~~~~~~~~
Some py2/py3 compatibility support based on a stripped down
version of six so we don't have to depend on a specific version
of it.
:copyright: 2010 Pallets
:license: BSD-3-Clause
"""
import sys
PY2 = sys.version_info[0] == 2
_identity = lambda x: x
try: # Python 2
text_type = unicode
string_types = (str, unicode)
integer_types = (int, long)
except NameError: # Python 3
text_type = str
string_types = (str,)
integer_types = (int,)
if not PY2:
iterkeys = lambda d: iter(d.keys())
itervalues = lambda d: iter(d.values())
iteritems = lambda d: iter(d.items())
from inspect import getfullargspec as getargspec
from io import StringIO
import collections.abc as collections_abc
def reraise(tp, value, tb=None):
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
implements_to_string = _identity
else:
iterkeys = lambda d: d.iterkeys()
itervalues = lambda d: d.itervalues()
iteritems = lambda d: d.iteritems()
from inspect import getargspec
from cStringIO import StringIO
import collections as collections_abc
exec("def reraise(tp, value, tb=None):\n raise tp, value, tb")
def implements_to_string(cls):
cls.__unicode__ = cls.__str__
cls.__str__ = lambda x: x.__unicode__().encode("utf-8")
return cls
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a
# dummy metaclass for one level of class instantiation that replaces
# itself with the actual metaclass.
class metaclass(type):
def __new__(metacls, name, this_bases, d):
return meta(name, bases, d)
return type.__new__(metaclass, "temporary_class", (), {})
# Certain versions of pypy have a bug where clearing the exception stack
# breaks the __exit__ function in a very peculiar way. The second level of
# exception blocks is necessary because pypy seems to forget to check if an
# exception happened until the next bytecode instruction?
#
# Relevant PyPy bugfix commit:
# https://bitbucket.org/pypy/pypy/commits/77ecf91c635a287e88e60d8ddb0f4e9df4003301
# According to ronan on #pypy IRC, it is released in PyPy2 2.3 and later
# versions.
#
# Ubuntu 14.04 has PyPy 2.2.1, which does exhibit this bug.
BROKEN_PYPY_CTXMGR_EXIT = False
if hasattr(sys, "pypy_version_info"):
class _Mgr(object):
def __enter__(self):
return self
def __exit__(self, *args):
if hasattr(sys, "exc_clear"):
# Python 3 (PyPy3) doesn't have exc_clear
sys.exc_clear()
try:
try:
with _Mgr():
raise AssertionError()
except: # noqa: B001
# We intentionally use a bare except here. See the comment above
# regarding a pypy bug as to why.
raise
except TypeError:
BROKEN_PYPY_CTXMGR_EXIT = True
except AssertionError:
pass
try:
from os import fspath
except ImportError:
# Backwards compatibility as proposed in PEP 0519:
# https://www.python.org/dev/peps/pep-0519/#backwards-compatibility
def fspath(path):
return path.__fspath__() if hasattr(path, "__fspath__") else path

View file

@ -31,10 +31,6 @@ from werkzeug.wrappers import BaseResponse
from . import cli
from . import json
from ._compat import integer_types
from ._compat import reraise
from ._compat import string_types
from ._compat import text_type
from .config import Config
from .config import ConfigAttribute
from .ctx import _AppCtxGlobals
@ -1179,10 +1175,10 @@ class Flask(_PackageBoundObject):
# a tuple of only ``GET`` as default.
if methods is None:
methods = getattr(view_func, "methods", None) or ("GET",)
if isinstance(methods, string_types):
if isinstance(methods, str):
raise TypeError(
"Allowed methods have to be iterables of strings, "
'for example: @app.route(..., methods=["POST"])'
"Allowed methods must be a list of strings, for"
' example: @app.route(..., methods=["POST"])'
)
methods = set(item.upper() for item in methods)
@ -1278,7 +1274,7 @@ class Flask(_PackageBoundObject):
:param exc_class_or_code: Any exception class, or an HTTP status
code as an integer.
"""
if isinstance(exc_class_or_code, integer_types):
if isinstance(exc_class_or_code, int):
exc_class = default_exceptions[exc_class_or_code]
else:
exc_class = exc_class_or_code
@ -1727,13 +1723,6 @@ class Flask(_PackageBoundObject):
.. versionadded:: 0.7
"""
exc_type, exc_value, tb = sys.exc_info()
assert exc_value is e
# ensure not to trash sys.exc_info() at that point in case someone
# wants the traceback preserved in handle_http_exception. Of course
# we cannot prevent users from trashing it themselves in a custom
# trap_http_exception method so that's their fault then.
if isinstance(e, BadRequestKeyError):
if self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"]:
e.show_exception = True
@ -1752,7 +1741,8 @@ class Flask(_PackageBoundObject):
handler = self._find_error_handler(e)
if handler is None:
reraise(exc_type, exc_value, tb)
raise
return handler(e)
def handle_exception(self, e):
@ -1789,20 +1779,18 @@ class Flask(_PackageBoundObject):
.. versionadded:: 0.3
"""
exc_type, exc_value, tb = sys.exc_info()
exc_info = sys.exc_info()
got_request_exception.send(self, exception=e)
if self.propagate_exceptions:
# if we want to repropagate the exception, we can attempt to
# raise it with the whole traceback in case we can do that
# (the function was actually called from the except part)
# otherwise, we just raise the error again
if exc_value is e:
reraise(exc_type, exc_value, tb)
else:
raise e
# Re-raise if called with an active exception, otherwise
# raise the passed in exception.
if exc_info[1] is e:
raise
self.log_exception((exc_type, exc_value, tb))
raise e
self.log_exception(exc_info)
server_error = InternalServerError()
# TODO: pass as param when Werkzeug>=1.0.0 is required
# TODO: also remove note about this from docstring and docs
@ -2026,7 +2014,7 @@ class Flask(_PackageBoundObject):
# make sure the body is an instance of the response class
if not isinstance(rv, self.response_class):
if isinstance(rv, (text_type, bytes, bytearray)):
if isinstance(rv, (str, bytes, bytearray)):
# let the response class set the status and headers instead of
# waiting to do it manually, so that the class can handle any
# special logic
@ -2040,13 +2028,12 @@ class Flask(_PackageBoundObject):
try:
rv = self.response_class.force_type(rv, request.environ)
except TypeError as e:
new_error = TypeError(
raise TypeError(
"{e}\nThe view function did not return a valid"
" response. The return type must be a string, dict, tuple,"
" Response instance, or WSGI callable, but it was a"
" {rv.__class__.__name__}.".format(e=e, rv=rv)
)
reraise(TypeError, new_error, sys.exc_info()[2])
).with_traceback(sys.exc_info()[2])
else:
raise TypeError(
"The view function did not return a valid"
@ -2057,7 +2044,7 @@ class Flask(_PackageBoundObject):
# prefer the status if it was provided
if status is not None:
if isinstance(status, (text_type, bytes, bytearray)):
if isinstance(status, (str, bytes, bytearray)):
rv.status = status
else:
rv.status_code = status
@ -2121,23 +2108,24 @@ class Flask(_PackageBoundObject):
func(endpoint, values)
def handle_url_build_error(self, error, endpoint, values):
"""Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`.
"""Handle :class:`~werkzeug.routing.BuildError` on
:meth:`url_for`.
"""
exc_type, exc_value, tb = sys.exc_info()
for handler in self.url_build_error_handlers:
try:
rv = handler(error, endpoint, values)
except BuildError as e:
# make error available outside except block
error = e
else:
if rv is not None:
return rv
except BuildError as e:
# make error available outside except block (py3)
error = e
# At this point we want to reraise the exception. If the error is
# still the same one we can reraise it with the original traceback,
# otherwise we raise it from here.
if error is exc_value:
reraise(exc_type, exc_value, tb)
# Re-raise if called with an active exception, otherwise raise
# the passed in exception.
if error is sys.exc_info()[1]:
raise
raise error
def preprocess_request(self):

View file

@ -25,10 +25,6 @@ from threading import Thread
import click
from werkzeug.utils import import_string
from ._compat import getargspec
from ._compat import itervalues
from ._compat import reraise
from ._compat import text_type
from .globals import current_app
from .helpers import get_debug_flag
from .helpers import get_env
@ -63,7 +59,7 @@ def find_best_app(script_info, module):
return app
# Otherwise find the only object that is a Flask instance.
matches = [v for v in itervalues(module.__dict__) if isinstance(v, Flask)]
matches = [v for v in module.__dict__.values() if isinstance(v, Flask)]
if len(matches) == 1:
return matches[0]
@ -105,7 +101,7 @@ def call_factory(script_info, app_factory, arguments=()):
of arguments. Checks for the existence of a script_info argument and calls
the app_factory depending on that and the arguments provided.
"""
args_spec = getargspec(app_factory)
args_spec = inspect.getfullargspec(app_factory)
arg_names = args_spec.args
arg_defaults = args_spec.defaults
@ -241,7 +237,7 @@ def locate_app(script_info, module_name, app_name, raise_if_not_found=True):
except ImportError:
# Reraise the ImportError if it occurred within the imported module.
# Determine this by checking whether the trace has a depth > 1.
if sys.exc_info()[-1].tb_next:
if sys.exc_info()[2].tb_next:
raise NoAppException(
'While importing "{name}", an ImportError was raised:'
"\n\n{tb}".format(name=module_name, tb=traceback.format_exc())
@ -327,7 +323,7 @@ class DispatchingApp(object):
exc_info = self._bg_loading_exc_info
if exc_info is not None:
self._bg_loading_exc_info = None
reraise(*exc_info)
raise exc_info
def _load_unlocked(self):
__traceback_hide__ = True # noqa: F841
@ -741,11 +737,7 @@ def _validate_key(ctx, param, value):
"""
cert = ctx.params.get("cert")
is_adhoc = cert == "adhoc"
if sys.version_info < (2, 7, 9):
is_context = cert and not isinstance(cert, (text_type, bytes))
else:
is_context = ssl and isinstance(cert, ssl.SSLContext)
is_context = ssl and isinstance(cert, ssl.SSLContext)
if value is not None:
if is_adhoc:

View file

@ -14,9 +14,6 @@ import types
from werkzeug.utils import import_string
from ._compat import iteritems
from ._compat import string_types
class ConfigAttribute(object):
"""Makes an attribute forward to the config"""
@ -169,7 +166,7 @@ class Config(dict):
:param obj: an import name or object
"""
if isinstance(obj, string_types):
if isinstance(obj, str):
obj = import_string(obj)
for key in dir(obj):
if key.isupper():
@ -261,7 +258,7 @@ class Config(dict):
.. versionadded:: 0.11
"""
rv = {}
for k, v in iteritems(self):
for k, v in self.items():
if not k.startswith(namespace):
continue
if trim_namespace:

View file

@ -13,8 +13,6 @@ from functools import update_wrapper
from werkzeug.exceptions import HTTPException
from ._compat import BROKEN_PYPY_CTXMGR_EXIT
from ._compat import reraise
from .globals import _app_ctx_stack
from .globals import _request_ctx_stack
from .signals import appcontext_popped
@ -248,9 +246,6 @@ class AppContext(object):
def __exit__(self, exc_type, exc_value, tb):
self.pop(exc_value)
if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None:
reraise(exc_type, exc_value, tb)
class RequestContext(object):
"""The request context contains all request relevant information. It is
@ -463,9 +458,6 @@ class RequestContext(object):
# See flask.testing for how this works.
self.auto_pop(exc_value)
if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None:
reraise(exc_type, exc_value, tb)
def __repr__(self):
return "<%s '%s' [%s] of %s>" % (
self.__class__.__name__,

View file

@ -11,8 +11,6 @@
import os
from warnings import warn
from ._compat import implements_to_string
from ._compat import text_type
from .app import Flask
from .blueprints import Blueprint
from .globals import _request_ctx_stack
@ -24,7 +22,6 @@ class UnexpectedUnicodeError(AssertionError, UnicodeError):
"""
@implements_to_string
class DebugFilesKeyError(KeyError, AssertionError):
"""Raised from request.files during debugging. The idea is that it can
provide a better error message than just a generic KeyError/BadRequest.
@ -110,13 +107,13 @@ def _dump_loader_info(loader):
if key.startswith("_"):
continue
if isinstance(value, (tuple, list)):
if not all(isinstance(x, (str, text_type)) for x in value):
if not all(isinstance(x, str) for x in value):
continue
yield "%s:" % key
for item in value:
yield " - %s" % item
continue
elif not isinstance(value, (str, text_type, int, float, bool)):
elif not isinstance(value, (str, int, float, bool)):
continue
yield "%s: %r" % (key, value)

View file

@ -30,10 +30,6 @@ from werkzeug.routing import BuildError
from werkzeug.urls import url_quote
from werkzeug.wsgi import wrap_file
from ._compat import fspath
from ._compat import PY2
from ._compat import string_types
from ._compat import text_type
from .globals import _app_ctx_stack
from .globals import _request_ctx_stack
from .globals import current_app
@ -576,9 +572,9 @@ def send_file(
fsize = None
if hasattr(filename_or_fp, "__fspath__"):
filename_or_fp = fspath(filename_or_fp)
filename_or_fp = os.fspath(filename_or_fp)
if isinstance(filename_or_fp, string_types):
if isinstance(filename_or_fp, str):
filename = filename_or_fp
if not os.path.isabs(filename):
filename = os.path.join(current_app.root_path, filename)
@ -608,7 +604,7 @@ def send_file(
if attachment_filename is None:
raise TypeError("filename unavailable, required for sending as attachment")
if not isinstance(attachment_filename, text_type):
if not isinstance(attachment_filename, str):
attachment_filename = attachment_filename.decode("utf-8")
try:
@ -618,7 +614,7 @@ def send_file(
"filename": unicodedata.normalize("NFKD", attachment_filename).encode(
"ascii", "ignore"
),
"filename*": "UTF-8''%s" % url_quote(attachment_filename, safe=b""),
"filename*": "UTF-8''%s" % url_quote(attachment_filename, safe=""),
}
else:
filenames = {"filename": attachment_filename}
@ -678,7 +674,7 @@ def send_file(
os.path.getsize(filename),
adler32(
filename.encode("utf-8")
if isinstance(filename, text_type)
if isinstance(filename, str)
else filename
)
& 0xFFFFFFFF,
@ -769,8 +765,8 @@ def send_from_directory(directory, filename, **options):
:param options: optional keyword arguments that are directly
forwarded to :func:`send_file`.
"""
filename = fspath(filename)
directory = fspath(directory)
filename = os.fspath(filename)
directory = os.fspath(directory)
filename = safe_join(directory, filename)
if not os.path.isabs(filename):
filename = os.path.join(current_app.root_path, filename)
@ -1140,22 +1136,12 @@ def total_seconds(td):
def is_ip(value):
"""Determine if the given string is an IP address.
Python 2 on Windows doesn't provide ``inet_pton``, so this only
checks IPv4 addresses in that environment.
:param value: value to check
:type value: str
:return: True if string is an IP address
:rtype: bool
"""
if PY2 and os.name == "nt":
try:
socket.inet_aton(value)
return True
except socket.error:
return False
for family in (socket.AF_INET, socket.AF_INET6):
try:
socket.inet_pton(family, value)

View file

@ -16,14 +16,13 @@ from itsdangerous import json as _json
from jinja2 import Markup
from werkzeug.http import http_date
from .._compat import PY2
from .._compat import text_type
from ..globals import current_app
from ..globals import request
try:
import dataclasses
except ImportError:
# Python < 3.7
dataclasses = None
# Figure out if simplejson escapes slashes. This behavior was changed
@ -96,7 +95,7 @@ class JSONEncoder(_json.JSONEncoder):
if dataclasses and dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
if hasattr(o, "__html__"):
return text_type(o.__html__())
return str(o.__html__())
return _json.JSONEncoder.default(self, o)
@ -209,7 +208,7 @@ def dumps(obj, app=None, **kwargs):
_dump_arg_defaults(kwargs, app=app)
encoding = kwargs.pop("encoding", None)
rv = _json.dumps(obj, **kwargs)
if encoding is not None and isinstance(rv, text_type):
if encoding is not None and isinstance(rv, str):
rv = rv.encode(encoding)
return rv
@ -256,8 +255,7 @@ def loads(s, app=None, **kwargs):
def load(fp, app=None, **kwargs):
"""Like :func:`loads` but reads from a file object."""
_load_arg_defaults(kwargs, app=app)
if not PY2:
fp = _wrap_reader_for_text(fp, kwargs.pop("encoding", None) or "utf-8")
fp = _wrap_reader_for_text(fp, kwargs.pop("encoding", None) or "utf-8")
return _json.load(fp, **kwargs)
@ -300,7 +298,7 @@ def htmlsafe_dumps(obj, **kwargs):
def htmlsafe_dump(obj, fp, **kwargs):
"""Like :func:`htmlsafe_dumps` but writes into a file object."""
fp.write(text_type(htmlsafe_dumps(obj, **kwargs)))
fp.write(str(htmlsafe_dumps(obj, **kwargs)))
def jsonify(*args, **kwargs):

View file

@ -50,8 +50,6 @@ from jinja2 import Markup
from werkzeug.http import http_date
from werkzeug.http import parse_date
from .._compat import iteritems
from .._compat import text_type
from ..json import dumps
from ..json import loads
@ -124,7 +122,7 @@ class PassDict(JSONTag):
def to_json(self, value):
# JSON objects may only have string keys, so don't bother tagging the
# key here.
return dict((k, self.serializer.tag(v)) for k, v in iteritems(value))
return dict((k, self.serializer.tag(v)) for k, v in value.items())
tag = to_json
@ -181,7 +179,7 @@ class TagMarkup(JSONTag):
return callable(getattr(value, "__html__", None))
def to_json(self, value):
return text_type(value.__html__())
return str(value.__html__())
def to_python(self, value):
return Markup(value)

View file

@ -10,19 +10,19 @@
"""
import hashlib
import warnings
from collections.abc import MutableMapping
from datetime import datetime
from itsdangerous import BadSignature
from itsdangerous import URLSafeTimedSerializer
from werkzeug.datastructures import CallbackDict
from ._compat import collections_abc
from .helpers import is_ip
from .helpers import total_seconds
from .json.tag import TaggedJSONSerializer
class SessionMixin(collections_abc.MutableMapping):
class SessionMixin(MutableMapping):
"""Expands a basic dictionary with session attributes."""
@property

View file

@ -8,7 +8,6 @@
:copyright: 2010 Pallets
:license: BSD-3-Clause
"""
from ._compat import with_metaclass
from .globals import request
@ -135,7 +134,7 @@ class MethodViewType(type):
cls.methods = methods
class MethodView(with_metaclass(MethodViewType, View)):
class MethodView(View, metaclass=MethodViewType):
"""A class-based view that dispatches request methods to the corresponding
class methods. For example, if you implement a ``get`` method, it will be
used to handle ``GET`` requests. ::

View file

@ -24,7 +24,6 @@ from werkzeug.http import parse_date
from werkzeug.routing import BuildError
import flask
from flask._compat import text_type
def test_options_work(app, client):
@ -413,7 +412,7 @@ def test_session_expiration(app, client):
@app.route("/test")
def test():
return text_type(flask.session.permanent)
return str(flask.session.permanent)
rv = client.get("/")
assert "set-cookie" in rv.headers

View file

@ -15,7 +15,6 @@ from jinja2 import TemplateNotFound
from werkzeug.http import parse_cache_control_header
import flask
from flask._compat import text_type
def test_blueprint_specific_error_handling(app, client):
@ -150,7 +149,7 @@ def test_blueprint_url_defaults(app, client):
@bp.route("/bar")
def bar(bar):
return text_type(bar)
return str(bar)
app.register_blueprint(bp, url_prefix="/1", url_defaults={"bar": 23})
app.register_blueprint(bp, url_prefix="/2", url_defaults={"bar": 19})

View file

@ -14,7 +14,6 @@ from datetime import timedelta
import pytest
import flask
from flask._compat import PY2
# config keys used for the TestConfig
@ -198,6 +197,4 @@ def test_from_pyfile_weird_encoding(tmpdir, encoding):
app = flask.Flask(__name__)
app.config.from_pyfile(str(f))
value = app.config["TEST_VALUE"]
if PY2:
value = value.decode(encoding)
assert value == u"föö"

View file

@ -24,9 +24,6 @@ from werkzeug.http import parse_options_header
import flask
from flask import json
from flask._compat import PY2
from flask._compat import StringIO
from flask._compat import text_type
from flask.helpers import get_debug_flag
from flask.helpers import get_env
@ -116,7 +113,7 @@ class TestJSON(object):
def test_json_bad_requests(self, app, client):
@app.route("/json", methods=["POST"])
def return_json():
return flask.jsonify(foo=text_type(flask.request.get_json()))
return flask.jsonify(foo=str(flask.request.get_json()))
rv = client.post("/json", data="malformed", content_type="application/json")
assert rv.status_code == 400
@ -140,7 +137,7 @@ class TestJSON(object):
def test_json_dump_to_file(self, app, app_ctx):
test_data = {"name": "Flask"}
out = StringIO()
out = io.StringIO()
flask.json.dump(test_data, out)
out.seek(0)
@ -254,7 +251,7 @@ class TestJSON(object):
@app.route("/add", methods=["POST"])
def add():
json = flask.request.get_json()
return text_type(json["a"] + json["b"])
return str(json["a"] + json["b"])
rv = client.post(
"/add",
@ -267,7 +264,7 @@ class TestJSON(object):
render = flask.render_template_string
rv = flask.json.htmlsafe_dumps("</script>")
assert rv == u'"\\u003c/script\\u003e"'
assert type(rv) == text_type
assert type(rv) is str
rv = render('{{ "</script>"|tojson }}')
assert rv == '"\\u003c/script\\u003e"'
rv = render('{{ "<\0/script>"|tojson }}')
@ -447,7 +444,7 @@ class TestJSON(object):
assert lines == sorted_by_str
class PyStringIO(object):
class PyBytesIO(object):
def __init__(self, *args, **kwargs):
self._io = io.BytesIO(*args, **kwargs)
@ -503,11 +500,7 @@ class TestSendfile(object):
[
lambda app: open(os.path.join(app.static_folder, "index.html"), "rb"),
lambda app: io.BytesIO(b"Test"),
pytest.param(
lambda app: StringIO("Test"),
marks=pytest.mark.skipif(not PY2, reason="Python 2 only"),
),
lambda app: PyStringIO(b"Test"),
lambda app: PyBytesIO(b"Test"),
],
)
@pytest.mark.usefixtures("req_ctx")
@ -525,10 +518,7 @@ class TestSendfile(object):
"opener",
[
lambda app: io.StringIO(u"Test"),
pytest.param(
lambda app: open(os.path.join(app.static_folder, "index.html")),
marks=pytest.mark.skipif(PY2, reason="Python 3 only"),
),
lambda app: open(os.path.join(app.static_folder, "index.html")),
],
)
@pytest.mark.usefixtures("req_ctx")

View file

@ -12,7 +12,6 @@ import sys
import pytest
import flask
from flask._compat import PY2
def test_explicit_instance_paths(modules_tmpdir):
@ -128,19 +127,3 @@ def test_egg_installed_paths(install_egg, modules_tmpdir, modules_tmpdir_prefix)
finally:
if "site_egg" in sys.modules:
del sys.modules["site_egg"]
@pytest.mark.skipif(not PY2, reason="This only works under Python 2.")
def test_meta_path_loader_without_is_package(request, modules_tmpdir):
app = modules_tmpdir.join("unimportable.py")
app.write("import flask\napp = flask.Flask(__name__)")
class Loader(object):
def find_module(self, name, path=None):
return self
sys.meta_path.append(Loader())
request.addfinalizer(sys.meta_path.pop)
with pytest.raises(AttributeError):
import unimportable # noqa: F401

View file

@ -8,10 +8,10 @@ tests.test_logging
"""
import logging
import sys
from io import StringIO
import pytest
from flask._compat import StringIO
from flask.logging import default_handler
from flask.logging import has_level_handler
from flask.logging import wsgi_errors_stream

View file

@ -1,6 +0,0 @@
import io
def test_changelog_utf8_compatible():
with io.open("CHANGES.rst", encoding="UTF-8") as f:
f.read()

View file

@ -9,8 +9,9 @@
:copyright: 2010 Pallets
:license: BSD-3-Clause
"""
from io import StringIO
import flask
from flask._compat import StringIO
def test_suppressed_exception_logging():

View file

@ -14,7 +14,6 @@ import werkzeug
import flask
from flask import appcontext_popped
from flask._compat import text_type
from flask.cli import ScriptInfo
from flask.json import jsonify
from flask.testing import EnvironBuilder
@ -184,7 +183,7 @@ def test_redirect_keep_session(app, client, app_ctx):
def test_session_transactions(app, client):
@app.route("/")
def index():
return text_type(flask.session["foo"])
return str(flask.session["foo"])
with client:
with client.session_transaction() as sess: