Skip to content

Add support for typing.Never #1579

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

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open

Conversation

changhc
Copy link
Contributor

@changhc changhc commented Dec 10, 2024

Change Summary

Add support for typing.Never.

Validation

The validator implementation might look a bit weird. This is because of RootModel. Even though it doesn't really make sense, I assume that the following should work:

from typing import Never
from pydantic import RootModel

v = RootModel[Never]()

and because RootModel passes PydanticUndefined to the validator when no data is provided, the validator needs to work with PydanticUndefined. If we don't expect RootModel[Never]() to ever work, we can simplify the implementation and simply reject all values, but there might be another issue: users might wonder how the following works while RootModel does not:

from typing import Never
from pydantic import BaseModel

class Model(BaseModel):
    a: Never

Also, simply rejecting everything in the validator means that the validated model instance will not contain any value for the Never fields. When users try to access those fields, they will get an error, but the error is going to be something like

AttributeError: 'Model' object has no attribute 'a'

This kind of makes sense because indeed the Never fields never hold any value, but at the same time they are defined in the model, so it kind of makes sense as well to say that the instances do have those attributes. We should provide some better error messages, but before that gets handled in pydantic, I think in core we can return PydanticUndefined as a placeholder.

Serialisation

Serialising the never fields themselves will trigger an error. For instance,

v = RootModel[Never]()
v.model_dump()  # TypeError: type `never` cannot be serialized

On the other hand, serialising models containing never fields should work and the never fields should be omitted:

class Model(BaseModel):
    a: Never

assert Model().model_dump() == {}

These are covered by the new test cases included in this PR.

Manual integration test

Tested locally with the counterpart implementation for pydantic and it worked.

Related issue number

Part of pydantic/pydantic#9731

Checklist

  • Unit tests for the changes exist
  • Documentation reflects the changes where applicable
  • Pydantic tests pass with this pydantic-core (except for expected changes)
  • My PR is ready to review, please add a comment including the phrase "please review" to assign reviewers

Selected Reviewer: @sydney-runkle

Copy link

codspeed-hq bot commented Dec 10, 2024

CodSpeed Performance Report

Merging #1579 will not alter performance

Comparing changhc:9731-never (3b439fa) with main (52e9a53)

Summary

✅ 157 untouched benchmarks

Copy link

codecov bot commented Dec 10, 2024

Codecov Report

Attention: Patch coverage is 7.59494% with 73 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/validators/never.rs 0.00% 33 Missing ⚠️
src/serializers/type_serializers/never.rs 0.00% 32 Missing ⚠️
src/serializers/type_serializers/model.rs 0.00% 5 Missing ⚠️
src/errors/types.rs 0.00% 2 Missing ⚠️
src/serializers/shared.rs 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@changhc changhc marked this pull request as ready for review December 11, 2024 22:51
@changhc
Copy link
Contributor Author

changhc commented Dec 11, 2024

please review

@davidhewitt
Copy link
Contributor

@pydantic/oss would love your input on this design. I would have assumed a simpler design where any type containing a Never field (be it RootModel, BaseModel etc) would itself not be instantiable, because Never is not. Maybe there is some context I am missing.

@MarcBresson
Copy link

any traction on that PR? I'd love to have Never supported in pydantic :)

@samuelcolvin
Copy link
Member

Thanks so much for contributing, but I don't really see why this needs to be in core?

@Viicos
Copy link
Member

Viicos commented Jun 6, 2025

I think we can have a simpler alternative in pydantic, that generates a plain validator (and a serializer) unconditionally raising a PydanticCustomError.

Anyway, I'm also interested in knowing the use cases for this: why do you need a field to always fail when validating?

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

Successfully merging this pull request may close these issues.

6 participants