5
\$\begingroup\$

I have a script that makes a bunch of api calls (xml) and it's not adhering to DRY because I am repeating a lot of the code in the functions, what would be the best way to clean this up and reduce the amount of repeat code?

def get_api_key(hostname, username, password):
    url = 'https://' + hostname + '/api'
    values = {'type': 'keygen', 'user': username, 'password': password}
    response = requests.post(url, params=values, verify=False, proxies=proxies)
    return ET.fromstring(response.text).find('.//result/key').text

def add_template(hostname, api_key, template_name, name):
    url = 'https://' + hostname + '/api'
    values = {'type': 'config',
        'action': 'set',
        'xpath': f"entry[@name='{template_name}']/",
        'element': f"<tag>{name}</tag>",
        'key': api_key
        }
    requests.post(url, params=values, verify=False, proxies=proxies)
    return(template_name)

def add_template_stack(hostname, api_key, stack_name, template_name):
    url = 'https://' + hostname + '/api'
    values = {'type': 'config',
        'action': 'set',
        'xpath': f"entry[@name='{stack_name}']",
        'element': f"<tag>{template_name}</tag>",
        'key': api_key
        }
    requests.post(url, params=values, verify=False, proxies=proxies)
    return(stack_name)

def add_variable(template_name, var_name, netmask, hostname, api_key): 
    url = 'https://' + hostname + '/api'
    values = {'type': 'config',
        'action': 'set',
        'xpath': f"entry[@name='{template_name}']/variable/entry[@name='{var_name}']",
        'element': f"<tag>{netmask}</tag>",
        'key': api_key
        }
    requests.post(url, params=values, verify=False, proxies=proxies)
    return(var_name)
\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to Code Review! The current question title, which states your concerns about the code, is too general to be useful here. Please edit to the site standard, which is for the title to simply state the task accomplished by the code. Please see How do I ask a good question?, as well as How to get the best value out of Code Review: Asking Questions for guidance on writing good question titles. \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Aug 3 at 17:47
  • \$\begingroup\$ Not enough for an answer, but return shouldn't have parenthesis after it. Just return x. \$\endgroup\$ – Linny Aug 3 at 21:59
4
\$\begingroup\$

I think a good way to reduce the WET code here is to consolidate and generalize the core functionality to a single function, and tweak the arguments going into it accordingly. I left the get_api_key function alone and focused on the other ones as they are the most similar. See below:

def add_template_2(hostname, api_key, template_name, name):
    return add(hostname, api_key, template_name, name)


def add_template_stack_2(hostname, api_key, stack_name, template_name):
    return add(hostname, api_key, stack_name, template_name)


def add_variable_2(template_name, var_name, netmask, hostname, api_key):
    return add(hostname, api_key, template_name, netmask, var_name)


def add(hostname, api_key, xpath_name, element, xpath_var=None):
    url = f'https://{hostname}/api'

    if xpath_var:
        xpath = f"entry[@name='{xpath_name}']/variable/entry[@name='{xpath_var}']"
        ret_val = xpath_var
    else:
        xpath = f"entry[@name='{xpath_name}']"
        ret_val = xpath_name

    values = {'type': 'config',
        'action': 'set',
        'xpath': xpath,
        'element': f"<tag>{element}</tag>",
        'key': api_key
        }
    requests.post(url, params=values, verify=False, proxies=proxies)
    return(ret_val)
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.