mirror of https://github.com/dbcli/pgcli
More generic try/catch when dealing with keyring.
This commit is contained in:
parent
d608ffe7c7
commit
165818bee3
|
@ -1,6 +1,11 @@
|
|||
Upcoming:
|
||||
=========
|
||||
|
||||
Bug fixes:
|
||||
----------
|
||||
|
||||
* Fix exception when retrieving password from keyring ([issue 1338](https://github.com/dbcli/pgcli/issues/1338)).
|
||||
|
||||
Internal:
|
||||
---------
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import click
|
||||
from textwrap import dedent
|
||||
|
||||
|
||||
keyring = None # keyring will be loaded later
|
||||
|
||||
|
||||
keyring_error_message = dedent(
|
||||
"""\
|
||||
{}
|
||||
{}
|
||||
To remove this message do one of the following:
|
||||
- prepare keyring as described at: https://keyring.readthedocs.io/en/stable/
|
||||
- uninstall keyring: pip uninstall keyring
|
||||
- disable keyring in our configuration: add keyring = False to [main]"""
|
||||
)
|
||||
|
||||
|
||||
def keyring_initialize(keyring_enabled, *, logger):
|
||||
"""Initialize keyring only if explicitly enabled"""
|
||||
global keyring
|
||||
|
||||
if keyring_enabled:
|
||||
# Try best to load keyring (issue #1041).
|
||||
import importlib
|
||||
|
||||
try:
|
||||
keyring = importlib.import_module("keyring")
|
||||
except Exception as e: # ImportError for Python 2, ModuleNotFoundError for Python 3
|
||||
logger.warning("import keyring failed: %r.", e)
|
||||
|
||||
|
||||
def keyring_get_password(key):
|
||||
"""Attempt to get password from keyring"""
|
||||
# Find password from store
|
||||
passwd = ""
|
||||
try:
|
||||
passwd = keyring.get_password("pgcli", key) or ""
|
||||
except Exception as e:
|
||||
click.secho(
|
||||
keyring_error_message.format(
|
||||
"Load your password from keyring returned:", str(e)
|
||||
),
|
||||
err=True,
|
||||
fg="red",
|
||||
)
|
||||
return passwd
|
||||
|
||||
|
||||
def keyring_set_password(key, passwd):
|
||||
try:
|
||||
keyring.set_password("pgcli", key, passwd)
|
||||
except Exception as e:
|
||||
click.secho(
|
||||
keyring_error_message.format("Set password in keyring returned:", str(e)),
|
||||
err=True,
|
||||
fg="red",
|
||||
)
|
|
@ -18,8 +18,6 @@ import platform
|
|||
from time import time, sleep
|
||||
from typing import Optional
|
||||
|
||||
keyring = None # keyring will be loaded later
|
||||
|
||||
from cli_helpers.tabular_output import TabularOutputFormatter
|
||||
from cli_helpers.tabular_output.preprocessors import align_decimals, format_numbers
|
||||
from cli_helpers.utils import strip_ansi
|
||||
|
@ -49,6 +47,7 @@ from pygments.lexers.sql import PostgresLexer
|
|||
from pgspecial.main import PGSpecial, NO_QUERY, PAGER_OFF, PAGER_LONG_OUTPUT
|
||||
import pgspecial as special
|
||||
|
||||
from . import auth
|
||||
from .pgcompleter import PGCompleter
|
||||
from .pgtoolbar import create_toolbar_tokens_func
|
||||
from .pgstyle import style_factory, style_factory_output
|
||||
|
@ -80,8 +79,6 @@ from psycopg.conninfo import make_conninfo, conninfo_to_dict
|
|||
|
||||
from collections import namedtuple
|
||||
|
||||
from textwrap import dedent
|
||||
|
||||
try:
|
||||
import sshtunnel
|
||||
|
||||
|
@ -242,7 +239,7 @@ class PGCli:
|
|||
self.on_error = c["main"]["on_error"].upper()
|
||||
self.decimal_format = c["data_formats"]["decimal"]
|
||||
self.float_format = c["data_formats"]["float"]
|
||||
self.initialize_keyring()
|
||||
auth.keyring_initialize(c["main"].as_bool("keyring"), logger=self.logger)
|
||||
self.show_bottom_toolbar = c["main"].as_bool("show_bottom_toolbar")
|
||||
|
||||
self.pgspecial.pset_pager(
|
||||
|
@ -497,19 +494,6 @@ class PGCli:
|
|||
pgspecial_logger.addHandler(handler)
|
||||
pgspecial_logger.setLevel(log_level)
|
||||
|
||||
def initialize_keyring(self):
|
||||
global keyring
|
||||
|
||||
keyring_enabled = self.config["main"].as_bool("keyring")
|
||||
if keyring_enabled:
|
||||
# Try best to load keyring (issue #1041).
|
||||
import importlib
|
||||
|
||||
try:
|
||||
keyring = importlib.import_module("keyring")
|
||||
except Exception as e: # ImportError for Python 2, ModuleNotFoundError for Python 3
|
||||
self.logger.warning("import keyring failed: %r.", e)
|
||||
|
||||
def connect_dsn(self, dsn, **kwargs):
|
||||
self.connect(dsn=dsn, **kwargs)
|
||||
|
||||
|
@ -552,18 +536,6 @@ class PGCli:
|
|||
if not self.force_passwd_prompt and not passwd:
|
||||
passwd = os.environ.get("PGPASSWORD", "")
|
||||
|
||||
# Find password from store
|
||||
key = f"{user}@{host}"
|
||||
keyring_error_message = dedent(
|
||||
"""\
|
||||
{}
|
||||
{}
|
||||
To remove this message do one of the following:
|
||||
- prepare keyring as described at: https://keyring.readthedocs.io/en/stable/
|
||||
- uninstall keyring: pip uninstall keyring
|
||||
- disable keyring in our configuration: add keyring = False to [main]"""
|
||||
)
|
||||
|
||||
# Prompt for a password immediately if requested via the -W flag. This
|
||||
# avoids wasting time trying to connect to the database and catching a
|
||||
# no-password exception.
|
||||
|
@ -574,18 +546,10 @@ class PGCli:
|
|||
"Password for %s" % user, hide_input=True, show_default=False, type=str
|
||||
)
|
||||
|
||||
if not passwd and keyring:
|
||||
key = f"{user}@{host}"
|
||||
|
||||
try:
|
||||
passwd = keyring.get_password("pgcli", key) or ""
|
||||
except (RuntimeError, keyring.errors.InitError) as e:
|
||||
click.secho(
|
||||
keyring_error_message.format(
|
||||
"Load your password from keyring returned:", str(e)
|
||||
),
|
||||
err=True,
|
||||
fg="red",
|
||||
)
|
||||
if not passwd and auth.keyring:
|
||||
passwd = auth.keyring_get_password(key)
|
||||
|
||||
def should_ask_for_password(exc):
|
||||
# Prompt for a password after 1st attempt to connect
|
||||
|
@ -669,17 +633,8 @@ class PGCli:
|
|||
)
|
||||
else:
|
||||
raise e
|
||||
if passwd and keyring:
|
||||
try:
|
||||
keyring.set_password("pgcli", key, passwd)
|
||||
except (RuntimeError, keyring.errors.KeyringError) as e:
|
||||
click.secho(
|
||||
keyring_error_message.format(
|
||||
"Set password in keyring returned:", str(e)
|
||||
),
|
||||
err=True,
|
||||
fg="red",
|
||||
)
|
||||
if passwd and auth.keyring:
|
||||
auth.keyring_set_password(key, passwd)
|
||||
|
||||
except Exception as e: # Connecting to a database could fail.
|
||||
self.logger.debug("Database connection failed: %r.", e)
|
||||
|
|
Loading…
Reference in New Issue