forked from orbit-oss/flask
remove _compat module
This commit is contained in:
parent
1263d3bd14
commit
662c245795
20 changed files with 68 additions and 274 deletions
|
|
@ -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
|
|
||||||
|
|
@ -31,10 +31,6 @@ from werkzeug.wrappers import BaseResponse
|
||||||
|
|
||||||
from . import cli
|
from . import cli
|
||||||
from . import json
|
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 Config
|
||||||
from .config import ConfigAttribute
|
from .config import ConfigAttribute
|
||||||
from .ctx import _AppCtxGlobals
|
from .ctx import _AppCtxGlobals
|
||||||
|
|
@ -1179,10 +1175,10 @@ class Flask(_PackageBoundObject):
|
||||||
# a tuple of only ``GET`` as default.
|
# a tuple of only ``GET`` as default.
|
||||||
if methods is None:
|
if methods is None:
|
||||||
methods = getattr(view_func, "methods", None) or ("GET",)
|
methods = getattr(view_func, "methods", None) or ("GET",)
|
||||||
if isinstance(methods, string_types):
|
if isinstance(methods, str):
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"Allowed methods have to be iterables of strings, "
|
"Allowed methods must be a list of strings, for"
|
||||||
'for example: @app.route(..., methods=["POST"])'
|
' example: @app.route(..., methods=["POST"])'
|
||||||
)
|
)
|
||||||
methods = set(item.upper() for item in methods)
|
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
|
:param exc_class_or_code: Any exception class, or an HTTP status
|
||||||
code as an integer.
|
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]
|
exc_class = default_exceptions[exc_class_or_code]
|
||||||
else:
|
else:
|
||||||
exc_class = exc_class_or_code
|
exc_class = exc_class_or_code
|
||||||
|
|
@ -1727,13 +1723,6 @@ class Flask(_PackageBoundObject):
|
||||||
|
|
||||||
.. versionadded:: 0.7
|
.. 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 isinstance(e, BadRequestKeyError):
|
||||||
if self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"]:
|
if self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"]:
|
||||||
e.show_exception = True
|
e.show_exception = True
|
||||||
|
|
@ -1752,7 +1741,8 @@ class Flask(_PackageBoundObject):
|
||||||
handler = self._find_error_handler(e)
|
handler = self._find_error_handler(e)
|
||||||
|
|
||||||
if handler is None:
|
if handler is None:
|
||||||
reraise(exc_type, exc_value, tb)
|
raise
|
||||||
|
|
||||||
return handler(e)
|
return handler(e)
|
||||||
|
|
||||||
def handle_exception(self, e):
|
def handle_exception(self, e):
|
||||||
|
|
@ -1789,20 +1779,18 @@ class Flask(_PackageBoundObject):
|
||||||
|
|
||||||
.. versionadded:: 0.3
|
.. versionadded:: 0.3
|
||||||
"""
|
"""
|
||||||
exc_type, exc_value, tb = sys.exc_info()
|
exc_info = sys.exc_info()
|
||||||
got_request_exception.send(self, exception=e)
|
got_request_exception.send(self, exception=e)
|
||||||
|
|
||||||
if self.propagate_exceptions:
|
if self.propagate_exceptions:
|
||||||
# if we want to repropagate the exception, we can attempt to
|
# Re-raise if called with an active exception, otherwise
|
||||||
# raise it with the whole traceback in case we can do that
|
# raise the passed in exception.
|
||||||
# (the function was actually called from the except part)
|
if exc_info[1] is e:
|
||||||
# otherwise, we just raise the error again
|
raise
|
||||||
if exc_value is e:
|
|
||||||
reraise(exc_type, exc_value, tb)
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
self.log_exception((exc_type, exc_value, tb))
|
raise e
|
||||||
|
|
||||||
|
self.log_exception(exc_info)
|
||||||
server_error = InternalServerError()
|
server_error = InternalServerError()
|
||||||
# TODO: pass as param when Werkzeug>=1.0.0 is required
|
# TODO: pass as param when Werkzeug>=1.0.0 is required
|
||||||
# TODO: also remove note about this from docstring and docs
|
# 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
|
# make sure the body is an instance of the response class
|
||||||
if not isinstance(rv, self.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
|
# let the response class set the status and headers instead of
|
||||||
# waiting to do it manually, so that the class can handle any
|
# waiting to do it manually, so that the class can handle any
|
||||||
# special logic
|
# special logic
|
||||||
|
|
@ -2040,13 +2028,12 @@ class Flask(_PackageBoundObject):
|
||||||
try:
|
try:
|
||||||
rv = self.response_class.force_type(rv, request.environ)
|
rv = self.response_class.force_type(rv, request.environ)
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
new_error = TypeError(
|
raise TypeError(
|
||||||
"{e}\nThe view function did not return a valid"
|
"{e}\nThe view function did not return a valid"
|
||||||
" response. The return type must be a string, dict, tuple,"
|
" response. The return type must be a string, dict, tuple,"
|
||||||
" Response instance, or WSGI callable, but it was a"
|
" Response instance, or WSGI callable, but it was a"
|
||||||
" {rv.__class__.__name__}.".format(e=e, rv=rv)
|
" {rv.__class__.__name__}.".format(e=e, rv=rv)
|
||||||
)
|
).with_traceback(sys.exc_info()[2])
|
||||||
reraise(TypeError, new_error, sys.exc_info()[2])
|
|
||||||
else:
|
else:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"The view function did not return a valid"
|
"The view function did not return a valid"
|
||||||
|
|
@ -2057,7 +2044,7 @@ class Flask(_PackageBoundObject):
|
||||||
|
|
||||||
# prefer the status if it was provided
|
# prefer the status if it was provided
|
||||||
if status is not None:
|
if status is not None:
|
||||||
if isinstance(status, (text_type, bytes, bytearray)):
|
if isinstance(status, (str, bytes, bytearray)):
|
||||||
rv.status = status
|
rv.status = status
|
||||||
else:
|
else:
|
||||||
rv.status_code = status
|
rv.status_code = status
|
||||||
|
|
@ -2121,23 +2108,24 @@ class Flask(_PackageBoundObject):
|
||||||
func(endpoint, values)
|
func(endpoint, values)
|
||||||
|
|
||||||
def handle_url_build_error(self, error, 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:
|
for handler in self.url_build_error_handlers:
|
||||||
try:
|
try:
|
||||||
rv = handler(error, endpoint, values)
|
rv = handler(error, endpoint, values)
|
||||||
|
except BuildError as e:
|
||||||
|
# make error available outside except block
|
||||||
|
error = e
|
||||||
|
else:
|
||||||
if rv is not None:
|
if rv is not None:
|
||||||
return rv
|
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
|
# Re-raise if called with an active exception, otherwise raise
|
||||||
# still the same one we can reraise it with the original traceback,
|
# the passed in exception.
|
||||||
# otherwise we raise it from here.
|
if error is sys.exc_info()[1]:
|
||||||
if error is exc_value:
|
raise
|
||||||
reraise(exc_type, exc_value, tb)
|
|
||||||
raise error
|
raise error
|
||||||
|
|
||||||
def preprocess_request(self):
|
def preprocess_request(self):
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,6 @@ from threading import Thread
|
||||||
import click
|
import click
|
||||||
from werkzeug.utils import import_string
|
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 .globals import current_app
|
||||||
from .helpers import get_debug_flag
|
from .helpers import get_debug_flag
|
||||||
from .helpers import get_env
|
from .helpers import get_env
|
||||||
|
|
@ -63,7 +59,7 @@ def find_best_app(script_info, module):
|
||||||
return app
|
return app
|
||||||
|
|
||||||
# Otherwise find the only object that is a Flask instance.
|
# 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:
|
if len(matches) == 1:
|
||||||
return matches[0]
|
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
|
of arguments. Checks for the existence of a script_info argument and calls
|
||||||
the app_factory depending on that and the arguments provided.
|
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_names = args_spec.args
|
||||||
arg_defaults = args_spec.defaults
|
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:
|
except ImportError:
|
||||||
# Reraise the ImportError if it occurred within the imported module.
|
# Reraise the ImportError if it occurred within the imported module.
|
||||||
# Determine this by checking whether the trace has a depth > 1.
|
# 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(
|
raise NoAppException(
|
||||||
'While importing "{name}", an ImportError was raised:'
|
'While importing "{name}", an ImportError was raised:'
|
||||||
"\n\n{tb}".format(name=module_name, tb=traceback.format_exc())
|
"\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
|
exc_info = self._bg_loading_exc_info
|
||||||
if exc_info is not None:
|
if exc_info is not None:
|
||||||
self._bg_loading_exc_info = None
|
self._bg_loading_exc_info = None
|
||||||
reraise(*exc_info)
|
raise exc_info
|
||||||
|
|
||||||
def _load_unlocked(self):
|
def _load_unlocked(self):
|
||||||
__traceback_hide__ = True # noqa: F841
|
__traceback_hide__ = True # noqa: F841
|
||||||
|
|
@ -741,11 +737,7 @@ def _validate_key(ctx, param, value):
|
||||||
"""
|
"""
|
||||||
cert = ctx.params.get("cert")
|
cert = ctx.params.get("cert")
|
||||||
is_adhoc = cert == "adhoc"
|
is_adhoc = cert == "adhoc"
|
||||||
|
is_context = ssl and isinstance(cert, ssl.SSLContext)
|
||||||
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)
|
|
||||||
|
|
||||||
if value is not None:
|
if value is not None:
|
||||||
if is_adhoc:
|
if is_adhoc:
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,6 @@ import types
|
||||||
|
|
||||||
from werkzeug.utils import import_string
|
from werkzeug.utils import import_string
|
||||||
|
|
||||||
from ._compat import iteritems
|
|
||||||
from ._compat import string_types
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigAttribute(object):
|
class ConfigAttribute(object):
|
||||||
"""Makes an attribute forward to the config"""
|
"""Makes an attribute forward to the config"""
|
||||||
|
|
@ -169,7 +166,7 @@ class Config(dict):
|
||||||
|
|
||||||
:param obj: an import name or object
|
:param obj: an import name or object
|
||||||
"""
|
"""
|
||||||
if isinstance(obj, string_types):
|
if isinstance(obj, str):
|
||||||
obj = import_string(obj)
|
obj = import_string(obj)
|
||||||
for key in dir(obj):
|
for key in dir(obj):
|
||||||
if key.isupper():
|
if key.isupper():
|
||||||
|
|
@ -261,7 +258,7 @@ class Config(dict):
|
||||||
.. versionadded:: 0.11
|
.. versionadded:: 0.11
|
||||||
"""
|
"""
|
||||||
rv = {}
|
rv = {}
|
||||||
for k, v in iteritems(self):
|
for k, v in self.items():
|
||||||
if not k.startswith(namespace):
|
if not k.startswith(namespace):
|
||||||
continue
|
continue
|
||||||
if trim_namespace:
|
if trim_namespace:
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ from functools import update_wrapper
|
||||||
|
|
||||||
from werkzeug.exceptions import HTTPException
|
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 _app_ctx_stack
|
||||||
from .globals import _request_ctx_stack
|
from .globals import _request_ctx_stack
|
||||||
from .signals import appcontext_popped
|
from .signals import appcontext_popped
|
||||||
|
|
@ -248,9 +246,6 @@ class AppContext(object):
|
||||||
def __exit__(self, exc_type, exc_value, tb):
|
def __exit__(self, exc_type, exc_value, tb):
|
||||||
self.pop(exc_value)
|
self.pop(exc_value)
|
||||||
|
|
||||||
if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None:
|
|
||||||
reraise(exc_type, exc_value, tb)
|
|
||||||
|
|
||||||
|
|
||||||
class RequestContext(object):
|
class RequestContext(object):
|
||||||
"""The request context contains all request relevant information. It is
|
"""The request context contains all request relevant information. It is
|
||||||
|
|
@ -463,9 +458,6 @@ class RequestContext(object):
|
||||||
# See flask.testing for how this works.
|
# See flask.testing for how this works.
|
||||||
self.auto_pop(exc_value)
|
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):
|
def __repr__(self):
|
||||||
return "<%s '%s' [%s] of %s>" % (
|
return "<%s '%s' [%s] of %s>" % (
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,6 @@
|
||||||
import os
|
import os
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
from ._compat import implements_to_string
|
|
||||||
from ._compat import text_type
|
|
||||||
from .app import Flask
|
from .app import Flask
|
||||||
from .blueprints import Blueprint
|
from .blueprints import Blueprint
|
||||||
from .globals import _request_ctx_stack
|
from .globals import _request_ctx_stack
|
||||||
|
|
@ -24,7 +22,6 @@ class UnexpectedUnicodeError(AssertionError, UnicodeError):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@implements_to_string
|
|
||||||
class DebugFilesKeyError(KeyError, AssertionError):
|
class DebugFilesKeyError(KeyError, AssertionError):
|
||||||
"""Raised from request.files during debugging. The idea is that it can
|
"""Raised from request.files during debugging. The idea is that it can
|
||||||
provide a better error message than just a generic KeyError/BadRequest.
|
provide a better error message than just a generic KeyError/BadRequest.
|
||||||
|
|
@ -110,13 +107,13 @@ def _dump_loader_info(loader):
|
||||||
if key.startswith("_"):
|
if key.startswith("_"):
|
||||||
continue
|
continue
|
||||||
if isinstance(value, (tuple, list)):
|
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
|
continue
|
||||||
yield "%s:" % key
|
yield "%s:" % key
|
||||||
for item in value:
|
for item in value:
|
||||||
yield " - %s" % item
|
yield " - %s" % item
|
||||||
continue
|
continue
|
||||||
elif not isinstance(value, (str, text_type, int, float, bool)):
|
elif not isinstance(value, (str, int, float, bool)):
|
||||||
continue
|
continue
|
||||||
yield "%s: %r" % (key, value)
|
yield "%s: %r" % (key, value)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,6 @@ from werkzeug.routing import BuildError
|
||||||
from werkzeug.urls import url_quote
|
from werkzeug.urls import url_quote
|
||||||
from werkzeug.wsgi import wrap_file
|
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 _app_ctx_stack
|
||||||
from .globals import _request_ctx_stack
|
from .globals import _request_ctx_stack
|
||||||
from .globals import current_app
|
from .globals import current_app
|
||||||
|
|
@ -576,9 +572,9 @@ def send_file(
|
||||||
fsize = None
|
fsize = None
|
||||||
|
|
||||||
if hasattr(filename_or_fp, "__fspath__"):
|
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
|
filename = filename_or_fp
|
||||||
if not os.path.isabs(filename):
|
if not os.path.isabs(filename):
|
||||||
filename = os.path.join(current_app.root_path, filename)
|
filename = os.path.join(current_app.root_path, filename)
|
||||||
|
|
@ -608,7 +604,7 @@ def send_file(
|
||||||
if attachment_filename is None:
|
if attachment_filename is None:
|
||||||
raise TypeError("filename unavailable, required for sending as attachment")
|
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")
|
attachment_filename = attachment_filename.decode("utf-8")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -618,7 +614,7 @@ def send_file(
|
||||||
"filename": unicodedata.normalize("NFKD", attachment_filename).encode(
|
"filename": unicodedata.normalize("NFKD", attachment_filename).encode(
|
||||||
"ascii", "ignore"
|
"ascii", "ignore"
|
||||||
),
|
),
|
||||||
"filename*": "UTF-8''%s" % url_quote(attachment_filename, safe=b""),
|
"filename*": "UTF-8''%s" % url_quote(attachment_filename, safe=""),
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
filenames = {"filename": attachment_filename}
|
filenames = {"filename": attachment_filename}
|
||||||
|
|
@ -678,7 +674,7 @@ def send_file(
|
||||||
os.path.getsize(filename),
|
os.path.getsize(filename),
|
||||||
adler32(
|
adler32(
|
||||||
filename.encode("utf-8")
|
filename.encode("utf-8")
|
||||||
if isinstance(filename, text_type)
|
if isinstance(filename, str)
|
||||||
else filename
|
else filename
|
||||||
)
|
)
|
||||||
& 0xFFFFFFFF,
|
& 0xFFFFFFFF,
|
||||||
|
|
@ -769,8 +765,8 @@ def send_from_directory(directory, filename, **options):
|
||||||
:param options: optional keyword arguments that are directly
|
:param options: optional keyword arguments that are directly
|
||||||
forwarded to :func:`send_file`.
|
forwarded to :func:`send_file`.
|
||||||
"""
|
"""
|
||||||
filename = fspath(filename)
|
filename = os.fspath(filename)
|
||||||
directory = fspath(directory)
|
directory = os.fspath(directory)
|
||||||
filename = safe_join(directory, filename)
|
filename = safe_join(directory, filename)
|
||||||
if not os.path.isabs(filename):
|
if not os.path.isabs(filename):
|
||||||
filename = os.path.join(current_app.root_path, filename)
|
filename = os.path.join(current_app.root_path, filename)
|
||||||
|
|
@ -1140,22 +1136,12 @@ def total_seconds(td):
|
||||||
def is_ip(value):
|
def is_ip(value):
|
||||||
"""Determine if the given string is an IP address.
|
"""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
|
:param value: value to check
|
||||||
:type value: str
|
:type value: str
|
||||||
|
|
||||||
:return: True if string is an IP address
|
:return: True if string is an IP address
|
||||||
:rtype: bool
|
: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):
|
for family in (socket.AF_INET, socket.AF_INET6):
|
||||||
try:
|
try:
|
||||||
socket.inet_pton(family, value)
|
socket.inet_pton(family, value)
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,13 @@ from itsdangerous import json as _json
|
||||||
from jinja2 import Markup
|
from jinja2 import Markup
|
||||||
from werkzeug.http import http_date
|
from werkzeug.http import http_date
|
||||||
|
|
||||||
from .._compat import PY2
|
|
||||||
from .._compat import text_type
|
|
||||||
from ..globals import current_app
|
from ..globals import current_app
|
||||||
from ..globals import request
|
from ..globals import request
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import dataclasses
|
import dataclasses
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
# Python < 3.7
|
||||||
dataclasses = None
|
dataclasses = None
|
||||||
|
|
||||||
# Figure out if simplejson escapes slashes. This behavior was changed
|
# 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):
|
if dataclasses and dataclasses.is_dataclass(o):
|
||||||
return dataclasses.asdict(o)
|
return dataclasses.asdict(o)
|
||||||
if hasattr(o, "__html__"):
|
if hasattr(o, "__html__"):
|
||||||
return text_type(o.__html__())
|
return str(o.__html__())
|
||||||
return _json.JSONEncoder.default(self, o)
|
return _json.JSONEncoder.default(self, o)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -209,7 +208,7 @@ def dumps(obj, app=None, **kwargs):
|
||||||
_dump_arg_defaults(kwargs, app=app)
|
_dump_arg_defaults(kwargs, app=app)
|
||||||
encoding = kwargs.pop("encoding", None)
|
encoding = kwargs.pop("encoding", None)
|
||||||
rv = _json.dumps(obj, **kwargs)
|
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)
|
rv = rv.encode(encoding)
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
@ -256,8 +255,7 @@ def loads(s, app=None, **kwargs):
|
||||||
def load(fp, app=None, **kwargs):
|
def load(fp, app=None, **kwargs):
|
||||||
"""Like :func:`loads` but reads from a file object."""
|
"""Like :func:`loads` but reads from a file object."""
|
||||||
_load_arg_defaults(kwargs, app=app)
|
_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)
|
return _json.load(fp, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -300,7 +298,7 @@ def htmlsafe_dumps(obj, **kwargs):
|
||||||
|
|
||||||
def htmlsafe_dump(obj, fp, **kwargs):
|
def htmlsafe_dump(obj, fp, **kwargs):
|
||||||
"""Like :func:`htmlsafe_dumps` but writes into a file object."""
|
"""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):
|
def jsonify(*args, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,6 @@ from jinja2 import Markup
|
||||||
from werkzeug.http import http_date
|
from werkzeug.http import http_date
|
||||||
from werkzeug.http import parse_date
|
from werkzeug.http import parse_date
|
||||||
|
|
||||||
from .._compat import iteritems
|
|
||||||
from .._compat import text_type
|
|
||||||
from ..json import dumps
|
from ..json import dumps
|
||||||
from ..json import loads
|
from ..json import loads
|
||||||
|
|
||||||
|
|
@ -124,7 +122,7 @@ class PassDict(JSONTag):
|
||||||
def to_json(self, value):
|
def to_json(self, value):
|
||||||
# JSON objects may only have string keys, so don't bother tagging the
|
# JSON objects may only have string keys, so don't bother tagging the
|
||||||
# key here.
|
# 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
|
tag = to_json
|
||||||
|
|
||||||
|
|
@ -181,7 +179,7 @@ class TagMarkup(JSONTag):
|
||||||
return callable(getattr(value, "__html__", None))
|
return callable(getattr(value, "__html__", None))
|
||||||
|
|
||||||
def to_json(self, value):
|
def to_json(self, value):
|
||||||
return text_type(value.__html__())
|
return str(value.__html__())
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
return Markup(value)
|
return Markup(value)
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,19 @@
|
||||||
"""
|
"""
|
||||||
import hashlib
|
import hashlib
|
||||||
import warnings
|
import warnings
|
||||||
|
from collections.abc import MutableMapping
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from itsdangerous import BadSignature
|
from itsdangerous import BadSignature
|
||||||
from itsdangerous import URLSafeTimedSerializer
|
from itsdangerous import URLSafeTimedSerializer
|
||||||
from werkzeug.datastructures import CallbackDict
|
from werkzeug.datastructures import CallbackDict
|
||||||
|
|
||||||
from ._compat import collections_abc
|
|
||||||
from .helpers import is_ip
|
from .helpers import is_ip
|
||||||
from .helpers import total_seconds
|
from .helpers import total_seconds
|
||||||
from .json.tag import TaggedJSONSerializer
|
from .json.tag import TaggedJSONSerializer
|
||||||
|
|
||||||
|
|
||||||
class SessionMixin(collections_abc.MutableMapping):
|
class SessionMixin(MutableMapping):
|
||||||
"""Expands a basic dictionary with session attributes."""
|
"""Expands a basic dictionary with session attributes."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
:copyright: 2010 Pallets
|
:copyright: 2010 Pallets
|
||||||
:license: BSD-3-Clause
|
:license: BSD-3-Clause
|
||||||
"""
|
"""
|
||||||
from ._compat import with_metaclass
|
|
||||||
from .globals import request
|
from .globals import request
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -135,7 +134,7 @@ class MethodViewType(type):
|
||||||
cls.methods = methods
|
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
|
"""A class-based view that dispatches request methods to the corresponding
|
||||||
class methods. For example, if you implement a ``get`` method, it will be
|
class methods. For example, if you implement a ``get`` method, it will be
|
||||||
used to handle ``GET`` requests. ::
|
used to handle ``GET`` requests. ::
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ from werkzeug.http import parse_date
|
||||||
from werkzeug.routing import BuildError
|
from werkzeug.routing import BuildError
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask._compat import text_type
|
|
||||||
|
|
||||||
|
|
||||||
def test_options_work(app, client):
|
def test_options_work(app, client):
|
||||||
|
|
@ -413,7 +412,7 @@ def test_session_expiration(app, client):
|
||||||
|
|
||||||
@app.route("/test")
|
@app.route("/test")
|
||||||
def test():
|
def test():
|
||||||
return text_type(flask.session.permanent)
|
return str(flask.session.permanent)
|
||||||
|
|
||||||
rv = client.get("/")
|
rv = client.get("/")
|
||||||
assert "set-cookie" in rv.headers
|
assert "set-cookie" in rv.headers
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ from jinja2 import TemplateNotFound
|
||||||
from werkzeug.http import parse_cache_control_header
|
from werkzeug.http import parse_cache_control_header
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask._compat import text_type
|
|
||||||
|
|
||||||
|
|
||||||
def test_blueprint_specific_error_handling(app, client):
|
def test_blueprint_specific_error_handling(app, client):
|
||||||
|
|
@ -150,7 +149,7 @@ def test_blueprint_url_defaults(app, client):
|
||||||
|
|
||||||
@bp.route("/bar")
|
@bp.route("/bar")
|
||||||
def bar(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="/1", url_defaults={"bar": 23})
|
||||||
app.register_blueprint(bp, url_prefix="/2", url_defaults={"bar": 19})
|
app.register_blueprint(bp, url_prefix="/2", url_defaults={"bar": 19})
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ from datetime import timedelta
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask._compat import PY2
|
|
||||||
|
|
||||||
|
|
||||||
# config keys used for the TestConfig
|
# config keys used for the TestConfig
|
||||||
|
|
@ -198,6 +197,4 @@ def test_from_pyfile_weird_encoding(tmpdir, encoding):
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
app.config.from_pyfile(str(f))
|
app.config.from_pyfile(str(f))
|
||||||
value = app.config["TEST_VALUE"]
|
value = app.config["TEST_VALUE"]
|
||||||
if PY2:
|
|
||||||
value = value.decode(encoding)
|
|
||||||
assert value == u"föö"
|
assert value == u"föö"
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,6 @@ from werkzeug.http import parse_options_header
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import json
|
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_debug_flag
|
||||||
from flask.helpers import get_env
|
from flask.helpers import get_env
|
||||||
|
|
||||||
|
|
@ -116,7 +113,7 @@ class TestJSON(object):
|
||||||
def test_json_bad_requests(self, app, client):
|
def test_json_bad_requests(self, app, client):
|
||||||
@app.route("/json", methods=["POST"])
|
@app.route("/json", methods=["POST"])
|
||||||
def return_json():
|
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")
|
rv = client.post("/json", data="malformed", content_type="application/json")
|
||||||
assert rv.status_code == 400
|
assert rv.status_code == 400
|
||||||
|
|
@ -140,7 +137,7 @@ class TestJSON(object):
|
||||||
|
|
||||||
def test_json_dump_to_file(self, app, app_ctx):
|
def test_json_dump_to_file(self, app, app_ctx):
|
||||||
test_data = {"name": "Flask"}
|
test_data = {"name": "Flask"}
|
||||||
out = StringIO()
|
out = io.StringIO()
|
||||||
|
|
||||||
flask.json.dump(test_data, out)
|
flask.json.dump(test_data, out)
|
||||||
out.seek(0)
|
out.seek(0)
|
||||||
|
|
@ -254,7 +251,7 @@ class TestJSON(object):
|
||||||
@app.route("/add", methods=["POST"])
|
@app.route("/add", methods=["POST"])
|
||||||
def add():
|
def add():
|
||||||
json = flask.request.get_json()
|
json = flask.request.get_json()
|
||||||
return text_type(json["a"] + json["b"])
|
return str(json["a"] + json["b"])
|
||||||
|
|
||||||
rv = client.post(
|
rv = client.post(
|
||||||
"/add",
|
"/add",
|
||||||
|
|
@ -267,7 +264,7 @@ class TestJSON(object):
|
||||||
render = flask.render_template_string
|
render = flask.render_template_string
|
||||||
rv = flask.json.htmlsafe_dumps("</script>")
|
rv = flask.json.htmlsafe_dumps("</script>")
|
||||||
assert rv == u'"\\u003c/script\\u003e"'
|
assert rv == u'"\\u003c/script\\u003e"'
|
||||||
assert type(rv) == text_type
|
assert type(rv) is str
|
||||||
rv = render('{{ "</script>"|tojson }}')
|
rv = render('{{ "</script>"|tojson }}')
|
||||||
assert rv == '"\\u003c/script\\u003e"'
|
assert rv == '"\\u003c/script\\u003e"'
|
||||||
rv = render('{{ "<\0/script>"|tojson }}')
|
rv = render('{{ "<\0/script>"|tojson }}')
|
||||||
|
|
@ -447,7 +444,7 @@ class TestJSON(object):
|
||||||
assert lines == sorted_by_str
|
assert lines == sorted_by_str
|
||||||
|
|
||||||
|
|
||||||
class PyStringIO(object):
|
class PyBytesIO(object):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self._io = io.BytesIO(*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: open(os.path.join(app.static_folder, "index.html"), "rb"),
|
||||||
lambda app: io.BytesIO(b"Test"),
|
lambda app: io.BytesIO(b"Test"),
|
||||||
pytest.param(
|
lambda app: PyBytesIO(b"Test"),
|
||||||
lambda app: StringIO("Test"),
|
|
||||||
marks=pytest.mark.skipif(not PY2, reason="Python 2 only"),
|
|
||||||
),
|
|
||||||
lambda app: PyStringIO(b"Test"),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.usefixtures("req_ctx")
|
@pytest.mark.usefixtures("req_ctx")
|
||||||
|
|
@ -525,10 +518,7 @@ class TestSendfile(object):
|
||||||
"opener",
|
"opener",
|
||||||
[
|
[
|
||||||
lambda app: io.StringIO(u"Test"),
|
lambda app: io.StringIO(u"Test"),
|
||||||
pytest.param(
|
lambda app: open(os.path.join(app.static_folder, "index.html")),
|
||||||
lambda app: open(os.path.join(app.static_folder, "index.html")),
|
|
||||||
marks=pytest.mark.skipif(PY2, reason="Python 3 only"),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.usefixtures("req_ctx")
|
@pytest.mark.usefixtures("req_ctx")
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import sys
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask._compat import PY2
|
|
||||||
|
|
||||||
|
|
||||||
def test_explicit_instance_paths(modules_tmpdir):
|
def test_explicit_instance_paths(modules_tmpdir):
|
||||||
|
|
@ -128,19 +127,3 @@ def test_egg_installed_paths(install_egg, modules_tmpdir, modules_tmpdir_prefix)
|
||||||
finally:
|
finally:
|
||||||
if "site_egg" in sys.modules:
|
if "site_egg" in sys.modules:
|
||||||
del sys.modules["site_egg"]
|
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
|
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ tests.test_logging
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from flask._compat import StringIO
|
|
||||||
from flask.logging import default_handler
|
from flask.logging import default_handler
|
||||||
from flask.logging import has_level_handler
|
from flask.logging import has_level_handler
|
||||||
from flask.logging import wsgi_errors_stream
|
from flask.logging import wsgi_errors_stream
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
import io
|
|
||||||
|
|
||||||
|
|
||||||
def test_changelog_utf8_compatible():
|
|
||||||
with io.open("CHANGES.rst", encoding="UTF-8") as f:
|
|
||||||
f.read()
|
|
||||||
|
|
@ -9,8 +9,9 @@
|
||||||
:copyright: 2010 Pallets
|
:copyright: 2010 Pallets
|
||||||
:license: BSD-3-Clause
|
:license: BSD-3-Clause
|
||||||
"""
|
"""
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask._compat import StringIO
|
|
||||||
|
|
||||||
|
|
||||||
def test_suppressed_exception_logging():
|
def test_suppressed_exception_logging():
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import werkzeug
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import appcontext_popped
|
from flask import appcontext_popped
|
||||||
from flask._compat import text_type
|
|
||||||
from flask.cli import ScriptInfo
|
from flask.cli import ScriptInfo
|
||||||
from flask.json import jsonify
|
from flask.json import jsonify
|
||||||
from flask.testing import EnvironBuilder
|
from flask.testing import EnvironBuilder
|
||||||
|
|
@ -184,7 +183,7 @@ def test_redirect_keep_session(app, client, app_ctx):
|
||||||
def test_session_transactions(app, client):
|
def test_session_transactions(app, client):
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
return text_type(flask.session["foo"])
|
return str(flask.session["foo"])
|
||||||
|
|
||||||
with client:
|
with client:
|
||||||
with client.session_transaction() as sess:
|
with client.session_transaction() as sess:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue