/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/ui/text.py

  • Committer: Robert Collins
  • Date: 2009-08-04 04:36:34 UTC
  • mfrom: (4583 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4593.
  • Revision ID: robertc@robertcollins.net-20090804043634-2iu9wpcgs273i97s
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
 
 
19
18
"""Text UI, write output to the console.
20
19
"""
21
20
 
 
21
import getpass
 
22
import os
22
23
import sys
23
24
import time
24
25
import warnings
34
35
 
35
36
""")
36
37
 
37
 
from bzrlib.ui import CLIUIFactory
38
 
 
39
 
 
40
 
class TextUIFactory(CLIUIFactory):
 
38
from bzrlib.ui import (
 
39
    UIFactory,
 
40
    NullProgressView,
 
41
    )
 
42
 
 
43
 
 
44
class TextUIFactory(UIFactory):
41
45
    """A UI factory for Text user interefaces."""
42
46
 
43
47
    def __init__(self,
44
 
                 bar_type=None,
45
48
                 stdin=None,
46
49
                 stdout=None,
47
50
                 stderr=None):
51
54
                         letting the bzrlib.progress.ProgressBar factory auto
52
55
                         select.   Deprecated.
53
56
        """
54
 
        super(TextUIFactory, self).__init__(stdin=stdin,
55
 
                stdout=stdout, stderr=stderr)
56
 
        if bar_type:
57
 
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 11, 0))
58
 
                % "bar_type parameter")
 
57
        super(TextUIFactory, self).__init__()
 
58
        # TODO: there's no good reason not to pass all three streams, maybe we
 
59
        # should deprecate the default values...
 
60
        self.stdin = stdin
 
61
        self.stdout = stdout
 
62
        self.stderr = stderr
59
63
        # paints progress, network activity, etc
60
 
        self._progress_view = TextProgressView(self.stderr)
61
 
 
 
64
        self._progress_view = self.make_progress_view()
 
65
        
62
66
    def clear_term(self):
63
67
        """Prepare the terminal for output.
64
68
 
70
74
        # to clear it.  We might need to separately check for the case of
71
75
        self._progress_view.clear()
72
76
 
 
77
    def get_boolean(self, prompt):
 
78
        while True:
 
79
            self.prompt(prompt + "? [y/n]: ")
 
80
            line = self.stdin.readline().lower()
 
81
            if line in ('y\n', 'yes\n'):
 
82
                return True
 
83
            elif line in ('n\n', 'no\n'):
 
84
                return False
 
85
            elif line in ('', None):
 
86
                # end-of-file; possibly should raise an error here instead
 
87
                return None
 
88
 
 
89
    def get_non_echoed_password(self):
 
90
        isatty = getattr(self.stdin, 'isatty', None)
 
91
        if isatty is not None and isatty():
 
92
            # getpass() ensure the password is not echoed and other
 
93
            # cross-platform niceties
 
94
            password = getpass.getpass('')
 
95
        else:
 
96
            # echo doesn't make sense without a terminal
 
97
            password = self.stdin.readline()
 
98
            if not password:
 
99
                password = None
 
100
            elif password[-1] == '\n':
 
101
                password = password[:-1]
 
102
        return password
 
103
 
 
104
    def get_password(self, prompt='', **kwargs):
 
105
        """Prompt the user for a password.
 
106
 
 
107
        :param prompt: The prompt to present the user
 
108
        :param kwargs: Arguments which will be expanded into the prompt.
 
109
                       This lets front ends display different things if
 
110
                       they so choose.
 
111
        :return: The password string, return None if the user
 
112
                 canceled the request.
 
113
        """
 
114
        prompt += ': '
 
115
        self.prompt(prompt, **kwargs)
 
116
        # There's currently no way to say 'i decline to enter a password'
 
117
        # as opposed to 'my password is empty' -- does it matter?
 
118
        return self.get_non_echoed_password()
 
119
 
 
120
    def get_username(self, prompt, **kwargs):
 
121
        """Prompt the user for a username.
 
122
 
 
123
        :param prompt: The prompt to present the user
 
124
        :param kwargs: Arguments which will be expanded into the prompt.
 
125
                       This lets front ends display different things if
 
126
                       they so choose.
 
127
        :return: The username string, return None if the user
 
128
                 canceled the request.
 
129
        """
 
130
        prompt += ': '
 
131
        self.prompt(prompt, **kwargs)
 
132
        username = self.stdin.readline()
 
133
        if not username:
 
134
            username = None
 
135
        elif username[-1] == '\n':
 
136
            username = username[:-1]
 
137
        return username
 
138
 
 
139
    def make_progress_view(self):
 
140
        """Construct and return a new ProgressView subclass for this UI.
 
141
        """
 
142
        # if the user specifically requests either text or no progress bars,
 
143
        # always do that.  otherwise, guess based on $TERM and tty presence.
 
144
        if os.environ.get('BZR_PROGRESS_BAR') == 'text':
 
145
            return TextProgressView(self.stderr)
 
146
        elif os.environ.get('BZR_PROGRESS_BAR') == 'none':
 
147
            return NullProgressView()
 
148
        elif progress._supports_progress(self.stderr):
 
149
            return TextProgressView(self.stderr)
 
150
        else:
 
151
            return NullProgressView()
 
152
 
73
153
    def note(self, msg):
74
154
        """Write an already-formatted message, clearing the progress bar if necessary."""
75
155
        self.clear_term()
76
156
        self.stdout.write(msg + '\n')
77
157
 
 
158
    def prompt(self, prompt, **kwargs):
 
159
        """Emit prompt on the CLI.
 
160
        
 
161
        :param kwargs: Dictionary of arguments to insert into the prompt,
 
162
            to allow UIs to reformat the prompt.
 
163
        """
 
164
        if kwargs:
 
165
            # See <https://launchpad.net/bugs/365891>
 
166
            prompt = prompt % kwargs
 
167
        prompt = prompt.encode(osutils.get_terminal_encoding(), 'replace')
 
168
        self.clear_term()
 
169
        self.stderr.write(prompt)
 
170
 
78
171
    def report_transport_activity(self, transport, byte_count, direction):
79
172
        """Called by transports as they do IO.
80
173
 
81
174
        This may update a progress bar, spinner, or similar display.
82
175
        By default it does nothing.
83
176
        """
84
 
        self._progress_view._show_transport_activity(transport,
 
177
        self._progress_view.show_transport_activity(transport,
85
178
            direction, byte_count)
86
179
 
87
180
    def _progress_updated(self, task):
119
212
        # true when there's output on the screen we may need to clear
120
213
        self._have_output = False
121
214
        # XXX: We could listen for SIGWINCH and update the terminal width...
 
215
        # https://launchpad.net/bugs/316357
122
216
        self._width = osutils.terminal_width()
123
217
        self._last_transport_msg = ''
124
218
        self._spin_pos = 0
223
317
        self._last_repaint = now
224
318
        self._repaint()
225
319
 
226
 
    def _show_transport_activity(self, transport, direction, byte_count):
 
320
    def show_transport_activity(self, transport, direction, byte_count):
227
321
        """Called by transports via the ui_factory, as they do IO.
228
322
 
229
323
        This may update a progress bar, spinner, or similar display.
232
326
        # XXX: Probably there should be a transport activity model, and that
233
327
        # too should be seen by the progress view, rather than being poked in
234
328
        # here.
 
329
        if not self._have_output:
 
330
            # As a workaround for <https://launchpad.net/bugs/321935> we only
 
331
            # show transport activity when there's already a progress bar
 
332
            # shown, which time the application code is expected to know to
 
333
            # clear off the progress bar when it's going to send some other
 
334
            # output.  Eventually it would be nice to have that automatically
 
335
            # synchronized.
 
336
            return
235
337
        self._total_byte_count += byte_count
236
338
        self._bytes_since_update += byte_count
237
339
        now = time.time()
241
343
            # guard against clock stepping backwards, and don't update too
242
344
            # often
243
345
            rate = self._bytes_since_update / (now - self._transport_update_time)
244
 
            scheme = getattr(transport, '_scheme', None) or repr(transport)
245
 
            if direction == 'read':
246
 
                dir_char = '>'
247
 
            elif direction == 'write':
248
 
                dir_char = '<'
249
 
            else:
250
 
                dir_char = ' '
251
 
            msg = ("%.7s %s %6dKB %5dKB/s" %
252
 
                    (scheme, dir_char, self._total_byte_count>>10, int(rate)>>10,))
 
346
            msg = ("%6dKB %5dKB/s" %
 
347
                    (self._total_byte_count>>10, int(rate)>>10,))
253
348
            self._transport_update_time = now
254
349
            self._last_repaint = now
255
350
            self._bytes_since_update = 0
256
351
            self._last_transport_msg = msg
257
352
            self._repaint()
258
 
 
259