diff --git a/drakes_api/Dockerfile b/drakes_api/Dockerfile new file mode 100644 index 0000000..9ff7c82 --- /dev/null +++ b/drakes_api/Dockerfile @@ -0,0 +1,24 @@ +# +FROM python:3.9 + +# +LABEL authors="JoseLevel" + +# Setting env variable via arg to be passed at container run time or build time +ARG MONGO_URI_ARG +ENV MONGO_URI=$MONGO_URI_ARG + +# +WORKDIR /drakes_api + +# +COPY ./requirements.txt /drakes_api/requirements.txt + +# +RUN pip install --no-cache-dir --upgrade -r /drakes_api/requirements.txt + +# +COPY ./app /drakes_api/app + +# +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] \ No newline at end of file diff --git a/drakes_api/crud.py b/drakes_api/app/crud.py similarity index 74% rename from drakes_api/crud.py rename to drakes_api/app/crud.py index 0ba642a..97ae53b 100644 --- a/drakes_api/crud.py +++ b/drakes_api/app/crud.py @@ -1,8 +1,9 @@ from pymongo import MongoClient -from models import Lookbook +from app.models import Lookbook +import os # MongoDB Setup -MONGO_URI = "mongodb+srv://user2:x7s1uNrJePt7ZvCq@cluster1.rdtlrgq.mongodb.net/?retryWrites=true&w=majority" +MONGO_URI = os.getenv("MONGO_URI") client = MongoClient(MONGO_URI) db = client.drakes_lookbooks lookbooks_collection = db.lookbooks @@ -19,7 +20,10 @@ def check_db_connection(): if db.lookbooks is not None: print(f"Lookbook collection: {db.lookbooks}") check += 1 - return check == 3 + if db.lookbooks.find_one({"lookbook_name": "spring-summer-2017-lookbook"}) is not None: + print(f'Lookbook = {db.lookbooks.find_one({"lookbook_name": "spring-summer-2017-lookbook"})}') + check += 1 + return check == 4 def retrieve_lookbook_by_tag(tags: list[str]) -> list[Lookbook]: diff --git a/drakes_api/lookbook_upload.py b/drakes_api/app/lookbook_upload.py similarity index 86% rename from drakes_api/lookbook_upload.py rename to drakes_api/app/lookbook_upload.py index 76650e8..af66523 100644 --- a/drakes_api/lookbook_upload.py +++ b/drakes_api/app/lookbook_upload.py @@ -1,9 +1,10 @@ import os -from pymongo import MongoClient + +from app.crud import client import typer -MONGO_URI = "mongodb+srv://user2:x7s1uNrJePt7ZvCq@cluster1.rdtlrgq.mongodb.net/?retryWrites=true&w=majority" + app = typer.Typer() google_storage_bucket_base = "https://storage.googleapis.com/drakes_lookbooks_bucket/drakes_images/" @@ -26,12 +27,8 @@ def iterate_subdirectories(directory_path: str): for root, directories, _ in os.walk(directory_path): for lookbook in directories: lookbook_path = os.path.join(root, lookbook) - # typer.echo(f"Lookbook: {lookbook_path}") for _, _, files in os.walk(lookbook_path): - # typer.echo(f"lookbook_name: {lookbook}") - # typer.echo(f" tags: []") image_paths = [google_storage_bucket_base + lookbook + "/" + image_name for image_name in files] - # typer.echo(f" images: {image_paths}") new_lookbook = create_lookbook_dict(lookbook_name=lookbook, lookbook_tags=[], image_paths=image_paths) upload_lookbook(new_lookbook) @@ -52,7 +49,7 @@ def upload_lookbook(lookbooks_to_upload: list[dict]): """Uploads given lookbook to Google Cloud""" try: - client = MongoClient(MONGO_URI) + # Check the connection by listing database names print(f"Client: {client}") database_names = client.list_databases() diff --git a/drakes_api/main.py b/drakes_api/app/main.py similarity index 62% rename from drakes_api/main.py rename to drakes_api/app/main.py index e5722e0..7e932d0 100644 --- a/drakes_api/main.py +++ b/drakes_api/app/main.py @@ -1,7 +1,7 @@ from fastapi import FastAPI, Query -from models import FilterParams, Lookbook -import crud +from app.models import Lookbook +from app import crud app = FastAPI(title="Unofficial Drakes Lookbook API", @@ -9,13 +9,13 @@ @app.get("/syscheck") -async def system_check(): +def system_check(): print(f"Starting system check for API and DB connection") return crud.check_db_connection() @app.get("/lookbooks/{title}") -async def get_lookbook(title: str) -> list[Lookbook]: +def get_lookbook(title: str) -> list[Lookbook]: print(f"Searching for {title} in lookbooks db...") lookbooks = crud.retrieve_lookbook_by_name(name=title) print(f"{lookbooks =}") @@ -23,17 +23,9 @@ async def get_lookbook(title: str) -> list[Lookbook]: @app.get("/lookbooks/any/") -async def get_lookbooks_any(tags: list[str] = Query(default=None)) -> list[Lookbook]: +def get_lookbooks_any(tags: list[str] = Query(default=None)) -> list[Lookbook]: """Returns all lookbooks that have the given tag(s)""" print(f"Searching for {tags} in lookbooks db...") lookbooks = crud.retrieve_lookbook_by_tag(tags=tags) print(f"{lookbooks =}") return lookbooks - - -@app.get("/lookbooks/all") -async def get_lookbooks_all(filter_params: FilterParams): - """Returns lookbooks that match ALL the tags given""" - # Use 'filter_params.tags' to filter lookbooks - # ... - return None diff --git a/drakes_api/models.py b/drakes_api/app/models.py similarity index 71% rename from drakes_api/models.py rename to drakes_api/app/models.py index 7e41847..1c3ee59 100644 --- a/drakes_api/models.py +++ b/drakes_api/app/models.py @@ -6,17 +6,9 @@ class FilterParams(BaseModel): tags: List[str] -# Temporarily unused (need to add infra to mongodb) -# class Image(BaseModel): -# filename: str -# path: str - - class Lookbook(BaseModel): - # id: str = Field(alias="_id", default=None) # Needs extra config to convert objectID to pydantic supported type lookbook_name: str tags: List[str] - # images: List[Image] images: List[str] class Config: diff --git a/drakes_api/app/test_main.py b/drakes_api/app/test_main.py new file mode 100644 index 0000000..f2e78cc --- /dev/null +++ b/drakes_api/app/test_main.py @@ -0,0 +1,28 @@ +from fastapi.testclient import TestClient +from app.main import app + +client = TestClient(app) + + +def test_system_check(): + response = client.get("/syscheck") + assert response.status_code == 200 + assert response.json() == True + + +def test_get_lookbook(): + response = client.get("/lookbooks/paris") + assert response.status_code == 200 + assert len(response.json()) == 1 + assert response.json()[0]["lookbook_name"] == "autumn-in-paris-lookbook" + + +def test_get_lookbooks_any(): + response = client.get("/lookbooks/any/?tags=2017") + assert response.status_code == 200 + assert len(response.json()) >= 1 + assert response.json()[0]["tags"] == [ + "spring-summer", + "2017", + "casual", + "menswear"] diff --git a/drakes_api/utilities.py b/drakes_api/app/utilities.py similarity index 94% rename from drakes_api/utilities.py rename to drakes_api/app/utilities.py index fd48e11..04005f7 100644 --- a/drakes_api/utilities.py +++ b/drakes_api/app/utilities.py @@ -1,6 +1,7 @@ from pymongo import MongoClient +import os -MONGO_URI = "mongodb+srv://user2:x7s1uNrJePt7ZvCq@cluster1.rdtlrgq.mongodb.net/?retryWrites=true&w=majority" +MONGO_URI = os.getenv("MONGO_URI") client = MongoClient(MONGO_URI) db = client.drakes_lookbooks diff --git a/drakes_api/connection.py b/drakes_api/connection.py deleted file mode 100644 index 73e0513..0000000 --- a/drakes_api/connection.py +++ /dev/null @@ -1,47 +0,0 @@ -from pymongo import MongoClient - -MONGO_URI = "mongodb+srv://user2:x7s1uNrJePt7ZvCq@cluster1.rdtlrgq.mongodb.net/?retryWrites=true&w=majority" - -new_lookbook = [ - { - "lookbook_name": "spring-summer-2017-lookbook", - "tags": ["spring-summer", "2017", "casual", "menswear"], - "images": [ - "/images/spring-summer-2017-lookbook/image_22.jpg", - "/images/spring-summer-2017-lookbook/image_21.jpg", - "/images/spring-summer-2017-lookbook/image_20.jpg", - "/images/spring-summer-2017-lookbook/image_19.jpg", - "/images/spring-summer-2017-lookbook/image_18.jpg", - "/images/spring-summer-2017-lookbook/image_17.jpg", - "/images/spring-summer-2017-lookbook/image_11.jpg", - "/images/spring-summer-2017-lookbook/image_10.jpg", - "/images/spring-summer-2017-lookbook/image_9.jpg", - "/images/spring-summer-2017-lookbook/image_8.jpg", - "/images/spring-summer-2017-lookbook/image_7.jpg", - "/images/spring-summer-2017-lookbook/image_3.jpg", - "/images/spring-summer-2017-lookbook/image_1.jpg" - ] - }, -] - -try: - client = MongoClient(MONGO_URI) - # Check the connection by listing database names - print(f"Client: {client}") - database_names = client.list_databases() - print("Connected to MongoDB. Database names:") - for db_name in database_names: - print(db_name) - db = client.drakes_lookbooks - lookbooks_collection = db.lookbooks - result = lookbooks_collection.insert_many(new_lookbook) - - document_ids = result.inserted_ids - print("# of documents inserted: " + str(len(document_ids))) - print(f"_ids of inserted documents: {document_ids}") - - client.close() - - -except Exception as e: - print(f"Error connecting to MongoDB: {e}") diff --git a/drakes_api/requirements.txt b/drakes_api/requirements.txt index ec689f3..bdf350a 100644 --- a/drakes_api/requirements.txt +++ b/drakes_api/requirements.txt @@ -11,21 +11,26 @@ httpcore==1.0.2 httptools==0.6.1 httpx==0.25.2 idna==3.6 +iniconfig==2.0.0 install==1.3.5 itsdangerous==2.1.2 Jinja2==3.1.2 MarkupSafe==2.1.3 orjson==3.9.10 +packaging==24.0 +pluggy==1.4.0 pydantic==2.5.2 pydantic-core==2.14.5 pydantic-extra-types==2.1.0 pydantic-settings==2.1.0 pymongo==4.6.2 +pytest==8.1.1 python-dotenv==1.0.0 python-multipart==0.0.6 PyYAML==6.0.1 sniffio==1.3.0 starlette==0.27.0 +tomli==2.0.1 typer==0.9.0 typing-extensions==4.8.0 ujson==5.8.0