Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Altering traceback of a non-callable module

I'm a minor contributor to a package where people are meant to do this (Foo.Bar.Bar is a class):

>>> from Foo.Bar import Bar
>>> s = Bar('a')

Sometimes people do this by mistake (Foo.Bar is a module):

>>> from Foo import Bar   
>>> s = Bar('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'module' object is not callable

This might seems simple, but users still fail to debug it, I would like to make it easier. I can't change the names of Foo or Bar but I would like to add a more informative traceback like:

TypeError("'module' object is not callable, perhaps you meant to call 'Bar.Bar()'")

I read the Callable modules Q&A, and I know that I can't add a __call__ method to a module (and I don't want to wrap the whole module in a class just for this). Anyway, I don't want the module to be callable, I just want a custom traceback. Is there a clean solution for Python 3.x and 2.7+?

like image 344
Chris_Rands Avatar asked Jun 28 '18 15:06

Chris_Rands


People also ask

How do you fix a module object is not callable?

The Python "TypeError: 'module' object is not callable" occurs when we import a module as import some_module but try to call it as a function or class. To solve the error, use dot notation to access the specific function or class before calling it, e.g. module. my_func() .

How do you solve a tuple object is not callable?

The Python "TypeError: 'tuple' object is not callable" occurs when we try to call a tuple as if it were a function. To solve the error, make sure to use square brackets when accessing a tuple at a specific index, e.g. my_tuple[0] .

How do you make a function callable?

How to Make an Object Callable. Simply, you make an object callable by overriding the special method __call__() . __call__(self, arg1, .., argn, *args, **kwargs) : This method is like any other normal method in Python. It also can accept positional and arbitrary arguments.

What is TypeError str object is not callable?

The result was the TypeError: 'str' object is not callable error. This is happening because we are using a variable name that the compiler already recognizes as something different. To fix this, you can rename the variable to a something that isn't a predefined keyword in Python. Now the code works perfectly.


1 Answers

Add this to top of Bar.py: (Based on this question)

import sys

this_module = sys.modules[__name__]
class MyModule(sys.modules[__name__].__class__):
    def __call__(self, *a, **k):  # module callable
        raise TypeError("'module' object is not callable, perhaps you meant to call 'Bar.Bar()'")
    def __getattribute__(self, name):
        return this_module.__getattribute__(name)

sys.modules[__name__] = MyModule(__name__)


# the rest of file
class Bar:
    pass

Note: Tested with python3.6 & python2.7.

like image 166
Mohsenasm Avatar answered Oct 02 '22 14:10

Mohsenasm