Flake8 plugin to detect (too) common mistakes and bad practices in Tkinter projects
Project description
flake8-tkinter
Flake8 plugin to detect (too) common mistakes and bad practices in Tkinter projects
List of warnings
TK102
Don't call mainloop
multiple times, as it's totally unnecessary
def func():
top = tk.Toplevel()
- top.mainloop()
root.mainloop()
TK111
Calling a function instead of passing the reference for command
argument
- ttk.Button(command=foo())
+ ttk.Button(command=foo)
TK112
Calling a function with arguments instead of using a lambda or a partial function and passing the reference for command
argument
- ttk.Button(command=foo(bar, baz))
+ ttk.Button(command=lambda: foo(bar, baz))
TK201
Don't use from tkinter import *
- from tkinter import *
+ import tkinter
# OR
+ import tkinter as tk
TK202
Don't use from tkinter.ttk import *
- from tkinter.ttk import *
+ from tkinter import ttk
TK211
import tkinter.ttk as ttk
is pointless
- import tkinter.ttk as ttk
+ from tkinter import ttk
TK221
Don't use dumb tkinter constants, use booleans instead
- w.pack(expand=tk.TRUE)
+ w.pack(expand=True)
- w.pack(expand=tk.FALSE)
+ w.pack(expand=False)
- w.pack(expand=tk.YES)
+ w.pack(expand=True)
- w.pack(expand=tk.NO)
+ w.pack(expand=False)
- w.pack(expand=tk.ON)
+ w.pack(expand=True)
- w.pack(expand=tk.OFF)
+ w.pack(expand=False)
TK231
Use add=True
or explicit add=False
in bindings
- w.bind("<Button-1>, foo)
+ w.bind("<Button-1>, foo, add=True)
# OR
+ w.bind("<Button-1>, foo, add=False)
TK232
Creating tag bindings in a loop can lead to memory leaks, because the created Tcl commands won't be cleaned up when deleting the tag
for index, foo in enumerate(foos):
- w.tag_bind(f"bar_{index}", "<Button-1>, baz)
+ tcl_command = w.tag_bind(f"bar_{index}", "<Button-1>, baz)
+ bindings.append(tcl_command) # Clean them up later with `.deletecommand()`
TK304
Don't use things like add="+"
. Use a boolean instead
- w.bind("<Button-1>, foo, add="+")
+ w.bind("<Button-1>, foo, add=True)
More planned warnings
-
Common mistakes
- Warn when assigning to result of
w.pack()
|w.grid()
|w.place()
call (None
) (TK131) - Warn when using more than one
Tk
instance: child windows must be created fromToplevel
class (TK101) - Warn when using more than one
mainloop()
call (TK102) - Suggest using
w.after(ms)
instead oftime.sleep(s)
(TK121) - Suggest keeping reference of local
PhotoImage
instance to avoid GC (TK141) - Suggest refactoring code that uses
w.update
, as it's usually pointless, potentially harmful, and considered a code smell (TK103) - Warn when using a float as
Text
widget index (TK132) - Infinite loop in a handler - propose to use recursive function with
w.after
(TK122) - Warn when calling the function inline, instead of just referencing it (TK111)
- Suggest using a lambda function when args are passed to inline calls (TK112)
- Warn when assigning to result of
-
Common best practices
- Warn on
from tkinter import *
, suggest usingimport tkinter
orimport tkinter as tk
instead (TK201) - Warn on
from tkinter.ttk import *
, suggest usingfrom tkinter import ttk
instead (TK202) - Warn on
import tkinter.ttk as ttk
, asfrom tkinter import ttk
is simpler (TK211) - Suggest changing
tk.TRUE
andtk.FALSE
toTrue
andFalse
, as there's really no reason for using these constants instead of booleans (TK221) - Suggest using
tk.NSEW
instead oftk.N+tk.S+tk.E+tk.W
, and other combinations (TK222) - A widget is created without a parent container specified, and there is a container in the same scope (
tk.Toplevel
ortk.Frame
), or the widget is created in a method a subclass oftk.Tk
,tk.Toplevel
ortk.Frame
(TK232) - Warn when a huge app isn't OO (?)
- Warn when not using
add=True
or explicitadd=False
in bindings (TK231) - Warn when using
tag_bind
inside a loop, but not storing the Tcl command (can cause memory leaks later) (TK232)
- Warn on
-
Opinionated suggestions
- Suggest changing things like
root.wm_title()
toroot.title()
(tho I usewm_
quite often) (TK305) - Warn when calling
mainloop()
on something other than the root window (TK303) - Suggest using more clear binding sequences, like
<Button-1>
instead of<1>
and<Key-a>
instead of<a>
(TK301) - Warn if a parent is not specified (?) (TK306)
- Prefer to use more readable
widget.config(property=value)
instead ofwidget["property"] = value
(TK302) - Suggest changing tkinter constants to string literals (this option should be disabled by default) (TK307)
- Warn when using
add="+"
in bindings, use a boolean instead (TK304)
- Suggest changing things like
Development
- Clone the repo
- Set up a virtual environment, activate, and install
flake8
andpytest
in it - Run
pip install -e .
to installflake8-tkinter
in editable format - Run
python3 -m pytest
to test your changes
Credits
The idea of this project is by @insolor
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.