The Wayback Machine - https://web.archive.org/web/20240907013712/https://github.com/pydantic/pydantic/pull/4154
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

Allow BaseModel schema to have fields of type Type #4154

Merged

Conversation

aminalaee
Copy link
Contributor

@aminalaee aminalaee commented Jun 11, 2022

Change Summary

Allows BaseModel to have fields of type Type[] and generate JSON schema.

Related issue number

Fixes #4051 and fixes #2916 .

Checklist

  • Unit tests for the changes exist
  • Tests pass on CI and coverage remains at 100%
  • Documentation reflects the changes where applicable
  • changes/<pull request or issue id>-<github username>.md file added describing change
    (see changes/README.md for details)
  • My PR is ready to review, please add a comment including the phrase "please review" to assign reviewers

@aminalaee
Copy link
Contributor Author

aminalaee commented Jun 11, 2022

please review

@hramezani
Copy link
Member

Thanks @aminalaee for the patch 👍

I've tested your fix locally and it raises ValueError if the class type doesn't inherit from BaseModel

here is the eaxmple:

from pydantic import BaseModel
from typing import Type

class Test:
    b: int

class TypeTest(BaseModel):
  t: Type[Test]

print(TypeTest.schema())

it will raise

raise ValueError(f'Value not declarable with JSON Schema, field: {field}')
ValueError: Value not declarable with JSON Schema, field: name='t' type=Type[__main__.Test] required=True

@hramezani
Copy link
Member

please update

@github-actions github-actions bot added awaiting author revision awaiting changes from the PR author and removed ready for review labels Jul 18, 2022
@github-actions github-actions bot assigned aminalaee and unassigned samuelcolvin and PrettyWood Jul 18, 2022
@samuelcolvin
Copy link
Member

Also conflicts, @aminalaee do you think you'll be able to look at this?

@aminalaee
Copy link
Contributor Author

aminalaee commented Aug 8, 2022

Yes if it's not a very high priority I can take a look to fix this.
Otherwise I can close it.

@samuelcolvin
Copy link
Member

I think best to fix it if you have time 🙏, V1.10 won't be out until earliest the end of the week.

@aminalaee
Copy link
Contributor Author

aminalaee commented Aug 8, 2022

@hramezani I'm not sure how that would be possible since in your example Test does not inherit from BaseModel so there's no way to get the schema from it.
The validation part will not be changed and is already tested in some tests like:

pydantic/tests/test_main.py

Lines 984 to 988 in d90def3

def test_bare_type_type_validation_success():
class ArbitraryClassAllowedModel(BaseModel):
t: Type
arbitrary_type_class = ArbitraryType

So to my understanding this is the current situation, both validation and schema will work for this:

from pydantic import BaseModel
from typing import Type

class Test(BaseModel):
    a: int

class TypeTest(BaseModel):
  t: Type[Test]

since the Test is inheriting from BaseModel.

But for cases like this which are also mentioned in the docs here, the schema() won't work since there's no way to get the schema, but validation works ok:

from pydantic import BaseModel
from typing import Type

class Test:
    b: int

class TypeTest(BaseModel):
  t: Type[Test]

# Or

class TypeTest(BaseModel):
    t: Type

I guess this has been the behaviour all along.

I think in some issues they are referring to the first case which will be fixed by this like #4051 and #2916 and some the second case which really is a wrong usage (IMO) like #3390

@aminalaee
Copy link
Contributor Author

please review

@github-actions github-actions bot added ready for review and removed awaiting author revision awaiting changes from the PR author labels Aug 8, 2022
@hramezani
Copy link
Member

Thanks @aminalaee for your update!

Copy link
Member

@samuelcolvin samuelcolvin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be re-thought. We also need tests for other types that don't inherit from BaseModel.

'type': 'object',
'properties': {'a': {'title': 'A', 'type': 'integer'}, 'b': {'$ref': '#/definitions/Foo'}},
'required': ['a', 'b'],
'definitions': {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct, this is saying b should be an instance of Foo, but the type says "b should be Foo or a subclass of Foo".

I assume there's no equivalent in JSONSchema since you can't encode "the type Foo" in JSON, so I assume we'll need to use a generic "any" or similar.

@samuelcolvin
Copy link
Member

please update.

@github-actions github-actions bot added awaiting author revision awaiting changes from the PR author and removed ready for review labels Aug 9, 2022
@aminalaee
Copy link
Contributor Author

aminalaee commented Aug 9, 2022

Thanks for the review, I've changed it to behave as Any I hope this makes sense

@github-actions github-actions bot added ready for review and removed awaiting author revision awaiting changes from the PR author labels Aug 9, 2022
Copy link
Member

@samuelcolvin samuelcolvin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otherwise LGTM.

changes/4051-aminalaee.md Outdated Show resolved Hide resolved
@samuelcolvin samuelcolvin enabled auto-merge (squash) August 11, 2022 10:37
@samuelcolvin
Copy link
Member

Thank so much.

@samuelcolvin samuelcolvin merged commit fa6b978 into pydantic:master Aug 11, 2022
@aminalaee aminalaee deleted the allow-model-fields-have-type-type branch August 11, 2022 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants