Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. PyQt: Mixin that inherits from typing.Protocol : metaclass conflict: must be a subclass of the metaclasses of all its bases
Forum Updated to NodeBB v4.3 + New Features

PyQt: Mixin that inherits from typing.Protocol : metaclass conflict: must be a subclass of the metaclasses of all its bases

Scheduled Pinned Locked Moved Unsolved Qt for Python
2 Posts 2 Posters 568 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    hakonhagland
    wrote on last edited by
    #1

    I am using PyQt and mypy for type checking. When I create a mixin class for a QWidget or a QMainWindow I use typing.Protocol to satisfy mypy, but then I get a run time error instead:

    $ ./main.py 
    Traceback (most recent call last):
      File "/home/hakon/test/python/pyqt/./main.py", line 8, in <module>
        from window import Window
      File "/home/hakon/test/python/pyqt/window.py", line 7, in <module>
        class Window(QMainWindow, ResizeWindowMixin):
    TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
    

    main.py:

    #! /usr/bin/env python3
    
    import logging
    import sys
    
    from PyQt6.QtWidgets import QApplication
    
    from window import Window
    
    def main() -> None:
        logging.basicConfig(level=logging.INFO)
        app = QApplication(sys.argv)
        config = {'X': '100', 'Y': '100', 'Width': '500', 'Height': '500'}
        window = Window(config)
        window.show()
        app.exec()
    
    if __name__ == "__main__":
        main()
    

    window.py:

    from mixin import ResizeWindowMixin
    
    from PyQt6.QtWidgets import QLabel, QVBoxLayout, QMainWindow
    
    class Window(QMainWindow, ResizeWindowMixin):
        def __init__(self, config: dict[str, str]) -> None:
            super().__init__()
            self.window_config = config
            self.fontsize = self.window_config["FontSize"]
            self.setWindowTitle("Test Window")
            layout = QVBoxLayout()
            layout.addWidget(QLabel("Hello world!"))
            self.setLayout(layout)
            self.resize_window_from_config()
    

    mixin.py:

    from typing import Protocol
    
    # from PyQt6.QtCore import QMetaObject
    
    class ConfigWindow(Protocol):
        window_config: dict[str, str]
    
        def move(self, x: int, y: int) -> None:
            ...
    
        def resize(self, w: int, h: int) -> None:
            ...
    
    
    class ResizeWindowMixin(ConfigWindow):
        def resize_window_from_config(self: ConfigWindow) -> None:
            if ("X" in self.window_config) and ("Y" in self.window_config):
                self.move(
                    int(self.window_config["X"]),
                    int(self.window_config["Y"]),
                )
            self.resize(int(self.window_config["Width"]), int(self.window_config["Height"]))
    

    How to resolve this issue?
    Note: also posted on stackoverflow: https://stackoverflow.com/q/77543597/2173773

    JonBJ 1 Reply Last reply
    0
    • H hakonhagland

      I am using PyQt and mypy for type checking. When I create a mixin class for a QWidget or a QMainWindow I use typing.Protocol to satisfy mypy, but then I get a run time error instead:

      $ ./main.py 
      Traceback (most recent call last):
        File "/home/hakon/test/python/pyqt/./main.py", line 8, in <module>
          from window import Window
        File "/home/hakon/test/python/pyqt/window.py", line 7, in <module>
          class Window(QMainWindow, ResizeWindowMixin):
      TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
      

      main.py:

      #! /usr/bin/env python3
      
      import logging
      import sys
      
      from PyQt6.QtWidgets import QApplication
      
      from window import Window
      
      def main() -> None:
          logging.basicConfig(level=logging.INFO)
          app = QApplication(sys.argv)
          config = {'X': '100', 'Y': '100', 'Width': '500', 'Height': '500'}
          window = Window(config)
          window.show()
          app.exec()
      
      if __name__ == "__main__":
          main()
      

      window.py:

      from mixin import ResizeWindowMixin
      
      from PyQt6.QtWidgets import QLabel, QVBoxLayout, QMainWindow
      
      class Window(QMainWindow, ResizeWindowMixin):
          def __init__(self, config: dict[str, str]) -> None:
              super().__init__()
              self.window_config = config
              self.fontsize = self.window_config["FontSize"]
              self.setWindowTitle("Test Window")
              layout = QVBoxLayout()
              layout.addWidget(QLabel("Hello world!"))
              self.setLayout(layout)
              self.resize_window_from_config()
      

      mixin.py:

      from typing import Protocol
      
      # from PyQt6.QtCore import QMetaObject
      
      class ConfigWindow(Protocol):
          window_config: dict[str, str]
      
          def move(self, x: int, y: int) -> None:
              ...
      
          def resize(self, w: int, h: int) -> None:
              ...
      
      
      class ResizeWindowMixin(ConfigWindow):
          def resize_window_from_config(self: ConfigWindow) -> None:
              if ("X" in self.window_config) and ("Y" in self.window_config):
                  self.move(
                      int(self.window_config["X"]),
                      int(self.window_config["Y"]),
                  )
              self.resize(int(self.window_config["Width"]), int(self.window_config["Height"]))
      

      How to resolve this issue?
      Note: also posted on stackoverflow: https://stackoverflow.com/q/77543597/2173773

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @hakonhagland
      For PyQt you will surely get answer from the PyQt mailing list if you do not elsewhere.

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved