|
@@ -1,107 +1,67 @@
|
|
|
#! /usr/bin/env python3
|
|
|
# NOTE: Requires python3.10 or above
|
|
|
|
|
|
+import json
|
|
|
+import redis
|
|
|
+import uuid
|
|
|
+import sys
|
|
|
+
|
|
|
from enum import Enum
|
|
|
-from fastapi import FastAPI, Query
|
|
|
-from pydantic import BaseModel
|
|
|
+from fastapi import FastAPI, Query, HTTPException
|
|
|
+from fastapi.encoders import jsonable_encoder
|
|
|
+from pydantic import BaseModel, Field
|
|
|
|
|
|
app = FastAPI()
|
|
|
+r = redis.StrictRedis(host="redis.home.monkeybox.org", port=6379, db=0)
|
|
|
|
|
|
-# Root is an example, just returns static stuff
|
|
|
-@app.get("/")
|
|
|
-async def root():
|
|
|
- return {"message": "Hello World"}
|
|
|
-
|
|
|
-
|
|
|
-# /items is an example, just returns the provided value, but must be an int.
|
|
|
-@app.get("/items/{item_id}")
|
|
|
-async def read_items(item_id: int):
|
|
|
- return {"item_id": item_id}
|
|
|
-
|
|
|
-
|
|
|
-# /models only allows select values. These are machine learning models.
|
|
|
-class ModelName(str, Enum):
|
|
|
- alexnet = "alexnet" # FTD: Appears both sides have to match
|
|
|
- resnet = "resnet"
|
|
|
- lenet = "lenet"
|
|
|
-
|
|
|
-
|
|
|
-@app.get("/models/{model_name}")
|
|
|
-async def get_model(model_name: ModelName):
|
|
|
- if model_name is ModelName.alexnet:
|
|
|
- return {"model_name": model_name, "message": "Deep Learning FTW!"}
|
|
|
-
|
|
|
- if model_name.value == "lenet":
|
|
|
- return {"model_name": model_name, "message": "LeCNN all the images."}
|
|
|
-
|
|
|
- return {"model_name": model_name, "message": "Have some residuals"}
|
|
|
-
|
|
|
-
|
|
|
-# /items/ has query parameters
|
|
|
-fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
|
|
|
+# Games is a list of implemented games
|
|
|
+class Games(str, Enum):
|
|
|
+ # ttt3d = "ttt3d"
|
|
|
+ # euchre = "euchre"
|
|
|
+ # poker = "poker"
|
|
|
+ # ...?
|
|
|
+ ttt = "ttt"
|
|
|
|
|
|
|
|
|
-@app.get("/items/")
|
|
|
-async def read_item(skip: int = 0, limit: int = 10):
|
|
|
- return fake_items_db[skip : skip + limit] # first value, last value
|
|
|
-
|
|
|
-
|
|
|
-# /items2/ shows how to use an optional parameter
|
|
|
-@app.get("/items2/{item_id}")
|
|
|
-async def read_item2(item_id: str, q: str | None = None):
|
|
|
- if q:
|
|
|
- return {"item_id": item_id, "q": q}
|
|
|
- return {"item_id": item_id}
|
|
|
-
|
|
|
-
|
|
|
-# A POST to /items/, our first example with a body
|
|
|
-class Item(BaseModel):
|
|
|
- name: str
|
|
|
- description: str | None = None
|
|
|
- price: float
|
|
|
- tax: float | None = None
|
|
|
+class User(BaseModel):
|
|
|
+ username: str = Field(
|
|
|
+ title="User Name",
|
|
|
+ description="A username to identify yourself.",
|
|
|
+ min_length=3,
|
|
|
+ max_length=255,
|
|
|
+ regex="^[A-Za-z0-9 -_]*$",
|
|
|
+ )
|
|
|
+ secret: str | None = Field(
|
|
|
+ default=None,
|
|
|
+ description="A secret, currently assign from the server",
|
|
|
+ min_length=0,
|
|
|
+ max_length=64,
|
|
|
+ regex="^[A-Za-z0-64]*$",
|
|
|
+ )
|
|
|
|
|
|
|
|
|
-@app.post("/items/")
|
|
|
-async def create_item(item: Item):
|
|
|
- return item
|
|
|
+@app.get("/list")
|
|
|
+async def list_games():
|
|
|
+ return {"games": [g.name for g in Games]}
|
|
|
|
|
|
|
|
|
-# Validation:
|
|
|
-# max_length: async def read_items(q: str | None = Query(default=None, max_length=50)):
|
|
|
-# default: async def read_items(q: str = Query(default="fixedquery", min_length=3)):
|
|
|
-# Regex: Query(default=None, ..., regex="^fixedquery$"
|
|
|
-# List: async def read_items(q: list[str] | None = Query(default=None)): # call via ?q=foo&q=bar&q=zoo
|
|
|
-# more: https://fastapi.tiangolo.com/tutorial/query-params-str-validations/
|
|
|
-@app.get("/items3/")
|
|
|
-async def read_items(
|
|
|
- q: list[str] | None = Query(default=None),
|
|
|
-): # call via ?q=foo&q=bar&q=zoo
|
|
|
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
|
|
- if q:
|
|
|
- results.update({"q": q})
|
|
|
- return results
|
|
|
+@app.post("/login")
|
|
|
+async def login(user: User):
|
|
|
+ j_user = jsonable_encoder(user)
|
|
|
+ if j_user.get("secret") is not None:
|
|
|
+ raise HTTPException(
|
|
|
+ status_code=500, detail="You may not specify a secret during login"
|
|
|
+ )
|
|
|
+ j_user["secret"] = uuid.uuid4().hex
|
|
|
+ return j_user
|
|
|
|
|
|
|
|
|
-# More metadata (https://fastapi.tiangolo.com/tutorial/query-params-str-validations/)
|
|
|
-# Big example of lots of metadata
|
|
|
-@app.get("/items4/")
|
|
|
-async def read_items(
|
|
|
- q: str
|
|
|
- | None = Query(
|
|
|
- default=None,
|
|
|
- alias="item-query",
|
|
|
- title="Query string",
|
|
|
- description="Query string for the items to search in the database that have a good match",
|
|
|
- min_length=3,
|
|
|
- max_length=50,
|
|
|
- regex="^fixedquery$",
|
|
|
- # gt=0, # For numeric types, Won't work here, "greater than"
|
|
|
- # le=1000, # for numeric types, "less than or equal"
|
|
|
- deprecated=True,
|
|
|
- )
|
|
|
-):
|
|
|
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
|
|
- if q:
|
|
|
- results.update({"q": q})
|
|
|
- return results
|
|
|
+## def main():
|
|
|
+## print(f"Not intended to be run from command-line")
|
|
|
+##
|
|
|
+##
|
|
|
+### sys.exit(1)
|
|
|
+##
|
|
|
+##
|
|
|
+## if __name__ == "__main__":
|
|
|
+## main()
|