The current functions for creating log message (info(), warning(), …) takes **kwargs. These are forwarded to Logger._log():
Therefore, the effectively accepted kwargs are exc_info=None, extra=None, stack_info=False, stacklevel=1.
Having such a hidden signature is not user-friendly. I propose to write the optional parameters out explicitly already in the message creation functions, i.e.
change
There may be a slight performance impact in passing around individual parameters, that are the defaults most of the time. - This would need investigation. The logging functions must stay cheap. If performance prevents this change, would __signature__ be an alternative to provide a more user-friendly signature?
I suspect you’ll find in the wild custom implementations of Logger.log (or other methods down the chain, including of LogRecord) which use some extra keyword arguments (either pre-defined or generic). More investigation required.
I believe custom parameters are currently not possible. Everything runs through the private Logger._log() method mentioned above, which has fixed explicit parameter names. Unless somebody monkey-patches that, custom parameters cannot pass.
A user could reimplement log() to bypass _log, but the private method does all the logic, so that would be pretty wild.
Also, it would be possible to keep **kwargs, but still pull out all known optional parameters. **kwargs would then only be relevant for custom subclasses.
I don’t think CPyrhon generally needs to worry about having user-friendly signatures for its internal implementations, since the actual user-friendly signatures are kept in the docs (what the end users will typically see) and typeshed (what IDEs and static analysis tools will use). For what’s it’s worth, the typeshed signatures for those functions already include all the optional parameters:
>>> import logging
>>> help(logging.info)
Help on function info in module logging:
info(msg, *args, **kwargs)
Log a message with severity 'INFO' on the root logger. If the logger has
no handlers, call basicConfig() to add a console handler with a pre-defined
format.
Yes, more maintenance burden if any of these parameters ever get renamed, their defaults changed, they get type hints added, deprecated or new parameters get added. (technically it also has a performance cost I think, but it’s unlikely that this is ever going to be noticeable)
A better idea would be to properly add the ability to copy signatures from one callable to another in a typing-transparent way.
One can possibly make that work, but it would have to be a partial copy taking some parameters from _log and replacing **kwargs in the other functions. Is that complexity worth the trouble? Writing out the signatures manually is simple and explicit.
Alternatively, would debug.__signature__ = Signature(...) be an option? While __signature__ is currently not a stable and public API, we may be able to use it internally. The worst thing that can happen is that it gets changed in the future and we have to go back to the current state or use a different approach.
Is there really a substantial maintainance burden? It’s not too likely that the signatures will change. Most of the mentioned changes would be breaking API and given the high bar we have on those quite unlikely. Adding new parameters is conceivable though. If there’s really a change, modifying 5 places instead of one is not too troublesome. One should notice that there are related variants of these methods and can make a simple search/replace to update all. I believe actually changing the signatues will be negligable effort compared to the preceeding discussion on if and how a change should be made.
It’s still not a zero cost change. And if we did this here it would also set a precedent for all other places where this is an issue, inside and outside of the stdlib, namely that we will not add a nice and generally useful API, instead please duplicate information (or in this case, write the names 10 extra times, and the defaults 5 extra time).
Maybe - it should be some option that is visible for both dynamic tools (check) and static tools (not check, but they could learn). But this is a topic that I don’t think we need to start another discussion about this here - I actually think that enough discussions about this have already happened that at this point someone needs to write a PEP making a concrete proposal.