1
2 '''
3 # DESCRIPTION:
4 # Text formatting and colouring tools
5
6 Copyright 1998-2004 Gentoo Foundation
7 # $Id: output.py 4906 2006-11-01 23:55:29Z zmedico $
8 Copyright (C) 2007-2008 Fabio Erculiani
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 '''
24
25 import sys, os
26 import curses
27 from entropy.const import etpUi
28 from entropy.exceptions import IncorrectParameter
29 from entropy.i18n import _
30 stuff = {}
31 stuff['cols'] = 30
32 try:
33 curses.setupterm()
34 stuff['cols'] = curses.tigetnum('cols')
35 except:
36 pass
37 stuff['cleanline'] = ""
39 stuff['cleanline'] = ""
40 count = stuff['cols']
41 while count:
42 stuff['cleanline'] += ' '
43 count -= 1
44 setcols()
45 stuff['cursor'] = False
46 stuff['ESC'] = chr(27)
47
48 havecolor=1
49 global dotitles
50 dotitles=1
51
52 esc_seq = "\x1b["
53
54 g_attr = {}
55 g_attr["normal"] = 0
56
57 g_attr["bold"] = 1
58 g_attr["faint"] = 2
59 g_attr["standout"] = 3
60 g_attr["underline"] = 4
61 g_attr["blink"] = 5
62 g_attr["overline"] = 6
63 g_attr["reverse"] = 7
64 g_attr["invisible"] = 8
65
66 g_attr["no-attr"] = 22
67 g_attr["no-standout"] = 23
68 g_attr["no-underline"] = 24
69 g_attr["no-blink"] = 25
70 g_attr["no-overline"] = 26
71 g_attr["no-reverse"] = 27
72
73
74 g_attr["black"] = 30
75 g_attr["red"] = 31
76 g_attr["green"] = 32
77 g_attr["yellow"] = 33
78 g_attr["blue"] = 34
79 g_attr["magenta"] = 35
80 g_attr["cyan"] = 36
81 g_attr["white"] = 37
82
83 g_attr["default"] = 39
84 g_attr["bg_black"] = 40
85 g_attr["bg_red"] = 41
86 g_attr["bg_green"] = 42
87 g_attr["bg_yellow"] = 43
88 g_attr["bg_blue"] = 44
89 g_attr["bg_magenta"] = 45
90 g_attr["bg_cyan"] = 46
91 g_attr["bg_white"] = 47
92 g_attr["bg_default"] = 49
93
94
95
96 -def color(fg, bg="default", attr=["normal"]):
97 mystr = esc_seq[:] + "%02d" % g_attr[fg]
98 for x in [bg]+attr:
99 mystr += ";%02d" % g_attr[x]
100 return mystr+"m"
101
102
103
104 codes={}
105 codes["reset"] = esc_seq + "39;49;00m"
106
107 codes["bold"] = esc_seq + "01m"
108 codes["faint"] = esc_seq + "02m"
109 codes["standout"] = esc_seq + "03m"
110 codes["underline"] = esc_seq + "04m"
111 codes["blink"] = esc_seq + "05m"
112 codes["overline"] = esc_seq + "06m"
113
114 ansi_color_codes = []
115 for x in xrange(30, 38):
116 ansi_color_codes.append("%im" % x)
117 ansi_color_codes.append("%i;01m" % x)
118
119 rgb_ansi_colors = ['0x000000', '0x555555', '0xAA0000', '0xFF5555', '0x00AA00',
120 '0x55FF55', '0xAA5500', '0xFFFF55', '0x0000AA', '0x5555FF', '0xAA00AA',
121 '0xFF55FF', '0x00AAAA', '0x55FFFF', '0xAAAAAA', '0xFFFFFF']
122
123 for x in xrange(len(rgb_ansi_colors)):
124 codes[rgb_ansi_colors[x]] = esc_seq + ansi_color_codes[x]
125
126 del x
127
128 codes["black"] = codes["0x000000"]
129 codes["darkgray"] = codes["0x555555"]
130
131 codes["red"] = codes["0xFF5555"]
132 codes["darkred"] = codes["0xAA0000"]
133
134 codes["green"] = codes["0x55FF55"]
135 codes["darkgreen"] = codes["0x00AA00"]
136
137 codes["yellow"] = codes["0xFFFF55"]
138 codes["brown"] = codes["0xAA5500"]
139
140 codes["blue"] = codes["0x5555FF"]
141 codes["darkblue"] = codes["0x0000AA"]
142
143 codes["fuchsia"] = codes["0xFF55FF"]
144 codes["purple"] = codes["0xAA00AA"]
145
146 codes["turquoise"] = codes["0x55FFFF"]
147 codes["teal"] = codes["0x00AAAA"]
148
149 codes["white"] = codes["0xFFFFFF"]
150 codes["lightgray"] = codes["0xAAAAAA"]
151
152 codes["darkteal"] = codes["turquoise"]
153 codes["darkyellow"] = codes["brown"]
154 codes["fuscia"] = codes["fuchsia"]
155 codes["white"] = codes["bold"]
156
157
158 codes["GOOD"] = codes["green"]
159 codes["WARN"] = codes["yellow"]
160 codes["BAD"] = codes["red"]
161 codes["HILITE"] = codes["teal"]
162 codes["BRACKET"] = codes["blue"]
163
164
165 codes["INFORM"] = codes["darkgreen"]
166 codes["UNMERGE_WARN"] = codes["red"]
167 codes["MERGE_LIST_PROGRESS"] = codes["yellow"]
168
170 """
171 Set new xterm title.
172
173 @param mystr: new xterm title
174 @type mystr: string
175 @keyword raw: write title in raw mode
176 @type raw: bool
177 """
178 if dotitles and "TERM" in os.environ and sys.stderr.isatty():
179 myt = os.environ["TERM"]
180 legal_terms = ["xterm","Eterm","aterm","rxvt","screen","kterm","rxvt-unicode","gnome"]
181 if myt in legal_terms:
182 if not raw:
183 mystr = "\x1b]0;%s\x07" % mystr
184 try:
185 sys.stderr.write(mystr)
186 except UnicodeEncodeError:
187 sys.stderr.write(mystr.encode('utf-8'))
188 sys.stderr.flush()
189
190 default_xterm_title = None
191
214
216 """
217 Turn off title setting. In this way, xterm title won't be touched.
218 """
219 global dotitles
220 dotitles=0
221
223 """
224 Turn off colorization process-wide.
225 """
226 os.environ['ETP_NO_COLOR'] = "1"
227 global havecolor
228 havecolor=0
229
230 nc = os.getenv("ETP_NO_COLOR")
231 if nc:
232 nocolor()
233
235 """
236 Reset terminal color currently set.
237 """
238 return codes["reset"]
239
241 """
242 Colorize text with given color key using bash/terminal codes.
243
244 @param color_key: color identifier available in entropy.output.codes
245 @type color_key: string
246 @return: coloured text
247 @rtype: string
248 """
249 if etpUi['mute']:
250 return text
251 global havecolor
252 if havecolor:
253 return codes[color_key] + text + codes["reset"]
254 return text
255
257 """
258 Make text bold using bash/terminal codes.
259
260 @param text: text to colorize
261 @type text: string
262 @return: colorized text
263 @rtype: string
264 """
265 return colorize("bold", text)
266
268 """
269 Make text white using bash/terminal codes.
270
271 @param text: text to colorize
272 @type text: string
273 @return: colorized text
274 @rtype: string
275 """
276 return colorize("white", text)
277
279 """
280 Make text teal using bash/terminal codes.
281
282 @param text: text to colorize
283 @type text: string
284 @return: colorized text
285 @rtype: string
286 """
287 return colorize("teal", text)
288
290 """
291 Make text turquoise using bash/terminal codes.
292
293 @param text: text to colorize
294 @type text: string
295 @return: colorized text
296 @rtype: string
297 """
298 return colorize("turquoise", text)
299
301 """
302 Make text darkteal using bash/terminal codes.
303
304 @param text: text to colorize
305 @type text: string
306 @return: colorized text
307 @rtype: string
308 """
309 return colorize("darkteal", text)
310
312 """
313 Make text purple using bash/terminal codes.
314
315 @param text: text to colorize
316 @type text: string
317 @return: colorized text
318 @rtype: string
319 """
320 return colorize("purple", text)
321
323 """
324 Make text blue using bash/terminal codes.
325
326 @param text: text to colorize
327 @type text: string
328 @return: colorized text
329 @rtype: string
330 """
331 return colorize("blue", text)
332
334 """
335 Make text darkblue using bash/terminal codes.
336
337 @param text: text to colorize
338 @type text: string
339 @return: colorized text
340 @rtype: string
341 """
342 return colorize("darkblue", text)
343
345 """
346 Make text green using bash/terminal codes.
347
348 @param text: text to colorize
349 @type text: string
350 @return: colorized text
351 @rtype: string
352 """
353 return colorize("green", text)
354
356 """
357 Make text darkgreen using bash/terminal codes.
358
359 @param text: text to colorize
360 @type text: string
361 @return: colorized text
362 @rtype: string
363 """
364 return colorize("darkgreen", text)
365
367 """
368 Make text yellow using bash/terminal codes.
369
370 @param text: text to colorize
371 @type text: string
372 @return: colorized text
373 @rtype: string
374 """
375 return colorize("yellow", text)
376
378 """
379 Make text brown using bash/terminal codes.
380
381 @param text: text to colorize
382 @type text: string
383 @return: colorized text
384 @rtype: string
385 """
386 return colorize("brown", text)
387
389 """
390 Make text darkyellow using bash/terminal codes.
391
392 @param text: text to colorize
393 @type text: string
394 @return: colorized text
395 @rtype: string
396 """
397 return colorize("darkyellow", text)
398
400 """
401 Make text red using bash/terminal codes.
402
403 @param text: text to colorize
404 @type text: string
405 @return: colorized text
406 @rtype: string
407 """
408 return colorize("red", text)
409
411 """
412 Make text darkred using bash/terminal codes.
413
414 @param text: text to colorize
415 @type text: string
416 @return: colorized text
417 @rtype: string
418 """
419 return colorize("darkred", text)
420
422 """
423 Colorize package atoms with standard colors.
424
425 @param atom: atom string
426 @type atom: string
427 @return: colorized string
428 @rtype: string
429 """
430 out = atom.split("/")
431 return blue(out[0])+"/"+red(out[1])
432
434 """
435 Function used by Entropy text client (will be moved from here) to
436 print the menu output given a properly formatted list.
437 This method is not intended for general used and will be moved away from
438 here.
439 """
440 if args == None:
441 args = []
442
443 def orig_myfunc(x):
444 return x
445 def orig_myfunc_desc(x):
446 return x
447
448 try:
449 i = args.index("--help")
450 del args[i]
451 command = args.pop(0)
452 except ValueError:
453 command = None
454 except IndexError:
455 command = None
456 section_found = False
457 search_depth = 1
458
459
460 for item in data:
461 myfunc = orig_myfunc
462 myfunc_desc = orig_myfunc_desc
463
464 if not item:
465 if command == None or section_found:
466 writechar("\n")
467 else:
468 n_ident = item[0]
469 name = item[1]
470 n_d_ident = item[2]
471 desc = item[3]
472 if command != None:
473
474 if name == command and n_ident == search_depth:
475 try:
476 command = args.pop(0)
477 search_depth = n_ident + 1
478 except IndexError:
479 command = "##unused_from_now_on"
480 section_found = True
481 indent_level = n_ident
482 elif section_found:
483 if n_ident <= indent_level:
484 return
485 else:
486 continue
487
488 if n_ident == 0:
489 writechar(" ")
490
491 while n_ident > 0:
492 n_ident -= 1
493 writechar("\t")
494 n_ident = item[0]
495
496
497 if n_ident == 0:
498 myfunc = darkgreen
499 elif n_ident == 1:
500 myfunc = blue
501 myfunc_desc = darkgreen
502 elif n_ident == 2:
503 if not name.startswith("--"):
504 myfunc = red
505 myfunc_desc = brown
506 elif n_ident == 3:
507 myfunc = darkblue
508 myfunc_desc = purple
509 try:
510 print myfunc(name),
511 except UnicodeEncodeError:
512 print myfunc(name.encode('utf-8')),
513
514
515 if desc:
516 while n_d_ident > 0:
517 n_d_ident -= 1
518 writechar("\t")
519 try:
520 print myfunc_desc(desc),
521 except UnicodeEncodeError:
522 print myfunc_desc(desc.encode('utf-8')),
523 writechar("\n")
524
526 """
527 Print to stdout the terminal code to push back cursor at the beginning
528 of the line.
529 """
530 if havecolor:
531 sys.stdout.write(stuff['ESC'] + '[2K')
532 _flush_stdouterr()
533
537
539 """
540 Service function used by Entropy text client (will be moved from here)
541 to write error messages to stdout (not stderr, atm).
542 NOTE: don't use this directly but rather subclass TextInterface class.
543
544 @param msg: text message to print
545 @type msg: string
546 @keyword back: move text cursor back to the beginning of the line
547 @type back: bool
548 @keyword flush: flush stdout and stderr
549 @type flush: bool
550 @return: None
551 @rtype: None
552 """
553 if etpUi['mute']:
554 return
555 if not back:
556 setcols()
557 reset_cursor()
558 writechar("\r")
559 if back:
560 try:
561 print darkred(">>"),msg,
562 except UnicodeEncodeError:
563 print darkred(">>"),msg.encode('utf-8'),
564 else:
565 try:
566 print darkred(">>"),msg
567 except UnicodeEncodeError:
568 print darkred(">>"),msg.encode('utf-8')
569 if flush:
570 _flush_stdouterr()
571
573 """
574 Service function used by Entropy text client (will be moved from here)
575 to write info messages to stdout (not stderr, atm).
576 NOTE: don't use this directly but rather subclass TextInterface class.
577
578 @param msg: text message to print
579 @type msg: string
580 @keyword back: move text cursor back to the beginning of the line
581 @type back: bool
582 @keyword flush: flush stdout and stderr
583 @type flush: bool
584 @return: None
585 @rtype: None
586 """
587 if etpUi['mute']:
588 return
589 if not back:
590 setcols()
591 reset_cursor()
592 writechar("\r")
593 if back:
594 try:
595 print darkgreen(">>"),msg,
596 except UnicodeEncodeError:
597 print darkgreen(">>"),msg.encode('utf-8'),
598 else:
599 try:
600 print darkgreen(">>"),msg
601 except UnicodeEncodeError:
602 print darkgreen(">>"),msg.encode('utf-8')
603 if flush:
604 _flush_stdouterr()
605
607 """
608 Service function used by Entropy text client (will be moved from here)
609 to write warning messages to stdout (not stderr, atm).
610 NOTE: don't use this directly but rather subclass TextInterface class.
611
612 @param msg: text message to print
613 @type msg: string
614 @keyword back: move text cursor back to the beginning of the line
615 @type back: bool
616 @keyword flush: flush stdout and stderr
617 @type flush: bool
618 @return: None
619 @rtype: None
620 """
621 if etpUi['mute']:
622 return
623 if not back:
624 setcols()
625 reset_cursor()
626 writechar("\r")
627 if back:
628 try:
629 print red(">>"),msg,
630 except UnicodeEncodeError:
631 print red(">>"),msg.encode('utf-8'),
632 else:
633 try:
634 print red(">>"),msg
635 except UnicodeEncodeError:
636 print red(">>"),msg.encode('utf-8')
637 if flush:
638 _flush_stdouterr()
639
641 """
642 Service function used by Entropy text client (will be moved from here)
643 to write generic messages to stdout (not stderr, atm).
644 NOTE: don't use this directly but rather subclass TextInterface class.
645
646 @param msg: text message to print
647 @type msg: string
648 @keyword back: move text cursor back to the beginning of the line
649 @type back: bool
650 @keyword flush: flush stdout and stderr
651 @type flush: bool
652 @return: None
653 @rtype: None
654 """
655 if etpUi['mute']:
656 return
657 writechar("\r")
658 try:
659 print msg
660 except UnicodeEncodeError:
661 print msg.encode('utf-8')
662 _flush_stdouterr()
663
665 """
666 Write characters to stdout (will be moved from here).
667
668 @param chars: chars to write
669 @type chars: string
670 """
671 if etpUi['mute']:
672 return
673 try:
674 sys.stdout.write(chars)
675 sys.stdout.flush()
676 except IOError, e:
677 if e.errno == 32:
678 return
679 raise
680
681 -def readtext(request, password = False):
682 """
683 Read text from stdin and return it (will be moved from here).
684
685 @param request: textual request to print
686 @type request: string
687 @keyword password: if you are requesting a password, set this to True
688 @type password: bool
689 @return: text read back from stdin
690 @rtype: string
691 """
692 xtermTitle(_("Entropy needs your attention"))
693 if password:
694 from getpass import getpass
695 try:
696 text = getpass(request+" ")
697 except UnicodeEncodeError:
698 text = getpass(request.encode('utf-8')+" ")
699 else:
700 try:
701 print request,"",
702 except UnicodeEncodeError:
703 print request.encode('utf-8'),"",
704 _flush_stdouterr()
705 text = _my_raw_input()
706 return text
707
722
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746 - def updateProgress(self, text, header = "", footer = "", back = False, importance = 0, type = "info", count = [], percent = False):
747 if (etpUi['quiet']) or (etpUi['mute']):
748 return
749
750 _flush_stdouterr()
751
752 myfunc = print_info
753 if type == "warning":
754 myfunc = print_warning
755 elif type == "error":
756 myfunc = print_error
757
758 count_str = ""
759 if count:
760 if len(count) > 1:
761 if percent:
762 count_str = " ("+str(round((float(count[0])/count[1])*100,1))+"%) "
763 else:
764 count_str = " (%s/%s) " % (red(str(count[0])),blue(str(count[1])),)
765 if importance == 0:
766 myfunc(header+count_str+text+footer, back = back, flush = False)
767 elif importance == 1:
768 myfunc(header+count_str+text+footer, back = back, flush = False)
769 elif importance in (2,3):
770 myfunc(header+count_str+text+footer, back = back, flush = False)
771
772 _flush_stdouterr()
773
774
775
776
777
778
779
780
781
782
783
784 - def askQuestion(self, question, importance = 0, responses = ["Yes","No"]):
785
786 colours = [green, red, blue, darkgreen, darkred, darkblue, brown, purple]
787 colours += colours[:]
788 if len(responses) > len(colours):
789 raise IncorrectParameter("IncorrectParameter: %s = %s" % (_("maximum responses length"),len(colours),))
790 try:
791 print darkgreen(question),
792 except UnicodeEncodeError:
793 print darkgreen(question.encode('utf-8')),
794 _flush_stdouterr()
795 try:
796 while True:
797 xtermTitle(_("Entropy got a question for you"))
798 _flush_stdouterr()
799 response = _my_raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
800 _flush_stdouterr()
801 for key in responses:
802
803 if response.upper() == key[:len(response)].upper():
804 xtermTitleReset()
805 return key
806 '''
807 try:
808 print "%s '%s'" % (_("I cannot understand"),response,),
809 except UnicodeEncodeError:
810 print "%s '%s'" % (_("I cannot understand"),response.encode('utf-8'),),
811 '''
812 _flush_stdouterr()
813 except (EOFError, KeyboardInterrupt):
814 print "%s." % (_("Interrupted"),)
815 xtermTitleReset()
816 raise SystemExit(100)
817 xtermTitleReset()
818 _flush_stdouterr()
819
820 '''
821 @ title: title of the input box
822 @ input_parameters: [
823 ('identifier 1','input text 1',input_verification_callback,False),
824 ('password','Password',input_verification_callback,True),
825 ('item_3',('checkbox','Checkbox option (boolean request) - please choose',),input_verification_callback,True),
826 ('item_4',('combo',('Select your favorite option',['option 1', 'option 2', 'option 3']),),input_verification_callback,True),
827 ('item_4',('list',('Setup your list',['default list item 1', 'default list item 2']),),input_verification_callback,True)
828 ]
829 @ cancel_button: show cancel button ?
830 @ output: dictionary as follows:
831 {'identifier 1': result, 'identifier 2': result}
832 '''
833 - def inputBox(self, title, input_parameters, cancel_button = True):
834 results = {}
835 if title:
836 try:
837 print title
838 except UnicodeEncodeError:
839 print title.encode('utf-8')
840 _flush_stdouterr()
841
842 def option_chooser(option_data):
843 mydict = {}
844 counter = 1
845 option_text, option_list = option_data
846 self.updateProgress(option_text)
847 for item in option_list:
848 mydict[counter] = item
849 txt = "[%s] %s" % (darkgreen(str(counter)), blue(item),)
850 self.updateProgress(txt)
851 counter += 1
852 while 1:
853 myresult = readtext("%s:" % (_('Selected number'),)).decode('utf-8')
854 try:
855 myresult = int(myresult)
856 except ValueError:
857 continue
858 selected = mydict.get(myresult)
859 if selected != None:
860 return myresult, selected
861
862 def list_editor(option_data, can_cancel, callback):
863
864 def selaction():
865 self.updateProgress('')
866 self.updateProgress(darkred(_("Please select an option")))
867 if can_cancel:
868 self.updateProgress(" ("+blue("-1")+") "+darkred(_("Discard all")))
869 self.updateProgress(" ("+blue("0")+") "+darkgreen(_("Confirm")))
870 self.updateProgress(" ("+blue("1")+") "+brown(_("Add item")))
871 self.updateProgress(" ("+blue("2")+") "+darkblue(_("Remove item")))
872 self.updateProgress(" ("+blue("3")+") "+darkgreen(_("Show current list")))
873
874 self.updateProgress('')
875 action = readtext(darkgreen(_("Your choice (type a number and press enter):"))+" ")
876 return action
877
878 mydict = {}
879 counter = 1
880 valid_actions = [0,1,2,3]
881 if can_cancel: valid_actions.insert(0,-1)
882 option_text, option_list = option_data
883 txt = "%s:" % (blue(option_text),)
884 self.updateProgress(txt)
885
886 for item in option_list:
887 mydict[counter] = item
888 txt = "[%s] %s" % (darkgreen(str(counter)), blue(item),)
889 self.updateProgress(txt)
890 counter += 1
891
892 def show_current_list():
893 for key in sorted(mydict):
894 txt = "[%s] %s" % (darkgreen(str(key)), blue(mydict[key]),)
895 self.updateProgress(txt)
896
897 while 1:
898 try:
899 action = int(selaction())
900 except (ValueError,TypeError,):
901 self.updateProgress(_("You don't have typed a number."), type = "warning")
902 continue
903 if action not in valid_actions:
904 self.updateProgress(_("Invalid action."), type = "warning")
905 continue
906 if action == -1:
907 raise KeyboardInterrupt
908 elif action == 0:
909 break
910 elif action == 1:
911 while 1:
912 try:
913 s_el = readtext(darkred(_("String to add:"))+" ")
914 if not callback(s_el):
915 raise ValueError
916 mydict[counter] = s_el
917 counter += 1
918 except (ValueError,):
919 self.updateProgress(_("Invalid string."), type = "warning")
920 continue
921 break
922 show_current_list()
923 continue
924 elif action == 2:
925 while 1:
926 try:
927 s_el = int(readtext(darkred(_("Element number to remove:"))+" "))
928 if s_el not in mydict:
929 raise ValueError
930 del mydict[s_el]
931 except (ValueError,TypeError,):
932 self.updateProgress(_("Invalid element."), type = "warning")
933 continue
934 break
935 show_current_list()
936 continue
937 elif action == 3:
938 show_current_list()
939 continue
940 break
941
942 mylist = [mydict[x] for x in sorted(mydict)]
943 return mylist
944
945 for identifier, input_text, callback, password in input_parameters:
946 while 1:
947 use_cb = True
948 try:
949 if isinstance(input_text,tuple):
950 myresult = False
951 input_type, data = input_text
952 if input_type == "checkbox":
953 answer = self.askQuestion(data)
954 if answer == "Yes": myresult = True
955 elif input_type == "combo":
956 myresult = option_chooser(data)
957 elif input_type == "list":
958 use_cb = False
959 myresult = list_editor(data, cancel_button, callback)
960 else:
961 myresult = readtext(input_text+":", password = password).decode('utf-8')
962 except (KeyboardInterrupt,EOFError,):
963 if not cancel_button:
964 continue
965 return None
966 valid = True
967 if use_cb:
968 valid = callback(myresult)
969 if valid:
970 results[identifier] = myresult
971 break
972 return results
973
974
975
976 - def cycleDone(self):
978
979 - def setTitle(self, title):
981
982 - def setTotalCycles(self, total):
984
987
990
991 - def notitles(self):
993