comparison sat_frontends/jp/xmlui_manager.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 620bbcec884c
children fee60f17ebac
comparison
equal deleted inserted replaced
3027:ff5bcb12ae60 3028:ab2696e34d29
58 def disp(self, *args, **kwargs): 58 def disp(self, *args, **kwargs):
59 self.host.disp(*args, **kwargs) 59 self.host.disp(*args, **kwargs)
60 60
61 61
62 class Widget(Base): 62 class Widget(Base):
63 category = u"widget" 63 category = "widget"
64 enabled = True 64 enabled = True
65 65
66 @property 66 @property
67 def name(self): 67 def name(self):
68 return self._xmlui_name 68 return self._xmlui_name
87 if value is None: 87 if value is None:
88 value = self.name 88 value = self.name
89 if self.host.verbosity: 89 if self.host.verbosity:
90 to_disp = [ 90 to_disp = [
91 A.FG_MAGENTA, 91 A.FG_MAGENTA,
92 u" " if elems else u"", 92 " " if elems else "",
93 u"({})".format(value), 93 "({})".format(value),
94 A.RESET, 94 A.RESET,
95 ] 95 ]
96 if elems is None: 96 if elems is None:
97 self.host.disp(A.color(*to_disp)) 97 self.host.disp(A.color(*to_disp))
98 else: 98 else:
164 if no_select or value in self.selected: 164 if no_select or value in self.selected:
165 yield value, label 165 yield value, label
166 166
167 @property 167 @property
168 def inline(self): 168 def inline(self):
169 return u"inline" in self.style 169 return "inline" in self.style
170 170
171 @property 171 @property
172 def no_select(self): 172 def no_select(self):
173 return u"noselect" in self.style 173 return "noselect" in self.style
174 174
175 175
176 class EmptyWidget(xmlui_base.EmptyWidget, Widget): 176 class EmptyWidget(xmlui_base.EmptyWidget, Widget):
177 177
178 def __init__(self, xmlui_parent): 178 def __init__(self, xmlui_parent):
179 Widget.__init__(self, xmlui_parent) 179 Widget.__init__(self, xmlui_parent)
180 180
181 def show(self): 181 def show(self):
182 self.host.disp(u'') 182 self.host.disp('')
183 183
184 184
185 class TextWidget(xmlui_base.TextWidget, ValueWidget): 185 class TextWidget(xmlui_base.TextWidget, ValueWidget):
186 type = u"text" 186 type = "text"
187 187
188 def show(self): 188 def show(self):
189 self.host.disp(self.value) 189 self.host.disp(self.value)
190 190
191 191
192 class LabelWidget(xmlui_base.LabelWidget, ValueWidget): 192 class LabelWidget(xmlui_base.LabelWidget, ValueWidget):
193 type = u"label" 193 type = "label"
194 194
195 @property 195 @property
196 def for_name(self): 196 def for_name(self):
197 try: 197 try:
198 return self._xmlui_for_name 198 return self._xmlui_for_name
199 except AttributeError: 199 except AttributeError:
200 return None 200 return None
201 201
202 def show(self, no_lf=False, ansi=u""): 202 def show(self, no_lf=False, ansi=""):
203 """show label 203 """show label
204 204
205 @param no_lf(bool): same as for [JP.disp] 205 @param no_lf(bool): same as for [JP.disp]
206 @param ansi(unicode): ansi escape code to print before label 206 @param ansi(unicode): ansi escape code to print before label
207 """ 207 """
208 self.disp(A.color(ansi, self.value), no_lf=no_lf) 208 self.disp(A.color(ansi, self.value), no_lf=no_lf)
209 209
210 210
211 class JidWidget(xmlui_base.JidWidget, TextWidget): 211 class JidWidget(xmlui_base.JidWidget, TextWidget):
212 type = u"jid" 212 type = "jid"
213 213
214 class StringWidget(xmlui_base.StringWidget, InputWidget): 214 class StringWidget(xmlui_base.StringWidget, InputWidget):
215 type = u"string" 215 type = "string"
216 216
217 def show(self): 217 def show(self):
218 if self.read_only or self.root.read_only: 218 if self.read_only or self.root.read_only:
219 self.disp(self.value) 219 self.disp(self.value)
220 else: 220 else:
221 elems = [] 221 elems = []
222 self.verboseName(elems) 222 self.verboseName(elems)
223 if self.value: 223 if self.value:
224 elems.append(_(u"(enter: {default})").format(default=self.value)) 224 elems.append(_("(enter: {default})").format(default=self.value))
225 elems.extend([C.A_HEADER, u"> "]) 225 elems.extend([C.A_HEADER, "> "])
226 value = raw_input(A.color(*elems).encode('utf-8')) 226 value = input(A.color(*elems).encode('utf-8'))
227 if value: 227 if value:
228 #  TODO: empty value should be possible 228 #  TODO: empty value should be possible
229 # an escape key should be used for default instead of enter with empty value 229 # an escape key should be used for default instead of enter with empty value
230 self.value = value 230 self.value = value
231 231
232 232
233 class JidInputWidget(xmlui_base.JidInputWidget, StringWidget): 233 class JidInputWidget(xmlui_base.JidInputWidget, StringWidget):
234 type = u"jid_input" 234 type = "jid_input"
235 235
236 236
237 class TextBoxWidget(xmlui_base.TextWidget, StringWidget): 237 class TextBoxWidget(xmlui_base.TextWidget, StringWidget):
238 type = u"textbox" 238 type = "textbox"
239 # TODO: use a more advanced input method 239 # TODO: use a more advanced input method
240 240
241 def show(self): 241 def show(self):
242 self.verboseName() 242 self.verboseName()
243 if self.read_only or self.root.read_only: 243 if self.read_only or self.root.read_only:
244 self.disp(self.value) 244 self.disp(self.value)
245 else: 245 else:
246 if self.value: 246 if self.value:
247 self.disp(A.color(C.A_HEADER, u"↓ current value ↓\n", A.FG_CYAN, self.value, 247 self.disp(A.color(C.A_HEADER, "↓ current value ↓\n", A.FG_CYAN, self.value,
248 "")) 248 ""))
249 249
250 values = [] 250 values = []
251 while True: 251 while True:
252 try: 252 try:
253 if not values: 253 if not values:
254 line = raw_input(A.color(C.A_HEADER, u"[Ctrl-D to finish]> ")) 254 line = input(A.color(C.A_HEADER, "[Ctrl-D to finish]> "))
255 else: 255 else:
256 line = raw_input() 256 line = input()
257 values.append(line) 257 values.append(line)
258 except EOFError: 258 except EOFError:
259 break 259 break
260 260
261 self.value = u'\n'.join(values).rstrip() 261 self.value = '\n'.join(values).rstrip()
262 262
263 263
264 class XHTMLBoxWidget(xmlui_base.XHTMLBoxWidget, StringWidget): 264 class XHTMLBoxWidget(xmlui_base.XHTMLBoxWidget, StringWidget):
265 type = u"xhtmlbox" 265 type = "xhtmlbox"
266 266
267 def show(self): 267 def show(self):
268 # FIXME: we use bridge in a blocking way as permitted by python-dbus 268 # FIXME: we use bridge in a blocking way as permitted by python-dbus
269 # this only for now to make it simpler, it must be refactored 269 # this only for now to make it simpler, it must be refactored
270 # to use async when jp will be fully async (expected for 0.8) 270 # to use async when jp will be fully async (expected for 0.8)
272 self.value, C.SYNTAX_XHTML, "markdown", False, self.host.profile) 272 self.value, C.SYNTAX_XHTML, "markdown", False, self.host.profile)
273 super(XHTMLBoxWidget, self).show() 273 super(XHTMLBoxWidget, self).show()
274 274
275 275
276 class ListWidget(xmlui_base.ListWidget, OptionsWidget): 276 class ListWidget(xmlui_base.ListWidget, OptionsWidget):
277 type = u"list" 277 type = "list"
278 # TODO: handle flags, notably multi 278 # TODO: handle flags, notably multi
279 279
280 def show(self): 280 def show(self):
281 if self.root.values_only: 281 if self.root.values_only:
282 for value in self.values: 282 for value in self.values:
289 self.verboseName() 289 self.verboseName()
290 290
291 for idx, (value, label) in enumerate(self.options): 291 for idx, (value, label) in enumerate(self.options):
292 elems = [] 292 elems = []
293 if not self.root.read_only: 293 if not self.root.read_only:
294 elems.extend([C.A_SUBHEADER, unicode(idx), A.RESET, u": "]) 294 elems.extend([C.A_SUBHEADER, str(idx), A.RESET, ": "])
295 elems.append(label) 295 elems.append(label)
296 self.verboseName(elems, value) 296 self.verboseName(elems, value)
297 self.disp(A.color(*elems)) 297 self.disp(A.color(*elems))
298 298
299 if self.root.read_only: 299 if self.root.read_only:
306 306
307 #  we ask use to choose an option 307 #  we ask use to choose an option
308 choice = None 308 choice = None
309 limit_max = len(self.options) - 1 309 limit_max = len(self.options) - 1
310 while choice is None or choice < 0 or choice > limit_max: 310 while choice is None or choice < 0 or choice > limit_max:
311 choice = raw_input( 311 choice = input(
312 A.color(C.A_HEADER, _(u"your choice (0-{max}): ").format(max=limit_max)) 312 A.color(C.A_HEADER, _("your choice (0-{max}): ").format(max=limit_max))
313 ) 313 )
314 try: 314 try:
315 choice = int(choice) 315 choice = int(choice)
316 except ValueError: 316 except ValueError:
317 choice = None 317 choice = None
318 self.value = self.options[choice][0] 318 self.value = self.options[choice][0]
319 self.disp("") 319 self.disp("")
320 320
321 321
322 class BoolWidget(xmlui_base.BoolWidget, InputWidget): 322 class BoolWidget(xmlui_base.BoolWidget, InputWidget):
323 type = u"bool" 323 type = "bool"
324 324
325 def show(self): 325 def show(self):
326 disp_true = A.color(A.FG_GREEN, u"TRUE") 326 disp_true = A.color(A.FG_GREEN, "TRUE")
327 disp_false = A.color(A.FG_RED, u"FALSE") 327 disp_false = A.color(A.FG_RED, "FALSE")
328 if self.read_only or self.root.read_only: 328 if self.read_only or self.root.read_only:
329 self.disp(disp_true if self.value else disp_false) 329 self.disp(disp_true if self.value else disp_false)
330 else: 330 else:
331 self.disp(A.color(C.A_HEADER, u"0: ", 331 self.disp(A.color(C.A_HEADER, "0: ",
332 disp_false, A.RESET, 332 disp_false, A.RESET,
333 u" *" if not self.value else u"")) 333 " *" if not self.value else ""))
334 self.disp(A.color(C.A_HEADER, u"1: ", 334 self.disp(A.color(C.A_HEADER, "1: ",
335 disp_true, A.RESET, 335 disp_true, A.RESET,
336 u" *" if self.value else u"")) 336 " *" if self.value else ""))
337 choice = None 337 choice = None
338 while choice not in ("0", "1"): 338 while choice not in ("0", "1"):
339 elems = [C.A_HEADER, _(u"your choice (0,1): ")] 339 elems = [C.A_HEADER, _("your choice (0,1): ")]
340 self.verboseName(elems) 340 self.verboseName(elems)
341 choice = raw_input(A.color(*elems)) 341 choice = input(A.color(*elems))
342 self.value = bool(int(choice)) 342 self.value = bool(int(choice))
343 self.disp("") 343 self.disp("")
344 344
345 def _xmluiGetValue(self): 345 def _xmluiGetValue(self):
346 return C.boolConst(self.value) 346 return C.boolConst(self.value)
348 348
349 ## Containers ## 349 ## Containers ##
350 350
351 351
352 class Container(Base): 352 class Container(Base):
353 category = u"container" 353 category = "container"
354 354
355 def __init__(self, xmlui_parent): 355 def __init__(self, xmlui_parent):
356 super(Container, self).__init__(xmlui_parent) 356 super(Container, self).__init__(xmlui_parent)
357 self.children = [] 357 self.children = []
358 358
369 for child in self.children: 369 for child in self.children:
370 child.show() 370 child.show()
371 371
372 372
373 class VerticalContainer(xmlui_base.VerticalContainer, Container): 373 class VerticalContainer(xmlui_base.VerticalContainer, Container):
374 type = u"vertical" 374 type = "vertical"
375 375
376 376
377 class PairsContainer(xmlui_base.PairsContainer, Container): 377 class PairsContainer(xmlui_base.PairsContainer, Container):
378 type = u"pairs" 378 type = "pairs"
379 379
380 380
381 class LabelContainer(xmlui_base.PairsContainer, Container): 381 class LabelContainer(xmlui_base.PairsContainer, Container):
382 type = u"label" 382 type = "label"
383 383
384 def show(self): 384 def show(self):
385 for child in self.children: 385 for child in self.children:
386 no_lf = False 386 no_lf = False
387 # we check linked widget type 387 # we check linked widget type
388 # to see if we want the label on the same line or not 388 # to see if we want the label on the same line or not
389 if child.type == u"label": 389 if child.type == "label":
390 for_name = child.for_name 390 for_name = child.for_name
391 if for_name: 391 if for_name:
392 for_widget = self.root.widgets[for_name] 392 for_widget = self.root.widgets[for_name]
393 wid_type = for_widget.type 393 wid_type = for_widget.type
394 if self.root.values_only or wid_type in ( 394 if self.root.values_only or wid_type in (
533 pass 533 pass
534 534
535 def _launchActionCb(self, data): 535 def _launchActionCb(self, data):
536 XMLUIPanel._actions -= 1 536 XMLUIPanel._actions -= 1
537 assert XMLUIPanel._actions >= 0 537 assert XMLUIPanel._actions >= 0
538 if u"xmlui" in data: 538 if "xmlui" in data:
539 xmlui_raw = data["xmlui"] 539 xmlui_raw = data["xmlui"]
540 xmlui = create(self.host, xmlui_raw) 540 xmlui = create(self.host, xmlui_raw)
541 xmlui.show() 541 xmlui.show()
542 if xmlui.submit_id: 542 if xmlui.submit_id:
543 xmlui.onFormSubmitted() 543 xmlui.onFormSubmitted()
555 data, 555 data,
556 self.profile, 556 self.profile,
557 callback=self._launchActionCb, 557 callback=self._launchActionCb,
558 errback=partial( 558 errback=partial(
559 self.command.errback, 559 self.command.errback,
560 msg=_(u"can't launch XMLUI action: {}"), 560 msg=_("can't launch XMLUI action: {}"),
561 exit_code=C.EXIT_BRIDGE_ERRBACK, 561 exit_code=C.EXIT_BRIDGE_ERRBACK,
562 ), 562 ),
563 ) 563 )
564 564
565 565