urlencode a multidimensional dictionary in python

Based on the code of @malaney, I think that the code below emulates the PHP function http_build_query() quite well.

#!/usr/bin/env python3

import urllib.parse

def http_build_query(data):
    parents = list()
    pairs = dict()

    def renderKey(parents):
        depth, outStr = 0, ''
        for x in parents:
            s = "[%s]" if depth > 0 or isinstance(x, int) else "%s"
            outStr += s % str(x)
            depth += 1
        return outStr

    def r_urlencode(data):
        if isinstance(data, list) or isinstance(data, tuple):
            for i in range(len(data)):
                parents.append(i)
                r_urlencode(data[i])
                parents.pop()
        elif isinstance(data, dict):
            for key, value in data.items():
                parents.append(key)
                r_urlencode(value)
                parents.pop()
        else:
            pairs[renderKey(parents)] = str(data)

        return pairs
    return urllib.parse.urlencode(r_urlencode(data))

if __name__ == '__main__':
    payload = {
        'action': 'add',
        'controller': 'invoice',
        'code': 'debtor',
        'InvoiceLines': [
            {'PriceExcl': 150, 'Description': 'Setupfee'},
            {'PriceExcl':49.99, 'Description':'Subscription'}
        ],
        'date': '2016-08-01',
        'key': 'Yikes&ampersand'
    }
    print(http_build_query(payload))

    payload2 = [
        'item1',
        'item2'
    ]
    print(http_build_query(payload2))

Something like this?

a = {'a': 'b', 'c': {'d': 'e'}}

url = urllib.urlencode([('%s[%s]'%(k,v.keys()[0]), v.values()[0] ) if type(v)==dict else (k,v) for k,v in a.iteritems()])

url = 'a=b&c%5Bd%5D=e'

OK people. I implemented it myself:

import urllib

def recursive_urlencode(d):
    """URL-encode a multidimensional dictionary.

    >>> data = {'a': 'b&c', 'd': {'e': {'f&g': 'h*i'}}, 'j': 'k'}
    >>> recursive_urlencode(data)
    u'a=b%26c&j=k&d[e][f%26g]=h%2Ai'
    """
    def recursion(d, base=[]):
        pairs = []

        for key, value in d.items():
            new_base = base + [key]
            if hasattr(value, 'values'):
                pairs += recursion(value, new_base)
            else:
                new_pair = None
                if len(new_base) > 1:
                    first = urllib.quote(new_base.pop(0))
                    rest = map(lambda x: urllib.quote(x), new_base)
                    new_pair = "%s[%s]=%s" % (first, ']['.join(rest), urllib.quote(unicode(value)))
                else:
                    new_pair = "%s=%s" % (urllib.quote(unicode(key)), urllib.quote(unicode(value)))
                pairs.append(new_pair)
        return pairs

    return '&'.join(recursion(d))

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Still, I'd be interested to know if there's a better way to do this. I can't believe Python's standard library doesn't implement this.