Skip to content

Commit

Permalink
show deprecation warning on json_encoder/decoder access
Browse files Browse the repository at this point in the history
  • Loading branch information
davidism committed Aug 3, 2022
1 parent 9a1b25f commit 714ccef
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 42 deletions.
11 changes: 7 additions & 4 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ Version 2.2.1

Unreleased

- Setting or accessing ``json_encoder`` or ``json_decoder`` raises a
deprecation warning. :issue:`4732`


Version 2.2.0
-------------
Expand Down Expand Up @@ -50,18 +53,18 @@ Released 2022-08-01
provider can be set to use a different JSON library.
``flask.jsonify`` will call ``app.json.response``, other
functions in ``flask.json`` will call corresponding functions in
``app.json``. :pr:`4688`
``app.json``. :pr:`4692`

- JSON configuration is moved to attributes on the default
``app.json`` provider. ``JSON_AS_ASCII``, ``JSON_SORT_KEYS``,
``JSONIFY_MIMETYPE``, and ``JSONIFY_PRETTYPRINT_REGULAR`` are
deprecated. :pr:`4688`
deprecated. :pr:`4692`
- Setting custom ``json_encoder`` and ``json_decoder`` classes on the
app or a blueprint, and the corresponding ``json.JSONEncoder`` and
``JSONDecoder`` classes, are deprecated. JSON behavior can now be
overridden using the ``app.json`` provider interface. :pr:`4688`
overridden using the ``app.json`` provider interface. :pr:`4692`
- ``json.htmlsafe_dumps`` and ``json.htmlsafe_dump`` are deprecated,
the function is built-in to Jinja now. :pr:`4688`
the function is built-in to Jinja now. :pr:`4692`
- Refactor ``register_error_handler`` to consolidate error checking.
Rewrite some error messages to be more consistent. :issue:`4559`
- Use Blueprint decorators and functions intended for setup after
Expand Down
98 changes: 80 additions & 18 deletions src/flask/app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import functools
import inspect
import json
import logging
import os
import sys
Expand Down Expand Up @@ -379,25 +380,86 @@ def use_x_sendfile(self, value: bool) -> None:
)
self.config["USE_X_SENDFILE"] = value

#: The JSON encoder class to use. Defaults to
#: :class:`~flask.json.JSONEncoder`.
#:
#: .. deprecated:: 2.2
#: Will be removed in Flask 2.3. Customize
#: :attr:`json_provider_class` instead.
#:
#: .. versionadded:: 0.10
json_encoder: None = None
_json_encoder: t.Union[t.Type[json.JSONEncoder], None] = None
_json_decoder: t.Union[t.Type[json.JSONDecoder], None] = None

#: The JSON decoder class to use. Defaults to
#: :class:`~flask.json.JSONDecoder`.
#:
#: .. deprecated:: 2.2
#: Will be removed in Flask 2.3. Customize
#: :attr:`json_provider_class` instead.
#:
#: .. versionadded:: 0.10
json_decoder: None = None
@property # type: ignore[override]
def json_encoder(self) -> t.Type[json.JSONEncoder]: # type: ignore[override]
"""The JSON encoder class to use. Defaults to
:class:`~flask.json.JSONEncoder`.
.. deprecated:: 2.2
Will be removed in Flask 2.3. Customize
:attr:`json_provider_class` instead.
.. versionadded:: 0.10
"""
import warnings

warnings.warn(
"'app.json_encoder' is deprecated and will be removed in Flask 2.3."
" Customize 'app.json_provider_class' or 'app.json' instead.",
DeprecationWarning,
stacklevel=2,
)

if self._json_encoder is None:
from . import json

return json.JSONEncoder

return self._json_encoder

@json_encoder.setter
def json_encoder(self, value: t.Type[json.JSONEncoder]) -> None:
import warnings

warnings.warn(
"'app.json_encoder' is deprecated and will be removed in Flask 2.3."
" Customize 'app.json_provider_class' or 'app.json' instead.",
DeprecationWarning,
stacklevel=2,
)
self._json_encoder = value

@property # type: ignore[override]
def json_decoder(self) -> t.Type[json.JSONDecoder]: # type: ignore[override]
"""The JSON decoder class to use. Defaults to
:class:`~flask.json.JSONDecoder`.
.. deprecated:: 2.2
Will be removed in Flask 2.3. Customize
:attr:`json_provider_class` instead.
.. versionadded:: 0.10
"""
import warnings

warnings.warn(
"'app.json_decoder' is deprecated and will be removed in Flask 2.3."
" Customize 'app.json_provider_class' or 'app.json' instead.",
DeprecationWarning,
stacklevel=2,
)

if self._json_decoder is None:
from . import json

return json.JSONDecoder

return self._json_decoder

@json_decoder.setter
def json_decoder(self, value: t.Type[json.JSONDecoder]) -> None:
import warnings

warnings.warn(
"'app.json_decoder' is deprecated and will be removed in Flask 2.3."
" Customize 'app.json_provider_class' or 'app.json' instead.",
DeprecationWarning,
stacklevel=2,
)
self._json_decoder = value

json_provider_class: t.Type[JSONProvider] = DefaultJSONProvider
"""A subclass of :class:`~flask.json.provider.JSONProvider`. An
Expand Down
83 changes: 71 additions & 12 deletions src/flask/blueprints.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import os
import typing as t
from collections import defaultdict
Expand Down Expand Up @@ -172,18 +173,76 @@ class Blueprint(Scaffold):

_got_registered_once = False

#: Blueprint local JSON encoder class to use. Set to ``None`` to use
#: the app's :class:`~flask.Flask.json_encoder`.
#:
#: .. deprecated:: 2.2
#: Will be removed in Flask 2.3.
json_encoder: None = None
#: Blueprint local JSON decoder class to use. Set to ``None`` to use
#: the app's :class:`~flask.Flask.json_decoder`.
#:
#: .. deprecated:: 2.2
#: Will be removed in Flask 2.3.
json_decoder: None = None
_json_encoder: t.Union[t.Type[json.JSONEncoder], None] = None
_json_decoder: t.Union[t.Type[json.JSONDecoder], None] = None

@property # type: ignore[override]
def json_encoder( # type: ignore[override]
self,
) -> t.Union[t.Type[json.JSONEncoder], None]:
"""Blueprint-local JSON encoder class to use. Set to ``None`` to use the app's.
.. deprecated:: 2.2
Will be removed in Flask 2.3. Customize
:attr:`json_provider_class` instead.
.. versionadded:: 0.10
"""
import warnings

warnings.warn(
"'bp.json_encoder' is deprecated and will be removed in Flask 2.3."
" Customize 'app.json_provider_class' or 'app.json' instead.",
DeprecationWarning,
stacklevel=2,
)
return self._json_encoder

@json_encoder.setter
def json_encoder(self, value: t.Union[t.Type[json.JSONEncoder], None]) -> None:
import warnings

warnings.warn(
"'bp.json_encoder' is deprecated and will be removed in Flask 2.3."
" Customize 'app.json_provider_class' or 'app.json' instead.",
DeprecationWarning,
stacklevel=2,
)
self._json_encoder = value

@property # type: ignore[override]
def json_decoder( # type: ignore[override]
self,
) -> t.Union[t.Type[json.JSONDecoder], None]:
"""Blueprint-local JSON decoder class to use. Set to ``None`` to use the app's.
.. deprecated:: 2.2
Will be removed in Flask 2.3. Customize
:attr:`json_provider_class` instead.
.. versionadded:: 0.10
"""
import warnings

warnings.warn(
"'bp.json_decoder' is deprecated and will be removed in Flask 2.3."
" Customize 'app.json_provider_class' or 'app.json' instead.",
DeprecationWarning,
stacklevel=2,
)
return self._json_decoder

@json_decoder.setter
def json_decoder(self, value: t.Union[t.Type[json.JSONDecoder], None]) -> None:
import warnings

warnings.warn(
"'bp.json_decoder' is deprecated and will be removed in Flask 2.3."
" Customize 'app.json_provider_class' or 'app.json' instead.",
DeprecationWarning,
stacklevel=2,
)
self._json_decoder = value

def __init__(
self,
Expand Down
12 changes: 6 additions & 6 deletions src/flask/json/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ def dumps(self, obj: t.Any, **kwargs: t.Any) -> str:
:param obj: The data to serialize.
:param kwargs: Passed to :func:`json.dumps`.
"""
cls = self._app.json_encoder
cls = self._app._json_encoder
bp = self._app.blueprints.get(request.blueprint) if request else None

if bp is not None and bp.json_encoder is not None:
cls = bp.json_encoder
if bp is not None and bp._json_encoder is not None:
cls = bp._json_encoder

if cls is not None:
import warnings
Expand Down Expand Up @@ -235,11 +235,11 @@ def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any:
:param s: Text or UTF-8 bytes.
:param kwargs: Passed to :func:`json.loads`.
"""
cls = self._app.json_decoder
cls = self._app._json_decoder
bp = self._app.blueprints.get(request.blueprint) if request else None

if bp is not None and bp.json_decoder is not None:
cls = bp.json_decoder
if bp is not None and bp._json_decoder is not None:
cls = bp._json_decoder

if cls is not None:
import warnings
Expand Down
5 changes: 3 additions & 2 deletions src/flask/scaffold.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import importlib.util
import json
import os
import pathlib
import pkgutil
Expand Down Expand Up @@ -78,14 +79,14 @@ class Scaffold:
#:
#: .. deprecated:: 2.2
#: Will be removed in Flask 2.3.
json_encoder: None = None
json_encoder: t.Union[t.Type[json.JSONEncoder], None] = None

#: JSON decoder class used by :func:`flask.json.loads`. If a
#: blueprint sets this, it will be used instead of the app's value.
#:
#: .. deprecated:: 2.2
#: Will be removed in Flask 2.3.
json_decoder: None = None
json_decoder: t.Union[t.Type[json.JSONDecoder], None] = None

def __init__(
self,
Expand Down

0 comments on commit 714ccef

Please sign in to comment.