forked from robcarver17/pysystemtrade
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinteractively_run_functions.py
137 lines (107 loc) · 4.1 KB
/
interactively_run_functions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import inspect
NO_DEFAULT = object()
NO_TYPE_PROVIDED = object()
NO_VALID_ARGUMENT_PASSED = object()
def parameter_default(parameter_signature):
default = parameter_signature.default
if default is inspect._empty:
default = NO_DEFAULT
return default
def has_default(parameter_signature):
return parameter_default(parameter_signature) is not NO_DEFAULT
def parameter_type(parameter_signature):
ptype = parameter_signature.annotation
if ptype is inspect._empty:
# get from default
if has_default(parameter_signature):
default_value = parameter_default(parameter_signature)
ptype = type(default_value)
else:
# give up
return NO_TYPE_PROVIDED
return ptype.__name__
def has_type(parameter_signature):
return parameter_type(parameter_signature) is not NO_TYPE_PROVIDED
def input_and_type_cast_argument(argname, parameter_signature):
"""
Interactively get a value for a parameter, considering any type casting required or defaults
:param argname: str
:param parameter_signature: results of doing inspect.signature(func)['parameter name']
:return: argument value
"""
default_provided = has_default(parameter_signature)
needs_casting = has_type(parameter_signature)
if default_provided:
argdefault = parameter_default(parameter_signature)
if needs_casting:
type_to_cast_to = parameter_type(parameter_signature)
# Should never return this unless something gone horribly wrong
arg_value = NO_VALID_ARGUMENT_PASSED
while arg_value is NO_VALID_ARGUMENT_PASSED:
if default_provided:
default_string = " (default: '%s')" % str(argdefault)
else:
default_string = ""
if needs_casting:
type_string = " (type: %s)" % str(type_to_cast_to)
else:
type_string = ""
arg_value = input(
"Argument %s %s %s?" %
(argname, default_string, type_string))
if arg_value == "": # just pressed carriage return...
if default_provided:
arg_value = argdefault
break
else:
print(
"No default provided for %s - need a value. Please type something!" %
argname)
arg_value = NO_VALID_ARGUMENT_PASSED
else:
# A value has been typed - check if needs type casting
if needs_casting:
try:
# Cast the type
# this might not work
type_func = eval("%s" % type_to_cast_to)
arg_value = type_func(arg_value)
break
except BaseException:
print(
"\nCouldn't cast value %s to type %s\n"
% (arg_value, type_to_cast_to)
)
arg_value = NO_VALID_ARGUMENT_PASSED
else:
# no type casting required
pass
return arg_value
def fill_args_and_run_func(func, full_funcname):
"""
Prints the docstring of func, then asks for all of its arguments with defaults
Optionally casts to type, if any argument name is an entry in the dict type_casting
"""
# print doc string
print("\n")
print(full_funcname + ":")
print(inspect.getdoc(func))
print("\n")
func_arguments = inspect.signature(func).parameters
print("\nArguments:")
print(list(func_arguments.keys()))
print("\n")
args = []
kwargs = dict()
for (argname, parameter_signature) in func_arguments.items():
arg_value = input_and_type_cast_argument(argname, parameter_signature)
if arg_value is NO_VALID_ARGUMENT_PASSED:
raise Exception(
"Invalid argument passed - should not happen - check function 'input_and_type_cast_argument' logic"
)
is_kwarg = has_default(parameter_signature)
if is_kwarg:
kwargs[argname] = arg_value
else:
args.append(arg_value)
return args, kwargs