Do a HTTP post to upload some data. If progress_cb is not None, it
    should be a callable which takes two arguments: the total number of bytes
    to upload and the number of bytes which have been uploaded. The callable is
    called periodically to show the progress of the upload.

def _dopost(url, params=None, payload=None, progress_cb=None):
    """Do a HTTP post to upload some data. If progress_cb is not None, it
    should be a callable which takes two arguments: the total number of bytes
    to upload and the number of bytes which have been uploaded. The callable is
    called periodically to show the progress of the upload.

    """
    if params:
        encoded = urlencode(params)
    else:
        encoded = ''

    url = str(url + encoded)

    if payload is None:
        payload = ''

    # Try to make use of PyCURL if we have it
    try:
        c = pycurl.Curl()
    except NameError:
        c = None

    if c is not None:
        response = [ ]
        def append_to_response(buf):
            response.append(buf.decode())

        def progress(download_t, download_d, upload_t, upload_d):
            if progress_cb is not None:
                progress_cb(upload_d, upload_t)

        c = pycurl.Curl()
        c.setopt(pycurl.URL, url)
        c.setopt(pycurl.POST, 1)
        c.setopt(pycurl.POSTFIELDS, payload)
        c.setopt(pycurl.INFILESIZE, len(payload))
        c.setopt(pycurl.WRITEFUNCTION, append_to_response)
        c.setopt(pycurl.NOPROGRESS, 0)
        c.setopt(pycurl.PROGRESSFUNCTION, progress)
        c.perform()
        c.close()

        return json.loads(''.join(response))
    else:
        if progress_cb is not None:
            progress_cb(0, len(payload))
        response = [x.decode() for x in urlopen(url, payload).readlines()]
        if progress_cb is not None:
            progress_cb(len(payload), len(payload))
        return json.loads(''.join(response))