Python await is not finished but skipped

Viewed 130

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!

0 Answers
Related