Turn (almost) any Python command line program into a full GUI application with one line
This report summarizes scanner evidence for chriskiehl/Gooey, a Python project with 21,898 GitHub stars. SynthScan examined 19,158 lines of code across 212 source files, recording 296 pattern matches distributed across 11 syntactic categories. The legacy adjusted pattern signal is 15.9 (Elevated pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 88 finding(s).
Are imports declared and package/API names verified? 197 finding(s).
Are wrappers, guards, and repeated structures necessary? 63 finding(s).
Which changes need focused human review? 296 finding(s).
Run additional scans to build a history of the legacy pattern signal. Score changes are not a measure of AI adoption or code quality.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 296 distinct pattern matches across 11 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | setup.py | 2 | CODE | |
| LOW | gooey/__init__.py | 1 | CODE | |
| LOW | gooey/__init__.py | 2 | CODE | |
| LOW | gooey/__init__.py | 3 | CODE | |
| LOW | gooey/__init__.py | 4 | CODE | |
| LOW | gooey/__init__.py | 5 | CODE | |
| LOW | gooey/__init__.py | 6 | CODE | |
| LOW | gooey/__init__.py | 7 | CODE | |
| LOW | gooey/__init__.py | 8 | CODE | |
| LOW | gooey/util/functional.py | 6 | CODE | |
| LOW | gooey/tests/test_filterable_dropdown.py | 2 | CODE | |
| LOW | gooey/tests/test_filterable_dropdown.py | 4 | CODE | |
| LOW | gooey/tests/test_filterable_dropdown.py | 6 | CODE | |
| LOW | gooey/tests/test_slider.py | 2 | CODE | |
| LOW | gooey/tests/test_slider.py | 6 | CODE | |
| LOW | gooey/tests/test_time_remaining.py | 1 | CODE | |
| LOW | gooey/tests/test_time_remaining.py | 4 | CODE | |
| LOW | gooey/tests/test_time_remaining.py | 9 | CODE | |
| LOW | gooey/tests/test_config_generator.py | 6 | CODE | |
| LOW | gooey/tests/test_common.py | 6 | CODE | |
| LOW | gooey/tests/harness.py | 3 | CODE | |
| LOW | gooey/tests/harness.py | 4 | CODE | |
| LOW | gooey/tests/harness.py | 12 | CODE | |
| LOW | gooey/tests/tmmmmp.py | 1 | CODE | |
| LOW | gooey/tests/test_radiogroup.py | 4 | CODE | |
| LOW | gooey/tests/test_textarea.py | 5 | CODE | |
| LOW | gooey/tests/test_control.py | 1 | CODE | |
| LOW | gooey/tests/test_control.py | 4 | CODE | |
| LOW | gooey/tests/test_control.py | 5 | CODE | |
| LOW | gooey/tests/test_control.py | 6 | CODE | |
| LOW | gooey/tests/test_control.py | 7 | CODE | |
| LOW | gooey/tests/test_control.py | 9 | CODE | |
| LOW | gooey/tests/test_control.py | 12 | CODE | |
| LOW | gooey/tests/test_control.py | 15 | CODE | |
| LOW | gooey/tests/test_control.py | 16 | CODE | |
| LOW | gooey/tests/test_control.py | 16 | CODE | |
| LOW | gooey/tests/test_control.py | 25 | CODE | |
| LOW | gooey/tests/test_util.py | 1 | CODE | |
| LOW | gooey/tests/test_util.py | 4 | CODE | |
| LOW | gooey/tests/test_textfield.py | 6 | CODE | |
| LOW | gooey/tests/test_constraints.py | 4 | CODE | |
| LOW | gooey/tests/test_decoration.py | 1 | CODE | |
| LOW | gooey/tests/test_decoration.py | 2 | CODE | |
| LOW | gooey/tests/test_decoration.py | 3 | CODE | |
| LOW | gooey/tests/test_decoration.py | 5 | CODE | |
| LOW | gooey/tests/test_cmd_args.py | 6 | CODE | |
| LOW | gooey/tests/test_chooser_results.py | 1 | CODE | |
| LOW | gooey/tests/test_chooser_results.py | 6 | CODE | |
| LOW | gooey/tests/test_dropdown.py | 2 | CODE | |
| LOW | gooey/tests/test_dropdown.py | 3 | CODE | |
| LOW | gooey/tests/test_dropdown.py | 7 | CODE | |
| LOW | gooey/tests/test_numeric_inputs.py | 2 | CODE | |
| LOW | gooey/tests/test_numeric_inputs.py | 3 | CODE | |
| LOW | gooey/tests/test_numeric_inputs.py | 7 | CODE | |
| LOW | gooey/tests/test_password.py | 5 | CODE | |
| LOW | gooey/tests/test_parent_inheritance.py | 5 | CODE | |
| LOW | gooey/tests/test_header.py | 3 | CODE | |
| LOW | gooey/tests/test_header.py | 6 | CODE | |
| LOW | gooey/tests/test_checkbox.py | 5 | CODE | |
| LOW | gooey/tests/test_application.py | 1 | CODE | |
| 120 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | gooey/tests/test_filterable_dropdown.py | 33 | def test_arrow_key_selection_cycling(self): | CODE |
| LOW | gooey/tests/test_time_remaining.py | 19 | def test_time_remaining_visibility(self): | CODE |
| LOW | gooey/tests/test_time_remaining.py | 34 | def test_time_remaining_visibility_on_complete(self): | CODE |
| LOW | gooey/tests/test_config_generator.py | 44 | def test_font_weight_defaults_to_normal(self): | CODE |
| LOW | gooey/tests/test_config_generator.py | 51 | def test_invalid_font_weights_throw_error(self): | CODE |
| LOW | gooey/tests/test_options.py | 39 | def test_only_provided_arguments_included(self): | CODE |
| LOW | gooey/tests/test_radiogroup.py | 22 | def test_initial_selection_options(self): | CODE |
| LOW | gooey/tests/test_radiogroup.py | 76 | def test_optional_radiogroup_click_behavior(self): | CODE |
| LOW | gooey/tests/test_radiogroup.py | 113 | def click_scenarios_optional_widget(self): | CODE |
| LOW | gooey/tests/test_radiogroup.py | 144 | def click_scenarios_required_widget(self): | CODE |
| LOW | gooey/tests/test_radiogroup.py | 172 | def click_scenarios_initial_selection(self): | CODE |
| LOW | gooey/tests/test_constraints.py | 39 | def test_visibility_constraint(self): | CODE |
| LOW | gooey/tests/test_cmd_args.py | 22 | def test_required_not_enforced(self): | CODE |
| LOW | gooey/tests/test_parent_inheritance.py | 9 | def test_parent_arguments_exist_in_child(self): | CODE |
| LOW | gooey/tests/test_parent_inheritance.py | 30 | def test_parent_arguments_are_not_overridden(self): | CODE |
| LOW | gooey/tests/test_parent_inheritance.py | 55 | def test_duplicates_on_same_parser_are_ignored(self): | CODE |
| LOW | gooey/tests/test_parent_inheritance.py | 76 | def _verify_duplicate_parameters(self, action1, action2, parser): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 16 | def test_mutex_groups_conversion(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 43 | def test_json_iterable_conversion(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 67 | def test_choice_string_cooersion(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 79 | def test_choice_string_cooersion_no_default(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 92 | def test_listbox_defaults_cast_correctly(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 106 | def test_listbox_single_default_cast_correctly(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 119 | def test_non_data_defaults_are_dropped_entirely(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 145 | def test_suppress_is_removed_as_default_value(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 161 | def test_version_maps_to_checkbox(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 181 | def test_textinput_with_list_default_mapped_to_cli_friendly_value(self): | CODE |
| LOW | gooey/tests/test_argparse_to_json.py | 267 | def test_filetype_chooses_good_widget(self): | CODE |
| LOW | gooey/tests/test_formatters.py | 47 | def test_multifilechooser_formatter(self): | CODE |
| LOW | gooey/tests/dynamics/test_live_updates.py | 43 | def test_validate_form_without_errors(self): | CODE |
| LOW | gooey/tests/processor/test_processor.py | 27 | def test_extract_progress_returns_none_if_no_regex_supplied(self): | CODE |
| LOW | gooey/tests/processor/test_processor.py | 32 | def test_extract_progress_returns_none_if_no_match_found(self): | CODE |
| LOW | gooey/tests/processor/test_processor.py | 43 | def test_eval_progress_returns_none_on_failure(self): | CODE |
| LOW | gooey/tests/processor/test_processor.py | 51 | def test_all_interrupts_halt_process(self): | CODE |
| LOW | gooey/tests/processor/test_processor.py | 87 | def test_ignore_sigint_family_signals(self): | CODE |
| LOW | gooey/python_bindings/argparse_to_json.py | 150 | def assert_subparser_constraints(parser): | CODE |
| LOW | gooey/python_bindings/argparse_to_json.py | 571 | def textinput_with_nargs_and_list_default(action, widget): | CODE |
| LOW | gooey/python_bindings/gooey_parser.py | 37 | def add_mutually_exclusive_group(self, *args, **kwargs): | CODE |
| LOW | gooey/python_bindings/gooey_parser.py | 118 | def _mutually_exclusive_groups(self): | CODE |
| LOW | gooey/python_bindings/gooey_parser.py | 162 | def add_mutually_exclusive_group(self, *args, **kwargs): | CODE |
| LOW | gooey/python_bindings/types.py | 359 | def getOrThrow(self): | CODE |
| LOW | gooey/python_bindings/types.py | 377 | def getOrThrow(self): | CODE |
| LOW | gooey/python_bindings/constraints.py | 25 | def assert_visibility_requirements(action, options): | CODE |
| LOW | gooey/python_bindings/constraints.py | 42 | def assert_listbox_constraints(widget, **kwargs): | CODE |
| LOW | gooey/python_bindings/cmd_args.py | 59 | def restore_original_configuration(item): | CODE |
| LOW | gooey/python_bindings/dynamics.py | 155 | def recursively_patch_actions(parser, fn): | STRING |
| LOW | gooey/python_bindings/dynamics.py | 265 | def monkey_patch_for_form_validation(error_registry: Dict[str, Exception], parser): | STRING |
| LOW | gooey/gui/components/options/options.py | 14 | def _include_global_option_docs(f): | CODE |
| LOW | gooey/gui/components/options/options.py | 24 | def _include_chooser_msg_wildcard_docs(f): | STRING |
| LOW | gooey/gui/components/options/options.py | 36 | def _include_choose_dir_file_docs(f): | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | README.md | 550 | <p><font color="red">Lorem ipsum dolor sit amet, consectetur</font></p> | CODE |
| LOW | README.md | 550 | <p><font color="red">Lorem ipsum dolor sit amet, consectetur</font></p> | CODE |
| LOW | docs/releases/1.0.6-release-notes.md | 18 | 'placeholder': 'Start typing to view suggestions', | CODE |
| LOW | docs/releases/1.0.7-release-notes.md | 31 | 'placeholder': 'Type some text here!' | CODE |
| LOW | docs/releases/1.0.7-release-notes.md | 49 | 'placeholder': 'Type some text here!', | CODE |
| LOW | docs/releases/1.0.5-release-notes.md | 29 | 'placeholder': 'Type something!' | CODE |
| LOW | gooey/tests/test_textarea.py | 18 | [{'placeholder': 'Hello'}, 'Hello'] | CODE |
| LOW | gooey/tests/test_textfield.py | 21 | [{'placeholder': 'Hello'}, 'Hello'] | CODE |
| LOW | gooey/tests/test_password.py | 18 | [{'placeholder': 'Hello'}, 'Hello'] | CODE |
| LOW | gooey/gui/components/options/validators.py | 144 | 'placeholder': non_empty_string, | CODE |
| LOW | gooey/gui/components/widgets/dropdown_filterable.py | 49 | 'placeholder': str, | CODE |
| LOW | gooey/gui/components/widgets/dropdown_filterable.py | 96 | self.widget.SetHint(self._options.get('placeholder', '')) | CODE |
| LOW | gooey/gui/components/widgets/dropdown_filterable.py | 244 | 'placeholder': str, | CODE |
| LOW | gooey/gui/components/widgets/textfield.py | 26 | textctr.SetHint(state['placeholder']) | CODE |
| LOW | gooey/gui/components/widgets/dropdown.py | 14 | 'placeholder': str, | CODE |
| LOW | gooey/gui/components/widgets/bases.py | 91 | if self._options.get('placeholder'): | CODE |
| LOW | gooey/gui/components/widgets/bases.py | 92 | self.setPlaceholder(self._options.get('placeholder')) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | gooey/__main__.py | 1 | # ''' | COMMENT |
| LOW | gooey/tests/test_slider.py | 21 | [{'default': 76}, 76], | COMMENT |
| LOW | gooey/tests/test_decoration.py | 1 | import unittest | COMMENT |
| LOW | gooey/tests/test_decoration.py | 21 | # | COMMENT |
| LOW | gooey/tests/test_decoration.py | 41 | # subs = parser.add_subparsers() | COMMENT |
| LOW | gooey/tests/test_dropdown.py | 21 | # - default values are used as the initial selection (when present) | COMMENT |
| LOW | gooey/tests/test_dropdown.py | 41 | # for choices, default, initalSelection, dynamicUpdate, expectedFinalSelection in testcases: | COMMENT |
| LOW | gooey/tests/test_numeric_inputs.py | 21 | [{'default': 10, 'widget': 'IntegerField'}, 10], | COMMENT |
| LOW | gooey/tests/test_application.py | 61 | # def testOnCloseShutsDownActiveClients(self, mockModal): | COMMENT |
| LOW | gooey/tests/test_cli.py | 21 | # print(cli.formValidationCmd('target', 'cmd', positionals, optionals)) | COMMENT |
| LOW | gooey/tests/test_filtering.py | 41 | TestData({'choice_tokenizer': PrefixTokenizers.ENTIRE_PHRASE}, 'Afghan', [p.kabul]), | COMMENT |
| LOW | gooey/python_bindings/argparse_to_json.py | 241 | def reapply_mutex_groups(mutex_groups, action_groups): | COMMENT |
| LOW | gooey/python_bindings/argparse_to_json.py | 661 | 'BlockCheckbox', | COMMENT |
| LOW | gooey/python_bindings/dynamics.py | 181 | # lift_actions_mutating(subparser) | COMMENT |
| LOW | gooey/gui/state.py | 161 | def cmdOrPlaceholderOrNone(item: EnrichedItem) -> Optional[str]: | COMMENT |
| LOW | gooey/gui/components/options/validators.py | 181 | # print(validateColor(123.234)) | COMMENT |
| LOW | gooey/gui/components/widgets/bases.py | 41 | def dispatchChange(self, value, **kwargs): | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | gooey/tests/test_time_remaining.py | 34 | CODE | |
| LOW | gooey/tests/test_common.py | 22 | CODE | |
| LOW | gooey/tests/test_radiogroup.py | 22 | CODE | |
| LOW | gooey/tests/test_radiogroup.py | 76 | CODE | |
| LOW | gooey/tests/test_numeric_inputs.py | 65 | CODE | |
| LOW | gooey/python_bindings/argparse_to_json.py | 278 | CODE | |
| LOW | gooey/python_bindings/cmd_args.py | 12 | CODE | |
| LOW | gooey/python_bindings/cmd_args.py | 14 | CODE | |
| LOW | gooey/python_bindings/cmd_args.py | 42 | CODE | |
| LOW | gooey/gui/formatters.py | 11 | CODE | |
| LOW | gooey/gui/formatters.py | 54 | CODE | |
| LOW | gooey/gui/components/footer.py | 58 | CODE | |
| LOW | gooey/gui/components/widgets/dropdown_filterable.py | 180 | CODE | |
| LOW | gooey/gui/containers/application.py | 157 | CODE | |
| LOW | gooey/gui/containers/application.py | 208 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | gooey/tests/processor/test_processor.py | 83 | except KeyboardInterrupt: | CODE |
| HIGH | gooey/gui/three_to_four.py | 8 | except ImportError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | gooey/util/functional.py | 117 | except Exception as e: | CODE |
| MEDIUM | gooey/util/functional.py | 114 | def inner(x) -> Try: | CODE |
| LOW | gooey/python_bindings/control.py | 78 | except Exception as e: | CODE |
| LOW | gooey/python_bindings/control.py | 125 | except Exception as e: | CODE |
| LOW | gooey/python_bindings/control.py | 164 | except Exception as e: | CODE |
| LOW | gooey/python_bindings/dynamics.py | 88 | except Exception as e: | STRING |
| MEDIUM | gooey/python_bindings/dynamics.py | 85 | def update_reg(_self, _action, _value): | CODE |
| LOW | gooey/gui/application/application.py | 315 | except Exception as e: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | gooey/tests/test_filtering.py | 60 | # In this example, we index the choices under PHRASE, but set the input | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | gooey/tests/test_config_generator.py | 28 | # if no description is provided anywhere, we just set it to be an empty string. | COMMENT |
| MEDIUM | gooey/tests/test_filtering.py | 69 | # the default AND behavior can be swapped to OR to facilitate matching across | COMMENT |
| LOW | gooey/gui/components/widgets/radio_group.py | 47 | # just return the first widget's value even though it's | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | gooey/gui/processor.py | 141 | CODE | |
| LOW | gooey/gui/components/options/options.py | 49 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | gooey/gui/lang/i18n.py | 14 | __all__ = ['load', '_'] | CODE |