> On 16 Oct 2021, at 06:13, Steven D'Aprano <st...@pearwood.info> wrote: > Be careful about believing what you are told.
Indeed, MyPy will correctly raise errors if you assign {None: []} to a variable annotated with dict[str, Number]. However, you'll find that MyPy also raises an error if you assign {'foo': 4} to a variable annotated with dict[str, Number]: https://mypy-play.net/?mypy=latest&python=3.10&gist=de7faea3b4d6a0ffefc64acf3bfa7b77 The issue isn't a matter of false negatives from Mypy; it's a matter of false positives. For more, see the (rather long — sorry!) answer I gave Sebastian to a previous question of his on Stack Overflow: https://stackoverflow.com/questions/69334475/how-to-hint-at-number-types-i-e-subclasses-of-number-not-numbers-themselv/69383462#69383462 Having said that, I absolutely agree that type-hinting doesn't seem to have much to do with this specific problem, and that a UserDict subclass is probably the way to go here. Best, Alex > On 16 Oct 2021, at 06:13, Steven D'Aprano <st...@pearwood.info> wrote: > > On Fri, Oct 15, 2021 at 06:17:12PM +0200, Sebastian M. Ernst wrote: > >> Data = Dict[str, Number] >> >> @typechecked >> def foo(bar: Data): >> print(bar) >> ``` >> >> Yes, this is using run-time checks (typeguard), which works just fine. >> Only strings as keys and Number objects as values are going through. (I >> was told that MyPy does not get this at the moment.) > > Be careful about believing what you are told. > > > [steve ~]$ cat test.py > from numbers import Number > from typing import Dict > Data = Dict[str, Number] > a: Data = {None: []} > > [steve ~]$ mypy test.py > test.py:4: error: Dict entry 0 has incompatible type "None": > "List[<nothing>]"; expected "str": "Number" > Found 1 error in 1 file (checked 1 source file) > > >> The issue is that `bar` itself still allows "everything" to go in (and out): >> >> ```python >> @typechecked >> def foo2(bar: Data): >> bar[1.0] = b'should not be allowed' >> ``` > > The Python interpreter intentionally doesn't know or care about > typing annotations. The interpreter should absolutely allow that. > > However mypy correctly flags that assignment as a type error. > > How about typeguard? That's for the typeguard developers to answer, but > my guess is that they will say that the typechecked decorator can > enforce type checking of the input parameters and perhaps even the > return result, but there is nothing they can do about what happens > inside the body of the function. > > >> PEP 589 introduces typed dictionaries, but for a fixed set of predefined >> keys (similar to struct-like constructs in other languages). In >> contrast, I am looking for an arbitrary number of typed keys/value pairs. > > Something like this? > > from numbers import Number > from collections import UserDict > > class RestrictedDict(UserDict): > def __setitem__(self, key, value): > if not isinstance(key, str): > raise TypeError('key must be a string') > if not isinstance(value, Number): > raise TypeError('value must be a number') > super().__setitem__(key, value) > > > (I think that is the only method that needs to be overloaded.) > > > -- > Steve > _______________________________________________ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/HLGDIWGHSIG3LDSBN7RDARK6E7VYTXQT/ > Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/NJQD6TKI5EIWBIAFKOL5L7SNHJX2KK7A/ Code of Conduct: http://python.org/psf/codeofconduct/