Hi all,

thanks for all the feedback.

> But this is probably off-topic. I'm not 100% sure what the OP's
> proposal was, but as far as I can tell it seems to me that "dict[str,
> Number] is the correct usage for static typing" is the answer,
> regardless of mypy's ability to process it.

Let me explain the rational. Albeit type annotations in Python are
usually viewed as a tool for static code analysis, I really started to
like them for run-time checks and testing. I am hammering my code with
pytest, hypothesis and typeguard. It is this very combination that
allows me to find the kind of odd cases that I am looking for. The cool
thing is that, once the code is tested, I can turn the run-time checks
(i.e. typeguard) off simply by setting `PYTHONOPTIMIZE` to `1` or by
running CPython with the `-o` flag for production use. It kills the
`assert` statements *and* the run-time type checks without touching the
code.

Now, what PEP 589 *theoretically* allows is something as follows:

```python
from typing import TypedDict
from typeguard import typechecked

@typechecked
class Movie(TypedDict):
    name: str
    year: int

a = Movie(name = 'a', year = 1984) # ok
a['height'] = 2.0 # fail
b = Movie(something = 1.0) # fail
```

I am aware that typeguard does not support this at the moment, but based
on its design, it could be implemented (I think). A simple decorator on
top of a class with type annotations - done. Every instance of `Movie`
could be automatically type-checked. For this approach to work, it is
key that `Movie` is a class (which can be decorated).

In contrast, something like `dict[str, Number]` is perfectly fine for
static type checking and/or if there is type interference. Consider the
following example:

```python
Data = dict[str, Number]
c: Data = {}
c[3.0] = b'foo' # how to catch this at runtime?
```

In this case, `c` is just a "regular" instance of `dict`. I am not sure
how a run-time checker could catch any subsequent errors as shown above
(unless the dict is passed into or returned from a function/method). The
type checker would need to dig into the `dict` class itself and/or deep
into the interpreter. Correct me if I am wrong here - I'd be happy to
learn something new. Now my potentially stupid idea is to have a
counterpart to PEP 589's `TypedDict` classes which allows to subclass
and decorate the result, e.g. something elegant like this:

```python
@typechecked
class Data(YetAnotherTypedDictThing):
    keys: str
    values: Number
```

At the end of the day, a variation of Steven's and Alex's solutions
should do for me for the time being:

```python
from numbers import Number
from collections import UserDict

@typechecked
class Data(UserDict[str, Number]):
    def __setitem__(self, key: str, value: Number):
        super().__setitem__(key, value)
```

It is ok, it works, but it still looks and feels a little awkward:

(1) I need to override a dunder method.
(2) I need to subclass from something that already wraps `dict`.
(3) I need to specify the types in two separate places (redundancy) if I
am going for a generic solution - unless I am introducing type variables.

Last but not least, typeguard is looking for a new maintainer at the
moment, yes. I can not stress enough how useful this tool is for
testing. Maybe it is of interest and relevance to someone around here.

Thanks,
Sebastian
_______________________________________________
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/GJ4EP7WPSF5GQ5M2HB3PNDJJTJJTBZUX/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to