sqlmodel icon indicating copy to clipboard operation
sqlmodel copied to clipboard

✨ Support `pattern` parameter

Open stickm4n opened this issue 1 year ago • 15 comments

I faced this issue with Pydantic V2 and there is a simple workaround to it by passing the pattern Field parameter as schema extra:

Ex:

class MyClass(SQLModel)
    id: str = Field(unique=True, schema_extra={'pattern': r"^\d{5}$"})

I don't know if this issue was already fixed in another branch, I saw there was a temporary PR already made but closed.

stickm4n avatar Dec 01 '24 21:12 stickm4n

@tiangolo @alejsdev or some other maintainer... could you please review this issue?

stickm4n avatar Dec 11 '24 22:12 stickm4n

Thanks for the PR! We're going through the backlog of PRs right now, and will get back to you once we've had the time to review this and consider the (breaking) change 🙏

svlandeg avatar Feb 20 '25 15:02 svlandeg

@svlandeg Nice to hear you are taking action on this matter. There is remark, the parameter the was renamed between Pydantic v1 and v2 is regex-> pattern, not as listed in the PR.

The suggestion I made in the PR was to keep both versions compatible when upgrading, but there is an alternative, which is not managing the change between them and just provide the proper type hints.

If you want me to update the PR just let me know, IDK which approach is more adequate for the project.

stickm4n avatar Feb 22 '25 14:02 stickm4n

@stickM4N, could you please clarify why this should be treated as breaking change?

Apart from that, should we add a test for new parameter?

YuriiMotov avatar Aug 05 '25 16:08 YuriiMotov

Hi @YuriiMotov, nice to hear from you again. Sorry for not have given a better description for the problem, but here it is:

from sqlmodel import SQLModel, Field

class MyClass(SQLModel):
    id: str = Field(unique=True, pattern=r"^\d{5}$")

This code raises TypeError: Field() got an unexpected keyword argument 'pattern' which is the intended keyword for pydantic.v2.FieldInfo, differet from regex for pydantic.v1.FieldInfo The aim of this PR is to make them compatible and have the same logic for both version sqlmodel-wise

I have other proposition that is more comfortable to work with in my opinion, but its more of a change... and its to convert schema_extra param to **schema_extra, so the input from sqlmodel.Field is more flexible, should not have impacts in other places and it add flexibility to implementations and simpler way to migrate from pydantic.Field to sqlmodel.Field

stickm4n avatar Aug 08 '25 06:08 stickm4n

Since we still support regex parameter and just add alias (pattern) and make it working with Pydantic V2, I wouldn't call these changes braking. So, I would remove the mention of breaking.

Also, I think we should mark regex as deprecated and prioritize pattern over regexp regardless the version of Pydantic.

Still we need to add some test:

  • pass regex and validate valid\invalid value
  • pass pattern and validate valid\invalid value
  • pass both regex and pattern and see that pattern is used
  • don't pass pattern directly, but pass schema_extra={"pattern": r"..."} (workaround that is currently being used to make it working with Pydantic V2) - it should still work

YuriiMotov avatar Aug 23 '25 12:08 YuriiMotov

Noted @YuriiMotov, I will do that. Here there is the reference to the removed parameter and error raise associated to it. Here is its implementation.

I would like to propose the following change:

def Field(default, *, ..., **schema_extra)

rather than

def Field(default, *, ..., schema_extra)

stickm4n avatar Aug 28 '25 04:08 stickm4n

I would like to propose the following change:

def Field(default, *, ..., **schema_extra)

I think this should be done in a separate PR. And I would do it in a different way - I would add pydantic_kwargs and json_schema_extra parameters and deprecate schema_extra.


Could you please address other ideas from this comment?

YuriiMotov avatar Sep 09 '25 08:09 YuriiMotov

I think this should be done in a separate PR. And I would do it in a different way - I would add pydantic_kwargs and json_schema_extra parameters and deprecate schema_extra. Fine by me!

Since we still support regex parameter and just add alias (pattern) and make it working with Pydantic V2, I wouldn't call these changes braking. So, I would remove the mention of breaking.

Regarding this, I would still label it as breaking because pydantic.v2 does not support the keyarg and will raise an error if provided. You can check the docs and the implementation for farther details.

Tests

  • [x] pass regex and validate valid\invalid value.
  • [x] pass pattern and validate valid\invalid value.
  • [ ] ~pass both regex and pattern and see that pattern is used~ -> this is implicitly tested because if its V1 pattern will not work and if its V2 the test will raise an error.
  • [x] don't pass pattern directly, but pass schema_extra={"pattern": r"..."} (workaround that is currently being used to make it working with Pydantic V2) -> kept for compatibility, might be removed in the future

stickm4n avatar Sep 09 '25 22:09 stickm4n

Regarding this, I would still label it as breaking because pydantic.v2 does not support the keyarg and will raise an error if provided. You can check the docs and the implementation for farther details.

I still can't get it.. Could you please share a code example that works in current version (0.0.24) but will be broken after applying changes from this PR?

YuriiMotov avatar Sep 10 '25 14:09 YuriiMotov

I still can't get it.. Could you please share a code example that works in current version (0.0.24) but will be broken after applying changes from this PR?

No, it will break now, after migrating from pydantic.v1 to pydantic.v2 without changing parameters from Field(...). This PR will provide a solution for that rather than create an incompatibility. Maybe i misunderstood the label breaking meaning.

stickm4n avatar Sep 10 '25 16:09 stickm4n

No, it will break now, after migrating from pydantic.v1 to pydantic.v2 without changing parameters from Field(...). This PR will provide a solution for that rather than create an incompatibility. Maybe i misunderstood the label breaking meaning.

So, it's not breaking. Breaking changes is when new changes brake old user's code that worked without errors previously

YuriiMotov avatar Sep 10 '25 17:09 YuriiMotov

So, it's not breaking. Breaking changes is when new changes brake old user's code that worked without errors previously

Noted! Thanks

stickm4n avatar Sep 10 '25 22:09 stickm4n

Tests currently fail because new Pydantic version has been released and caused linting errors. See: https://github.com/fastapi/sqlmodel/pull/1591

YuriiMotov avatar Oct 07 '25 20:10 YuriiMotov

Thanks! I think we should wait for #1035 to be reviewed by Sebastian and merged, then reflect those changes in this PR. So, let's wait a bit

YuriiMotov avatar Oct 13 '25 08:10 YuriiMotov