/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/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-01-14 00:01:32 UTC
  • mfrom: (4957.1.1 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100114000132-3p3rabnonjw3gzqb
(jam) Merge bzr.stable, bringing in bug fixes #175839, #504390

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
Several levels are supported, and you can also register new factories such as
23
23
for a GUI.
24
24
 
25
 
UIFactory
 
25
bzrlib.ui.UIFactory
26
26
    Semi-abstract base class
27
27
 
28
 
SilentUIFactory
 
28
bzrlib.ui.SilentUIFactory
29
29
    Produces no output and cannot take any input; useful for programs using
30
30
    bzrlib in batch mode or for programs such as loggerhead.
31
31
 
32
 
CannedInputUIFactory
 
32
bzrlib.ui.CannedInputUIFactory
33
33
    For use in testing; the input values to be returned are provided 
34
34
    at construction.
35
35
 
36
 
TextUIFactory
 
36
bzrlib.ui.text.TextUIFactory
37
37
    Standard text command-line interface, with stdin, stdout, stderr.
38
38
    May make more or less advanced use of them, eg in drawing progress bars,
39
39
    depending on the detected capabilities of the terminal.
125
125
        """
126
126
        raise NotImplementedError(self.get_password)
127
127
 
 
128
    def make_output_stream(self, encoding=None, encoding_type=None):
 
129
        """Get a stream for sending out bulk text data.
 
130
 
 
131
        This is used for commands that produce bulk text, such as log or diff
 
132
        output, as opposed to user interaction.  This should work even for
 
133
        non-interactive user interfaces.  Typically this goes to a decorated
 
134
        version of stdout, but in a GUI it might be appropriate to send it to a 
 
135
        window displaying the text.
 
136
     
 
137
        :param encoding: Unicode encoding for output; default is the 
 
138
            terminal encoding, which may be different from the user encoding.
 
139
            (See get_terminal_encoding.)
 
140
 
 
141
        :param encoding_type: How to handle encoding errors:
 
142
            replace/strict/escape/exact.  Default is replace.
 
143
        """
 
144
        # XXX: is the caller supposed to close the resulting object?
 
145
        if encoding is None:
 
146
            encoding = osutils.get_terminal_encoding()
 
147
        if encoding_type is None:
 
148
            encoding_type = 'replace'
 
149
        out_stream = self._make_output_stream_explicit(encoding, encoding_type)
 
150
        return out_stream
 
151
 
 
152
    def _make_output_stream_explicit(self, encoding, encoding_type):
 
153
        raise NotImplementedError("%s doesn't support make_output_stream"
 
154
            % (self.__class__.__name__))
 
155
 
128
156
    def nested_progress_bar(self):
129
157
        """Return a nested progress bar.
130
158
 
179
207
        """
180
208
        raise NotImplementedError(self.get_boolean)
181
209
 
 
210
    def get_integer(self, prompt):
 
211
        """Get an integer from the user.
 
212
 
 
213
        :param prompt: a message to prompt the user with. Could be a multi-line
 
214
            prompt but without a terminating \n.
 
215
 
 
216
        :return: A signed integer.
 
217
        """
 
218
        raise NotImplementedError(self.get_integer)
 
219
 
182
220
    def make_progress_view(self):
183
221
        """Construct a new ProgressView object for this UI.
184
222
 
208
246
        """
209
247
        pass
210
248
 
211
 
 
212
 
 
213
 
class CLIUIFactory(UIFactory):
214
 
    """Deprecated in favor of TextUIFactory."""
215
 
 
216
 
    @deprecated_method(deprecated_in((1, 18, 0)))
217
 
    def __init__(self, stdin=None, stdout=None, stderr=None):
218
 
        UIFactory.__init__(self)
219
 
        self.stdin = stdin or sys.stdin
220
 
        self.stdout = stdout or sys.stdout
221
 
        self.stderr = stderr or sys.stderr
222
 
 
223
 
    _accepted_boolean_strings = dict(y=True, n=False, yes=True, no=False)
224
 
 
225
 
    def get_boolean(self, prompt):
226
 
        while True:
227
 
            self.prompt(prompt + "? [y/n]: ")
228
 
            line = self.stdin.readline()
229
 
            line = line.rstrip('\n')
230
 
            val = bool_from_string(line, self._accepted_boolean_strings)
231
 
            if val is not None:
232
 
                return val
233
 
 
234
 
    def get_non_echoed_password(self):
235
 
        isatty = getattr(self.stdin, 'isatty', None)
236
 
        if isatty is not None and isatty():
237
 
            # getpass() ensure the password is not echoed and other
238
 
            # cross-platform niceties
239
 
            password = getpass.getpass('')
240
 
        else:
241
 
            # echo doesn't make sense without a terminal
242
 
            password = self.stdin.readline()
243
 
            if not password:
244
 
                password = None
245
 
            elif password[-1] == '\n':
246
 
                password = password[:-1]
247
 
        return password
248
 
 
249
 
    def get_password(self, prompt='', **kwargs):
250
 
        """Prompt the user for a password.
251
 
 
252
 
        :param prompt: The prompt to present the user
253
 
        :param kwargs: Arguments which will be expanded into the prompt.
254
 
                       This lets front ends display different things if
255
 
                       they so choose.
256
 
        :return: The password string, return None if the user
257
 
                 canceled the request.
258
 
        """
259
 
        prompt += ': '
260
 
        self.prompt(prompt, **kwargs)
261
 
        # There's currently no way to say 'i decline to enter a password'
262
 
        # as opposed to 'my password is empty' -- does it matter?
263
 
        return self.get_non_echoed_password()
264
 
 
265
 
    def get_username(self, prompt, **kwargs):
266
 
        """Prompt the user for a username.
267
 
 
268
 
        :param prompt: The prompt to present the user
269
 
        :param kwargs: Arguments which will be expanded into the prompt.
270
 
                       This lets front ends display different things if
271
 
                       they so choose.
272
 
        :return: The username string, return None if the user
273
 
                 canceled the request.
274
 
        """
275
 
        prompt += ': '
276
 
        self.prompt(prompt, **kwargs)
277
 
        username = self.stdin.readline()
278
 
        if not username:
279
 
            username = None
280
 
        elif username[-1] == '\n':
281
 
            username = username[:-1]
282
 
        return username
283
 
 
284
 
    def prompt(self, prompt, **kwargs):
285
 
        """Emit prompt on the CLI.
 
249
    def log_transport_activity(self, display=False):
 
250
        """Write out whatever transport activity has been measured.
 
251
 
 
252
        Implementations are allowed to do nothing, but it is useful if they can
 
253
        write a line to the log file.
 
254
 
 
255
        :param display: If False, only log to disk, if True also try to display
 
256
            a message to the user.
 
257
        :return: None
 
258
        """
 
259
        # Default implementation just does nothing
 
260
        pass
 
261
 
 
262
    def show_error(self, msg):
 
263
        """Show an error message (not an exception) to the user.
286
264
        
287
 
        :param kwargs: Dictionary of arguments to insert into the prompt,
288
 
            to allow UIs to reformat the prompt.
 
265
        The message should not have an error prefix or trailing newline.  That
 
266
        will be added by the factory if appropriate. 
289
267
        """
290
 
        if kwargs:
291
 
            # See <https://launchpad.net/bugs/365891>
292
 
            prompt = prompt % kwargs
293
 
        prompt = prompt.encode(osutils.get_terminal_encoding(), 'replace')
294
 
        self.clear_term()
295
 
        self.stderr.write(prompt)
296
 
 
297
 
    def note(self, msg):
298
 
        """Write an already-formatted message."""
299
 
        self.stdout.write(msg + '\n')
 
268
        raise NotImplementedError(self.show_error)
 
269
 
 
270
    def show_message(self, msg):
 
271
        """Show a message to the user."""
 
272
        raise NotImplementedError(self.show_message)
 
273
 
 
274
    def show_warning(self, msg):
 
275
        """Show a warning to the user."""
 
276
        raise NotImplementedError(self.show_warning)
 
277
 
300
278
 
301
279
 
302
280
class SilentUIFactory(UIFactory):
318
296
    def get_username(self, prompt, **kwargs):
319
297
        return None
320
298
 
 
299
    def show_error(self, msg):
 
300
        pass
 
301
 
 
302
    def show_message(self, msg):
 
303
        pass
 
304
 
 
305
    def show_warning(self, msg):
 
306
        pass
 
307
 
321
308
 
322
309
class CannedInputUIFactory(SilentUIFactory):
323
310
    """A silent UI that return canned input."""
331
318
    def get_boolean(self, prompt):
332
319
        return self.responses.pop(0)
333
320
 
 
321
    def get_integer(self, prompt):
 
322
        return self.responses.pop(0)
 
323
 
334
324
    def get_password(self, prompt='', **kwargs):
335
325
        return self.responses.pop(0)
336
326
 
337
327
    def get_username(self, prompt, **kwargs):
338
328
        return self.responses.pop(0)
339
 
    
 
329
 
340
330
    def assert_all_input_consumed(self):
341
331
        if self.responses:
342
332
            raise AssertionError("expected all input in %r to be consumed"
343
333
                % (self,))
344
334
 
345
335
 
346
 
@deprecated_function(deprecated_in((1, 18, 0)))
347
 
def clear_decorator(func, *args, **kwargs):
348
 
    """Decorator that clears the term"""
349
 
    ui_factory.clear_term()
350
 
    func(*args, **kwargs)
351
 
 
352
 
 
353
336
ui_factory = SilentUIFactory()
354
337
# IMPORTANT: never import this symbol directly. ONLY ever access it as
355
338
# ui.ui_factory, so that you refer to the current value.
375
358
 
376
359
    def show_transport_activity(self, transport, direction, byte_count):
377
360
        pass
 
361
 
 
362
    def log_transport_activity(self, display=False):
 
363
        pass