'How to override a function which is used in multiple places in an application in python?

I have a few functions which use S3 to access resources and these functions are used in many places in my application these s3 codes are saved in the aws_resource.py script.

def create_client():
    client = boto3.client('s3',
                          region_name=current_app.config["REGION_NAME"],
                          aws_access_key_id=current_app.config["AWS_ACCESS_KEY_ID"],
                          aws_secret_access_key=current_app.config["AWS_SECRET_ACCESS_KEY"])
    return client


def create_resource():
    s3 = boto3.resource('s3',
                        region_name=current_app.config["REGION_NAME"],
                        aws_access_key_id=current_app.config["AWS_ACCESS_KEY_ID"],
                        aws_secret_access_key=current_app.config["AWS_SECRET_ACCESS_KEY"])
    return s3

def boto_object_read(bucket_name, key):
    client = create_client()
    response = client.get_object(Bucket=bucket_name, Key=key)
    return response


def boto_object_write(bucket_name, key):
    s3 = create_resource()
    return s3.Object(bucket_name, key)

Used in many parts of the code.

from ..aws_resource import create_client, create_resource
s3 = create_resource()
obj = s3.Object(bucket_name, key_prediction)

Now our application is moving to the Azure cloud. I do not want to change the function calls which are already present in many places.

I want to override these methods based on an environmental variable. So something like the below code

def create_resource():

    if os.environ.get("CLOUD_ENV") == "AWS":
        s3 = boto3.resource('s3',
                            region_name=current_app.config["REGION_NAME"],
                            aws_access_key_id=current_app.config["AWS_ACCESS_KEY_ID"],
                            aws_secret_access_key=current_app.config["AWS_SECRET_ACCESS_KEY"])
    else:

        s3 = azure_lib("storage", region_name="something",..)

    return s3

What should be my approach should I recreate a new class which has methods for AWS and AZURE and then instantiate and call the methods ( I do not want to do this ). Which is the best and most scalable method, next time I want to scale to the GCP platform with different methods coming in.



Solution 1:[1]

Move the functions from "aws_resource.py" to a "real_aws_resource.py" (or whatever name). Write functions with same names for azure and place them in "azure_resource.py".

In "aws_resource.py" place something like

if os.environ.get("CLOUD_ENV") == "AWS":
    from .real_aws_resource import *
elif <platform is Azure>:
    from .azure_resource import *

Depending on the location of the modules the imports may need some adjustments.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1