/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: 2009-12-21 06:03:07 UTC
  • mfrom: (4665.7.3 serve-init)
  • Revision ID: pqm@pqm.ubuntu.com-20091221060307-uvja3vdy1o6dzzy0
(mbp) example debian init script

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 show_error(self, msg):
 
250
        """Show an error message (not an exception) to the user.
286
251
        
287
 
        :param kwargs: Dictionary of arguments to insert into the prompt,
288
 
            to allow UIs to reformat the prompt.
 
252
        The message should not have an error prefix or trailing newline.  That
 
253
        will be added by the factory if appropriate. 
289
254
        """
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')
 
255
        raise NotImplementedError(self.show_error)
 
256
 
 
257
    def show_message(self, msg):
 
258
        """Show a message to the user."""
 
259
        raise NotImplementedError(self.show_message)
 
260
 
 
261
    def show_warning(self, msg):
 
262
        """Show a warning to the user."""
 
263
        raise NotImplementedError(self.show_warning)
 
264
 
300
265
 
301
266
 
302
267
class SilentUIFactory(UIFactory):
318
283
    def get_username(self, prompt, **kwargs):
319
284
        return None
320
285
 
 
286
    def show_error(self, msg):
 
287
        pass
 
288
 
 
289
    def show_message(self, msg):
 
290
        pass
 
291
 
 
292
    def show_warning(self, msg):
 
293
        pass
 
294
 
321
295
 
322
296
class CannedInputUIFactory(SilentUIFactory):
323
297
    """A silent UI that return canned input."""
331
305
    def get_boolean(self, prompt):
332
306
        return self.responses.pop(0)
333
307
 
 
308
    def get_integer(self, prompt):
 
309
        return self.responses.pop(0)
 
310
 
334
311
    def get_password(self, prompt='', **kwargs):
335
312
        return self.responses.pop(0)
336
313
 
337
314
    def get_username(self, prompt, **kwargs):
338
315
        return self.responses.pop(0)
339
 
    
 
316
 
340
317
    def assert_all_input_consumed(self):
341
318
        if self.responses:
342
319
            raise AssertionError("expected all input in %r to be consumed"
343
320
                % (self,))
344
321
 
345
322
 
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
323
ui_factory = SilentUIFactory()
354
324
# IMPORTANT: never import this symbol directly. ONLY ever access it as
355
325
# ui.ui_factory, so that you refer to the current value.