mirror of
https://github.com/davidhalter/typeshed.git
synced 2026-01-02 09:33:25 +08:00
Use enum trick for dataclasses.MISSING (#7127)
The goal of this change is to fix the behavior of
`dataclasses.Field`. Several attributes of a `Field` may have a value
of `MISSING` (a sentinel value). As a result, attributes of Field may
be checked against `MISSING` as in
[f for f in fields(obj) if f.default is MISSING]
`default`, `default_factory`, and `kw_only` are the attributes
which may have a value of `MISSING`.
This workaround of defining `_MISSING_TYPE` as an enum, and `MISSING`
as its only member, allows `... | Literal[_MISSING_TYPE.MISSING]` to
be used in type annotations for these attributes. This is very
slightly inaccurate -- primarily in that `_MISSING_TYPE` isn't really
an enum -- but this allows for use in `Literal`.
After PEP 661 (Sentinel Values), there may be a more accurate way of
writing this, but for now this works.
This adjustment is only applied to the attributes of Field, not the
arguments to functions and methods.
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import enum
|
||||
import sys
|
||||
import types
|
||||
from builtins import type as Type # alias to avoid name clashes with fields named "type"
|
||||
from typing import Any, Callable, Generic, Iterable, Mapping, Protocol, TypeVar, overload
|
||||
from typing_extensions import Literal
|
||||
|
||||
if sys.version_info >= (3, 9):
|
||||
from types import GenericAlias
|
||||
@@ -9,9 +11,15 @@ if sys.version_info >= (3, 9):
|
||||
_T = TypeVar("_T")
|
||||
_T_co = TypeVar("_T_co", covariant=True)
|
||||
|
||||
class _MISSING_TYPE: ...
|
||||
# define _MISSING_TYPE as an enum within the type stubs,
|
||||
# even though that is not really its type at runtime
|
||||
# this allows us to use Literal[_MISSING_TYPE.MISSING]
|
||||
# for background, see:
|
||||
# https://github.com/python/typeshed/pull/5900#issuecomment-895513797
|
||||
class _MISSING_TYPE(enum.Enum):
|
||||
MISSING = enum.auto()
|
||||
|
||||
MISSING: _MISSING_TYPE
|
||||
MISSING = _MISSING_TYPE.MISSING
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
class KW_ONLY: ...
|
||||
@@ -72,15 +80,15 @@ class _DefaultFactory(Protocol[_T_co]):
|
||||
class Field(Generic[_T]):
|
||||
name: str
|
||||
type: Type[_T]
|
||||
default: _T
|
||||
default_factory: _DefaultFactory[_T]
|
||||
default: _T | Literal[_MISSING_TYPE.MISSING]
|
||||
default_factory: _DefaultFactory[_T] | Literal[_MISSING_TYPE.MISSING]
|
||||
repr: bool
|
||||
hash: bool | None
|
||||
init: bool
|
||||
compare: bool
|
||||
metadata: types.MappingProxyType[Any, Any]
|
||||
if sys.version_info >= (3, 10):
|
||||
kw_only: bool
|
||||
kw_only: bool | Literal[_MISSING_TYPE.MISSING]
|
||||
def __init__(
|
||||
self,
|
||||
default: _T,
|
||||
|
||||
Reference in New Issue
Block a user