From d5ad4e1db9feaa8e238e5b2789fd0e8ee79fd80f Mon Sep 17 00:00:00 2001 From: Kevin M Granger Date: Thu, 14 Jul 2022 11:35:09 -0400 Subject: [PATCH 1/6] Use enum for typing NOTHING. This will allow those extending attrs to type NOTHING as Literal[NOTHING]. --- src/attr/__init__.pyi | 2 -- src/attr/_make.py | 16 +++++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/attr/__init__.pyi b/src/attr/__init__.pyi index 03cc4c82d..f6c560c68 100644 --- a/src/attr/__init__.pyi +++ b/src/attr/__init__.pyi @@ -65,8 +65,6 @@ class AttrsInstance(Protocol): # _make -- -NOTHING: object - # NOTE: Factory lies about its return type to make this possible: # `x: List[int] # = Factory(list)` # Work around mypy issue #4554 in the common case by using an overload. diff --git a/src/attr/_make.py b/src/attr/_make.py index 0c2da5edd..c436f390f 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: MIT import copy +import enum import linecache import sys import types @@ -46,21 +47,18 @@ _ng_default_on_setattr = setters.pipe(setters.convert, setters.validate) -class _Nothing: +class _Nothing(enum.Enum): """ Sentinel class to indicate the lack of a value when ``None`` is ambiguous. - ``_Nothing`` is a singleton. There is only ever one of it. + This is an Enum so that the single variant can be used as a `Literal` for + type checking tools. .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False. + .. versionchanged:: 22.2.0 ``NOTHING`` is now an `enum.Enum` variant. """ - _singleton = None - - def __new__(cls): - if _Nothing._singleton is None: - _Nothing._singleton = super().__new__(cls) - return _Nothing._singleton + NOTHING = enum.auto() def __repr__(self): return "NOTHING" @@ -69,7 +67,7 @@ def __bool__(self): return False -NOTHING = _Nothing() +NOTHING = _Nothing.NOTHING """ Sentinel to indicate the lack of a value when ``None`` is ambiguous. """ From aeac6bdd0c7d8b4e212bd9b56d22cff9917c3880 Mon Sep 17 00:00:00 2001 From: Kevin M Granger Date: Mon, 8 Aug 2022 19:05:29 -0400 Subject: [PATCH 2/6] Make test_dunders test `NOTHING` directly --- tests/test_dunders.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/test_dunders.py b/tests/test_dunders.py index 03644f8b2..4a28a0ba7 100644 --- a/tests/test_dunders.py +++ b/tests/test_dunders.py @@ -21,7 +21,6 @@ _add_repr, _is_slot_cls, _make_init, - _Nothing, fields, make_class, ) @@ -907,30 +906,30 @@ class C: class TestNothing: """ - Tests for `_Nothing`. + Tests for `NOTHING`. """ def test_copy(self): """ __copy__ returns the same object. """ - n = _Nothing() + n = NOTHING assert n is copy.copy(n) def test_deepcopy(self): """ __deepcopy__ returns the same object. """ - n = _Nothing() + n = NOTHING assert n is copy.deepcopy(n) def test_eq(self): """ All instances are equal. """ - assert _Nothing() == _Nothing() == NOTHING - assert not (_Nothing() != _Nothing()) - assert 1 != _Nothing() + assert NOTHING == NOTHING == NOTHING + assert not (NOTHING != NOTHING) + assert 1 != NOTHING def test_false(self): """ From 36d942aa26e8f0c2420f895725a53440380cafcb Mon Sep 17 00:00:00 2001 From: Kevin M Granger Date: Mon, 8 Aug 2022 19:05:49 -0400 Subject: [PATCH 3/6] Reflect NOTHING enum typing in __init__.pyi --- src/attr/__init__.pyi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/attr/__init__.pyi b/src/attr/__init__.pyi index f6c560c68..9fe2943d4 100644 --- a/src/attr/__init__.pyi +++ b/src/attr/__init__.pyi @@ -1,3 +1,4 @@ +import enum import sys from typing import ( @@ -65,6 +66,11 @@ class AttrsInstance(Protocol): # _make -- +class _Nothing(enum.Enum): + NOTHING = enum.auto() + +NOTHING = _Nothing.NOTHING + # NOTE: Factory lies about its return type to make this possible: # `x: List[int] # = Factory(list)` # Work around mypy issue #4554 in the common case by using an overload. From 2358f8efe9379de0702551ef007bfd7b71698065 Mon Sep 17 00:00:00 2001 From: Kevin M Granger Date: Mon, 8 Aug 2022 19:33:29 -0400 Subject: [PATCH 4/6] Fix docs for NOTHING --- docs/api.rst | 1 + src/attr/_make.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index a609833c5..f7298118b 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -28,6 +28,7 @@ Core Therefore if a class, method, or function claims that it has been added in an older version, it is only available in the ``attr`` namespace. .. autodata:: attrs.NOTHING + :no-value: .. autofunction:: attrs.define diff --git a/src/attr/_make.py b/src/attr/_make.py index c436f390f..c5ce07a02 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -49,13 +49,13 @@ class _Nothing(enum.Enum): """ - Sentinel class to indicate the lack of a value when ``None`` is ambiguous. + Sentinel to indicate the lack of a value when ``None`` is ambiguous. - This is an Enum so that the single variant can be used as a `Literal` for - type checking tools. + If extending attrs, you can use ``typing.Literal[NOTHING]`` to show + that a value may be ``NOTHING``. .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False. - .. versionchanged:: 22.2.0 ``NOTHING`` is now an `enum.Enum` variant. + .. versionchanged:: 22.2.0 ``NOTHING`` is now an ``enum.Enum`` variant. """ NOTHING = enum.auto() From 6b8fce81c99847eddb86d1c6e978f1bf5d917cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tin=20Tvrtkovi=C4=87?= Date: Sat, 27 Aug 2022 17:24:53 +0200 Subject: [PATCH 5/6] Add changelog entry --- changelog.d/983.change.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/983.change.rst diff --git a/changelog.d/983.change.rst b/changelog.d/983.change.rst new file mode 100644 index 000000000..8fa9a7e0b --- /dev/null +++ b/changelog.d/983.change.rst @@ -0,0 +1 @@ +``attrs.NOTHING`` is now an enum value, making it possible to use with f.e. ``typing.Literal``. \ No newline at end of file From 3ee99eb59df4aa7292a9d56f58bfc2ce458c085a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 27 Aug 2022 15:25:11 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- changelog.d/983.change.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/983.change.rst b/changelog.d/983.change.rst index 8fa9a7e0b..bb1a96849 100644 --- a/changelog.d/983.change.rst +++ b/changelog.d/983.change.rst @@ -1 +1 @@ -``attrs.NOTHING`` is now an enum value, making it possible to use with f.e. ``typing.Literal``. \ No newline at end of file +``attrs.NOTHING`` is now an enum value, making it possible to use with f.e. ``typing.Literal``.