> On 16 Oct 2021, at 06:13, Steven D'Aprano <[email protected]> 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 <[email protected]> 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 -- [email protected]
> To unsubscribe send an email to [email protected]
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/[email protected]/message/HLGDIWGHSIG3LDSBN7RDARK6E7VYTXQT/
> Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/NJQD6TKI5EIWBIAFKOL5L7SNHJX2KK7A/
Code of Conduct: http://python.org/psf/codeofconduct/