Repository: sympy/sympy

Issue:
coverage_report.py should be able to run slow tests also
Currently Coverage report doesn't runs slow tests, so the coverage report generated is not accurate.
It should run slow tests by a flag.

```
bin/coverage_report.py 
```

**EDIT**
It  should accept a --slow flag just like bin/test.

Discussion:
moorepants: +1
aktech: I am getting the following warning:

```python
Coverage.py warning: No data was collected.
```
```
The generated coverage report is in covhtml directory.
Open sympy/covhtml/index.html in your web browser to view the report
```

leosartaj: @aktech I have made small changes. Can you have a look again? It's working for me.
aktech: @leosartaj 
It looks good to me. Can you add a line  for the usage in the doc-string at the top of the file.
leosartaj: Sure.
On 4 Sep 2015 09:33, "AMiT Kumar" <notifications@github.com> wrote:

> @leosartaj <https://github.com/leosartaj>
> It looks good to me. Can you add a line for the usage in the doc-string at
> the top of the file.
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/sympy/sympy/pull/9884#issuecomment-137645664>.
>


Patch:
diff --git a/bin/coverage_report.py b/bin/coverage_report.py
index 6d27376f6d..26e570c77b 100755
--- a/bin/coverage_report.py
+++ b/bin/coverage_report.py
@@ -14,9 +14,9 @@
 $ bin/coverage_report.py sympy/logic
 
 runs only the tests in sympy/logic/ and reports only on the modules in
-sympy/logic/. You can also get a report on the parts of the whole sympy
-code covered by the tests in sympy/logic/ by following up the previous
-command with
+sympy/logic/. To also run slow tests use --slow option. You can also get a
+report on the parts of the whole sympy code covered by the tests in
+sympy/logic/ by following up the previous command with
 
 
 $ bin/coverage_report.py -c
@@ -60,15 +60,16 @@ def generate_covered_files(top_dir):
                 yield os.path.join(dirpath, filename)
 
 
-def make_report(source_dir, report_dir, use_cache=False):
-    #code adapted from /bin/test
-    bin_dir = os.path.abspath(os.path.dirname(__file__))         # bin/
-    sympy_top = os.path.split(bin_dir)[0]      # ../
+def make_report(source_dir, report_dir, use_cache=False, slow=False):
+    # code adapted from /bin/test
+    bin_dir = os.path.abspath(os.path.dirname(__file__))  # bin/
+    sympy_top = os.path.split(bin_dir)[0]  # ../
     sympy_dir = os.path.join(sympy_top, 'sympy')  # ../sympy/
     if os.path.isdir(sympy_dir):
         sys.path.insert(0, sympy_top)
     os.chdir(sympy_top)
 
+    import sympy
     cov = coverage.coverage()
     cov.exclude("raise NotImplementedError")
     cov.exclude("def canonize")  # this should be "@decorated"
@@ -78,8 +79,9 @@ def make_report(source_dir, report_dir, use_cache=False):
     else:
         cov.erase()
         cov.start()
-        import sympy
         sympy.test(source_dir, subprocess=False)
+        if slow:
+            sympy.test(source_dir, subprocess=False, slow=slow)
         #sympy.doctest()  # coverage doesn't play well with doctests
         cov.stop()
         cov.save()
@@ -99,6 +101,8 @@ def make_report(source_dir, report_dir, use_cache=False):
                       help='Use cached data.')
     parser.add_option('-d', '--report-dir', default='covhtml',
                       help='Directory to put the generated report in.')
+    parser.add_option("--slow", action="store_true", dest="slow",
+                      default=False, help="Run slow functions also.")
 
     options, args = parser.parse_args()
 
diff --git a/sympy/series/formal.py b/sympy/series/formal.py
index b7c2ded401..1a21b2aafd 100644
--- a/sympy/series/formal.py
+++ b/sympy/series/formal.py
@@ -14,7 +14,6 @@
 from sympy.core.symbol import Wild, Dummy, symbols, Symbol
 from sympy.core.relational import Eq
 from sympy.core.numbers import Rational
-from sympy.core.compatibility import iterable
 from sympy.sets.sets import Interval
 from sympy.functions.combinatorial.factorials import binomial, factorial, rf
 from sympy.functions.elementary.piecewise import Piecewise
@@ -749,7 +748,7 @@ def hyper_algorithm(f, x, k, order=4):
             return sol
 
 
-def _compute_fps(f, x, x0, dir, hyper, order, rational, full):
+def _compute_fps(f, x, x0, dir, hyper, order, rational, full, extract=True):
     """Recursive wrapper to compute fps.
 
     See :func:`compute_fps` for details.
@@ -760,7 +759,8 @@ def _compute_fps(f, x, x0, dir, hyper, order, rational, full):
         result = _compute_fps(temp, x, 0, dir, hyper, order, rational, full)
         if result is None:
             return None
-        return (result[0], result[1].subs(x, 1/x), result[2].subs(x, 1/x))
+        return (result[0], result[1].subs(x, 1/x), result[2].subs(x, 1/x),
+                result[3].subs(x, 1/x))
     elif x0 or dir == -S.One:
         if dir == -S.One:
             rep = -x + x0
@@ -775,11 +775,28 @@ def _compute_fps(f, x, x0, dir, hyper, order, rational, full):
         if result is None:
             return None
         return (result[0], result[1].subs(x, rep2 + rep2b),
-                result[2].subs(x, rep2 + rep2b))
+                result[2].subs(x, rep2 + rep2b),
+                result[3].subs(x, rep2 + rep2b))
 
     if f.is_polynomial(x):
         return None
 
+    #  extract x**n from f(x)
+    mul = S.One
+    if extract and f.free_symbols.difference(set([x])):
+        m = Wild('m')
+        n = Wild('n', exclude=[m])
+        f = f.factor().powsimp()
+        s = f.match(x**n*m)
+        if s[n]:
+            for t in Add.make_args(s[n]):
+                if t.has(Symbol):
+                    mul *= (x)**t
+        if mul is not S.One:
+            f = (f / mul)
+
+    f = f.expand()
+
     #  Break instances of Add
     #  this allows application of different
     #  algorithms on different terms increasing the
@@ -789,7 +806,8 @@ def _compute_fps(f, x, x0, dir, hyper, order, rational, full):
         ak = sequence(S.Zero, (0, oo))
         ind, xk = S.Zero, None
         for t in Add.make_args(f):
-            res = _compute_fps(t, x, 0, S.One, hyper, order, rational, full)
+            res = _compute_fps(t, x, 0, S.One, hyper, order, rational, full,
+                               False)
             if res:
                 if not result:
                     result = True
@@ -806,7 +824,7 @@ def _compute_fps(f, x, x0, dir, hyper, order, rational, full):
             else:
                 ind += t
         if result:
-            return ak, xk, ind
+            return ak, xk, ind, mul
         return None
 
     result = None
@@ -826,7 +844,7 @@ def _compute_fps(f, x, x0, dir, hyper, order, rational, full):
     xk = sequence(x**k, (k, 0, oo))
     ind = result[1]
 
-    return ak, xk, ind
+    return ak, xk, ind, mul
 
 
 def compute_fps(f, x, x0=0, dir=1, hyper=True, order=4, rational=True,
@@ -929,10 +947,6 @@ def x(self):
     def x0(self):
         return self.args[2]
 
-    @property
-    def dir(self):
-        return self.args[3]
-
     @property
     def ak(self):
         return self.args[4][0]
@@ -945,6 +959,10 @@ def xk(self):
     def ind(self):
         return self.args[4][2]
 
+    @property
+    def mul(self):
+        return self.args[4][3]
+
     @property
     def interval(self):
         return Interval(0, oo)
@@ -967,9 +985,11 @@ def infinite(self):
         from sympy.concrete import Sum
         ak, xk = self.ak, self.xk
         k = ak.variables[0]
-        inf_sum = Sum(ak.formula * xk.formula, (k, ak.start, ak.stop))
+        ind = (self.ind * self.mul).expand()
+        inf_sum = Sum(ak.formula * xk.formula * self.mul,
+                      (k, ak.start, ak.stop))
 
-        return self.ind + inf_sum
+        return ind + inf_sum
 
     def _get_pow_x(self, term):
         """Returns the power of x in a term."""
@@ -992,7 +1012,7 @@ def polynomial(self, n=6):
             elif xp.is_integer is True and i == n + 1:
                 break
             elif t is not S.Zero:
-                terms.append(t)
+                terms.append(t * self.mul)
 
         return Add(*terms)
 
@@ -1012,16 +1032,17 @@ def truncate(self, n=6):
         if x0 is S.NegativeInfinity:
             x0 = S.Infinity
 
-        return self.polynomial(n) + Order(pt_xk, (x, x0))
+        return self.polynomial(n) + self.mul * Order(pt_xk, (x, x0))
 
     def _eval_term(self, pt):
+        pt_xk = self.xk.coeff(pt)
+
         try:
-            pt_xk = self.xk.coeff(pt)
             pt_ak = self.ak.coeff(pt).simplify()  # Simplify the coefficients
         except IndexError:
-            term = S.Zero
-        else:
-            term = (pt_ak * pt_xk)
+            pt_ak = S.Zero
+
+        term = (pt_ak * pt_xk)
 
         if self.ind:
             ind = S.Zero
@@ -1045,139 +1066,6 @@ def _eval_as_leading_term(self, x):
             if t is not S.Zero:
                 return t
 
-    def _eval_derivative(self, x):
-        f = self.function.diff(x)
-        ind = self.ind.diff(x)
-
-        pow_xk = self._get_pow_x(self.xk.formula)
-        ak = self.ak
-        k = ak.variables[0]
-        if ak.formula.has(x):
-            form = []
-            for e, c in ak.formula.args:
-                temp = S.Zero
-                for t in Add.make_args(e):
-                    pow_x = self._get_pow_x(t)
-                    temp += t * (pow_xk + pow_x)
-                form.append((temp, c))
-            form = Piecewise(*form)
-            ak = sequence(form.subs(k, k + 1), (k, ak.start - 1, ak.stop))
-        else:
-            ak = sequence((ak.formula * pow_xk).subs(k, k + 1),
-                          (k, ak.start - 1, ak.stop))
-
-        return self.func(f, self.x, self.x0, self.dir, (ak, self.xk, ind))
-
-    def integrate(self, x=None):
-        """Integrate Formal Power Series.
-
-        Examples
-        ========
-
-        >>> from sympy import fps, sin
-        >>> from sympy.abc import x
-        >>> f = fps(sin(x))
-        >>> f.integrate(x).truncate()
-        -1 + x**2/2 - x**4/24 + O(x**6)
-        >>> f.integrate((x, 0, 1))
-        -cos(1) + 1
-        """
-        from sympy.integrals import integrate
-
-        if x is None:
-            x = self.x
-        elif iterable(x):
-            return integrate(self.function, x)
-
-        f = integrate(self.function, x)
-        ind = integrate(self.ind, x)
-        ind += (f - ind).limit(x, 0)  # constant of integration
-
-        pow_xk = self._get_pow_x(self.xk.formula)
-        ak = self.ak
-        k = ak.variables[0]
-        if ak.formula.has(x):
-            form = []
-            for e, c in ak.formula.args:
-                temp = S.Zero
-                for t in Add.make_args(e):
-                    pow_x = self._get_pow_x(t)
-                    temp += t / (pow_xk + pow_x + 1)
-                form.append((temp, c))
-            form = Piecewise(*form)
-            ak = sequence(form.subs(k, k - 1), (k, ak.start + 1, ak.stop))
-        else:
-            ak = sequence((ak.formula / (pow_xk + 1)).subs(k, k - 1),
-                          (k, ak.start + 1, ak.stop))
-
-        return self.func(f, self.x, self.x0, self.dir, (ak, self.xk, ind))
-
-    def __add__(self, other):
-        other = sympify(other)
-
-        if isinstance(other, FormalPowerSeries):
-            if self.dir != other.dir:
-                raise ValueError("Both series should be calculated from the"
-                                 " same direction.")
-            elif self.x0 != other.x0:
-                raise ValueError("Both series should be calculated about the"
-                                 " same point.")
-
-            x, y = self.x, other.x
-            f = self.function + other.function.subs(y, x)
-
-            if self.x not in f.free_symbols:
-                return f
-
-            ak = self.ak + other.ak
-            if self.ak.start > other.ak.start:
-                seq = other.ak
-                s, e = other.ak.start, self.ak.start
-            else:
-                seq = self.ak
-                s, e = self.ak.start, other.ak.start
-            save = Add(*[z[0]*z[1] for z in zip(seq[0:(e - s)], self.xk[s:e])])
-            ind = self.ind + other.ind + save
-
-            return self.func(f, x, self.x0, self.dir, (ak, self.xk, ind))
-
-        elif not other.has(self.x):
-            f = self.function + other
-            ind = self.ind + other
-
-            return self.func(f, self.x, self.x0, self.dir,
-                             (self.ak, self.xk, ind))
-
-        return Add(self, other)
-
-    def __radd__(self, other):
-        return self.__add__(other)
-
-    def __neg__(self):
-        return self.func(-self.function, self.x, self.x0, self.dir,
-                         (-self.ak, self.xk, -self.ind))
-
-    def __sub__(self, other):
-        return self.__add__(-other)
-
-    def __rsub__(self, other):
-        return (-self).__add__(other)
-
-    def __mul__(self, other):
-        other = sympify(other)
-
-        if other.has(self.x):
-            return Mul(self, other)
-
-        f = self.function * other
-        ak = self.ak.coeff_mul(other)
-        ind = self.ind * other
-
-        return self.func(f, self.x, self.x0, self.dir, (ak, self.xk, ind))
-
-    def __rmul__(self, other):
-        return self.__mul__(other)
-
 
 def fps(f, x=None, x0=0, dir=1, hyper=True, order=4, rational=True, full=False):
     """Generates Formal Power Series of f.


Test patch:
diff --git a/sympy/series/tests/test_formal.py b/sympy/series/tests/test_formal.py
index b11de2cb5a..b0d2c21b83 100644
--- a/sympy/series/tests/test_formal.py
+++ b/sympy/series/tests/test_formal.py
@@ -1,6 +1,6 @@
 from sympy import (symbols, factorial, sqrt, Rational, atan, I, log, fps, O,
                    Sum, oo, S, pi, cos, sin, Function, exp, Derivative, asin,
-                   airyai, acos, acosh, gamma, erf, asech, Add, Integral, Mul)
+                   airyai, acos, acosh, gamma, erf, asech)
 from sympy.series.formal import (rational_algorithm, FormalPowerSeries,
                                  rational_independent, simpleDE, exp_re,
                                  hyper_re)
@@ -374,7 +374,6 @@ def test_fps__logarithmic_singularity_fail():
     assert fps(f, x) == log(2) - log(x) - x**2/4 - 3*x**4/64 + O(x**6)
 
 
-@XFAIL
 def test_fps__symbolic():
     f = x**n*sin(x**2)
     assert fps(f, x).truncate(8) == x**2*x**n - x**6*x**n/6 + O(x**(n + 8), x)
@@ -412,84 +411,3 @@ def test_fps__symbolic():
 def test_fps__slow():
     f = x*exp(x)*sin(2*x)  # TODO: rsolve needs improvement
     assert fps(f, x).truncate() == 2*x**2 + 2*x**3 - x**4/3 - x**5 + O(x**6)
-
-
-def test_fps__operations():
-    f1, f2 = fps(sin(x)), fps(cos(x))
-
-    fsum = f1 + f2
-    assert fsum.function == sin(x) + cos(x)
-    assert fsum.truncate() == \
-        1 + x - x**2/2 - x**3/6 + x**4/24 + x**5/120 + O(x**6)
-
-    fsum = f1 + 1
-    assert fsum.function == sin(x) + 1
-    assert fsum.truncate() == 1 + x - x**3/6 + x**5/120 + O(x**6)
-
-    fsum = 1 + f2
-    assert fsum.function == cos(x) + 1
-    assert fsum.truncate() == 2 - x**2/2 + x**4/24 + O(x**6)
-
-    assert (f1 + x) == Add(f1, x)
-
-    assert -f2.truncate() == -1 + x**2/2 - x**4/24 + O(x**6)
-    assert (f1 - f1) == S.Zero
-
-    fsub = f1 - f2
-    assert fsub.function == sin(x) - cos(x)
-    assert fsub.truncate() == \
-        -1 + x + x**2/2 - x**3/6 - x**4/24 + x**5/120 + O(x**6)
-
-    fsub = f1 - 1
-    assert fsub.function == sin(x) - 1
-    assert fsub.truncate() == -1 + x - x**3/6 + x**5/120 + O(x**6)
-
-    fsub = 1 - f2
-    assert fsub.function == -cos(x) + 1
-    assert fsub.truncate() == x**2/2 - x**4/24 + O(x**6)
-
-    raises(ValueError, lambda: f1 + fps(exp(x), dir=-1))
-    raises(ValueError, lambda: f1 + fps(exp(x), x0=1))
-
-    fm = f1 * 3
-
-    assert fm.function == 3*sin(x)
-    assert fm.truncate() == 3*x - x**3/2 + x**5/40 + O(x**6)
-
-    fm = 3 * f2
-
-    assert fm.function == 3*cos(x)
-    assert fm.truncate() == 3 - 3*x**2/2 + x**4/8 + O(x**6)
-
-    assert (f1 * f2) == Mul(f1, f2)
-    assert (f1 * x) == Mul(f1, x)
-
-    fd = f1.diff()
-    assert fd.function == cos(x)
-    assert fd.truncate() == 1 - x**2/2 + x**4/24 + O(x**6)
-
-    fd = f2.diff()
-    assert fd.function == -sin(x)
-    assert fd.truncate() == -x + x**3/6 - x**5/120 + O(x**6)
-
-    fd = f2.diff().diff()
-    assert fd.function == -cos(x)
-    assert fd.truncate() == -1 + x**2/2 - x**4/24 + O(x**6)
-
-    f3 = fps(exp(sqrt(x)))
-    fd = f3.diff()
-    assert fd.truncate().expand() == \
-        (1/(2*sqrt(x)) + S(1)/2 + x/12 + x**2/240 + x**3/10080 + x**4/725760 +
-         x**5/79833600 + sqrt(x)/4 + x**(S(3)/2)/48 + x**(S(5)/2)/1440 +
-         x**(S(7)/2)/80640 + x**(S(9)/2)/7257600 + x**(S(11)/2)/958003200 +
-         O(x**6))
-
-    assert f1.integrate((x, 0, 1)) == -cos(1) + 1
-
-    fi = f1.integrate(x)
-    assert fi.function == -cos(x)
-    assert fi.truncate() == -1 + x**2/2 - x**4/24 + O(x**6)
-
-    fi = f2.integrate()
-    assert fi.function == sin(x)
-    assert fi.truncate() == x - x**3/6 + x**5/120 + O(x**6)