VirtualMailManager/cli/__init__.py
branchv0.6.x
changeset 205 bc9726c9ad85
child 215 33f727efa7c4
equal deleted inserted replaced
204:83938336c518 205:bc9726c9ad85
       
     1 # -*- coding: UTF-8 -*-
       
     2 # Copyright (c) 2010, Pascal Volk
       
     3 # See COPYING for distribution information.
       
     4 
       
     5 """
       
     6     VirtualMailManager.cli
       
     7 
       
     8     VirtualMailManager's command line interface.
       
     9 """
       
    10 
       
    11 from cStringIO import StringIO
       
    12 from getpass import getpass
       
    13 from textwrap import TextWrapper
       
    14 
       
    15 import VirtualMailManager
       
    16 
       
    17 
       
    18 __all__ = ('get_winsize', 'read_pass', 'string_io', 'w_err', 'w_std')
       
    19 
       
    20 os = VirtualMailManager.os
       
    21 _std_write = os.sys.stdout.write
       
    22 _err_write = os.sys.stderr.write
       
    23 
       
    24 
       
    25 def w_std(*args):
       
    26     """Writes each arg of `args`, encoded in the current ENCODING, to stdout
       
    27     and appends a newline."""
       
    28     for arg in args:
       
    29         _std_write(arg.encode(VirtualMailManager.ENCODING, 'replace'))
       
    30         _std_write('\n')
       
    31 
       
    32 
       
    33 def w_err(code, *args):
       
    34     """Writes each arg of `args`, encoded in the current ENCODING, to stderr
       
    35     and appends a newline.
       
    36 
       
    37     This function additional interrupts the program execution and uses
       
    38     `code` system exit status."""
       
    39     for arg in args:
       
    40         _err_write(arg.encode(VirtualMailManager.ENCODING, 'replace'))
       
    41         _err_write('\n')
       
    42     os.sys.exit(code)
       
    43 
       
    44 
       
    45 def get_winsize():
       
    46     """Returns a tuple of integers ``(ws_row, ws_col)`` with the height and
       
    47     width of the terminal."""
       
    48     fd = None
       
    49     for dev in (os.sys.stdout, os.sys.stderr, os.sys.stdin):
       
    50         if hasattr(dev, 'fileno') and os.isatty(dev.fileno()):
       
    51             fd = dev.fileno()
       
    52             break
       
    53     if fd is None:# everything seems to be redirected
       
    54         # fall back to environment or assume some common defaults
       
    55         ws_row, ws_col = 24, 80
       
    56         try:
       
    57             ws_col = int(os.environ.get('COLUMNS', 80))
       
    58             ws_row = int(os.environ.get('LINES', 24))
       
    59         except ValueError:
       
    60             pass
       
    61         return ws_row, ws_col
       
    62 
       
    63     from array import array
       
    64     from fcntl import ioctl
       
    65     from termios import TIOCGWINSZ
       
    66 
       
    67     #"struct winsize" with the ``unsigned short int``s ws_{row,col,{x,y}pixel}
       
    68     ws = array('H', (0, 0, 0, 0))
       
    69     ioctl(fd, TIOCGWINSZ, ws, True)
       
    70     ws_row, ws_col = ws[:2]
       
    71     return ws_row, ws_col
       
    72 
       
    73 
       
    74 def read_pass():
       
    75     """Interactive 'password chat', returns the password in plain format.
       
    76 
       
    77     Throws a VMMException after the third failure.
       
    78     """
       
    79     # TP: Please preserve the trailing space.
       
    80     readp_msg0 = _(u'Enter new password: ').encode(ENCODING, 'replace')
       
    81     # TP: Please preserve the trailing space.
       
    82     readp_msg1 = _(u'Retype new password: ').encode(ENCODING, 'replace')
       
    83     mismatched = True
       
    84     failures = 0
       
    85     while mismatched:
       
    86         if failures > 2:
       
    87             raise VMMException(_(u'Too many failures - try again later.'),
       
    88                                ERR.VMM_TOO_MANY_FAILURES)
       
    89         clear0 = getpass(prompt=readp_msg0)
       
    90         clear1 = getpass(prompt=readp_msg1)
       
    91         if clear0 != clear1:
       
    92             failures += 1
       
    93             w_std(_(u'Sorry, passwords do not match'))
       
    94             continue
       
    95         if not clear0:
       
    96             failures += 1
       
    97             w_std(_(u'Sorry, empty passwords are not permitted'))
       
    98             continue
       
    99         mismatched = False
       
   100     return clear0
       
   101 
       
   102 
       
   103 def string_io():
       
   104     """Returns a new `cStringIO.StringIO` instance."""
       
   105     return StringIO()