You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I think mypy is doing the correct thing here. In your first sample, some_data has no type annotation, so its type is inferred to be dict[str, str]. The type parameters for dict are invariant, so they must match exactly. Since some_data is dict[str, str], it is not compatible with dict[str, JSON]. If you add the type annotation for some_data as you do in your second example, then it will work fine. Also, if you inline the expression for some_data rather than creating a separate variable, mypy can use the type context to infer that its type should be dict[str, JSON] in that context.
I think mypy is doing the correct thing here. In your first sample, some_data has no type annotation, so its type is inferred to be dict[str, str]. The type parameters for dict are invariant, so they must match exactly. Since some_data is dict[str, str], it is not compatible with dict[str, JSON]. If you add the type annotation for some_data as you do in your second example, then it will work fine. Also, if you inline the expression for some_data rather than creating a separate variable, mypy can use the type context to infer that its type should be dict[str, JSON] in that context.
Thank you for the answer. How should I proceed with the JSON type definition then? There are some functions in my code that have annotated return value as dict[str, str] and I'd like them to be accepted as part of JSON structure. Should I just cast them explicitly?
Casting is one option. Another option is possible if you don't need the resulting type to be mutable. You could define another type for a read-only JSON value.
@erictraut The problem with that is that you often genuinely don't want generic mappings and sequences to be considered valid JSON-like types, because certain JSON libraries won't accept them.
Python's own builtin json module, for example, insists on lists and dicts (or subclasses thereof) and will fail if you e.g. give it another kind of mapping:
Mypy doesn't complain about this, of course, but it fails at runtime with
Traceback (most recent call last):
File "/home/smheidrich/json-type.py", line 29, in <module>
dumps(MyMapping())
File "/home/smheidrich/json-type.py", line 26, in dumps
json.dumps(j)
File "/usr/lib/python3.10/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python3.10/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.10/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python3.10/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type MyMapping is not JSON serializable
So in that case, using list and dict instead of Sequence and Mapping would be quite deliberate and allow Mypy to catch the invalid usage.
Is there a way to fix the type alias while keeping it limited to lists and dicts (or subclasses) specifically? 🤔
Activity
erictraut commentedon Oct 1, 2022
I think mypy is doing the correct thing here. In your first sample,
some_datahas no type annotation, so its type is inferred to bedict[str, str]. The type parameters fordictare invariant, so they must match exactly. Sincesome_dataisdict[str, str], it is not compatible withdict[str, JSON]. If you add the type annotation forsome_dataas you do in your second example, then it will work fine. Also, if you inline the expression forsome_datarather than creating a separate variable, mypy can use the type context to infer that its type should bedict[str, JSON]in that context.Waszker commentedon Oct 1, 2022
Thank you for the answer. How should I proceed with the
JSONtype definition then? There are some functions in my code that have annotated return value asdict[str, str]and I'd like them to be accepted as part of JSON structure. Should I just cast them explicitly?erictraut commentedon Oct 2, 2022
Casting is one option. Another option is possible if you don't need the resulting type to be mutable. You could define another type for a read-only JSON value.
This works because the type parameters for
MappingandSequenceare covariant.smheidrich commentedon Nov 18, 2022
@erictraut The problem with that is that you often genuinely don't want generic mappings and sequences to be considered valid JSON-like types, because certain JSON libraries won't accept them.
Python's own builtin
jsonmodule, for example, insists onlists anddicts (or subclasses thereof) and will fail if you e.g. give it another kind of mapping:Mypy doesn't complain about this, of course, but it fails at runtime with
So in that case, using
listanddictinstead ofSequenceandMappingwould be quite deliberate and allow Mypy to catch the invalid usage.Is there a way to fix the type alias while keeping it limited to
lists anddicts (or subclasses) specifically? 🤔