-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
215 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ | |
|
||
from .visitor import Visitor | ||
|
||
__version__ = "0.2.3" | ||
__version__ = "0.2.4" | ||
|
||
|
||
@dataclass(frozen=True) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from __future__ import annotations | ||
|
||
import ast | ||
|
||
from .data import is_from_tkinter | ||
from .TK111 import TK111 | ||
from .TK231 import BIND_METHODS | ||
|
||
COMMAND_ARGS = {"command", "xscrollcommand", "yscrollcommand", "postcommand"} | ||
CONFIG_METHODS = {"config", "configure"} | ||
|
||
|
||
def is_partial(func: ast.Name | ast.Attribute) -> bool: | ||
if isinstance(func, ast.Name): | ||
return func.id in ("partial", "partialmethod") | ||
elif isinstance(func, ast.Attribute): | ||
return f"{func.value.id}.{func.attr}" in ( | ||
"functools.partial", | ||
"functools.partialmethod", | ||
) | ||
|
||
return False | ||
|
||
|
||
class TK112(TK111): | ||
message = " If you need to call '{handler}' with arguments, use lambda or functools.partial." | ||
message_on_command_arg = ( | ||
"Calling '{handler}()' with arguments instead of referencing it for '{argument}'." | ||
) | ||
message_on_bind = "Calling '{handler}()' with arguments instead of referencing it for bind." | ||
|
||
@staticmethod | ||
def detect(node: ast.Call) -> bool: | ||
if not isinstance(node.func.value, ast.Name): | ||
return | ||
|
||
if is_from_tkinter(node.func.value.id) or node.func.attr in CONFIG_METHODS: | ||
for keyword in node.keywords: | ||
func = keyword.value | ||
return ( | ||
keyword.arg in COMMAND_ARGS | ||
and isinstance(func, ast.Call) | ||
and (func.args or func.keywords) | ||
and not is_partial(func.func) | ||
) | ||
elif node.func.attr in BIND_METHODS and len(node.args) >= 2: | ||
func = node.args[1] | ||
return ( | ||
isinstance(func, ast.Call) | ||
and (func.args or func.keywords) | ||
and not is_partial(func.func) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from base import lint | ||
|
||
|
||
def test_command_arg_function_call_with_plain_tkinter(): | ||
code = "import tkinter as tk;tk.Button(command=handler())" | ||
assert lint(code) == { | ||
"1:40 TK111 Calling 'handler()' instead of referencing it for 'command'. Perhaps you meant 'command=handler' (without the parentheses)?" | ||
} | ||
|
||
|
||
def test_command_arg_function_call_with_ttk(): | ||
code = "from tkinter import ttk;ttk.Button(command=handler())" | ||
assert lint(code) == { | ||
"1:44 TK111 Calling 'handler()' instead of referencing it for 'command'. Perhaps you meant 'command=handler' (without the parentheses)?" | ||
} | ||
|
||
|
||
def test_command_arg_function_call_in_config(): | ||
code = "w.config(command=handler())" | ||
assert lint(code) == { | ||
"1:18 TK111 Calling 'handler()' instead of referencing it for 'command'. Perhaps you meant 'command=handler' (without the parentheses)?" | ||
} | ||
|
||
|
||
def test_bind_function_call(): | ||
code = "w.bind('<Button-1>', handler(), add=True)" | ||
assert lint(code) == { | ||
"1:22 TK111 Calling 'handler()' instead of referencing it for bind. Perhaps you meant 'handler' (without the parentheses)?" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from base import lint | ||
|
||
|
||
def test_command_arg_function_call_with_args_with_plain_tkinter(): | ||
code = "import tkinter as tk;tk.Button(command=handler(foo, bar))" | ||
assert lint(code) == { | ||
"1:40 TK112 Calling 'handler()' with arguments instead of referencing it for 'command'. If you need to call 'handler' with arguments, use lambda or functools.partial." | ||
} | ||
|
||
|
||
def test_command_arg_function_call_with_args_with_ttk(): | ||
code = "from tkinter import ttk;ttk.Button(command=handler(foo, bar))" | ||
assert lint(code) == { | ||
"1:44 TK112 Calling 'handler()' with arguments instead of referencing it for 'command'. If you need to call 'handler' with arguments, use lambda or functools.partial." | ||
} | ||
|
||
|
||
def test_command_arg_function_call_with_args_in_config(): | ||
code = "w.config(command=handler(foo, bar))" | ||
assert lint(code) == { | ||
"1:18 TK112 Calling 'handler()' with arguments instead of referencing it for 'command'. If you need to call 'handler' with arguments, use lambda or functools.partial." | ||
} | ||
|
||
|
||
def test_bind_function_call_with_args(): | ||
code = "w.bind('<Button-1>', handler(foo, bar), add=True)" | ||
assert lint(code) == { | ||
"1:22 TK112 Calling 'handler()' with arguments instead of referencing it for bind. If you need to call 'handler' with arguments, use lambda or functools.partial." | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
from base import _results | ||
from base import lint | ||
from flake8_tkinter.checkers.TK221 import DUMB_CONSTANTS | ||
|
||
|
||
def test_dumb_boolean_constants(): | ||
for constant in DUMB_CONSTANTS: | ||
code = f"import tkinter as tk\ntk.{constant}" | ||
assert _results(code) == { | ||
assert lint(code) == { | ||
f"2:1 TK221 Using tkinter.{constant} is pointless. Use an appropriate Python boolean instead." | ||
} |
Oops, something went wrong.