1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from __future__
import division
, absolute_import
, print_function
25 from operator
import itemgetter
26 from getpass
import getpass
28 from colorclass
import Color
30 from indico
.util
.string
import is_valid_mail
, to_unicode
33 def strip_ansi(s
, _re
=re
.compile(r
'\x1b\[[;\d]*[A-Za-z]')):
39 A simple yes/no question (returns True/False)
41 inp
= raw_input("%s [y/N] " % message
)
42 if inp
== 'y' or inp
== 'Y':
48 def prompt_email(prompt
="Enter email: "):
51 email
= unicode(raw_input(prompt
.encode(sys
.stderr
.encoding
)), sys
.stdin
.encoding
).strip()
52 except (EOFError, KeyboardInterrupt): # ^D or ^C
55 if is_valid_mail(email
):
58 warning(u
"Email format is invalid")
61 def prompt_pass(prompt
=u
"Enter password: ", confirm_prompt
=u
"Confirm password: ", min_length
=8, confirm
=True):
64 password
= unicode(getpass(prompt
.encode(sys
.stderr
.encoding
)), sys
.stdin
.encoding
).strip()
65 except (EOFError, KeyboardInterrupt): # ^D or ^C
68 # Empty, just prompt again
71 # Too short, tell the user about the fact
72 if min_length
and len(password
) < min_length
:
73 warning(u
"Password is too short (must be at least {} chars)".format(min_length
))
75 # Confirm password if requested
79 confirmation
= prompt_pass(confirm_prompt
, min_length
=0, confirm
=False)
82 elif confirmation
== password
:
85 warning(u
"Passwords don't match")
89 h
, w
, hp
, wp
= struct
.unpack('HHHH', fcntl
.ioctl(0, termios
.TIOCGWINSZ
, struct
.pack('HHHH', 0, 0, 0, 0)))
94 """Clears the current line in the terminal"""
95 print('\r', ' ' * terminal_size()[0], '\r', end
='', sep
='')
98 def verbose_iterator(iterable
, total
, get_id
, get_title
, print_every
=10):
99 """Iterates large iterables verbosely
101 :param iterable: An iterable
102 :param total: The number of items in `iterable`
103 :param get_id: callable to retrieve the ID of an item
104 :param get_title: callable to retrieve the title of an item
106 term_width
= terminal_size()[0]
107 start_time
= time
.time()
109 '[%{cyan!}{:6}%{reset}/%{cyan}{}%{reset} %{yellow!}{:.3f}%{reset}% %{green!}{}%{reset}] {:>8} %{grey!}{}'
112 for i
, item
in enumerate(iterable
, 1):
113 if i
% print_every
== 0 or i
== total
:
114 remaining_seconds
= int((time
.time() - start_time
) / i
* (total
- i
))
115 remaining
= '{:02}:{:02}'.format(remaining_seconds
// 60, remaining_seconds
% 60)
116 title
= to_unicode(get_title(item
).replace('\n', ' '))
117 text
= fmt
.format(i
, total
, (i
/ total
* 100.0), remaining
, get_id(item
), title
)
118 print('\r', ' ' * term_width
, end
='', sep
='')
119 # terminal width + ansi control code length - trailing reset code (4)
120 print('\r', text
[:term_width
+ len(text
.value_colors
) - len(text
.value_no_colors
) - 4], cformat('%{reset}'),
129 def conferenceHolderIterator(ch
, verbose
=True, deepness
='subcontrib'):
131 Goes over all conferences, printing a status message (ideal for scripts)
134 def _eventIterator(conference
, tabs
):
135 for contrib
in conference
.getContributionList():
136 yield ('contrib', contrib
)
138 if deepness
== 'subcontrib':
139 for scontrib
in contrib
.getSubContributionList():
140 yield ('subcontrib', scontrib
)
143 iterator
= idx
.iteritems()
145 iterator
= verbose_iterator(iterator
, len(idx
.keys()), itemgetter(0), lambda x
: x
[1].getTitle())
147 for id_
, conf
in iterator
:
149 if deepness
in {'contrib', 'subcontrib'}:
150 for contrib
in _eventIterator(conf
, 0):
157 from termcolor
import colored
159 def colored(text
, *__
, **___
):
161 just a dummy function that returns the same string
162 (in case termcolor is not available)
168 bg
= u
'on_{}'.format(m
.group('bg')) if m
.group('bg') else None
169 attrs
= ['bold'] if m
.group('fg_bold') else None
170 return colored(u
'', m
.group('fg'), bg
, attrs
=attrs
)[:-4]
174 """Replaces %{color} and %{color,bgcolor} with ansi colors.
176 Bold foreground can be achieved by suffixing the color with a '!'
179 string
= string
.replace(u
'%{reset}', reset
)
180 string
= re
.sub(ur
'%\{(?P<fg>[a-z]+)(?P<fg_bold>!?)(?:,(?P<bg>[a-z]+))?}', _cformat_sub
, string
)
181 if not string
.endswith(reset
):
186 # Error/warning/info message util methods
190 Print a red error message
192 print(colored(message
, 'red'))
195 def warning(message
):
197 Print a yellow warning message
199 print(colored(message
, 'yellow'))
204 Print a blue information message
206 print(colored(message
, 'cyan', attrs
=['bold']))
209 def success(message
):
211 Print a green success message
213 print(colored(message
, 'green'))