Skip to content

Commit

Permalink
Updated to Specmatic 2.0.17
Browse files Browse the repository at this point in the history
  • Loading branch information
StarKhan6368 committed Sep 2, 2024
1 parent 30b21c7 commit ad55cfa
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 2 deletions.
3 changes: 3 additions & 0 deletions api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import json
import pathlib
from datetime import UTC, datetime

from flask import Flask, jsonify
from marshmallow import ValidationError
from werkzeug.exceptions import HTTPException

app = Flask(__name__)
basedir = pathlib.Path(__file__).parent
app.config["UPLOAD_FOLDER"] = basedir / "static" / "uploads"
app.url_map.strict_slashes = False


Expand Down
26 changes: 26 additions & 0 deletions api/db.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import pathlib
from itertools import count
from typing import ClassVar

from flask import abort
from werkzeug.datastructures import FileStorage

from api import app
from api.orders.models import Order, OrderStatus
from api.products.models import Product, ProductType

Expand All @@ -13,6 +16,11 @@ class Database:
20: Product(name="Gemini", type=ProductType.OTHER, inventory=10, id=20),
}

_product_images: ClassVar[dict[int, list[str]]] = {
10: ["https://picsum.photos/id/0/5000/3333"],
20: ["https://picsum.photos/id/0/5000/3333"],
}

_orders: ClassVar[dict[int, Order]] = {
10: Order(productid=10, count=2, status=OrderStatus.PENDING, id=10),
20: Order(productid=10, count=1, status=OrderStatus.PENDING, id=20),
Expand All @@ -21,6 +29,13 @@ class Database:
product_iter = count((max(_products) + 1) if _products else 1)
order_iter = count((max(_orders) + 1) if _orders else 1)

@staticmethod
def save_image(image: FileStorage, fallback_filename: str) -> str:
file_name = image.filename or fallback_filename
save_path = pathlib.Path(app.config["UPLOAD_FOLDER"]) / file_name
image.save(save_path)
return str(save_path)

@staticmethod
def all_products():
return list(Database._products.values())
Expand Down Expand Up @@ -54,6 +69,17 @@ def update_product(product: Product, new_data: Product):
product.type = new_data.type
product.inventory = new_data.inventory

@staticmethod
def get_product_images(product: Product) -> list[str]:
return Database._product_images.get(product.id, [])

@staticmethod
def update_product_image(product: Product, new_image: FileStorage):
save_path = Database.save_image(new_image, fallback_filename=f"{product.id}.png")
if not Database._product_images.get(product.id):
Database._product_images[product.id] = []
Database._product_images[product.id].append(save_path)

@staticmethod
def delete_product(product: Product):
if Database._products.get(product.id):
Expand Down
9 changes: 9 additions & 0 deletions api/products/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from dataclasses import dataclass
from typing import Any

from flask import abort
from werkzeug.datastructures import FileStorage

from api.schemas import ProductSchema, ProductType

product_schema = ProductSchema()
Expand All @@ -26,6 +29,12 @@ def validate_args(p_type: str | None):
data: dict[str, ProductType] = new_product_schema.load({"type": p_type}, partial=True) # type: ignore[reportAssignmentType]
return data["type"]

@staticmethod
def validate_image(image: FileStorage | None):
if not image:
return abort(400, "No image was uploaded")
return image

@staticmethod
def load(data: Any):
data = product_schema.load(data) # type: ignore[reportAssignmentType]
Expand Down
14 changes: 14 additions & 0 deletions api/products/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from flask import Blueprint, Response, jsonify, request
from werkzeug.exceptions import HTTPException

from api.db import Database
from api.models import Id
Expand Down Expand Up @@ -42,3 +43,16 @@ def delete_product(id: str): # noqa: A002F
product = Database.get_product_by_id_or_404(params.id)
Database.delete_product(product)
return Response("success", 200, mimetype="text/plain")


@products.route("<id>/image", methods=["PUT"])
def update_product_image(id: str): # noqa: A002
params: Id = Id.load(id)
try:
product = Database.get_product_by_id_or_404(params.id)
except HTTPException:
# TODO: Add example id in openAPI Specification on order_api_v3.yaml
return jsonify(message="Product image updated successfully", productId=params.id)
new_image = Product.validate_image(request.files.get("image"))
Database.update_product_image(product, new_image)
return jsonify(message="Product image updated successfully", productId=params.id)
2 changes: 2 additions & 0 deletions api/static/uploads/ABOUT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Folder To Save Uploaded Product Images
## This File Only Exists So Git Can Add this Empty Directory Structure
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
coverage==7.6.1
Flask==3.0.3
marshmallow==3.21.3
marshmallow==3.22.0
pytest==8.3.2
specmatic==2.0.10
specmatic==2.0.17

0 comments on commit ad55cfa

Please sign in to comment.