🐛 Fix AsyncSession type annotations for exec() - #58

Merged
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix
Oct 23, 2023
Merged

🐛 Fix AsyncSession type annotations for exec()#58
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix

Conversation

@Bobronium

@BobroniumBobronium commented Aug 29, 2021

Copy link
Copy Markdown
Contributor

Fixes#54

hero.py:

importasyncioimportinspectimportsysfromcontextlibimportsuppressfrompathlibimportPathfromtypingimportOptional, TYPE_CHECKINGfrommypy.mainimportmainasmypy_mainfromsqlalchemy.ext.asyncioimportcreate_async_enginefromsqlmodelimportField, SQLModel, selectfromsqlmodel.ext.asyncio.sessionimportAsyncSessionclassHero(SQLModel, table=True):
id: Optional[int] =Field(default=None, primary_key=True)
name: strsecret_name: strage: Optional[int] =Noneasyncdefmain() ->None:
engine=create_async_engine("sqlite+aiosqlite:///:memory:")
asyncwithengine.begin() asconn:
awaitconn.run_sync(SQLModel.metadata.create_all)
asyncwithAsyncSession(engine) assession:
session.add(Hero(name="Spider-Boy", secret_name="Pedro Parqueador"))
awaitsession.commit()
asyncwithAsyncSession(engine) assession:
statement=select(Hero).where(Hero.name=="Spider-Boy")
reveal_type(session)
result=awaitsession.exec(statement)
reveal_type(result)
h=result.first()
reveal_type(h)
ifnotTYPE_CHECKING:
defreveal_type(obj):
f_back=inspect.currentframe().f_backfilename=f_back.f_globals["__file__"]
withsuppress(ValueError):
filename=Path(filename).relative_to(Path.cwd())
print(f"{filename}:{f_back.f_lineno}: note: Runtime value is {obj!r}")
print("Running main()")
asyncio.run(main())
print("\nRunning mypy (first run may take some time)")
mypy_main(None, stdout=sys.stdout, stderr=sys.stderr, args=[__file__])

Running on main

Runningmain()
hero.py:33: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x10314f9a0>hero.py:35: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x10308bdc0>hero.py:37: note: RuntimevalueisHero(age=None, name='Spider-Boy', secret_name='Pedro Parqueador', id=1)
Runningmypy (firstrunmaytakesometime)
hero.py:33: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:34: error: Needtypeannotationfor'result'hero.py:34: error: Argument1to"exec"of"AsyncSession"hasincompatibletype"SelectOfScalar[Hero]"; expected"Union[Select[<nothing>], Executable[<nothing>]]"hero.py:35: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult[Any]'hero.py:37: note: Revealedtypeis'Union[Any, None]'Found2errorsin1file (checked1sourcefile)

Running on Bobronium:AsyncSession_typing_fix:

Runningmain()
hero.py:43: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x102a0f940>hero.py:45: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x1029e9190>hero.py:47: note: RuntimevalueisHero(name='Spider-Boy', secret_name='Pedro Parqueador', id=1, age=None)
Runningmypy (firstrunmaytakesometime)
hero.py:43: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:45: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult*[hero.Hero*]'hero.py:47: note: Revealedtypeis'Union[hero.Hero*, None]'

image

@Bobronium
Bobroniumforce-pushed the AsyncSession_typing_fix branch from 894c60d to 8d578a9CompareAugust 29, 2021 11:03
@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, is this PR or #54 going to be addressed?

@priyansh-anand

Copy link
Copy Markdown

Thanks for the feature! Until this PR gets merged, manually patching will work for my workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 11ff44f at: https://639cfc052b35ad15e2e48091--sqlmodel.netlify.app

@Bobronium

Bobronium commented Jan 12, 2023

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I can try to resolve CI issues and update the branch, but I need a confirmation that you have intention of merging it once issues are resolved and willing to communicate if I'll need any feedback on resolving them. Complete lack of comminucation from your side on this issue is frustrating.

I don't want to waste any more time on this PR only to find it in the same condition a year later.

@maresb

Copy link
Copy Markdown

Thanks @Bobronium for the fix, I am pip installing your branch instead of v0.0.8. I hope this gets merged soon.

@diego-escobedo

Copy link
Copy Markdown

Crazy this has been around since 2021. Awesome work @Bobronium on this.

adamsanaglo pushed a commit to adamsanaglo/pulpcore that referenced this pull request Jul 13, 2023
The whole point of SQLModel is that it returns typed objects that play nice with Pydantic and allow your editor's autocomplete functions to work properly. Except when you're using `sqlalchemy.AsyncSession`, it... doesn't. And there *is* a `sqlmodel.AsyncSession`, but it's broken. And there is a *fix* for it in an upstream PR, but it's not merged yet.
fastapi/sqlmodel#58
This PR just copies and uses the upstream PR implementation of `sqlmodel.AsyncSession`. Most of the actual diff here is related to the side-benefit that we no longer have to unwrap the row-tuples that `sqlalchemy.execute` returns, but most of the actual benefit for doing this is that we'll now actually get our appropriately-typed model objects back out of `session.exec` instead of `Any`.
Related work items: #15767106
@ornakash

Copy link
Copy Markdown

Please merge this?

@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I've fixed CI issue.

Tests are passing now.

Please merge.

@tiangolotiangolo added the bug Something isn't working label Oct 22, 2023
@tiangolo

Copy link
Copy Markdown
Member

Great, thanks @Bobronium! 🚀

Thanks everyone for the comments, in particular confirming this solved it for you. 🍰

Thanks for the patience everyone!

This will be available in the next version, 0.0.9. 🎉

@tiangolotiangolo changed the title Fix AsyncSession annotations🐛 Fix AsyncSession type annotations for exec()Oct 23, 2023
@tiangolo
tiangolo merged commit 9732c5a into fastapi:mainOct 23, 2023
shabani1 added a commit to lexy-ai/lexy that referenced this pull request Nov 3, 2023
# What
This updates SQLModel to version 0.0.11, which solves an
[issue](fastapi/sqlmodel#443) with foreign key
declaration, and another
[issue](fastapi/sqlmodel#58) with AsyncSession
type annotations.
# Why
Prior to this update, attempting to delete a document with an associated
index record would throw a foreign key violation error.
# Test plan
Add a document which results in an index record being created. Delete
the same document and verify that
- The document is deleted without error
- The index records associated with the document are also deleted
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSession does not play well with typing and autocompletion

6 participants

@Bobronium@priyansh-anand@maresb@diego-escobedo@ornakash@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

🐛 Fix AsyncSession type annotations for exec() - #58

Merged
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix
Oct 23, 2023
Merged

🐛 Fix AsyncSession type annotations for exec()#58
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix

Conversation

@Bobronium

@BobroniumBobronium commented Aug 29, 2021

Copy link
Copy Markdown
Contributor

Fixes#54

hero.py:

importasyncioimportinspectimportsysfromcontextlibimportsuppressfrompathlibimportPathfromtypingimportOptional, TYPE_CHECKINGfrommypy.mainimportmainasmypy_mainfromsqlalchemy.ext.asyncioimportcreate_async_enginefromsqlmodelimportField, SQLModel, selectfromsqlmodel.ext.asyncio.sessionimportAsyncSessionclassHero(SQLModel, table=True):
id: Optional[int] =Field(default=None, primary_key=True)
name: strsecret_name: strage: Optional[int] =Noneasyncdefmain() ->None:
engine=create_async_engine("sqlite+aiosqlite:///:memory:")
asyncwithengine.begin() asconn:
awaitconn.run_sync(SQLModel.metadata.create_all)
asyncwithAsyncSession(engine) assession:
session.add(Hero(name="Spider-Boy", secret_name="Pedro Parqueador"))
awaitsession.commit()
asyncwithAsyncSession(engine) assession:
statement=select(Hero).where(Hero.name=="Spider-Boy")
reveal_type(session)
result=awaitsession.exec(statement)
reveal_type(result)
h=result.first()
reveal_type(h)
ifnotTYPE_CHECKING:
defreveal_type(obj):
f_back=inspect.currentframe().f_backfilename=f_back.f_globals["__file__"]
withsuppress(ValueError):
filename=Path(filename).relative_to(Path.cwd())
print(f"{filename}:{f_back.f_lineno}: note: Runtime value is {obj!r}")
print("Running main()")
asyncio.run(main())
print("\nRunning mypy (first run may take some time)")
mypy_main(None, stdout=sys.stdout, stderr=sys.stderr, args=[__file__])

Running on main

Runningmain()
hero.py:33: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x10314f9a0>hero.py:35: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x10308bdc0>hero.py:37: note: RuntimevalueisHero(age=None, name='Spider-Boy', secret_name='Pedro Parqueador', id=1)
Runningmypy (firstrunmaytakesometime)
hero.py:33: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:34: error: Needtypeannotationfor'result'hero.py:34: error: Argument1to"exec"of"AsyncSession"hasincompatibletype"SelectOfScalar[Hero]"; expected"Union[Select[<nothing>], Executable[<nothing>]]"hero.py:35: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult[Any]'hero.py:37: note: Revealedtypeis'Union[Any, None]'Found2errorsin1file (checked1sourcefile)

Running on Bobronium:AsyncSession_typing_fix:

Runningmain()
hero.py:43: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x102a0f940>hero.py:45: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x1029e9190>hero.py:47: note: RuntimevalueisHero(name='Spider-Boy', secret_name='Pedro Parqueador', id=1, age=None)
Runningmypy (firstrunmaytakesometime)
hero.py:43: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:45: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult*[hero.Hero*]'hero.py:47: note: Revealedtypeis'Union[hero.Hero*, None]'

image

@Bobronium
Bobroniumforce-pushed the AsyncSession_typing_fix branch from 894c60d to 8d578a9CompareAugust 29, 2021 11:03
@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, is this PR or #54 going to be addressed?

@priyansh-anand

Copy link
Copy Markdown

Thanks for the feature! Until this PR gets merged, manually patching will work for my workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 11ff44f at: https://639cfc052b35ad15e2e48091--sqlmodel.netlify.app

@Bobronium

Bobronium commented Jan 12, 2023

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I can try to resolve CI issues and update the branch, but I need a confirmation that you have intention of merging it once issues are resolved and willing to communicate if I'll need any feedback on resolving them. Complete lack of comminucation from your side on this issue is frustrating.

I don't want to waste any more time on this PR only to find it in the same condition a year later.

@maresb

Copy link
Copy Markdown

Thanks @Bobronium for the fix, I am pip installing your branch instead of v0.0.8. I hope this gets merged soon.

@diego-escobedo

Copy link
Copy Markdown

Crazy this has been around since 2021. Awesome work @Bobronium on this.

adamsanaglo pushed a commit to adamsanaglo/pulpcore that referenced this pull request Jul 13, 2023
The whole point of SQLModel is that it returns typed objects that play nice with Pydantic and allow your editor's autocomplete functions to work properly. Except when you're using `sqlalchemy.AsyncSession`, it... doesn't. And there *is* a `sqlmodel.AsyncSession`, but it's broken. And there is a *fix* for it in an upstream PR, but it's not merged yet.
fastapi/sqlmodel#58
This PR just copies and uses the upstream PR implementation of `sqlmodel.AsyncSession`. Most of the actual diff here is related to the side-benefit that we no longer have to unwrap the row-tuples that `sqlalchemy.execute` returns, but most of the actual benefit for doing this is that we'll now actually get our appropriately-typed model objects back out of `session.exec` instead of `Any`.
Related work items: #15767106
@ornakash

Copy link
Copy Markdown

Please merge this?

@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I've fixed CI issue.

Tests are passing now.

Please merge.

@tiangolotiangolo added the bug Something isn't working label Oct 22, 2023
@tiangolo

Copy link
Copy Markdown
Member

Great, thanks @Bobronium! 🚀

Thanks everyone for the comments, in particular confirming this solved it for you. 🍰

Thanks for the patience everyone!

This will be available in the next version, 0.0.9. 🎉

@tiangolotiangolo changed the title Fix AsyncSession annotations🐛 Fix AsyncSession type annotations for exec()Oct 23, 2023
@tiangolo
tiangolo merged commit 9732c5a into fastapi:mainOct 23, 2023
shabani1 added a commit to lexy-ai/lexy that referenced this pull request Nov 3, 2023
# What
This updates SQLModel to version 0.0.11, which solves an
[issue](fastapi/sqlmodel#443) with foreign key
declaration, and another
[issue](fastapi/sqlmodel#58) with AsyncSession
type annotations.
# Why
Prior to this update, attempting to delete a document with an associated
index record would throw a foreign key violation error.
# Test plan
Add a document which results in an index record being created. Delete
the same document and verify that
- The document is deleted without error
- The index records associated with the document are also deleted
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSession does not play well with typing and autocompletion

6 participants

@Bobronium@priyansh-anand@maresb@diego-escobedo@ornakash@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

🐛 Fix AsyncSession type annotations for exec() - #58

Merged
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix
Oct 23, 2023
Merged

🐛 Fix AsyncSession type annotations for exec()#58
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix

Conversation

@Bobronium

@BobroniumBobronium commented Aug 29, 2021

Copy link
Copy Markdown
Contributor

Fixes#54

hero.py:

importasyncioimportinspectimportsysfromcontextlibimportsuppressfrompathlibimportPathfromtypingimportOptional, TYPE_CHECKINGfrommypy.mainimportmainasmypy_mainfromsqlalchemy.ext.asyncioimportcreate_async_enginefromsqlmodelimportField, SQLModel, selectfromsqlmodel.ext.asyncio.sessionimportAsyncSessionclassHero(SQLModel, table=True):
id: Optional[int] =Field(default=None, primary_key=True)
name: strsecret_name: strage: Optional[int] =Noneasyncdefmain() ->None:
engine=create_async_engine("sqlite+aiosqlite:///:memory:")
asyncwithengine.begin() asconn:
awaitconn.run_sync(SQLModel.metadata.create_all)
asyncwithAsyncSession(engine) assession:
session.add(Hero(name="Spider-Boy", secret_name="Pedro Parqueador"))
awaitsession.commit()
asyncwithAsyncSession(engine) assession:
statement=select(Hero).where(Hero.name=="Spider-Boy")
reveal_type(session)
result=awaitsession.exec(statement)
reveal_type(result)
h=result.first()
reveal_type(h)
ifnotTYPE_CHECKING:
defreveal_type(obj):
f_back=inspect.currentframe().f_backfilename=f_back.f_globals["__file__"]
withsuppress(ValueError):
filename=Path(filename).relative_to(Path.cwd())
print(f"{filename}:{f_back.f_lineno}: note: Runtime value is {obj!r}")
print("Running main()")
asyncio.run(main())
print("\nRunning mypy (first run may take some time)")
mypy_main(None, stdout=sys.stdout, stderr=sys.stderr, args=[__file__])

Running on main

Runningmain()
hero.py:33: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x10314f9a0>hero.py:35: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x10308bdc0>hero.py:37: note: RuntimevalueisHero(age=None, name='Spider-Boy', secret_name='Pedro Parqueador', id=1)
Runningmypy (firstrunmaytakesometime)
hero.py:33: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:34: error: Needtypeannotationfor'result'hero.py:34: error: Argument1to"exec"of"AsyncSession"hasincompatibletype"SelectOfScalar[Hero]"; expected"Union[Select[<nothing>], Executable[<nothing>]]"hero.py:35: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult[Any]'hero.py:37: note: Revealedtypeis'Union[Any, None]'Found2errorsin1file (checked1sourcefile)

Running on Bobronium:AsyncSession_typing_fix:

Runningmain()
hero.py:43: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x102a0f940>hero.py:45: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x1029e9190>hero.py:47: note: RuntimevalueisHero(name='Spider-Boy', secret_name='Pedro Parqueador', id=1, age=None)
Runningmypy (firstrunmaytakesometime)
hero.py:43: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:45: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult*[hero.Hero*]'hero.py:47: note: Revealedtypeis'Union[hero.Hero*, None]'

image

@Bobronium
Bobroniumforce-pushed the AsyncSession_typing_fix branch from 894c60d to 8d578a9CompareAugust 29, 2021 11:03
@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, is this PR or #54 going to be addressed?

@priyansh-anand

Copy link
Copy Markdown

Thanks for the feature! Until this PR gets merged, manually patching will work for my workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 11ff44f at: https://639cfc052b35ad15e2e48091--sqlmodel.netlify.app

@Bobronium

Bobronium commented Jan 12, 2023

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I can try to resolve CI issues and update the branch, but I need a confirmation that you have intention of merging it once issues are resolved and willing to communicate if I'll need any feedback on resolving them. Complete lack of comminucation from your side on this issue is frustrating.

I don't want to waste any more time on this PR only to find it in the same condition a year later.

@maresb

Copy link
Copy Markdown

Thanks @Bobronium for the fix, I am pip installing your branch instead of v0.0.8. I hope this gets merged soon.

@diego-escobedo

Copy link
Copy Markdown

Crazy this has been around since 2021. Awesome work @Bobronium on this.

adamsanaglo pushed a commit to adamsanaglo/pulpcore that referenced this pull request Jul 13, 2023
The whole point of SQLModel is that it returns typed objects that play nice with Pydantic and allow your editor's autocomplete functions to work properly. Except when you're using `sqlalchemy.AsyncSession`, it... doesn't. And there *is* a `sqlmodel.AsyncSession`, but it's broken. And there is a *fix* for it in an upstream PR, but it's not merged yet.
fastapi/sqlmodel#58
This PR just copies and uses the upstream PR implementation of `sqlmodel.AsyncSession`. Most of the actual diff here is related to the side-benefit that we no longer have to unwrap the row-tuples that `sqlalchemy.execute` returns, but most of the actual benefit for doing this is that we'll now actually get our appropriately-typed model objects back out of `session.exec` instead of `Any`.
Related work items: #15767106
@ornakash

Copy link
Copy Markdown

Please merge this?

@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I've fixed CI issue.

Tests are passing now.

Please merge.

@tiangolotiangolo added the bug Something isn't working label Oct 22, 2023
@tiangolo

Copy link
Copy Markdown
Member

Great, thanks @Bobronium! 🚀

Thanks everyone for the comments, in particular confirming this solved it for you. 🍰

Thanks for the patience everyone!

This will be available in the next version, 0.0.9. 🎉

@tiangolotiangolo changed the title Fix AsyncSession annotations🐛 Fix AsyncSession type annotations for exec()Oct 23, 2023
@tiangolo
tiangolo merged commit 9732c5a into fastapi:mainOct 23, 2023
shabani1 added a commit to lexy-ai/lexy that referenced this pull request Nov 3, 2023
# What
This updates SQLModel to version 0.0.11, which solves an
[issue](fastapi/sqlmodel#443) with foreign key
declaration, and another
[issue](fastapi/sqlmodel#58) with AsyncSession
type annotations.
# Why
Prior to this update, attempting to delete a document with an associated
index record would throw a foreign key violation error.
# Test plan
Add a document which results in an index record being created. Delete
the same document and verify that
- The document is deleted without error
- The index records associated with the document are also deleted
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSession does not play well with typing and autocompletion

6 participants

@Bobronium@priyansh-anand@maresb@diego-escobedo@ornakash@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

🐛 Fix AsyncSession type annotations for exec() - #58

Merged
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix
Oct 23, 2023
Merged

🐛 Fix AsyncSession type annotations for exec()#58
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix

Conversation

@Bobronium

@BobroniumBobronium commented Aug 29, 2021

Copy link
Copy Markdown
Contributor

Fixes#54

hero.py:

importasyncioimportinspectimportsysfromcontextlibimportsuppressfrompathlibimportPathfromtypingimportOptional, TYPE_CHECKINGfrommypy.mainimportmainasmypy_mainfromsqlalchemy.ext.asyncioimportcreate_async_enginefromsqlmodelimportField, SQLModel, selectfromsqlmodel.ext.asyncio.sessionimportAsyncSessionclassHero(SQLModel, table=True):
id: Optional[int] =Field(default=None, primary_key=True)
name: strsecret_name: strage: Optional[int] =Noneasyncdefmain() ->None:
engine=create_async_engine("sqlite+aiosqlite:///:memory:")
asyncwithengine.begin() asconn:
awaitconn.run_sync(SQLModel.metadata.create_all)
asyncwithAsyncSession(engine) assession:
session.add(Hero(name="Spider-Boy", secret_name="Pedro Parqueador"))
awaitsession.commit()
asyncwithAsyncSession(engine) assession:
statement=select(Hero).where(Hero.name=="Spider-Boy")
reveal_type(session)
result=awaitsession.exec(statement)
reveal_type(result)
h=result.first()
reveal_type(h)
ifnotTYPE_CHECKING:
defreveal_type(obj):
f_back=inspect.currentframe().f_backfilename=f_back.f_globals["__file__"]
withsuppress(ValueError):
filename=Path(filename).relative_to(Path.cwd())
print(f"{filename}:{f_back.f_lineno}: note: Runtime value is {obj!r}")
print("Running main()")
asyncio.run(main())
print("\nRunning mypy (first run may take some time)")
mypy_main(None, stdout=sys.stdout, stderr=sys.stderr, args=[__file__])

Running on main

Runningmain()
hero.py:33: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x10314f9a0>hero.py:35: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x10308bdc0>hero.py:37: note: RuntimevalueisHero(age=None, name='Spider-Boy', secret_name='Pedro Parqueador', id=1)
Runningmypy (firstrunmaytakesometime)
hero.py:33: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:34: error: Needtypeannotationfor'result'hero.py:34: error: Argument1to"exec"of"AsyncSession"hasincompatibletype"SelectOfScalar[Hero]"; expected"Union[Select[<nothing>], Executable[<nothing>]]"hero.py:35: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult[Any]'hero.py:37: note: Revealedtypeis'Union[Any, None]'Found2errorsin1file (checked1sourcefile)

Running on Bobronium:AsyncSession_typing_fix:

Runningmain()
hero.py:43: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x102a0f940>hero.py:45: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x1029e9190>hero.py:47: note: RuntimevalueisHero(name='Spider-Boy', secret_name='Pedro Parqueador', id=1, age=None)
Runningmypy (firstrunmaytakesometime)
hero.py:43: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:45: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult*[hero.Hero*]'hero.py:47: note: Revealedtypeis'Union[hero.Hero*, None]'

image

@Bobronium
Bobroniumforce-pushed the AsyncSession_typing_fix branch from 894c60d to 8d578a9CompareAugust 29, 2021 11:03
@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, is this PR or #54 going to be addressed?

@priyansh-anand

Copy link
Copy Markdown

Thanks for the feature! Until this PR gets merged, manually patching will work for my workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 11ff44f at: https://639cfc052b35ad15e2e48091--sqlmodel.netlify.app

@Bobronium

Bobronium commented Jan 12, 2023

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I can try to resolve CI issues and update the branch, but I need a confirmation that you have intention of merging it once issues are resolved and willing to communicate if I'll need any feedback on resolving them. Complete lack of comminucation from your side on this issue is frustrating.

I don't want to waste any more time on this PR only to find it in the same condition a year later.

@maresb

Copy link
Copy Markdown

Thanks @Bobronium for the fix, I am pip installing your branch instead of v0.0.8. I hope this gets merged soon.

@diego-escobedo

Copy link
Copy Markdown

Crazy this has been around since 2021. Awesome work @Bobronium on this.

adamsanaglo pushed a commit to adamsanaglo/pulpcore that referenced this pull request Jul 13, 2023
The whole point of SQLModel is that it returns typed objects that play nice with Pydantic and allow your editor's autocomplete functions to work properly. Except when you're using `sqlalchemy.AsyncSession`, it... doesn't. And there *is* a `sqlmodel.AsyncSession`, but it's broken. And there is a *fix* for it in an upstream PR, but it's not merged yet.
fastapi/sqlmodel#58
This PR just copies and uses the upstream PR implementation of `sqlmodel.AsyncSession`. Most of the actual diff here is related to the side-benefit that we no longer have to unwrap the row-tuples that `sqlalchemy.execute` returns, but most of the actual benefit for doing this is that we'll now actually get our appropriately-typed model objects back out of `session.exec` instead of `Any`.
Related work items: #15767106
@ornakash

Copy link
Copy Markdown

Please merge this?

@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I've fixed CI issue.

Tests are passing now.

Please merge.

@tiangolotiangolo added the bug Something isn't working label Oct 22, 2023
@tiangolo

Copy link
Copy Markdown
Member

Great, thanks @Bobronium! 🚀

Thanks everyone for the comments, in particular confirming this solved it for you. 🍰

Thanks for the patience everyone!

This will be available in the next version, 0.0.9. 🎉

@tiangolotiangolo changed the title Fix AsyncSession annotations🐛 Fix AsyncSession type annotations for exec()Oct 23, 2023
@tiangolo
tiangolo merged commit 9732c5a into fastapi:mainOct 23, 2023
shabani1 added a commit to lexy-ai/lexy that referenced this pull request Nov 3, 2023
# What
This updates SQLModel to version 0.0.11, which solves an
[issue](fastapi/sqlmodel#443) with foreign key
declaration, and another
[issue](fastapi/sqlmodel#58) with AsyncSession
type annotations.
# Why
Prior to this update, attempting to delete a document with an associated
index record would throw a foreign key violation error.
# Test plan
Add a document which results in an index record being created. Delete
the same document and verify that
- The document is deleted without error
- The index records associated with the document are also deleted
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSession does not play well with typing and autocompletion

6 participants

@Bobronium@priyansh-anand@maresb@diego-escobedo@ornakash@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

🐛 Fix AsyncSession type annotations for exec() - #58

Merged
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix
Oct 23, 2023
Merged

🐛 Fix AsyncSession type annotations for exec()#58
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix

Conversation

@Bobronium

@BobroniumBobronium commented Aug 29, 2021

Copy link
Copy Markdown
Contributor

Fixes#54

hero.py:

importasyncioimportinspectimportsysfromcontextlibimportsuppressfrompathlibimportPathfromtypingimportOptional, TYPE_CHECKINGfrommypy.mainimportmainasmypy_mainfromsqlalchemy.ext.asyncioimportcreate_async_enginefromsqlmodelimportField, SQLModel, selectfromsqlmodel.ext.asyncio.sessionimportAsyncSessionclassHero(SQLModel, table=True):
id: Optional[int] =Field(default=None, primary_key=True)
name: strsecret_name: strage: Optional[int] =Noneasyncdefmain() ->None:
engine=create_async_engine("sqlite+aiosqlite:///:memory:")
asyncwithengine.begin() asconn:
awaitconn.run_sync(SQLModel.metadata.create_all)
asyncwithAsyncSession(engine) assession:
session.add(Hero(name="Spider-Boy", secret_name="Pedro Parqueador"))
awaitsession.commit()
asyncwithAsyncSession(engine) assession:
statement=select(Hero).where(Hero.name=="Spider-Boy")
reveal_type(session)
result=awaitsession.exec(statement)
reveal_type(result)
h=result.first()
reveal_type(h)
ifnotTYPE_CHECKING:
defreveal_type(obj):
f_back=inspect.currentframe().f_backfilename=f_back.f_globals["__file__"]
withsuppress(ValueError):
filename=Path(filename).relative_to(Path.cwd())
print(f"{filename}:{f_back.f_lineno}: note: Runtime value is {obj!r}")
print("Running main()")
asyncio.run(main())
print("\nRunning mypy (first run may take some time)")
mypy_main(None, stdout=sys.stdout, stderr=sys.stderr, args=[__file__])

Running on main

Runningmain()
hero.py:33: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x10314f9a0>hero.py:35: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x10308bdc0>hero.py:37: note: RuntimevalueisHero(age=None, name='Spider-Boy', secret_name='Pedro Parqueador', id=1)
Runningmypy (firstrunmaytakesometime)
hero.py:33: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:34: error: Needtypeannotationfor'result'hero.py:34: error: Argument1to"exec"of"AsyncSession"hasincompatibletype"SelectOfScalar[Hero]"; expected"Union[Select[<nothing>], Executable[<nothing>]]"hero.py:35: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult[Any]'hero.py:37: note: Revealedtypeis'Union[Any, None]'Found2errorsin1file (checked1sourcefile)

Running on Bobronium:AsyncSession_typing_fix:

Runningmain()
hero.py:43: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x102a0f940>hero.py:45: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x1029e9190>hero.py:47: note: RuntimevalueisHero(name='Spider-Boy', secret_name='Pedro Parqueador', id=1, age=None)
Runningmypy (firstrunmaytakesometime)
hero.py:43: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:45: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult*[hero.Hero*]'hero.py:47: note: Revealedtypeis'Union[hero.Hero*, None]'

image

@Bobronium
Bobroniumforce-pushed the AsyncSession_typing_fix branch from 894c60d to 8d578a9CompareAugust 29, 2021 11:03
@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, is this PR or #54 going to be addressed?

@priyansh-anand

Copy link
Copy Markdown

Thanks for the feature! Until this PR gets merged, manually patching will work for my workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 11ff44f at: https://639cfc052b35ad15e2e48091--sqlmodel.netlify.app

@Bobronium

Bobronium commented Jan 12, 2023

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I can try to resolve CI issues and update the branch, but I need a confirmation that you have intention of merging it once issues are resolved and willing to communicate if I'll need any feedback on resolving them. Complete lack of comminucation from your side on this issue is frustrating.

I don't want to waste any more time on this PR only to find it in the same condition a year later.

@maresb

Copy link
Copy Markdown

Thanks @Bobronium for the fix, I am pip installing your branch instead of v0.0.8. I hope this gets merged soon.

@diego-escobedo

Copy link
Copy Markdown

Crazy this has been around since 2021. Awesome work @Bobronium on this.

adamsanaglo pushed a commit to adamsanaglo/pulpcore that referenced this pull request Jul 13, 2023
The whole point of SQLModel is that it returns typed objects that play nice with Pydantic and allow your editor's autocomplete functions to work properly. Except when you're using `sqlalchemy.AsyncSession`, it... doesn't. And there *is* a `sqlmodel.AsyncSession`, but it's broken. And there is a *fix* for it in an upstream PR, but it's not merged yet.
fastapi/sqlmodel#58
This PR just copies and uses the upstream PR implementation of `sqlmodel.AsyncSession`. Most of the actual diff here is related to the side-benefit that we no longer have to unwrap the row-tuples that `sqlalchemy.execute` returns, but most of the actual benefit for doing this is that we'll now actually get our appropriately-typed model objects back out of `session.exec` instead of `Any`.
Related work items: #15767106
@ornakash

Copy link
Copy Markdown

Please merge this?

@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I've fixed CI issue.

Tests are passing now.

Please merge.

@tiangolotiangolo added the bug Something isn't working label Oct 22, 2023
@tiangolo

Copy link
Copy Markdown
Member

Great, thanks @Bobronium! 🚀

Thanks everyone for the comments, in particular confirming this solved it for you. 🍰

Thanks for the patience everyone!

This will be available in the next version, 0.0.9. 🎉

@tiangolotiangolo changed the title Fix AsyncSession annotations🐛 Fix AsyncSession type annotations for exec()Oct 23, 2023
@tiangolo
tiangolo merged commit 9732c5a into fastapi:mainOct 23, 2023
shabani1 added a commit to lexy-ai/lexy that referenced this pull request Nov 3, 2023
# What
This updates SQLModel to version 0.0.11, which solves an
[issue](fastapi/sqlmodel#443) with foreign key
declaration, and another
[issue](fastapi/sqlmodel#58) with AsyncSession
type annotations.
# Why
Prior to this update, attempting to delete a document with an associated
index record would throw a foreign key violation error.
# Test plan
Add a document which results in an index record being created. Delete
the same document and verify that
- The document is deleted without error
- The index records associated with the document are also deleted
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSession does not play well with typing and autocompletion

6 participants

@Bobronium@priyansh-anand@maresb@diego-escobedo@ornakash@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

🐛 Fix AsyncSession type annotations for exec() - #58

Merged
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix
Oct 23, 2023
Merged

🐛 Fix AsyncSession type annotations for exec()#58
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix

Conversation

@Bobronium

@BobroniumBobronium commented Aug 29, 2021

Copy link
Copy Markdown
Contributor

Fixes#54

hero.py:

importasyncioimportinspectimportsysfromcontextlibimportsuppressfrompathlibimportPathfromtypingimportOptional, TYPE_CHECKINGfrommypy.mainimportmainasmypy_mainfromsqlalchemy.ext.asyncioimportcreate_async_enginefromsqlmodelimportField, SQLModel, selectfromsqlmodel.ext.asyncio.sessionimportAsyncSessionclassHero(SQLModel, table=True):
id: Optional[int] =Field(default=None, primary_key=True)
name: strsecret_name: strage: Optional[int] =Noneasyncdefmain() ->None:
engine=create_async_engine("sqlite+aiosqlite:///:memory:")
asyncwithengine.begin() asconn:
awaitconn.run_sync(SQLModel.metadata.create_all)
asyncwithAsyncSession(engine) assession:
session.add(Hero(name="Spider-Boy", secret_name="Pedro Parqueador"))
awaitsession.commit()
asyncwithAsyncSession(engine) assession:
statement=select(Hero).where(Hero.name=="Spider-Boy")
reveal_type(session)
result=awaitsession.exec(statement)
reveal_type(result)
h=result.first()
reveal_type(h)
ifnotTYPE_CHECKING:
defreveal_type(obj):
f_back=inspect.currentframe().f_backfilename=f_back.f_globals["__file__"]
withsuppress(ValueError):
filename=Path(filename).relative_to(Path.cwd())
print(f"{filename}:{f_back.f_lineno}: note: Runtime value is {obj!r}")
print("Running main()")
asyncio.run(main())
print("\nRunning mypy (first run may take some time)")
mypy_main(None, stdout=sys.stdout, stderr=sys.stderr, args=[__file__])

Running on main

Runningmain()
hero.py:33: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x10314f9a0>hero.py:35: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x10308bdc0>hero.py:37: note: RuntimevalueisHero(age=None, name='Spider-Boy', secret_name='Pedro Parqueador', id=1)
Runningmypy (firstrunmaytakesometime)
hero.py:33: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:34: error: Needtypeannotationfor'result'hero.py:34: error: Argument1to"exec"of"AsyncSession"hasincompatibletype"SelectOfScalar[Hero]"; expected"Union[Select[<nothing>], Executable[<nothing>]]"hero.py:35: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult[Any]'hero.py:37: note: Revealedtypeis'Union[Any, None]'Found2errorsin1file (checked1sourcefile)

Running on Bobronium:AsyncSession_typing_fix:

Runningmain()
hero.py:43: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x102a0f940>hero.py:45: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x1029e9190>hero.py:47: note: RuntimevalueisHero(name='Spider-Boy', secret_name='Pedro Parqueador', id=1, age=None)
Runningmypy (firstrunmaytakesometime)
hero.py:43: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:45: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult*[hero.Hero*]'hero.py:47: note: Revealedtypeis'Union[hero.Hero*, None]'

image

@Bobronium
Bobroniumforce-pushed the AsyncSession_typing_fix branch from 894c60d to 8d578a9CompareAugust 29, 2021 11:03
@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, is this PR or #54 going to be addressed?

@priyansh-anand

Copy link
Copy Markdown

Thanks for the feature! Until this PR gets merged, manually patching will work for my workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 11ff44f at: https://639cfc052b35ad15e2e48091--sqlmodel.netlify.app

@Bobronium

Bobronium commented Jan 12, 2023

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I can try to resolve CI issues and update the branch, but I need a confirmation that you have intention of merging it once issues are resolved and willing to communicate if I'll need any feedback on resolving them. Complete lack of comminucation from your side on this issue is frustrating.

I don't want to waste any more time on this PR only to find it in the same condition a year later.

@maresb

Copy link
Copy Markdown

Thanks @Bobronium for the fix, I am pip installing your branch instead of v0.0.8. I hope this gets merged soon.

@diego-escobedo

Copy link
Copy Markdown

Crazy this has been around since 2021. Awesome work @Bobronium on this.

adamsanaglo pushed a commit to adamsanaglo/pulpcore that referenced this pull request Jul 13, 2023
The whole point of SQLModel is that it returns typed objects that play nice with Pydantic and allow your editor's autocomplete functions to work properly. Except when you're using `sqlalchemy.AsyncSession`, it... doesn't. And there *is* a `sqlmodel.AsyncSession`, but it's broken. And there is a *fix* for it in an upstream PR, but it's not merged yet.
fastapi/sqlmodel#58
This PR just copies and uses the upstream PR implementation of `sqlmodel.AsyncSession`. Most of the actual diff here is related to the side-benefit that we no longer have to unwrap the row-tuples that `sqlalchemy.execute` returns, but most of the actual benefit for doing this is that we'll now actually get our appropriately-typed model objects back out of `session.exec` instead of `Any`.
Related work items: #15767106
@ornakash

Copy link
Copy Markdown

Please merge this?

@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I've fixed CI issue.

Tests are passing now.

Please merge.

@tiangolotiangolo added the bug Something isn't working label Oct 22, 2023
@tiangolo

Copy link
Copy Markdown
Member

Great, thanks @Bobronium! 🚀

Thanks everyone for the comments, in particular confirming this solved it for you. 🍰

Thanks for the patience everyone!

This will be available in the next version, 0.0.9. 🎉

@tiangolotiangolo changed the title Fix AsyncSession annotations🐛 Fix AsyncSession type annotations for exec()Oct 23, 2023
@tiangolo
tiangolo merged commit 9732c5a into fastapi:mainOct 23, 2023
shabani1 added a commit to lexy-ai/lexy that referenced this pull request Nov 3, 2023
# What
This updates SQLModel to version 0.0.11, which solves an
[issue](fastapi/sqlmodel#443) with foreign key
declaration, and another
[issue](fastapi/sqlmodel#58) with AsyncSession
type annotations.
# Why
Prior to this update, attempting to delete a document with an associated
index record would throw a foreign key violation error.
# Test plan
Add a document which results in an index record being created. Delete
the same document and verify that
- The document is deleted without error
- The index records associated with the document are also deleted
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSession does not play well with typing and autocompletion

6 participants

@Bobronium@priyansh-anand@maresb@diego-escobedo@ornakash@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

🐛 Fix AsyncSession type annotations for exec() - #58

Merged
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix
Oct 23, 2023
Merged

🐛 Fix AsyncSession type annotations for exec()#58
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix

Conversation

@Bobronium

@BobroniumBobronium commented Aug 29, 2021

Copy link
Copy Markdown
Contributor

Fixes#54

hero.py:

importasyncioimportinspectimportsysfromcontextlibimportsuppressfrompathlibimportPathfromtypingimportOptional, TYPE_CHECKINGfrommypy.mainimportmainasmypy_mainfromsqlalchemy.ext.asyncioimportcreate_async_enginefromsqlmodelimportField, SQLModel, selectfromsqlmodel.ext.asyncio.sessionimportAsyncSessionclassHero(SQLModel, table=True):
id: Optional[int] =Field(default=None, primary_key=True)
name: strsecret_name: strage: Optional[int] =Noneasyncdefmain() ->None:
engine=create_async_engine("sqlite+aiosqlite:///:memory:")
asyncwithengine.begin() asconn:
awaitconn.run_sync(SQLModel.metadata.create_all)
asyncwithAsyncSession(engine) assession:
session.add(Hero(name="Spider-Boy", secret_name="Pedro Parqueador"))
awaitsession.commit()
asyncwithAsyncSession(engine) assession:
statement=select(Hero).where(Hero.name=="Spider-Boy")
reveal_type(session)
result=awaitsession.exec(statement)
reveal_type(result)
h=result.first()
reveal_type(h)
ifnotTYPE_CHECKING:
defreveal_type(obj):
f_back=inspect.currentframe().f_backfilename=f_back.f_globals["__file__"]
withsuppress(ValueError):
filename=Path(filename).relative_to(Path.cwd())
print(f"{filename}:{f_back.f_lineno}: note: Runtime value is {obj!r}")
print("Running main()")
asyncio.run(main())
print("\nRunning mypy (first run may take some time)")
mypy_main(None, stdout=sys.stdout, stderr=sys.stderr, args=[__file__])

Running on main

Runningmain()
hero.py:33: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x10314f9a0>hero.py:35: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x10308bdc0>hero.py:37: note: RuntimevalueisHero(age=None, name='Spider-Boy', secret_name='Pedro Parqueador', id=1)
Runningmypy (firstrunmaytakesometime)
hero.py:33: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:34: error: Needtypeannotationfor'result'hero.py:34: error: Argument1to"exec"of"AsyncSession"hasincompatibletype"SelectOfScalar[Hero]"; expected"Union[Select[<nothing>], Executable[<nothing>]]"hero.py:35: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult[Any]'hero.py:37: note: Revealedtypeis'Union[Any, None]'Found2errorsin1file (checked1sourcefile)

Running on Bobronium:AsyncSession_typing_fix:

Runningmain()
hero.py:43: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x102a0f940>hero.py:45: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x1029e9190>hero.py:47: note: RuntimevalueisHero(name='Spider-Boy', secret_name='Pedro Parqueador', id=1, age=None)
Runningmypy (firstrunmaytakesometime)
hero.py:43: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:45: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult*[hero.Hero*]'hero.py:47: note: Revealedtypeis'Union[hero.Hero*, None]'

image

@Bobronium
Bobroniumforce-pushed the AsyncSession_typing_fix branch from 894c60d to 8d578a9CompareAugust 29, 2021 11:03
@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, is this PR or #54 going to be addressed?

@priyansh-anand

Copy link
Copy Markdown

Thanks for the feature! Until this PR gets merged, manually patching will work for my workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 11ff44f at: https://639cfc052b35ad15e2e48091--sqlmodel.netlify.app

@Bobronium

Bobronium commented Jan 12, 2023

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I can try to resolve CI issues and update the branch, but I need a confirmation that you have intention of merging it once issues are resolved and willing to communicate if I'll need any feedback on resolving them. Complete lack of comminucation from your side on this issue is frustrating.

I don't want to waste any more time on this PR only to find it in the same condition a year later.

@maresb

Copy link
Copy Markdown

Thanks @Bobronium for the fix, I am pip installing your branch instead of v0.0.8. I hope this gets merged soon.

@diego-escobedo

Copy link
Copy Markdown

Crazy this has been around since 2021. Awesome work @Bobronium on this.

adamsanaglo pushed a commit to adamsanaglo/pulpcore that referenced this pull request Jul 13, 2023
The whole point of SQLModel is that it returns typed objects that play nice with Pydantic and allow your editor's autocomplete functions to work properly. Except when you're using `sqlalchemy.AsyncSession`, it... doesn't. And there *is* a `sqlmodel.AsyncSession`, but it's broken. And there is a *fix* for it in an upstream PR, but it's not merged yet.
fastapi/sqlmodel#58
This PR just copies and uses the upstream PR implementation of `sqlmodel.AsyncSession`. Most of the actual diff here is related to the side-benefit that we no longer have to unwrap the row-tuples that `sqlalchemy.execute` returns, but most of the actual benefit for doing this is that we'll now actually get our appropriately-typed model objects back out of `session.exec` instead of `Any`.
Related work items: #15767106
@ornakash

Copy link
Copy Markdown

Please merge this?

@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I've fixed CI issue.

Tests are passing now.

Please merge.

@tiangolotiangolo added the bug Something isn't working label Oct 22, 2023
@tiangolo

Copy link
Copy Markdown
Member

Great, thanks @Bobronium! 🚀

Thanks everyone for the comments, in particular confirming this solved it for you. 🍰

Thanks for the patience everyone!

This will be available in the next version, 0.0.9. 🎉

@tiangolotiangolo changed the title Fix AsyncSession annotations🐛 Fix AsyncSession type annotations for exec()Oct 23, 2023
@tiangolo
tiangolo merged commit 9732c5a into fastapi:mainOct 23, 2023
shabani1 added a commit to lexy-ai/lexy that referenced this pull request Nov 3, 2023
# What
This updates SQLModel to version 0.0.11, which solves an
[issue](fastapi/sqlmodel#443) with foreign key
declaration, and another
[issue](fastapi/sqlmodel#58) with AsyncSession
type annotations.
# Why
Prior to this update, attempting to delete a document with an associated
index record would throw a foreign key violation error.
# Test plan
Add a document which results in an index record being created. Delete
the same document and verify that
- The document is deleted without error
- The index records associated with the document are also deleted
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSession does not play well with typing and autocompletion

6 participants

@Bobronium@priyansh-anand@maresb@diego-escobedo@ornakash@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

🐛 Fix AsyncSession type annotations for exec() - #58

Merged
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix
Oct 23, 2023
Merged

🐛 Fix AsyncSession type annotations for exec()#58
tiangolo merged 8 commits into
fastapi:mainfrom
Bobronium:AsyncSession_typing_fix

Conversation

@Bobronium

@BobroniumBobronium commented Aug 29, 2021

Copy link
Copy Markdown
Contributor

Fixes#54

hero.py:

importasyncioimportinspectimportsysfromcontextlibimportsuppressfrompathlibimportPathfromtypingimportOptional, TYPE_CHECKINGfrommypy.mainimportmainasmypy_mainfromsqlalchemy.ext.asyncioimportcreate_async_enginefromsqlmodelimportField, SQLModel, selectfromsqlmodel.ext.asyncio.sessionimportAsyncSessionclassHero(SQLModel, table=True):
id: Optional[int] =Field(default=None, primary_key=True)
name: strsecret_name: strage: Optional[int] =Noneasyncdefmain() ->None:
engine=create_async_engine("sqlite+aiosqlite:///:memory:")
asyncwithengine.begin() asconn:
awaitconn.run_sync(SQLModel.metadata.create_all)
asyncwithAsyncSession(engine) assession:
session.add(Hero(name="Spider-Boy", secret_name="Pedro Parqueador"))
awaitsession.commit()
asyncwithAsyncSession(engine) assession:
statement=select(Hero).where(Hero.name=="Spider-Boy")
reveal_type(session)
result=awaitsession.exec(statement)
reveal_type(result)
h=result.first()
reveal_type(h)
ifnotTYPE_CHECKING:
defreveal_type(obj):
f_back=inspect.currentframe().f_backfilename=f_back.f_globals["__file__"]
withsuppress(ValueError):
filename=Path(filename).relative_to(Path.cwd())
print(f"{filename}:{f_back.f_lineno}: note: Runtime value is {obj!r}")
print("Running main()")
asyncio.run(main())
print("\nRunning mypy (first run may take some time)")
mypy_main(None, stdout=sys.stdout, stderr=sys.stderr, args=[__file__])

Running on main

Runningmain()
hero.py:33: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x10314f9a0>hero.py:35: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x10308bdc0>hero.py:37: note: RuntimevalueisHero(age=None, name='Spider-Boy', secret_name='Pedro Parqueador', id=1)
Runningmypy (firstrunmaytakesometime)
hero.py:33: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:34: error: Needtypeannotationfor'result'hero.py:34: error: Argument1to"exec"of"AsyncSession"hasincompatibletype"SelectOfScalar[Hero]"; expected"Union[Select[<nothing>], Executable[<nothing>]]"hero.py:35: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult[Any]'hero.py:37: note: Revealedtypeis'Union[Any, None]'Found2errorsin1file (checked1sourcefile)

Running on Bobronium:AsyncSession_typing_fix:

Runningmain()
hero.py:43: note: Runtimevalueis<sqlmodel.ext.asyncio.session.AsyncSessionobjectat0x102a0f940>hero.py:45: note: Runtimevalueis<sqlalchemy.engine.result.ScalarResultobjectat0x1029e9190>hero.py:47: note: RuntimevalueisHero(name='Spider-Boy', secret_name='Pedro Parqueador', id=1, age=None)
Runningmypy (firstrunmaytakesometime)
hero.py:43: note: Revealedtypeis'sqlmodel.ext.asyncio.session.AsyncSession*'hero.py:45: note: Revealedtypeis'sqlmodel.engine.result.ScalarResult*[hero.Hero*]'hero.py:47: note: Revealedtypeis'Union[hero.Hero*, None]'

image

@Bobronium
Bobroniumforce-pushed the AsyncSession_typing_fix branch from 894c60d to 8d578a9CompareAugust 29, 2021 11:03
@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, is this PR or #54 going to be addressed?

@priyansh-anand

Copy link
Copy Markdown

Thanks for the feature! Until this PR gets merged, manually patching will work for my workflow.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Docs preview for commit 11ff44f at: https://639cfc052b35ad15e2e48091--sqlmodel.netlify.app

@Bobronium

Bobronium commented Jan 12, 2023

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I can try to resolve CI issues and update the branch, but I need a confirmation that you have intention of merging it once issues are resolved and willing to communicate if I'll need any feedback on resolving them. Complete lack of comminucation from your side on this issue is frustrating.

I don't want to waste any more time on this PR only to find it in the same condition a year later.

@maresb

Copy link
Copy Markdown

Thanks @Bobronium for the fix, I am pip installing your branch instead of v0.0.8. I hope this gets merged soon.

@diego-escobedo

Copy link
Copy Markdown

Crazy this has been around since 2021. Awesome work @Bobronium on this.

adamsanaglo pushed a commit to adamsanaglo/pulpcore that referenced this pull request Jul 13, 2023
The whole point of SQLModel is that it returns typed objects that play nice with Pydantic and allow your editor's autocomplete functions to work properly. Except when you're using `sqlalchemy.AsyncSession`, it... doesn't. And there *is* a `sqlmodel.AsyncSession`, but it's broken. And there is a *fix* for it in an upstream PR, but it's not merged yet.
fastapi/sqlmodel#58
This PR just copies and uses the upstream PR implementation of `sqlmodel.AsyncSession`. Most of the actual diff here is related to the side-benefit that we no longer have to unwrap the row-tuples that `sqlalchemy.execute` returns, but most of the actual benefit for doing this is that we'll now actually get our appropriately-typed model objects back out of `session.exec` instead of `Any`.
Related work items: #15767106
@ornakash

Copy link
Copy Markdown

Please merge this?

@Bobronium

Copy link
Copy Markdown
ContributorAuthor

@tiangolo, I've fixed CI issue.

Tests are passing now.

Please merge.

@tiangolotiangolo added the bug Something isn't working label Oct 22, 2023
@tiangolo

Copy link
Copy Markdown
Member

Great, thanks @Bobronium! 🚀

Thanks everyone for the comments, in particular confirming this solved it for you. 🍰

Thanks for the patience everyone!

This will be available in the next version, 0.0.9. 🎉

@tiangolotiangolo changed the title Fix AsyncSession annotations🐛 Fix AsyncSession type annotations for exec()Oct 23, 2023
@tiangolo
tiangolo merged commit 9732c5a into fastapi:mainOct 23, 2023
shabani1 added a commit to lexy-ai/lexy that referenced this pull request Nov 3, 2023
# What
This updates SQLModel to version 0.0.11, which solves an
[issue](fastapi/sqlmodel#443) with foreign key
declaration, and another
[issue](fastapi/sqlmodel#58) with AsyncSession
type annotations.
# Why
Prior to this update, attempting to delete a document with an associated
index record would throw a foreign key violation error.
# Test plan
Add a document which results in an index record being created. Delete
the same document and verify that
- The document is deleted without error
- The index records associated with the document are also deleted
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncSession does not play well with typing and autocompletion

6 participants

@Bobronium@priyansh-anand@maresb@diego-escobedo@ornakash@tiangolo