Removing C++ template arguments from a C++ function name I'm working on some code that deals with mangled C++ function names. I'm displaying these to the user, so to help with readability of some of the really long C++ template class/function names, I'm removing some of the template arguments based on how deeply nested the template argument is.

The code below works fine, but it seems fairly clunky. It feels like I'm "writing C in any language". I'm wondering if I can improve it, shorten it, and make it more pythonic.

def removeTemplateArguments(str, depthToRemove):
    """ Remove template arguments deeper than depthToRemove
        so removeTemplateArguments("foo&lt;int&gt;()", 1) gives foo&lt;&gt;()
           removeTemplateArguments("foo&lt; bar&lt;int&gt; &gt;()", 1) gives foo&lt; &gt;()
           removeTemplateArguments("foo&lt; bar&lt;int&gt; &gt;()", 2) gives foo&lt; bar&lt;&gt; &gt;()"""
    if depthToRemove &lt;= 0:
        return str
    currDepth = 0
    res = ""
    for c in str:
        if currDepth &lt; depthToRemove:
            res += c
        if c == "&lt;":
            currDepth += 1
        elif c == "&gt;":
            currDepth -= 1
            if currDepth &lt; depthToRemove:
                res += "&gt;"
    return res
For that kind of parsing itertools.groupby is the right tool.
With groupby, as I used it down below, every group is either: &lt;,&gt; or an actual piece of code (like foo). So the only thing left to do is to increment/decrement the depth level and decide if the group should be appended or not to the final result list.
from itertools import groupby

def remove_arguments(template, depth):
    res = []
    curr_depth = 0
    for k,g in groupby(template, lambda x: x in ['&lt;', '&gt;']):
        text = ''.join(g)    # rebuild the group as a string
        if text == '&lt;':
            curr_depth += 1

        # it's important to put this part in the middle
        if curr_depth &lt; depth:
            res.append(text)
        elif k and curr_depth == depth:   # add the inner &lt;&gt;
            res.append(text)

        if text == '&gt;':
            curr_depth -= 1

    return ''.join(res)   # rebuild the complete string

It's important to put the depth-level check in between the increment and decrement part, because it has to be decided if the &lt;/&gt; are in or out the current depth level.
Output examples:
&gt;&gt;&gt; remove_arguments('foo&lt;int&gt;()', 1)
foo&lt;&gt;()
&gt;&gt;&gt; remove_arguments('foo&lt; bar&lt;int&gt; &gt;()', 1)
foo&lt;&gt;()
&gt;&gt;&gt; remove_arguments('foo&lt; bar&lt;int&gt; &gt;()', 2)
foo&lt; bar&lt;&gt; &gt;()
&gt;&gt;&gt; remove_arguments('foo&lt; bar &gt;()', 2)
foo&lt; bar &gt;()

Also, a couple of quick style notes:

Don't use str as variable name or you'll shadow the builitin str.
Don't use CamelCase for functions/variable names (look at PEP8).


Inspired by lvc comment, I've grouped here possible lambdas/functions to be used in groupby:
groupby(template, lambda x: x in ['&lt;', '&gt;'])    # most obvious one
groupby(template, lambda x: x in '&lt;&gt;')   # equivalent to the one above
groupby(template, '&lt;&gt;'.__contains__)    # this is ugly ugly
groupby(template, '&lt;&gt;'.count)    # not obvious, but looks sweet


Update
To handle cases like: foo&lt;bar&lt;int&gt;&gt;(), you'll need a better groupby key function. To be specific, a key function that return the current depth-level for a given charachter.
Like this one:
def get_level(ch, level=[0]):
    current = level[0]
    if ch == '&lt;':
        level[0] += 1
    if ch == '&gt;':
        level[0] -= 1
        current = level[0]

    return current

That take advantage of the mutable argument level to perform some kind of memoization.
Observe that remove_arguments will now be more simple:
def remove_arguments(template, depth):
    res = []
    for k,g in groupby(template, get_level):
        if k &lt; depth:
            res.append(''.join(g))
    return ''.join(res)