⬆️ Add support for Python 3.13 - #1289

Merged
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python
Mar 6, 2025
Merged

⬆️ Add support for Python 3.13#1289
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python

Conversation

@svlandeg

@svlandegsvlandeg commented Feb 7, 2025

Copy link
Copy Markdown
Member

This ended up needing more changes than I had expected:

  • To allow a valid resolution of dependencies, for Python 3.13 we need to allow a higher version of typing-extensions. This then allows us to pull in Pydantic 2.8+ which supports Python 3.13.
  • If we keep the upper version of Pydantic unbounded (fastapi imposes "only" pydanctic<3.0.0), we would currently pull in Pydantic v.2.10
  • Since Pydantic 2.10.0, the definition of IncEx has changed, which means we need to change it as well or we'll get mypy errors complaining about violating the Liskov substitution principle
  • In SQLModelMetaclass, when we redefine model_fields, we'd get this mypy error:
sqlmodel\main.py:482: error: Incompatible types in assignment (expression has type "dict[str, sqlmodel.main.FieldInfo]", base class "ModelMetaclass" defined the type as "dict[str, pydantic.fields.FieldInfo]") [assignment]

But I don't think we really need to redefine it? We'll be able to pass in a sqlmodel.main.FieldInfo object whereever a pydantic.fields.FieldInfo is expected, and the rest of the code base / tests / type checks don't seem to complain when we remove the redefinition (L482).

As discussed below with Tiangolo, this PR now just adds an ignore statement for this.

@svlandeg
svlandeg marked this pull request as draft February 7, 2025 10:08
@svlandeg

svlandeg commented Feb 7, 2025

Copy link
Copy Markdown
MemberAuthor

I'll fix the test suite first in a separate PR.

[UPDATE: done]

@svlandegsvlandeg self-assigned this Feb 7, 2025
@github-actions

This comment was marked as outdated.

@svlandegsvlandeg left a comment

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Test suite for Python 3.13 is currently failing because pydantic-core==2.18.4 can't get installed with PyO3 0.21.2 on Python 3.13. We need PyO3 v0.22.0 or higher as that version supports Python 3.13, but I'm not sure yet why it's not pulling in the latest version - probably some other dependency is imposing an upper bound.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

Ok, some progress: sqlmodel's pin on typing-extensions was preventing us to use the latest pydantic version compatible with Python 3.13. If we relax that pin, we can get correct Pydantic versions for Python 3.13. The CI is then still failing with a linting error, which I'll look into now.

[UPDATE]: these linting errors appear because we're upgrading to Pydantic 2.10.6 (they don't appear when using Pydantic 2.9.2 for instance)

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandegsvlandeg removed their assignment Mar 4, 2025
@svlandeg
svlandeg marked this pull request as ready for review March 4, 2025 09:57
@tiangolo

Copy link
Copy Markdown
Member

Whoa, this was a lot of work! 😱

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅 If 3.7 is being problematic again in the future, let me know and we can just drop support for it. Maybe we can just do it soon, preemptively, it's already too old. I wanted to include any easy bug fixes in and make a final 3.7 release before dropping support, but if there's no single bug fix release to make, we can just drop it. We should also do it soon for 3.8 as well, we'll get into the same issues soon. 😬

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant). I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

It's also not common for people to extend that in Pydantic, it's not a fully public object (it's not documented), so I don't judge it and wouldn't necessarily expect them to change it. 😅

Nevertheless, our code should be okay, so we could add a # type: ignore there and it would be fine.

Now, what do we get from our definition?

Whenever someone tries to iterate on the model fields of a model, they would get autocompletion and inline errors for our custom extra attributes. E.g.:

forfinHero.model_fields.values():
print(f.index)

In this case, they would get autocompletion for f.index.

...but, checking that code, I also realize that it is not properly typed, those extra attributes have no types, so they show as existing, but as Any. So, the "advantage" we could get is not even properly/fully implemented yet.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

What do you think?

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅

Hehe, gotcha. The most time was spent on actually figuring out WHY uv's dependency resolution tracked back to such an old version of Pydantic. Once I found out that the typing-extensions pin was the culprit, the fix was actually an easy one.

But yes - I agree we could drop 3.7 (and maybe even 3.8) to avoid these kind of issues in the future.

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant).

Yep - exactly - that's the issue.

I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

Yep - that's my understanding as well.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 5b1f617 at: https://1205cfb7.sqlmodel.pages.dev

@tiangolo

Copy link
Copy Markdown
Member

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

Yep, I think so, we expect people to use sqlmodel.Field instead of pydantic.Field, so we would always have our own custom FieldInfo there. So, yep, I think that makes sense. 🤓

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thank you for all the work put into this! 🚀

@tiangolo
tiangolo merged commit b1349da into fastapi:mainMar 6, 2025
@svlandeg
svlandeg deleted the update/python branch March 6, 2025 20:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@svlandeg@tiangolo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

⬆️ Add support for Python 3.13 - #1289

Merged
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python
Mar 6, 2025
Merged

⬆️ Add support for Python 3.13#1289
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python

Conversation

@svlandeg

@svlandegsvlandeg commented Feb 7, 2025

Copy link
Copy Markdown
Member

This ended up needing more changes than I had expected:

  • To allow a valid resolution of dependencies, for Python 3.13 we need to allow a higher version of typing-extensions. This then allows us to pull in Pydantic 2.8+ which supports Python 3.13.
  • If we keep the upper version of Pydantic unbounded (fastapi imposes "only" pydanctic<3.0.0), we would currently pull in Pydantic v.2.10
  • Since Pydantic 2.10.0, the definition of IncEx has changed, which means we need to change it as well or we'll get mypy errors complaining about violating the Liskov substitution principle
  • In SQLModelMetaclass, when we redefine model_fields, we'd get this mypy error:
sqlmodel\main.py:482: error: Incompatible types in assignment (expression has type "dict[str, sqlmodel.main.FieldInfo]", base class "ModelMetaclass" defined the type as "dict[str, pydantic.fields.FieldInfo]") [assignment]

But I don't think we really need to redefine it? We'll be able to pass in a sqlmodel.main.FieldInfo object whereever a pydantic.fields.FieldInfo is expected, and the rest of the code base / tests / type checks don't seem to complain when we remove the redefinition (L482).

As discussed below with Tiangolo, this PR now just adds an ignore statement for this.

@svlandeg
svlandeg marked this pull request as draft February 7, 2025 10:08
@svlandeg

svlandeg commented Feb 7, 2025

Copy link
Copy Markdown
MemberAuthor

I'll fix the test suite first in a separate PR.

[UPDATE: done]

@svlandegsvlandeg self-assigned this Feb 7, 2025
@github-actions

This comment was marked as outdated.

@svlandegsvlandeg left a comment

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Test suite for Python 3.13 is currently failing because pydantic-core==2.18.4 can't get installed with PyO3 0.21.2 on Python 3.13. We need PyO3 v0.22.0 or higher as that version supports Python 3.13, but I'm not sure yet why it's not pulling in the latest version - probably some other dependency is imposing an upper bound.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

Ok, some progress: sqlmodel's pin on typing-extensions was preventing us to use the latest pydantic version compatible with Python 3.13. If we relax that pin, we can get correct Pydantic versions for Python 3.13. The CI is then still failing with a linting error, which I'll look into now.

[UPDATE]: these linting errors appear because we're upgrading to Pydantic 2.10.6 (they don't appear when using Pydantic 2.9.2 for instance)

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandegsvlandeg removed their assignment Mar 4, 2025
@svlandeg
svlandeg marked this pull request as ready for review March 4, 2025 09:57
@tiangolo

Copy link
Copy Markdown
Member

Whoa, this was a lot of work! 😱

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅 If 3.7 is being problematic again in the future, let me know and we can just drop support for it. Maybe we can just do it soon, preemptively, it's already too old. I wanted to include any easy bug fixes in and make a final 3.7 release before dropping support, but if there's no single bug fix release to make, we can just drop it. We should also do it soon for 3.8 as well, we'll get into the same issues soon. 😬

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant). I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

It's also not common for people to extend that in Pydantic, it's not a fully public object (it's not documented), so I don't judge it and wouldn't necessarily expect them to change it. 😅

Nevertheless, our code should be okay, so we could add a # type: ignore there and it would be fine.

Now, what do we get from our definition?

Whenever someone tries to iterate on the model fields of a model, they would get autocompletion and inline errors for our custom extra attributes. E.g.:

forfinHero.model_fields.values():
print(f.index)

In this case, they would get autocompletion for f.index.

...but, checking that code, I also realize that it is not properly typed, those extra attributes have no types, so they show as existing, but as Any. So, the "advantage" we could get is not even properly/fully implemented yet.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

What do you think?

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅

Hehe, gotcha. The most time was spent on actually figuring out WHY uv's dependency resolution tracked back to such an old version of Pydantic. Once I found out that the typing-extensions pin was the culprit, the fix was actually an easy one.

But yes - I agree we could drop 3.7 (and maybe even 3.8) to avoid these kind of issues in the future.

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant).

Yep - exactly - that's the issue.

I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

Yep - that's my understanding as well.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 5b1f617 at: https://1205cfb7.sqlmodel.pages.dev

@tiangolo

Copy link
Copy Markdown
Member

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

Yep, I think so, we expect people to use sqlmodel.Field instead of pydantic.Field, so we would always have our own custom FieldInfo there. So, yep, I think that makes sense. 🤓

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thank you for all the work put into this! 🚀

@tiangolo
tiangolo merged commit b1349da into fastapi:mainMar 6, 2025
@svlandeg
svlandeg deleted the update/python branch March 6, 2025 20:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@svlandeg@tiangolo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

⬆️ Add support for Python 3.13 - #1289

Merged
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python
Mar 6, 2025
Merged

⬆️ Add support for Python 3.13#1289
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python

Conversation

@svlandeg

@svlandegsvlandeg commented Feb 7, 2025

Copy link
Copy Markdown
Member

This ended up needing more changes than I had expected:

  • To allow a valid resolution of dependencies, for Python 3.13 we need to allow a higher version of typing-extensions. This then allows us to pull in Pydantic 2.8+ which supports Python 3.13.
  • If we keep the upper version of Pydantic unbounded (fastapi imposes "only" pydanctic<3.0.0), we would currently pull in Pydantic v.2.10
  • Since Pydantic 2.10.0, the definition of IncEx has changed, which means we need to change it as well or we'll get mypy errors complaining about violating the Liskov substitution principle
  • In SQLModelMetaclass, when we redefine model_fields, we'd get this mypy error:
sqlmodel\main.py:482: error: Incompatible types in assignment (expression has type "dict[str, sqlmodel.main.FieldInfo]", base class "ModelMetaclass" defined the type as "dict[str, pydantic.fields.FieldInfo]") [assignment]

But I don't think we really need to redefine it? We'll be able to pass in a sqlmodel.main.FieldInfo object whereever a pydantic.fields.FieldInfo is expected, and the rest of the code base / tests / type checks don't seem to complain when we remove the redefinition (L482).

As discussed below with Tiangolo, this PR now just adds an ignore statement for this.

@svlandeg
svlandeg marked this pull request as draft February 7, 2025 10:08
@svlandeg

svlandeg commented Feb 7, 2025

Copy link
Copy Markdown
MemberAuthor

I'll fix the test suite first in a separate PR.

[UPDATE: done]

@svlandegsvlandeg self-assigned this Feb 7, 2025
@github-actions

This comment was marked as outdated.

@svlandegsvlandeg left a comment

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Test suite for Python 3.13 is currently failing because pydantic-core==2.18.4 can't get installed with PyO3 0.21.2 on Python 3.13. We need PyO3 v0.22.0 or higher as that version supports Python 3.13, but I'm not sure yet why it's not pulling in the latest version - probably some other dependency is imposing an upper bound.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

Ok, some progress: sqlmodel's pin on typing-extensions was preventing us to use the latest pydantic version compatible with Python 3.13. If we relax that pin, we can get correct Pydantic versions for Python 3.13. The CI is then still failing with a linting error, which I'll look into now.

[UPDATE]: these linting errors appear because we're upgrading to Pydantic 2.10.6 (they don't appear when using Pydantic 2.9.2 for instance)

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandegsvlandeg removed their assignment Mar 4, 2025
@svlandeg
svlandeg marked this pull request as ready for review March 4, 2025 09:57
@tiangolo

Copy link
Copy Markdown
Member

Whoa, this was a lot of work! 😱

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅 If 3.7 is being problematic again in the future, let me know and we can just drop support for it. Maybe we can just do it soon, preemptively, it's already too old. I wanted to include any easy bug fixes in and make a final 3.7 release before dropping support, but if there's no single bug fix release to make, we can just drop it. We should also do it soon for 3.8 as well, we'll get into the same issues soon. 😬

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant). I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

It's also not common for people to extend that in Pydantic, it's not a fully public object (it's not documented), so I don't judge it and wouldn't necessarily expect them to change it. 😅

Nevertheless, our code should be okay, so we could add a # type: ignore there and it would be fine.

Now, what do we get from our definition?

Whenever someone tries to iterate on the model fields of a model, they would get autocompletion and inline errors for our custom extra attributes. E.g.:

forfinHero.model_fields.values():
print(f.index)

In this case, they would get autocompletion for f.index.

...but, checking that code, I also realize that it is not properly typed, those extra attributes have no types, so they show as existing, but as Any. So, the "advantage" we could get is not even properly/fully implemented yet.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

What do you think?

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅

Hehe, gotcha. The most time was spent on actually figuring out WHY uv's dependency resolution tracked back to such an old version of Pydantic. Once I found out that the typing-extensions pin was the culprit, the fix was actually an easy one.

But yes - I agree we could drop 3.7 (and maybe even 3.8) to avoid these kind of issues in the future.

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant).

Yep - exactly - that's the issue.

I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

Yep - that's my understanding as well.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 5b1f617 at: https://1205cfb7.sqlmodel.pages.dev

@tiangolo

Copy link
Copy Markdown
Member

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

Yep, I think so, we expect people to use sqlmodel.Field instead of pydantic.Field, so we would always have our own custom FieldInfo there. So, yep, I think that makes sense. 🤓

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thank you for all the work put into this! 🚀

@tiangolo
tiangolo merged commit b1349da into fastapi:mainMar 6, 2025
@svlandeg
svlandeg deleted the update/python branch March 6, 2025 20:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@svlandeg@tiangolo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

⬆️ Add support for Python 3.13 - #1289

Merged
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python
Mar 6, 2025
Merged

⬆️ Add support for Python 3.13#1289
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python

Conversation

@svlandeg

@svlandegsvlandeg commented Feb 7, 2025

Copy link
Copy Markdown
Member

This ended up needing more changes than I had expected:

  • To allow a valid resolution of dependencies, for Python 3.13 we need to allow a higher version of typing-extensions. This then allows us to pull in Pydantic 2.8+ which supports Python 3.13.
  • If we keep the upper version of Pydantic unbounded (fastapi imposes "only" pydanctic<3.0.0), we would currently pull in Pydantic v.2.10
  • Since Pydantic 2.10.0, the definition of IncEx has changed, which means we need to change it as well or we'll get mypy errors complaining about violating the Liskov substitution principle
  • In SQLModelMetaclass, when we redefine model_fields, we'd get this mypy error:
sqlmodel\main.py:482: error: Incompatible types in assignment (expression has type "dict[str, sqlmodel.main.FieldInfo]", base class "ModelMetaclass" defined the type as "dict[str, pydantic.fields.FieldInfo]") [assignment]

But I don't think we really need to redefine it? We'll be able to pass in a sqlmodel.main.FieldInfo object whereever a pydantic.fields.FieldInfo is expected, and the rest of the code base / tests / type checks don't seem to complain when we remove the redefinition (L482).

As discussed below with Tiangolo, this PR now just adds an ignore statement for this.

@svlandeg
svlandeg marked this pull request as draft February 7, 2025 10:08
@svlandeg

svlandeg commented Feb 7, 2025

Copy link
Copy Markdown
MemberAuthor

I'll fix the test suite first in a separate PR.

[UPDATE: done]

@svlandegsvlandeg self-assigned this Feb 7, 2025
@github-actions

This comment was marked as outdated.

@svlandegsvlandeg left a comment

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Test suite for Python 3.13 is currently failing because pydantic-core==2.18.4 can't get installed with PyO3 0.21.2 on Python 3.13. We need PyO3 v0.22.0 or higher as that version supports Python 3.13, but I'm not sure yet why it's not pulling in the latest version - probably some other dependency is imposing an upper bound.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

Ok, some progress: sqlmodel's pin on typing-extensions was preventing us to use the latest pydantic version compatible with Python 3.13. If we relax that pin, we can get correct Pydantic versions for Python 3.13. The CI is then still failing with a linting error, which I'll look into now.

[UPDATE]: these linting errors appear because we're upgrading to Pydantic 2.10.6 (they don't appear when using Pydantic 2.9.2 for instance)

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandegsvlandeg removed their assignment Mar 4, 2025
@svlandeg
svlandeg marked this pull request as ready for review March 4, 2025 09:57
@tiangolo

Copy link
Copy Markdown
Member

Whoa, this was a lot of work! 😱

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅 If 3.7 is being problematic again in the future, let me know and we can just drop support for it. Maybe we can just do it soon, preemptively, it's already too old. I wanted to include any easy bug fixes in and make a final 3.7 release before dropping support, but if there's no single bug fix release to make, we can just drop it. We should also do it soon for 3.8 as well, we'll get into the same issues soon. 😬

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant). I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

It's also not common for people to extend that in Pydantic, it's not a fully public object (it's not documented), so I don't judge it and wouldn't necessarily expect them to change it. 😅

Nevertheless, our code should be okay, so we could add a # type: ignore there and it would be fine.

Now, what do we get from our definition?

Whenever someone tries to iterate on the model fields of a model, they would get autocompletion and inline errors for our custom extra attributes. E.g.:

forfinHero.model_fields.values():
print(f.index)

In this case, they would get autocompletion for f.index.

...but, checking that code, I also realize that it is not properly typed, those extra attributes have no types, so they show as existing, but as Any. So, the "advantage" we could get is not even properly/fully implemented yet.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

What do you think?

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅

Hehe, gotcha. The most time was spent on actually figuring out WHY uv's dependency resolution tracked back to such an old version of Pydantic. Once I found out that the typing-extensions pin was the culprit, the fix was actually an easy one.

But yes - I agree we could drop 3.7 (and maybe even 3.8) to avoid these kind of issues in the future.

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant).

Yep - exactly - that's the issue.

I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

Yep - that's my understanding as well.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 5b1f617 at: https://1205cfb7.sqlmodel.pages.dev

@tiangolo

Copy link
Copy Markdown
Member

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

Yep, I think so, we expect people to use sqlmodel.Field instead of pydantic.Field, so we would always have our own custom FieldInfo there. So, yep, I think that makes sense. 🤓

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thank you for all the work put into this! 🚀

@tiangolo
tiangolo merged commit b1349da into fastapi:mainMar 6, 2025
@svlandeg
svlandeg deleted the update/python branch March 6, 2025 20:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@svlandeg@tiangolo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

⬆️ Add support for Python 3.13 - #1289

Merged
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python
Mar 6, 2025
Merged

⬆️ Add support for Python 3.13#1289
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python

Conversation

@svlandeg

@svlandegsvlandeg commented Feb 7, 2025

Copy link
Copy Markdown
Member

This ended up needing more changes than I had expected:

  • To allow a valid resolution of dependencies, for Python 3.13 we need to allow a higher version of typing-extensions. This then allows us to pull in Pydantic 2.8+ which supports Python 3.13.
  • If we keep the upper version of Pydantic unbounded (fastapi imposes "only" pydanctic<3.0.0), we would currently pull in Pydantic v.2.10
  • Since Pydantic 2.10.0, the definition of IncEx has changed, which means we need to change it as well or we'll get mypy errors complaining about violating the Liskov substitution principle
  • In SQLModelMetaclass, when we redefine model_fields, we'd get this mypy error:
sqlmodel\main.py:482: error: Incompatible types in assignment (expression has type "dict[str, sqlmodel.main.FieldInfo]", base class "ModelMetaclass" defined the type as "dict[str, pydantic.fields.FieldInfo]") [assignment]

But I don't think we really need to redefine it? We'll be able to pass in a sqlmodel.main.FieldInfo object whereever a pydantic.fields.FieldInfo is expected, and the rest of the code base / tests / type checks don't seem to complain when we remove the redefinition (L482).

As discussed below with Tiangolo, this PR now just adds an ignore statement for this.

@svlandeg
svlandeg marked this pull request as draft February 7, 2025 10:08
@svlandeg

svlandeg commented Feb 7, 2025

Copy link
Copy Markdown
MemberAuthor

I'll fix the test suite first in a separate PR.

[UPDATE: done]

@svlandegsvlandeg self-assigned this Feb 7, 2025
@github-actions

This comment was marked as outdated.

@svlandegsvlandeg left a comment

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Test suite for Python 3.13 is currently failing because pydantic-core==2.18.4 can't get installed with PyO3 0.21.2 on Python 3.13. We need PyO3 v0.22.0 or higher as that version supports Python 3.13, but I'm not sure yet why it's not pulling in the latest version - probably some other dependency is imposing an upper bound.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

Ok, some progress: sqlmodel's pin on typing-extensions was preventing us to use the latest pydantic version compatible with Python 3.13. If we relax that pin, we can get correct Pydantic versions for Python 3.13. The CI is then still failing with a linting error, which I'll look into now.

[UPDATE]: these linting errors appear because we're upgrading to Pydantic 2.10.6 (they don't appear when using Pydantic 2.9.2 for instance)

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandegsvlandeg removed their assignment Mar 4, 2025
@svlandeg
svlandeg marked this pull request as ready for review March 4, 2025 09:57
@tiangolo

Copy link
Copy Markdown
Member

Whoa, this was a lot of work! 😱

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅 If 3.7 is being problematic again in the future, let me know and we can just drop support for it. Maybe we can just do it soon, preemptively, it's already too old. I wanted to include any easy bug fixes in and make a final 3.7 release before dropping support, but if there's no single bug fix release to make, we can just drop it. We should also do it soon for 3.8 as well, we'll get into the same issues soon. 😬

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant). I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

It's also not common for people to extend that in Pydantic, it's not a fully public object (it's not documented), so I don't judge it and wouldn't necessarily expect them to change it. 😅

Nevertheless, our code should be okay, so we could add a # type: ignore there and it would be fine.

Now, what do we get from our definition?

Whenever someone tries to iterate on the model fields of a model, they would get autocompletion and inline errors for our custom extra attributes. E.g.:

forfinHero.model_fields.values():
print(f.index)

In this case, they would get autocompletion for f.index.

...but, checking that code, I also realize that it is not properly typed, those extra attributes have no types, so they show as existing, but as Any. So, the "advantage" we could get is not even properly/fully implemented yet.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

What do you think?

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅

Hehe, gotcha. The most time was spent on actually figuring out WHY uv's dependency resolution tracked back to such an old version of Pydantic. Once I found out that the typing-extensions pin was the culprit, the fix was actually an easy one.

But yes - I agree we could drop 3.7 (and maybe even 3.8) to avoid these kind of issues in the future.

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant).

Yep - exactly - that's the issue.

I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

Yep - that's my understanding as well.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 5b1f617 at: https://1205cfb7.sqlmodel.pages.dev

@tiangolo

Copy link
Copy Markdown
Member

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

Yep, I think so, we expect people to use sqlmodel.Field instead of pydantic.Field, so we would always have our own custom FieldInfo there. So, yep, I think that makes sense. 🤓

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thank you for all the work put into this! 🚀

@tiangolo
tiangolo merged commit b1349da into fastapi:mainMar 6, 2025
@svlandeg
svlandeg deleted the update/python branch March 6, 2025 20:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@svlandeg@tiangolo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

⬆️ Add support for Python 3.13 - #1289

Merged
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python
Mar 6, 2025
Merged

⬆️ Add support for Python 3.13#1289
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python

Conversation

@svlandeg

@svlandegsvlandeg commented Feb 7, 2025

Copy link
Copy Markdown
Member

This ended up needing more changes than I had expected:

  • To allow a valid resolution of dependencies, for Python 3.13 we need to allow a higher version of typing-extensions. This then allows us to pull in Pydantic 2.8+ which supports Python 3.13.
  • If we keep the upper version of Pydantic unbounded (fastapi imposes "only" pydanctic<3.0.0), we would currently pull in Pydantic v.2.10
  • Since Pydantic 2.10.0, the definition of IncEx has changed, which means we need to change it as well or we'll get mypy errors complaining about violating the Liskov substitution principle
  • In SQLModelMetaclass, when we redefine model_fields, we'd get this mypy error:
sqlmodel\main.py:482: error: Incompatible types in assignment (expression has type "dict[str, sqlmodel.main.FieldInfo]", base class "ModelMetaclass" defined the type as "dict[str, pydantic.fields.FieldInfo]") [assignment]

But I don't think we really need to redefine it? We'll be able to pass in a sqlmodel.main.FieldInfo object whereever a pydantic.fields.FieldInfo is expected, and the rest of the code base / tests / type checks don't seem to complain when we remove the redefinition (L482).

As discussed below with Tiangolo, this PR now just adds an ignore statement for this.

@svlandeg
svlandeg marked this pull request as draft February 7, 2025 10:08
@svlandeg

svlandeg commented Feb 7, 2025

Copy link
Copy Markdown
MemberAuthor

I'll fix the test suite first in a separate PR.

[UPDATE: done]

@svlandegsvlandeg self-assigned this Feb 7, 2025
@github-actions

This comment was marked as outdated.

@svlandegsvlandeg left a comment

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Test suite for Python 3.13 is currently failing because pydantic-core==2.18.4 can't get installed with PyO3 0.21.2 on Python 3.13. We need PyO3 v0.22.0 or higher as that version supports Python 3.13, but I'm not sure yet why it's not pulling in the latest version - probably some other dependency is imposing an upper bound.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

Ok, some progress: sqlmodel's pin on typing-extensions was preventing us to use the latest pydantic version compatible with Python 3.13. If we relax that pin, we can get correct Pydantic versions for Python 3.13. The CI is then still failing with a linting error, which I'll look into now.

[UPDATE]: these linting errors appear because we're upgrading to Pydantic 2.10.6 (they don't appear when using Pydantic 2.9.2 for instance)

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandegsvlandeg removed their assignment Mar 4, 2025
@svlandeg
svlandeg marked this pull request as ready for review March 4, 2025 09:57
@tiangolo

Copy link
Copy Markdown
Member

Whoa, this was a lot of work! 😱

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅 If 3.7 is being problematic again in the future, let me know and we can just drop support for it. Maybe we can just do it soon, preemptively, it's already too old. I wanted to include any easy bug fixes in and make a final 3.7 release before dropping support, but if there's no single bug fix release to make, we can just drop it. We should also do it soon for 3.8 as well, we'll get into the same issues soon. 😬

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant). I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

It's also not common for people to extend that in Pydantic, it's not a fully public object (it's not documented), so I don't judge it and wouldn't necessarily expect them to change it. 😅

Nevertheless, our code should be okay, so we could add a # type: ignore there and it would be fine.

Now, what do we get from our definition?

Whenever someone tries to iterate on the model fields of a model, they would get autocompletion and inline errors for our custom extra attributes. E.g.:

forfinHero.model_fields.values():
print(f.index)

In this case, they would get autocompletion for f.index.

...but, checking that code, I also realize that it is not properly typed, those extra attributes have no types, so they show as existing, but as Any. So, the "advantage" we could get is not even properly/fully implemented yet.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

What do you think?

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅

Hehe, gotcha. The most time was spent on actually figuring out WHY uv's dependency resolution tracked back to such an old version of Pydantic. Once I found out that the typing-extensions pin was the culprit, the fix was actually an easy one.

But yes - I agree we could drop 3.7 (and maybe even 3.8) to avoid these kind of issues in the future.

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant).

Yep - exactly - that's the issue.

I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

Yep - that's my understanding as well.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 5b1f617 at: https://1205cfb7.sqlmodel.pages.dev

@tiangolo

Copy link
Copy Markdown
Member

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

Yep, I think so, we expect people to use sqlmodel.Field instead of pydantic.Field, so we would always have our own custom FieldInfo there. So, yep, I think that makes sense. 🤓

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thank you for all the work put into this! 🚀

@tiangolo
tiangolo merged commit b1349da into fastapi:mainMar 6, 2025
@svlandeg
svlandeg deleted the update/python branch March 6, 2025 20:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@svlandeg@tiangolo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

⬆️ Add support for Python 3.13 - #1289

Merged
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python
Mar 6, 2025
Merged

⬆️ Add support for Python 3.13#1289
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python

Conversation

@svlandeg

@svlandegsvlandeg commented Feb 7, 2025

Copy link
Copy Markdown
Member

This ended up needing more changes than I had expected:

  • To allow a valid resolution of dependencies, for Python 3.13 we need to allow a higher version of typing-extensions. This then allows us to pull in Pydantic 2.8+ which supports Python 3.13.
  • If we keep the upper version of Pydantic unbounded (fastapi imposes "only" pydanctic<3.0.0), we would currently pull in Pydantic v.2.10
  • Since Pydantic 2.10.0, the definition of IncEx has changed, which means we need to change it as well or we'll get mypy errors complaining about violating the Liskov substitution principle
  • In SQLModelMetaclass, when we redefine model_fields, we'd get this mypy error:
sqlmodel\main.py:482: error: Incompatible types in assignment (expression has type "dict[str, sqlmodel.main.FieldInfo]", base class "ModelMetaclass" defined the type as "dict[str, pydantic.fields.FieldInfo]") [assignment]

But I don't think we really need to redefine it? We'll be able to pass in a sqlmodel.main.FieldInfo object whereever a pydantic.fields.FieldInfo is expected, and the rest of the code base / tests / type checks don't seem to complain when we remove the redefinition (L482).

As discussed below with Tiangolo, this PR now just adds an ignore statement for this.

@svlandeg
svlandeg marked this pull request as draft February 7, 2025 10:08
@svlandeg

svlandeg commented Feb 7, 2025

Copy link
Copy Markdown
MemberAuthor

I'll fix the test suite first in a separate PR.

[UPDATE: done]

@svlandegsvlandeg self-assigned this Feb 7, 2025
@github-actions

This comment was marked as outdated.

@svlandegsvlandeg left a comment

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Test suite for Python 3.13 is currently failing because pydantic-core==2.18.4 can't get installed with PyO3 0.21.2 on Python 3.13. We need PyO3 v0.22.0 or higher as that version supports Python 3.13, but I'm not sure yet why it's not pulling in the latest version - probably some other dependency is imposing an upper bound.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

Ok, some progress: sqlmodel's pin on typing-extensions was preventing us to use the latest pydantic version compatible with Python 3.13. If we relax that pin, we can get correct Pydantic versions for Python 3.13. The CI is then still failing with a linting error, which I'll look into now.

[UPDATE]: these linting errors appear because we're upgrading to Pydantic 2.10.6 (they don't appear when using Pydantic 2.9.2 for instance)

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandegsvlandeg removed their assignment Mar 4, 2025
@svlandeg
svlandeg marked this pull request as ready for review March 4, 2025 09:57
@tiangolo

Copy link
Copy Markdown
Member

Whoa, this was a lot of work! 😱

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅 If 3.7 is being problematic again in the future, let me know and we can just drop support for it. Maybe we can just do it soon, preemptively, it's already too old. I wanted to include any easy bug fixes in and make a final 3.7 release before dropping support, but if there's no single bug fix release to make, we can just drop it. We should also do it soon for 3.8 as well, we'll get into the same issues soon. 😬

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant). I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

It's also not common for people to extend that in Pydantic, it's not a fully public object (it's not documented), so I don't judge it and wouldn't necessarily expect them to change it. 😅

Nevertheless, our code should be okay, so we could add a # type: ignore there and it would be fine.

Now, what do we get from our definition?

Whenever someone tries to iterate on the model fields of a model, they would get autocompletion and inline errors for our custom extra attributes. E.g.:

forfinHero.model_fields.values():
print(f.index)

In this case, they would get autocompletion for f.index.

...but, checking that code, I also realize that it is not properly typed, those extra attributes have no types, so they show as existing, but as Any. So, the "advantage" we could get is not even properly/fully implemented yet.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

What do you think?

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅

Hehe, gotcha. The most time was spent on actually figuring out WHY uv's dependency resolution tracked back to such an old version of Pydantic. Once I found out that the typing-extensions pin was the culprit, the fix was actually an easy one.

But yes - I agree we could drop 3.7 (and maybe even 3.8) to avoid these kind of issues in the future.

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant).

Yep - exactly - that's the issue.

I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

Yep - that's my understanding as well.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 5b1f617 at: https://1205cfb7.sqlmodel.pages.dev

@tiangolo

Copy link
Copy Markdown
Member

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

Yep, I think so, we expect people to use sqlmodel.Field instead of pydantic.Field, so we would always have our own custom FieldInfo there. So, yep, I think that makes sense. 🤓

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thank you for all the work put into this! 🚀

@tiangolo
tiangolo merged commit b1349da into fastapi:mainMar 6, 2025
@svlandeg
svlandeg deleted the update/python branch March 6, 2025 20:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@svlandeg@tiangolo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

⬆️ Add support for Python 3.13 - #1289

Merged
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python
Mar 6, 2025
Merged

⬆️ Add support for Python 3.13#1289
tiangolo merged 10 commits into
fastapi:mainfrom
svlandeg:update/python

Conversation

@svlandeg

@svlandegsvlandeg commented Feb 7, 2025

Copy link
Copy Markdown
Member

This ended up needing more changes than I had expected:

  • To allow a valid resolution of dependencies, for Python 3.13 we need to allow a higher version of typing-extensions. This then allows us to pull in Pydantic 2.8+ which supports Python 3.13.
  • If we keep the upper version of Pydantic unbounded (fastapi imposes "only" pydanctic<3.0.0), we would currently pull in Pydantic v.2.10
  • Since Pydantic 2.10.0, the definition of IncEx has changed, which means we need to change it as well or we'll get mypy errors complaining about violating the Liskov substitution principle
  • In SQLModelMetaclass, when we redefine model_fields, we'd get this mypy error:
sqlmodel\main.py:482: error: Incompatible types in assignment (expression has type "dict[str, sqlmodel.main.FieldInfo]", base class "ModelMetaclass" defined the type as "dict[str, pydantic.fields.FieldInfo]") [assignment]

But I don't think we really need to redefine it? We'll be able to pass in a sqlmodel.main.FieldInfo object whereever a pydantic.fields.FieldInfo is expected, and the rest of the code base / tests / type checks don't seem to complain when we remove the redefinition (L482).

As discussed below with Tiangolo, this PR now just adds an ignore statement for this.

@svlandeg
svlandeg marked this pull request as draft February 7, 2025 10:08
@svlandeg

svlandeg commented Feb 7, 2025

Copy link
Copy Markdown
MemberAuthor

I'll fix the test suite first in a separate PR.

[UPDATE: done]

@svlandegsvlandeg self-assigned this Feb 7, 2025
@github-actions

This comment was marked as outdated.

@svlandegsvlandeg left a comment

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Test suite for Python 3.13 is currently failing because pydantic-core==2.18.4 can't get installed with PyO3 0.21.2 on Python 3.13. We need PyO3 v0.22.0 or higher as that version supports Python 3.13, but I'm not sure yet why it's not pulling in the latest version - probably some other dependency is imposing an upper bound.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

Ok, some progress: sqlmodel's pin on typing-extensions was preventing us to use the latest pydantic version compatible with Python 3.13. If we relax that pin, we can get correct Pydantic versions for Python 3.13. The CI is then still failing with a linting error, which I'll look into now.

[UPDATE]: these linting errors appear because we're upgrading to Pydantic 2.10.6 (they don't appear when using Pydantic 2.9.2 for instance)

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

@svlandegsvlandeg removed their assignment Mar 4, 2025
@svlandeg
svlandeg marked this pull request as ready for review March 4, 2025 09:57
@tiangolo

Copy link
Copy Markdown
Member

Whoa, this was a lot of work! 😱

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅 If 3.7 is being problematic again in the future, let me know and we can just drop support for it. Maybe we can just do it soon, preemptively, it's already too old. I wanted to include any easy bug fixes in and make a final 3.7 release before dropping support, but if there's no single bug fix release to make, we can just drop it. We should also do it soon for 3.8 as well, we'll get into the same issues soon. 😬

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant). I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

It's also not common for people to extend that in Pydantic, it's not a fully public object (it's not documented), so I don't judge it and wouldn't necessarily expect them to change it. 😅

Nevertheless, our code should be okay, so we could add a # type: ignore there and it would be fine.

Now, what do we get from our definition?

Whenever someone tries to iterate on the model fields of a model, they would get autocompletion and inline errors for our custom extra attributes. E.g.:

forfinHero.model_fields.values():
print(f.index)

In this case, they would get autocompletion for f.index.

...but, checking that code, I also realize that it is not properly typed, those extra attributes have no types, so they show as existing, but as Any. So, the "advantage" we could get is not even properly/fully implemented yet.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

What do you think?

@svlandeg

svlandeg commented Mar 4, 2025

Copy link
Copy Markdown
MemberAuthor

If dropping support for Python 3.7 would have made this easier, I would have definitely accepted it, just so you know you don't have to battle it so hard. 😅

Hehe, gotcha. The most time was spent on actually figuring out WHY uv's dependency resolution tracked back to such an old version of Pydantic. Once I found out that the typing-extensions pin was the culprit, the fix was actually an easy one.

But yes - I agree we could drop 3.7 (and maybe even 3.8) to avoid these kind of issues in the future.

About model_fields

I'm pretty sure the problem is that Pydantic has it defined as a dict[str, pydantic.fields.FieldInfo] and dict doesn't support subclasses of the parameters defined (the erudite term is "invariant" I think 😅, dict is invariant).

Yep - exactly - that's the issue.

I suspect they don't really need it to be a dict, it could be any mapping, so Mapping[str, pydantic.fields.FieldInfo] would have probably worked as well, and Mapping allows subclasses in the value types (erudite term: Mapping is covariant in the second parameter, if I'm not wrong).

Yep - that's my understanding as well.

I would say we can add a type ignore and later in another PR add the types, just to save the autocompletion there, not sure how useful and used it is, but maybe.

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 5b1f617 at: https://1205cfb7.sqlmodel.pages.dev

@tiangolo

Copy link
Copy Markdown
Member

I see what you mean with respect to having (potentially future) access to better autocompletion & type hints when we keep the redefinition to the dictionary containing sqlmodel's FieldInfo objects. I assume we would never really expect to add Pydantic's FieldInfo objects into SQLModelMetaclass, right? In that case I agree that we can just add the ignore. I'll push that change.

Yep, I think so, we expect people to use sqlmodel.Field instead of pydantic.Field, so we would always have our own custom FieldInfo there. So, yep, I think that makes sense. 🤓

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thank you for all the work put into this! 🚀

@tiangolo
tiangolo merged commit b1349da into fastapi:mainMar 6, 2025
@svlandeg
svlandeg deleted the update/python branch March 6, 2025 20:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@svlandeg@tiangolo