Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/plotext/_doc_utils.py: 92%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

219 statements  

1# this file contains all tools necessary to build the docstrings in _doc.py 

2 

3from plotext._utility import pad_string, colorize, uncolorize 

4from inspect import getfullargspec as args 

5from re import sub 

6import copy 

7 

8 

9 

10method_name_color = 'blue+' 

11method_name_style = 'bold' 

12alias_style = 'italic' 

13 

14parameters_title_color = 'none' 

15parameters_title_style = 'none' 

16 

17parameter_name_color = 'red+' 

18parameter_name_style = 'bold' 

19 

20parameter_specs_color = 'orange+' 

21parameter_specs_style = 'dim' 

22 

23parameter_doc_style = 'italic' 

24 

25return_color = 'orange+' 

26return_style = 'bold' 

27 

28warning = colorize('Warning', 'orange', 'bold') 

29 

30nl = '\n' 

31sp = ' ' 

32cm = ', ' 

33sc = '; ' 

34 

35def correct_doc(doc): 

36 doc = doc.strip() 

37 doc = doc[:1].upper() + doc[1:] 

38 doc = doc if len(doc) == 0 or doc[-1] == '.' else doc + '.' 

39 doc = sub(' ', ' ', doc) 

40 return doc 

41 

42class parameter_class(): # parameter doc 

43 def __init__(self, name, doc = '', type = '', default = ''): 

44 self.name = name.lower() 

45 self.doc = correct_doc(doc) 

46 self.type = None if type is None else str(type) 

47 self.set_default(default) 

48 

49 def set_default(self, default = ''): 

50 if default == '': 

51 self.default = '' 

52 elif isinstance(default, str): 

53 self.default = "'" + default + "'" 

54 elif isinstance(default, float): 

55 self.default = str(round(default, 3)) 

56 else: 

57 self.default = str(default) 

58 

59 def get_doc(self): 

60 name = colorize(self.name, parameter_name_color, parameter_name_style) 

61 type = '' if self.type == '' else 'type: ' + str(self.type) 

62 default = '' if self.default == '' else 'default: ' + self.default 

63 specs = sc.join([spec for spec in [type, default] if spec != '']) 

64 specs = nl + colorize(specs, parameter_specs_color, parameter_specs_style) if specs != '' else '' 

65 doc = colorize(self.doc, style = parameter_doc_style) 

66 return nl + name + sp + doc + specs 

67 

68 def copy(self, default = ''): 

69 par = copy.copy(self) 

70 par.set_default(default) 

71 return par 

72 

73 

74class parameters_class(): 

75 def __init__(self): 

76 self.list = [] 

77 

78 def append(self, parameter): 

79 self.list.append(parameter) 

80 

81 def add(self, name, doc = '', type = '', default = ''): 

82 self.append(parameter_class(name, doc, type, default)) 

83 

84 def get_title(self): 

85 lp = len(self.list) 

86 title = 'This is its parameter:' if lp == 1 else 'These are its parameters:' 

87 return colorize(title, parameters_title_color, parameters_title_style) 

88 

89 def get_doc(self): 

90 docs = [el.get_doc() for el in self.list] 

91 return nl + self.get_title() + nl + nl.join(docs) if len(self.list) != 0 else '' 

92 

93 def get_parameter(self, name): 

94 names = [el.name for el in self.list] 

95 if name not in names: 

96 print(warning, 'no parameter', name, 'found') 

97 index = names.index(name) if name in names else None 

98 return self.list[index] if name in names else None 

99 

100 

101 

102class output_class(): 

103 def __init__(self, doc = '', type = None): 

104 self.type = type 

105 self.doc = correct_doc(doc) 

106 

107 def get_doc(self): 

108 title = colorize('Returns', return_color, return_style) 

109 type = '' if self.type is None else 'type: ' + str(self.type) 

110 type = colorize(type , parameter_specs_color, parameter_specs_style) if type != '' else '' 

111 doc = colorize(self.doc, style = parameter_doc_style) 

112 return nl + title + sp + doc + nl + type if self.doc != '' else '' 

113 

114 

115class method_class(): 

116 def __init__(self, name, alias = None): 

117 self.name = name.lower() 

118 self.set_doc() 

119 self.alias = alias 

120 

121 self.parameters = parameters_class() 

122 self.set_output() 

123 self.status = False 

124 

125 def set_doc(self, doc = ''): 

126 self.doc = correct_doc(doc) 

127 

128 def set_output(self, doc = '', type = ''): 

129 self.output = output_class(doc, type) 

130 

131 def append_parameter(self, parameter_object): 

132 self.parameters.append(parameter_object) 

133 

134 def add_parameter(self, name, doc = '', type = '', default = ''): 

135 self.parameters.add(name, doc, type, default) 

136 

137 def get_title(self): 

138 return colorize(self.name, method_name_color, method_name_style) 

139 

140 def get_doc(self): 

141 alias = (nl + "The methods " + colorize(self.name + '()', style = alias_style) + ' and ' + colorize(self.alias + '()', style = alias_style) + ' are equivalent.') if self.alias != '' else '' 

142 pars = self.parameters.get_doc() 

143 out = self.output.get_doc() 

144 return nl.join([el for el in [self.doc, alias, pars, out] if el != '']) 

145 

146 def get_parameters(self): 

147 return [el.name for el in self.parameters.list] 

148 

149 def get_parameter(self, name): 

150 return self.parameters.get_parameter(name) 

151 

152 def show(self): 

153 print(self.get_doc()) 

154 

155 

156def get_parameters(method): 

157 spec = args(method) 

158 parameters = ([spec.varargs] if spec.varargs is not None else []) + spec.args + spec.kwonlyargs 

159 parameters = [el for el in parameters if el != 'self'] 

160 #defaults = spec.defaults if spec.defaults is not None else spec.kwonlydefaults.values() if spec.kwonlydefaults is not None else [] 

161 #lp, ld = len(parameters), len(defaults) 

162 #defaults = [None] * (lp - ld) + list(defaults) 

163 #return [(parameters[i], defaults[i]) for i in range(lp)] 

164 return parameters#, defaults 

165 

166 

167class documentation_class(): # a list of method_class objects 

168 "It contains the doc-strings of all the main plotext functions." 

169 

170 def __init__(self): 

171 self._methods = [] 

172 

173 def _add_method(self, name, alias = ''): 

174 method = method_class(name, alias) 

175 self._methods.append(method) 

176 setattr(self, name, method.show) 

177 

178 def _last(self): 

179 return self._methods[-1] 

180 

181 def _set_doc(self, doc): 

182 self._last().set_doc(doc) 

183 

184 def _add_parameter(self, name, doc = '', type = '', default = ''): 

185 self._last().add_parameter(name, doc, type, default) 

186 

187 def _set_output(self, doc = '', type = ''): 

188 self._last().set_output(doc, type) 

189 

190 def _get_method(self, name): 

191 names = [el.name for el in self._methods] 

192 if name not in names: 

193 print(warning, 'no method', name + '() found') 

194 return self._methods[names.index(name)] if name in names else None 

195 

196 def _get_parameters(self, parameter, method): 

197 method = self.get_method(method) 

198 return method.get_parameters(parameter) if method is not None else None 

199 

200 def _add_past_parameter(self, name, method, default = None): 

201 method = self._get_method(method) 

202 parameter = method.get_parameter(name) if method is not None else None 

203 parameter = parameter if default is None else parameter.copy(default) 

204 self._last().append_parameter(parameter) if parameter is not None else None 

205 

206 def _set_past_output(self, method): 

207 method = self.get_method(method) 

208 output = method.output 

209 self._set_output(output.type, output.doc) 

210 

211 def all(self): 

212 docs = (nl * 3).join([el.get_title() + nl + el.get_doc() for el in self._methods if el.status in [0, 1]]) 

213 print(docs) 

214 

215 def _add_function(self, function): 

216 name = function.__name__ 

217 method = self._get_method(name) 

218 name += '()' 

219 if method is None: 

220 print(warning, name, "doc not present") 

221 return 

222 doc = method.get_doc() 

223 function.__doc__ = uncolorize(doc) 

224 function.doc = lambda: print(doc) 

225 parameters_actual = get_parameters(function) 

226 parameters_found = method.get_parameters() 

227 if parameters_actual != parameters_found: 

228 actual = colorize(cm.join(parameters_actual), style = 'italic') 

229 found = colorize(cm.join(parameters_found), style = 'italic') 

230 print(warning, "the parameters of", name, "are", actual, "not", found + '.') 

231 

232 

233class parameter_types(): 

234 def __init__(self): 

235 self.int = 'an integer' 

236 self.float = 'a float' 

237 self.num = 'a number' 

238 self.str = 'a string' 

239 self.bool = 'a Boolean' 

240 

241 

242 self.ints = 'integers' 

243 self.floats = 'floats' 

244 self.nums = 'numbers' 

245 self.strs = 'strings' 

246 self.bools = 'Booleans' 

247 

248 self.list_int = lambda n = 'many': self.plural(self.ints, n) 

249 self.list_float = lambda n = 'many': self.plural(self.floats, n) 

250 self.list_num = lambda n = 'many': self.plural(self.nums, n) 

251 self.list_str = lambda n = 'many': self.plural(self.strs, n) 

252 self.list_bool = lambda n = 'many': self.plural(self.bools, n) 

253 

254 self.fig = 'a plotext figure' 

255 self.xy = 'one or two lists of numbers or string dates' 

256 self.multiple_xy = 'an optional list of numbers or date strings and a mandatory matrix of numbers' 

257 self.x = 'a list of numbers or string dates' 

258 self.marker = 'a string or a list of strings' 

259 self.color = 'a string or an integer (from 0 to 255) or a tuple of 3 integers (from 0 to 255)' 

260 self.colors = 'strings or integers (from 0 to 255) or tuples of 3 integers (from 0 to 255)' 

261 self.list_color = lambda n = 'many': self.plural(self.colors, n) 

262 self.color_list = self.color + ' or a list of those' 

263 self.str_list = self.mix(self.str, self.list_str()) 

264 

265 self.str_int = self.mix(self.str, self.int) 

266 self.str_num = self.mix(self.str, self.num) 

267 self.list_str_num = lambda n = 'many': self.plural(self.mix(self.strs, self.nums), n) 

268 self.list_num_bool = lambda n = 'many': self.plural(self.mix(self.nums, self.bools), n) 

269 self.bool_num_str = self.mix(self.bool, self.num, self.str) 

270 self.dic = "a dictionary with mandatory keys: 'Open', 'Close', 'High', 'Low'; each value should be a list of numbers." 

271 self.matrix = 'a list of numbers or a list of tuples 3 integers (from 0 to 255)' 

272 self.datetime = 'a datetime object' 

273 self.list_datetime = self.plural(self.datetime) 

274 self.data = 'a 2 dimensional matrix of numbers or strings' 

275 

276 def plural(self, type, n = 'many'): 

277 return 'a list of ' + (str(n) + sp if not isinstance(n, str) else '') + type 

278 

279 def mix(self, *types): 

280 return ' or '.join(types) 

281 

282documentation = documentation_class() 

283method = documentation._add_method 

284doc = documentation._set_doc 

285par = documentation._add_parameter 

286past = documentation._add_past_parameter 

287out = documentation._set_output 

288past_out = documentation._set_past_output 

289add = documentation._add_function 

290 

291t = parameter_types()