From be1343b6daadfe7d455d1bfc81b7aa39c750b2d7 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 9 Mar 2019 17:16:42 -0800 Subject: [PATCH] closes #377 - drop all non-serializable objects from default args --- gooey/python_bindings/argparse_to_json.py | 20 +++++++++----- gooey/tests/test_argparse_to_json.py | 33 ++++++++++++++++++----- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/gooey/python_bindings/argparse_to_json.py b/gooey/python_bindings/argparse_to_json.py index eec8ba0..023a2eb 100644 --- a/gooey/python_bindings/argparse_to_json.py +++ b/gooey/python_bindings/argparse_to_json.py @@ -2,6 +2,7 @@ Converts argparse parser actions into json "Build Specs" """ import argparse +import json import os import sys from argparse import ( @@ -457,15 +458,20 @@ def clean_list_defaults(default_values): def clean_default(default): - ''' + """ Attemps to safely coalesce the default value down to a valid JSON type. - - See: Issue #147. - function references supplied as arguments to the - `default` parameter in Argparse cause errors in Gooey. - ''' - return default.__name__ if callable(default) else default + """ + try: + json.dumps(default) + return default + except TypeError as e: + # see: Issue #377 + # if is ins't json serializable (i.e. primitive data) there's nothing + # useful for Gooey to do with it (since Gooey deals in primitive data + # types). So the correct behavior is dropping them. This affects ONLY + # gooey, not the client code. + return None def safe_string(value): diff --git a/gooey/tests/test_argparse_to_json.py b/gooey/tests/test_argparse_to_json.py index f96ab1a..8d18680 100644 --- a/gooey/tests/test_argparse_to_json.py +++ b/gooey/tests/test_argparse_to_json.py @@ -1,5 +1,7 @@ +import sys import unittest from argparse import ArgumentParser + from gooey import GooeyParser from gooey.python_bindings import argparse_to_json from gooey.util.functional import getin @@ -84,12 +86,29 @@ class TestArgparse(unittest.TestCase): result = argparse_to_json.action_to_json(choice_action, 'Listbox', {}) self.assertEqual(getin(result, ['data', 'default']), ['sup']) - def test_callables_as_default_args_are_cast_to_their_name(self): - """ Issue 147 """ - parser = ArgumentParser() - parser.add_argument('--foo', default=max) + def test_non_data_defaults_are_dropped_entirely(self): + """ + This is a refinement in understanding of Issue #147 + + Caused by Issue 377 - passing arbitrary objects as defaults + causes failures. + """ + # passing plain data to cleaning function results in plain data + # being returned + data = ['abc', + 123, + ['a', 'b'], + [1, 2, 3]] + + for datum in data: + result = argparse_to_json.clean_default(datum) + self.assertEqual(result, datum) + + # passing in complex objects results in None + objects = [sys.stdout, sys.stdin, object(), max, min] + + for obj in objects: + result = argparse_to_json.clean_default(obj) + self.assertEqual(result, None) - choice_action = parser._actions[-1] - result = argparse_to_json.action_to_json(choice_action, 'Textfield', {}) - self.assertEqual(getin(result, ['data', 'default']), 'max')