Inspect.signature not working with math.log?

See

from inspect import signature
import math
import traceback
import sys

print(sys.version)

funcs_to_try = [
    math.acos, math.acosh, math.asinh, math.atan, math.atan2, math.cos, math.cosh,
    math.degrees, math.erf, math.erfc, math.exp, math.log, math.log10, math.radians,
    math.sin, math.sinh, math.sqrt, math.tan, math.tanh
]

for func in funcs_to_try:
    try:
        print(f"{func.__name__}: {signature(func)}")
    except ValueError:
        print(f"{func.__name__}: Didn't work.")
        traceback.print_exc(file=sys.stdout)


# 3.12.4 (tags/v3.12.4:8e8a4ba, Jun  6 2024, 19:30:16) [MSC v.1940 64 bit (AMD64)]
# acos: (x, /)
# acosh: (x, /)
# asinh: (x, /)
# atan: (x, /)
# atan2: (y, x, /)
# cos: (x, /)
# cosh: (x, /)
# degrees: (x, /)
# erf: (x, /)
# erfc: (x, /)
# exp: (x, /)
# log: Didn't work.
# Traceback (most recent call last):
#   File "...\AppData\Roaming\JetBrains\PyCharm2024.1\scratches\scratch.py", line 16, in <module>
#     print(f"{func.__name__}: {signature(func)}")
#                               ^^^^^^^^^^^^^^^
#   File "...\AppData\Local\Programs\Python\Python312\Lib\inspect.py", line 3335, in signature
#     return Signature.from_callable(obj, follow_wrapped=follow_wrapped,
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#   File "...\AppData\Local\Programs\Python\Python312\Lib\inspect.py", line 3075, in from_callable
#     return _signature_from_callable(obj, sigcls=cls,
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#   File "...\AppData\Local\Programs\Python\Python312\Lib\inspect.py", line 2592, in _signature_from_callable
#     return _signature_from_builtin(sigcls, obj,
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#   File "...\AppData\Local\Programs\Python\Python312\Lib\inspect.py", line 2382, in _signature_from_builtin
#     raise ValueError("no signature found for builtin {!r}".format(func))
# ValueError: no signature found for builtin <built-in function log>
# log10: (x, /)
# radians: (x, /)
# sin: (x, /)
# sinh: (x, /)
# sqrt: (x, /)
# tan: (x, /)
# tanh: (x, /)

Why is math.log the only function out of this long list on which inspect.signature fails? I’m curious if there’s something I can do to get this working.

I understand there’s some historical trickiness with inspect.signature and built-in functions, but it works for all these other functions so it seems like it should work for math.log.

FYI: Should `None` defaults for optional arguments be discouraged?.

But it’s not alone in the math module. E.g. math.hypot().

Edit: See also gh-73536: Add support of multi-signatures by serhiy-storchaka · Pull Request #117671 · python/cpython · GitHub

Ah, great, thank you! It looks like the issue is related to a function having multiple signatures and that this is an active area of work. I’ll read through those links you shared.

In the meantime I’ll have to figure out how to work around this.

Ok, after skimming the links and PRs it isn’t totally clear to me what’s going on. It looks like Mark Dickinson had a fix that involved changing log to accept something like log(3, None) to be equivalent to log(3). This seems super fine to me but it sounds like this was hotly debated and the PR died because of it.

This leaves me with QUESTION: does gh-73536: Add support of multi-signatures by serhiy-storchaka · Pull Request #117671 · python/cpython · GitHub solve the problem I’m having here in a different way?

Also should I expect to see this resolved in 3.13? 3.14? It’s very sad, the workaround for this for me is very ugly. I have to manually loop through args and kwargs when I could just use inspect.signature and .bind() if log worked as needed here. The project I’m working on support python 3.8, meaning it will probably be years before I can move to inspect.signature for this use case.

Yes, I think it should. Correct signature for this function shown in the sphinx docs with funny bracket syntax:

math.log(x[, base])

This is an equivalent of:

log(x, /)
log(x, base, /)

See e.g. gmpy2.mpz docs. Unfortunately, this works only in the sphinx now.

It’s definitely out of 3.13. I’ll try to ping Serhiy, but for me it seems there is a lot of work to do.