TypeError: Error when calling the metaclass bases function() argument 1 must be code, not str 7


Cette erreur est souvent déclenchée quand on essaye d’hériter d’une fonction au lieu d’une classe. Cela peut arriver par erreur avec des fonctions qui sont nommées en CamelCase, en dépit du PEP8.

Par exemple:

class Truc(threading.Condition):
    pass
 
class Machine(tempfile.NamedTemporaryFile):
    pass

Lèveront l’exception :

TypeError: Error when calling the metaclass bases 
    function() argument 1 must be code, not str

Car:

>>> import threading, tempfile
>>> type(threading.Condition)
<type 'function'>
>>> type(tempfile.NamedTemporaryFile)
<type 'function'>

Malgré leurs noms en majuscule.

Le message d’erreur est lui-même complètement obscure. Bref, le genre de truc qui est 100% lié à des erreurs d’autres personnes que vous aller payer par une après-midi de debug si on ne vous donne pas la solution.

Mais bon, la queue de celui qui n’a jamais pourri l’après-midi d’un autre codeur avec son travail merdique jette le premier parpaing.

7 thoughts on “TypeError: Error when calling the metaclass bases function() argument 1 must be code, not str

  • Etienne

    Ah bon? Ça veut dire que tu fies au nom d’un truc pour savoir si ce truc est une fonction ou une classe? Tu va pas jeter un oeil sur le code avant d’essayer d’en hériter? Comme ça, franco: “Ah ben ce truc là, je vais lui ajouter une méthode qu’elle me manque cette méthode”.

    Question de bleu, hein, ça m’étonne… Je me demande dans quelle situation ça peu se passer…

  • Sam Post author

    Oui, c’est une convention de mettre le nom d’une classe en CamelCase (à l’exception des types built-in) donc on gagne du temps en partant du principe que les gens respectent la convention.

    Outre le fait qu’on ne peut pas toujours voir le code source facilement (par exemple, si c’est une classe C), on a en a pas forcément besoin. Dans mon use case en particulier j’ai voulu hériter de NamedTemporaryFile uniquement pour donner à ma classe un type acceptable pour une certaine lib. Je me foutais complètement du code. Mais tu vois, j’ai bien été obligé d’aller voir finalement :-)

    Moralité : soit feignant, tu vivras content, jusqu’à ce que tu l’ais dedans.

  • Jivay

    J’ai eu ce problème sur Django en me plantant sur les decorators sur des CBV. Evidemment le fait de mettre un @login_required sur une classe, qui plus est si elle est étendue plus tard, fait tout planter. Du coup la solution que j’ai trouvé a été d’utiliser ça :

    @method_decorator(login_required)

    def dispatch(self, request, *args, **kwargs):

    return super().dispatch(self, request, *args, **kwargs)

Leave a comment

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.