Repository: python-attrs/attrs

Problem statement:
Attrs deletes any non-None class attributes
Currently, `attrs` will delete any non-`None` class attributes when `_ClassBuilder._delete_attribs` is `True` (i.e. when attributes are specified via class attributes, not directly via `these` field).
According to comment on [_make.py:502](https://github.com/python-attrs/attrs/blob/master/src/attr/_make.py#L502), this is intended to remove `attr.ib` instances from the class.
But it does not play well with attributes declared using PEP 484 type annotations and `auto_attribs=True` argument to `attr.s`, because any attribute with non-`None` default value specified will be pruned from the class, while attributes with `None` value are retained.
This leads to unexpected behaviour in many cases, in particular when generating documentation using `Sphinx` `autosummary` extension which relies on class introspection.
I think we should remove only `attr.ib` instances, not any not-None fields. At least in `auto_attribs` mode. Or at least fix the comment.

Attrs version checked: 19.1.0
Code to reproduce:
```
import attr
import typing

@attr.s(auto_attribs=True)
class Foo:
    bar: int = 42
    baz: typing.Any = None

print([f for f in dir(Foo) if not f.startswith('_')])  # ['baz']
print(Foo.baz)  # 42
print(Foo.bar)  # AttributeError
```


Hints:
Gosh I'm traveling but isn't the problem just that we need to use a proper/unique sentinel value instead of None here?!
There is totally a bug here, because None and non-None fields should obviously be treated differently.

Removing only `attr.ib`s would work, however the values those fields have are semantically supposed to be default values that get assigned on instantiation, not class variables. It gets even more complicated when we introduce default factories. We'd have to remove them too…but that'd be highly inconsistent?

So the fix here is to remove `None` too.

Patch:
diff --git a/src/attr/_make.py b/src/attr/_make.py
--- a/src/attr/_make.py
+++ b/src/attr/_make.py
@@ -42,6 +42,9 @@
 
 _empty_metadata_singleton = metadata_proxy({})
 
+# Unique object for unequivocal getattr() defaults.
+_sentinel = object()
+
 
 class _Nothing(object):
     """
@@ -504,7 +507,7 @@ def _patch_original_class(self):
             for name in self._attr_names:
                 if (
                     name not in base_names
-                    and getattr(cls, name, None) is not None
+                    and getattr(cls, name, _sentinel) != _sentinel
                 ):
                     try:
                         delattr(cls, name)


Test patch:
diff --git a/tests/test_annotations.py b/tests/test_annotations.py
--- a/tests/test_annotations.py
+++ b/tests/test_annotations.py
@@ -265,3 +265,20 @@ class C(Base):
             x: int
 
         assert 1 == C(1).x
+
+    def test_removes_none_too(self):
+        """
+        Regression test for #523: make sure defaults that are set to None are
+        removed too.
+        """
+
+        @attr.s(auto_attribs=True)
+        class C:
+            x: int = 42
+            y: typing.Any = None
+
+        with pytest.raises(AttributeError):
+            C.x
+
+        with pytest.raises(AttributeError):
+            C.y