During Sage Days 100, I experienced an issue with Sage's Integers and Rational not being compatible with Python's built in Fraction class. This made me unable to run my Python code within Sage and so I raised ticket 28234 <https://trac.sagemath.org/ticket/28234>. For example, in Sage 8.8:
sage: from fractions import Fraction sage: Fraction(7, 3) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-3-4a5c214ab004> in <module>() ----> 1 Fraction(Integer(7), Integer(3)) /Applications/SageMath-8.6.app/Contents/Resources/sage/local/lib/python2.7/ fractions.pyc in __new__(cls, numerator, denominator) 152 isinstance(denominator, Rational)): 153 numerator, denominator = ( --> 154 numerator.numerator * denominator.denominator, 155 denominator.numerator * numerator.denominator 156 ) TypeError: unsupported operand type(s) for *: 'builtin_function_or_method' and 'builtin_function_or_method' sage: Fraction(7) Fraction(<built-in method numerator of sage.rings.integer.Integer object at 0x182ab93f0>, <built-in method denominator of sage.rings.integer.Integer object at 0x182ab93f0>) sage: Fraction(7 / 3) Fraction(<built-in method numerator of sage.rings.rational.Rational object at 0x182ab2950>, <built-in method denominator of sage.rings.rational. Rational object at 0x182ab2950>) This issue is because, despite the Integer and Rational class being registered as Python's numbers.Integral and numbers.Rational classes, they do not implement numerator and denominator *properties* as required by the Python specification. Instead they implement numerator and denominator *methods*. This issue has been spotted a number of times [1] <https://trac.sagemath.org/ticket/20861> [2] <https://ask.sagemath.org/question/39717>. During the course of the workshop several solutions were suggested and investigated including: 1. Make Integer and Rational numerator and denominator properties and accept that this would not be backwards compatible within Sage 2. Make Integer and Rational numerator and denominator properties and add numer and denom methods to classes that have these properties and switch to using these throughout 3. Make Integer and Rational numerator and denominator properties and make Integers callable and return themselves 4. Raise a PEP to change the Python specification to be / include numerator and denominator methods 5. Do not register Integer and Rational as numbers.Integral and numbers.Rational 6. Do nothing and so accept that Sage does not perfectly match the Python specification As part of the workshop, I worked on implementing approach #3 within branch 28234 <https://git.sagemath.org/sage.git/diff?id2=a1e1a8f721fa32840968248200327af6a7f35de0&id=4977867e55d76c29b7286e2d542d8342889d8305>. This implementation is now complete and passes all of Sages doctests [although its implementation revealed a bug in sagemath-patchbot which I subsequently fixed <https://github.com/sagemath/sage-patchbot/pull/139>]. This means that now if, for example, x = 5 then both x.numerator and x.numerator() return 5 [in the latter case x.numerator returns 5, and then 5() returns 5]. Hence not only does this make Sage Integers and Rationals compatible with Python Fractions: sage: from fractions import Fraction sage: Fraction(7, 3) Fraction(7, 3) sage: Fraction(7) Fraction(7, 1) sage: Fraction(7/3) Fraction(7, 3) but this change is morally backwards compatible with existing Sage code. However, this approach makes Sage Integers callable and so additional work was needed to ensure that the control flow within Sage kernel was not affected. I used a short Python script to generate a patch (that was applied within branch 28234) that: 1. Replaced all uses of hasattr(x, '__call__') with callable(x) 2. Replaced all uses of isinstance(x, collections.Callable) with callable(x) 3. Replaced all uses of callable(x) with callable(x) and not isinstance(x, numbers.Integral) Therefore if this branch is merged then users may need to make similar changes to their code if they ever rely on the fact that Integers were not callable. Now regarding the other approaches: - Approach #1 would be backwards incompatibly and would likely affect a substantially larger number of users (anyone who has ever access a numerator). It would also mean that care would be needed as to use x.numerator or x.numerator() depending on the type of x. - Approach #2 was attempted but presented difficulties since numer() methods would also need to be added all external objects (e.g. Pari object) that are available within Sage that implement numerator() methods. - Approach #4 was also started and discussion about changing the Python specification from PEP 3141 can be found here <https://discuss.python.org/t/pep-3141-numerator-instead-of-numerator/2037>. This is likely to also have a knock-on effect on other systems such as numpy. - Approach #5 would also result in serious backwards compatibility issues and would still mean that Sage Integers and Rationals would not be compatible with Python Fractions. Therefore I would like to ask the Sage development community for their opinions on: - the different approaches and whether approach #3 is the most suitable - whether branch public/28234 is the most suitable implementation of approach #3 and whether it should be merged into Sage - whether similar changes should be made to other classes within Sage that implement numerator / denominator methods - whether similar changes should be made to the .real() and .imag() methods which should also be properties under the Python specification <https://www.python.org/dev/peps/pep-3141/#numeric-classes> I would also like to emphasise that although only these six approaches were discussed during the workshop, there may well be others. Therefore others should be encouraged to alternative approaches so that these can all be discussed together. Regards, Mark Bell -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sage-devel/595abaa2-2efa-4b64-be52-0afc87210251%40googlegroups.com.