Skip to content

SymPy

Utility functions for parsing and evaluating SymPy expressions.

from prairielearn.sympy_utils import ...

AssumptionsDictT module-attribute

AssumptionsDictT = dict[str, dict[str, Any]]

A dictionary of assumptions for variables in the expression.

Examples:

>>> {"x": {"positive": True}, "y": {"real": True}}

BaseSympyError

Exception base class for SymPy parsing errors

LocalsForEval

A class with type signatures for the locals_for_eval dict

SympyJson

A class with type signatures for the SymPy JSON dict

ast_check_str

ast_check_str(
    expr: str, locals_for_eval: LocalsForEval
) -> None

Check the AST of the expression for security, whitelisting only certain nodes.

This prevents the user from executing arbitrary code through eval_expr.

Raises:

Type Description
HasEscapeError

If the expression contains an escape character.

HasCommentError

If the expression contains a comment character.

convert_string_to_sympy

convert_string_to_sympy(
    expr: str,
    variables: Iterable[str] | None = None,
    *,
    allow_hidden: bool = False,
    allow_complex: bool = False,
    allow_trig_functions: bool = True,
    custom_functions: Iterable[str] | None = None,
    assumptions: AssumptionsDictT | None = None,
) -> Expr

Convert a string to a SymPy expression, with optional restrictions on the variables and functions that can be used. If the string is invalid, raise an exception with a message that can be displayed to the user.

Parameters:

Name Type Description Default
expr str

The string to convert to a SymPy expression.

required
variables Iterable[str] | None

A list of variable names that are allowed in the expression.

None
allow_hidden bool

Whether to allow hidden variables (like pi and e).

False
allow_complex bool

Whether to allow complex numbers (like i).

False
allow_trig_functions bool

Whether to allow trigonometric functions.

True
custom_functions Iterable[str] | None

A list of custom function names that are allowed in the expression.

None
assumptions AssumptionsDictT | None

A dictionary of assumptions for variables in the expression.

None

Examples:

>>> convert_string_to_sympy("n * sin(7*m) + m**2 * cos(6*n)", variables=["m", "n"])
n * sympy.sin(m * 7) + m * m * sympy.cos(n * 6)
>>> convert_string_to_sympy("-infty")
-sympy.oo
>>> convert_string_to_sympy("z**2 + y - x", variables=["x", "y", "z"], allow_complex=True, assumptions={"x": {"positive": False}, "z": {"complex": True}})

Returns:

Type Description
Expr

A sympy expression.

convert_string_to_sympy_with_source

convert_string_to_sympy_with_source(
    expr: str,
    variables: Iterable[str] | None = None,
    *,
    allow_hidden: bool = False,
    allow_complex: bool = False,
    allow_trig_functions: bool = True,
    custom_functions: Iterable[str] | None = None,
    assumptions: AssumptionsDictT | None = None,
) -> tuple[Expr, str]

Convert a string to a sympy expression, with optional restrictions on the variables and functions that can be used. If the string is invalid, raise an exception with a message that can be displayed to the user.

Returns:

Type Description
tuple[Expr, str]

A tuple of the sympy expression and the source code that was used to generate it.

Raises:

Type Description
HasInvalidAssumptionError

If the assumptions are not valid.

HasConflictingVariableError

If the variable names conflict with existing names.

HasConflictingFunctionError

If the function names conflict with existing names.

evaluate

evaluate(
    expr: str,
    locals_for_eval: LocalsForEval,
    *,
    allow_complex: bool = False,
) -> Expr

Evaluate a SymPy expression string with a given set of locals, and return only the result.

Returns:

Type Description
Expr

A SymPy expression.

evaluate_with_source

evaluate_with_source(
    expr: str,
    locals_for_eval: LocalsForEval,
    *,
    allow_complex: bool = False,
) -> tuple[Expr, str]

Evaluate a SymPy expression string with a given set of locals.

Returns:

Type Description
tuple[Expr, str]

A tuple of the SymPy expression and the code that was used to generate it.

Raises:

Type Description
HasParseError

If the expression cannot be parsed.

BaseSympyError

If the expression cannot be evaluated.

get_items_list

get_items_list(items_string: str | None) -> list[str]

Return a list of items from a comma-separated string.

greek_unicode_transform

greek_unicode_transform(input_str: str) -> str

Return input_str where all unicode greek letters are replaced by their spelled-out english names.

is_sympy_json

is_sympy_json(json: Any) -> TypeGuard[SympyJson]

Check if the input is a valid SymPy JSON dict.

Returns:

Type Description
TypeGuard[SympyJson]

True if the input is a valid SymPy JSON dict, False otherwise.

json_to_sympy

json_to_sympy(
    sympy_expr_dict: SympyJson,
    *,
    allow_complex: bool = True,
    allow_trig_functions: bool = True,
) -> Expr

Convert a json-seralizable dictionary created by sympy_to_json to a SymPy expression.

Returns:

Type Description
Expr

A SymPy expression.

Raises:

Type Description
ValueError

If the input is not a valid SymPy JSON dict.

point_to_error

point_to_error(expr: str, ind: int, w: int = 5) -> str

Generate a string with a pointer to error in expr with index ind

Returns:

Type Description
str

A string with the error location in the expression.

sympy_check

sympy_check(
    expr: Expr,
    locals_for_eval: LocalsForEval,
    *,
    allow_complex: bool,
) -> None

Check the SymPy expression for complex numbers, invalid symbols, and floats.

sympy_to_json

sympy_to_json(
    a: Expr,
    *,
    allow_complex: bool = True,
    allow_trig_functions: bool = True,
) -> SympyJson

Convert a SymPy expression to a JSON-seralizable dictionary.

Returns:

Type Description
SympyJson

A JSON-serializable representation of the SymPy expression.

validate_string_as_sympy

validate_string_as_sympy(
    expr: str,
    variables: Iterable[str] | None,
    *,
    allow_hidden: bool = False,
    allow_complex: bool = False,
    allow_trig_functions: bool = True,
    custom_functions: list[str] | None = None,
    imaginary_unit: str | None = None,
) -> str | None

Try to parse expr as a SymPy expression. If it fails, return a string with an appropriate error message for display on the frontend.

Returns:

Type Description
str | None

None if the expression is valid, and an error message otherwise.