Repository: sympy/sympy
File: sympy/polys/polytools.py (Python)

Code before:
    degree_list
    """

    _degree = lambda x: Integer(x) if type(x) is int else x

    f = sympify(f, strict=True)
    if type(gen) is int:
        if isinstance(f, Poly):
            return _degree(f.degree(gen))
        if f.is_Number:
            return S.NegativeInfinity if f.is_zero else S.Zero
        try:
            p = Poly(f, expand=False)
        except GeneratorsNeeded:
            p = Poly(f, Dummy())
        else:
            gens = p.gens
            free = f.free_symbols
            if not (gen == 0 and len(gens) == 1 and len(free) < 2 and f.is_polynomial(
                    gen := next(iter(gens))) and # <-- assigns gen
                    gen.is_Atom):  # e.g. x or pi
                raise TypeError(filldedent('''
                    To avoid ambiguity, this expression requires either
                    a symbol (not int) generator or a Poly (which identifies
                    the generators).'''))
        return p.degree(gen)

    gen = sympify(gen, strict=True)
    if not isinstance(f, Poly) or gen not in f.gens:
        f = poly_from_expr(f, gen)[0]
    return _degree(f.degree(gen))


@public
def total_degree(f, *gens):
    """
    Return the total_degree of ``f`` in the given variables.

    Examples
    ========
    >>> from sympy import total_degree, Poly
    >>> from sympy.abc import x, y

    >>> total_degree(1)
    0
    >>> total_degree(x + x*y)
    2
    >>> total_degree(x + x*y, x)
    1

    If the expression is a Poly and no variables are given

Review comment (bug):
Also, let's not guess. In this case if a generator is needed we don't know if the user intended I or not. So let's record the failure and use that as a condition for raising the TypeError later.

Code after:
    degree_list
    """

    _degree = lambda x: Integer(x) if type(x) is int else x

    f = sympify(f, strict=True)
    if type(gen) is int:
        if isinstance(f, Poly):
            return _degree(f.degree(gen))
        if f.is_Number:
            return S.NegativeInfinity if f.is_zero else S.Zero
        try:
            p = Poly(f, expand=False)
        except GeneratorsNeeded:  # e.g. f = (1+I)**2/2
            gens = ()  # do not guess what the user intended
        else:
            gens = p.gens
        free = f.free_symbols
        if not (gen == 0 and len(gens) == 1 and len(free) < 2 and f.is_polynomial(
                gen := next(iter(gens))) and # <-- assigns gen
                gen.is_Atom):  # e.g. x or pi
            raise TypeError(filldedent('''
                To avoid ambiguity, this expression requires either
                a symbol (not int) generator or a Poly (which identifies
                the generators).'''))
        return p.degree(gen)

    gen = sympify(gen, strict=True)
    if not isinstance(f, Poly) or gen not in f.gens:
        f = poly_from_expr(f, gen)[0]
    return _degree(f.degree(gen))


@public
def total_degree(f, *gens):
    """
    Return the total_degree of ``f`` in the given variables.

    Examples
    ========
    >>> from sympy import total_degree, Poly
    >>> from sympy.abc import x, y

    >>> total_degree(1)
    0
    >>> total_degree(x + x*y)
    2
    >>> total_degree(x + x*y, x)
    1

    If the expression is a Poly and no variables are given