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/

Reply via email to