Repository: sympy/sympy

Issue:
TypeError: Argument of Integer should be of numeric type, got -oo.
The present expression generates the previous error.

```python
sp.degree(sp.sympify('_R*_X34*(_X35**2*_X26 - _X26*_X35*(_X35 + 1) + 2*_X26*_X35 - _X26*(_X35 + 1) + _X26 - _X29*_X32*_X35 + _X29*_X32*(_X35 + 1) - _X29*_X32)'), sp.Symbol('_R'))
```

The return statement does not take into account the `p.degree(gen)` returns and -oo.

Discussion:

Patch:
diff --git a/sympy/integrals/singularityfunctions.py b/sympy/integrals/singularityfunctions.py
index c941f8b34a..64492deea3 100644
--- a/sympy/integrals/singularityfunctions.py
+++ b/sympy/integrals/singularityfunctions.py
@@ -9,9 +9,6 @@ def singularityintegrate(f, x):
     The ``integrate`` function calls this function internally whenever an
     instance of SingularityFunction is passed as argument.
 
-    Explanation
-    ===========
-
     The idea for integration is the following:
 
     - If we are dealing with a SingularityFunction expression,
@@ -28,7 +25,6 @@ def singularityintegrate(f, x):
 
     Examples
     ========
-
     >>> from sympy.integrals.singularityfunctions import singularityintegrate
     >>> from sympy import SingularityFunction, symbols, Function
     >>> x, a, n, y = symbols('x a n y')
diff --git a/sympy/integrals/transforms.py b/sympy/integrals/transforms.py
index f8b0eab79d..13bc9a9bc9 100644
--- a/sympy/integrals/transforms.py
+++ b/sympy/integrals/transforms.py
@@ -23,9 +23,6 @@ class IntegralTransformError(NotImplementedError):
     """
     Exception raised in relation to problems computing transforms.
 
-    Explanation
-    ===========
-
     This class is mostly used internally; if integrals cannot be computed
     objects representing unevaluated transforms are usually returned.
 
@@ -43,9 +40,6 @@ class IntegralTransform(Function):
     """
     Base class for integral transforms.
 
-    Explanation
-    ===========
-
     This class represents unevaluated transforms.
 
     To implement a concrete transform, derive from this class and implement
@@ -102,9 +96,6 @@ def doit(self, **hints):
         """
         Try to evaluate the transform in closed form.
 
-        Explanation
-        ===========
-
         This general function handles linearity, but apart from that leaves
         pretty much everything to _compute_transform.
 
@@ -195,9 +186,6 @@ def _noconds_(default):
     """
     This is a decorator generator for dropping convergence conditions.
 
-    Explanation
-    ===========
-
     Suppose you define a function ``transform(*args)`` which returns a tuple of
     the form ``(result, cond1, cond2, ...)``.
 
@@ -343,9 +331,6 @@ def mellin_transform(f, x, s, **hints):
     For all "sensible" functions, this converges absolutely in a strip
       `a < \operatorname{Re}(s) < b`.
 
-    Explanation
-    ===========
-
     The Mellin transform is related via change of variables to the Fourier
     transform, and also to the (bilateral) Laplace transform.
 
@@ -361,9 +346,6 @@ def mellin_transform(f, x, s, **hints):
     then only `F` will be returned (i.e. not ``cond``, and also not the strip
     ``(a, b)``).
 
-    Examples
-    ========
-
     >>> from sympy.integrals.transforms import mellin_transform
     >>> from sympy import exp
     >>> from sympy.abc import x, s
@@ -386,9 +368,6 @@ def _rewrite_sin(m_n, s, a, b):
 
     Return ``(gamma1, gamma2, fac)`` so that ``f == fac/(gamma1 * gamma2)``.
 
-    Examples
-    ========
-
     >>> from sympy.integrals.transforms import _rewrite_sin
     >>> from sympy import pi, S
     >>> from sympy.abc import s
@@ -438,9 +417,6 @@ def _rewrite_gamma(f, s, a, b):
     so that the inverse Mellin transform of f can be expressed as a meijer
     G function.
 
-    Explanation
-    ===========
-
     Return (an, ap), (bm, bq), arg, exp, fac such that
     G((an, ap), (bm, bq), arg/z**exp)*fac is the inverse Mellin transform of f(s).
 
@@ -456,9 +432,6 @@ def _rewrite_gamma(f, s, a, b):
     This is a helper function for inverse_mellin_transform that will not
     attempt any transformations on f.
 
-    Examples
-    ========
-
     >>> from sympy.integrals.transforms import _rewrite_gamma
     >>> from sympy.abc import s
     >>> from sympy import oo
@@ -855,9 +828,6 @@ def inverse_mellin_transform(F, s, x, strip, **hints):
     Compute the inverse Mellin transform of `F(s)` over the fundamental
     strip given by ``strip=(a, b)``.
 
-    Explanation
-    ===========
-
     This can be defined as
 
     .. math:: f(x) = \frac{1}{2\pi i} \int_{c - i\infty}^{c + i\infty} x^{-s} F(s) \mathrm{d}s,
@@ -879,9 +849,6 @@ def inverse_mellin_transform(F, s, x, strip, **hints):
     For a description of possible hints, refer to the docstring of
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
 
-    Examples
-    ========
-
     >>> from sympy.integrals.transforms import inverse_mellin_transform
     >>> from sympy import oo, gamma
     >>> from sympy.abc import x, s
@@ -915,9 +882,6 @@ def _simplifyconds(expr, s, a):
     r"""
     Naively simplify some conditions occurring in ``expr``, given that `\operatorname{Re}(s) > a`.
 
-    Examples
-    ========
-
     >>> from sympy.integrals.transforms import _simplifyconds as simp
     >>> from sympy.abc import x
     >>> from sympy import sympify as S
@@ -1149,9 +1113,6 @@ def laplace_transform(f, t, s, **hints):
 
     .. math :: F(s) = \int_0^\infty e^{-st} f(t) \mathrm{d}t.
 
-    Explanation
-    ===========
-
     For all "sensible" functions, this converges absolutely in a
     half plane  `a < \operatorname{Re}(s)`.
 
@@ -1166,9 +1127,6 @@ def laplace_transform(f, t, s, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`. If ``noconds=True``,
     only `F` will be returned (i.e. not ``cond``, and also not the plane ``a``).
 
-    Examples
-    ========
-
     >>> from sympy.integrals import laplace_transform
     >>> from sympy.abc import t, s, a
     >>> laplace_transform(t**a, t, s)
@@ -1300,9 +1258,6 @@ def inverse_laplace_transform(F, s, t, plane=None, **hints):
     for `c` so large that `F(s)` has no singularites in the
     half-plane `\operatorname{Re}(s) > c-\epsilon`.
 
-    Explanation
-    ===========
-
     The plane can be specified by
     argument ``plane``, but will be inferred if passed as None.
 
@@ -1319,9 +1274,6 @@ def inverse_laplace_transform(F, s, t, plane=None, **hints):
     For a description of possible hints, refer to the docstring of
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
 
-    Examples
-    ========
-
     >>> from sympy.integrals.transforms import inverse_laplace_transform
     >>> from sympy import exp, Symbol
     >>> from sympy.abc import s, t
@@ -1420,14 +1372,11 @@ def b(self):
 
 def fourier_transform(f, x, k, **hints):
     r"""
-    Compute the unitary, ordinary-frequency Fourier transform of ``f``, defined
+    Compute the unitary, ordinary-frequency Fourier transform of `f`, defined
     as
 
     .. math:: F(k) = \int_{-\infty}^\infty f(x) e^{-2\pi i x k} \mathrm{d} x.
 
-    Explanation
-    ===========
-
     If the transform cannot be computed in closed form, this
     function returns an unevaluated :class:`FourierTransform` object.
 
@@ -1438,9 +1387,6 @@ def fourier_transform(f, x, k, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
     Note that for this transform, by default ``noconds=True``.
 
-    Examples
-    ========
-
     >>> from sympy import fourier_transform, exp
     >>> from sympy.abc import x, k
     >>> fourier_transform(exp(-x**2), x, k)
@@ -1486,9 +1432,6 @@ def inverse_fourier_transform(F, k, x, **hints):
 
     .. math:: f(x) = \int_{-\infty}^\infty F(k) e^{2\pi i x k} \mathrm{d} k.
 
-    Explanation
-    ===========
-
     If the transform cannot be computed in closed form, this
     function returns an unevaluated :class:`InverseFourierTransform` object.
 
@@ -1499,9 +1442,6 @@ def inverse_fourier_transform(F, k, x, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
     Note that for this transform, by default ``noconds=True``.
 
-    Examples
-    ========
-
     >>> from sympy import inverse_fourier_transform, exp, sqrt, pi
     >>> from sympy.abc import x, k
     >>> inverse_fourier_transform(sqrt(pi)*exp(-(pi*k)**2), k, x)
@@ -1608,9 +1548,6 @@ def sine_transform(f, x, k, **hints):
 
     .. math:: F(k) = \sqrt{\frac{2}{\pi}} \int_{0}^\infty f(x) \sin(2\pi x k) \mathrm{d} x.
 
-    Explanation
-    ===========
-
     If the transform cannot be computed in closed form, this
     function returns an unevaluated :class:`SineTransform` object.
 
@@ -1618,9 +1555,6 @@ def sine_transform(f, x, k, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
     Note that for this transform, by default ``noconds=True``.
 
-    Examples
-    ========
-
     >>> from sympy import sine_transform, exp
     >>> from sympy.abc import x, k, a
     >>> sine_transform(x*exp(-a*x**2), x, k)
@@ -1667,9 +1601,6 @@ def inverse_sine_transform(F, k, x, **hints):
 
     .. math:: f(x) = \sqrt{\frac{2}{\pi}} \int_{0}^\infty F(k) \sin(2\pi x k) \mathrm{d} k.
 
-    Explanation
-    ===========
-
     If the transform cannot be computed in closed form, this
     function returns an unevaluated :class:`InverseSineTransform` object.
 
@@ -1677,9 +1608,6 @@ def inverse_sine_transform(F, k, x, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
     Note that for this transform, by default ``noconds=True``.
 
-    Examples
-    ========
-
     >>> from sympy import inverse_sine_transform, exp, sqrt, gamma
     >>> from sympy.abc import x, k, a
     >>> inverse_sine_transform(2**((1-2*a)/2)*k**(a - 1)*
@@ -1727,9 +1655,6 @@ def cosine_transform(f, x, k, **hints):
 
     .. math:: F(k) = \sqrt{\frac{2}{\pi}} \int_{0}^\infty f(x) \cos(2\pi x k) \mathrm{d} x.
 
-    Explanation
-    ===========
-
     If the transform cannot be computed in closed form, this
     function returns an unevaluated :class:`CosineTransform` object.
 
@@ -1737,9 +1662,6 @@ def cosine_transform(f, x, k, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
     Note that for this transform, by default ``noconds=True``.
 
-    Examples
-    ========
-
     >>> from sympy import cosine_transform, exp, sqrt, cos
     >>> from sympy.abc import x, k, a
     >>> cosine_transform(exp(-a*x), x, k)
@@ -1786,9 +1708,6 @@ def inverse_cosine_transform(F, k, x, **hints):
 
     .. math:: f(x) = \sqrt{\frac{2}{\pi}} \int_{0}^\infty F(k) \cos(2\pi x k) \mathrm{d} k.
 
-    Explanation
-    ===========
-
     If the transform cannot be computed in closed form, this
     function returns an unevaluated :class:`InverseCosineTransform` object.
 
@@ -1796,9 +1715,6 @@ def inverse_cosine_transform(F, k, x, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
     Note that for this transform, by default ``noconds=True``.
 
-    Examples
-    ========
-
     >>> from sympy import inverse_cosine_transform, sqrt, pi
     >>> from sympy.abc import x, k, a
     >>> inverse_cosine_transform(sqrt(2)*a/(sqrt(pi)*(a**2 + k**2)), k, x)
@@ -1891,9 +1807,6 @@ def hankel_transform(f, r, k, nu, **hints):
 
     .. math:: F_\nu(k) = \int_{0}^\infty f(r) J_\nu(k r) r \mathrm{d} r.
 
-    Explanation
-    ===========
-
     If the transform cannot be computed in closed form, this
     function returns an unevaluated :class:`HankelTransform` object.
 
@@ -1901,9 +1814,6 @@ def hankel_transform(f, r, k, nu, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
     Note that for this transform, by default ``noconds=True``.
 
-    Examples
-    ========
-
     >>> from sympy import hankel_transform, inverse_hankel_transform
     >>> from sympy import exp
     >>> from sympy.abc import r, k, m, nu, a
@@ -1953,9 +1863,6 @@ def inverse_hankel_transform(F, k, r, nu, **hints):
 
     .. math:: f(r) = \int_{0}^\infty F_\nu(k) J_\nu(k r) k \mathrm{d} k.
 
-    Explanation
-    ===========
-
     If the transform cannot be computed in closed form, this
     function returns an unevaluated :class:`InverseHankelTransform` object.
 
@@ -1963,9 +1870,6 @@ def inverse_hankel_transform(F, k, r, nu, **hints):
     :func:`sympy.integrals.transforms.IntegralTransform.doit`.
     Note that for this transform, by default ``noconds=True``.
 
-    Examples
-    ========
-
     >>> from sympy import hankel_transform, inverse_hankel_transform
     >>> from sympy import exp
     >>> from sympy.abc import r, k, m, nu, a
diff --git a/sympy/integrals/trigonometry.py b/sympy/integrals/trigonometry.py
index 15723871a3..009a7c4280 100644
--- a/sympy/integrals/trigonometry.py
+++ b/sympy/integrals/trigonometry.py
@@ -26,32 +26,25 @@ def _pat_sincos(x):
 
 
 def trigintegrate(f, x, conds='piecewise'):
-    """
-    Integrate f = Mul(trig) over x.
-
-    Examples
-    ========
-
-    >>> from sympy import sin, cos, tan, sec
-    >>> from sympy.integrals.trigonometry import trigintegrate
-    >>> from sympy.abc import x
+    """Integrate f = Mul(trig) over x
 
-    >>> trigintegrate(sin(x)*cos(x), x)
-    sin(x)**2/2
+       >>> from sympy import sin, cos, tan, sec
+       >>> from sympy.integrals.trigonometry import trigintegrate
+       >>> from sympy.abc import x
 
-    >>> trigintegrate(sin(x)**2, x)
-    x/2 - sin(x)*cos(x)/2
+       >>> trigintegrate(sin(x)*cos(x), x)
+       sin(x)**2/2
 
-    >>> trigintegrate(tan(x)*sec(x), x)
-    1/cos(x)
+       >>> trigintegrate(sin(x)**2, x)
+       x/2 - sin(x)*cos(x)/2
 
-    >>> trigintegrate(sin(x)*tan(x), x)
-    -log(sin(x) - 1)/2 + log(sin(x) + 1)/2 - sin(x)
+       >>> trigintegrate(tan(x)*sec(x), x)
+       1/cos(x)
 
-    References
-    ==========
+       >>> trigintegrate(sin(x)*tan(x), x)
+       -log(sin(x) - 1)/2 + log(sin(x) + 1)/2 - sin(x)
 
-    .. [1] http://en.wikibooks.org/wiki/Calculus/Integration_techniques
+       http://en.wikibooks.org/wiki/Calculus/Integration_techniques
 
     See Also
     ========
diff --git a/sympy/polys/polytools.py b/sympy/polys/polytools.py
index 70112de3b6..18655988a8 100644
--- a/sympy/polys/polytools.py
+++ b/sympy/polys/polytools.py
@@ -4480,8 +4480,8 @@ def degree(f, gen=0):
          expression like func = %s, e.g. degree(func, gen = %s) instead of
          degree(func, gen = %s).
         ''' % (f, next(ordered(f.free_symbols)), gen)))
-
-    return Integer(p.degree(gen))
+    result = p.degree(gen)
+    return Integer(result) if isinstance(result, int) else S.NegativeInfinity
 
 
 @public


Test patch:
diff --git a/sympy/polys/tests/test_polytools.py b/sympy/polys/tests/test_polytools.py
index c774fc41e2..48916f4afb 100644
--- a/sympy/polys/tests/test_polytools.py
+++ b/sympy/polys/tests/test_polytools.py
@@ -3441,3 +3441,8 @@ def test_deserialized_poly_equals_original():
         "Deserialized polynomial not equal to original.")
     assert poly.gens == deserialized.gens, (
         "Deserialized polynomial has different generators than original.")
+
+
+def test_issue_20389():
+    result = degree(x * (x + 1) - x ** 2 - x, x)
+    assert result == -oo