-
Notifications
You must be signed in to change notification settings - Fork 197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dictionaries with sympy symbols as keys throw TypeError #199
Comments
related #103, meaning that |
@notPlancha thank you for the issue and posting the workaround 🙏 sorting dictionaries is useful for human debuggers. ie us. 🙂 ive never used sympy before. any idea why the keys cant be sorted? is this an issue better filed with them to support sorting? |
The keys can't be sorted because there's no order to the symbols, like we can't say if x > y. It's not really an error on their part, it's on purpose. I feel like if this is something that icecream could address, perhaps a check if the keys can be sorted or not (with for example a try except with the |
I recommend looking at the peek package which does it all ... and more. |
yep! first thing that comes to mind is:
but breaking on a failed dict sort is not desired behavior @notPlancha do you have time to take a stab at implementing this and submitting a PR? 🙌 shouldn't be too bad beyond a |
I was trying that but upon further inspection it seems that on pprint.py#L84: class _safe_key:
"""Helper function for key functions when sorting unorderable objects.
The wrapped-object will fallback to a Py2.x style comparison for
unorderable types (sorting first comparing the type name and then by
the obj ids). Does not work recursively, so dict.items() must have
_safe_key applied to both the key and the value.
"""
__slots__ = ['obj']
def __init__(self, obj):
self.obj = obj
def __lt__(self, other):
try:
return self.obj < other.obj
except TypeError:
return ((str(type(self.obj)), id(self.obj)) < \
(str(type(other.obj)), id(other.obj))) Applying this would be a better solution since it still sorts regardless; what I am wondering is why these guardrails fail for sympy. Aditionally, sympy's own pretty_print does not raise the same issue as pprint does, and it does sort dictionaries by default as well: from sympy import symbols, pprint as sym_pprint
from pprint import pprint
x, y = symbols('x y')
d = {y: 1, x: 2}
sym_pprint(d) # {x: y, y: 1}
pprint(d) # TypeError This leads me to believe that this is either an issue on sympy's behalf, or it's due to another reason besides sorting. I'll investigate this further tomorrow |
Why not simply use pprint/pformat with sort_dicts=False? |
Got it: pprint's _safe_key lt returns sympy's from sympy.abc import x, y
x < y # x < y
type(x < y) # <class 'sympy.core.relational.StrictLessThan'>
bool(x < y) # TypeError Checking out the docs for operator.py, it seems it's intentional that the class _safe_key:
__slots__ = ['obj']
def __init__(self, obj):
self.obj = obj
def __lt__(self, other):
try:
- return self.obj < other.obj
+ return bool(self.obj < other.obj)
except TypeError:
return ((str(type(self.obj)), id(self.obj)) < \
(str(type(other.obj)), id(other.obj))) I think this is unfeasible since (not only is it scary to contribute to cpython directly, but also that) changing pprint now would not change supported icecream python versions. Worth a shot to anyone brave enough. Second best option is to do a try except for icecream, like originally planned, but right before the actual pformat call, and turn off sorting after a TypeError. If that doesn't resolve it then it'll still raise an Exception, just twice. |
results in
TypeError: cannot determine truth value of Relational
due to pprint's pformat (according to the stack), since it tries to sort the keys. This doesn't happen with normal objects as keys for some reason.This, for example, makes it so you can call
ic
for system of equations:The text was updated successfully, but these errors were encountered: