Repository: pydantic/pydantic

Issue:
underscore_attrs_are_private causes TypeError
### Checks

- [x] I added a descriptive title to this issue
- [x] I have searched (google, github) for similar issues and couldn't find anything
- [x] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and still think this is a bug

# Bug

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:

```
        pydantic version: 1.7
       pydantic compiled: True
            install path: /Users/ahedges/.pyenv/versions/3.7.8/envs/sdf/lib/python3.7/site-packages/pydantic
          python version: 3.7.8 (default, Sep 16 2020, 18:33:23)  [Clang 11.0.3 (clang-1103.0.32.59)]
                platform: Darwin-19.6.0-x86_64-i386-64bit
optional deps. installed: ['typing-extensions']
```

I spent a decent amount of time this weekend trying to make a private field using code posted in #655. I was happy to see Pydantic 1.7 came out today and had support for private fields built in. I upgraded and tried to convert my code, but I encountered some unusual problems. (Even though it doesn't work perfectly, I still appreciate the feature.) Most are type errors from mypy (might report later), but this one is more serious. I simplified the problem below.

The issue is that `underscore_attrs_are_private` causes an exception where `PrivateAttr` does not.

When using `underscore_attrs_are_private` with the following code:

```python
from typing import Any
from pydantic import BaseModel

class TestObject(BaseModel):
    public_field: str
    _private_field: str

    class Config:
        underscore_attrs_are_private = True

    def __init__(self, **data: Any) -> None:
        super().__init__(**data)
        self._private_field = "bar"

print(TestObject(public_field="foo"))
```

I get the following output:

```
test.py:4: DeprecationWarning: __class__ not set defining 'TestObject' as <class '__main__.TestObject'>. Was __classcell__ propagated to type.__new__?
  class TestObject(BaseModel):
Traceback (most recent call last):
  File "test.py", line 15, in <module>
    print(TestObject(public_field="foo"))
  File "test.py", line 12, in __init__
    super().__init__(**data)
  File "pydantic/main.py", line 365, in pydantic.main.BaseModel.__init__
  File "pydantic/main.py", line 424, in pydantic.main.BaseModel._init_private_attributes
  File "pydantic/fields.py", line 821, in pydantic.fields.PrivateAttr.get_default
  File "pydantic/utils.py", line 624, in pydantic.utils.smart_deepcopy
  File "/Users/ahedges/.pyenv/versions/3.7.8/lib/python3.7/copy.py", line 169, in deepcopy
    rv = reductor(4)
TypeError: can't pickle cell objects
```

However, when using `PrivateAttr` with the following code:

```python
from typing import Any
from pydantic import BaseModel, PrivateAttr

class TestObject(BaseModel):
    public_field: str
    _private_field: str = PrivateAttr()

    def __init__(self, **data: Any) -> None:
        super().__init__(**data)
        self._private_field = "bar"

print(TestObject(public_field="foo"))
```

I get the following, desired output:

```
public_field='foo'
```

I also noticed that removing `__init__()` from the first example also prevents the crash. However, it is needed to set the private field.

Another thing to note is that in my full code, the exception caused by `underscore_attrs_are_private` appears but the `DeprecationWarning` does not. If you think this matters, I can try to reproduce my code without the warning.



Discussion:

Resolving patch:
diff --git a/pydantic/utils.py b/pydantic/utils.py
--- a/pydantic/utils.py
+++ b/pydantic/utils.py
@@ -631,4 +631,4 @@ def is_valid_field(name: str) -> bool:
 
 
 def is_valid_private_name(name: str) -> bool:
-    return not is_valid_field(name) and name not in {'__annotations__', '__module__', '__annotations__', '__qualname__'}
+    return not is_valid_field(name) and name not in {'__annotations__', '__classcell__', '__module__', '__qualname__'}


Test patch:
diff --git a/tests/test_private_attributes.py b/tests/test_private_attributes.py
--- a/tests/test_private_attributes.py
+++ b/tests/test_private_attributes.py
@@ -160,3 +160,20 @@ def __init__(self):
 def test_default_and_default_factory_used_error():
     with pytest.raises(TypeError, match='default and default_factory args can not be used together'):
         PrivateAttr(default=123, default_factory=lambda: 321)
+
+
+def test_config_override_init():
+    class MyModel(BaseModel):
+        x: str
+        _private_attr: int
+
+        def __init__(self, **data) -> None:
+            super().__init__(**data)
+            self._private_attr = 123
+
+        class Config:
+            underscore_attrs_are_private = True
+
+    m = MyModel(x='hello')
+    assert m.dict() == {'x': 'hello'}
+    assert m._private_attr == 123