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

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!

Related

TypeError: float() argument must be a string or a number, not 'ModelMetaclass'

I have trained a model on credit card churn and saved it using joblib. Now, I want to use FastAPI as restful API for deployment. I have done the preprocessing of the data as shown below, but I get this error:
TypeError: float() argument must be a string or a number, not 'ModelMetaclass.
Please have a look at the code and error log below.
from fastapi import FastAPI
import joblib
import uvicorn
from pydantic import BaseModel
from sklearn.pipeline import Pipeline, make_pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.compose import ColumnTransformer, make_column_selector as selector
import pandas as pd
import numpy as np
app = FastAPI(title ='Credit Card Churn Prediction', version = 1.0, description = 'Classification Machine Learning Prediction')
class model_input(BaseModel):
Customer_Age : int
Gender : int
Dependent_count : int
Education_level : int
Marital_status : str
Income_category : str
Card_category : str
months_on_book : int
Total_Relationship_Count : int
Months_Inactive_12_mon : int
Contacts_Count_12_mon : int
Credit_Limit : int
Total_Revolving_Bal : int
Avg_Open_To_Buy : int
Total_Amt_Chng_Q4_Q1 : int
Total_Trans_Amt : int
Total_Trans_Ct : int
Total_Ct_Chng_Q4_Q1 : int
Avg_Utilization_Ratio : int
# load the model
model = joblib.load("joblib_CC_Model.pkl")
#app.post("/credit_card_churn_prediction")
async def predicts(input:model_input):
# Numeric Features
num_features = [[input.Customer_Age, input.Dependent_count, input.months_on_book, input.Total_Relationship_Count, input.Months_Inactive_12_mon,
input.Contacts_Count_12_mon, input.Credit_Limit, input.Total_Revolving_Bal, input.Avg_Open_To_Buy, input.Total_Amt_Chng_Q4_Q1, input.Total_Trans_Amt,
input.Total_Trans_Ct, input.Total_Ct_Chng_Q4_Q1, input.Avg_Utilization_Ratio, input.Gender, input.Education_level]]
num_pipeline = Pipeline([("Scaler", StandardScaler())])
# Categorical Features
cat_features = [[input.Gender, input.Education_level, input.Marital_status, input.Card_category]]
cat_pipeline = Pipeline([("onehot", OneHotEncoder())])
final_input = ColumnTransformer(transformers = [("numeric_preprocessing", num_pipeline, num_features),
("categorical_preprocessing", cat_pipeline, cat_features)])
prediction = model.predict([[model_input]])
return prediction
if __name__ == '__main__':
uvicorn.run("Main:app", reload = True)
I have built a ML classification model, which is used in a FastAPI application, but I get this error:
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 419, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\fastapi\applications.py", line 270, in __call__
await super().__call__(scope, receive, send)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\starlette\applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\starlette\middleware\errors.py", line 184, in __call__
raise exc
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\starlette\middleware\errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\starlette\middleware\exceptions.py", line 79, in __call__
raise exc
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\starlette\middleware\exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
raise e
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\starlette\routing.py", line 706, in __call__
await route.handle(scope, receive, send)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\starlette\routing.py", line 276, in handle
await self.app(scope, receive, send)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\starlette\routing.py", line 66, in app
response = await func(request)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\fastapi\routing.py", line 235, in app
raw_response = await run_endpoint_function(
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\fastapi\routing.py", line 161, in run_endpoint_function
return await dependant.call(**values)
File "d:\Work\Mine\Data Science\Projects\Data Science\FastAPI\Main.py", line 59, in predicts
prediction = model.predict([[model_input]])
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\xgboost\sklearn.py", line 1284, in predict
class_probs = super().predict(
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\xgboost\sklearn.py", line 897, in predict
test = DMatrix(
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\xgboost\core.py", line 506, in inner_f
return f(**kwargs)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\xgboost\core.py", line 616, in __init__
handle, feature_names, feature_types = dispatch_data_backend(
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\xgboost\data.py", line 768, in dispatch_data_backend
return _from_list(data, missing, threads, feature_names, feature_types)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\xgboost\data.py", line 700, in _from_list
return _from_numpy_array(array, missing, n_threads, feature_names, feature_types)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\xgboost\data.py", line 171, in _from_numpy_array
data, _ = _ensure_np_dtype(data, data.dtype)
File "D:\Work\Mine\Data Science\Projects\Data Science\FastAPI\venv\lib\site-packages\xgboost\data.py", line 138, in _ensure_np_dtype
data = data.astype(np.float32, copy=False)
TypeError: float() argument must be a string or a number, not 'ModelMetaclass'
I have it run on Swagger UI and enter the inputs shown in the class BaseModel. Now, I don't know what to do
The error is thrown in the following line of your code (as shown from the traceback you provided):
File "d:\Work\Mine\Data Science\Projects\Data Science\FastAPI\Main.py", line 59, in predicts
prediction = model.predict([[model_input]])
^^^^^^^^^^^
You are passing the BaseModel class to the predict() function instead of the final_input object you prepared. Hence, you should change the line above to the one below:
prediction = model.predict([[final_input]])
Please have a look at related answers on using ML models with FastAPI here, here and here, as well as take a look at this, this and this answer.

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)

FastAPI sqlmodel get all rows from the database

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.

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

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,
)

Categories

Resources