flutter-dev 0.1.6__tar.gz → 0.1.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/CHANGELOG.md +7 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/PKG-INFO +12 -2
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/README.md +11 -1
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/gui.py +105 -24
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/pyproject.toml +1 -1
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/tests/test_gui.py +64 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/.env.example +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/LICENSE +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/MANIFEST.in +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/common_utils.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/core/__init__.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/core/constants.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/core/state.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/create_page.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/fdev.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/flutter_dev.egg-info/SOURCES.txt +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/gemini_api.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/git_diff_output_editor.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/install_legacy.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/__init__.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/ai.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/app.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/brew.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/build.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/datetime.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/device.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/doctor.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/git.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/git_account.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/localization.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/merge.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/mirror.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/package.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/project.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/managers/web_deploy.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/requirements.txt +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/setup.cfg +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/setup.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/switch_ai.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/tests/test_fdev_cli.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/tests/test_localization.py +0 -0
- {flutter_dev-0.1.6 → flutter_dev-0.1.7}/tests/test_package_commands.py +0 -0
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.1.7 - 2026-06-25
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Reworked the Tkinter dashboard to use classic Tk widgets with explicit colors so `fdev` stays visible on macOS Xcode/system Python runtimes that can render `ttk` widgets as a blank popup.
|
|
10
|
+
- Silenced the macOS system Tk deprecation warning before launching the dashboard.
|
|
11
|
+
|
|
5
12
|
## 0.1.6 - 2026-06-25
|
|
6
13
|
|
|
7
14
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flutter-dev
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: A cross-platform CLI toolkit for Flutter development workflows.
|
|
5
5
|
Author: Royal Court BD
|
|
6
6
|
License-Expression: MIT
|
|
@@ -42,7 +42,7 @@ The package is published on PyPI as `flutter-dev` and installs console commands
|
|
|
42
42
|
python -m pip install flutter-dev
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
Current package metadata declares version `0.1.
|
|
45
|
+
Current package metadata declares version `0.1.7`, Python `>=3.8`, MIT license, and support for macOS, Linux, and Windows.
|
|
46
46
|
|
|
47
47
|
## Key Features
|
|
48
48
|
|
|
@@ -433,6 +433,16 @@ fdev delete
|
|
|
433
433
|
|
|
434
434
|
Both commands print the detected OS and exact Python executable before running. They use that executable with `-m pip`, not a hardcoded `python`, `python3`, `pip`, or `pip3`, so the active venv/global Python that launched `fdev` is the environment that gets upgraded or deleted. On Windows, `fdev delete` and `fdev upgrade` schedule the same `sys.executable -m pip ...` operation in a delayed command process so the currently running console launcher can exit first.
|
|
435
435
|
|
|
436
|
+
### Blank Dashboard On macOS
|
|
437
|
+
|
|
438
|
+
If `fdev` prints an Xcode/system Tk warning or opens a blank dashboard, upgrade to `flutter-dev` 0.1.7 or newer:
|
|
439
|
+
|
|
440
|
+
```bash
|
|
441
|
+
fdev upgrade
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
`fdev` prints the Python executable it is using. If that path is `/Applications/Xcode.app/Contents/Developer/usr/bin/python3`, the CLI is running on Xcode's bundled Python and system Tk; 0.1.7 uses a more conservative Tk UI path for that runtime.
|
|
445
|
+
|
|
436
446
|
### Flutter Project Not Detected
|
|
437
447
|
|
|
438
448
|
Run project-specific commands from the directory that contains `pubspec.yaml`.
|
|
@@ -8,7 +8,7 @@ The package is published on PyPI as `flutter-dev` and installs console commands
|
|
|
8
8
|
python -m pip install flutter-dev
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Current package metadata declares version `0.1.
|
|
11
|
+
Current package metadata declares version `0.1.7`, Python `>=3.8`, MIT license, and support for macOS, Linux, and Windows.
|
|
12
12
|
|
|
13
13
|
## Key Features
|
|
14
14
|
|
|
@@ -399,6 +399,16 @@ fdev delete
|
|
|
399
399
|
|
|
400
400
|
Both commands print the detected OS and exact Python executable before running. They use that executable with `-m pip`, not a hardcoded `python`, `python3`, `pip`, or `pip3`, so the active venv/global Python that launched `fdev` is the environment that gets upgraded or deleted. On Windows, `fdev delete` and `fdev upgrade` schedule the same `sys.executable -m pip ...` operation in a delayed command process so the currently running console launcher can exit first.
|
|
401
401
|
|
|
402
|
+
### Blank Dashboard On macOS
|
|
403
|
+
|
|
404
|
+
If `fdev` prints an Xcode/system Tk warning or opens a blank dashboard, upgrade to `flutter-dev` 0.1.7 or newer:
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
fdev upgrade
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
`fdev` prints the Python executable it is using. If that path is `/Applications/Xcode.app/Contents/Developer/usr/bin/python3`, the CLI is running on Xcode's bundled Python and system Tk; 0.1.7 uses a more conservative Tk UI path for that runtime.
|
|
411
|
+
|
|
402
412
|
### Flutter Project Not Detected
|
|
403
413
|
|
|
404
414
|
Run project-specific commands from the directory that contains `pubspec.yaml`.
|
|
@@ -5,6 +5,7 @@ Small Tkinter GUI for running fdev commands with live logs.
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import os
|
|
8
9
|
import shlex
|
|
9
10
|
import subprocess
|
|
10
11
|
import sys
|
|
@@ -37,6 +38,21 @@ ANSI_COLORS = {
|
|
|
37
38
|
97: "bright_white",
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
UI_BG = "#f8fafc"
|
|
42
|
+
SIDEBAR_BG = "#e5e7eb"
|
|
43
|
+
PANEL_BG = "#ffffff"
|
|
44
|
+
TEXT_FG = "#111827"
|
|
45
|
+
MUTED_FG = "#475569"
|
|
46
|
+
BUTTON_BG = "#e2e8f0"
|
|
47
|
+
BUTTON_ACTIVE_BG = "#cbd5e1"
|
|
48
|
+
LOG_BG = "#111827"
|
|
49
|
+
LOG_FG = "#e5e7eb"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def prepare_tk_environment():
|
|
53
|
+
"""Prepare Tk for older macOS system Tk runtimes before importing tkinter."""
|
|
54
|
+
os.environ.setdefault("TK_SILENCE_DEPRECATION", "1")
|
|
55
|
+
|
|
40
56
|
|
|
41
57
|
def _apply_ansi_codes(codes: List[int], current_tag: Optional[str]) -> Optional[str]:
|
|
42
58
|
if not codes:
|
|
@@ -303,52 +319,73 @@ class FdevGui:
|
|
|
303
319
|
|
|
304
320
|
def _build_widgets(self):
|
|
305
321
|
import tkinter as tk
|
|
306
|
-
|
|
322
|
+
|
|
323
|
+
self.root.configure(bg=UI_BG)
|
|
307
324
|
|
|
308
325
|
self.root.columnconfigure(1, weight=1)
|
|
309
326
|
self.root.rowconfigure(0, weight=1)
|
|
310
327
|
|
|
311
|
-
sidebar =
|
|
328
|
+
sidebar = tk.Frame(self.root, bg=SIDEBAR_BG, padx=10, pady=10)
|
|
312
329
|
sidebar.grid(row=0, column=0, sticky="ns")
|
|
313
330
|
|
|
314
|
-
title =
|
|
331
|
+
title = tk.Label(
|
|
332
|
+
sidebar,
|
|
333
|
+
text="fdev",
|
|
334
|
+
font=("TkDefaultFont", 16, "bold"),
|
|
335
|
+
bg=SIDEBAR_BG,
|
|
336
|
+
fg=TEXT_FG,
|
|
337
|
+
)
|
|
315
338
|
title.grid(row=0, column=0, sticky="w", pady=(0, 10))
|
|
316
339
|
|
|
317
340
|
for index, section_name in enumerate(self.sections, start=1):
|
|
318
|
-
button =
|
|
341
|
+
button = tk.Button(
|
|
319
342
|
sidebar,
|
|
320
343
|
text=section_name,
|
|
321
344
|
command=lambda name=section_name: self._show_section(name),
|
|
345
|
+
bg=BUTTON_BG,
|
|
346
|
+
fg=TEXT_FG,
|
|
347
|
+
activebackground=BUTTON_ACTIVE_BG,
|
|
348
|
+
activeforeground=TEXT_FG,
|
|
349
|
+
relief="raised",
|
|
350
|
+
bd=1,
|
|
351
|
+
padx=10,
|
|
352
|
+
pady=4,
|
|
322
353
|
)
|
|
323
354
|
button.grid(row=index, column=0, sticky="ew", pady=3)
|
|
324
355
|
|
|
325
|
-
content =
|
|
356
|
+
content = tk.Frame(self.root, bg=UI_BG, padx=8, pady=10)
|
|
326
357
|
content.grid(row=0, column=1, sticky="nsew")
|
|
327
358
|
content.columnconfigure(0, weight=1)
|
|
328
359
|
content.rowconfigure(1, weight=1)
|
|
329
360
|
|
|
330
|
-
header =
|
|
361
|
+
header = tk.Frame(content, bg=UI_BG)
|
|
331
362
|
header.grid(row=0, column=0, sticky="ew", pady=(0, 8))
|
|
332
363
|
header.columnconfigure(0, weight=1)
|
|
333
364
|
|
|
334
|
-
self.section_label =
|
|
365
|
+
self.section_label = tk.Label(
|
|
366
|
+
header,
|
|
367
|
+
text="",
|
|
368
|
+
font=("TkDefaultFont", 14, "bold"),
|
|
369
|
+
bg=UI_BG,
|
|
370
|
+
fg=TEXT_FG,
|
|
371
|
+
)
|
|
335
372
|
self.section_label.grid(row=0, column=0, sticky="w")
|
|
336
373
|
|
|
337
|
-
self.status_label =
|
|
374
|
+
self.status_label = tk.Label(header, text="Ready", bg=UI_BG, fg=MUTED_FG)
|
|
338
375
|
self.status_label.grid(row=0, column=1, sticky="e")
|
|
339
376
|
|
|
340
|
-
body =
|
|
377
|
+
body = tk.Frame(content, bg=UI_BG)
|
|
341
378
|
body.grid(row=1, column=0, sticky="nsew")
|
|
342
379
|
body.columnconfigure(0, weight=1)
|
|
343
380
|
body.rowconfigure(0, weight=0)
|
|
344
381
|
body.rowconfigure(1, weight=1)
|
|
345
382
|
|
|
346
|
-
self.command_frame =
|
|
383
|
+
self.command_frame = tk.Frame(body, bg=UI_BG, pady=6)
|
|
347
384
|
self.command_frame.grid(row=0, column=0, sticky="ew")
|
|
348
385
|
self.command_frame.columnconfigure(0, weight=1)
|
|
349
386
|
self.command_frame.columnconfigure(1, weight=1)
|
|
350
387
|
|
|
351
|
-
log_frame =
|
|
388
|
+
log_frame = tk.Frame(body, bg=UI_BG)
|
|
352
389
|
log_frame.grid(row=1, column=0, sticky="nsew", pady=(6, 0))
|
|
353
390
|
log_frame.columnconfigure(0, weight=1)
|
|
354
391
|
log_frame.rowconfigure(0, weight=1)
|
|
@@ -358,31 +395,51 @@ class FdevGui:
|
|
|
358
395
|
height=12,
|
|
359
396
|
wrap="word",
|
|
360
397
|
state="disabled",
|
|
361
|
-
bg=
|
|
362
|
-
fg=
|
|
363
|
-
insertbackground=
|
|
398
|
+
bg=LOG_BG,
|
|
399
|
+
fg=LOG_FG,
|
|
400
|
+
insertbackground=LOG_FG,
|
|
401
|
+
relief="sunken",
|
|
402
|
+
bd=1,
|
|
364
403
|
)
|
|
365
404
|
self.log_text.grid(row=0, column=0, sticky="nsew")
|
|
366
405
|
|
|
367
|
-
scrollbar =
|
|
406
|
+
scrollbar = tk.Scrollbar(log_frame, orient="vertical", command=self.log_text.yview)
|
|
368
407
|
scrollbar.grid(row=0, column=1, sticky="ns")
|
|
369
408
|
self.log_text.configure(yscrollcommand=scrollbar.set)
|
|
370
409
|
self._configure_log_tags()
|
|
371
410
|
|
|
372
|
-
input_bar =
|
|
411
|
+
input_bar = tk.Frame(content, bg=UI_BG)
|
|
373
412
|
input_bar.grid(row=2, column=0, sticky="ew", pady=(8, 0))
|
|
374
413
|
input_bar.columnconfigure(0, weight=1)
|
|
375
414
|
|
|
376
|
-
self.input_entry =
|
|
415
|
+
self.input_entry = tk.Entry(input_bar, bg=PANEL_BG, fg=TEXT_FG, insertbackground=TEXT_FG)
|
|
377
416
|
self.input_entry.grid(row=0, column=0, sticky="ew", padx=(0, 6))
|
|
378
417
|
self.input_entry.bind("<Return>", lambda _event: self._send_input())
|
|
379
418
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
419
|
+
tk.Button(
|
|
420
|
+
input_bar,
|
|
421
|
+
text="Send Input",
|
|
422
|
+
command=self._send_input,
|
|
423
|
+
bg=BUTTON_BG,
|
|
424
|
+
activebackground=BUTTON_ACTIVE_BG,
|
|
425
|
+
).grid(row=0, column=1, padx=(0, 6))
|
|
426
|
+
tk.Button(
|
|
427
|
+
input_bar,
|
|
428
|
+
text="Stop",
|
|
429
|
+
command=self._stop_process,
|
|
430
|
+
bg=BUTTON_BG,
|
|
431
|
+
activebackground=BUTTON_ACTIVE_BG,
|
|
432
|
+
).grid(row=0, column=2, padx=(0, 6))
|
|
433
|
+
tk.Button(
|
|
434
|
+
input_bar,
|
|
435
|
+
text="Clear",
|
|
436
|
+
command=self._clear_log,
|
|
437
|
+
bg=BUTTON_BG,
|
|
438
|
+
activebackground=BUTTON_ACTIVE_BG,
|
|
439
|
+
).grid(row=0, column=3)
|
|
383
440
|
|
|
384
441
|
def _show_section(self, section_name: str):
|
|
385
|
-
|
|
442
|
+
import tkinter as tk
|
|
386
443
|
|
|
387
444
|
self.current_section = section_name
|
|
388
445
|
self.section_label.configure(text=section_name)
|
|
@@ -394,18 +451,41 @@ class FdevGui:
|
|
|
394
451
|
row = index // 2
|
|
395
452
|
column = index % 2
|
|
396
453
|
|
|
397
|
-
container =
|
|
454
|
+
container = tk.Frame(
|
|
455
|
+
self.command_frame,
|
|
456
|
+
bg=PANEL_BG,
|
|
457
|
+
bd=1,
|
|
458
|
+
relief="solid",
|
|
459
|
+
padx=6,
|
|
460
|
+
pady=6,
|
|
461
|
+
)
|
|
398
462
|
container.grid(row=row, column=column, sticky="nsew", padx=4, pady=4)
|
|
399
463
|
container.columnconfigure(0, weight=1)
|
|
400
464
|
|
|
401
|
-
button =
|
|
465
|
+
button = tk.Button(
|
|
402
466
|
container,
|
|
403
467
|
text=command.label,
|
|
404
468
|
command=lambda item=command: self._run_command(item),
|
|
469
|
+
bg=BUTTON_BG,
|
|
470
|
+
fg=TEXT_FG,
|
|
471
|
+
activebackground=BUTTON_ACTIVE_BG,
|
|
472
|
+
activeforeground=TEXT_FG,
|
|
473
|
+
relief="raised",
|
|
474
|
+
bd=1,
|
|
475
|
+
padx=8,
|
|
476
|
+
pady=4,
|
|
405
477
|
)
|
|
406
478
|
button.grid(row=0, column=0, sticky="ew")
|
|
407
479
|
|
|
408
|
-
description =
|
|
480
|
+
description = tk.Label(
|
|
481
|
+
container,
|
|
482
|
+
text=command.description,
|
|
483
|
+
wraplength=260,
|
|
484
|
+
bg=PANEL_BG,
|
|
485
|
+
fg=MUTED_FG,
|
|
486
|
+
justify="left",
|
|
487
|
+
anchor="w",
|
|
488
|
+
)
|
|
409
489
|
description.grid(row=1, column=0, sticky="w", pady=(4, 0))
|
|
410
490
|
|
|
411
491
|
def _run_command(self, command: GuiCommand):
|
|
@@ -523,6 +603,7 @@ class FdevGui:
|
|
|
523
603
|
|
|
524
604
|
def launch_gui() -> int:
|
|
525
605
|
"""Launch the fdev Tkinter dashboard."""
|
|
606
|
+
prepare_tk_environment()
|
|
526
607
|
try:
|
|
527
608
|
import tkinter as tk
|
|
528
609
|
except ImportError:
|
|
@@ -2,10 +2,12 @@ import sys
|
|
|
2
2
|
import unittest
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from tkinter import TclError
|
|
5
|
+
from unittest.mock import patch
|
|
5
6
|
|
|
6
7
|
from managers.gui import (
|
|
7
8
|
FdevGui,
|
|
8
9
|
GuiCommand,
|
|
10
|
+
prepare_tk_environment,
|
|
9
11
|
parse_ansi_segments,
|
|
10
12
|
build_fdev_command,
|
|
11
13
|
get_gui_sections,
|
|
@@ -144,6 +146,14 @@ class GuiCatalogTests(unittest.TestCase):
|
|
|
144
146
|
["sync", "dev", "main"],
|
|
145
147
|
)
|
|
146
148
|
|
|
149
|
+
def test_prepare_tk_environment_silences_macos_system_tk_warning(self):
|
|
150
|
+
with patch.dict("os.environ", {}, clear=True):
|
|
151
|
+
prepare_tk_environment()
|
|
152
|
+
|
|
153
|
+
import os
|
|
154
|
+
|
|
155
|
+
self.assertEqual(os.environ["TK_SILENCE_DEPRECATION"], "1")
|
|
156
|
+
|
|
147
157
|
def test_dashboard_uses_stable_grid_layout_without_paned_window(self):
|
|
148
158
|
try:
|
|
149
159
|
import tkinter as tk
|
|
@@ -172,6 +182,60 @@ class GuiCatalogTests(unittest.TestCase):
|
|
|
172
182
|
finally:
|
|
173
183
|
root.destroy()
|
|
174
184
|
|
|
185
|
+
def test_dashboard_maps_initial_widgets_after_mainloop_starts(self):
|
|
186
|
+
try:
|
|
187
|
+
import tkinter as tk
|
|
188
|
+
except ImportError:
|
|
189
|
+
self.skipTest("Tkinter is not available")
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
root = tk.Tk()
|
|
193
|
+
except TclError as error:
|
|
194
|
+
self.skipTest(f"Tk display is not available: {error}")
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
app = FdevGui(root)
|
|
198
|
+
root.after(10, root.quit)
|
|
199
|
+
app.run()
|
|
200
|
+
|
|
201
|
+
self.assertTrue(app.command_frame.winfo_ismapped())
|
|
202
|
+
self.assertTrue(app.log_text.winfo_ismapped())
|
|
203
|
+
self.assertGreater(app.command_frame.winfo_width(), 100)
|
|
204
|
+
self.assertGreater(app.log_text.winfo_width(), 100)
|
|
205
|
+
finally:
|
|
206
|
+
root.destroy()
|
|
207
|
+
|
|
208
|
+
def test_dashboard_uses_classic_tk_widgets_for_system_tk_compatibility(self):
|
|
209
|
+
try:
|
|
210
|
+
import tkinter as tk
|
|
211
|
+
except ImportError:
|
|
212
|
+
self.skipTest("Tkinter is not available")
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
root = tk.Tk()
|
|
216
|
+
except TclError as error:
|
|
217
|
+
self.skipTest(f"Tk display is not available: {error}")
|
|
218
|
+
|
|
219
|
+
try:
|
|
220
|
+
app = FdevGui(root)
|
|
221
|
+
root.update_idletasks()
|
|
222
|
+
|
|
223
|
+
widget_classes = {
|
|
224
|
+
widget.winfo_class()
|
|
225
|
+
for widget in _walk_widgets(root)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
self.assertFalse(
|
|
229
|
+
{"TButton", "TEntry", "TFrame", "TLabel", "TScrollbar"} & widget_classes
|
|
230
|
+
)
|
|
231
|
+
self.assertIn("Button", widget_classes)
|
|
232
|
+
self.assertIn("Label", widget_classes)
|
|
233
|
+
self.assertIn("Entry", widget_classes)
|
|
234
|
+
self.assertIn("Scrollbar", widget_classes)
|
|
235
|
+
self.assertGreater(app.command_frame.winfo_width(), 100)
|
|
236
|
+
finally:
|
|
237
|
+
root.destroy()
|
|
238
|
+
|
|
175
239
|
|
|
176
240
|
def _walk_widgets(widget):
|
|
177
241
|
yield widget
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|