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
Installation
pip install flake8-tkinter
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))
TK131
Don't assign to w.grid()
/ w.pack()
/ w.place()
, it's return value is None
- btn = ttk.Button().grid()
+ btn = ttk.Button()
+ btn.grid()
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_attributes
quite often, probably that should be an exception) (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.
Source Distribution
File details
Details for the file flake8_tkinter-0.5.0.tar.gz
.
File metadata
- Download URL: flake8_tkinter-0.5.0.tar.gz
- Upload date:
- Size: 10.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.13
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 733127d17679f17b2f3aec6d805afaac4df5252606a646f89230264f6570c6cb |
|
MD5 | ceab8e55140fe632ee4bf0704e82185a |
|
BLAKE2b-256 | 924c2ee4cd01c6be9aaff033014da3187e23d77a0c5825d7f64d5fe6cbd4a577 |