Search code examples
pythontkinterpycharmttkbootstrap

Unexpected argument in PyCharm for the ttkbootstrap bootstyle argument


I got an "Unexpected argument" warning in PyCharm when using the ttkbootstrap's bootstyle argument.

The following code works but I couldn't fix the warning.

import ttkbootstrap as ttk
from ttkbootstrap.constants import *

root = ttk.Window()

b1 = ttk.Button(root, text="Button 1", bootstyle=SUCCESS)
b1.pack(side=LEFT, padx=5, pady=10)

b2 = ttk.Button(root, text="Button 2", bootstyle=(INFO, OUTLINE))
b2.pack(side=LEFT, padx=5, pady=10)

root.mainloop()

Solution

  • Use style instead like so. No warning in pycharm and works like a charm:

        b1 = ttk.Button(root, text="Button 1", style=SUCCESS)
        b1.pack(side=LEFT, padx=5, pady=10)
    
        b2 = ttk.Button(root, text="Button 2", style=f'{INFO},{OUTLINE}')
        b2.pack(side=LEFT, padx=5, pady=10)
    
        b3 = ttk.Button(root, text="Button 2", style=f'{TTK_DEFAULT}, {OUTLINE}')
        b3.pack(side=LEFT, padx=5, pady=10)
    

    However, this is not a recommended use of ttkbootstrap as per the tutorial, which brings bootstyle parameter, a replacement for style.

    The reason behind the PyCharm warning stands in the way how ttkbootstrap is designed and implemented. On first glance, the ttkbootstrap.Button is a class of ttk.Button, and this is what PyCharm sees and utilizes for Warnings about correct/incorrect params. However, during the runtime, the import ttkbootstrap overrides the widgets constructors by its own ttkbootstrap generic constructor adding the bootstyle param.

    The runtime constructor for ttkbootstrap widgets:

        @staticmethod
        def override_ttk_widget_constructor(func):
            """Override widget constructors with bootstyle api options.
    
            Parameters:
    
                func (Callable):
                    The widget class `__init__` method
            """
    
            def __init__(self, *args, **kwargs):
    
                # capture bootstyle and style arguments
                if "bootstyle" in kwargs:
                    bootstyle = kwargs.pop("bootstyle")
                else:
                    bootstyle = ""
    
                if "style" in kwargs:
                    style = kwargs.pop("style") or ""
                else:
                    style = ""
        ...
    

    The style/bootstyle are both used.

    While one could argue this implementation is elegant in my opinion it brings confusion and makes IDEs such as PyCharm trigger false Warnings.