1"""Tools for applying functions to specified parts of expressions."""
2
3from ..core import sympify
4
5
6def use(expr, func, level=0, args=(), kwargs={}):
7    """
8    Use ``func`` to transform ``expr`` at the given level.
9
10    Examples
11    ========
12
13    >>> f = (x + y)**2*x + 1
14
15    >>> use(f, expand, level=2)
16    x*(x**2 + 2*x*y + y**2) + 1
17    >>> expand(f)
18    x**3 + 2*x**2*y + x*y**2 + 1
19
20    """
21    def _use(expr, level):
22        if not level:
23            return func(expr, *args, **kwargs)
24        else:
25            if expr.is_Atom:
26                return expr
27            else:
28                level -= 1
29                _args = []
30
31                for arg in expr.args:
32                    _args.append(_use(arg, level))
33
34                return expr.__class__(*_args)
35
36    return _use(sympify(expr), level)
37