diff --git a/clients/python/moonstream/aws/__init__.py b/clients/python/moonstream/aws/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/clients/python/moonstream/aws/bucket.py b/clients/python/moonstream/aws/bucket.py new file mode 100644 index 00000000..4eab58f3 --- /dev/null +++ b/clients/python/moonstream/aws/bucket.py @@ -0,0 +1,24 @@ +from typing import Any, Dict + +import boto3 + + +def upload_to_aws_s3_bucket( + data: str, + bucket: str, + key: str, + metadata: Dict[str, Any] = {}, +) -> str: + """ + Push data to AWS S3 bucket and return URL to object. + """ + s3 = boto3.client("s3") + s3.put_object( + Body=data, + Bucket=bucket, + Key=key, + ContentType="application/json", + Metadata=metadata, + ) + + return f"{bucket}/{key}" diff --git a/clients/python/moonstream/client.py b/clients/python/moonstream/client.py index ddaf0a03..036afa5e 100644 --- a/clients/python/moonstream/client.py +++ b/clients/python/moonstream/client.py @@ -3,6 +3,10 @@ from typing import Any, Dict, Union import requests +try: + from .aws.bucket import upload_to_aws_s3_bucket +except Exception as e: + pass from .data import ( APISpec, AuthType, @@ -68,12 +72,12 @@ class Moonstream: method.value, url=url, timeout=timeout, **kwargs ) response.raise_for_status() - except requests.exceptions.RequestException as err: - r = err.response - if not err.response: + except requests.exceptions.RequestException as e: + r = e.response + if not e.response: # Connection errors, timeouts, etc... raise MoonstreamResponseException( - "Network error", status_code=599, detail=str(err) + "Network error", status_code=599, detail=str(e) ) if r.headers.get("Content-Type") == "application/json": exception_detail = r.json()["detail"] @@ -223,6 +227,23 @@ class Moonstream: return output + def upload_query_results( + self, data: str, bucket: str, key: str, metadata: Dict[str, Any] = {} + ) -> str: + """ + Uploads data to AWS S3 bucket. + + Requirements: "pip install -e .[aws]" with "boto3" module. + """ + try: + url = upload_to_aws_s3_bucket( + data=data, bucket=bucket, key=key, metadata=metadata + ) + except Exception as e: + raise Exception(str(e)) + + return url + def delete_query( self, token: Union[str, uuid.UUID], diff --git a/clients/python/mypy.ini b/clients/python/mypy.ini new file mode 100644 index 00000000..29ecf6ac --- /dev/null +++ b/clients/python/mypy.ini @@ -0,0 +1,4 @@ +[mypy] + +[mypy-boto3.*] +ignore_missing_imports = True \ No newline at end of file diff --git a/clients/python/setup.py b/clients/python/setup.py index c6abb690..a3733873 100644 --- a/clients/python/setup.py +++ b/clients/python/setup.py @@ -13,6 +13,7 @@ setup( package_data={"moonstream": ["py.typed"]}, install_requires=["requests", "pydantic", "dataclasses; python_version=='3.6'"], extras_require={ + "aws": ["boto3"], "dev": [ "black", "mypy",