Skip to main content

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 oneTk instance: child windows must be created from Toplevel class (TK101)
    • Warn when using more than one mainloop() call (TK102)
    • Suggest using w.after(ms) instead of time.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)
  • Common best practices

    • Warn on from tkinter import *, suggest using import tkinter or import tkinter as tk instead (TK201)
    • Warn on from tkinter.ttk import *, suggest using from tkinter import ttk instead (TK202)
    • Warn on import tkinter.ttk as ttk, as from tkinter import ttk is simpler (TK211)
    • Suggest changing tk.TRUE and tk.FALSE to True and False, as there's really no reason for using these constants instead of booleans (TK221)
    • Suggest using tk.NSEW instead of tk.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 or tk.Frame), or the widget is created in a method a subclass of tk.Tk, tk.Toplevel or tk.Frame (TK232)
    • Warn when a huge app isn't OO (?)
    • Warn when not using add=True or explicit add=False in bindings (TK231)
    • Warn when using tag_bind inside a loop, but not storing the Tcl command (can cause memory leaks later) (TK232)
  • Opinionated suggestions

    • Suggest changing things like root.wm_title() to root.title() (tho I use wm_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 of widget["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)

Development

  1. Clone the repo
  2. Set up a virtual environment, activate, and install flake8 and pytest in it
  3. Run pip install -e . to install flake8-tkinter in editable format
  4. Run python3 -m pytest to test your changes

Credits

The idea of this project is by @insolor

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flake8_tkinter-0.5.0.tar.gz (10.0 kB view details)

Uploaded Source

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

Hashes for flake8_tkinter-0.5.0.tar.gz
Algorithm Hash digest
SHA256 733127d17679f17b2f3aec6d805afaac4df5252606a646f89230264f6570c6cb
MD5 ceab8e55140fe632ee4bf0704e82185a
BLAKE2b-256 924c2ee4cd01c6be9aaff033014da3187e23d77a0c5825d7f64d5fe6cbd4a577

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page