From 5094c849d2c32c625800e53a1073198afe1b298e Mon Sep 17 00:00:00 2001 From: David Foster Date: Tue, 16 Jan 2024 19:30:11 -0500 Subject: [PATCH] *IP/SQ: Add logic for Do Not Download groups. Needs tests, release notes, and docs. --- src/crystal/browser/__init__.py | 21 +++++++++++++++---- src/crystal/browser/new_group.py | 35 +++++++++++++++++++++++--------- src/crystal/model.py | 1 + src/crystal/server.py | 3 ++- src/crystal/task.py | 4 +++- 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/crystal/browser/__init__.py b/src/crystal/browser/__init__.py index 0fb83913..ad2f1668 100644 --- a/src/crystal/browser/__init__.py +++ b/src/crystal/browser/__init__.py @@ -499,17 +499,29 @@ def _on_new_group(self, event: wx.CommandEvent) -> None: pass @fg_affinity - def _on_new_group_dialog_ok(self, name: str, url_pattern: str, source: ResourceGroupSource) -> None: + def _on_new_group_dialog_ok(self, + name: str, + url_pattern: str, + source: ResourceGroupSource, + do_not_download: bool, + ) -> None: # TODO: Validate user input: # * Is url_pattern empty? # * Is url_pattern already taken? - ResourceGroup(self.project, name, url_pattern, source) + rg = ResourceGroup(self.project, name, url_pattern, source) + rg.do_not_download = do_not_download @fg_affinity - def _on_edit_group_dialog_ok(self, rg: ResourceGroup, name: str, url_pattern: str, source: ResourceGroupSource) -> None: + def _on_edit_group_dialog_ok(self, + rg: ResourceGroup, + name: str, + url_pattern: str, + source: ResourceGroupSource, + do_not_download: bool, + ) -> None: if url_pattern != rg.url_pattern: raise ValueError() - (rg.name, rg.source) = (name, source) + (rg.name, rg.source, rg.do_not_download) = (name, source, do_not_download) # TODO: This update should happen in response to an event # fired by the entity itself. @@ -555,6 +567,7 @@ def _on_edit_entity(self, event) -> None: initial_url_pattern=rg.url_pattern, initial_source=rg.source, initial_name=rg.name, + initial_do_not_download=rg.do_not_download, is_edit=True) except CancelLoadUrls: pass diff --git a/src/crystal/browser/new_group.py b/src/crystal/browser/new_group.py index 74cb71e0..0e89935a 100644 --- a/src/crystal/browser/new_group.py +++ b/src/crystal/browser/new_group.py @@ -29,12 +29,13 @@ class NewGroupDialog: def __init__(self, parent: wx.Window, - on_finish: Callable[[str, str, ResourceGroupSource], None], + on_finish: Callable[[str, str, ResourceGroupSource, bool], None], project: Project, saving_source_would_create_cycle_func: Callable[[ResourceGroupSource], bool], initial_url_pattern: str='', initial_source: ResourceGroupSource=None, initial_name: str='', + initial_do_not_download: bool=False, is_edit: bool=False, ) -> None: """ @@ -84,7 +85,7 @@ def __init__(self, flag=wx.EXPAND|preview_box_flags, border=preview_box_border) content_sizer.Add( - self._create_advanced_options(dialog), + self._create_advanced_options(dialog, initial_do_not_download), flag=wx.EXPAND|wx.TOP, border=10) @@ -226,22 +227,35 @@ def _create_preview_box_content(self, parent: wx.Window) -> wx.Sizer: return content_sizer - def _create_advanced_options(self, parent: wx.Window) -> wx.Sizer: + def _create_advanced_options(self, parent: wx.Window, *args, **kwargs) -> wx.Sizer: options_sizer = wx.StaticBoxSizer(wx.VERTICAL, parent, label='Advanced Options') options_sizer.Add( wrap_static_box_sizer_child( self._create_advanced_options_content( - options_sizer.GetStaticBox())), + options_sizer.GetStaticBox(), + *args, **kwargs)), flag=wx.EXPAND) return options_sizer - def _create_advanced_options_content(self, parent: wx.Window) -> wx.Sizer: + def _create_advanced_options_content(self, + parent: wx.Window, + initial_do_not_download: bool, + ) -> wx.Sizer: options_sizer = wx.BoxSizer(wx.VERTICAL) + options_sizer.Add( + wx.StaticText(parent, label='These options reset when Crystal quits.'), + ) + self.do_not_download_checkbox = wx.CheckBox( - parent, label='Do not download members', + parent, label='Do not download members when embedded', name='cr-new-group-dialog__do-not-download-checkbox') - options_sizer.Add(self.do_not_download_checkbox) + self.do_not_download_checkbox.Value = initial_do_not_download + options_sizer.Add( + self.do_not_download_checkbox, + flag=wx.TOP, + border=8, + ) options_sizer.AddSpacer(_FORM_ROW_SPACING) sequential_row = wx.BoxSizer(wx.HORIZONTAL) @@ -392,8 +406,8 @@ def _on_close(self, event: wx.CloseEvent) -> None: self._on_cancel(event) def _on_ok(self, event: wx.CommandEvent) -> None: - name = self.name_field.GetValue() - url_pattern = self.pattern_field.GetValue() + name = self.name_field.Value + url_pattern = self.pattern_field.Value source = self.source_choice_box.GetClientData( self.source_choice_box.GetSelection()) if self._saving_source_would_create_cycle_func(source): @@ -408,7 +422,8 @@ def _on_ok(self, event: wx.CommandEvent) -> None: choice = ShowModal(dialog) assert wx.ID_OK == choice return - self._on_finish(name, url_pattern, source) + do_not_download = self.do_not_download_checkbox.Value + self._on_finish(name, url_pattern, source, do_not_download) self.dialog.Destroy() diff --git a/src/crystal/model.py b/src/crystal/model.py index 39b3549f..384376a0 100644 --- a/src/crystal/model.py +++ b/src/crystal/model.py @@ -3152,6 +3152,7 @@ def __init__(self, self.url_pattern = url_pattern self._url_pattern_re = ResourceGroup.create_re_for_url_pattern(url_pattern) self._source = None # type: Union[ResourceGroupSource, EllipsisType] + self.do_not_download = False # Calculate members on demand rather than up front self._members = None # type: Optional[List[Resource]] diff --git a/src/crystal/server.py b/src/crystal/server.py index 9f115778..79818b5a 100644 --- a/src/crystal/server.py +++ b/src/crystal/server.py @@ -534,8 +534,9 @@ def _find_root_resource_matching_archive_url(self, archive_url: str) -> Optional return None def _find_group_matching_archive_url(self, archive_url: str) -> Optional[ResourceGroup]: + # ...excluding "do not download" groups for rg in self.project.resource_groups: - if rg.contains_url(archive_url): + if rg.contains_url(archive_url) and not rg.do_not_download: return rg return None diff --git a/src/crystal/task.py b/src/crystal/task.py index c2b31751..beb4088c 100644 --- a/src/crystal/task.py +++ b/src/crystal/task.py @@ -884,6 +884,7 @@ def fg_task() -> List[Resource]: link_urls_seen = set() base_url = self._resource.url # cache project = self._resource.project # cache + dnd_groups = [g for g in project.resource_groups if g.do_not_download] # cache for link in links: if not link.embedded: continue @@ -902,7 +903,8 @@ def fg_task() -> List[Resource]: # by ParseResourceRevisionLinks and being # accessed here. link_resource = Resource(project, link_url) - embedded_resources.append(link_resource) + if not any([g.contains_url(link_resource.url) for g in dnd_groups]): + embedded_resources.append(link_resource) return embedded_resources embedded_resources = fg_call_and_wait(fg_task)