Skip to content

Commit ee3e954

Browse files
committed
refactor: operation_id generation across routers
our web client has a ticket where we require the operation_id of the openapi spec to be human readable, this is inline with cameCasing and snake_casing depending on the server or client anomaly/lab-web-client#6 the attempt is to greatly improve code readability which in turn makes documentation a lot more readable. initially we were assigning the operation_id manually but have nice moved to using what's references in the fastapi docs https://bit.ly/3rXeAvH this does imply that the function names have to well written by developers
1 parent 5a7c26f commit ee3e954

File tree

6 files changed

+67
-36
lines changed

6 files changed

+67
-36
lines changed

src/labs/api.py

+45-23
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
"""
1313
from . import __title__, __version__
1414

15-
from fastapi import FastAPI, Request, Depends, status, WebSocket
15+
from fastapi import FastAPI, Request, status, WebSocket
1616
from fastapi.responses import JSONResponse
17+
from fastapi.routing import APIRoute
1718

1819
from .routers import router_auth, router_ext
1920

@@ -31,33 +32,34 @@
3132
"""A FastAPI application that serves handlers
3233
"""
3334
app = FastAPI(
34-
title=__title__,
35-
version=__version__,
36-
description=api_description,
37-
docs_url="/docs",
38-
terms_of_service="https://github.com/anomaly/labs",
39-
contact={
40-
"name": "Anomaly Software",
41-
"url": "https://github.com/anomaly/labs",
42-
"email": "[email protected]"
43-
},
44-
license_info={
45-
"name": "Apache 2.0",
46-
"url": "https://www.apache.org/licenses/LICENSE-2.0"
47-
},
48-
openapi_tags=[
49-
{
50-
"name": "auth",
51-
"description": "Authentication related endpoints"
52-
}
53-
]
54-
)
35+
title=__title__,
36+
version=__version__,
37+
description=api_description,
38+
docs_url="/docs",
39+
terms_of_service="https://github.com/anomaly/labs",
40+
contact={
41+
"name": "Anomaly Software",
42+
"url": "https://github.com/anomaly/labs",
43+
"email": "[email protected]"
44+
},
45+
license_info={
46+
"name": "Apache 2.0",
47+
"url": "https://www.apache.org/licenses/LICENSE-2.0"
48+
},
49+
openapi_tags=[
50+
{
51+
"name": "auth",
52+
"description": "Authentication related endpoints"
53+
}
54+
]
55+
)
5556

5657
# Additional routers of the application described in the routers package
5758
app.include_router(router_auth, prefix="/auth")
5859
app.include_router(router_ext, prefix="/ext")
5960

6061

62+
6163
@app.get("/")
6264
async def root(request: Request):
6365
"""Placeholder for the root endpoint
@@ -78,4 +80,24 @@ async def websocket_endpoint(websocket: WebSocket):
7880
await websocket.send_text(f"Message text was: {data}")
7981

8082
# Hook up any events worth responding to
81-
# https://fastapi.tiangolo.com/advanced/events/
83+
# https://fastapi.tiangolo.com/advanced/events/
84+
85+
# With a little help from FastAPI docs
86+
# https://bit.ly/3rXeAvH
87+
#
88+
# Globally use the path name as the operation id thus
89+
# making things a lot more readable, note that this requires
90+
# you name your functions really well.
91+
def use_route_names_as_operation_ids(app: FastAPI) -> None:
92+
"""
93+
Simplify operation IDs so that generated API clients have simpler function
94+
names.
95+
96+
Should be called only after all routes have been added.
97+
"""
98+
for route in app.routes:
99+
if isinstance(route, APIRoute):
100+
route.operation_id = route.name
101+
102+
103+
use_route_names_as_operation_ids(app)

src/labs/routers/auth/__init__.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ async def login_user(request: PasswordLoginRequest,
4949
token_type="Bearer",
5050
expires_in=100)
5151

52+
5253
@router.post("/refresh",
5354
summary=""" Provides an endpoint for refreshing the JWT token""",
5455
response_model=AuthResponse,
@@ -66,11 +67,15 @@ async def refresh_jwt_token(request: Request,
6667
operation_id="logout_user"
6768
)
6869
async def logout_user(session: AsyncSession = Depends(session_context)):
70+
""" Ends a users session
71+
72+
"""
6973
return {}
7074

7175
@router.get("/me", response_model=UserRequest)
7276
async def get_me(request: Request,
73-
session: AsyncSession = Depends(session_context)):
77+
session: AsyncSession = Depends(session_context)
78+
):
7479
"""Get the currently logged in user or myself
7580
7681
This endpoint will return the currently logged in user or raise

src/labs/routers/auth/create.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
operation_id="signup_user",
2020
)
2121
async def signup_user(request: SignupRequest,
22-
session: AsyncSession = Depends(get_async_session)):
22+
session: AsyncSession = Depends(get_async_session)
23+
):
2324
# Try and get a user by email
2425
user = await User.get_by_email(session, request.email)
2526
if user:
@@ -34,7 +35,7 @@ async def signup_user(request: SignupRequest,
3435
"/verify",
3536
operation_id="verify_user",
3637
)
37-
async def verify_user_account(request: Request):
38+
async def verify_user(request: Request):
3839
"""Verify an account
3940
"""
4041
verification_email.delay()

src/labs/routers/auth/otp.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616

1717
@router.post("/initiate/email",
1818
response_model=OTPTriggerResponse,
19-
operation_id="initiate_otp_via_email",
2019
)
21-
async def initiate_otp_request(request: OTPTriggerEmailRequest,
22-
session: AsyncSession = Depends(get_async_session)):
20+
async def initiate_otp_email(request: OTPTriggerEmailRequest,
21+
session: AsyncSession = Depends(get_async_session)
22+
):
2323
""" Attempt to authenticate a user and issue JWT token
2424
2525
The user has provided us their email address and we will
@@ -42,10 +42,10 @@ async def initiate_otp_request(request: OTPTriggerEmailRequest,
4242

4343
@router.post("/initiate/sms",
4444
response_model=OTPTriggerResponse,
45-
operation_id="initiate_otp_via_sms"
4645
)
47-
async def initiate_otp_request(request: OTPTriggerSMSRequest,
48-
session: AsyncSession = Depends(get_async_session)):
46+
async def initiate_otp_sms(request: OTPTriggerSMSRequest,
47+
session: AsyncSession = Depends(get_async_session)
48+
):
4949
""" Attempt to authenticate a user and issue JWT token
5050
5151
The user has provided a mobile number and we will text them
@@ -66,7 +66,8 @@ async def initiate_otp_request(request: OTPTriggerSMSRequest,
6666

6767
@router.post("/verify")
6868
async def verify_otp(request: OTPVerifyRequest,
69-
session: AsyncSession = Depends(get_async_session)):
69+
session: AsyncSession = Depends(get_async_session)
70+
):
7071
""" Attempt to authenticate a user and issue JWT token
7172
7273
"""

src/labs/routers/ext/__init__.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ async def echo(request: Request):
1919
return {"message": "Hello, world!"}
2020

2121
@router.get("/healthcheck")
22-
async def perform_healthcheck(request: Request):
22+
async def get_health(request: Request):
2323
"""Check the health of the server.
2424
2525
Purpose of this endpoint is to check the health of the server.
@@ -30,7 +30,9 @@ async def perform_healthcheck(request: Request):
3030

3131

3232
@router.get("/log")
33-
async def write_to_logger(request: Request, session: AsyncSession = Depends(session_context)):
33+
async def test_logger(request: Request,
34+
session: AsyncSession = Depends(session_context)
35+
):
3436
"""Log a message.
3537
3638
Purpose of this endpoint is to log a message to the logger.

src/labs/routers/stripe/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
# Note that include_in_schema=False and this will not appear
3434
# in the OpenAPI documentation
3535
@router.post("/webhook", include_in_schema=False)
36-
async def process_webhook(
36+
async def stripe_webhook(
3737
request: Request,
3838
background_tasks: BackgroundTasks,
3939
STRIPE_SIGNATURE: str = Header(default=None),

0 commit comments

Comments
 (0)