def handle_option_merge(group_defaults, incoming_options, title):
    """
    Merges a set of group defaults with incoming options.

    A bunch of ceremony here is to ensure backwards compatibility with the old
    num_required_cols and num_optional_cols decorator args. They are used as
    the seed values for the new group defaults which keeps the old behavior
    _mostly_ in tact.

    Known failure points:
        * Using custom groups / names. No 'positional arguments' group
          means no required_cols arg being honored
        * Non-positional args marked as required. It would take group
          shuffling along the lines of that required to make
          mutually exclusive groups show in the correct place. In short, not
          worth the complexity for a legacy feature that's been succeeded by
          a much more powerful alternative.
    """
    if title == 'positional arguments':
        # the argparse default 'required' bucket
        req_cols = getin(group_defaults, ['legacy', 'required_cols'], 2)
        new_defaults = assoc(group_defaults, 'columns', req_cols)
        return merge(new_defaults, incoming_options)
    else:
        opt_cols = getin(group_defaults, ['legacy', 'optional_cols'], 2)
        new_defaults = assoc(group_defaults, 'columns', opt_cols)
        return merge(new_defaults, incoming_options)
Beispiel #2
0
def add_placeholder(field: FormField, placeholder=VALUE_PLACEHOLDER):
    """
    TODO: Docs about placeholders
    """
    if field['type'] in ['Checkbox', 'CheckBox', 'BlockCheckbox']:
        # there's no sane placeholder we can make for this one, as
        # it's kind of a nonsensical case: a required optional flag.
        # We set it to True here, which is equally nonsensical, but
        # ultimately will allow the validation to pass. We have no
        # way of passing a placeholder without even MORE monket patching
        # of the user's parser to rewrite the action type
        return assoc(field, 'checked', True)
    elif field['type'] in ['Dropdown', 'Listbox', 'Counter']:
        return assoc(field, 'selected', placeholder)
    elif field['type'] == 'RadioGroup':
        # We arbitrarily attach a placeholder for first RadioGroup option
        # and mark it as the selected one.
        return {
            **field,
            'selected': 0,
            'options': [
                add_placeholder(field['options'][0], placeholder=RADIO_PLACEHOLDER),  # type: ignore
                *field['options'][1:]  # type: ignore
            ]
        }
    else:
        return assoc(field, 'value', placeholder)
Beispiel #3
0
def formatArgument(item: EnrichedItem):
    if item['type'] in ['Checkbox', 'CheckBox', 'BlockCheckbox']:
        return checkbox(item['data'], value(item['field']))
    elif item['type'] == 'MultiFileChooser':
        return multiFileChooser(item['data'], value(item['field']))
    elif item['type'] == 'Textarea':
        return textArea(item['data'], value(item['field']))
    elif item['type'] == 'CommandField':
        return textArea(item['data'], value(item['field']))
    elif item['type'] == 'Counter':
        return counter(item['data'], value(item['field']))
    elif item['type'] == 'Dropdown':
        return dropdown(item['data'], value(item['field']))
    elif item['type'] == 'Listbox':
        return listbox(item['data'], value(item['field']))
    elif item['type'] == 'RadioGroup':
        selected = item['field']['selected']  # type: ignore
        if selected is not None:
            formField = item['field']['options'][selected]  # type: ignore
            argparseDefinition = item['data']['widgets'][selected]  # type: ignore
            return formatArgument(assoc(argparseDefinition, 'field', formField))  # type: ignore
        else:
            return None
    else:
        return general(item['data'], value(item['field']))
Beispiel #4
0
def cmdOrPlaceholderOrNone(item: EnrichedItem) -> Optional[str]:
    # Argparse has a fail-fast-and-exit behavior for any missing
    # values. This poses a problem for dynamic validation, as we
    # want to collect _all_ errors to be more useful to the user.
    # As such, if there is no value currently available, we pass
    # through a stock placeholder values which allows GooeyParser
    # to handle it being missing without Argparse exploding due to
    # it actually being missing.
    if item['cli_type'] == 'positional':
        return formatArgument(item) or VALUE_PLACEHOLDER
    elif item['cli_type'] != 'positional' and item['required']:
        # same rationale applies here. We supply the argument
        # along with a fixed placeholder (when relevant i.e. `store`
        # actions)
        return formatArgument(item) or formatArgument(assoc(item, 'field', add_placeholder(item['field'])))
    else:
        # Optional values are, well, optional. So, like usual, we send
        # them if present or drop them if not.
        return formatArgument(item)
Beispiel #5
0
def interruptedScreen(_: Callable[[str], str], state: GooeyState):
    next_state = errorScreen(_, state) if state['force_stop_is_error'] else successScreen(_, state)
    return assoc(next_state, 'subtitle', _('finished_forced_quit'))
Beispiel #6
0
def show_alert(state: FullGooeyState):
    return assoc(state, 'show_error_alert', True)
Beispiel #7
0
def enable_buttons(state, to_enable: List[str]):
    updated = [{**btn, 'enabled': btn['label_id'] in to_enable}
               for btn in state['buttons']]
    return assoc(state, 'buttons', updated)
Beispiel #8
0
 def handleSelectAction(self, event):
     self.set_state(assoc(self.state, 'activeSelection', event.Selection))