Repository: sympy/sympy
File: sympy/vector/vector.py (Python)

Code before:

    def _div_helper(one, other):
        """ Helper for division involving vectors. """
        if isinstance(one, Vector) and isinstance(other, Vector):
            raise TypeError("Cannot divide two vectors")
        elif isinstance(one, Vector):
            if other == S.Zero:
                raise ValueError("Cannot divide a vector by zero")
            return VectorMul(one, Pow(other, S.NegativeOne))
        else:
            raise TypeError("Invalid division involving a vector")

# The following is adapted from the matrices.expressions.matexpr file

def get_postprocessor(cls):
    def _postprocessor(expr):
        vec_class = {Add: VectorAdd, Mul: VectorMul}[cls]
        vectors = []
        for term in expr.args:
            if isinstance(term.kind, VectorKind):
                vectors.append(term)

        if vec_class == VectorAdd:
            return VectorAdd(*expr.args).doit(deep=False)
        if vec_class == VectorMul:
            return VectorMul(*vectors).doit(deep=False)
    return _postprocessor


Basic._constructor_postprocessor_mapping[Vector] = {
    "Add": [get_postprocessor(Add)],
    "Mul": [get_postprocessor(Mul)],
}

class BaseVector(Vector, AtomicExpr):
    """
    Class to denote a base vector.

    """

    def __new__(cls, index, system, pretty_str=None, latex_str=None):
        if pretty_str is None:
            pretty_str = "x{}".format(index)
        if latex_str is None:
            latex_str = "x_{}".format(index)
        pretty_str = str(pretty_str)
        latex_str = str(latex_str)
        # Verify arguments
        if index not in range(0, 3):
            raise ValueError("index must be 0, 1 or 2")
        if not isinstance(system, CoordSys3D):

Review comment (suggestion):
Can this not just pass all of `expr.args`? What happens to the other args?

I think there needs to be some tests in the `test_vector.py` for what happens when calling `Add(*args)` or `Mul(*args)` with args that are vectors or scalars. These can go along with the tests for kind.

Code after:

    def _div_helper(one, other):
        """ Helper for division involving vectors. """
        if isinstance(one, Vector) and isinstance(other, Vector):
            raise TypeError("Cannot divide two vectors")
        elif isinstance(one, Vector):
            if other == S.Zero:
                raise ValueError("Cannot divide a vector by zero")
            return VectorMul(one, Pow(other, S.NegativeOne))
        else:
            raise TypeError("Invalid division involving a vector")

# The following is adapted from the matrices.expressions.matexpr file

def _add_vector_postprocessor(expr: Add) -> Vector:
    return VectorAdd(*expr.args).doit(deep=False)

def _mul_vector_postprocessor(expr: Mul) -> Vector:
    return VectorMul(*expr.args).doit(deep=False)

def _pow_vector_postprocessor(expr: Pow):
    raise TypeError("Power operation is not supported for vectors")


Basic._constructor_postprocessor_mapping[Vector] = {
    "Add": [_add_vector_postprocessor],
    "Mul": [_mul_vector_postprocessor],
    "Pow": [_pow_vector_postprocessor],
}

class BaseVector(Vector, AtomicExpr):
    """
    Class to denote a base vector.

    """

    def __new__(cls, index, system, pretty_str=None, latex_str=None):
        if pretty_str is None:
            pretty_str = "x{}".format(index)
        if latex_str is None:
            latex_str = "x_{}".format(index)
        pretty_str = str(pretty_str)
        latex_str = str(latex_str)
        # Verify arguments
        if index not in range(0, 3):
            raise ValueError("index must be 0, 1 or 2")
        if not isinstance(system, CoordSys3D):
            raise TypeError("system should be a CoordSys3D")
        name = system._vector_names[index]
        # Initialize an object
        obj = super().__new__(cls, S(index), system)