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.
Il manque une queue à “que celui qui n’a….”
ça m’étonne de votre part !
Fixed.
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…
Une queue qui jette des parpaings! C’est ce que j’aime sur ce blog, on voit de tout.
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.
Moralité 2: les plumes ne font pas le canard
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)