Pydantic: Is there a way to use sunder (private) attributes as a normal field for pydantic models without alias etc? If set underscore_attrs_are_private = False private attributes are just ignored.

Created on 8 Nov 2020  路  8Comments  路  Source: samuelcolvin/pydantic

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 and couldn't find an answer
  • [x] After submitting this, I commit to one of:

    • Look through open issues and helped at least one other person

    • Hit the "watch" button on this repo to receive notifications and I commit to help at least 2 people that ask questions in the future

    • Implement a Pull Request for a confirmed bug

Question

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.7.2
            pydantic compiled: True
                 install path: /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pydantic
               python version: 3.7.6 (v3.7.6:43364a7ae0, Dec 18 2019, 14:18:50)  [Clang 6.0 (clang-600.0.57)]
                     platform: Darwin-18.7.0-x86_64-i386-64bit
     optional deps. installed: ['typing-extensions', 'devtools']
from pydantic import BaseModel

class Model(BaseModel):
    _foo: str

    class Config:
        underscore_attrs_are_private = False

m = Model(_foo=1)
print(m._foo)
Traceback (most recent call last):
  File "/Users/aovsyannikov/Library/Application Support/JetBrains/PyCharm2020.2/scratches/scratch_138.py", line 10, in <module>
    print(m._foo)
AttributeError: 'Model' object has no attribute '_foo'
question

Most helpful comment

@MrMrRobat
is about using underscore attributes as regular fields

All 8 comments

Hello @AntonOvsyannikov

Well it seems like it's the expected behaviour. Maybe this could/should be changed I have no idea to be honest. @MrMrRobat can probably give more information about it ;)

TL;DR: no, it's not possible, use attr = Field(alias='_attr')

Ignoring underscore attrs was default behavior for a long time, if not always (see pydantic.utils.is_valid_field()).

underscore_attrs_are_private was introduced to allow to use such attrs as private and not just throw them away, but it set to False by default so as not to break existing behavior.

Ok, thanks, clear. But now, been having the Config for such attributes it seems quite artificial limitation, which brings lot of inconvenience when work with models for MongoDB i.g.

@AntonOvsyannikov I quite agree as it makes sense to have fields you don't want to expose but still use them when instantiating. But @MrMrRobat is right when mentioning it is the existing behaviour. Maybe it can be changed in v2.
In the meantime you can use your own BaseModel by overwriting _pydantic_ one to add this behaviour ;)
For example

from typing import Any

from pydantic import BaseModel as PydanticBaseModel

class BaseModel(PydanticBaseModel):
    """Same as default BaseModel but allows private fields in __init__"""
    def __init__(__pydantic_self__, **data: Any) -> None:
        for name, private_attr in __pydantic_self__.__private_attributes__.items():
            if name in data:
                # remove private field from data to also work with Config.extra = 'forbid'
                private_attr.default = data.pop(name)
        super().__init__(**data)


class Model(BaseModel):
    _foo: str

    class Config:
        underscore_attrs_are_private = True
        extra = 'forbid'

m = Model(_foo=1)
print(m._foo)  # 1

@PrettyWood, it looks like in your example Model. __private_attributes__ defaults will be overwritten on every model init, which seems like unwanted side effect.

@AntonOvsyannikov, just to be sure: your initial problem is about using underscore attributes as regular fields, or about passing private attributes through __init__?

@MrMrRobat
is about using underscore attributes as regular fields

Ok, so seems like problem is really similar to #288.

Ahhh sorry I didn't understand the full problem my bad. Now it all makes sense. Thanks @MrMrRobat for clarifying.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vvoody picture vvoody  路  3Comments

nav picture nav  路  3Comments

cdeil picture cdeil  路  3Comments

dconathan picture dconathan  路  3Comments

sbv-trueenergy picture sbv-trueenergy  路  3Comments