Repository: sympy/sympy

Issue:
sympify("abs(x)*5",evaluate=False) crashes
Long story short: The following program crashes:
```
import sympy
sympy.sympify("abs(x)*5",evaluate=False)
```
with the message:
> Traceback (most recent call last):
>   File "bugreport2.py", line 3, in <module>
>     sympy.sympify("abs(x)*5",evaluate=False)
>   File "/home/volker/.local/lib/python3.7/site-packages/sympy/core/sympify.py", line 384, in sympify
>     expr = parse_expr(a, local_dict=locals, transformations=transformations, evaluate=evaluate)
>   File "/home/volker/.local/lib/python3.7/site-packages/sympy/parsing/sympy_parser.py", line 964, in parse_expr
>     code = compile(evaluateFalse(code), '<string>', 'eval')
>   File "/home/volker/.local/lib/python3.7/site-packages/sympy/parsing/sympy_parser.py", line 974, in evaluateFalse
>     node = EvaluateFalseTransformer().visit(node)
>   File "/usr/lib/python3.7/ast.py", line 262, in visit
>     return visitor(node)
>   File "/usr/lib/python3.7/ast.py", line 317, in generic_visit
>     value = self.visit(value)
>   File "/usr/lib/python3.7/ast.py", line 262, in visit
>     return visitor(node)
>   File "/usr/lib/python3.7/ast.py", line 326, in generic_visit
>     new_node = self.visit(old_value)
>   File "/usr/lib/python3.7/ast.py", line 262, in visit
>     return visitor(node)
>   File "/home/volker/.local/lib/python3.7/site-packages/sympy/parsing/sympy_parser.py", line 1047, in visit_BinOp
>     new_node.args = self.flatten(new_node.args, sympy_class)
>   File "/home/volker/.local/lib/python3.7/site-packages/sympy/parsing/sympy_parser.py", line 996, in flatten
>     if isinstance(arg, ast.Call) and arg.func.id == func:
> AttributeError: 'Call' object has no attribute 'id'

sympy.\_\_version\_\_ is '1.4' and sys.version is '3.7.3 (default, Oct  7 2019, 12:56:13) \n[GCC 8.3.0]'

Discussion:

Patch:
diff --git a/sympy/combinatorics/permutations.py b/sympy/combinatorics/permutations.py
index 6c1a212afd..fdfa928f56 100644
--- a/sympy/combinatorics/permutations.py
+++ b/sympy/combinatorics/permutations.py
@@ -5,8 +5,6 @@
 
 from sympy.core.basic import Atom
 from sympy.core.compatibility import is_sequence, reduce, range, as_int
-from sympy.core.sympify import _sympify
-from sympy.logic.boolalg import as_Boolean
 from sympy.matrices import zeros
 from sympy.polys.polytools import lcm
 from sympy.utilities.iterables import (flatten, has_variety, minlex,
@@ -950,16 +948,6 @@ def __new__(cls, *args, **kwargs):
 
         return cls._af_new(aform)
 
-    def _eval_Eq(self, other):
-        other = _sympify(other)
-        if not isinstance(other, Permutation):
-            return None
-
-        if self._size != other._size:
-            return None
-
-        return as_Boolean(self._array_form == other._array_form)
-
     @classmethod
     def _af_new(cls, perm):
         """A method to produce a Permutation object from a list;
diff --git a/sympy/parsing/sympy_parser.py b/sympy/parsing/sympy_parser.py
index a2c400b758..60a5557520 100644
--- a/sympy/parsing/sympy_parser.py
+++ b/sympy/parsing/sympy_parser.py
@@ -1035,8 +1035,14 @@ class EvaluateFalseTransformer(ast.NodeTransformer):
     def flatten(self, args, func):
         result = []
         for arg in args:
-            if isinstance(arg, ast.Call) and arg.func.id == func:
-                result.extend(self.flatten(arg.args, func))
+            if isinstance(arg, ast.Call):
+                arg_func = arg.func
+                if isinstance(arg_func, ast.Call):
+                    arg_func = arg_func.func
+                if arg_func.id == func:
+                    result.extend(self.flatten(arg.args, func))
+                else:
+                    result.append(arg)
             else:
                 result.append(arg)
         return result
diff --git a/sympy/sets/handlers/intersection.py b/sympy/sets/handlers/intersection.py
index aa192ab233..51bd413f99 100644
--- a/sympy/sets/handlers/intersection.py
+++ b/sympy/sets/handlers/intersection.py
@@ -223,31 +223,39 @@ def intersection_sets(self, other):
         return None
     base_set = self.base_sets[0]
 
-    # Intersection between ImageSets with Integers as base set
-    # For {f(n) : n in Integers} & {g(m) : m in Integers} we solve the
-    # diophantine equations f(n)=g(m).
-    # If the solutions for n are {h(t) : t in Integers} then we return
-    # {f(h(t)) : t in integers}.
     if base_set is S.Integers:
-        gm = None
+        g = None
         if isinstance(other, ImageSet) and other.base_sets == (S.Integers,):
-            gm = other.lamda.expr
+            g = other.lamda.expr
             m = other.lamda.variables[0]
         elif other is S.Integers:
-            m = gm = Dummy('x')
-        if gm is not None:
-            fn = self.lamda.expr
+            m = g = Dummy('x')
+        if g is not None:
+            f = self.lamda.expr
             n = self.lamda.variables[0]
-            solns = list(diophantine(fn - gm, syms=(n, m)))
-            if len(solns) == 0:
+            # Diophantine sorts the solutions according to the alphabetic
+            # order of the variable names, since the result should not depend
+            # on the variable name, they are replaced by the dummy variables
+            # below
+            a, b = Dummy('a'), Dummy('b')
+            fa, ga = f.subs(n, a), g.subs(m, b)
+            solns = list(diophantine(fa - ga))
+            if not solns:
                 return EmptySet()
-            elif len(solns) != 1:
+
+            if len(solns) != 1:
                 return
-            else:
-                soln, solm = solns[0]
-                (t,) = soln.free_symbols
-                expr = fn.subs(n, soln.subs(t, n))
-                return imageset(Lambda(n, expr), S.Integers)
+            nsol = solns[0][0]  # since 'a' < 'b', nsol is first
+            t = nsol.free_symbols.pop()  # diophantine supplied symbol
+            nsol = nsol.subs(t, n)
+            if nsol != n:
+                # if nsol == n and we know were are working with
+                # a base_set of Integers then this was an unevaluated
+                # ImageSet representation of Integers, otherwise
+                # it is a new ImageSet intersection with a subset
+                # of integers
+                nsol = f.subs(n, nsol)
+            return imageset(Lambda(n, nsol), S.Integers)
 
     if other == S.Reals:
         from sympy.solvers.solveset import solveset_real


Test patch:
diff --git a/sympy/combinatorics/tests/test_permutations.py b/sympy/combinatorics/tests/test_permutations.py
index 4b53c1e79f..1685475cba 100644
--- a/sympy/combinatorics/tests/test_permutations.py
+++ b/sympy/combinatorics/tests/test_permutations.py
@@ -1,10 +1,7 @@
 from itertools import permutations
 
 from sympy.core.compatibility import range
-from sympy.core.expr import unchanged
-from sympy.core.relational import Eq
 from sympy.core.symbol import Symbol
-from sympy.core.singleton import S
 from sympy.combinatorics.permutations import (Permutation, _af_parity,
     _af_rmul, _af_rmuln, Cycle)
 from sympy.utilities.pytest import raises
@@ -468,20 +465,3 @@ def test_printing_non_cyclic():
     assert str(p3) == 'Permutation([0, 2, 1])'
     p4 = Permutation([0, 1, 3, 2, 4, 5, 6, 7])
     assert repr(p4) == 'Permutation([0, 1, 3, 2], size=8)'
-
-
-def test_permutation_equality():
-    a = Permutation(0, 1, 2)
-    b = Permutation(0, 1, 2)
-    assert Eq(a, b) is S.true
-    c = Permutation(0, 2, 1)
-    assert Eq(a, c) is S.false
-
-    d = Permutation(0, 1, 2, size=4)
-    assert unchanged(Eq, a, d)
-    e = Permutation(0, 2, 1, size=4)
-    assert unchanged(Eq, a, e)
-
-    i = Permutation()
-    assert unchanged(Eq, i, 0)
-    assert unchanged(Eq, 0, i)
diff --git a/sympy/core/tests/test_sympify.py b/sympy/core/tests/test_sympify.py
index 03506617ec..719d0db0a7 100644
--- a/sympy/core/tests/test_sympify.py
+++ b/sympy/core/tests/test_sympify.py
@@ -695,3 +695,8 @@ def test_issue_16759():
     assert S.Half not in d
     assert Float(.5) in d
     assert d[.5] is S.One
+
+
+def test_issue_17811():
+    a = Function('a')
+    assert sympify('a(x)*5', evaluate=False) == Mul(a(x), 5, evaluate=False)
diff --git a/sympy/sets/tests/test_fancysets.py b/sympy/sets/tests/test_fancysets.py
index c278a3c300..cba7d60e1f 100644
--- a/sympy/sets/tests/test_fancysets.py
+++ b/sympy/sets/tests/test_fancysets.py
@@ -528,10 +528,6 @@ def test_infinitely_indexed_set_1():
     assert imageset(x, x/2 + Rational(1, 3), S.Integers).intersect(S.Integers) is S.EmptySet
     assert imageset(x, x/2 + S.Half, S.Integers).intersect(S.Integers) is S.Integers
 
-    # https://github.com/sympy/sympy/issues/17355
-    S53 = ImageSet(Lambda(n, 5*n + 3), S.Integers)
-    assert S53.intersect(S.Integers) == S53
-
 
 def test_infinitely_indexed_set_2():
     from sympy.abc import n