I am trying to implement an async database connection library to my FastAPI program, but it seems like python skips my await keyword.
My expected behaviour is that the login func will call get_user_info, which will print "before calling query" and then call _query and print "about to execute" and then print the result.
The actual outcome:
before calling query
user: None
INFO: 127.0.0.1:60548 - "POST /api/auth/login HTTP/1.1" 401 Unauthorized
2021-05-24 12:31:44.007 | INFO | authentication.routes:login:31 - 127.0.0.1 tried to log in with user x
my code:
route.py
@auth_app.post("/auth/login", response_model=Token, tags=["Authentication"])
async def login(request: Request, form_data: OAuth2PasswordRequestForm = Depends()):
credentials_exceptions = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect credentials.",
headers={"Authenticate": "Bearer"}
)
username = form_data.username
password = form_data.password
async with MysqlConnector() as conn:
user = await conn.get_user_info(username)
print("user:", user)
logger.info(f"{request.client.host} tried to log in with user {username}")
if not user:
raise credentials_exceptions
My MysqlConnector() class:
class MysqlConnector:
async def __aenter__(self):
await self._create_connection()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
await self.connection.disconnect()
def __await__(self):
return self.__aenter__().__await__()
@staticmethod
def _create_conn_string():
return f"mysql://{MYSQL_SETTINGS['user']}:{MYSQL_SETTINGS['password']}@{MYSQL_SETTINGS['host']}:" \
f"{MYSQL_SETTINGS['port']}/{MYSQL_SETTINGS['database']}"
async def disconnect(self):
await self.connection.disconnect()
async def _create_connection(self):
MYSQL_SETTINGS['use_unicode'] = True
MYSQL_SETTINGS['charset'] = 'utf8'
self.connection = Database(self._create_conn_string())
await self.connection.connect()
async def _query(self, sql_query, dictionary=False, **kwargs):
print("about to execute")
await self.connection.execute(query=sql_query, values=kwargs)
self.res = await self.connection.fetch_all(query=sql_query)
print("result: ", self.res)
async def get_user_info(self, username: str) -> str:
sql_query = """
CALL `sp_get_user`(:username);
"""
try:
print("before calling query")
await self._query(sql_query, username=username)
result = self.res
print("result:")
print(result)
except IndexError:
return
user = User( # User is a pydantic model
user_id=result[0],
username=result[1],
first_name=result[2],
last_name=result[3],
role=result[4],
hashed_password=result[5],
email_addr=result[6],
phone=result[7],
desc=result[8],
last_login=datetime.strptime(result[9], '%Y-%m-%d %H:%M:%S.%f'),
active=result[10],
api_access=result[11]
)
print("user:", user)
return user
Thank you for any help!