Skip to content

Commit 30ebb31

Browse files
committed
Refactor move crystal.browser.MainWindow to its own submodule
1 parent 011cdda commit 30ebb31

21 files changed

+2277
-2277
lines changed

src/crystal/browser/__init__.py

Lines changed: 0 additions & 2225 deletions
Large diffs are not rendered by default.

src/crystal/browser/main_window.py

Lines changed: 2225 additions & 0 deletions
Large diffs are not rendered by default.

src/crystal/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from typing import Any, BinaryIO, TextIO, cast, Never, ParamSpec, TypeVar, TYPE_CHECKING, override
3232

3333
if TYPE_CHECKING:
34-
from crystal.browser import MainWindow
34+
from crystal.browser.main_window import MainWindow
3535
from crystal.model import Project
3636
from crystal.progress.interface import OpenProjectProgressListener
3737
from crystal.shell import Shell
@@ -1039,7 +1039,7 @@ async def _did_launch(
10391039

10401040
# Create main window (unless in headless mode)
10411041
if not parsed_args.headless:
1042-
from crystal.browser import MainWindow
1042+
from crystal.browser.main_window import MainWindow
10431043
# NOTE: Can raise CancelOpenProject
10441044
window = MainWindow(project, progress_listener)
10451045
except CancelOpenProject:
@@ -1107,7 +1107,7 @@ async def _prompt_for_project(
11071107
Raises:
11081108
* SystemExit -- if the user quits rather than providing a project
11091109
"""
1110-
from crystal.browser import MainWindow
1110+
from crystal.browser.main_window import MainWindow
11111111
from crystal.progress.interface import CancelOpenProject
11121112
from crystal.ui.dialog import BetterMessageDialog
11131113
from crystal.util.wx_bind import bind

src/crystal/shell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
)
3838

3939
if TYPE_CHECKING:
40-
from crystal.browser import MainWindow
40+
from crystal.browser.main_window import MainWindow
4141

4242

4343
_R = TypeVar('_R')

src/crystal/tests/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ recommended unless you are writing tests intended to directly test the UI.
270270
After creating or opening a project, you'll get an `mw`
271271
(`crystal.tests.util.windows.MainWindow`) object which can be interacted with
272272
to manipulate the UI in the main window. (This is not the same as the
273-
`crystal.browser.MainWindow` object that is available on the Crystal CLI.)
273+
`crystal.browser.main_window.MainWindow` object that is available on the Crystal CLI.)
274274

275275
Read the source of `MainWindow` or look at how other tests interact with it
276276
to determine what actions are possible.

src/crystal/tests/aspects/test_readonly_mode.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from collections.abc import Iterator
22
from contextlib import contextmanager
3-
from crystal.browser import MainWindow as RealMainWindow
3+
from crystal.browser.main_window import MainWindow as RealMainWindow
44
from crystal.model import Project, Resource, RootResource
55
# TODO: Extract shared utilities to own module
66
from crystal.tests.aspects.test_untitled_projects import (
@@ -516,7 +516,7 @@ def spy_execute(self, command: str, *args, **kwargs):
516516

517517
# Run the save operation
518518
with patch.object(DatabaseCursor, 'execute', spy_execute), \
519-
patch('crystal.browser.ShowModal', mocked_show_modal(
519+
patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
520520
'cr-save-error-dialog', wx.ID_OK)):
521521
await save_as_with_ui(rmw, save_path)
522522

src/crystal/tests/aspects/test_untitled_projects.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from collections.abc import AsyncIterator, Callable, Iterator
22
from contextlib import asynccontextmanager, contextmanager
33
from crystal.app_preferences import app_prefs
4-
from crystal.browser import MainWindow as RealMainWindow
4+
from crystal.browser.main_window import MainWindow as RealMainWindow
55
from crystal.browser.tasktree import TaskTreeNode
66
from crystal.model import (
77
Project, ProjectReadOnlyError, Resource, ResourceGroup, RootResource,
@@ -330,7 +330,7 @@ async def test_when_dirty_untitled_project_closed_then_prompts_to_save() -> None
330330
assert mw.main_window.OSXIsModified()
331331

332332
# Close the project, expect a prompt to save, and save to the specified path
333-
with patch('crystal.browser.ShowModal', mocked_show_modal('cr-save-changes-dialog', wx.ID_YES)), \
333+
with patch('crystal.browser.main_window.ShowModal', mocked_show_modal('cr-save-changes-dialog', wx.ID_YES)), \
334334
file_dialog_returning(save_path):
335335
await mw.close()
336336
assert os.path.exists(save_path)
@@ -341,7 +341,7 @@ async def test_when_clean_untitled_project_closed_then_does_not_prompt_to_save()
341341
assert not project.is_dirty
342342

343343
# Close project. Ensure no prompt to save.
344-
with patch('crystal.browser.ShowModal') as mock_show_modal:
344+
with patch('crystal.browser.main_window.ShowModal') as mock_show_modal:
345345
await mw.close()
346346
mock_show_modal.assert_not_called()
347347

@@ -407,7 +407,7 @@ def _ensure_logout_vetoed_and_return_yes(dialog: wx.Dialog) -> int:
407407
return wx.ID_YES
408408

409409
# Start logout. Expect a prompt to save. Save.
410-
with patch('crystal.browser.ShowModal', mocked_show_modal(
410+
with patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
411411
'cr-save-changes-dialog',
412412
_ensure_logout_vetoed_and_return_yes)), \
413413
file_dialog_returning(save_path):
@@ -435,7 +435,7 @@ async def test_given_os_logout_with_dirty_untitled_project_and_prompts_to_save_w
435435
assert project.is_dirty
436436

437437
# Start logout. Expect a prompt to save. Cancel.
438-
with patch('crystal.browser.ShowModal', mocked_show_modal('cr-save-changes-dialog', wx.ID_CANCEL)):
438+
with patch('crystal.browser.main_window.ShowModal', mocked_show_modal('cr-save-changes-dialog', wx.ID_CANCEL)):
439439
logout_event = _simulate_os_logout()
440440

441441
# Verify the logout was vetoed
@@ -446,7 +446,7 @@ async def test_given_os_logout_with_dirty_untitled_project_and_prompts_to_save_w
446446
assert project.is_untitled
447447

448448
# Now close the project without saving
449-
with patch('crystal.browser.ShowModal', mocked_show_modal('cr-save-changes-dialog', wx.ID_NO)):
449+
with patch('crystal.browser.main_window.ShowModal', mocked_show_modal('cr-save-changes-dialog', wx.ID_NO)):
450450
await mw.close()
451451

452452

@@ -460,7 +460,7 @@ async def test_given_os_logout_with_dirty_untitled_project_and_prompts_to_save_w
460460
assert project.is_dirty
461461

462462
# Start logout. Expect a prompt to save. Do not save.
463-
with patch('crystal.browser.ShowModal', mocked_show_modal('cr-save-changes-dialog', wx.ID_NO)):
463+
with patch('crystal.browser.main_window.ShowModal', mocked_show_modal('cr-save-changes-dialog', wx.ID_NO)):
464464
_simulate_os_logout()
465465

466466
# Ensure project was closed
@@ -476,7 +476,7 @@ async def test_when_close_untitled_prompt_and_user_does_not_save_then_project_mo
476476

477477
with patch('crystal.filesystem.LocalFilesystem.send2trash', wraps=send2trash.send2trash) as send2trash_spy, \
478478
patch(
479-
'crystal.browser.ShowModal',
479+
'crystal.browser.main_window.ShowModal',
480480
mocked_show_modal('cr-save-changes-dialog', wx.ID_NO)):
481481
await mw.close()
482482

@@ -820,7 +820,7 @@ def spy_execute(self, command: str, *args, **kwargs):
820820

821821
# Run the save operation
822822
with patch.object(DatabaseCursor, 'execute', spy_execute), \
823-
patch('crystal.browser.ShowModal', mocked_show_modal(
823+
patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
824824
'cr-save-error-dialog', wx.ID_OK)):
825825
await save_as_with_ui(rmw, save_path)
826826

@@ -857,7 +857,7 @@ def raise_disk_full_error() -> Never:
857857

858858
# Run the save operation
859859
with _file_object_write_mocked_to(raise_disk_full_error), \
860-
patch('crystal.browser.ShowModal', mocked_show_modal(
860+
patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
861861
'cr-save-error-dialog', wx.ID_OK)):
862862
await save_as_with_ui(rmw, save_path)
863863

@@ -904,7 +904,7 @@ def raise_destination_filesystem_gone_error() -> Never:
904904

905905
# Run the save operation
906906
with _file_object_write_mocked_to(raise_destination_filesystem_gone_error), \
907-
patch('crystal.browser.ShowModal', mocked_show_modal(
907+
patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
908908
'cr-save-error-dialog', wx.ID_OK)):
909909
await save_as_with_ui(rmw, save_path)
910910

@@ -981,7 +981,7 @@ async def test_when_save_as_project_and_old_project_fails_to_close_then_handles_
981981
# Patch the scheduler join timeout to 0 to force immediate timeout
982982
with patch.object(Project, '_SCHEDULER_JOIN_TIMEOUT', 0):
983983
# Mock error dialog to acknowledge the timeout error
984-
with patch('crystal.browser.ShowModal', mocked_show_modal(
984+
with patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
985985
'cr-save-error-dialog', wx.ID_OK)):
986986
await save_as_with_ui(rmw, save_path)
987987

@@ -1029,7 +1029,7 @@ def raise_database_corruption_error(*args, **kwargs):
10291029

10301030
# Run the save operation
10311031
with patch('sqlite3.connect', side_effect=raise_database_corruption_error), \
1032-
patch('crystal.browser.ShowModal', mocked_show_modal(
1032+
patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
10331033
'cr-save-error-dialog', wx.ID_OK)):
10341034
await save_as_with_ui(rmw, save_path)
10351035

@@ -1071,7 +1071,7 @@ def fake_reopen(self):
10711071
f.truncate(size // 2)
10721072
return original_reopen(self)
10731073
with patch.object(Project, '_reopen', fake_reopen), \
1074-
patch('crystal.browser.ShowModal', mocked_show_modal(
1074+
patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
10751075
'cr-save-error-dialog', wx.ID_OK)) as show_modal_method:
10761076
await save_as_with_ui(rmw, save_path)
10771077
assert 1 == show_modal_method.call_count, \
@@ -1119,7 +1119,7 @@ def fake_reopen(self):
11191119
return original_reopen(self)
11201120

11211121
with patch.object(Project, '_reopen', fake_reopen), \
1122-
patch('crystal.browser.ShowModal', mocked_show_modal(
1122+
patch('crystal.browser.main_window.ShowModal', mocked_show_modal(
11231123
'cr-save-error-dialog', wx.ID_OK)) as show_modal_method:
11241124
await save_as_with_ui(rmw, save_path)
11251125
assert 1 == show_modal_method.call_count, \
@@ -1506,7 +1506,7 @@ def SaveAsProgressDialogSpy(*args, **kwargs) -> SaveAsProgressDialog: # wraps r
15061506
return instance
15071507

15081508
try:
1509-
with patch('crystal.browser.SaveAsProgressDialog', SaveAsProgressDialogSpy):
1509+
with patch('crystal.browser.main_window.SaveAsProgressDialog', SaveAsProgressDialogSpy):
15101510
async with wait_for_save_as_to_complete(project):
15111511
# 1. Tell caller to start a Save As operation
15121512
# 2. Yield a placeholder for spies that will be updated when the dialog is created
@@ -1537,7 +1537,7 @@ def SaveAsProgressDialogSpy(*args, **kwargs): # wraps real constructor
15371537
try:
15381538
old_project_dirpath = project.path # capture
15391539
assert os.path.exists(old_project_dirpath)
1540-
with patch('crystal.browser.SaveAsProgressDialog', SaveAsProgressDialogSpy):
1540+
with patch('crystal.browser.main_window.SaveAsProgressDialog', SaveAsProgressDialogSpy):
15411541
async with wait_for_save_as_to_complete(project):
15421542
yield
15431543

src/crystal/tests/cli/test_cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ def test_when_launched_with_shell_and_project_filepath_then_shell_starts_with_op
418418

419419
# Verify window variable is set to a real MainWindow object
420420
result = py_eval_literal(crystal, 'repr(window)')
421-
assertIn('<crystal.browser.MainWindow object at 0x', result)
421+
assertIn('<crystal.browser.main_window.MainWindow object at 0x', result)
422422

423423
# Verify the project path is correct
424424
result = py_eval_literal(crystal, 'project.path')

src/crystal/tests/cli/test_runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"""
77

88
from contextlib import redirect_stderr
9-
from crystal.browser import MainWindow as RealMainWindow
9+
from crystal.browser.main_window import MainWindow as RealMainWindow
1010
from crystal.model import Project
1111
from crystal.tests.util.asserts import (
1212
assertEqual, assertIn, assertNotEqual, assertNotIn, assertRegex

src/crystal/tests/cli/test_shell.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,12 @@ def test_can_launch_with_shell(subtests: SubtestsContext) -> None:
126126
r'^<crystal\.model\.project\.Project object at 0x[0-9a-f]+>\n$',
127127
py_eval(crystal, 'project'))
128128
assert re.fullmatch(
129-
r'^<crystal\.browser\.MainWindow object at 0x[0-9a-f]+>\n$',
129+
r'^<crystal\.browser\.main_window\.MainWindow object at 0x[0-9a-f]+>\n$',
130130
py_eval(crystal, 'window'))
131131

132132
with subtests.test(msg='and {project, window} can be used with help()'):
133133
assertIn('Help on Project in module crystal.model.project object:', py_eval(crystal, 'help(project)'))
134-
assertIn('Help on MainWindow in module crystal.browser object:', py_eval(crystal, 'help(window)'))
134+
assertIn('Help on MainWindow in module crystal.browser.main_window object:', py_eval(crystal, 'help(window)'))
135135

136136

137137
def test_can_use_pythonstartup_file() -> None:

0 commit comments

Comments
 (0)