Though we weren't using the affected feature, I am going to avoid
``from __future__ import annotations`` since it is likely going to be
replaced with a different approach. The only two things that we were
getting out of it is using `dict[]` instead of `typing.Dict[]` and using
`typing.Literal` in Python 3.7. Neither is compelling IMO.
https://discuss.python.org/t/type-annotations-pep-649-and-pep-563/
This could be lossy on the JSON side since the precision is up to the
reader as well. I implemented the encoding as a cast to `float` so
there will almost certainly be some loss of precision.
Since the form encoder refuses to handle nested sequences, the content
mixin explicitly handles this case instead of letting the unhandled
exception bubble up.
I rearranged the _encode method branching a bit. This resulted in a
little more than a 12% gain. Still slower than JSON or msgpack but it's
in python instead of C.
If someone explicitly removes the literal mappings, then refuse to
serialize None, True, and False instead of guessing. Note that I
explicitly included True and False in the branch logic since bool is a
subclass of int but str(True) != str(int(True)) :/
I ended up not using urllib.parse functions since they do not implement
the specification. The only difference is that the specification
requires that "~" is encoded.
NB - this commit is incomplete since it does not handle calling the
transcoder on simple objects. mypy will quite correctly fail.
If there is no transcoder for the default content type, sending a
response would fail with a "500 Internal Server Error" due to an
*unhandled* KeyError. This commit catches the KeyError and produces
an explicit "500 Internal Server Error" with an appropriate error
message being logged.
If there is no default content type and nothing matches in the Accept
header, previous versions would fail with an Internal Server Error
because of an unhandled exception. Instead we should be returning
a "406 Not Acceptable".
This allows us to remove the ImportError hack from __init__.py.
It also simplifies how the package is versioned - deriving it solely
from the repository tag.
Both version_info and __version__ have been removed with this change.
Given how these are a unofficial-standard at best, I've found it safer to
always use pkg_resources to determine the version when I need to.