# Buggy code
def imageset(*args):
    r"""
    Return an image of the set under transformation ``f``.

    If this function can't compute the image, it returns an
    unevaluated ImageSet object.

    .. math::
        { f(x) | x \in self }

    Examples
    ========

    >>> from sympy import Interval, Symbol, imageset, sin, Lambda
    >>> from sympy.abc import x, y

    >>> imageset(x, 2*x, Interval(0, 2))
    [0, 4]

    >>> imageset(lambda x: 2*x, Interval(0, 2))
    [0, 4]

    >>> imageset(Lambda(x, sin(x)), Interval(-2, 1))
    ImageSet(Lambda(x, sin(x)), [-2, 1])

    >>> imageset(sin, Interval(-2, 1))
    ImageSet(Lambda(x, sin(x)), [-2, 1])
    >>> imageset(lambda y: x + y, Interval(-2, 1))
    ImageSet(Lambda(_x, _x + x), [-2, 1])

    See Also
    ========

    sympy.sets.fancysets.ImageSet

    """
    from sympy.core import Lambda
    from sympy.sets.fancysets import ImageSet
    from sympy.geometry.util import _uniquely_named_symbol

    if len(args) not in (2, 3):
        raise ValueError("imageset expects 2 or 3 args, got: %s" % len(args))

    set = args[-1]
    if not isinstance(set, Set):
        name = func_name(set)
        raise ValueError("last argument should be a set, not %s" % name)

    if len(args) == 3:
        f = Lambda(*args[:2])
    elif len(args) == 2:
        f = args[0]
        if isinstance(f, Lambda):
            pass
        elif (
            isinstance(f, FunctionClass)  # like cos
            or func_name(f) == "<lambda>"
        ):
            var = _uniquely_named_symbol(Symbol("x"), f(Dummy()))
            expr = f(var)
            f = Lambda(var, expr)
        else:
            raise TypeError(
                filldedent(
                    """
        expecting lambda, Lambda, or FunctionClass, not \'%s\'"""
                    % func_name(f)
                )
            )

    r = set._eval_imageset(f)
    if isinstance(r, ImageSet):
        f, set = r.args

    if f.variables[0] == f.expr:
        return set

    if isinstance(set, ImageSet):
        if len(set.lamda.variables) == 1 and len(f.variables) == 1:
            return imageset(
                Lambda(
                    set.lamda.variables[0], f.expr.subs(f.variables[0], set.lamda.expr)
                ),
                set.base_set,
            )

    if r is not None:
        return r

    return ImageSet(f, set)


# Traceback (TypeError)
Following function call generate an error in Python3 but work well in Python2.

factor_list(x*(x+y))

Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/thilinarmtb/GSoC/sympy/sympy/polys/polytools.py", line 5675, in factor_list
return _generic_factor_list(f, gens, args, method='factor')
File "/home/thilinarmtb/GSoC/sympy/sympy/polys/polytools.py", line 5423, in _generic_factor_list
fp = _sorted_factors(fp, method)
File "/home/thilinarmtb/GSoC/sympy/sympy/polys/polytools.py", line 5322, in _sorted_factors
return sorted(factors, key=key)
TypeError: unorderable types: list() < int()


Similarly following calls generate the same error:
[1] factor_list(y*(x+y)),  factor_list(x*y + y**2)
[2] factor_list(x*(x+y+z)), factor_list(x**2+x*y+x*z)
[3] factor_list((x + 1)*(x + y))

But the following don't:
[4] factor_list(x*(x**2 + y**2)), factor_list(x**3 + x*y**2)
[5] factor_list(x**3 - x),  factor_list(x*(x**2 - 1))
[6] factor_list(x**2 + x*y + x + y)
[7] factor_list((x + z)*(x + y)), factor_list(x**2 + x*z + y*x + y*z)

Here [6] is mathematically same as [3]. But only [3] gives the error.

# Fixed code
def imageset(*args):
    r"""
    Return an image of the set under transformation ``f``.

    If this function can't compute the image, it returns an
    unevaluated ImageSet object.

    .. math::
        { f(x) | x \in self }

    Examples
    ========

    >>> from sympy import S, Interval, Symbol, imageset, sin, Lambda
    >>> from sympy.abc import x, y

    >>> imageset(x, 2*x, Interval(0, 2))
    [0, 4]

    >>> imageset(lambda x: 2*x, Interval(0, 2))
    [0, 4]

    >>> imageset(Lambda(x, sin(x)), Interval(-2, 1))
    ImageSet(Lambda(x, sin(x)), [-2, 1])

    >>> imageset(sin, Interval(-2, 1))
    ImageSet(Lambda(x, sin(x)), [-2, 1])
    >>> imageset(lambda y: x + y, Interval(-2, 1))
    ImageSet(Lambda(_x, _x + x), [-2, 1])

    Expressions applied to the set of Integers are simplified
    to show as few negatives as possible and linear expressions
    are converted to a canonical form. If this is not desirable
    then the unevaluated ImageSet should be used.

    >>> imageset(x, -2*x + 5, S.Integers)
    ImageSet(Lambda(x, 2*x + 1), Integers())

    See Also
    ========

    sympy.sets.fancysets.ImageSet

    """
    from sympy.core import Lambda
    from sympy.sets.fancysets import ImageSet
    from sympy.geometry.util import _uniquely_named_symbol

    if len(args) not in (2, 3):
        raise ValueError("imageset expects 2 or 3 args, got: %s" % len(args))

    set = args[-1]
    if not isinstance(set, Set):
        name = func_name(set)
        raise ValueError("last argument should be a set, not %s" % name)

    if len(args) == 3:
        f = Lambda(*args[:2])
    elif len(args) == 2:
        f = args[0]
        if isinstance(f, Lambda):
            pass
        elif (
            isinstance(f, FunctionClass)  # like cos
            or func_name(f) == "<lambda>"
        ):
            var = _uniquely_named_symbol(Symbol("x"), f(Dummy()))
            expr = f(var)
            f = Lambda(var, expr)
        else:
            raise TypeError(
                filldedent(
                    """
        expecting lambda, Lambda, or FunctionClass, not \'%s\'"""
                    % func_name(f)
                )
            )

    r = set._eval_imageset(f)
    if isinstance(r, ImageSet):
        f, set = r.args

    if f.variables[0] == f.expr:
        return set

    if isinstance(set, ImageSet):
        if len(set.lamda.variables) == 1 and len(f.variables) == 1:
            return imageset(
                Lambda(
                    set.lamda.variables[0], f.expr.subs(f.variables[0], set.lamda.expr)
                ),
                set.base_set,
            )

    if r is not None:
        return r

    return ImageSet(f, set)