There is the same issue in the stdlib. The difference between the C and Python implementations of Decimal:
>>> from decimal import Decimal
>>> pow(10, Decimal(2), 7)
Decimal('2')
>>> pow(10, 2, Decimal(7))
Decimal('2')
>>> from _pydecimal import Decimal
>>> pow(10, Decimal(2), 7)
Traceback (most recent call last):
File "<python-input-4>", line 1, in <module>
pow(10, Decimal(2), 7)
~~~^^^^^^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for ** or pow(): 'int', 'Decimal', 'int'
>>> pow(10, 2, Decimal(7))
Traceback (most recent call last):
File "<python-input-5>", line 1, in <module>
pow(10, 2, Decimal(7))
~~~^^^^^^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for ** or pow(): 'int', 'int', 'Decimal'
2-argument pow() works with any combination of arguments.
The dispatching code for the second argument in 3-argument pow() can harmonized with 2-argument variant. But for dispatching on the third argument we need a separate special method, e.g. __mpow__(mod, base, exp), if follow tradition of special methods for binary operations.
Alternatively, we could have a single special method for direct and reverse operation, as was proposed above. Actually, extension classes have a single slot nb_subtract while Python classes have __sub__ and __rsub__ methods. The behavior is more complicated than it is described in the documentation, because it is really difficult to document such complicated behavior. It somehow works,… except when it doesn’t, like in this case.
I think that adding the __mpow__ method is simpler solution.