~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/ui/__init__.py

  • Committer: Martin Pool
  • Date: 2009-06-22 09:16:26 UTC
  • mto: This revision was merged to the branch mainline in revision 4558.
  • Revision ID: mbp@sourcefrog.net-20090622091626-03xi30uj70owv95d
Fuse CLIUIFactory and TextUIFactory and deprecate the old name

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
#
52
52
# GUIs may actually choose to subclass TextUIFactory, so unimplemented methods
53
53
# fall back to working through the terminal.
 
54
#
 
55
# SilentUIFactory used to read input from stdin, but not print anything, which
 
56
# now seems like an unhelpful combination.  So it will now just fail if asked
 
57
# for input.
54
58
 
55
59
import os
56
60
import sys
67
71
    trace,
68
72
    )
69
73
""")
 
74
from bzrlib.symbol_versioning import (
 
75
    deprecated_function,
 
76
    deprecated_in,
 
77
    deprecated_method,
 
78
    )
70
79
 
71
80
 
72
81
class UIFactory(object):
180
189
 
181
190
 
182
191
class CLIUIFactory(UIFactory):
183
 
    """Common behaviour for command line UI factories.
184
 
 
185
 
    This is suitable for dumb terminals that can't repaint existing text."""
186
 
 
 
192
    """Deprecated in favor of TextUIFactory."""
 
193
 
 
194
    @deprecated_method(deprecated_in((1, 17, 0)))
187
195
    def __init__(self, stdin=None, stdout=None, stderr=None):
188
196
        UIFactory.__init__(self)
189
197
        self.stdin = stdin or sys.stdin
190
198
        self.stdout = stdout or sys.stdout
191
199
        self.stderr = stderr or sys.stderr
192
200
 
193
 
    def get_boolean(self, prompt):
194
 
        # FIXME: make a regexp and handle case variations as well.
195
 
        while True:
196
 
            self.prompt(prompt + "? [y/n]: ")
197
 
            line = self.stdin.readline()
198
 
            if line in ('y\n', 'yes\n'):
199
 
                return True
200
 
            if line in ('n\n', 'no\n'):
201
 
                return False
202
 
 
203
 
    def get_non_echoed_password(self):
204
 
        isatty = getattr(self.stdin, 'isatty', None)
205
 
        if isatty is not None and isatty():
206
 
            # getpass() ensure the password is not echoed and other
207
 
            # cross-platform niceties
208
 
            password = getpass.getpass('')
209
 
        else:
210
 
            # echo doesn't make sense without a terminal
211
 
            password = self.stdin.readline()
212
 
            if not password:
213
 
                password = None
214
 
            elif password[-1] == '\n':
215
 
                password = password[:-1]
216
 
        return password
217
 
 
218
 
    def get_password(self, prompt='', **kwargs):
219
 
        """Prompt the user for a password.
220
 
 
221
 
        :param prompt: The prompt to present the user
222
 
        :param kwargs: Arguments which will be expanded into the prompt.
223
 
                       This lets front ends display different things if
224
 
                       they so choose.
225
 
        :return: The password string, return None if the user
226
 
                 canceled the request.
227
 
        """
228
 
        prompt += ': '
229
 
        self.prompt(prompt, **kwargs)
230
 
        # There's currently no way to say 'i decline to enter a password'
231
 
        # as opposed to 'my password is empty' -- does it matter?
232
 
        return self.get_non_echoed_password()
233
 
 
234
 
    def get_username(self, prompt, **kwargs):
235
 
        """Prompt the user for a username.
236
 
 
237
 
        :param prompt: The prompt to present the user
238
 
        :param kwargs: Arguments which will be expanded into the prompt.
239
 
                       This lets front ends display different things if
240
 
                       they so choose.
241
 
        :return: The username string, return None if the user
242
 
                 canceled the request.
243
 
        """
244
 
        prompt += ': '
245
 
        self.prompt(prompt, **kwargs)
246
 
        username = self.stdin.readline()
247
 
        if not username:
248
 
            username = None
249
 
        elif username[-1] == '\n':
250
 
            username = username[:-1]
251
 
        return username
252
 
 
253
 
    def prompt(self, prompt, **kwargs):
254
 
        """Emit prompt on the CLI.
255
 
        
256
 
        :param kwargs: Dictionary of arguments to insert into the prompt,
257
 
            to allow UIs to reformat the prompt.
258
 
        """
259
 
        if kwargs:
260
 
            # See <https://launchpad.net/bugs/365891>
261
 
            prompt = prompt % kwargs
262
 
        prompt = prompt.encode(osutils.get_terminal_encoding(), 'replace')
263
 
        self.clear_term()
264
 
        self.stderr.write(prompt)
265
 
 
266
 
    def note(self, msg):
267
 
        """Write an already-formatted message."""
268
 
        self.stdout.write(msg + '\n')
269
 
 
270
 
 
271
 
class SilentUIFactory(CLIUIFactory):
 
201
 
 
202
class SilentUIFactory(UIFactory):
272
203
    """A UI Factory which never prints anything.
273
204
 
274
205
    This is the default UI, if another one is never registered.
275
206
    """
276
207
 
277
208
    def __init__(self):
278
 
        CLIUIFactory.__init__(self)
 
209
        UIFactory.__init__(self)
279
210
 
280
211
    def get_password(self, prompt='', **kwargs):
281
212
        return None
298
229
 
299
230
 
300
231
ui_factory = SilentUIFactory()
301
 
"""IMPORTANT: never import this symbol directly. ONLY ever access it as
302
 
ui.ui_factory."""
 
232
# IMPORTANT: never import this symbol directly. ONLY ever access it as
 
233
# ui.ui_factory, so that you refer to the current value.
303
234
 
304
235
 
305
236
def make_ui_for_terminal(stdin, stdout, stderr):
306
237
    """Construct and return a suitable UIFactory for a text mode program.
307
 
 
308
 
    If stdout is a smart terminal, this gets a smart UIFactory with
309
 
    progress indicators, etc.  If it's a dumb terminal, just plain text output.
310
238
    """
311
 
    cls = None
312
 
    isatty = getattr(stdin, 'isatty', None)
313
 
    if isatty is None:
314
 
        cls = CLIUIFactory
315
 
    elif not isatty():
316
 
        cls = CLIUIFactory
317
 
    # The following case also handles Win32 - on that platform $TERM is
318
 
    # typically never set, so the case None is treated as a smart terminal,
319
 
    # not dumb.  <https://bugs.launchpad.net/bugs/334808>  win32 files do have
320
 
    # isatty methods that return true.
321
 
    elif os.environ.get('TERM') in ('dumb', ''):
322
 
        # e.g. emacs compile window
323
 
        cls = CLIUIFactory
324
 
    # User may know better, otherwise default to TextUIFactory
325
 
    if (os.environ.get('BZR_USE_TEXT_UI', None) is not None
326
 
        or cls is None):
327
 
        from bzrlib.ui.text import TextUIFactory
328
 
        cls = TextUIFactory
329
 
    return cls(stdin=stdin, stdout=stdout, stderr=stderr)
 
239
    # this is now always TextUIFactory, which in turn decides whether it
 
240
    # should display progress bars etc
 
241
    from bzrlib.ui.text import TextUIFactory
 
242
    return TextUIFactory(stdin, stdout, stderr)
330
243
 
331
244
 
332
245
class NullProgressView(object):