Sunday, September 4, 2022

[SOLVED] pass parameters to a string json within a function

Issue

If I run a post request like this, it works:

def myFunction():
  contentTypeHeader = {
    'Content-type': 'application/json',
  }
 
  data = """
  {
  "target": {
    "ref_type": "branch",
    "type": "pipeline_ref_target",
    "ref_name": "master",
  "selector": {
    "type": "custom",
    "pattern" : "mypipeline"
    }
  },
  "variables": []
  }
  """

  http = urllib3.PoolManager()
  headers = urllib3.make_headers(basic_auth='{}:{}'.format("username", "password"))
  headers = dict(list(contentTypeHeader .items()) + list(headers.items()))
  try:
    resp = http.urlopen('POST', 'https://api.bitbucket.org/2.0/repositories/owner/slugg/pipelines/', headers=headers, body=data)
    print('Response', str(resp.data))
  except Exception as e:
    print('Error', e)


myFunction()

However, if instead of hardcoding the values, I try to pass them on as a function:

def myFunction(bitbucket_branch, pipeline_name):
  contentTypeHeader = {
    'Content-type': 'application/json',
  }
  
  data = """
  {
  "target": {
    "ref_type": "branch",
    "type": "pipeline_ref_target",
    "ref_name": "${bitbucket_branch}",
  "selector": {
    "type": "custom",
    "pattern" : "${pipeline_name}"
    }
  },
  "variables": []
  }
  """
...


 myFunction("master","mypipeline")

I get this error:

Response b'{"error": {"message": "Not found", "detail": "Could not find last reference for branch ${bitbucket_branch}", "data": {"key": "result-service.pipeline.reference-not-found", "arguments": {"uuid": "${bitbucket_branch}"}}}}'

Additionally, in my function :

def myFunction(bitbucket_branch, pipeline_name):

the parameters are still in a light color in my VSCode, which indicates that the parameters aren't actually being used in the function.

Perhaps I am doing something wrong with encoding strings but can't figure out what exactly.


Solution

Python does not expand ${pipeline_name} inside strings for you; this is a feature of Javascript template strings (and is not part of JSON) - so unless you run actual Javascript, this is not going to work.

However, python have f-strings, which does the same:

def myFunction(bitbucket_branch, pipeline_name):
  contentTypeHeader = {
    'Content-type': 'application/json',
  }

  # notice the added f and removal of $
  data = f"""    
  {
  "target": {
    "ref_type": "branch",
    "type": "pipeline_ref_target",
    "ref_name": "{bitbucket_branch}",
  "selector": {
    "type": "custom",
    "pattern" : "{pipeline_name}"
    }
  },
  "variables": []
  }
  """

This will replace the content in {} inside your string with the values from the variables. I'd also like to mention that you might want to declare this as a Python structure instead and use json.dumps to transform it to JSON. That way you can do anything you're used to in Python, instead of having a JSON template and replacing values inside that template (if either of these values contain ", you'll end up generating invalid JSON in this case).

import json

def myFunction(bitbucket_branch, pipeline_name):
  data = {
    "target": {
      "ref_type": "branch",
      "type": "pipeline_ref_target",
      "ref_name": bitbucket_branch,
      "selector": {
        "type": "custom",
        "pattern" : pipeline_name
        }
      },
      "variables": []
    }
  }

  return json.dumps(data)


Answered By - MatsLindh
Answer Checked By - Marie Seifert (WPSolving Admin)