From b5d34fb311ef021778c6fbebff84af6683d7ce5c Mon Sep 17 00:00:00 2001 From: RomanZorkin Date: Tue, 2 Nov 2021 18:31:05 +0700 Subject: [PATCH] issue #28 solution Create an integration test for /share endpoint #28 --- geopatterns_demo/api.py | 12 +++++- geopatterns_demo/file_handler.py | 74 ++++++++++++++++++++++++++++++++ geopatterns_demo/models.py | 9 ++++ geopatterns_demo/settings.py | 4 ++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 geopatterns_demo/file_handler.py diff --git a/geopatterns_demo/api.py b/geopatterns_demo/api.py index ea50232..7641b14 100644 --- a/geopatterns_demo/api.py +++ b/geopatterns_demo/api.py @@ -9,6 +9,7 @@ from geopatterns_demo import methods_list, models, random_phrase, settings from geopatterns_demo.draw import geopattern +from geopatterns_demo.file_handler import get_url if settings.IS_IN_LAMBDA: sentry_sdk.init( @@ -60,8 +61,17 @@ def methods(): response_model=models.PhraseDescription, ) def phrase(): - """Generate and return return random phrase.""" + """Generate and return random phrase.""" return models.PhraseDescription(text=random_phrase.make_random_text()) +@api.get('/share',response_model=models.FileURL) +def share( + text: str = fastapi.Query(..., max_length=1024), + method: models.Method = models.Method.HEXAGONS, +): + """Save the GeoPattern file to S3 and returns it's url.""" + return get_url(text, method) + + lambda_handler = Mangum(api) diff --git a/geopatterns_demo/file_handler.py b/geopatterns_demo/file_handler.py new file mode 100644 index 0000000..8bcfa81 --- /dev/null +++ b/geopatterns_demo/file_handler.py @@ -0,0 +1,74 @@ +from io import BytesIO + +import boto3 + +from geopatterns_demo import models, settings +from geopatterns_demo.draw import geopattern + + +def hash_name(text: str) -> str: + """Generate the file name using the hash function. + + Args: + text (str): text that we get from get request + + Returns: + str: file name + """ + return 'image{0}.png'.format(hash(text)) + + +def check_file(file_name: str, bucket: boto3) -> bool: + """Check the file for presence in the S3 bucket. + + Args: + file_name (str): image file name + bucket (boto3): boto3 object - S3 bucket + + Returns: + bool: bool + """ + bucket_object = list(bucket.objects.filter(Prefix=file_name)) + if len(bucket_object) > 0: # noqa: WPS507 + return bucket_object + + +def file_to_s3(file_name: str, image: BytesIO) -> str: + """Save file to S3 bucket & return it's URL. + + Args: + file_name (str): image file name + image (BytesIO): image object in bytes + + Returns: + str: url + """ + s3 = boto3.Resource('s3') + bucket = s3.Bucket(settings.S3_BUCKET_NAME) + bucket.upload_fileobj(image.read(), file_name) + if check_file(file_name, bucket): + return 'http://s3-{0}-.amazonaws.com/{1}/{2}'.format( + settings.AWS_REGION, + settings.S3_BUCKET_NAME, + file_name, + ) + return 'error: file is not saving.' + + +def get_url(text: str, method: models.Method) -> str: + """Generate Geopatterns file & and starts the procedure for saving it. + + Args: + text (str): text that we get from get request + method: method for generate Geopatterns + + Returns: + str: url + """ + return file_to_s3( + hash_name(text), + image=geopattern( + text=text, + method=method, + ), + ) diff --git a/geopatterns_demo/models.py b/geopatterns_demo/models.py index bcfb224..59d7e92 100644 --- a/geopatterns_demo/models.py +++ b/geopatterns_demo/models.py @@ -46,3 +46,12 @@ class Thesaurus(Enum): ADJECTIVES = Path(__file__).parent / 'dictionary/adjectives.txt' NOUNS = Path(__file__).parent / 'dictionary/nouns.txt' + + +class FileURL(BaseModel): + """Class declares the model used for the response. + + Model used for the response in the /share API endpoint. + """ + + url: str diff --git a/geopatterns_demo/settings.py b/geopatterns_demo/settings.py index a9535c6..91e7fd7 100644 --- a/geopatterns_demo/settings.py +++ b/geopatterns_demo/settings.py @@ -5,3 +5,7 @@ ) IS_IN_LAMBDA = os.environ.get('AWS_EXECUTION_ENV') is not None + +S3_BUCKET_NAME = 'geopatterns-demo-images' + +AWS_REGION = 'us-east-1'