FastAPI sqlmodel get all rows from the database - python

I have a FastAPI application that needs to provide GET route to get all Items from a Postgres 13 database. The Item is defined and added from another app. The Item has a model like this:
class ItemDb(SQLModel, table=True):
__tablename__ = "items"
id: str = Field(
default_factory=uuid.uuid4, primary_key=True)
name: str
There is also table gadgets. Every Gadget has a foreign key which points to an Item:
class GadgetDb(SQLModel, table=True):
__tablename__ = "gadgets"
id: str = Field(
default_factory=uuid.uuid4, primary_key=True)
item_id: str = Field(..., foreign_key="items.id")
name: str
In my app, I want to retrieve just all the Items for now. I have created a simple model like this:
class Item(SQLModel):
id: str
key_name: str
This is my crud function:
class CRUDItem(CRUDBase[Item, None, None]):
def list(self, db: Session) -> List[Item]:
statement = select(self.model)
results = db.exec(statement)
return results.all()
item = CRUDItem(Item)
And this is my endpoint function:
from app.crud.crud_item import item
#router.get(
"/",
response_model=List[Item],
status_code=200,
response_model_exclude_unset=True,
)
def list_items(
session: Session = Depends(get_session),
) -> Any:
items = item.list(session)
return items
Now, this returns an error TypeError: 'SQLModelMetaclass' object is not iterable. Why this error occurs and how can I get all the rows from the database?
Edit. The error traceback:
INFO: 172.30.0.1:51432 - "GET /api/v1/items/ HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/uvicorn/protocols/http/httptools_impl.py", line 404, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/usr/local/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "/usr/local/lib/python3.9/site-packages/fastapi/applications.py", line 270, in __call__
await super().__call__(scope, receive, send)
File "/usr/local/lib/python3.9/site-packages/starlette/applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.9/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/usr/local/lib/python3.9/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/usr/local/lib/python3.9/site-packages/starlette/middleware/cors.py", line 84, in __call__
await self.app(scope, receive, send)
File "/usr/local/lib/python3.9/site-packages/starlette/middleware/exceptions.py", line 75, in __call__
raise exc
File "/usr/local/lib/python3.9/site-packages/starlette/middleware/exceptions.py", line 64, in __call__
await self.app(scope, receive, sender)
File "/usr/local/lib/python3.9/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/usr/local/lib/python3.9/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/usr/local/lib/python3.9/site-packages/starlette/routing.py", line 680, in __call__
await route.handle(scope, receive, send)
File "/usr/local/lib/python3.9/site-packages/starlette/routing.py", line 275, in handle
await self.app(scope, receive, send)
File "/usr/local/lib/python3.9/site-packages/starlette/routing.py", line 65, in app
response = await func(request)
File "/usr/local/lib/python3.9/site-packages/fastapi/routing.py", line 231, in app
raw_response = await run_endpoint_function(
File "/usr/local/lib/python3.9/site-packages/fastapi/routing.py", line 162, in run_endpoint_function
return await run_in_threadpool(dependant.call, **values)
File "/usr/local/lib/python3.9/site-packages/starlette/concurrency.py", line 41, in run_in_threadpool
return await anyio.to_thread.run_sync(func, *args)
File "/usr/local/lib/python3.9/site-packages/anyio/to_thread.py", line 31, in run_sync
return await get_asynclib().run_sync_in_worker_thread(
File "/usr/local/lib/python3.9/site-packages/anyio/_backends/_asyncio.py", line 937, in run_sync_in_worker_thread
return await future
File "/usr/local/lib/python3.9/site-packages/anyio/_backends/_asyncio.py", line 867, in run
result = context.run(func, *args)
File "/app/./app/api/api_v1/endpoints/items.py", line 29, in list_items
results = session.exec(select(Item)).all()
File "/usr/local/lib/python3.9/site-packages/sqlmodel/sql/expression.py", line 450, in select
return SelectOfScalar._create(*entities, **kw) # type: ignore
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/sql/selectable.py", line 5309, in _create
return cls.create_legacy_select(*args, **kw)
File "<string>", line 2, in create_legacy_select
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/deprecations.py", line 402, in warned
return fn(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/sql/selectable.py", line 5165, in create_legacy_select
self._raw_columns = [
TypeError: 'ModelMetaclass' object is not iterable
Edit2. The class CRUDBase:
ModelType = TypeVar("ModelType", bound=Base)
CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)
UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]): # 1
def __init__(self, model: Type[ModelType]): # 2
"""
CRUD object with default methods to Create, Read, Update, Delete (CRUD).
**Parameters**
* `model`: A SQLAlchemy model class
* `schema`: A Pydantic model (schema) class
"""
self.model = model
def get(self, db: Session, id: Any) -> Optional[ModelType]:
return db.query(self.model).filter(self.model.id == id).first() # 3
def list(
self, db: Session, *, skip: int = 0, limit: int = 100
) -> List[ModelType]:
return db.query(self.model).offset(skip).limit(limit).all() # 4
def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType:
obj_in_data = jsonable_encoder(obj_in)
db_obj = self.model(**obj_in_data) # type: ignore
db.add(db_obj)
db.commit() # 5
db.refresh(db_obj)
return db_obj

The Item class isn't an ORM model (it doesn't have table=True), so you can't use it in database queries. Using ItemDb should resolve the issue.

Related

Uploading image with FastAPI cause exc.ResourceClosedError

I have an endpoint which saves uploaded image to it:
#router.post("/v1/installation/{installation_uuid}/image")
#db.create_connection
async def upload_installation_image(installation_uuid: UUID, request: Request):
content_type = request.headers["content-type"]
async with db.transaction():
installation = await get_installation_by_uuid(installation_uuid)
if not installation:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Installation {installation} not found")
try:
content = await request.body()
image_uuid = await save_installation_image(installation.uuid, content, content_type)
except Exception as e:
log.debug(f"An error raised while uploading image: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error while uploading image to db"
)
return {"image_uuid": image_uuid}
save_installation_image make simple insert into DB.
In my tests I send 3 request to this endpoint. and all works fine:
tests.py
# upload image 1
data1 = b"\x01\x02\x03\x61\x05\x61"
response = session.post(
f"/v1/installation/{installation_uuid}/image", data=data1, headers={"content-type": "image/png"}
)
# upload image 2
data2 = b"\x01\x02\x03\x61\x05\x62"
response = session.post(
f"/v1/installation/{installation_uuid}/image", data=data2, headers={"content-type": "image/png"}
)
# upload image 3
data3 = b"\x01\x02\x03\x61\x05\x63"
response = session.post(
f"/v1/installation/{installation_uuid}/image", data=data3, headers={"content-type": "image/png"}
)
But when FE start calling that request, each request after first one start failing with this error:
Traceback (most recent call last):
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/uvicorn/protocols/http/httptools_impl.py", line 404, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/uvicorn/middleware/message_logger.py", line 86, in __call__
raise exc from None
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/uvicorn/middleware/message_logger.py", line 82, in __call__
await self.app(scope, inner_receive, inner_send)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/fastapi/applications.py", line 270, in __call__
await super().__call__(scope, receive, send)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/starlette/applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/starlette/middleware/exceptions.py", line 75, in __call__
raise exc
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/starlette/middleware/exceptions.py", line 64, in __call__
await self.app(scope, receive, sender)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/starlette/routing.py", line 680, in __call__
await route.handle(scope, receive, send)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/starlette/routing.py", line 275, in handle
await self.app(scope, receive, send)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/starlette/routing.py", line 65, in app
response = await func(request)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/fastapi/routing.py", line 231, in app
raw_response = await run_endpoint_function(
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/fastapi/routing.py", line 160, in run_endpoint_function
return await dependant.call(**values)
File "/opt/kelvatek/camlin-relink-broker/toolbox/asyncio_db.py", line 153, in wrapper
return await func(*args, **kwargs)
File "/opt/kelvatek/camlin-relink-broker/src/installation.py", line 347, in upload_installation_image
installation = await get_installation_by_uuid(installation_uuid)
File "/opt/kelvatek/camlin-relink-broker/src/installation.py", line 64, in get_installation_by_uuid
row = (await db.execute(query, installation_uuid=str(installation_uuid))).fetchone()
File "/opt/kelvatek/camlin-relink-broker/toolbox/asyncio_db.py", line 116, in execute
return await active_connection.execute(query, **params)
File "/opt/kelvatek/camlin-relink-broker/toolbox/asyncio_db.py", line 50, in execute
return await t.execute(query, **params)
File "/opt/kelvatek/camlin-relink-broker/toolbox/asyncio_db.py", line 30, in execute
return await self.async_connection.execute(text(query).bindparams(**params))
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/sqlalchemy/ext/asyncio/engine.py", line 453, in execute
result = await greenlet_spawn(
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 115, in greenlet_spawn
result = context.switch(*args, **kwargs)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1705, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 333, in _execute_on_connection
return connection._execute_clauseelement(
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1572, in _execute_clauseelement
ret = self._execute_context(
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1798, in _execute_context
conn = self._revalidate_connection()
File "/opt/kelvatek/camlin-relink-broker/venv/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 650, in _revalidate_connection
raise exc.ResourceClosedError("This Connection is closed")
sqlalchemy.exc.ResourceClosedError: This Connection is closed
Also, when I change by data to data which send FE, it start failing for me as well. What may cause this error, and why if I send real images connection close after first request?
P.S. If I send just 1 image, it works fine, so problem in sending several requests.
UPDATES
This is how I manage connection to db:
#asynccontextmanager
async def connection(self):
active_connection = self.get_active_connection()
if active_connection:
yield active_connection
return
async with self.engine.connect() as conn:
try:
wrapper = ConnectionWrapper(conn)
token = self.active_connection.set(wrapper)
await self.set_connection_options()
if not self.collation_check_done:
await self.check_collation()
self.collation_check_done = True
yield wrapper
finally:
self.active_connection.reset(token)
def create_connection(self, func):
#wraps(func)
async def wrapper(*args, **kwargs):
async with self.connection():
return await func(*args, **kwargs)
return wrapper
This is my Wrappers classes:
class TransactionWrapper:
def __init__(self, async_connection, async_transaction):
self.async_connection = async_connection
self.async_transaction = async_transaction
self.after_commit_callbacks = []
def add_after_commit_callback(self, fn):
self.after_commit_callbacks.append(fn)
async def execute(self, query, **params):
return await self.async_connection.execute(text(query).bindparams(**params))
async def commit(self):
await self.async_transaction.commit()
while self.after_commit_callbacks:
fn = self.after_commit_callbacks.pop(0)
fn()
async def rollback(self):
await self.async_transaction.rollback()
class ConnectionWrapper:
def __init__(self, async_connection):
self.async_connection = async_connection
self.active_transaction = contextvars.ContextVar('active_transaction')
async def execute(self, query, **params):
t = self.get_active_transaction()
if t:
return await t.execute(query, **params)
# create temporary transaction in case it doesn't exists (simulates autocommit feature)
async with self.transaction() as t:
return await t.execute(query, **params)
def get_active_transaction(self):
try:
return self.active_transaction.get()
except LookupError:
return None
#asynccontextmanager
async def transaction(self):
# reuse existing transaction
active_transaction = self.get_active_transaction()
if active_transaction:
yield active_transaction
return
async with self.async_connection.begin() as async_transaction:
wrapper = TransactionWrapper(self.async_connection, async_transaction)
token = self.active_transaction.set(wrapper)
try:
yield wrapper
except Exception:
await wrapper.rollback()
raise
else:
await wrapper.commit()
finally:
self.active_transaction.reset(token)

Pydantic Optional parameters not yet prepared so type is still a ForwardRef

I have the following code:
endpoints.py
from __future__ import annotations # this is important to have at the top
from fastapi import FastAPI
from pydantic import BaseModel
class MyOpt(BaseModel):
fieldfirst: str = "S"
fieldsecond: int = 1
fieldthird: str = None
fieldforth: list = []
fieldfifth: int
fieldsixth: list = [None, None]
fieldseventh: str = None
fieldeighth: Optional[int] = None
fieldnineth: Optional[str] = None
fieldtenth: Optional[list] = [None, None]
from typing import List, Optional
# Create object for fastAPI
app = FastAPI()
# START API ENDPOINTS
#app.get("/", tags=["root"])
def root():
return {"message": "REST API."}
# -- TESTING ENDPOINTS --
#app.get(
"/health",
name="health",
tags=["root"],
summary="Test connection to API",
status_code=200
)
def health():
return {"type": "complete"}
#app.post(
"/send_instruction",
name="send_instruction",
tags=["web"],
)
def send_instruction(myopts: MyOpt = None):
return {"result": "ok"}
run_api.py:
import uvicorn
if __name__ == "__main__":
uvicorn.run("endpoints:app", host="0.0.0.0", port=8822, reload=True, access_log=False)
When I call the api (python3 run_api.py), I get the following error only if I send any of the Optional values of MyOpt:
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 403, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/applications.py", line 269, in __call__
await super().__call__(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/exceptions.py", line 93, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/exceptions.py", line 82, in __call__
await self.app(scope, receive, sender)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 670, in __call__
await route.handle(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 266, in handle
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 65, in app
response = await func(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/routing.py", line 217, in app
solved_result = await solve_dependencies(
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/dependencies/utils.py", line 557, in solve_dependencies
) = await request_body_to_args( # body_params checked above
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/dependencies/utils.py", line 692, in request_body_to_args
v_, errors_ = field.validate(value, values, loc=loc)
File "pydantic/fields.py", line 857, in pydantic.fields.ModelField.validate
File "pydantic/fields.py", line 1074, in pydantic.fields.ModelField._validate_singleton
File "pydantic/fields.py", line 1121, in pydantic.fields.ModelField._apply_validators
File "pydantic/class_validators.py", line 313, in pydantic.class_validators._generic_validator_basic.lambda12
File "pydantic/main.py", line 686, in pydantic.main.BaseModel.validate
File "pydantic/main.py", line 339, in pydantic.main.BaseModel.__init__
File "pydantic/main.py", line 1038, in pydantic.main.validate_model
File "pydantic/fields.py", line 833, in pydantic.fields.ModelField.validate
pydantic.errors.ConfigError: field "fieldnineth" not yet prepared so type is still a ForwardRef, you might need to call SatOpt.update_forward_refs().
To send the request I use Postman and in Body as raw formated as JSON I have:
{"fieldfirst": "S", "fieldsecond": 1, "fieldthird": "a test", "fieldforth": [1,2], "fieldfifth": 42, "fieldsixth": [[1, 8, 3], [1, 9, 2]], "fieldseventh": "yey", "fieldnineth": "VV"}
What is wrong with my code?
from typing import List, Optional
Should be before the class definition

AttributeError: 'list' object has no attribute 'hypernyms'

I am trying to get distractors for a list of words and return them in arrays, but i keep getting this error.
Traceback (most recent call last):
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/fastapi/applications.py", line 199, in __call__
await super().__call__(scope, receive, send)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/applications.py", line 111, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
raise exc from None
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
raise exc from None
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/routing.py", line 566, in __call__
await route.handle(scope, receive, send)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
await self.app(scope, receive, send)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/routing.py", line 41, in app
response = await func(request)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/fastapi/routing.py", line 201, in app
raw_response = await run_endpoint_function(
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/fastapi/routing.py", line 150, in run_endpoint_function
return await run_in_threadpool(dependant.call, **values)
File "/home/maro/Documents/codefiles/nlp/venv/lib/python3.8/site-packages/starlette/concurrency.py", line 34, in run_in_threadpool
return await loop.run_in_executor(None, func, *args)
File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/maro/Documents/codefiles/nlx/./main.py", line 104, in getquestion
distractors.append(get_distractors_wordnet(wn.synsets(word),word))
File "/home/maro/Documents/codefiles/nlx/./main.py", line 76, in get_distractors_wordnet
hypernym = syn.hypernyms()
AttributeError: 'list' object has no attribute 'hypernyms'
This is my entire code
from typing import List
from fastT5 import get_onnx_model,get_onnx_runtime_sessions,OnnxT5
from transformers import AutoTokenizer
from pathlib import Path
import os
from fastapi import FastAPI
from pydantic import BaseModel
from textblob import TextBlob
import nltk
from nltk.corpus import wordnet as wn
app = FastAPI()
class QuestionRequest(BaseModel):
context: str
class QuestionResponse(BaseModel):
question: List[str] = []
answer: List[str] = []
distractors_sublist: List[List[str]] = [ [] ]
trained_model_path = './t5_squad_v1/'
pretrained_model_name = Path(trained_model_path).stem
encoder_path = os.path.join(trained_model_path,f"{pretrained_model_name}-encoder-quantized.onnx")
decoder_path = os.path.join(trained_model_path,f"{pretrained_model_name}-decoder-quantized.onnx")
init_decoder_path = os.path.join(trained_model_path,f"{pretrained_model_name}-init-decoder-quantized.onnx")
model_paths = encoder_path, decoder_path, init_decoder_path
model_sessions = get_onnx_runtime_sessions(model_paths)
model = OnnxT5(trained_model_path, model_sessions)
tokenizer = AutoTokenizer.from_pretrained(trained_model_path)
def get_question(sentence,mdl,tknizer):
gfg = TextBlob(sentence)
gfg = gfg.noun_phrases
array=[]
for i in gfg:
text = "context: {} answer: {}".format(sentence,i)
array.append(text)
max_len = 256
question_array =[]
for text in array:
encoding = tknizer.encode_plus(text,max_length=max_len, pad_to_max_length=False,truncation=True, return_tensors="pt")
input_ids, attention_mask = encoding["input_ids"], encoding["attention_mask"]
outs = mdl.generate(input_ids=input_ids,
attention_mask=attention_mask,
early_stopping=True,
num_beams=5,
num_return_sequences=1,
no_repeat_ngram_size=2,
max_length=128)
dec = [tknizer.decode(ids,skip_special_tokens=True) for ids in outs]
Question = dec[0].replace("question:","")
Question= Question.strip()
question_array.append(Question)
print (question_array)
return question_array, gfg
# Distractors from Wordnet
def get_distractors_wordnet(syn,word):
distractors=[]
word= word.lower()
orig_word = word
if len(word.split())>0:
word = word.replace(" ","_")
hypernym = syn.hypernyms()
if len(hypernym) == 0:
return distractors
for item in hypernym[0].hyponyms():
name = item.lemmas()[0].name()
#print ("name ",name, " word",orig_word)
if name == orig_word:
continue
name = name.replace("_"," ")
name = " ".join(w.capitalize() for w in name.split())
if name is not None and name not in distractors:
distractors.append(name)
return distractors
#app.get('/')
def index():
return {'message':'hello world'}
#app.post("/getquestion", response_model= QuestionResponse)
def getquestion(question: QuestionRequest):
context = question.context
question_array, gfg = get_question(context,model,tokenizer)
answer = gfg[0]
distractors = []
for word in gfg:
distractors.append(get_distractors_wordnet(wn.synsets(word),word))
distractors_sublist = []
for i in range(len(distractors)):
distractors_sublist.append(distractors[i])
return QuestionResponse(question=question_array, answer=answer, distractors_sublist=distractors_sublist)
distractors = get_distractors_wordnet(wn.synsets(answer),answer)
distractors_sublist = [distractors[i:i+3] for i in range(0, len(distractors), 3)]
return QuestionResponse(question=question_array, answer=answer, distractors_sublist=distractors_sublist)
I have tried so many iterations, none seem to work. I am using Fastapi and some personal models. The response should return an array of distractors that contain several sub arrays each representing the distractor for each answer or gfg
I took a look at the documentation for NLTK at https://www.nltk.org/howto/wordnet.html. It looks like the culprit is wn.synsets(word), in your invocation of get_distractors_wordnet. An easy typo - wn.synset returns a single synonym set, whereas wn.synsets returns a list of synonym sets. You're getting that error because you're trying to use a member function of a synset on a list of synsets (hence, "'list' object has no attribute 'hypernyms'").
All you have to do is either iterate over the list, or refactor to use wn.synset instead. Hope this helps!

Error Value not declarable with JSON Schema for PurePath with Pydantic and FastAPI

I'm trying to add a field path of type PureWindowsPath to my model. After implementing a custom validator as suggested here https://github.com/samuelcolvin/pydantic/issues/2089#issuecomment-890018075 I get the following error when trying to access the SwaggerUI:
INFO: 127.0.0.1:7696 - "GET /api/openapi.json HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 371, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 59, in __call__
return await self.app(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\fastapi\applications.py", line 208, in __call__
await super().__call__(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
raise exc from None
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\exceptions.py", line 82, in __call__
raise exc from None
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\routing.py", line 580, in __call__
await route.handle(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\routing.py", line 390, in handle
await self.app(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\fastapi\applications.py", line 208, in __call__
await super().__call__(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
raise exc from None
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\exceptions.py", line 82, in __call__
raise exc from None
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\routing.py", line 580, in __call__
await route.handle(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\routing.py", line 241, in handle
await self.app(scope, receive, send)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\starlette\routing.py", line 52, in app
response = await func(request)
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\fastapi\applications.py", line 161, in openapi
return JSONResponse(self.openapi())
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\fastapi\applications.py", line 136, in openapi
self.openapi_schema = get_openapi(
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\fastapi\openapi\utils.py", line 387, in get_openapi
definitions = get_model_definitions(
File "C:\Users\xxx\.virtualenvs\server-J9mXI7Iu\lib\site-packages\fastapi\utils.py", line 24, in get_model_definitions
m_schema, m_definitions, m_nested_models = model_process_schema(
File "pydantic\schema.py", line 548, in pydantic.schema.model_process_schema
File "pydantic\schema.py", line 589, in pydantic.schema.model_type_schema
File "pydantic\schema.py", line 241, in pydantic.schema.field_schema
File "pydantic\schema.py", line 495, in pydantic.schema.field_type_schema
File "pydantic\schema.py", line 863, in pydantic.schema.field_singleton_schema
ValueError: Value not declarable with JSON Schema, field: name='path' type=PureWindowsPath required=True
My Pydantic config looks like this:
class CamelModel(BaseModel, ABC):
class Config:
alias_generator = camelize
allow_population_by_field_name = True
frozen = True
json_encoders = {
datetime: lambda dt: dt.isoformat(),
PureWindowsPath: str,
PurePath: str
}
use_enum_values = True
class Foo(CamelModel, ABC):
path: PureWindowsPath
extraction_version: str
class Foo2(Foo):
pass
You can use the following code to make this work. It creates a subclass with validators so you can customise the schema and validation how you want to:
here is a link to a relevant Github issue: https://github.com/tiangolo/sqlmodel/issues/235#issuecomment-1162063590
from psycopg2.extras import DateTimeTZRange as DateTimeTZRangeBase
from sqlalchemy.dialects.postgresql import TSTZRANGE
from sqlmodel import (
Column,
Field,
Identity,
SQLModel,
)
from pydantic.json import ENCODERS_BY_TYPE
ENCODERS_BY_TYPE |= {DateTimeTZRangeBase: str}
class DateTimeTZRange(DateTimeTZRangeBase):
#classmethod
def __get_validators__(cls):
yield cls.validate
#classmethod
def validate(cls, v):
if isinstance(v, str):
lower = v.split(", ")[0][1:].strip().strip()
upper = v.split(", ")[1][:-1].strip().strip()
bounds = v[:1] + v[-1:]
return DateTimeTZRange(lower, upper, bounds)
elif isinstance(v, DateTimeTZRangeBase):
return v
raise TypeError("Type must be string or DateTimeTZRange")
#classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(type="string", example="[2022,01,01, 2022,02,02)")
class EventBase(SQLModel):
__tablename__ = "event"
timestamp_range: DateTimeTZRange = Field(
sa_column=Column(
TSTZRANGE(),
nullable=False,
),
)
class Event(EventBase, table=True):
id: int | None = Field(
default=None,
sa_column_args=(Identity(always=True),),
primary_key=True,
nullable=False,
)

Why is my table name being called twice in some cases but not in others? FastAPI, SQLAlchemy

I am using FastAPI which is Flask-like. I have 2 different pages, one which functions completely fine and the other which gives the following:
INFO: 127.0.0.1:57256 - "GET /companies?month=4&year=2020&day=5 HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 384, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
return await self.app(scope, receive, send)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\fastapi\applications.py", line 149, in __call__
await super().__call__(scope, receive, send)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\applications.py", line 102, in __call__
await self.middleware_stack(scope, receive, send)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
raise exc from None
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\exceptions.py", line 82, in __call__
raise exc from None
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\routing.py", line 550, in __call__
await route.handle(scope, receive, send)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\routing.py", line 227, in handle
await self.app(scope, receive, send)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\routing.py", line 41, in app
response = await func(request)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\fastapi\routing.py", line 196, in app
raw_response = await run_endpoint_function(
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\fastapi\routing.py", line 150, in run_endpoint_function
return await run_in_threadpool(dependant.call, **values)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\starlette\concurrency.py", line 34, in run_in_threadpool
return await loop.run_in_executor(None, func, *args)
File "c:\users\admin\appdata\local\programs\python\python38-32\Lib\concurrent\futures\thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File ".\main.py", line 73, in get_companies
return myquery.all()
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\orm\query.py", line 3246, in all
return list(self)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\orm\query.py", line 3405, in __iter__
return self._execute_and_instances(context)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\orm\query.py", line 3430, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\engine\base.py", line 984, in execute
return meth(self, multiparams, params)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\sql\elements.py", line 293, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\engine\base.py", line 1097, in _execute_clauseelement
ret = self._execute_context(
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\engine\base.py", line 1287, in _execute_context
self._handle_dbapi_exception(
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\engine\base.py", line 1481, in _handle_dbapi_exception
util.raise_(
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\util\compat.py", line 178, in raise_
raise exception
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\engine\base.py", line 1247, in _execute_context
self.dialect.do_execute(
File "c:\users\admin\google~1\python\new_co~1\env\lib\site-packages\sqlalchemy\engine\default.py", line 590, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.DuplicateAlias) table name "companies" specified more than once
[SQL: SELECT companies.record_created AS companies_record_created, companies.number AS companies_number, companies.name AS companies_name, companies.incorporated AS companies_incorporated
FROM companies, companies
WHERE EXTRACT(year FROM companies.incorporated) = %(param_1)s AND EXTRACT(month FROM companies.incorporated) = %(param_2)s AND EXTRACT(day FROM companies.incorporated) = %(param_3)s]
[parameters: {'param_1': 2020, 'param_2': 4, 'param_3': 5}]
(Background on this error at: http://sqlalche.me/e/f405)
So the crux of the error is that the table name is being generated twice for some unknown reason.
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.DuplicateAlias) table name "companies" specified more than once
Which I can see here:
FROM companies, companies
This only happens in one version and not the other(?!).
Now let me show you something that works completely fine.
# main.py
# various imports
...
#app.get("/incorporated/today")
def read_cos_today(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
today = datetime.datetime.now()
return crud.get_company_by_date(db, year=today.year, month=today.month, day=today.day).all()
The above works fine and returns the expected json.
The below however gives the error previously mentioned.
# main.py
# various imports
...
#app.get("/companies", response_model=List[schemas.Company])
def get_companies(
year: int = None, month: int = None, day: int = None, number: int = None,
name: str = None, db: Session = Depends(get_db)):
arguments = locals()
arguments.pop("db")
if not any(arguments.values()):
return None
myquery = db.query(models.Company)
for key, value in arguments.items():
if not value:
continue
if key == 'year' or key == 'month' or key == 'day':
myquery = crud.get_company_by_date(db, query=myquery, **{key:value})
else:
myquery = crud.filter_query(myquery, **{key:value})
return myquery.all()
and below are the functions in crud.py
# crud.py
# various imports
...
def filter_query(query: Query, **kwargs):
"""Filter an input query for the given kwargs.
Args:
query (Query): An existing query from the database.
**kwargs: A column from the database.
Returns:
query (Query): The filtered query.
"""
for key,value in kwargs.items():
query = query.filter_by(**{key:value})
return query
def get_company_by_date(session: Session, query: Query = None, **kwargs):
"""Return an ordered Company query object filtered by date.
Args:
session (Session): A session connected to the database.
query (Query): An existing query from the database.
**kwargs: year, month or day (int).
Returns:
query (Query): A query result filtered by the input kwargs.
"""
if not query:
query = session.query(models.Company)
for key, value in kwargs.items():
print("Do the thing here yes")
query = query.filter(extract(key, models.Company.incorporated)==value)
return query
This is driving me a little bit mad. I can't understand why it would be duplicating the table name here. Even when I do a simple request of http://127.0.0.1:8000/companies?month=4 it raises the error, so presumably it is not a problem with the way these are being chained(?).
Please help me understand what I'm doing wrong.
Bah. Apparently passing the existing query into crud.get_company_by_date is what's causing the issue.
In main.py I edited the get_companies function to the following (as the problem seems to be in chaining the get_company_by_date function):
#app.get("/companies", response_model=List[schemas.Company])
def get_companies(
year: int = None, month: int = None, day: int = None, number: int = None,
name: str = None, db: Session = Depends(get_db)):
arguments = locals()
arguments.pop("db")
if not any(arguments.values()):
return None
myquery = db.query(models.Company)
datedict = {}
for key, value in arguments.items():
if key == "number" and datedict:
myquery = crud.get_company_by_date(db, **datedict)
if not value:
continue
if key == 'year' or key == 'month' or key == 'day':
datedict[key] = value
else:
myquery = crud.filter_query(myquery, **{key:value})
return myquery.all()

Categories

Resources