importfunctoolsimportgetpassimportloggingfromtypingimportTYPE_CHECKING,Callable,Optional,Type,cast# keyring has an indirect dependency on PyCA cryptography, which has no# pre-built wheels for ppc64le and s390x, see #1158.ifTYPE_CHECKING:importkeyringelse:try:importkeyringexceptModuleNotFoundError:# pragma: no coverkeyring=Nonefromtwineimportexceptionsfromtwineimportutilslogger=logging.getLogger(__name__)
[docs]defget_username_from_keyring(self)->Optional[str]:ifkeyringisNone:logger.info("keyring module is not available")returnNonetry:system=cast(str,self.system)logger.info("Querying keyring for username")creds=keyring.get_credential(system,None)ifcreds:returncreds.usernameexceptAttributeError:# To support keyring prior to 15.2passexceptExceptionasexc:logger.warning("Error getting username from keyring",exc_info=exc)returnNone
[docs]defget_password_from_keyring(self)->Optional[str]:ifkeyringisNone:logger.info("keyring module is not available")returnNonetry:system=cast(str,self.system)username=cast(str,self.username)logger.info("Querying keyring for password")returncast(str,keyring.get_password(system,username))exceptExceptionasexc:logger.warning("Error getting password from keyring",exc_info=exc)returnNone
[docs]defusername_from_keyring_or_prompt(self)->str:username=self.get_username_from_keyring()ifusername:logger.info("username set from keyring")returnusernamereturnself.prompt("username",input)
[docs]defpassword_from_keyring_or_prompt(self)->str:password=self.get_password_from_keyring()ifpassword:logger.info("password set from keyring")returnpassword# Prompt for API token when required.what="API token"ifself.is_pypi()else"password"returnself.prompt(what,getpass.getpass)
[docs]defprompt(self,what:str,how:Callable[...,str])->str:returnhow(f"Enter your {what}: ")
[docs]defis_pypi(self)->bool:"""As of 2024-01-01, PyPI requires API tokens for uploads."""returncast(str,self.config["repository"]).startswith((utils.DEFAULT_REPOSITORY,utils.TEST_REPOSITORY,))