Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does Callable lack __module__?

I am making a logging decorator for functions in python:

import logging
from typing import Callable
from functools import wraps


def function_logging(fn: Callable) -> Callable:
    fn_logger = logging.getLogger(fn.__module__ + '.' + fn.__name__)

    @wraps(fn)
    def wrapper(*args, **kwargs):
        fn_logger.info("Args: {}".format(args))
        fn_logger.info("Kwargs: {}".format(kwargs))
        result = fn(*args, **kwargs)
        fn_logger.info("Return: {}".format(result))
        return result

    return wrapper

PyCharm's static analysis is telling me that I cannot expect a Callable to have the attribute __module__. So far I haven't encountered cases where this fails. Does anyone know under what circumstances one might encounter a Callable without the __module__ attribute?

like image 753
Harald Husum Avatar asked May 09 '19 14:05

Harald Husum


1 Answers

Here's an example:

list.__add__

That's a callable with no __module__. It's the unbound method for list concatenation.

In general, there's no requirement that callables have a __module__. It just has to be possible to call them. There's also no requirement that callables have a __name__, and for most callable types, it doesn't make sense to use functools.wraps with them.

Your decorator requires an instance of the ordinary Python function type; it cannot accept arbitrary callables. If you're going to give it type hints, you should hint it with that type:

def function_logging(fn: types.FunctionType) -> types.FunctionType:
    ...
like image 126
user2357112 supports Monica Avatar answered Oct 20 '22 17:10

user2357112 supports Monica