Type error in __init__ when deriving from two metaclasses












0














I'd like to make class that derives from PyQt5 QtWidget.QWidget and an abc.ABCMeta. Both these classes have their own meta class as type so, according to this page and this SO question, I need to create my own meta class that derives from the meta classes of QWidget and abc.ABCMeta, and explicitly use that as metaclass for my class.



So far so good, I've defined an QtAbcMeta class and used this as metaclass for my ConcreteWidget class (see below).



import abc
from PyQt5 import QtWidgets, QtCore


class AbstractClass(metaclass=abc.ABCMeta):

def __init__(self, name):
self._name = name

@abc.abstractmethod
def myMethod():
pass


class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass


class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.


def myMethod():
print("My widget does something")


def main():
app = QtWidgets.QApplication()
myWidget = ConcreteWidget('my name', parent=None)

if __name__ == "__main__":
main()


However, when I try to call the __init__ method of the QtWidgets.QWidget method, to set the parent, I get the following TypeError:



Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'


I have no idea what's wrong here. Has the signature of QtWidgets.QWidget.__init__ changed somehow? Any help would be appreciated.










share|improve this question
























  • What is the purpose of AbstractClass.__init__(self, name)? The AbstractClass instance is not saved anywhere within ConcreteWidget.
    – John Gordon
    Oct 22 '18 at 15:07












  • In this MVCE the line AbstractClass.__init__(self, name) indeed does nothing. In my actual use case ConcreteWidget inherits from some ConcreteClass, that, in turn, inherits from AbstractClass. The __init__ method of ConcreteClass expected the name parameter.
    – titusjan
    Oct 22 '18 at 15:58
















0














I'd like to make class that derives from PyQt5 QtWidget.QWidget and an abc.ABCMeta. Both these classes have their own meta class as type so, according to this page and this SO question, I need to create my own meta class that derives from the meta classes of QWidget and abc.ABCMeta, and explicitly use that as metaclass for my class.



So far so good, I've defined an QtAbcMeta class and used this as metaclass for my ConcreteWidget class (see below).



import abc
from PyQt5 import QtWidgets, QtCore


class AbstractClass(metaclass=abc.ABCMeta):

def __init__(self, name):
self._name = name

@abc.abstractmethod
def myMethod():
pass


class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass


class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.


def myMethod():
print("My widget does something")


def main():
app = QtWidgets.QApplication()
myWidget = ConcreteWidget('my name', parent=None)

if __name__ == "__main__":
main()


However, when I try to call the __init__ method of the QtWidgets.QWidget method, to set the parent, I get the following TypeError:



Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'


I have no idea what's wrong here. Has the signature of QtWidgets.QWidget.__init__ changed somehow? Any help would be appreciated.










share|improve this question
























  • What is the purpose of AbstractClass.__init__(self, name)? The AbstractClass instance is not saved anywhere within ConcreteWidget.
    – John Gordon
    Oct 22 '18 at 15:07












  • In this MVCE the line AbstractClass.__init__(self, name) indeed does nothing. In my actual use case ConcreteWidget inherits from some ConcreteClass, that, in turn, inherits from AbstractClass. The __init__ method of ConcreteClass expected the name parameter.
    – titusjan
    Oct 22 '18 at 15:58














0












0








0







I'd like to make class that derives from PyQt5 QtWidget.QWidget and an abc.ABCMeta. Both these classes have their own meta class as type so, according to this page and this SO question, I need to create my own meta class that derives from the meta classes of QWidget and abc.ABCMeta, and explicitly use that as metaclass for my class.



So far so good, I've defined an QtAbcMeta class and used this as metaclass for my ConcreteWidget class (see below).



import abc
from PyQt5 import QtWidgets, QtCore


class AbstractClass(metaclass=abc.ABCMeta):

def __init__(self, name):
self._name = name

@abc.abstractmethod
def myMethod():
pass


class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass


class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.


def myMethod():
print("My widget does something")


def main():
app = QtWidgets.QApplication()
myWidget = ConcreteWidget('my name', parent=None)

if __name__ == "__main__":
main()


However, when I try to call the __init__ method of the QtWidgets.QWidget method, to set the parent, I get the following TypeError:



Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'


I have no idea what's wrong here. Has the signature of QtWidgets.QWidget.__init__ changed somehow? Any help would be appreciated.










share|improve this question















I'd like to make class that derives from PyQt5 QtWidget.QWidget and an abc.ABCMeta. Both these classes have their own meta class as type so, according to this page and this SO question, I need to create my own meta class that derives from the meta classes of QWidget and abc.ABCMeta, and explicitly use that as metaclass for my class.



So far so good, I've defined an QtAbcMeta class and used this as metaclass for my ConcreteWidget class (see below).



import abc
from PyQt5 import QtWidgets, QtCore


class AbstractClass(metaclass=abc.ABCMeta):

def __init__(self, name):
self._name = name

@abc.abstractmethod
def myMethod():
pass


class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass


class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.


def myMethod():
print("My widget does something")


def main():
app = QtWidgets.QApplication()
myWidget = ConcreteWidget('my name', parent=None)

if __name__ == "__main__":
main()


However, when I try to call the __init__ method of the QtWidgets.QWidget method, to set the parent, I get the following TypeError:



Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'


I have no idea what's wrong here. Has the signature of QtWidgets.QWidget.__init__ changed somehow? Any help would be appreciated.







python pyqt pyqt5 metaclass






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 '18 at 4:27









eyllanesc

74.4k103156




74.4k103156










asked Oct 22 '18 at 14:54









titusjan

3,15511124




3,15511124












  • What is the purpose of AbstractClass.__init__(self, name)? The AbstractClass instance is not saved anywhere within ConcreteWidget.
    – John Gordon
    Oct 22 '18 at 15:07












  • In this MVCE the line AbstractClass.__init__(self, name) indeed does nothing. In my actual use case ConcreteWidget inherits from some ConcreteClass, that, in turn, inherits from AbstractClass. The __init__ method of ConcreteClass expected the name parameter.
    – titusjan
    Oct 22 '18 at 15:58


















  • What is the purpose of AbstractClass.__init__(self, name)? The AbstractClass instance is not saved anywhere within ConcreteWidget.
    – John Gordon
    Oct 22 '18 at 15:07












  • In this MVCE the line AbstractClass.__init__(self, name) indeed does nothing. In my actual use case ConcreteWidget inherits from some ConcreteClass, that, in turn, inherits from AbstractClass. The __init__ method of ConcreteClass expected the name parameter.
    – titusjan
    Oct 22 '18 at 15:58
















What is the purpose of AbstractClass.__init__(self, name)? The AbstractClass instance is not saved anywhere within ConcreteWidget.
– John Gordon
Oct 22 '18 at 15:07






What is the purpose of AbstractClass.__init__(self, name)? The AbstractClass instance is not saved anywhere within ConcreteWidget.
– John Gordon
Oct 22 '18 at 15:07














In this MVCE the line AbstractClass.__init__(self, name) indeed does nothing. In my actual use case ConcreteWidget inherits from some ConcreteClass, that, in turn, inherits from AbstractClass. The __init__ method of ConcreteClass expected the name parameter.
– titusjan
Oct 22 '18 at 15:58




In this MVCE the line AbstractClass.__init__(self, name) indeed does nothing. In my actual use case ConcreteWidget inherits from some ConcreteClass, that, in turn, inherits from AbstractClass. The __init__ method of ConcreteClass expected the name parameter.
– titusjan
Oct 22 '18 at 15:58












2 Answers
2






active

oldest

votes


















1














QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super(), to ensure all the proper methods in all superclasses are called with their respective parameters.



The creation of super() has come around exactly to avoid the need to hard-code calls to super-classes __init__ (and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.



The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super again with the remaining parameters.
QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.



More than that, since Qt classes themselves make use of super, that means your __init__ in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.



So, just rewrite your __init__ method to do it in the "pythonic" way:



class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

def __init__(self, name, parent=None):
super().__init__(name=name, parent=parent)





share|improve this answer





























    1














    According to the docs you must pass all the arguments to QWidget although you do not require it:



    class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
    def __init__(self, name, parent=None):
    AbstractClass.__init__(self, name)
    QtWidgets.QWidget.__init__(self, name=name, parent=parent)





    share|improve this answer





















    • Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the super() construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
      – titusjan
      Nov 14 '18 at 9:42











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52932238%2ftype-error-in-init-when-deriving-from-two-metaclasses%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super(), to ensure all the proper methods in all superclasses are called with their respective parameters.



    The creation of super() has come around exactly to avoid the need to hard-code calls to super-classes __init__ (and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.



    The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super again with the remaining parameters.
    QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.



    More than that, since Qt classes themselves make use of super, that means your __init__ in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.



    So, just rewrite your __init__ method to do it in the "pythonic" way:



    class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

    def __init__(self, name, parent=None):
    super().__init__(name=name, parent=parent)





    share|improve this answer


























      1














      QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super(), to ensure all the proper methods in all superclasses are called with their respective parameters.



      The creation of super() has come around exactly to avoid the need to hard-code calls to super-classes __init__ (and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.



      The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super again with the remaining parameters.
      QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.



      More than that, since Qt classes themselves make use of super, that means your __init__ in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.



      So, just rewrite your __init__ method to do it in the "pythonic" way:



      class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

      def __init__(self, name, parent=None):
      super().__init__(name=name, parent=parent)





      share|improve this answer
























        1












        1








        1






        QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super(), to ensure all the proper methods in all superclasses are called with their respective parameters.



        The creation of super() has come around exactly to avoid the need to hard-code calls to super-classes __init__ (and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.



        The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super again with the remaining parameters.
        QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.



        More than that, since Qt classes themselves make use of super, that means your __init__ in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.



        So, just rewrite your __init__ method to do it in the "pythonic" way:



        class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

        def __init__(self, name, parent=None):
        super().__init__(name=name, parent=parent)





        share|improve this answer












        QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super(), to ensure all the proper methods in all superclasses are called with their respective parameters.



        The creation of super() has come around exactly to avoid the need to hard-code calls to super-classes __init__ (and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.



        The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super again with the remaining parameters.
        QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.



        More than that, since Qt classes themselves make use of super, that means your __init__ in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.



        So, just rewrite your __init__ method to do it in the "pythonic" way:



        class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):

        def __init__(self, name, parent=None):
        super().__init__(name=name, parent=parent)






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 13 '18 at 11:47









        jsbueno

        55.2k677128




        55.2k677128

























            1














            According to the docs you must pass all the arguments to QWidget although you do not require it:



            class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
            def __init__(self, name, parent=None):
            AbstractClass.__init__(self, name)
            QtWidgets.QWidget.__init__(self, name=name, parent=parent)





            share|improve this answer





















            • Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the super() construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
              – titusjan
              Nov 14 '18 at 9:42
















            1














            According to the docs you must pass all the arguments to QWidget although you do not require it:



            class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
            def __init__(self, name, parent=None):
            AbstractClass.__init__(self, name)
            QtWidgets.QWidget.__init__(self, name=name, parent=parent)





            share|improve this answer





















            • Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the super() construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
              – titusjan
              Nov 14 '18 at 9:42














            1












            1








            1






            According to the docs you must pass all the arguments to QWidget although you do not require it:



            class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
            def __init__(self, name, parent=None):
            AbstractClass.__init__(self, name)
            QtWidgets.QWidget.__init__(self, name=name, parent=parent)





            share|improve this answer












            According to the docs you must pass all the arguments to QWidget although you do not require it:



            class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
            def __init__(self, name, parent=None):
            AbstractClass.__init__(self, name)
            QtWidgets.QWidget.__init__(self, name=name, parent=parent)






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Oct 22 '18 at 15:03









            eyllanesc

            74.4k103156




            74.4k103156












            • Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the super() construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
              – titusjan
              Nov 14 '18 at 9:42


















            • Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the super() construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
              – titusjan
              Nov 14 '18 at 9:42
















            Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the super() construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
            – titusjan
            Nov 14 '18 at 9:42




            Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the super() construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
            – titusjan
            Nov 14 '18 at 9:42


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52932238%2ftype-error-in-init-when-deriving-from-two-metaclasses%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Berounka

            Sphinx de Gizeh

            Different font size/position of beamer's navigation symbols template's content depending on regular/plain...