Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Private fields in python use dunder prefix, not __name__ pattern #4833

Closed
5 of 15 tasks
rafalkrupinski opened this issue Dec 10, 2022 · 6 comments · Fixed by #7265
Closed
5 of 15 tasks

Private fields in python use dunder prefix, not __name__ pattern #4833

rafalkrupinski opened this issue Dec 10, 2022 · 6 comments · Fixed by #7265
Assignees

Comments

@rafalkrupinski
Copy link

Initial Checks

  • I have searched GitHub for a duplicate issue and I'm sure this is something new
  • I have searched Google & StackOverflow for a solution and couldn't find anything
  • I have read and followed the docs and still think this is a bug
  • I am confident that the issue is with pydantic (not my code, or another library in the ecosystem like FastAPI or mypy)

Description

pydantic.PrivateAttr expects that the field is either prefixed with a single underscore (sunder) or surrounded with double underscores, like __name__.

Following https://peps.python.org/pep-0008/#descriptive-naming-styles

  • class-private fields should fallow __name pattern
  • and all __names__ are reserved for python magic

Example Code

No response

Python, Pydantic & OS Version

pydantic version: 1.10.2
            pydantic compiled: True
                 install path: ~/Library/Caches/pypoetry/virtualenvs/lapidary-6fqZNkrQ-py3.10/lib/python3.10/site-packages/pydantic
               python version: 3.10.7 (main, Oct 30 2022, 01:28:25) [Clang 14.0.0 (clang-1400.0.29.102)]
                     platform: macOS-13.0-x86_64-i386-64bit
     optional deps. installed: ['typing-extensions']
m

Affected Components

@rafalkrupinski rafalkrupinski added bug V1 Bug related to Pydantic V1.X unconfirmed Bug not yet confirmed as valid/applicable labels Dec 10, 2022
@rafalkrupinski rafalkrupinski changed the title Private fields in python use dunder prefix, not __name__ Private fields in python use dunder prefix, not __name__ pattern Dec 10, 2022
@hramezani
Copy link
Member

Thanks @rafalkrupinski for reporting this issue.
So, If I got you correctly, The issue is about does not support __ for pydantic.PrivateAttr. right?

@rafalkrupinski
Copy link
Author

@hramezani yes, also that it encourages code practice against the standards

@hramezani
Copy link
Member

Seems a good idea.
what do you think @samuelcolvin ?

@Bobronium
Copy link
Contributor

Bobronium commented Dec 13, 2022

I'd argue, having support for __dunder__ names in PrivateAttribute is a good thing.

The issue might be lying in naming of PrivateAttributes, giving impression that their only use is for some internal values of the models. However,, they act as a standard mechanism for declaring, setting and storing data on model instances separate from their fields, being an interface to python __slots__, dealing with their creation and assignment.

It's also not quite clear to me what exactly this issue is suggesting. @rafalkrupinski, do you have preferred outcome and a way of achieving it?

I personally think, PrivateAttributes might be better off with a different name, to suggest usages of dunder fields. We probably could drop Private part and leave just an Attribute?

One thing for sure, though: it's definitelly not a bug, but rather a design choice, and it's stated in docs:

Private attribute names must start with underscore to prevent conflicts with model fields: both _attr and __attr__ are supported.

@rafalkrupinski
Copy link
Author

rafalkrupinski commented Feb 17, 2023

Initially I wanted to set a default version when creating the data object.

class DataTransfer(BaseModel)
  __default_version = "1.0"
  version: str = __default_version
  # other data...

container = DataTransfer(mydata=...) # sets version to __default_version

Of course it's a bad code, bc it also set up default version when reading external data. And the private variable doesn't need any annotations, except perhaps ClassVar, but since pydantic.PrivateAttr is there I was sure I need it.

Cheers

@lig lig added feature request Feedback Wanted and removed bug V1 Bug related to Pydantic V1.X unconfirmed Bug not yet confirmed as valid/applicable labels Aug 28, 2023
@lig
Copy link
Contributor

lig commented Aug 28, 2023

@rafalkrupinski According to Pydantic v2 docs on private model attributes: "Private attribute names must start with underscore to prevent conflicts with model fields. However, dunder names (such as attr) are not supported."

This implies that Pydantic will recognize an attribute with any number of leading underscores as a private one. Indeed, looking in the test in this PR #7265 the behavior of an attribute with double leading underscores is exactly as expected. It behave similarly to an attribute with a single leading underscore and it behaves like a regular Python private attribute to which the name mangling ('m._Model__foo' instead of m.__foo) is applied.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants