conans/client/userio.py
import getpass
import os
import sys
from six.moves import input as raw_input
from conans.client.output import ConanOutput
from conans.errors import ConanException
class UserIO(object):
"""Class to interact with the user, used to show messages and ask for information"""
def __init__(self, ins=sys.stdin, out=None):
"""
Params:
ins: input stream
out: ConanOutput, should have "write" method
"""
self._ins = ins
if not out:
out = ConanOutput(sys.stdout, sys.stderr)
self.out = out
self._interactive = True
def disable_input(self):
self._interactive = False
def _raise_if_non_interactive(self):
if not self._interactive:
raise ConanException("Conan interactive mode disabled")
def raw_input(self):
self._raise_if_non_interactive()
return raw_input()
def get_pass(self):
self._raise_if_non_interactive()
return getpass.getpass("")
def request_login(self, remote_name, username=None):
"""Request user to input their name and password
:param username If username is specified it only request password"""
if not username:
if self._interactive:
self.out.write("Remote '%s' username: " % remote_name)
username = self.get_username(remote_name)
if self._interactive:
self.out.write('Please enter a password for "%s" account: ' % username)
try:
pwd = self.get_password(remote_name)
except ConanException:
raise
except Exception as e:
raise ConanException('Cancelled pass %s' % e)
return username, pwd
def get_username(self, remote_name):
"""Overridable for testing purpose"""
return self._get_env_username(remote_name) or self.raw_input()
def get_password(self, remote_name):
"""Overridable for testing purpose"""
return self._get_env_password(remote_name) or self.get_pass()
def request_string(self, msg, default_value=None):
"""Request user to input a msg
:param msg Name of the msg
"""
self._raise_if_non_interactive()
if default_value:
self.out.input_text('%s (%s): ' % (msg, default_value))
else:
self.out.input_text('%s: ' % msg)
s = self._ins.readline().replace("\n", "")
if default_value is not None and s == '':
return default_value
return s
def request_boolean(self, msg, default_option=None):
"""Request user to input a boolean"""
ret = None
while ret is None:
if default_option is True:
s = self.request_string("%s (YES/no)" % msg)
elif default_option is False:
s = self.request_string("%s (NO/yes)" % msg)
else:
s = self.request_string("%s (yes/no)" % msg)
if default_option is not None and s == '':
return default_option
if s.lower() in ['yes', 'y']:
ret = True
elif s.lower() in ['no', 'n']:
ret = False
else:
self.out.error("%s is not a valid answer" % s)
return ret
def _get_env_password(self, remote_name):
"""
Try CONAN_PASSWORD_REMOTE_NAME or CONAN_PASSWORD or return None
"""
remote_name = remote_name.replace("-", "_").upper()
var_name = "CONAN_PASSWORD_%s" % remote_name
ret = os.getenv(var_name, None) or os.getenv("CONAN_PASSWORD", None)
if ret:
self.out.info("Got password '******' from environment")
return ret
def _get_env_username(self, remote_name):
"""
Try CONAN_LOGIN_USERNAME_REMOTE_NAME or CONAN_LOGIN_USERNAME or return None
"""
remote_name = remote_name.replace("-", "_").upper()
var_name = "CONAN_LOGIN_USERNAME_%s" % remote_name
ret = os.getenv(var_name, None) or os.getenv("CONAN_LOGIN_USERNAME", None)
if ret:
self.out.info("Got username '%s' from environment" % ret)
return ret