Context: I’m trying to build a simple (read-only) python API client for a storage product dynamically.
Situation: The api server has endpoints like this:
- [GET] /monitor/host?nodeId=xxx[®ion=xxx]
- [GET] /monitor/nodelist?[region=xxx]
- [GET] /system/version
- [GET] /usage
My idea was to create classes for each endpoint (monitor, system, usage, etc), and then fetch the “child-endpoint” (in bold: /monitor/host or /monitor/nodelist, etc) dynamically… then, I would still need to fetch all URL the parameters (which are always optional and can only be: nodeId and/or region, etc)… the usage I have in something like this:
client = WhateverStorageApi()
client.monitor.host(hostId='node01', region='eu-west-1')
# the above would generate a str: /monitor/host?nodeId=node01®ion=eu-west-1
My problem is: __ getattr__ isn’t aware of any **kwargs, and __ call__ only works for whenever I call a class, which brings me to the question: is there any other well-known way of achieving this? Or is my usage idea completely non-sense? For example, I came up with:
class Monitor(object):
base_url = 'monitor'
def __getattr__(self, endpoint, **kwargs):
base_call = '/{base_url}/{endpoint}'.format(
base_url=Monitor.base_url,
endpoint=endpoint
)
if 'nodeId' in kwargs.keys():
base_call += '?nodeId={node_id}'.format(
node_id=kwargs['nodeId']
)
if 'region' in kwargs.keys():
base_call += '?region={region}'.format(
region=kwargs['region']
)
# do something with base_call
(which I know… it simply doesn’t work)