Repository: sympy/sympy

Issue:
inconsistent diff on polynomials
From this stackoverflow question: http://stackoverflow.com/questions/31120436/why-does-sympy-diff-not-differentiate-sympy-polynomials-as-expected

``` python
In [1]: from sympy import *

In [2]: from sympy.abc import x

In [3]: p = Poly(x+1, x, domain='QQ')

In [4]: p.diff(x)
Out[4]: Poly(1, x, domain='QQ')

In [5]: diff(p, x)
Out[5]: Derivative(Poly(x + 1, x, domain='QQ'), x)

In [6]: diff(p, x).doit()
Out[6]: Derivative(Poly(x + 1, x, domain='ZZ'), x)
```

Seems like the toplevel `diff` is following a different code path compared to the `diff` method on Poly.


Discussion:
leosartaj: Polys interface of diff is different from that of sympy's. Therefore unevaluated Derivative creation can fail. eg.
```
>>> p = Poly(x**2 + x, x)
>>> diff(p, (x, 1))
Poly(3*x**2, x, domain='ZZ') # works
>>> diff(p, (x, 1), evaluate=False)
AttributeError
```

This is beacause ``Derivative`` doesn't recognize this interface.

By removing [L-2204](https://github.com/sympy/sympy/pull/9622/files#diff-c96d00473bda7f403c25a06fc5814515R2204) and [L-2205](https://github.com/sympy/sympy/pull/9622/files#diff-c96d00473bda7f403c25a06fc5814515R2205), ``diff`` will always try to evaluate and never return unevaluated ``Derivative``.

These are my thoughts. Suggestions?
leosartaj: Ping @jksuom @aktech 
aktech: This looks fine to me, except for the minor [comment](https://github.com/sympy/sympy/pull/9622#discussion_r33917493).

Patch:
diff --git a/sympy/polys/polytools.py b/sympy/polys/polytools.py
index 1a119855c1..60b1cae841 100644
--- a/sympy/polys/polytools.py
+++ b/sympy/polys/polytools.py
@@ -12,6 +12,7 @@
 from sympy.core.relational import Relational
 from sympy.core.sympify import sympify
 from sympy.core.decorators import _sympifyit
+from sympy.core.function import Derivative
 
 from sympy.logic.boolalg import BooleanAtom
 
@@ -2183,7 +2184,7 @@ def integrate(self, *specs, **args):
         else:  # pragma: no cover
             raise OperationNotSupported(f, 'integrate')
 
-    def diff(f, *specs):
+    def diff(f, *specs, **kwargs):
         """
         Computes partial derivative of ``f``.
 
@@ -2200,6 +2201,9 @@ def diff(f, *specs):
         Poly(2*x*y, x, y, domain='ZZ')
 
         """
+        if not kwargs.get('evaluate', True):
+            return Derivative(f, *specs, **kwargs)
+
         if hasattr(f.rep, 'diff'):
             if not specs:
                 return f.per(f.rep.diff(m=1))
@@ -2218,6 +2222,9 @@ def diff(f, *specs):
         else:  # pragma: no cover
             raise OperationNotSupported(f, 'diff')
 
+    _eval_derivative = diff
+    _eval_diff = diff
+
     def eval(self, x, a=None, auto=True):
         """
         Evaluate ``f`` at ``a`` in the given variable.


Test patch:
diff --git a/sympy/polys/tests/test_polytools.py b/sympy/polys/tests/test_polytools.py
index 38deab20d5..2f6310e59b 100644
--- a/sympy/polys/tests/test_polytools.py
+++ b/sympy/polys/tests/test_polytools.py
@@ -51,8 +51,8 @@
 from sympy.polys.orderings import lex, grlex, grevlex
 
 from sympy import (
-    S, Integer, Rational, Float, Mul, Symbol, sqrt, Piecewise,
-    exp, sin, tanh, expand, oo, I, pi, re, im, RootOf, Eq, Tuple, Expr)
+    S, Integer, Rational, Float, Mul, Symbol, sqrt, Piecewise, Derivative,
+    exp, sin, tanh, expand, oo, I, pi, re, im, RootOf, Eq, Tuple, Expr, diff)
 
 from sympy.core.basic import _aresame
 from sympy.core.compatibility import iterable
@@ -1423,6 +1423,13 @@ def test_Poly_diff():
     assert Poly(x**2*y**2 + x*y).diff(y, x) == Poly(4*x*y + 1)
 
 
+def test_issue_9585():
+    assert diff(Poly(x**2 + x)) == Poly(2*x + 1)
+    assert diff(Poly(x**2 + x), x, evaluate=False) == \
+        Derivative(Poly(x**2 + x), x)
+    assert Derivative(Poly(x**2 + x), x).doit() == Poly(2*x + 1)
+
+
 def test_Poly_eval():
     assert Poly(0, x).eval(7) == 0
     assert Poly(1, x).eval(7) == 1
diff --git a/sympy/solvers/tests/test_solveset.py b/sympy/solvers/tests/test_solveset.py
index 3883120704..d1106efcf5 100644
--- a/sympy/solvers/tests/test_solveset.py
+++ b/sympy/solvers/tests/test_solveset.py
@@ -40,6 +40,7 @@
 def test_invert_real():
     x = Dummy(real=True)
     n = Symbol('n')
+    d = Dummy()
     assert solveset(abs(x) - n, x) == Intersection(S.Reals, FiniteSet(-n, n))
 
     n = Symbol('n', real=True)
@@ -587,6 +588,7 @@ def test_solveset_complex_polynomial():
 
 
 def test_sol_zero_complex():
+    # This should return the complex set after it is implemented
     assert solveset_complex(0, x) == S.Complex