Coverage for src/tkinterquickhelper/funcwin/function_helper.py: 71%
105 statements
« prev ^ index » next coverage.py v7.1.0, created at 2024-04-25 05:39 +0200
« prev ^ index » next coverage.py v7.1.0, created at 2024-04-25 05:39 +0200
1# -*- coding: utf-8 -*-
2"""
3@file
4@brief Various function needed when using the windows used to ask for parameters
5"""
6import sys
7import re
8import inspect
9import datetime
10from pyquickhelper.loghelper.flog import guess_machine_parameter
13def get_function_list(module):
14 """
15 Extracts all functions in a module.
17 @param module a object module
18 @return the list of function included in a module, dictionary { name, object }
19 """
20 res = {}
21 d = module.__dict__
22 for k, v in d.items():
23 if isinstance(v, get_function_list.__class__):
24 res[k] = v
25 return res
28def has_unknown_parameters(func):
29 """
30 Returns True if the function contains a parameter like ``**params``.
32 @param func function
33 @return True if the function contains something like ``**params``
34 """
35 # de = func.__defaults__
36 # na = func.__code__.co_varnames
37 keys = inspect.signature(func)
38 return "**" in str(keys)
41def extract_function_information(function):
42 """
43 Extracts information about a function.
44 The function assumes all parameters receive a default value.
46 @param function function object
47 @return dictionary { info : value }
49 The returned dictionary will be composed as follows:
50 - name: name of the function
51 - nbpar: number of parameters
52 - param: list of parameters (dictionary) and their default value
53 - types: type of parameters (dictionary), if the default value does not exist,
54 the function will look in the help looking for the following:
55 @code
56 param name (type)
57 @endcode
58 - help: documentation of the function
59 - helpparam: help associated to each parameters (dictionary),
60 assuming they are described in the documentation using
61 the same format as this docstring
62 - module: module which defines the function
63 """
64 if function.__doc__ is None:
65 raise RuntimeError(
66 "the function given to FrameFunction should be documented: help is displayed,"
67 " if you want parameter to be described, use javadoc format to do so: "
68 "@<tag> param_name param_meaning with tag=param")
70 res = dict()
71 res["name"] = function.__name__
72 nbp = function.__code__.co_argcount
73 par = function.__code__.co_varnames[:nbp]
74 res["nbpar"] = len(par)
75 defd = function.__defaults__ if function.__defaults__ is not None else []
76 dec = len(par) - len(defd)
78 typ = {}
79 p = {}
80 for pos, a in enumerate(par):
81 if a == 'fLOG':
82 continue
83 p2 = pos - dec
84 if p2 >= 0:
85 b = defd[p2]
86 typ[a] = b.__class__
87 else:
88 b = ""
89 typ[a] = None
90 if not a.startswith("_"):
91 p[a] = b
93 res["types"] = typ
94 res["param"] = p
95 res["help"] = function.__doc__
97 mod = function.__module__
98 mod = sys.modules.get(mod, None)
99 res["module"] = mod
101 regex = re.compile("@" + "param +([a-zA-Z0-9_]+) +(.+)")
102 alls = regex.findall(res["help"])
103 p = {}
104 for a, b in alls:
105 a = a.strip()
106 if a == "fLOG":
107 continue
108 p[a] = b.strip()
109 res["helpparam"] = p
111 reg = re.compile(
112 "@" + "param +([a-zA-Z_][a-zA-Z_0-9]*?) +[(]([a-zA-Z]+?)[)]")
113 alls = reg.findall(res["help"])
114 typ = {k: v for k, v in alls} # pylint: disable=R1721
115 keys = list(res["types"])
116 for a in keys:
117 b = res["types"][a]
118 if b is None or isinstance(None, b):
119 b = typ.get(a, None)
120 if b is not None:
121 if "|" in b:
122 e, ee = b.split("|")
123 e = eval(e)
124 ee = eval(ee)
125 res["types"][a] = lambda v, e=e, ee=ee: ee if (
126 len(v) == 0 or v == str(ee)) else e(v)
127 elif b == "datetime":
128 res["types"][a] = datetime.datetime
129 else:
130 res["types"][a] = eval(b)
132 # If no default value, we assume the type is str.
133 keys = list(res["types"])
134 for a in keys:
135 b = res["types"][a]
136 if b is None:
137 res[b] = str
139 return res
142def private_adjust_parameters(param):
143 """
144 Change the value of some parameters when they are NULL:
145 *user*. Changes the parameters inplace.
147 @param param list of parameters
148 """
149 res = guess_machine_parameter()
150 for k in param:
151 if param[k] is None and k.lower() in ["user", "username"]:
152 res[k] = res.get("USERNAME", res["USER"])
155def private_get_function(function_name):
156 """
157 Returns the function object from its name, the name
158 must contains a dot "." otherwise the function will assume
159 it is defined in module @see md default_functions.
161 @param function_name name of the function
162 @return object
163 """
164 if "." in function_name:
165 module = function_name.split(".")
166 name = module[-1]
167 fname = ".".join(module[:-1])
169 if fname in sys.modules:
170 mod = sys.modules[fname]
171 else:
172 mod = __import__(fname, globals(), locals(), [], 0)
174 if name not in mod.__dict__:
175 raise KeyError("module %s, function %s not in %s (path %s)" %
176 (module, name, str(mod.__dict__.keys()), mod.__file__))
177 return mod.__dict__[name]
178 else:
179 from .default_functions import file_grep, file_list, file_split, file_head, test_regular_expression
180 if function_name == "file_grep":
181 return file_grep
182 elif function_name == "file_list":
183 return file_list
184 elif function_name == "file_split":
185 return file_split
186 elif function_name == "file_head":
187 return file_head
188 elif function_name == "test_regular_expression":
189 return test_regular_expression
190 else:
191 raise NameError("unknown exception " + function_name)