Bitbucket Cloud REST API: encoding and decoding multipart messages in Python?
Asked by Ray Depew:

Following up on my [previous question](https://community.atlassian.com/t5/Bitbucket-questions/How-to-copy-snippets-from-BB-server-to-BB-cloud/qaq-p/1897353#U1902336):

1. The Bitbucket Cloud REST API allows me to get a snippet in application/json, multipart/related, or multipart/form-data content types. The multipart content types include file contents, while the application/json content type includes links to the files on BB cloud. I have not yet succeeded at parsing the multipart output, separating it into the JSON metadata and the included files. How can I do that, using Python?

2. Similarly, the REST API allows me to create a snippet in multipart/related or multipart/form-data content types. I have successfully created an unnamed snippet using Python, but I have not successfully created a named snippet, or a snippet with one or more files in it. How can I do that, using Python?

I have successfully created named snippets with multiple files using cURL. I could include system calls to cURL in my Python code, but that's rather a kludge.

I've read the "Get a snippet" and "Create a snippet" sections of the REST API documentation several times, and I'm still stuck.


Answers:
author: Ray Depew
body: Well, I did the kludge. It took less time than learning how to deal with multipart messages.

Handling MIME multipart messages is a skill that has been around for decades (literally). It's a generic skill, not specific to any OS, software package, or entity. But it's something that I never learned.

So I worked around it.

1. **Getting and decoding the snippet** : Armed with a username and an [app password](https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/), I used Python's **requests** library to retrieve the snippet from the local server. The entire contents of the snippet was wrapped up in one JSON object. (**EDIT:**my original editing was too vigorous. The local server doesn't need an app password But the next step does.)

```

def get_snippet_from_cloud(snippet_name, user, app_passwd):
    url = 'https://api.bitbucket.org/2.0/snippets/{0}/{1}'.format(workspace, snippetName)
    r = requests.get(url, auth=(user, passwd), headers={ "Accept": "application/json" })
    return r.json()

```

Parsing the JSON object to retrieve the contents was a simple matter.

2. **Encoding and writing the snippet** : I used the **os.system** call to execute **cURL** from the command line. By using the **-F**option, I created a multipart POST request without having to assemble the multipart message first.

```
def write_snippet_to_cloud(source_path, workspace, user, app_passwd):
    url = 'https://api.bitbucket.org/2.0/snippets/{0}'.format(workspace)
    auth = "{0}:{1}".format(user, app_passwd)
    header = "'Content-Type: application/json'"
    title = get_title(source_path) # get_title() returns a string
    files = get_files(source_path) # get_files() returns a list of filenames
    curl_cmd = "curl -u {0} --request POST {1} -F title=\"{2}\"".format(auth, url, title)
    for f in files:
        curl_cmd = "{0} -F file=@{1}".format(curl_cmd, os.path.join(source_path, f))
    response = os.system(curl_cmd)
    if response == 0:
         print("\n\nSnippet '{0}' successfully created".format(title))
```

The code can be cleaned up considerably, but it does the job.

**EDITED TO ADD:** This was all done in Linux. It can be done in Windows as well -- but since **curl** is an alias for PowerShell's **Invoke-WebRequest** , the **curl_cmd** strings will need to be rewritten to conform to the **Invoke-WebRequest** syntax.


Tags: bitbucket-cloud

cloud

rest-api

snippet