Home > Mobile >  How to call the right function (as a string) based on an argument?
How to call the right function (as a string) based on an argument?

Time:11-30

I have a class which is intended to create an IBM Cloud Object Storage object. There are 2 functions I can use for initialization : resource() and client(). In the init function there is an object_type parameter which will be used to decide which function to call.

class ObjectStorage:

    def __init__(self, object_type: str, endpoint: str, api_key: str, instance_crn: str, auth_endpoint: str):

        valid_object_types = ("resource", "client")
        if object_type not in valid_object_types:
            raise ValueError("Object initialization error: Status must be one of %r." % valid_object_types)

        method_type = getattr(ibm_boto3, object_type)()
        self._conn = method_type(
                    "s3",
                    ibm_api_key_id = api_key,
                    ibm_service_instance_id= instance_crn,
                    ibm_auth_endpoint = auth_endpoint,
                    config=Config(signature_version="oauth"),
                    endpoint_url=endpoint,
        )

    @property    
    def connect(self):
        return self._conn

If I run this, I receive the following error:

TypeError: client() missing 1 required positional argument: 'service_name'

If I use this in a simple function and call it by using ibm_boto3.client() or ibm_boto3.resource(), it works like a charm.

def get_cos_client_connection():
    COS_ENDPOINT = "xxxxx"
    COS_API_KEY_ID = "yyyyy"
    COS_INSTANCE_CRN = "zzzzz"
    COS_AUTH_ENDPOINT = "----"
    cos = ibm_boto3.client("s3",
            ibm_api_key_id=COS_API_KEY_ID,
            ibm_service_instance_id=COS_INSTANCE_CRN,
            ibm_auth_endpoint=COS_AUTH_ENDPOINT,
            config=Config(signature_version="oauth"),
            endpoint_url=COS_ENDPOINT
    )
    return cos

cos = get_cos_client_connection()

It looks like it calls the client function on this line, but I am not sure why:

method_type = getattr(ibm_boto3, object_type)()

I tried using:

method_type = getattr(ibm_boto3, lambda: object_type)()

but it was a silly move.

The client function looks like this btw:

def client(*args, **kwargs):
    """
    Create a low-level service client by name using the default session.

    See :py:meth:`ibm_boto3.session.Session.client`.
    """
    return _get_default_session().client(*args, **kwargs)

which refers to:

def client(self, service_name, region_name=None, api_version=None,
               use_ssl=True, verify=None, endpoint_url=None,
               aws_access_key_id=None, aws_secret_access_key=None, aws_session_token=None,
               ibm_api_key_id=None, ibm_service_instance_id=None, ibm_auth_endpoint=None,
               auth_function=None, token_manager=None,
               config=None):
        return self._session.create_client(
            service_name, region_name=region_name, api_version=api_version,
            use_ssl=use_ssl, verify=verify, endpoint_url=endpoint_url,
            aws_access_key_id=aws_access_key_id,
            aws_secret_access_key=aws_secret_access_key,
            aws_session_token=aws_session_token,
            ibm_api_key_id=ibm_api_key_id, ibm_service_instance_id=ibm_service_instance_id,
            ibm_auth_endpoint=ibm_auth_endpoint, auth_function=auth_function,
            token_manager=token_manager, config=config)

Same goes for resource()

CodePudding user response:

If you look at the stracktrace, it will probably point to this line:

method_type = getattr(ibm_boto3, object_type)()

And not the one after where you actually call it. The reason is simple, those last two parenthese () mean you're calling the function you just retrieved via getattr.

So simply do this:

method_type = getattr(ibm_boto3, object_type)

Which means that method_type is actually the method from the ibm_boto3 object you're interested in. Can confirm that by either debugging using import pdb; pdb.set_trace() and inspect it, or just add a print statement:

print(method_type)
  • Related