support typing_extensions Literal
petergaultney opened this issue · comments
- cattrs version: 23.1.2
- Python version: 3.8.17
- Operating System: Linux
Description
Cattrs fails to structure an object that contains a typing_extensions.Literal
.
I know cattrs only supports 3.8 and up, and typing
in 3.8 has Literal
, so the current support is probably considered complete. However, there's a pretty common use case that this leaves out - where an application running on 3.8 imports a library that is still targeted at 3.7-level code (or simply hasn't been upgraded/refactored to use typing.Literal
).
Proposal
Could we modify _compat
to do something like what typing-inspect
does?
from typing import Literal
LITERALS = {Literal}
try:
from typing_extensions import Literal as te_Literal
LITERALS.add(te_Literal)
except ModuleNotFoundError:
pass
if version >= 3.9:
def is_literal(type):
return type in LITERALS or type.__class__ is _LiteralGenericAlias or (isinstance(type, _GenericAlias) and type.__origin__ in LITERALS)
else: # 3.8
def is_literal(type) -> bool:
return type in LITERALS or (isinstance(type, _GenericAlias) and type.__origin__ in LITERALS)
typing_extensions.Literal
does still seem to support typing.get_args
, so the rest of the code should work fine.
Maybe this opens a can of worms as far as supporting other typing_extensions
things, but in my limited experience, Literal
is one of the main reasons people ever used to reach for typing_extensions
when static typing was a relatively new thing, so it might be nice to support handling those old-style Literals transparently instead of requiring structure hooks to be registered for all of them.
maybe slightly ironically, it appears that cattrs
itself still uses typing_extensions.Literal
. ;)
If you put a PR together I'd be ok with merging it in, I don't think this is a huge burden to bear if it's useful to someone.
I'd be happy to help with the PR in any shape or form :)
thanks y'all. take a look at #467 and see what you think. Hopefully CI will pass...