Skip to content

Commit 260ce41

Browse files
committed
Minor cleanup
1 parent 80146db commit 260ce41

File tree

3 files changed

+60
-41
lines changed

3 files changed

+60
-41
lines changed

src/idlemypyextension/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def fake_mainloop(tk_root: tk.Tk) -> None:
109109
assert isinstance(pyshell_window, pyshell.PyShellEditorWindow)
110110

111111
if not pyshell_window.extensions:
112-
# No extensions loadex, close.
112+
# No extensions loaded, close.
113113
pyshell.root.destroy()
114114
pyshell.capture_warnings(False)
115115
return 1

src/idlemypyextension/extension.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from idlemypyextension import annotate, client, tktrio, utils
4040

4141
if TYPE_CHECKING:
42-
from collections.abc import Callable
42+
from collections.abc import Callable, Sequence
4343
from idlelib.pyshell import PyShellEditorWindow
4444
from tkinter import Event, Misc
4545

@@ -135,26 +135,31 @@ class idlemypyextension(utils.BaseExtension): # noqa: N801
135135

136136
__slots__ = ("triorun",)
137137
# Extend the file and format menus.
138-
menudefs: ClassVar = [
138+
menudefs: ClassVar[
139+
Sequence[tuple[str, Sequence[tuple[str, str] | None]]]
140+
] = (
139141
(
140142
"edit",
141-
[
143+
(
142144
None,
143145
("_Type Check File", "<<type-check>>"),
144146
("Find Next Type Comment", "<<find-next-type-comment>>"),
145-
],
147+
),
146148
),
147149
(
148150
"format",
149-
[
151+
(
150152
("Suggest Signature", "<<suggest-signature>>"),
151153
("Remove Type Comments", "<<remove-type-comments>>"),
152-
],
154+
),
153155
),
154-
("run", [("Shutdown dmypy daemon", "<<shutdown-dmypy-daemon>>")]),
155-
]
156+
(
157+
"run",
158+
(("Shutdown dmypy daemon", "<<shutdown-dmypy-daemon>>"),),
159+
),
160+
)
156161
# Default values for configuration file
157-
values: ClassVar = {
162+
values: ClassVar[dict[str, str]] = {
158163
"enable": "True",
159164
"enable_editor": "True",
160165
"enable_shell": "False",
@@ -165,7 +170,7 @@ class idlemypyextension(utils.BaseExtension): # noqa: N801
165170
"action_max_sec": "None",
166171
}
167172
# Default key binds for configuration file
168-
bind_defaults: ClassVar = {
173+
bind_defaults: ClassVar[dict[str, str | None]] = {
169174
"type-check": "<Alt-Key-t>",
170175
"suggest-signature": "<Alt-Key-s>",
171176
"remove-type-comments": "<Alt-Shift-Key-T>",

src/idlemypyextension/utils.py

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
__author__ = "CoolCat467"
2525
__license__ = "GNU General Public License Version 3"
2626

27+
import importlib
2728
import sys
2829
import time
2930
import traceback
@@ -62,7 +63,7 @@ def set_title(title: str) -> None:
6263

6364
def get_required_config(
6465
values: dict[str, str],
65-
bind_defaults: dict[str, str],
66+
bind_defaults: dict[str, str | None],
6667
extension_title: str,
6768
) -> str:
6869
"""Get required configuration file data."""
@@ -79,7 +80,9 @@ def get_required_config(
7980
config += "\n"
8081
# Get key bindings data
8182
settings = "\n".join(
82-
f"{event} = {key}" for event, key in bind_defaults.items()
83+
f"{event} = {key}"
84+
for event, key in bind_defaults.items()
85+
if key is not None
8386
)
8487
if settings:
8588
config += f"\n[{extension_title}_cfgBindings]\n{settings}"
@@ -89,7 +92,7 @@ def get_required_config(
8992
def check_installed(
9093
extension: str,
9194
version: str,
92-
cls: type[BaseExtension] | None,
95+
cls: type[BaseExtension] | None = None,
9396
) -> bool:
9497
"""Make sure extension installed. Return True if installed correctly."""
9598
# Get list of system extensions
@@ -108,31 +111,31 @@ def check_installed(
108111

109112
if cls is None:
110113
# Import extension
111-
module = __import__(extension)
114+
module = importlib.import_module(extension)
112115

113116
# Get extension class
114117
if not hasattr(module, extension):
115118
print(
116-
f"ERROR: Somehow, {__title__} was installed improperly, "
117-
f"no {__title__} class found in module. Please report "
119+
f"ERROR: Somehow, {extension} was installed improperly, "
120+
f"no {extension} class found in module. Please report "
118121
"this on github.",
119122
file=sys.stderr,
120123
)
121-
sys.exit(1)
124+
return False
122125

123126
cls = getattr(module, extension)
124-
if not issubclass(cls, BaseExtension):
125-
raise ValueError(f"Expected BaseExtension subclass, got {cls!r}")
126-
127-
# Get extension class keybinding defaults
128-
required_config = get_required_config(
129-
getattr(cls, "values", {}),
130-
getattr(cls, "bind_defaults", {}),
131-
extension,
132-
)
127+
# if not issubclass(cls, BaseExtension):
128+
# raise ValueError(f"Expected BaseExtension subclass, got {cls!r}")
133129

134130
# If this extension not in there,
135131
if extension not in extensions:
132+
# Get extension class keybinding defaults
133+
required_config = get_required_config(
134+
getattr(cls, "values", {}),
135+
getattr(cls, "bind_defaults", {}),
136+
extension,
137+
)
138+
136139
# Tell user how to add it to system list.
137140
print(f"{extension} not in system registered extensions!")
138141
print(
@@ -266,11 +269,12 @@ def ensure_section_exists(section: str) -> bool:
266269

267270
def ensure_values_exist_in_section(
268271
section: str,
269-
values: dict[str, str],
272+
values: dict[str, str | None] | dict[str, str],
270273
) -> bool:
271274
"""For each key in values, make sure key exists. Return if edited.
272275
273-
If not, create and set to value.
276+
If key does not exist and default value is not None, create and set
277+
to value.
274278
"""
275279
need_save = False
276280
for key, default in values.items():
@@ -287,7 +291,10 @@ def ensure_values_exist_in_section(
287291

288292

289293
def ask_save_dialog(parent: Text) -> bool:
290-
"""Ask to save dialog stolen from idlelib.runscript.ScriptBinding."""
294+
"""Ask to save dialog. Return if ok to save.
295+
296+
Stolen from idlelib.runscript.ScriptBinding.
297+
"""
291298
msg = "Source Must Be Saved\n" + 5 * " " + "OK to Save?"
292299
confirm: bool = messagebox.askokcancel(
293300
title="Save Before Run or Check",
@@ -359,7 +366,7 @@ def temporary_overwrite(
359366

360367

361368
def extension_log(content: str) -> None:
362-
"""Log content to extension log."""
369+
"""Log content to extension log file."""
363370
if not LOGS_PATH.exists():
364371
LOGS_PATH.mkdir(exist_ok=True)
365372
log_file = LOGS_PATH / f"{TITLE}.log"
@@ -419,17 +426,19 @@ class BaseExtension:
419426
)
420427

421428
# Extend the file and format menus.
422-
menudefs: ClassVar = []
429+
menudefs: ClassVar[
430+
Sequence[tuple[str, Sequence[tuple[str, str] | None]]]
431+
] = ()
423432

424433
# Default values for configuration file
425-
values: ClassVar = {
434+
values: ClassVar[dict[str, str]] = {
426435
"enable": "True",
427436
"enable_editor": "True",
428437
"enable_shell": "False",
429438
}
430439

431440
# Default key binds for configuration file
432-
bind_defaults: ClassVar = {}
441+
bind_defaults: ClassVar[dict[str, str | None]] = {}
433442

434443
def __init__(
435444
self,
@@ -449,9 +458,18 @@ def __init__(
449458
comment_prefix = f"{self.__class__.__name__}"
450459
self.comment_prefix = f"# {comment_prefix}: "
451460

452-
# Bind non-keyboard triggered events, as IDLE only binds
453-
# keyboard events automatically.
454-
for bind_name, key in self.bind_defaults.items():
461+
self.bind_non_keyboard(self.bind_defaults)
462+
463+
def __repr__(self) -> str:
464+
"""Return representation of self."""
465+
return f"{self.__class__.__name__}({self.editwin!r})"
466+
467+
def bind_non_keyboard(self, bind_defaults: dict[str, str | None]) -> None:
468+
"""Bind non-keyboard triggered events.
469+
470+
IDLE only binds keyboard events automatically.
471+
"""
472+
for bind_name, key in bind_defaults.items():
455473
if key is not None:
456474
continue
457475
bind_func_name = bind_name.replace("-", "_") + "_event"
@@ -462,10 +480,6 @@ def __init__(
462480
raise ValueError(f"{bind_func_name} should be callable")
463481
self.text.bind(f"<<{bind_name}>>", bind_func)
464482

465-
def __repr__(self) -> str:
466-
"""Return representation of self."""
467-
return f"{self.__class__.__name__}({self.editwin!r})"
468-
469483
@classmethod
470484
def ensure_bindings_exist(cls) -> bool:
471485
"""Ensure key bindings exist in user extensions configuration.

0 commit comments

Comments
 (0)