From ac25d0e34d9186d63140abf31278b3369b6aab53 Mon Sep 17 00:00:00 2001 From: Alexander Gordeyev Date: Fri, 23 Oct 2015 17:02:17 +0300 Subject: [PATCH 1/7] make quoting implicit --- gooey/gui/util/quoting.py | 4 ---- gooey/gui/widgets/components.py | 1 + gooey/gui/widgets/widget_pack.py | 39 ++++++++++++++++++++------------ gooey/gui/windows/layouts.py | 2 +- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/gooey/gui/util/quoting.py b/gooey/gui/util/quoting.py index f955f8f..ae6710b 100644 --- a/gooey/gui/util/quoting.py +++ b/gooey/gui/util/quoting.py @@ -7,7 +7,3 @@ if sys.platform.startswith("win"): else: # POSIX shell def quote(value): return "'{}'".format('{}'.format(value).replace("'", "'\\''")) - - -def maybe_quote(string): - return '"{}"'.format(string) if not re.match(r'^".*"$', string) else string diff --git a/gooey/gui/widgets/components.py b/gooey/gui/widgets/components.py index 95deb3b..6f09999 100644 --- a/gooey/gui/widgets/components.py +++ b/gooey/gui/widgets/components.py @@ -234,6 +234,7 @@ DirChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_ FileSaver = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.FileSaverPayload()) DateChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DateChooserPayload()) TextField = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.TextInputPayload()) +CommandField = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.TextInputPayload(no_qouting=True)) Dropdown = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DropdownPayload()) Counter = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.CounterPayload()) MultiDirChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.MultiDirChooserPayload()) diff --git a/gooey/gui/widgets/widget_pack.py b/gooey/gui/widgets/widget_pack.py index cdbefa6..43ff219 100644 --- a/gooey/gui/widgets/widget_pack.py +++ b/gooey/gui/widgets/widget_pack.py @@ -1,8 +1,7 @@ from functools import partial -import re from gooey.gui.lang import i18n from gooey.gui.util.filedrop import FileDrop -from gooey.gui.util.quoting import maybe_quote +from gooey.gui.util.quoting import quote __author__ = 'Chris' @@ -69,9 +68,9 @@ class BaseChooser(WidgetPack): def getValue(self): value = self.text_box.GetValue() if self.option_string and value: - return '{0} {1}'.format(self.option_string, maybe_quote(value)) + return '{0} {1}'.format(self.option_string, quote(value)) else: - return maybe_quote(value) if value else '' + return quote(value) if value else '' def onButton(self, evt): raise NotImplementedError @@ -86,6 +85,13 @@ class BaseFileChooser(BaseChooser): BaseChooser.__init__(self) self.dialog = dialog + def getValue(self): + value = ' '.join(quote(x) for x in self.text_box.GetValue().split(os.pathsep)) + if self.option_string and value: + return '{} {}'.format(self.option_string, value) + else: + return value or '' + def onButton(self, evt): dlg = self.dialog(self.parent) result = (self.get_path(dlg) @@ -96,10 +102,9 @@ class BaseFileChooser(BaseChooser): def get_path(self, dlg): if isinstance(dlg, wx.DirDialog) or isinstance(dlg, CalendarDlg): - return maybe_quote(dlg.GetPath()) + return dlg.GetPath() else: - paths = dlg.GetPaths() - return maybe_quote(paths[0]) if len(paths) < 2 else ' '.join(map(maybe_quote, paths)) + return os.pathsep.join(dlg.GetPaths()) class MyMultiDirChooser(MDD.MultiDirDialog): def __init(self, *args, **kwargs): @@ -123,9 +128,10 @@ DateChooserPayload = partial(BaseFileChooser, dialog=CalendarDlg) MultiDirChooserPayload = partial(BaseFileChooser, dialog=lambda parent: MyMultiDirChooser(parent, title="Select Directories", defaultPath=os.getcwd(), agwStyle=MDD.DD_MULTIPLE|MDD.DD_DIR_MUST_EXIST)) class TextInputPayload(WidgetPack): - def __init__(self): + def __init__(self, no_quoting=False): self.widget = None self.option_string = None + self.no_quoting = no_quoting def build(self, parent, data): self.option_string = self.get_command(data) @@ -138,11 +144,15 @@ class TextInputPayload(WidgetPack): return self.widget def getValue(self): + if self.no_quoting: + _quote = lambda value: value + else: + _quote = lambda value: quote(value) value = self.widget.GetValue() if value and self.option_string: - return '{} {}'.format(self.option_string, value) + return '{} {}'.format(self.option_string, _quote(value)) else: - return '"{}"'.format(value) if value else '' + return _quote(value) if value else '' def _SetValue(self, text): # used for testing @@ -168,12 +178,13 @@ class DropdownPayload(WidgetPack): return self.widget def getValue(self): - if self.widget.GetValue() == self.default_value: + value = self.widget.GetValue() + if value == self.default_value: return '' - elif self.widget.GetValue() and self.option_string: - return '{} {}'.format(self.option_string, self.widget.GetValue()) + elif value and self.option_string: + return '{} {}'.format(self.option_string, quote(value)) else: - return self.widget.GetValue() + return quote(value) if value else '' def _SetValue(self, text): # used for testing diff --git a/gooey/gui/windows/layouts.py b/gooey/gui/windows/layouts.py index 67393fe..d528141 100644 --- a/gooey/gui/windows/layouts.py +++ b/gooey/gui/windows/layouts.py @@ -9,7 +9,7 @@ from gooey.gui.util import wx_util basic_config = { 'required': [{ - 'type': 'TextField', + 'type': 'CommandField', 'data': { 'display_name': 'Enter Commands', 'help': 'Enter command line arguments', From f14eb000e50fb22b881dd593cfda396f241d3fc7 Mon Sep 17 00:00:00 2001 From: Alexander Gordeyev Date: Thu, 5 Nov 2015 10:48:37 +0300 Subject: [PATCH 2/7] move multi Chooser logic from BaseFileChooser; fix bug in parsing `action='count'` --- gooey/gui/widgets/widget_pack.py | 37 +++++++++++++++++------ gooey/python_bindings/argparse_to_json.py | 2 +- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/gooey/gui/widgets/widget_pack.py b/gooey/gui/widgets/widget_pack.py index 43ff219..91efe68 100644 --- a/gooey/gui/widgets/widget_pack.py +++ b/gooey/gui/widgets/widget_pack.py @@ -86,11 +86,32 @@ class BaseFileChooser(BaseChooser): self.dialog = dialog def getValue(self): - value = ' '.join(quote(x) for x in self.text_box.GetValue().split(os.pathsep)) + value = self.text_box.GetValue() + if self.option_string and value: + return '{} {}'.format(self.option_string, quote(value)) + return quote(value) if value else '' + + def onButton(self, evt): + dlg = self.dialog(self.parent) + result = (self.get_path(dlg) + if dlg.ShowModal() == wx.ID_OK + else None) + if result: + self.text_box.SetValue(result) + + def get_path(self, dlg): + return dlg.GetPath() + + +class BaseMultiFileChooser(BaseFileChooser): + def __init__(self, dialog): + BaseFileChooser.__init__(self, dialog) + + def getValue(self): + value = ' '.join(quote(x) for x in self.text_box.GetValue().split(os.pathsep) if x) if self.option_string and value: return '{} {}'.format(self.option_string, value) - else: - return value or '' + return value or '' def onButton(self, evt): dlg = self.dialog(self.parent) @@ -101,10 +122,8 @@ class BaseFileChooser(BaseChooser): self.text_box.SetValue(result) def get_path(self, dlg): - if isinstance(dlg, wx.DirDialog) or isinstance(dlg, CalendarDlg): - return dlg.GetPath() - else: - return os.pathsep.join(dlg.GetPaths()) + return os.pathsep.join(dlg.GetPaths()) + class MyMultiDirChooser(MDD.MultiDirDialog): def __init(self, *args, **kwargs): @@ -122,10 +141,10 @@ def build_dialog(style, exist_constraint=True, **kwargs): FileChooserPayload = partial(BaseFileChooser, dialog=build_dialog(wx.FD_OPEN)) FileSaverPayload = partial(BaseFileChooser, dialog=build_dialog(wx.FD_SAVE, False, defaultFile="Enter Filename")) -MultiFileSaverPayload = partial(BaseFileChooser, dialog=build_dialog(wx.FD_MULTIPLE, False)) +MultiFileSaverPayload = partial(BaseMultiFileChooser, dialog=build_dialog(wx.FD_MULTIPLE, False)) DirChooserPayload = partial(BaseFileChooser, dialog=lambda parent: wx.DirDialog(parent, 'Select Directory', style=wx.DD_DEFAULT_STYLE)) DateChooserPayload = partial(BaseFileChooser, dialog=CalendarDlg) -MultiDirChooserPayload = partial(BaseFileChooser, dialog=lambda parent: MyMultiDirChooser(parent, title="Select Directories", defaultPath=os.getcwd(), agwStyle=MDD.DD_MULTIPLE|MDD.DD_DIR_MUST_EXIST)) +MultiDirChooserPayload = partial(BaseMultiFileChooser, dialog=lambda parent: MyMultiDirChooser(parent, title="Select Directories", defaultPath=os.getcwd(), agwStyle=MDD.DD_MULTIPLE|MDD.DD_DIR_MUST_EXIST)) class TextInputPayload(WidgetPack): def __init__(self, no_quoting=False): diff --git a/gooey/python_bindings/argparse_to_json.py b/gooey/python_bindings/argparse_to_json.py index 3508f7d..9233ce3 100644 --- a/gooey/python_bindings/argparse_to_json.py +++ b/gooey/python_bindings/argparse_to_json.py @@ -85,7 +85,7 @@ def categorize(actions, widget_dict, required=False): elif is_flag(action): yield as_json(action, _get_widget(action) or 'CheckBox', required) elif is_counter(action): - _json = as_json(action, _get_widget(action) or 'Dropdown', required) + _json = as_json(action, _get_widget(action) or 'Counter', required) # pre-fill the 'counter' dropdown _json['data']['choices'] = map(str, range(1, 11)) yield _json From 9b9167df303519831505ebb1bf4fce956bc0b8f8 Mon Sep 17 00:00:00 2001 From: Alexander Gordeyev Date: Thu, 5 Nov 2015 11:40:41 +0300 Subject: [PATCH 3/7] fix args ordering --- gooey/gui/widgets/components.py | 13 +++++++++++-- gooey/gui/windows/advanced_config.py | 10 ++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/gooey/gui/widgets/components.py b/gooey/gui/widgets/components.py index 6f09999..bb10717 100644 --- a/gooey/gui/widgets/components.py +++ b/gooey/gui/widgets/components.py @@ -97,6 +97,9 @@ class BaseGuiComponent(object): def GetValue(self): return self.widget_pack.getValue() + def HasOptionString(self): + return bool(self.widget_pack.option_string) + def _GetWidget(self): # used only for unittesting return self.widget_pack.widget @@ -157,6 +160,9 @@ class CheckBox(BaseGuiComponent): def GetValue(self): return self.option_strings if self.widget.GetValue() else '' + def HasOptionString(self): + return bool(self.option_strings) + def _GetWidget(self): return self.widget @@ -168,7 +174,7 @@ class RadioGroup(object): self.data = data self.radio_buttons = [] - self.option_stings = [] + self.option_strings = [] self.help_msgs = [] self.btn_names = [] @@ -181,7 +187,7 @@ class RadioGroup(object): self.radio_buttons = [wx.RadioButton(self.panel, -1) for _ in self.data] self.btn_names = [wx.StaticText(self.panel, label=btn_data['display_name'].title()) for btn_data in self.data] self.help_msgs = [wx.StaticText(self.panel, label=btn_data['help'].title()) for btn_data in self.data] - self.option_stings = [btn_data['commands'] for btn_data in self.data] + self.option_strings = [btn_data['commands'] for btn_data in self.data] # box = wx.StaticBox(self.panel, -1, label=self.data['group_name']) box = wx.StaticBox(self.panel, -1, label='') @@ -224,6 +230,9 @@ class RadioGroup(object): except: return '' + def HasOptionString(self): + return bool(self.option_strings) + def _GetWidget(self): return self.radio_buttons diff --git a/gooey/gui/windows/advanced_config.py b/gooey/gui/windows/advanced_config.py index 21bbcf2..c4276e9 100644 --- a/gooey/gui/windows/advanced_config.py +++ b/gooey/gui/windows/advanced_config.py @@ -93,10 +93,12 @@ class ConfigPanel(ScrolledPanel, OptionReader): """ returns the collective values from all of the widgets contained in the panel""" - values = [c.GetValue() - for c in chain(*self.widgets) - if c.GetValue() is not None] - return ' '.join(values) + _f = lambda lst: [x for x in lst if x is not None] + optional_args = _f([c.GetValue() for c in self.widgets.optional_args]) + required_args = _f([c.GetValue() for c in self.widgets.required_args if c.HasOptionString()]) + position_args = _f([c.GetValue() for c in self.widgets.required_args if not c.HasOptionString()]) + if position_args: position_args.insert(0, "--") + return ' '.join(chain(required_args, optional_args, position_args)) def GetRequiredArgs(self): return [arg.GetValue() for arg in self.widgets.required_args] From 8f2b951d18df00e60eb147222a6995e37140fc94 Mon Sep 17 00:00:00 2001 From: Alexander Gordeyev Date: Thu, 5 Nov 2015 11:50:27 +0300 Subject: [PATCH 4/7] linter fixes --- gooey/gui/widgets/components.py | 4 ++-- gooey/gui/widgets/widget_pack.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gooey/gui/widgets/components.py b/gooey/gui/widgets/components.py index bb10717..eab4ee0 100644 --- a/gooey/gui/widgets/components.py +++ b/gooey/gui/widgets/components.py @@ -145,7 +145,7 @@ class CheckBox(BaseGuiComponent): return self.panel def onSetter(self, evt): - self.getValue() + self.GetValue() def onResize(self, evt): msg = self.help_msg @@ -211,7 +211,7 @@ class RadioGroup(object): return self.panel def onSetter(self, evt): - self.getValue() + self.GetValue() def onResize(self, evt): msg = self.help_msgs[0] diff --git a/gooey/gui/widgets/widget_pack.py b/gooey/gui/widgets/widget_pack.py index 91efe68..1d34e0a 100644 --- a/gooey/gui/widgets/widget_pack.py +++ b/gooey/gui/widgets/widget_pack.py @@ -47,9 +47,9 @@ class BaseChooser(WidgetPack): self.text_box = None self.button = None - def build(self, parent, data=None): + def build(self, parent, data): self.parent = parent - self.option_string = data['commands'][0] if data['commands'] else '' + self.option_string = self.get_command(data) self.text_box = wx.TextCtrl(self.parent) self.text_box.AppendText(safe_default(data, '')) self.text_box.SetMinSize((0, -1)) @@ -166,7 +166,7 @@ class TextInputPayload(WidgetPack): if self.no_quoting: _quote = lambda value: value else: - _quote = lambda value: quote(value) + _quote = quote value = self.widget.GetValue() if value and self.option_string: return '{} {}'.format(self.option_string, _quote(value)) @@ -242,4 +242,4 @@ class CounterPayload(WidgetPack): def safe_default(data, default): # str(None) is 'None'!? Whaaaaat...? - return str(data['default']) if data['default'] else '' + return str(data['default']) if data['default'] else default From 7b00b5ccb7ee2fecd1bf51f4dc968871ee7cc95e Mon Sep 17 00:00:00 2001 From: Alexander Gordeyev Date: Thu, 5 Nov 2015 12:33:36 +0300 Subject: [PATCH 5/7] disable quoting if nargs specified --- gooey/gui/widgets/widget_pack.py | 33 +++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/gooey/gui/widgets/widget_pack.py b/gooey/gui/widgets/widget_pack.py index 1d34e0a..1ce4da1 100644 --- a/gooey/gui/widgets/widget_pack.py +++ b/gooey/gui/widgets/widget_pack.py @@ -36,7 +36,12 @@ class WidgetPack(object): def get_command(data): return data['commands'][0] if data['commands'] else '' - + @staticmethod + def disable_quoting(data): + nargs = data.get('nargs', None) + if not nargs: + return False + return nargs not in (1, '?') class BaseChooser(WidgetPack): @@ -75,7 +80,6 @@ class BaseChooser(WidgetPack): def onButton(self, evt): raise NotImplementedError - def __repr__(self): return self.__class__.__name__ @@ -85,12 +89,6 @@ class BaseFileChooser(BaseChooser): BaseChooser.__init__(self) self.dialog = dialog - def getValue(self): - value = self.text_box.GetValue() - if self.option_string and value: - return '{} {}'.format(self.option_string, quote(value)) - return quote(value) if value else '' - def onButton(self, evt): dlg = self.dialog(self.parent) result = (self.get_path(dlg) @@ -127,7 +125,7 @@ class BaseMultiFileChooser(BaseFileChooser): class MyMultiDirChooser(MDD.MultiDirDialog): def __init(self, *args, **kwargs): - super(MyMultiDirChooser,self).__init__(*args, **kwargs) + super(MyMultiDirChooser, self).__init__(*args, **kwargs) def GetPaths(self): return self.dirCtrl.GetPaths() @@ -154,6 +152,8 @@ class TextInputPayload(WidgetPack): def build(self, parent, data): self.option_string = self.get_command(data) + if self.disable_quoting(data): + self.no_quoting = True self.widget = wx.TextCtrl(parent) dt = FileDrop(self.widget) self.widget.SetDropTarget(dt) @@ -181,12 +181,15 @@ class TextInputPayload(WidgetPack): class DropdownPayload(WidgetPack): default_value = 'Select Option' - def __init__(self): - self.option_string = None + def __init__(self, no_quoting=False): self.widget = None + self.option_string = None + self.no_quoting = no_quoting def build(self, parent, data): self.option_string = self.get_command(data) + if self.disable_quoting(data): + self.no_quoting = True self.widget = wx.ComboBox( parent=parent, id=-1, @@ -197,13 +200,17 @@ class DropdownPayload(WidgetPack): return self.widget def getValue(self): + if self.no_quoting: + _quote = lambda value: value + else: + _quote = quote value = self.widget.GetValue() if value == self.default_value: return '' elif value and self.option_string: - return '{} {}'.format(self.option_string, quote(value)) + return '{} {}'.format(self.option_string, _quote(value)) else: - return quote(value) if value else '' + return _quote(value) if value else '' def _SetValue(self, text): # used for testing From 782d24237fe964ca388f642a7b6bb57f45594446 Mon Sep 17 00:00:00 2001 From: Alexander Gordeyev Date: Thu, 5 Nov 2015 20:53:16 +0300 Subject: [PATCH 6/7] quote subparser name --- gooey/gui/windows/layouts.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gooey/gui/windows/layouts.py b/gooey/gui/windows/layouts.py index d528141..ae8deca 100644 --- a/gooey/gui/windows/layouts.py +++ b/gooey/gui/windows/layouts.py @@ -6,6 +6,8 @@ from gooey.gui import events from gooey.gui.windows.advanced_config import ConfigPanel from gooey.gui.windows.sidebar import Sidebar from gooey.gui.util import wx_util +from gooey.gui.util.quoting import quote + basic_config = { 'required': [{ @@ -77,7 +79,7 @@ class ColumnLayout(wx.Panel): return panels def GetOptions(self): - return '{} {}'.format(self.active_panel, self.config_panels[self.active_panel].GetOptions()) + return '{} {}'.format(quote(self.active_panel), self.config_panels[self.active_panel].GetOptions()) def GetRequiredArgs(self): return self.config_panels[self.active_panel].GetRequiredArgs() From ac042fcb3da522a72185685341a73091eb1d413b Mon Sep 17 00:00:00 2001 From: Shura1oplot Date: Sun, 8 Nov 2015 11:46:22 +0300 Subject: [PATCH 7/7] delete duplicated method --- gooey/gui/widgets/widget_pack.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/gooey/gui/widgets/widget_pack.py b/gooey/gui/widgets/widget_pack.py index 1ce4da1..b12697a 100644 --- a/gooey/gui/widgets/widget_pack.py +++ b/gooey/gui/widgets/widget_pack.py @@ -111,20 +111,12 @@ class BaseMultiFileChooser(BaseFileChooser): return '{} {}'.format(self.option_string, value) return value or '' - def onButton(self, evt): - dlg = self.dialog(self.parent) - result = (self.get_path(dlg) - if dlg.ShowModal() == wx.ID_OK - else None) - if result: - self.text_box.SetValue(result) - def get_path(self, dlg): return os.pathsep.join(dlg.GetPaths()) class MyMultiDirChooser(MDD.MultiDirDialog): - def __init(self, *args, **kwargs): + def __init__(self, *args, **kwargs): super(MyMultiDirChooser, self).__init__(*args, **kwargs) def GetPaths(self):