This attribute is a callable that returns a string if the value is
invalid, otherwise None. This intended for cases like the `install_*`
function's `install_mode` paramater, which is either an int or the
string "preserve", which allows us to do nice things like:
```python
class Kwargs(TypedDict):
install_mode: T.Union[int, T.Literal['preserve']]
@typed_kwargs(
'foo', KwargInfo('install_mode', ...,
validator=lambda x: None if isinstance(x, int) or x == 'preserve' else 'must be the literal "preserve"),
)
def install_data(self, node, args, kwargs: 'Kwargs'):
...
```
In this case mypy *knows* that the string is preserve, as do we, and we
can simply do tests like:
```python
if kwargs['install_mode'] == 'preserve':
...
else:
# this is an int
```
It's really inconvenient to want a thing that is always a list, but not
be able to provide a default value of a list because of mutation. To
that end the typed_kwargs method now makes a shallow copy of the default
when using a `ContainerTypeInfo` as the type. This mean that using a
default of `[]` is perfectly safe.
When mutable items are stored in an lru cache, changing the returned
items changes the cached items as well. Therefore we want to ensure that
we're not mutating them. Using the ImmutableListProtocol allows mypy to
find mutations and reject them. This doesn't solve the problem of
mutable values inside the values, so you could have to do things like:
```python
ImmutableListProtocol[ImmutableListProtocol[str]]
```
or equally hacky. It can also be used for input types and acts a bit
like C's const:
```python
def foo(arg: ImmutableListProtocol[str]) -> T.List[str]:
arg[1] = 'foo' # works while running, but mypy errors
```
this is a place that *must* only be imported inside a if
typing.TYPE_CHECKING block. It is a mixture of smoothing over thinigs
that moved from typing_extensions to typing in later python versions and
useful but typing only code.
This makes typing_extensions required for python versions older than
3.8 *when running mypy*. typing_extensions should *only* be imported
inside an `if typing.TYPE_CHECKING` block (include the new _typing.py
module) to ensure that it doesn't become a runtime dependency
This is problematic when we meson is installed in the different
root(say C:) while building from another root(say D:).
This is how it is done in mesonpep517 and causes problems
because of that.