patharanor commited on
Commit
ab2ae08
·
1 Parent(s): c0fa56d

initial project

Browse files
Files changed (9) hide show
  1. .dockerignore +2 -0
  2. .gitignore +2 -0
  3. Dockerfile +14 -0
  4. README.md +7 -5
  5. apis/s3.py +50 -0
  6. app.py +76 -0
  7. models/common_headers.py +6 -0
  8. models/image_object.py +8 -0
  9. requirements.txt +7 -0
.dockerignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ __pycache__
2
+ .env
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ __pycache__
2
+ .env
Dockerfile ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the official Python 3.10.9 image
2
+ FROM python:3.10.9
3
+
4
+ # Copy the current directory contents into the container at .
5
+ COPY . .
6
+
7
+ # Set the working directory to /
8
+ WORKDIR /
9
+
10
+ # Install requirements.txt
11
+ RUN pip install --no-cache-dir --upgrade -r /requirements.txt
12
+
13
+ # Start the FastAPI app on port 7860, the default port expected by Spaces
14
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,9 +1,11 @@
1
  ---
2
- title: Qccamapi
3
- emoji: 👁
4
- colorFrom: purple
5
- colorTo: indigo
6
- sdk: docker
 
 
7
  pinned: false
8
  ---
9
 
 
1
  ---
2
+ title: QCCam APIs
3
+ emoji: 📈
4
+ colorFrom: red
5
+ colorTo: green
6
+ sdk: gradio
7
+ sdk_version: 4.44.0
8
+ app_file: app.py
9
  pinned: false
10
  ---
11
 
apis/s3.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import boto3
3
+ from dotenv import load_dotenv
4
+ load_dotenv()
5
+
6
+ class S3:
7
+
8
+ def __init__(self) -> None:
9
+ self.aws_access_key_id = os.getenv('AWS_ACCESS_KEY_ID', '')
10
+ self.aws_secret_access_key = os.getenv('AWS_SECRET_ACCESS_KEY', '')
11
+ self.aws_default_region = os.getenv('AWS_DEFAULT_REGION', '')
12
+
13
+ self.client = boto3.client(
14
+ service_name='s3',
15
+ region_name=self.aws_default_region,
16
+ aws_access_key_id=self.aws_access_key_id,
17
+ aws_secret_access_key=self.aws_secret_access_key
18
+ )
19
+
20
+ # Function to list images in a specific S3 bucket
21
+ def list_images_in_bucket(self, bucket_name):
22
+ response = self.client.list_objects_v2(Bucket=bucket_name)
23
+ return [obj['Key'] for obj in response.get('Contents', []) if obj['Key'].lower().endswith(('.png', '.jpg', '.jpeg'))]
24
+
25
+ # Function to get image URLs
26
+ def get_image_urls(self, bucket_name, image_keys):
27
+ return [self.client.generate_presigned_url('get_object', Params={'Bucket': bucket_name, 'Key': key}) for key in image_keys]
28
+
29
+ # Function to upload file to S3
30
+ def upload_file(self, bucket_name, file, name):
31
+ print(f'Uploading "{name}"...')
32
+ return self.client.upload_fileobj(file, bucket_name, name)
33
+
34
+ # Function to delete a file from S3
35
+ def delete_image(self, bucket_name, file_key):
36
+ if isinstance(file_key, list):
37
+ for k in file_key:
38
+ print(f'Removing "{k}"...')
39
+ self.client.delete_object(Bucket=bucket_name, Key=k)
40
+ else:
41
+ self.client.delete_object(Bucket=bucket_name, Key=file_key)
42
+
43
+ # Function to list images in a specific S3 bucket
44
+ def list_files_in_bucket(self, bucket_name):
45
+ response = self.client.list_objects_v2(Bucket=bucket_name)
46
+ return [obj['Key'] for obj in response.get('Contents', [])]
47
+
48
+ # Function to get image URLs
49
+ def get_files_urls(self, bucket_name, file_keys):
50
+ return [self.client.generate_presigned_url('get_object', Params={'Bucket': bucket_name, 'Key': key}) for key in file_keys]
app.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import Annotated
3
+ from fastapi import FastAPI, Header
4
+ from apis.s3 import S3
5
+ from dotenv import load_dotenv
6
+ from models.image_object import ImageObject
7
+ from models.common_headers import CommonHeaders
8
+ from fastapi.openapi.docs import (
9
+ get_redoc_html,
10
+ get_swagger_ui_html,
11
+ get_swagger_ui_oauth2_redirect_html,
12
+ )
13
+
14
+ load_dotenv()
15
+ IS_DEV = os.environ.get('ENV', 'DEV') != 'PROD'
16
+ AWS_S3_BUCKET_NAME = os.getenv('AWS_S3_BUCKET_NAME', '')
17
+ USERNAME = os.environ.get('USERNAME')
18
+ PASSWORD = os.environ.get('PASSWORD')
19
+
20
+ s3client = S3()
21
+ app = FastAPI(docs_url=None, redoc_url=None)
22
+
23
+ @app.get("/docs", include_in_schema=False)
24
+ async def custom_swagger_ui_html():
25
+ return get_swagger_ui_html(
26
+ openapi_url=app.openapi_url,
27
+ title=app.title + " - Swagger UI",
28
+ oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
29
+ swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
30
+ swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css",
31
+ )
32
+
33
+
34
+ @app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
35
+ async def swagger_ui_redirect():
36
+ return get_swagger_ui_oauth2_redirect_html()
37
+
38
+ @app.get("/redoc", include_in_schema=False)
39
+ async def redoc_html():
40
+ return get_redoc_html(
41
+ openapi_url=app.openapi_url,
42
+ title=app.title + " - ReDoc",
43
+ redoc_js_url="https://unpkg.com/redoc@next/bundles/redoc.standalone.js",
44
+ )
45
+
46
+ @app.get("/")
47
+ def root():
48
+ return {"message": "ok"}
49
+
50
+ @app.get("/health")
51
+ def healthcheck():
52
+ return {"message": "ok"}
53
+
54
+ @app.post("/image")
55
+ def upload(
56
+ o: ImageObject,
57
+ headers: Annotated[CommonHeaders, Header()]
58
+ ):
59
+ res = None
60
+ if headers.x_request_user == USERNAME \
61
+ and headers.x_api_key == PASSWORD:
62
+ key = f'{o.key}/{o.job_no}/{o.name}'
63
+ res = s3client.upload_file(AWS_S3_BUCKET_NAME, o.content, key)
64
+ return res
65
+
66
+ # # Create a Gradio interface
67
+ # with gr.Blocks() as demo:
68
+ # pass
69
+
70
+ # def auth(username, password):
71
+ # u = os.environ.get('USERNAME')
72
+ # p = os.environ.get('PASSWORD')
73
+ # return (username == u and password == p)
74
+
75
+ # # Launch the Gradio app
76
+ # demo.launch(auth=auth if not IS_DEV else None)
models/common_headers.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Union
3
+
4
+ class CommonHeaders(BaseModel):
5
+ x_request_user: str
6
+ x_api_key: str
models/image_object.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Union
3
+
4
+ class ImageObject(BaseModel):
5
+ name: str
6
+ key: str
7
+ job_no: str
8
+ content: Union[str, None] = None
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ boto3
2
+ gradio
3
+ pillow
4
+ pydantic
5
+ python-dotenv
6
+ fastapi[standard]
7
+ uvicorn