Browse Source

Intermediate changes

robot-piglet 10 months ago
parent
commit
38934cfb0b

+ 4 - 6
contrib/python/Flask/py3/.dist-info/METADATA

@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Metadata-Version: 2.1
 Name: Flask
 Name: Flask
-Version: 2.0.3
+Version: 2.1.3
 Summary: A simple framework for building complex web applications.
 Summary: A simple framework for building complex web applications.
 Home-page: https://palletsprojects.com/p/flask
 Home-page: https://palletsprojects.com/p/flask
 Author: Armin Ronacher
 Author: Armin Ronacher
@@ -15,7 +15,6 @@ Project-URL: Source Code, https://github.com/pallets/flask/
 Project-URL: Issue Tracker, https://github.com/pallets/flask/issues/
 Project-URL: Issue Tracker, https://github.com/pallets/flask/issues/
 Project-URL: Twitter, https://twitter.com/PalletsTeam
 Project-URL: Twitter, https://twitter.com/PalletsTeam
 Project-URL: Chat, https://discord.gg/pallets
 Project-URL: Chat, https://discord.gg/pallets
-Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Web Environment
 Classifier: Environment :: Web Environment
 Classifier: Framework :: Flask
 Classifier: Framework :: Flask
@@ -27,13 +26,14 @@ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
 Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
 Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
 Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
 Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
 Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
 Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
-Requires-Python: >=3.6
+Requires-Python: >=3.7
 Description-Content-Type: text/x-rst
 Description-Content-Type: text/x-rst
 License-File: LICENSE.rst
 License-File: LICENSE.rst
 Requires-Dist: Werkzeug (>=2.0)
 Requires-Dist: Werkzeug (>=2.0)
 Requires-Dist: Jinja2 (>=3.0)
 Requires-Dist: Jinja2 (>=3.0)
 Requires-Dist: itsdangerous (>=2.0)
 Requires-Dist: itsdangerous (>=2.0)
-Requires-Dist: click (>=7.1.2)
+Requires-Dist: click (>=8.0)
+Requires-Dist: importlib-metadata (>=3.6.0) ; python_version < "3.10"
 Provides-Extra: async
 Provides-Extra: async
 Requires-Dist: asgiref (>=3.2) ; extra == 'async'
 Requires-Dist: asgiref (>=3.2) ; extra == 'async'
 Provides-Extra: dotenv
 Provides-Extra: dotenv
@@ -121,5 +121,3 @@ Links
 -   Website: https://palletsprojects.com/p/flask/
 -   Website: https://palletsprojects.com/p/flask/
 -   Twitter: https://twitter.com/PalletsTeam
 -   Twitter: https://twitter.com/PalletsTeam
 -   Chat: https://discord.gg/pallets
 -   Chat: https://discord.gg/pallets
-
-

+ 1 - 2
contrib/python/Flask/py3/flask/__init__.py

@@ -23,7 +23,6 @@ from .helpers import flash as flash
 from .helpers import get_flashed_messages as get_flashed_messages
 from .helpers import get_flashed_messages as get_flashed_messages
 from .helpers import get_template_attribute as get_template_attribute
 from .helpers import get_template_attribute as get_template_attribute
 from .helpers import make_response as make_response
 from .helpers import make_response as make_response
-from .helpers import safe_join as safe_join
 from .helpers import send_file as send_file
 from .helpers import send_file as send_file
 from .helpers import send_from_directory as send_from_directory
 from .helpers import send_from_directory as send_from_directory
 from .helpers import stream_with_context as stream_with_context
 from .helpers import stream_with_context as stream_with_context
@@ -43,4 +42,4 @@ from .signals import template_rendered as template_rendered
 from .templating import render_template as render_template
 from .templating import render_template as render_template
 from .templating import render_template_string as render_template_string
 from .templating import render_template_string as render_template_string
 
 
-__version__ = "2.0.3"
+__version__ = "2.1.3"

+ 52 - 52
contrib/python/Flask/py3/flask/app.py

@@ -16,7 +16,6 @@ from werkzeug.exceptions import BadRequest
 from werkzeug.exceptions import BadRequestKeyError
 from werkzeug.exceptions import BadRequestKeyError
 from werkzeug.exceptions import HTTPException
 from werkzeug.exceptions import HTTPException
 from werkzeug.exceptions import InternalServerError
 from werkzeug.exceptions import InternalServerError
-from werkzeug.local import ContextVar
 from werkzeug.routing import BuildError
 from werkzeug.routing import BuildError
 from werkzeug.routing import Map
 from werkzeug.routing import Map
 from werkzeug.routing import MapAdapter
 from werkzeug.routing import MapAdapter
@@ -27,6 +26,7 @@ from werkzeug.wrappers import Response as BaseResponse
 
 
 from . import cli
 from . import cli
 from . import json
 from . import json
+from . import typing as ft
 from .config import Config
 from .config import Config
 from .config import ConfigAttribute
 from .config import ConfigAttribute
 from .ctx import _AppCtxGlobals
 from .ctx import _AppCtxGlobals
@@ -51,6 +51,7 @@ from .scaffold import find_package
 from .scaffold import Scaffold
 from .scaffold import Scaffold
 from .scaffold import setupmethod
 from .scaffold import setupmethod
 from .sessions import SecureCookieSessionInterface
 from .sessions import SecureCookieSessionInterface
+from .sessions import SessionInterface
 from .signals import appcontext_tearing_down
 from .signals import appcontext_tearing_down
 from .signals import got_request_exception
 from .signals import got_request_exception
 from .signals import request_finished
 from .signals import request_finished
@@ -58,12 +59,6 @@ from .signals import request_started
 from .signals import request_tearing_down
 from .signals import request_tearing_down
 from .templating import DispatchingJinjaLoader
 from .templating import DispatchingJinjaLoader
 from .templating import Environment
 from .templating import Environment
-from .typing import BeforeFirstRequestCallable
-from .typing import ResponseReturnValue
-from .typing import TeardownCallable
-from .typing import TemplateFilterCallable
-from .typing import TemplateGlobalCallable
-from .typing import TemplateTestCallable
 from .wrappers import Request
 from .wrappers import Request
 from .wrappers import Response
 from .wrappers import Response
 
 
@@ -72,7 +67,6 @@ if t.TYPE_CHECKING:
     from .blueprints import Blueprint
     from .blueprints import Blueprint
     from .testing import FlaskClient
     from .testing import FlaskClient
     from .testing import FlaskCliRunner
     from .testing import FlaskCliRunner
-    from .typing import ErrorHandlerCallable
 
 
 if sys.version_info >= (3, 8):
 if sys.version_info >= (3, 8):
     iscoroutinefunction = inspect.iscoroutinefunction
     iscoroutinefunction = inspect.iscoroutinefunction
@@ -379,7 +373,7 @@ class Flask(Scaffold):
     #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here.
     #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here.
     #:
     #:
     #: .. versionadded:: 0.8
     #: .. versionadded:: 0.8
-    session_interface = SecureCookieSessionInterface()
+    session_interface: SessionInterface = SecureCookieSessionInterface()
 
 
     def __init__(
     def __init__(
         self,
         self,
@@ -436,7 +430,7 @@ class Flask(Scaffold):
         #: :meth:`before_first_request` decorator.
         #: :meth:`before_first_request` decorator.
         #:
         #:
         #: .. versionadded:: 0.8
         #: .. versionadded:: 0.8
-        self.before_first_request_funcs: t.List[BeforeFirstRequestCallable] = []
+        self.before_first_request_funcs: t.List[ft.BeforeFirstRequestCallable] = []
 
 
         #: A list of functions that are called when the application context
         #: A list of functions that are called when the application context
         #: is destroyed.  Since the application context is also torn down
         #: is destroyed.  Since the application context is also torn down
@@ -444,7 +438,7 @@ class Flask(Scaffold):
         #: from databases.
         #: from databases.
         #:
         #:
         #: .. versionadded:: 0.9
         #: .. versionadded:: 0.9
-        self.teardown_appcontext_funcs: t.List[TeardownCallable] = []
+        self.teardown_appcontext_funcs: t.List[ft.TeardownCallable] = []
 
 
         #: A list of shell context processor functions that should be run
         #: A list of shell context processor functions that should be run
         #: when a shell context is created.
         #: when a shell context is created.
@@ -1039,7 +1033,7 @@ class Flask(Scaffold):
         self,
         self,
         rule: str,
         rule: str,
         endpoint: t.Optional[str] = None,
         endpoint: t.Optional[str] = None,
-        view_func: t.Optional[t.Callable] = None,
+        view_func: t.Optional[ft.ViewCallable] = None,
         provide_automatic_options: t.Optional[bool] = None,
         provide_automatic_options: t.Optional[bool] = None,
         **options: t.Any,
         **options: t.Any,
     ) -> None:
     ) -> None:
@@ -1096,7 +1090,7 @@ class Flask(Scaffold):
     @setupmethod
     @setupmethod
     def template_filter(
     def template_filter(
         self, name: t.Optional[str] = None
         self, name: t.Optional[str] = None
-    ) -> t.Callable[[TemplateFilterCallable], TemplateFilterCallable]:
+    ) -> t.Callable[[ft.TemplateFilterCallable], ft.TemplateFilterCallable]:
         """A decorator that is used to register custom template filter.
         """A decorator that is used to register custom template filter.
         You can specify a name for the filter, otherwise the function
         You can specify a name for the filter, otherwise the function
         name will be used. Example::
         name will be used. Example::
@@ -1109,7 +1103,7 @@ class Flask(Scaffold):
                      function name will be used.
                      function name will be used.
         """
         """
 
 
-        def decorator(f: TemplateFilterCallable) -> TemplateFilterCallable:
+        def decorator(f: ft.TemplateFilterCallable) -> ft.TemplateFilterCallable:
             self.add_template_filter(f, name=name)
             self.add_template_filter(f, name=name)
             return f
             return f
 
 
@@ -1117,7 +1111,7 @@ class Flask(Scaffold):
 
 
     @setupmethod
     @setupmethod
     def add_template_filter(
     def add_template_filter(
-        self, f: TemplateFilterCallable, name: t.Optional[str] = None
+        self, f: ft.TemplateFilterCallable, name: t.Optional[str] = None
     ) -> None:
     ) -> None:
         """Register a custom template filter.  Works exactly like the
         """Register a custom template filter.  Works exactly like the
         :meth:`template_filter` decorator.
         :meth:`template_filter` decorator.
@@ -1130,7 +1124,7 @@ class Flask(Scaffold):
     @setupmethod
     @setupmethod
     def template_test(
     def template_test(
         self, name: t.Optional[str] = None
         self, name: t.Optional[str] = None
-    ) -> t.Callable[[TemplateTestCallable], TemplateTestCallable]:
+    ) -> t.Callable[[ft.TemplateTestCallable], ft.TemplateTestCallable]:
         """A decorator that is used to register custom template test.
         """A decorator that is used to register custom template test.
         You can specify a name for the test, otherwise the function
         You can specify a name for the test, otherwise the function
         name will be used. Example::
         name will be used. Example::
@@ -1150,7 +1144,7 @@ class Flask(Scaffold):
                      function name will be used.
                      function name will be used.
         """
         """
 
 
-        def decorator(f: TemplateTestCallable) -> TemplateTestCallable:
+        def decorator(f: ft.TemplateTestCallable) -> ft.TemplateTestCallable:
             self.add_template_test(f, name=name)
             self.add_template_test(f, name=name)
             return f
             return f
 
 
@@ -1158,7 +1152,7 @@ class Flask(Scaffold):
 
 
     @setupmethod
     @setupmethod
     def add_template_test(
     def add_template_test(
-        self, f: TemplateTestCallable, name: t.Optional[str] = None
+        self, f: ft.TemplateTestCallable, name: t.Optional[str] = None
     ) -> None:
     ) -> None:
         """Register a custom template test.  Works exactly like the
         """Register a custom template test.  Works exactly like the
         :meth:`template_test` decorator.
         :meth:`template_test` decorator.
@@ -1173,7 +1167,7 @@ class Flask(Scaffold):
     @setupmethod
     @setupmethod
     def template_global(
     def template_global(
         self, name: t.Optional[str] = None
         self, name: t.Optional[str] = None
-    ) -> t.Callable[[TemplateGlobalCallable], TemplateGlobalCallable]:
+    ) -> t.Callable[[ft.TemplateGlobalCallable], ft.TemplateGlobalCallable]:
         """A decorator that is used to register a custom template global function.
         """A decorator that is used to register a custom template global function.
         You can specify a name for the global function, otherwise the function
         You can specify a name for the global function, otherwise the function
         name will be used. Example::
         name will be used. Example::
@@ -1188,7 +1182,7 @@ class Flask(Scaffold):
                      function name will be used.
                      function name will be used.
         """
         """
 
 
-        def decorator(f: TemplateGlobalCallable) -> TemplateGlobalCallable:
+        def decorator(f: ft.TemplateGlobalCallable) -> ft.TemplateGlobalCallable:
             self.add_template_global(f, name=name)
             self.add_template_global(f, name=name)
             return f
             return f
 
 
@@ -1196,7 +1190,7 @@ class Flask(Scaffold):
 
 
     @setupmethod
     @setupmethod
     def add_template_global(
     def add_template_global(
-        self, f: TemplateGlobalCallable, name: t.Optional[str] = None
+        self, f: ft.TemplateGlobalCallable, name: t.Optional[str] = None
     ) -> None:
     ) -> None:
         """Register a custom template global function. Works exactly like the
         """Register a custom template global function. Works exactly like the
         :meth:`template_global` decorator.
         :meth:`template_global` decorator.
@@ -1210,8 +1204,8 @@ class Flask(Scaffold):
 
 
     @setupmethod
     @setupmethod
     def before_first_request(
     def before_first_request(
-        self, f: BeforeFirstRequestCallable
-    ) -> BeforeFirstRequestCallable:
+        self, f: ft.BeforeFirstRequestCallable
+    ) -> ft.BeforeFirstRequestCallable:
         """Registers a function to be run before the first request to this
         """Registers a function to be run before the first request to this
         instance of the application.
         instance of the application.
 
 
@@ -1224,7 +1218,7 @@ class Flask(Scaffold):
         return f
         return f
 
 
     @setupmethod
     @setupmethod
-    def teardown_appcontext(self, f: TeardownCallable) -> TeardownCallable:
+    def teardown_appcontext(self, f: ft.TeardownCallable) -> ft.TeardownCallable:
         """Registers a function to be called when the application context
         """Registers a function to be called when the application context
         ends.  These functions are typically also called when the request
         ends.  These functions are typically also called when the request
         context is popped.
         context is popped.
@@ -1265,9 +1259,7 @@ class Flask(Scaffold):
         self.shell_context_processors.append(f)
         self.shell_context_processors.append(f)
         return f
         return f
 
 
-    def _find_error_handler(
-        self, e: Exception
-    ) -> t.Optional["ErrorHandlerCallable[Exception]"]:
+    def _find_error_handler(self, e: Exception) -> t.Optional[ft.ErrorHandlerCallable]:
         """Return a registered error handler for an exception in this order:
         """Return a registered error handler for an exception in this order:
         blueprint handler for a specific code, app handler for a specific code,
         blueprint handler for a specific code, app handler for a specific code,
         blueprint handler for an exception class, app handler for an exception
         blueprint handler for an exception class, app handler for an exception
@@ -1292,7 +1284,7 @@ class Flask(Scaffold):
 
 
     def handle_http_exception(
     def handle_http_exception(
         self, e: HTTPException
         self, e: HTTPException
-    ) -> t.Union[HTTPException, ResponseReturnValue]:
+    ) -> t.Union[HTTPException, ft.ResponseReturnValue]:
         """Handles an HTTP exception.  By default this will invoke the
         """Handles an HTTP exception.  By default this will invoke the
         registered error handlers and fall back to returning the
         registered error handlers and fall back to returning the
         exception as response.
         exception as response.
@@ -1362,7 +1354,7 @@ class Flask(Scaffold):
 
 
     def handle_user_exception(
     def handle_user_exception(
         self, e: Exception
         self, e: Exception
-    ) -> t.Union[HTTPException, ResponseReturnValue]:
+    ) -> t.Union[HTTPException, ft.ResponseReturnValue]:
         """This method is called whenever an exception occurs that
         """This method is called whenever an exception occurs that
         should be handled. A special case is :class:`~werkzeug
         should be handled. A special case is :class:`~werkzeug
         .exceptions.HTTPException` which is forwarded to the
         .exceptions.HTTPException` which is forwarded to the
@@ -1432,7 +1424,7 @@ class Flask(Scaffold):
             raise e
             raise e
 
 
         self.log_exception(exc_info)
         self.log_exception(exc_info)
-        server_error: t.Union[InternalServerError, ResponseReturnValue]
+        server_error: t.Union[InternalServerError, ft.ResponseReturnValue]
         server_error = InternalServerError(original_exception=e)
         server_error = InternalServerError(original_exception=e)
         handler = self._find_error_handler(server_error)
         handler = self._find_error_handler(server_error)
 
 
@@ -1459,17 +1451,26 @@ class Flask(Scaffold):
         )
         )
 
 
     def raise_routing_exception(self, request: Request) -> "te.NoReturn":
     def raise_routing_exception(self, request: Request) -> "te.NoReturn":
-        """Exceptions that are recording during routing are reraised with
-        this method.  During debug we are not reraising redirect requests
-        for non ``GET``, ``HEAD``, or ``OPTIONS`` requests and we're raising
-        a different error instead to help debug situations.
+        """Intercept routing exceptions and possibly do something else.
+
+        In debug mode, intercept a routing redirect and replace it with
+        an error if the body will be discarded.
+
+        With modern Werkzeug this shouldn't occur, since it now uses a
+        308 status which tells the browser to resend the method and
+        body.
+
+        .. versionchanged:: 2.1
+            Don't intercept 307 and 308 redirects.
 
 
+        :meta private:
         :internal:
         :internal:
         """
         """
         if (
         if (
             not self.debug
             not self.debug
             or not isinstance(request.routing_exception, RequestRedirect)
             or not isinstance(request.routing_exception, RequestRedirect)
-            or request.method in ("GET", "HEAD", "OPTIONS")
+            or request.routing_exception.code in {307, 308}
+            or request.method in {"GET", "HEAD", "OPTIONS"}
         ):
         ):
             raise request.routing_exception  # type: ignore
             raise request.routing_exception  # type: ignore
 
 
@@ -1477,7 +1478,7 @@ class Flask(Scaffold):
 
 
         raise FormDataRoutingRedirect(request)
         raise FormDataRoutingRedirect(request)
 
 
-    def dispatch_request(self) -> ResponseReturnValue:
+    def dispatch_request(self) -> ft.ResponseReturnValue:
         """Does the request dispatching.  Matches the URL and returns the
         """Does the request dispatching.  Matches the URL and returns the
         return value of the view or error handler.  This does not have to
         return value of the view or error handler.  This does not have to
         be a response object.  In order to convert the return value to a
         be a response object.  In order to convert the return value to a
@@ -1520,7 +1521,7 @@ class Flask(Scaffold):
 
 
     def finalize_request(
     def finalize_request(
         self,
         self,
-        rv: t.Union[ResponseReturnValue, HTTPException],
+        rv: t.Union[ft.ResponseReturnValue, HTTPException],
         from_error_handler: bool = False,
         from_error_handler: bool = False,
     ) -> Response:
     ) -> Response:
         """Given the return value from a view function this finalizes
         """Given the return value from a view function this finalizes
@@ -1621,16 +1622,9 @@ class Flask(Scaffold):
                 "Install Flask with the 'async' extra in order to use async views."
                 "Install Flask with the 'async' extra in order to use async views."
             ) from None
             ) from None
 
 
-        # Check that Werkzeug isn't using its fallback ContextVar class.
-        if ContextVar.__module__ == "werkzeug.local":
-            raise RuntimeError(
-                "Async cannot be used with this combination of Python "
-                "and Greenlet versions."
-            )
-
         return asgiref_async_to_sync(func)
         return asgiref_async_to_sync(func)
 
 
-    def make_response(self, rv: ResponseReturnValue) -> Response:
+    def make_response(self, rv: ft.ResponseReturnValue) -> Response:
         """Convert the return value from a view function to an instance of
         """Convert the return value from a view function to an instance of
         :attr:`response_class`.
         :attr:`response_class`.
 
 
@@ -1681,13 +1675,13 @@ class Flask(Scaffold):
 
 
             # a 3-tuple is unpacked directly
             # a 3-tuple is unpacked directly
             if len_rv == 3:
             if len_rv == 3:
-                rv, status, headers = rv
+                rv, status, headers = rv  # type: ignore[misc]
             # decide if a 2-tuple has status or headers
             # decide if a 2-tuple has status or headers
             elif len_rv == 2:
             elif len_rv == 2:
                 if isinstance(rv[1], (Headers, dict, tuple, list)):
                 if isinstance(rv[1], (Headers, dict, tuple, list)):
                     rv, headers = rv
                     rv, headers = rv
                 else:
                 else:
-                    rv, status = rv
+                    rv, status = rv  # type: ignore[assignment,misc]
             # other sized tuples are not allowed
             # other sized tuples are not allowed
             else:
             else:
                 raise TypeError(
                 raise TypeError(
@@ -1710,7 +1704,11 @@ class Flask(Scaffold):
                 # 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
-                rv = self.response_class(rv, status=status, headers=headers)
+                rv = self.response_class(
+                    rv,
+                    status=status,
+                    headers=headers,  # type: ignore[arg-type]
+                )
                 status = headers = None
                 status = headers = None
             elif isinstance(rv, dict):
             elif isinstance(rv, dict):
                 rv = jsonify(rv)
                 rv = jsonify(rv)
@@ -1718,7 +1716,9 @@ class Flask(Scaffold):
                 # evaluate a WSGI callable, or coerce a different response
                 # evaluate a WSGI callable, or coerce a different response
                 # class to the correct type
                 # class to the correct type
                 try:
                 try:
-                    rv = self.response_class.force_type(rv, request.environ)  # type: ignore  # noqa: B950
+                    rv = self.response_class.force_type(
+                        rv, request.environ  # type: ignore[arg-type]
+                    )
                 except TypeError as e:
                 except TypeError as e:
                     raise TypeError(
                     raise TypeError(
                         f"{e}\nThe view function did not return a valid"
                         f"{e}\nThe view function did not return a valid"
@@ -1738,13 +1738,13 @@ class Flask(Scaffold):
         # 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, (str, bytes, bytearray)):
             if isinstance(status, (str, bytes, bytearray)):
-                rv.status = status  # type: ignore
+                rv.status = status
             else:
             else:
                 rv.status_code = status
                 rv.status_code = status
 
 
         # extend existing headers with provided headers
         # extend existing headers with provided headers
         if headers:
         if headers:
-            rv.headers.update(headers)
+            rv.headers.update(headers)  # type: ignore[arg-type]
 
 
         return rv
         return rv
 
 
@@ -1834,7 +1834,7 @@ class Flask(Scaffold):
 
 
         raise error
         raise error
 
 
-    def preprocess_request(self) -> t.Optional[ResponseReturnValue]:
+    def preprocess_request(self) -> t.Optional[ft.ResponseReturnValue]:
         """Called before the request is dispatched. Calls
         """Called before the request is dispatched. Calls
         :attr:`url_value_preprocessors` registered with the app and the
         :attr:`url_value_preprocessors` registered with the app and the
         current blueprint (if any). Then calls :attr:`before_request_funcs`
         current blueprint (if any). Then calls :attr:`before_request_funcs`

+ 33 - 51
contrib/python/Flask/py3/flask/blueprints.py

@@ -3,23 +3,13 @@ import typing as t
 from collections import defaultdict
 from collections import defaultdict
 from functools import update_wrapper
 from functools import update_wrapper
 
 
+from . import typing as ft
 from .scaffold import _endpoint_from_view_func
 from .scaffold import _endpoint_from_view_func
 from .scaffold import _sentinel
 from .scaffold import _sentinel
 from .scaffold import Scaffold
 from .scaffold import Scaffold
-from .typing import AfterRequestCallable
-from .typing import BeforeFirstRequestCallable
-from .typing import BeforeRequestCallable
-from .typing import TeardownCallable
-from .typing import TemplateContextProcessorCallable
-from .typing import TemplateFilterCallable
-from .typing import TemplateGlobalCallable
-from .typing import TemplateTestCallable
-from .typing import URLDefaultCallable
-from .typing import URLValuePreprocessorCallable
 
 
 if t.TYPE_CHECKING:
 if t.TYPE_CHECKING:
     from .app import Flask
     from .app import Flask
-    from .typing import ErrorHandlerCallable
 
 
 DeferredSetupFunction = t.Callable[["BlueprintSetupState"], t.Callable]
 DeferredSetupFunction = t.Callable[["BlueprintSetupState"], t.Callable]
 
 
@@ -299,24 +289,14 @@ class Blueprint(Scaffold):
         name = f"{name_prefix}.{self_name}".lstrip(".")
         name = f"{name_prefix}.{self_name}".lstrip(".")
 
 
         if name in app.blueprints:
         if name in app.blueprints:
+            bp_desc = "this" if app.blueprints[name] is self else "a different"
             existing_at = f" '{name}'" if self_name != name else ""
             existing_at = f" '{name}'" if self_name != name else ""
 
 
-            if app.blueprints[name] is not self:
-                raise ValueError(
-                    f"The name '{self_name}' is already registered for"
-                    f" a different blueprint{existing_at}. Use 'name='"
-                    " to provide a unique name."
-                )
-            else:
-                import warnings
-
-                warnings.warn(
-                    f"The name '{self_name}' is already registered for"
-                    f" this blueprint{existing_at}. Use 'name=' to"
-                    " provide a unique name. This will become an error"
-                    " in Flask 2.1.",
-                    stacklevel=4,
-                )
+            raise ValueError(
+                f"The name '{self_name}' is already registered for"
+                f" {bp_desc} blueprint{existing_at}. Use 'name=' to"
+                f" provide a unique name."
+            )
 
 
         first_bp_registration = not any(bp is self for bp in app.blueprints.values())
         first_bp_registration = not any(bp is self for bp in app.blueprints.values())
         first_name_registration = name not in app.blueprints
         first_name_registration = name not in app.blueprints
@@ -404,7 +384,7 @@ class Blueprint(Scaffold):
         self,
         self,
         rule: str,
         rule: str,
         endpoint: t.Optional[str] = None,
         endpoint: t.Optional[str] = None,
-        view_func: t.Optional[t.Callable] = None,
+        view_func: t.Optional[ft.ViewCallable] = None,
         provide_automatic_options: t.Optional[bool] = None,
         provide_automatic_options: t.Optional[bool] = None,
         **options: t.Any,
         **options: t.Any,
     ) -> None:
     ) -> None:
@@ -429,7 +409,7 @@ class Blueprint(Scaffold):
 
 
     def app_template_filter(
     def app_template_filter(
         self, name: t.Optional[str] = None
         self, name: t.Optional[str] = None
-    ) -> t.Callable[[TemplateFilterCallable], TemplateFilterCallable]:
+    ) -> t.Callable[[ft.TemplateFilterCallable], ft.TemplateFilterCallable]:
         """Register a custom template filter, available application wide.  Like
         """Register a custom template filter, available application wide.  Like
         :meth:`Flask.template_filter` but for a blueprint.
         :meth:`Flask.template_filter` but for a blueprint.
 
 
@@ -437,14 +417,14 @@ class Blueprint(Scaffold):
                      function name will be used.
                      function name will be used.
         """
         """
 
 
-        def decorator(f: TemplateFilterCallable) -> TemplateFilterCallable:
+        def decorator(f: ft.TemplateFilterCallable) -> ft.TemplateFilterCallable:
             self.add_app_template_filter(f, name=name)
             self.add_app_template_filter(f, name=name)
             return f
             return f
 
 
         return decorator
         return decorator
 
 
     def add_app_template_filter(
     def add_app_template_filter(
-        self, f: TemplateFilterCallable, name: t.Optional[str] = None
+        self, f: ft.TemplateFilterCallable, name: t.Optional[str] = None
     ) -> None:
     ) -> None:
         """Register a custom template filter, available application wide.  Like
         """Register a custom template filter, available application wide.  Like
         :meth:`Flask.add_template_filter` but for a blueprint.  Works exactly
         :meth:`Flask.add_template_filter` but for a blueprint.  Works exactly
@@ -461,7 +441,7 @@ class Blueprint(Scaffold):
 
 
     def app_template_test(
     def app_template_test(
         self, name: t.Optional[str] = None
         self, name: t.Optional[str] = None
-    ) -> t.Callable[[TemplateTestCallable], TemplateTestCallable]:
+    ) -> t.Callable[[ft.TemplateTestCallable], ft.TemplateTestCallable]:
         """Register a custom template test, available application wide.  Like
         """Register a custom template test, available application wide.  Like
         :meth:`Flask.template_test` but for a blueprint.
         :meth:`Flask.template_test` but for a blueprint.
 
 
@@ -471,14 +451,14 @@ class Blueprint(Scaffold):
                      function name will be used.
                      function name will be used.
         """
         """
 
 
-        def decorator(f: TemplateTestCallable) -> TemplateTestCallable:
+        def decorator(f: ft.TemplateTestCallable) -> ft.TemplateTestCallable:
             self.add_app_template_test(f, name=name)
             self.add_app_template_test(f, name=name)
             return f
             return f
 
 
         return decorator
         return decorator
 
 
     def add_app_template_test(
     def add_app_template_test(
-        self, f: TemplateTestCallable, name: t.Optional[str] = None
+        self, f: ft.TemplateTestCallable, name: t.Optional[str] = None
     ) -> None:
     ) -> None:
         """Register a custom template test, available application wide.  Like
         """Register a custom template test, available application wide.  Like
         :meth:`Flask.add_template_test` but for a blueprint.  Works exactly
         :meth:`Flask.add_template_test` but for a blueprint.  Works exactly
@@ -497,7 +477,7 @@ class Blueprint(Scaffold):
 
 
     def app_template_global(
     def app_template_global(
         self, name: t.Optional[str] = None
         self, name: t.Optional[str] = None
-    ) -> t.Callable[[TemplateGlobalCallable], TemplateGlobalCallable]:
+    ) -> t.Callable[[ft.TemplateGlobalCallable], ft.TemplateGlobalCallable]:
         """Register a custom template global, available application wide.  Like
         """Register a custom template global, available application wide.  Like
         :meth:`Flask.template_global` but for a blueprint.
         :meth:`Flask.template_global` but for a blueprint.
 
 
@@ -507,14 +487,14 @@ class Blueprint(Scaffold):
                      function name will be used.
                      function name will be used.
         """
         """
 
 
-        def decorator(f: TemplateGlobalCallable) -> TemplateGlobalCallable:
+        def decorator(f: ft.TemplateGlobalCallable) -> ft.TemplateGlobalCallable:
             self.add_app_template_global(f, name=name)
             self.add_app_template_global(f, name=name)
             return f
             return f
 
 
         return decorator
         return decorator
 
 
     def add_app_template_global(
     def add_app_template_global(
-        self, f: TemplateGlobalCallable, name: t.Optional[str] = None
+        self, f: ft.TemplateGlobalCallable, name: t.Optional[str] = None
     ) -> None:
     ) -> None:
         """Register a custom template global, available application wide.  Like
         """Register a custom template global, available application wide.  Like
         :meth:`Flask.add_template_global` but for a blueprint.  Works exactly
         :meth:`Flask.add_template_global` but for a blueprint.  Works exactly
@@ -531,7 +511,9 @@ class Blueprint(Scaffold):
 
 
         self.record_once(register_template)
         self.record_once(register_template)
 
 
-    def before_app_request(self, f: BeforeRequestCallable) -> BeforeRequestCallable:
+    def before_app_request(
+        self, f: ft.BeforeRequestCallable
+    ) -> ft.BeforeRequestCallable:
         """Like :meth:`Flask.before_request`.  Such a function is executed
         """Like :meth:`Flask.before_request`.  Such a function is executed
         before each request, even if outside of a blueprint.
         before each request, even if outside of a blueprint.
         """
         """
@@ -541,15 +523,15 @@ class Blueprint(Scaffold):
         return f
         return f
 
 
     def before_app_first_request(
     def before_app_first_request(
-        self, f: BeforeFirstRequestCallable
-    ) -> BeforeFirstRequestCallable:
+        self, f: ft.BeforeFirstRequestCallable
+    ) -> ft.BeforeFirstRequestCallable:
         """Like :meth:`Flask.before_first_request`.  Such a function is
         """Like :meth:`Flask.before_first_request`.  Such a function is
         executed before the first request to the application.
         executed before the first request to the application.
         """
         """
         self.record_once(lambda s: s.app.before_first_request_funcs.append(f))
         self.record_once(lambda s: s.app.before_first_request_funcs.append(f))
         return f
         return f
 
 
-    def after_app_request(self, f: AfterRequestCallable) -> AfterRequestCallable:
+    def after_app_request(self, f: ft.AfterRequestCallable) -> ft.AfterRequestCallable:
         """Like :meth:`Flask.after_request` but for a blueprint.  Such a function
         """Like :meth:`Flask.after_request` but for a blueprint.  Such a function
         is executed after each request, even if outside of the blueprint.
         is executed after each request, even if outside of the blueprint.
         """
         """
@@ -558,7 +540,7 @@ class Blueprint(Scaffold):
         )
         )
         return f
         return f
 
 
-    def teardown_app_request(self, f: TeardownCallable) -> TeardownCallable:
+    def teardown_app_request(self, f: ft.TeardownCallable) -> ft.TeardownCallable:
         """Like :meth:`Flask.teardown_request` but for a blueprint.  Such a
         """Like :meth:`Flask.teardown_request` but for a blueprint.  Such a
         function is executed when tearing down each request, even if outside of
         function is executed when tearing down each request, even if outside of
         the blueprint.
         the blueprint.
@@ -569,8 +551,8 @@ class Blueprint(Scaffold):
         return f
         return f
 
 
     def app_context_processor(
     def app_context_processor(
-        self, f: TemplateContextProcessorCallable
-    ) -> TemplateContextProcessorCallable:
+        self, f: ft.TemplateContextProcessorCallable
+    ) -> ft.TemplateContextProcessorCallable:
         """Like :meth:`Flask.context_processor` but for a blueprint.  Such a
         """Like :meth:`Flask.context_processor` but for a blueprint.  Such a
         function is executed each request, even if outside of the blueprint.
         function is executed each request, even if outside of the blueprint.
         """
         """
@@ -579,29 +561,29 @@ class Blueprint(Scaffold):
         )
         )
         return f
         return f
 
 
-    def app_errorhandler(self, code: t.Union[t.Type[Exception], int]) -> t.Callable:
+    def app_errorhandler(
+        self, code: t.Union[t.Type[Exception], int]
+    ) -> t.Callable[[ft.ErrorHandlerDecorator], ft.ErrorHandlerDecorator]:
         """Like :meth:`Flask.errorhandler` but for a blueprint.  This
         """Like :meth:`Flask.errorhandler` but for a blueprint.  This
         handler is used for all requests, even if outside of the blueprint.
         handler is used for all requests, even if outside of the blueprint.
         """
         """
 
 
-        def decorator(
-            f: "ErrorHandlerCallable[Exception]",
-        ) -> "ErrorHandlerCallable[Exception]":
+        def decorator(f: ft.ErrorHandlerDecorator) -> ft.ErrorHandlerDecorator:
             self.record_once(lambda s: s.app.errorhandler(code)(f))
             self.record_once(lambda s: s.app.errorhandler(code)(f))
             return f
             return f
 
 
         return decorator
         return decorator
 
 
     def app_url_value_preprocessor(
     def app_url_value_preprocessor(
-        self, f: URLValuePreprocessorCallable
-    ) -> URLValuePreprocessorCallable:
+        self, f: ft.URLValuePreprocessorCallable
+    ) -> ft.URLValuePreprocessorCallable:
         """Same as :meth:`url_value_preprocessor` but application wide."""
         """Same as :meth:`url_value_preprocessor` but application wide."""
         self.record_once(
         self.record_once(
             lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f)
             lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f)
         )
         )
         return f
         return f
 
 
-    def app_url_defaults(self, f: URLDefaultCallable) -> URLDefaultCallable:
+    def app_url_defaults(self, f: ft.URLDefaultCallable) -> ft.URLDefaultCallable:
         """Same as :meth:`url_defaults` but application wide."""
         """Same as :meth:`url_defaults` but application wide."""
         self.record_once(
         self.record_once(
             lambda s: s.app.url_default_functions.setdefault(None, []).append(f)
             lambda s: s.app.url_default_functions.setdefault(None, []).append(f)

+ 70 - 79
contrib/python/Flask/py3/flask/cli.py

@@ -5,7 +5,6 @@ import platform
 import re
 import re
 import sys
 import sys
 import traceback
 import traceback
-import warnings
 from functools import update_wrapper
 from functools import update_wrapper
 from operator import attrgetter
 from operator import attrgetter
 from threading import Lock
 from threading import Lock
@@ -19,22 +18,12 @@ from .helpers import get_debug_flag
 from .helpers import get_env
 from .helpers import get_env
 from .helpers import get_load_dotenv
 from .helpers import get_load_dotenv
 
 
-try:
-    import dotenv
-except ImportError:
-    dotenv = None
-
-try:
-    import ssl
-except ImportError:
-    ssl = None  # type: ignore
-
 
 
 class NoAppException(click.UsageError):
 class NoAppException(click.UsageError):
     """Raised if an application cannot be found or loaded."""
     """Raised if an application cannot be found or loaded."""
 
 
 
 
-def find_best_app(script_info, module):
+def find_best_app(module):
     """Given a module instance this tries to find the best possible
     """Given a module instance this tries to find the best possible
     application in the module or raises an exception.
     application in the module or raises an exception.
     """
     """
@@ -65,7 +54,7 @@ def find_best_app(script_info, module):
 
 
         if inspect.isfunction(app_factory):
         if inspect.isfunction(app_factory):
             try:
             try:
-                app = call_factory(script_info, app_factory)
+                app = app_factory()
 
 
                 if isinstance(app, Flask):
                 if isinstance(app, Flask):
                     return app
                     return app
@@ -87,42 +76,6 @@ def find_best_app(script_info, module):
     )
     )
 
 
 
 
-def call_factory(script_info, app_factory, args=None, kwargs=None):
-    """Takes an app factory, a ``script_info` object and  optionally a tuple
-    of arguments. Checks for the existence of a script_info argument and calls
-    the app_factory depending on that and the arguments provided.
-    """
-    sig = inspect.signature(app_factory)
-    args = [] if args is None else args
-    kwargs = {} if kwargs is None else kwargs
-
-    if "script_info" in sig.parameters:
-        warnings.warn(
-            "The 'script_info' argument is deprecated and will not be"
-            " passed to the app factory function in Flask 2.1.",
-            DeprecationWarning,
-        )
-        kwargs["script_info"] = script_info
-
-    if not args and len(sig.parameters) == 1:
-        first_parameter = next(iter(sig.parameters.values()))
-
-        if (
-            first_parameter.default is inspect.Parameter.empty
-            # **kwargs is reported as an empty default, ignore it
-            and first_parameter.kind is not inspect.Parameter.VAR_KEYWORD
-        ):
-            warnings.warn(
-                "Script info is deprecated and will not be passed as the"
-                " single argument to the app factory function in Flask"
-                " 2.1.",
-                DeprecationWarning,
-            )
-            args.append(script_info)
-
-    return app_factory(*args, **kwargs)
-
-
 def _called_with_wrong_args(f):
 def _called_with_wrong_args(f):
     """Check whether calling a function raised a ``TypeError`` because
     """Check whether calling a function raised a ``TypeError`` because
     the call failed or because something in the factory raised the
     the call failed or because something in the factory raised the
@@ -149,7 +102,7 @@ def _called_with_wrong_args(f):
         del tb
         del tb
 
 
 
 
-def find_app_by_string(script_info, module, app_name):
+def find_app_by_string(module, app_name):
     """Check if the given string is a variable name or a function. Call
     """Check if the given string is a variable name or a function. Call
     a function to get the app instance, or return the variable directly.
     a function to get the app instance, or return the variable directly.
     """
     """
@@ -166,7 +119,8 @@ def find_app_by_string(script_info, module, app_name):
 
 
     if isinstance(expr, ast.Name):
     if isinstance(expr, ast.Name):
         name = expr.id
         name = expr.id
-        args = kwargs = None
+        args = []
+        kwargs = {}
     elif isinstance(expr, ast.Call):
     elif isinstance(expr, ast.Call):
         # Ensure the function name is an attribute name only.
         # Ensure the function name is an attribute name only.
         if not isinstance(expr.func, ast.Name):
         if not isinstance(expr.func, ast.Name):
@@ -202,7 +156,7 @@ def find_app_by_string(script_info, module, app_name):
     # to get the real application.
     # to get the real application.
     if inspect.isfunction(attr):
     if inspect.isfunction(attr):
         try:
         try:
-            app = call_factory(script_info, attr, args, kwargs)
+            app = attr(*args, **kwargs)
         except TypeError as e:
         except TypeError as e:
             if not _called_with_wrong_args(attr):
             if not _called_with_wrong_args(attr):
                 raise
                 raise
@@ -253,7 +207,7 @@ def prepare_import(path):
     return ".".join(module_name[::-1])
     return ".".join(module_name[::-1])
 
 
 
 
-def locate_app(script_info, module_name, app_name, raise_if_not_found=True):
+def locate_app(module_name, app_name, raise_if_not_found=True):
     __traceback_hide__ = True  # noqa: F841
     __traceback_hide__ = True  # noqa: F841
 
 
     try:
     try:
@@ -274,9 +228,9 @@ def locate_app(script_info, module_name, app_name, raise_if_not_found=True):
     module = sys.modules[module_name]
     module = sys.modules[module_name]
 
 
     if app_name is None:
     if app_name is None:
-        return find_best_app(script_info, module)
+        return find_best_app(module)
     else:
     else:
-        return find_app_by_string(script_info, module, app_name)
+        return find_app_by_string(module, app_name)
 
 
 
 
 def get_version(ctx, param, value):
 def get_version(ctx, param, value):
@@ -327,9 +281,17 @@ class DispatchingApp:
             self._load_in_background()
             self._load_in_background()
 
 
     def _load_in_background(self):
     def _load_in_background(self):
+        # Store the Click context and push it in the loader thread so
+        # script_info is still available.
+        ctx = click.get_current_context(silent=True)
+
         def _load_app():
         def _load_app():
             __traceback_hide__ = True  # noqa: F841
             __traceback_hide__ = True  # noqa: F841
+
             with self._lock:
             with self._lock:
+                if ctx is not None:
+                    click.globals.push_context(ctx)
+
                 try:
                 try:
                     self._load_unlocked()
                     self._load_unlocked()
                 except Exception as e:
                 except Exception as e:
@@ -397,18 +359,18 @@ class ScriptInfo:
             return self._loaded_app
             return self._loaded_app
 
 
         if self.create_app is not None:
         if self.create_app is not None:
-            app = call_factory(self, self.create_app)
+            app = self.create_app()
         else:
         else:
             if self.app_import_path:
             if self.app_import_path:
                 path, name = (
                 path, name = (
                     re.split(r":(?![\\/])", self.app_import_path, 1) + [None]
                     re.split(r":(?![\\/])", self.app_import_path, 1) + [None]
                 )[:2]
                 )[:2]
                 import_name = prepare_import(path)
                 import_name = prepare_import(path)
-                app = locate_app(self, import_name, name)
+                app = locate_app(import_name, name)
             else:
             else:
                 for path in ("wsgi.py", "app.py"):
                 for path in ("wsgi.py", "app.py"):
                     import_name = prepare_import(path)
                     import_name = prepare_import(path)
-                    app = locate_app(self, import_name, None, raise_if_not_found=False)
+                    app = locate_app(import_name, None, raise_if_not_found=False)
 
 
                     if app:
                     if app:
                         break
                         break
@@ -530,14 +492,18 @@ class FlaskGroup(AppGroup):
     def _load_plugin_commands(self):
     def _load_plugin_commands(self):
         if self._loaded_plugin_commands:
         if self._loaded_plugin_commands:
             return
             return
-        try:
-            import pkg_resources
-        except ImportError:
-            self._loaded_plugin_commands = True
-            return
 
 
-        for ep in pkg_resources.iter_entry_points("flask.commands"):
+        if sys.version_info >= (3, 10):
+            from importlib import metadata
+        else:
+            # Use a backport on Python < 3.10. We technically have
+            # importlib.metadata on 3.8+, but the API changed in 3.10,
+            # so use the backport for consistency.
+            import importlib_metadata as metadata
+
+        for ep in metadata.entry_points(group="flask.commands"):
             self.add_command(ep.load(), ep.name)
             self.add_command(ep.load(), ep.name)
+
         self._loaded_plugin_commands = True
         self._loaded_plugin_commands = True
 
 
     def get_command(self, ctx, name):
     def get_command(self, ctx, name):
@@ -630,7 +596,9 @@ def load_dotenv(path=None):
 
 
     .. versionadded:: 1.0
     .. versionadded:: 1.0
     """
     """
-    if dotenv is None:
+    try:
+        import dotenv
+    except ImportError:
         if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"):
         if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"):
             click.secho(
             click.secho(
                 " * Tip: There are .env or .flaskenv files present."
                 " * Tip: There are .env or .flaskenv files present."
@@ -706,12 +674,14 @@ class CertParamType(click.ParamType):
         self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True)
         self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True)
 
 
     def convert(self, value, param, ctx):
     def convert(self, value, param, ctx):
-        if ssl is None:
+        try:
+            import ssl
+        except ImportError:
             raise click.BadParameter(
             raise click.BadParameter(
                 'Using "--cert" requires Python to be compiled with SSL support.',
                 'Using "--cert" requires Python to be compiled with SSL support.',
                 ctx,
                 ctx,
                 param,
                 param,
-            )
+            ) from None
 
 
         try:
         try:
             return self.path_type(value, param, ctx)
             return self.path_type(value, param, ctx)
@@ -744,7 +714,13 @@ 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)
+
+    try:
+        import ssl
+    except ImportError:
+        is_context = False
+    else:
+        is_context = isinstance(cert, ssl.SSLContext)
 
 
     if value is not None:
     if value is not None:
         if is_adhoc:
         if is_adhoc:
@@ -785,7 +761,10 @@ class SeparatedPathType(click.Path):
 @click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.")
 @click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.")
 @click.option("--port", "-p", default=5000, help="The port to bind to.")
 @click.option("--port", "-p", default=5000, help="The port to bind to.")
 @click.option(
 @click.option(
-    "--cert", type=CertParamType(), help="Specify a certificate file to use HTTPS."
+    "--cert",
+    type=CertParamType(),
+    help="Specify a certificate file to use HTTPS.",
+    is_eager=True,
 )
 )
 @click.option(
 @click.option(
     "--key",
     "--key",
@@ -826,9 +805,28 @@ class SeparatedPathType(click.Path):
         f" are separated by {os.path.pathsep!r}."
         f" are separated by {os.path.pathsep!r}."
     ),
     ),
 )
 )
+@click.option(
+    "--exclude-patterns",
+    default=None,
+    type=SeparatedPathType(),
+    help=(
+        "Files matching these fnmatch patterns will not trigger a reload"
+        " on change. Multiple patterns are separated by"
+        f" {os.path.pathsep!r}."
+    ),
+)
 @pass_script_info
 @pass_script_info
 def run_command(
 def run_command(
-    info, host, port, reload, debugger, eager_loading, with_threads, cert, extra_files
+    info,
+    host,
+    port,
+    reload,
+    debugger,
+    eager_loading,
+    with_threads,
+    cert,
+    extra_files,
+    exclude_patterns,
 ):
 ):
     """Run a local development server.
     """Run a local development server.
 
 
@@ -860,6 +858,7 @@ def run_command(
         threaded=with_threads,
         threaded=with_threads,
         ssl_context=cert,
         ssl_context=cert,
         extra_files=extra_files,
         extra_files=extra_files,
+        exclude_patterns=exclude_patterns,
     )
     )
 
 
 
 
@@ -984,15 +983,7 @@ debug mode.
 
 
 
 
 def main() -> None:
 def main() -> None:
-    if int(click.__version__[0]) < 8:
-        warnings.warn(
-            "Using the `flask` cli with Click 7 is deprecated and"
-            " will not be supported starting with Flask 2.1."
-            " Please upgrade to Click 8 as soon as possible.",
-            DeprecationWarning,
-        )
-    # TODO omit sys.argv once https://github.com/pallets/click/issues/536 is fixed
-    cli.main(args=sys.argv[1:])
+    cli.main()
 
 
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":

+ 69 - 27
contrib/python/Flask/py3/flask/config.py

@@ -1,4 +1,5 @@
 import errno
 import errno
+import json
 import os
 import os
 import types
 import types
 import typing as t
 import typing as t
@@ -70,7 +71,7 @@ class Config(dict):
     """
     """
 
 
     def __init__(self, root_path: str, defaults: t.Optional[dict] = None) -> None:
     def __init__(self, root_path: str, defaults: t.Optional[dict] = None) -> None:
-        dict.__init__(self, defaults or {})
+        super().__init__(defaults or {})
         self.root_path = root_path
         self.root_path = root_path
 
 
     def from_envvar(self, variable_name: str, silent: bool = False) -> bool:
     def from_envvar(self, variable_name: str, silent: bool = False) -> bool:
@@ -97,6 +98,70 @@ class Config(dict):
             )
             )
         return self.from_pyfile(rv, silent=silent)
         return self.from_pyfile(rv, silent=silent)
 
 
+    def from_prefixed_env(
+        self, prefix: str = "FLASK", *, loads: t.Callable[[str], t.Any] = json.loads
+    ) -> bool:
+        """Load any environment variables that start with ``FLASK_``,
+        dropping the prefix from the env key for the config key. Values
+        are passed through a loading function to attempt to convert them
+        to more specific types than strings.
+
+        Keys are loaded in :func:`sorted` order.
+
+        The default loading function attempts to parse values as any
+        valid JSON type, including dicts and lists.
+
+        Specific items in nested dicts can be set by separating the
+        keys with double underscores (``__``). If an intermediate key
+        doesn't exist, it will be initialized to an empty dict.
+
+        :param prefix: Load env vars that start with this prefix,
+            separated with an underscore (``_``).
+        :param loads: Pass each string value to this function and use
+            the returned value as the config value. If any error is
+            raised it is ignored and the value remains a string. The
+            default is :func:`json.loads`.
+
+        .. versionadded:: 2.1
+        """
+        prefix = f"{prefix}_"
+        len_prefix = len(prefix)
+
+        for key in sorted(os.environ):
+            if not key.startswith(prefix):
+                continue
+
+            value = os.environ[key]
+
+            try:
+                value = loads(value)
+            except Exception:
+                # Keep the value as a string if loading failed.
+                pass
+
+            # Change to key.removeprefix(prefix) on Python >= 3.9.
+            key = key[len_prefix:]
+
+            if "__" not in key:
+                # A non-nested key, set directly.
+                self[key] = value
+                continue
+
+            # Traverse nested dictionaries with keys separated by "__".
+            current = self
+            *parts, tail = key.split("__")
+
+            for part in parts:
+                # If an intermediate dict does not exist, create it.
+                if part not in current:
+                    current[part] = {}
+
+                current = current[part]
+
+            current[tail] = value
+
+        return True
+
     def from_pyfile(self, filename: str, silent: bool = False) -> bool:
     def from_pyfile(self, filename: str, silent: bool = False) -> bool:
         """Updates the values in the config from a Python file.  This function
         """Updates the values in the config from a Python file.  This function
         behaves as if the file was imported as module with the
         behaves as if the file was imported as module with the
@@ -176,6 +241,9 @@ class Config(dict):
 
 
         .. code-block:: python
         .. code-block:: python
 
 
+            import json
+            app.config.from_file("config.json", load=json.load)
+
             import toml
             import toml
             app.config.from_file("config.toml", load=toml.load)
             app.config.from_file("config.toml", load=toml.load)
 
 
@@ -204,32 +272,6 @@ class Config(dict):
 
 
         return self.from_mapping(obj)
         return self.from_mapping(obj)
 
 
-    def from_json(self, filename: str, silent: bool = False) -> bool:
-        """Update the values in the config from a JSON file. The loaded
-        data is passed to the :meth:`from_mapping` method.
-
-        :param filename: The path to the JSON file. This can be an
-            absolute path or relative to the config root path.
-        :param silent: Ignore the file if it doesn't exist.
-        :return: ``True`` if the file was loaded successfully.
-
-        .. deprecated:: 2.0.0
-            Will be removed in Flask 2.1. Use :meth:`from_file` instead.
-            This was removed early in 2.0.0, was added back in 2.0.1.
-
-        .. versionadded:: 0.11
-        """
-        import warnings
-        from . import json
-
-        warnings.warn(
-            "'from_json' is deprecated and will be removed in Flask"
-            " 2.1. Use 'from_file(path, json.load)' instead.",
-            DeprecationWarning,
-            stacklevel=2,
-        )
-        return self.from_file(filename, json.load, silent=silent)
-
     def from_mapping(
     def from_mapping(
         self, mapping: t.Optional[t.Mapping[str, t.Any]] = None, **kwargs: t.Any
         self, mapping: t.Optional[t.Mapping[str, t.Any]] = None, **kwargs: t.Any
     ) -> bool:
     ) -> bool:

+ 32 - 8
contrib/python/Flask/py3/flask/ctx.py

@@ -5,11 +5,11 @@ from types import TracebackType
 
 
 from werkzeug.exceptions import HTTPException
 from werkzeug.exceptions import HTTPException
 
 
+from . import typing as ft
 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
 from .signals import appcontext_pushed
 from .signals import appcontext_pushed
-from .typing import AfterRequestCallable
 
 
 if t.TYPE_CHECKING:
 if t.TYPE_CHECKING:
     from .app import Flask
     from .app import Flask
@@ -109,7 +109,7 @@ class _AppCtxGlobals:
         return object.__repr__(self)
         return object.__repr__(self)
 
 
 
 
-def after_this_request(f: AfterRequestCallable) -> AfterRequestCallable:
+def after_this_request(f: ft.AfterRequestCallable) -> ft.AfterRequestCallable:
     """Executes a function after this request.  This is useful to modify
     """Executes a function after this request.  This is useful to modify
     response objects.  The function is passed the response object and has
     response objects.  The function is passed the response object and has
     to return the same or a new one.
     to return the same or a new one.
@@ -178,7 +178,7 @@ def copy_current_request_context(f: t.Callable) -> t.Callable:
 
 
     def wrapper(*args, **kwargs):
     def wrapper(*args, **kwargs):
         with reqctx:
         with reqctx:
-            return f(*args, **kwargs)
+            return reqctx.app.ensure_sync(f)(*args, **kwargs)
 
 
     return update_wrapper(wrapper, f)
     return update_wrapper(wrapper, f)
 
 
@@ -267,7 +267,10 @@ class AppContext:
         return self
         return self
 
 
     def __exit__(
     def __exit__(
-        self, exc_type: type, exc_value: BaseException, tb: TracebackType
+        self,
+        exc_type: t.Optional[type],
+        exc_value: t.Optional[BaseException],
+        tb: t.Optional[TracebackType],
     ) -> None:
     ) -> None:
         self.pop(exc_value)
         self.pop(exc_value)
 
 
@@ -338,14 +341,32 @@ class RequestContext:
         # Functions that should be executed after the request on the response
         # Functions that should be executed after the request on the response
         # object.  These will be called before the regular "after_request"
         # object.  These will be called before the regular "after_request"
         # functions.
         # functions.
-        self._after_request_functions: t.List[AfterRequestCallable] = []
+        self._after_request_functions: t.List[ft.AfterRequestCallable] = []
 
 
     @property
     @property
-    def g(self) -> AppContext:
+    def g(self) -> _AppCtxGlobals:
+        import warnings
+
+        warnings.warn(
+            "Accessing 'g' on the request context is deprecated and"
+            " will be removed in Flask 2.2. Access `g` directly or from"
+            "the application context instead.",
+            DeprecationWarning,
+            stacklevel=2,
+        )
         return _app_ctx_stack.top.g
         return _app_ctx_stack.top.g
 
 
     @g.setter
     @g.setter
-    def g(self, value: AppContext) -> None:
+    def g(self, value: _AppCtxGlobals) -> None:
+        import warnings
+
+        warnings.warn(
+            "Setting 'g' on the request context is deprecated and"
+            " will be removed in Flask 2.2. Set it on the application"
+            " context instead.",
+            DeprecationWarning,
+            stacklevel=2,
+        )
         _app_ctx_stack.top.g = value
         _app_ctx_stack.top.g = value
 
 
     def copy(self) -> "RequestContext":
     def copy(self) -> "RequestContext":
@@ -473,7 +494,10 @@ class RequestContext:
         return self
         return self
 
 
     def __exit__(
     def __exit__(
-        self, exc_type: type, exc_value: BaseException, tb: TracebackType
+        self,
+        exc_type: t.Optional[type],
+        exc_value: t.Optional[BaseException],
+        tb: t.Optional[TracebackType],
     ) -> None:
     ) -> None:
         # do not pop the request stack if we are in debug mode and an
         # do not pop the request stack if we are in debug mode and an
         # exception happened.  This will allow the debugger to still
         # exception happened.  This will allow the debugger to still

+ 24 - 22
contrib/python/Flask/py3/flask/debughelpers.py

@@ -41,53 +41,55 @@ class DebugFilesKeyError(KeyError, AssertionError):
 
 
 
 
 class FormDataRoutingRedirect(AssertionError):
 class FormDataRoutingRedirect(AssertionError):
-    """This exception is raised by Flask in debug mode if it detects a
-    redirect caused by the routing system when the request method is not
-    GET, HEAD or OPTIONS.  Reasoning: form data will be dropped.
+    """This exception is raised in debug mode if a routing redirect
+    would cause the browser to drop the method or body. This happens
+    when method is not GET, HEAD or OPTIONS and the status code is not
+    307 or 308.
     """
     """
 
 
     def __init__(self, request):
     def __init__(self, request):
         exc = request.routing_exception
         exc = request.routing_exception
         buf = [
         buf = [
-            f"A request was sent to this URL ({request.url}) but a"
-            " redirect was issued automatically by the routing system"
-            f" to {exc.new_url!r}."
+            f"A request was sent to '{request.url}', but routing issued"
+            f" a redirect to the canonical URL '{exc.new_url}'."
         ]
         ]
 
 
-        # In case just a slash was appended we can be extra helpful
-        if f"{request.base_url}/" == exc.new_url.split("?")[0]:
+        if f"{request.base_url}/" == exc.new_url.partition("?")[0]:
             buf.append(
             buf.append(
-                "  The URL was defined with a trailing slash so Flask"
-                " will automatically redirect to the URL with the"
-                " trailing slash if it was accessed without one."
+                " The URL was defined with a trailing slash. Flask"
+                " will redirect to the URL with a trailing slash if it"
+                " was accessed without one."
             )
             )
 
 
         buf.append(
         buf.append(
-            "  Make sure to directly send your"
-            f" {request.method}-request to this URL since we can't make"
-            " browsers or HTTP clients redirect with form data reliably"
-            " or without user interaction."
+            " Send requests to the canonical URL, or use 307 or 308 for"
+            " routing redirects. Otherwise, browsers will drop form"
+            " data.\n\n"
+            "This exception is only raised in debug mode."
         )
         )
-        buf.append("\n\nNote: this exception is only raised in debug mode")
-        AssertionError.__init__(self, "".join(buf).encode("utf-8"))
+        super().__init__("".join(buf))
 
 
 
 
 def attach_enctype_error_multidict(request):
 def attach_enctype_error_multidict(request):
-    """Since Flask 0.8 we're monkeypatching the files object in case a
-    request is detected that does not use multipart form data but the files
-    object is accessed.
+    """Patch ``request.files.__getitem__`` to raise a descriptive error
+    about ``enctype=multipart/form-data``.
+
+    :param request: The request to patch.
+    :meta private:
     """
     """
     oldcls = request.files.__class__
     oldcls = request.files.__class__
 
 
     class newcls(oldcls):
     class newcls(oldcls):
         def __getitem__(self, key):
         def __getitem__(self, key):
             try:
             try:
-                return oldcls.__getitem__(self, key)
+                return super().__getitem__(key)
             except KeyError as e:
             except KeyError as e:
                 if key not in request.form:
                 if key not in request.form:
                     raise
                     raise
 
 
-                raise DebugFilesKeyError(request, key) from e
+                raise DebugFilesKeyError(request, key).with_traceback(
+                    e.__traceback__
+                ) from None
 
 
     newcls.__name__ = oldcls.__name__
     newcls.__name__ = oldcls.__name__
     newcls.__module__ = oldcls.__module__
     newcls.__module__ = oldcls.__module__

+ 7 - 52
contrib/python/Flask/py3/flask/helpers.py

@@ -5,13 +5,11 @@ import sys
 import typing as t
 import typing as t
 import warnings
 import warnings
 from datetime import datetime
 from datetime import datetime
-from datetime import timedelta
 from functools import lru_cache
 from functools import lru_cache
 from functools import update_wrapper
 from functools import update_wrapper
 from threading import RLock
 from threading import RLock
 
 
 import werkzeug.utils
 import werkzeug.utils
-from werkzeug.exceptions import NotFound
 from werkzeug.routing import BuildError
 from werkzeug.routing import BuildError
 from werkzeug.urls import url_quote
 from werkzeug.urls import url_quote
 
 
@@ -188,7 +186,7 @@ def make_response(*args: t.Any) -> "Response":
         return current_app.response_class()
         return current_app.response_class()
     if len(args) == 1:
     if len(args) == 1:
         args = args[0]
         args = args[0]
-    return current_app.make_response(args)
+    return current_app.make_response(args)  # type: ignore
 
 
 
 
 def url_for(endpoint: str, **values: t.Any) -> str:
 def url_for(endpoint: str, **values: t.Any) -> str:
@@ -454,7 +452,7 @@ def _prepare_send_file_kwargs(
         warnings.warn(
         warnings.warn(
             "The 'attachment_filename' parameter has been renamed to"
             "The 'attachment_filename' parameter has been renamed to"
             " 'download_name'. The old name will be removed in Flask"
             " 'download_name'. The old name will be removed in Flask"
-            " 2.1.",
+            " 2.2.",
             DeprecationWarning,
             DeprecationWarning,
             stacklevel=3,
             stacklevel=3,
         )
         )
@@ -463,7 +461,7 @@ def _prepare_send_file_kwargs(
     if cache_timeout is not None:
     if cache_timeout is not None:
         warnings.warn(
         warnings.warn(
             "The 'cache_timeout' parameter has been renamed to"
             "The 'cache_timeout' parameter has been renamed to"
-            " 'max_age'. The old name will be removed in Flask 2.1.",
+            " 'max_age'. The old name will be removed in Flask 2.2.",
             DeprecationWarning,
             DeprecationWarning,
             stacklevel=3,
             stacklevel=3,
         )
         )
@@ -472,7 +470,7 @@ def _prepare_send_file_kwargs(
     if add_etags is not None:
     if add_etags is not None:
         warnings.warn(
         warnings.warn(
             "The 'add_etags' parameter has been renamed to 'etag'. The"
             "The 'add_etags' parameter has been renamed to 'etag'. The"
-            " old name will be removed in Flask 2.1.",
+            " old name will be removed in Flask 2.2.",
             DeprecationWarning,
             DeprecationWarning,
             stacklevel=3,
             stacklevel=3,
         )
         )
@@ -627,29 +625,6 @@ def send_file(
     )
     )
 
 
 
 
-def safe_join(directory: str, *pathnames: str) -> str:
-    """Safely join zero or more untrusted path components to a base
-    directory to avoid escaping the base directory.
-
-    :param directory: The trusted base directory.
-    :param pathnames: The untrusted path components relative to the
-        base directory.
-    :return: A safe path, otherwise ``None``.
-    """
-    warnings.warn(
-        "'flask.helpers.safe_join' is deprecated and will be removed in"
-        " Flask 2.1. Use 'werkzeug.utils.safe_join' instead.",
-        DeprecationWarning,
-        stacklevel=2,
-    )
-    path = werkzeug.utils.safe_join(directory, *pathnames)
-
-    if path is None:
-        raise NotFound()
-
-    return path
-
-
 def send_from_directory(
 def send_from_directory(
     directory: t.Union[os.PathLike, str],
     directory: t.Union[os.PathLike, str],
     path: t.Union[os.PathLike, str],
     path: t.Union[os.PathLike, str],
@@ -674,7 +649,8 @@ def send_from_directory(
     If the final path does not point to an existing regular file,
     If the final path does not point to an existing regular file,
     raises a 404 :exc:`~werkzeug.exceptions.NotFound` error.
     raises a 404 :exc:`~werkzeug.exceptions.NotFound` error.
 
 
-    :param directory: The directory that ``path`` must be located under.
+    :param directory: The directory that ``path`` must be located under,
+        relative to the current application's root path.
     :param path: The path to the file to send, relative to
     :param path: The path to the file to send, relative to
         ``directory``.
         ``directory``.
     :param kwargs: Arguments to pass to :func:`send_file`.
     :param kwargs: Arguments to pass to :func:`send_file`.
@@ -691,7 +667,7 @@ def send_from_directory(
     if filename is not None:
     if filename is not None:
         warnings.warn(
         warnings.warn(
             "The 'filename' parameter has been renamed to 'path'. The"
             "The 'filename' parameter has been renamed to 'path'. The"
-            " old name will be removed in Flask 2.1.",
+            " old name will be removed in Flask 2.2.",
             DeprecationWarning,
             DeprecationWarning,
             stacklevel=2,
             stacklevel=2,
         )
         )
@@ -785,27 +761,6 @@ class locked_cached_property(werkzeug.utils.cached_property):
             super().__delete__(obj)
             super().__delete__(obj)
 
 
 
 
-def total_seconds(td: timedelta) -> int:
-    """Returns the total seconds from a timedelta object.
-
-    :param timedelta td: the timedelta to be converted in seconds
-
-    :returns: number of seconds
-    :rtype: int
-
-    .. deprecated:: 2.0
-        Will be removed in Flask 2.1. Use
-        :meth:`timedelta.total_seconds` instead.
-    """
-    warnings.warn(
-        "'total_seconds' is deprecated and will be removed in Flask"
-        " 2.1. Use 'timedelta.total_seconds' instead.",
-        DeprecationWarning,
-        stacklevel=2,
-    )
-    return td.days * 60 * 60 * 24 + td.seconds
-
-
 def is_ip(value: str) -> bool:
 def is_ip(value: str) -> bool:
     """Determine if the given string is an IP address.
     """Determine if the given string is an IP address.
 
 

+ 8 - 67
contrib/python/Flask/py3/flask/json/__init__.py

@@ -1,9 +1,8 @@
+import dataclasses
 import decimal
 import decimal
-import io
 import json as _json
 import json as _json
 import typing as t
 import typing as t
 import uuid
 import uuid
-import warnings
 from datetime import date
 from datetime import date
 
 
 from jinja2.utils import htmlsafe_json_dumps as _jinja_htmlsafe_dumps
 from jinja2.utils import htmlsafe_json_dumps as _jinja_htmlsafe_dumps
@@ -16,12 +15,6 @@ if t.TYPE_CHECKING:
     from ..app import Flask
     from ..app import Flask
     from ..wrappers import Response
     from ..wrappers import Response
 
 
-try:
-    import dataclasses
-except ImportError:
-    # Python < 3.7
-    dataclasses = None  # type: ignore
-
 
 
 class JSONEncoder(_json.JSONEncoder):
 class JSONEncoder(_json.JSONEncoder):
     """The default JSON encoder. Handles extra types compared to the
     """The default JSON encoder. Handles extra types compared to the
@@ -30,6 +23,7 @@ class JSONEncoder(_json.JSONEncoder):
     -   :class:`datetime.datetime` and :class:`datetime.date` are
     -   :class:`datetime.datetime` and :class:`datetime.date` are
         serialized to :rfc:`822` strings. This is the same as the HTTP
         serialized to :rfc:`822` strings. This is the same as the HTTP
         date format.
         date format.
+    -   :class:`decimal.Decimal` is serialized to a string.
     -   :class:`uuid.UUID` is serialized to a string.
     -   :class:`uuid.UUID` is serialized to a string.
     -   :class:`dataclasses.dataclass` is passed to
     -   :class:`dataclasses.dataclass` is passed to
         :func:`dataclasses.asdict`.
         :func:`dataclasses.asdict`.
@@ -135,20 +129,7 @@ def dumps(obj: t.Any, app: t.Optional["Flask"] = None, **kwargs: t.Any) -> str:
         context for configuration.
         context for configuration.
     """
     """
     _dump_arg_defaults(kwargs, app=app)
     _dump_arg_defaults(kwargs, app=app)
-    encoding = kwargs.pop("encoding", None)
-    rv = _json.dumps(obj, **kwargs)
-
-    if encoding is not None:
-        warnings.warn(
-            "'encoding' is deprecated and will be removed in Flask 2.1.",
-            DeprecationWarning,
-            stacklevel=2,
-        )
-
-        if isinstance(rv, str):
-            return rv.encode(encoding)  # type: ignore
-
-    return rv
+    return _json.dumps(obj, **kwargs)
 
 
 
 
 def dump(
 def dump(
@@ -170,27 +151,14 @@ def dump(
         deprecated and will be removed in Flask 2.1.
         deprecated and will be removed in Flask 2.1.
     """
     """
     _dump_arg_defaults(kwargs, app=app)
     _dump_arg_defaults(kwargs, app=app)
-    encoding = kwargs.pop("encoding", None)
-    show_warning = encoding is not None
-
-    try:
-        fp.write("")
-    except TypeError:
-        show_warning = True
-        fp = io.TextIOWrapper(fp, encoding or "utf-8")  # type: ignore
-
-    if show_warning:
-        warnings.warn(
-            "Writing to a binary file, and the 'encoding' argument, is"
-            " deprecated and will be removed in Flask 2.1.",
-            DeprecationWarning,
-            stacklevel=2,
-        )
-
     _json.dump(obj, fp, **kwargs)
     _json.dump(obj, fp, **kwargs)
 
 
 
 
-def loads(s: str, app: t.Optional["Flask"] = None, **kwargs: t.Any) -> t.Any:
+def loads(
+    s: t.Union[str, bytes],
+    app: t.Optional["Flask"] = None,
+    **kwargs: t.Any,
+) -> t.Any:
     """Deserialize an object from a string of JSON.
     """Deserialize an object from a string of JSON.
 
 
     Takes the same arguments as the built-in :func:`json.loads`, with
     Takes the same arguments as the built-in :func:`json.loads`, with
@@ -210,19 +178,6 @@ def loads(s: str, app: t.Optional["Flask"] = None, **kwargs: t.Any) -> t.Any:
         context for configuration.
         context for configuration.
     """
     """
     _load_arg_defaults(kwargs, app=app)
     _load_arg_defaults(kwargs, app=app)
-    encoding = kwargs.pop("encoding", None)
-
-    if encoding is not None:
-        warnings.warn(
-            "'encoding' is deprecated and will be removed in Flask 2.1."
-            " The data must be a string or UTF-8 bytes.",
-            DeprecationWarning,
-            stacklevel=2,
-        )
-
-        if isinstance(s, bytes):
-            s = s.decode(encoding)
-
     return _json.loads(s, **kwargs)
     return _json.loads(s, **kwargs)
 
 
 
 
@@ -242,20 +197,6 @@ def load(fp: t.IO[str], app: t.Optional["Flask"] = None, **kwargs: t.Any) -> t.A
         file must be text mode, or binary mode with UTF-8 bytes.
         file must be text mode, or binary mode with UTF-8 bytes.
     """
     """
     _load_arg_defaults(kwargs, app=app)
     _load_arg_defaults(kwargs, app=app)
-    encoding = kwargs.pop("encoding", None)
-
-    if encoding is not None:
-        warnings.warn(
-            "'encoding' is deprecated and will be removed in Flask 2.1."
-            " The file must be text mode, or binary mode with UTF-8"
-            " bytes.",
-            DeprecationWarning,
-            stacklevel=2,
-        )
-
-        if isinstance(fp.read(0), bytes):
-            fp = io.TextIOWrapper(fp, encoding)  # type: ignore
-
     return _json.load(fp, **kwargs)
     return _json.load(fp, **kwargs)
 
 
 
 

Some files were not shown because too many files changed in this diff