sympy / sympy

A computer algebra system written in pure Python

Home Page:https://sympy.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`repr(Function | int)` returns results inconsistent with type name.

iamrecursion opened this issue · comments

I've been using sympy.Function == sympy.core.function.Function with https://github.com/beartype/beartype for runtime type checking. It works soundless with almost all the types I have tried, but when using Function in a union, function's repr returns sympy.core.function.Function instead of plain Function.

You can reproduce this by:

import sympy as S

print(repr(S.Function))        # prints 'Function'
print(repr(S.Function | int))  # prints 'sympy.core.function.Function | int'

In the latter case I think it should print 'Function | int' instead, but I don't know why it does this while many other types in sympy do not!

The error I get actually comes from beartype, and is as follows:

beartype.roar.BeartypeDecorHintPep604Exception: Type hint Function inconsistent with respect to repr() strings. Since @beartype requires consistency between type hints and repr() strings, this hint is unsupported by @beartype. Consider reporting this issue to the third-party developer implementing this hint: e.g.,
	>>> repr(Function)
	Function  # <-- this is fine
	>>> repr(Function | int)
	sympy.core.function.Function | int  # <-- *THIS IS REALLY SUPER BAD*

	# Ideally, that output should instead resemble:
	>>> repr(Function | int)
	Function | int  # <-- what @beartype wants!

Here's a (slightly) longer repro using beartype to demonstrate the error directly:

import sympy as S
from beartype import beartype
from typing import TypeAlias

MyType: TypeAlias = S.Symbol | S.MatrixSymbol | S.Function

@beartype
def fn(sym: MyType) -> str:
    return sym.name

A simpler demonstration is:

In [17]: repr(Function)
Out[17]: 'Function'

In [18]: repr(Function | int)
Out[18]: 'sympy.core.function.Function | int'

I don't know why that is a problem for beartype. I also have no idea how the union type does its printing: I don't think it comes from sympy.

It very well could be coming from SymPy. SymPy overrides the default printing on the type for Function subclasses

def _print_FunctionClass(self, expr):
if issubclass(expr, AppliedUndef):
return 'Function(%r)' % (expr.__name__)
else:
return expr.__name__