Merging upstream version 3.5.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
7a56138e00
commit
6bbbbdf0c7
43 changed files with 1272 additions and 430 deletions
|
@ -49,7 +49,6 @@ Feature: run the cli,
|
|||
when we send "\?" command
|
||||
then we see help output
|
||||
|
||||
@wip
|
||||
Scenario: run the cli with dsn and password
|
||||
When we launch dbcli using dsn_password
|
||||
then we send password
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from psycopg2 import connect
|
||||
from psycopg2.extensions import AsIs
|
||||
from psycopg import connect
|
||||
|
||||
|
||||
def create_db(
|
||||
|
@ -17,13 +16,10 @@ def create_db(
|
|||
"""
|
||||
cn = create_cn(hostname, password, username, "postgres", port)
|
||||
|
||||
# ISOLATION_LEVEL_AUTOCOMMIT = 0
|
||||
# Needed for DB creation.
|
||||
cn.set_isolation_level(0)
|
||||
|
||||
cn.autocommit = True
|
||||
with cn.cursor() as cr:
|
||||
cr.execute("drop database if exists %s", (AsIs(dbname),))
|
||||
cr.execute("create database %s", (AsIs(dbname),))
|
||||
cr.execute(f"drop database if exists {dbname}")
|
||||
cr.execute(f"create database {dbname}")
|
||||
|
||||
cn.close()
|
||||
|
||||
|
@ -41,13 +37,26 @@ def create_cn(hostname, password, username, dbname, port):
|
|||
:return: psycopg2.connection
|
||||
"""
|
||||
cn = connect(
|
||||
host=hostname, user=username, database=dbname, password=password, port=port
|
||||
host=hostname, user=username, dbname=dbname, password=password, port=port
|
||||
)
|
||||
|
||||
print(f"Created connection: {cn.dsn}.")
|
||||
print(f"Created connection: {cn.info.get_parameters()}.")
|
||||
return cn
|
||||
|
||||
|
||||
def pgbouncer_available(hostname="localhost", password=None, username="postgres"):
|
||||
cn = None
|
||||
try:
|
||||
cn = create_cn(hostname, password, username, "pgbouncer", 6432)
|
||||
return True
|
||||
except:
|
||||
print("Pgbouncer is not available.")
|
||||
finally:
|
||||
if cn:
|
||||
cn.close()
|
||||
return False
|
||||
|
||||
|
||||
def drop_db(hostname="localhost", username=None, password=None, dbname=None, port=None):
|
||||
"""
|
||||
Drop database.
|
||||
|
@ -58,12 +67,11 @@ def drop_db(hostname="localhost", username=None, password=None, dbname=None, por
|
|||
"""
|
||||
cn = create_cn(hostname, password, username, "postgres", port)
|
||||
|
||||
# ISOLATION_LEVEL_AUTOCOMMIT = 0
|
||||
# Needed for DB drop.
|
||||
cn.set_isolation_level(0)
|
||||
cn.autocommit = True
|
||||
|
||||
with cn.cursor() as cr:
|
||||
cr.execute("drop database if exists %s", (AsIs(dbname),))
|
||||
cr.execute(f"drop database if exists {dbname}")
|
||||
|
||||
close_cn(cn)
|
||||
|
||||
|
@ -74,5 +82,6 @@ def close_cn(cn=None):
|
|||
:param connection: psycopg2.connection
|
||||
"""
|
||||
if cn:
|
||||
cn_params = cn.info.get_parameters()
|
||||
cn.close()
|
||||
print(f"Closed connection: {cn.dsn}.")
|
||||
print(f"Closed connection: {cn_params}.")
|
||||
|
|
|
@ -111,7 +111,11 @@ def before_all(context):
|
|||
context.conf["dbname"],
|
||||
context.conf["port"],
|
||||
)
|
||||
|
||||
context.pgbouncer_available = dbutils.pgbouncer_available(
|
||||
hostname=context.conf["host"],
|
||||
password=context.conf["pass"],
|
||||
username=context.conf["user"],
|
||||
)
|
||||
context.fixture_data = fixutils.read_fixture_files()
|
||||
|
||||
# use temporary directory as config home
|
||||
|
@ -145,7 +149,7 @@ def after_all(context):
|
|||
context.conf["port"],
|
||||
)
|
||||
|
||||
# Remove temp config direcotry
|
||||
# Remove temp config directory
|
||||
shutil.rmtree(context.env_config_home)
|
||||
|
||||
# Restore env vars.
|
||||
|
@ -164,7 +168,19 @@ def before_scenario(context, scenario):
|
|||
if scenario.name == "list databases":
|
||||
# not using the cli for that
|
||||
return
|
||||
wrappers.run_cli(context)
|
||||
currentdb = None
|
||||
if "pgbouncer" in scenario.feature.tags:
|
||||
if context.pgbouncer_available:
|
||||
os.environ["PGDATABASE"] = "pgbouncer"
|
||||
os.environ["PGPORT"] = "6432"
|
||||
currentdb = "pgbouncer"
|
||||
else:
|
||||
scenario.skip()
|
||||
else:
|
||||
# set env vars back to normal test database
|
||||
os.environ["PGDATABASE"] = context.conf["dbname"]
|
||||
os.environ["PGPORT"] = context.conf["port"]
|
||||
wrappers.run_cli(context, currentdb=currentdb)
|
||||
wrappers.wait_prompt(context)
|
||||
|
||||
|
||||
|
@ -172,13 +188,17 @@ def after_scenario(context, scenario):
|
|||
"""Cleans up after each scenario completes."""
|
||||
if hasattr(context, "cli") and context.cli and not context.exit_sent:
|
||||
# Quit nicely.
|
||||
if not context.atprompt:
|
||||
if not getattr(context, "atprompt", False):
|
||||
dbname = context.currentdb
|
||||
context.cli.expect_exact(f"{dbname}> ", timeout=15)
|
||||
context.cli.sendcontrol("c")
|
||||
context.cli.sendcontrol("d")
|
||||
context.cli.expect_exact(f"{dbname}>", timeout=5)
|
||||
try:
|
||||
context.cli.expect_exact(pexpect.EOF, timeout=15)
|
||||
context.cli.sendcontrol("c")
|
||||
context.cli.sendcontrol("d")
|
||||
except Exception as x:
|
||||
print("Failed cleanup after scenario:")
|
||||
print(x)
|
||||
try:
|
||||
context.cli.expect_exact(pexpect.EOF, timeout=5)
|
||||
except pexpect.TIMEOUT:
|
||||
print(f"--- after_scenario {scenario.name}: kill cli")
|
||||
context.cli.kill(signal.SIGKILL)
|
||||
|
|
12
tests/features/pgbouncer.feature
Normal file
12
tests/features/pgbouncer.feature
Normal file
|
@ -0,0 +1,12 @@
|
|||
@pgbouncer
|
||||
Feature: run pgbouncer,
|
||||
call the help command,
|
||||
exit the cli
|
||||
|
||||
Scenario: run "show help" command
|
||||
When we send "show help" command
|
||||
then we see the pgbouncer help output
|
||||
|
||||
Scenario: run the cli and exit
|
||||
When we send "ctrl + d"
|
||||
then dbcli exits
|
|
@ -69,7 +69,7 @@ def step_ctrl_d(context):
|
|||
context.cli.sendline(r"\pset pager off")
|
||||
wrappers.wait_prompt(context)
|
||||
context.cli.sendcontrol("d")
|
||||
context.cli.expect(pexpect.EOF, timeout=15)
|
||||
context.cli.expect(pexpect.EOF, timeout=5)
|
||||
context.exit_sent = True
|
||||
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ def step_see_prompt(context):
|
|||
Wait to see the prompt.
|
||||
"""
|
||||
db_name = getattr(context, "currentdb", context.conf["dbname"])
|
||||
wrappers.expect_exact(context, f"{db_name}> ", timeout=5)
|
||||
wrappers.expect_exact(context, f"{db_name}>", timeout=5)
|
||||
context.atprompt = True
|
||||
|
||||
|
||||
|
|
22
tests/features/steps/pgbouncer.py
Normal file
22
tests/features/steps/pgbouncer.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
"""
|
||||
Steps for behavioral style tests are defined in this module.
|
||||
Each step is defined by the string decorating it.
|
||||
This string is used to call the step in "*.feature" file.
|
||||
"""
|
||||
|
||||
from behave import when, then
|
||||
import wrappers
|
||||
|
||||
|
||||
@when('we send "show help" command')
|
||||
def step_send_help_command(context):
|
||||
context.cli.sendline("show help")
|
||||
|
||||
|
||||
@then("we see the pgbouncer help output")
|
||||
def see_pgbouncer_help(context):
|
||||
wrappers.expect_exact(
|
||||
context,
|
||||
"SHOW HELP|CONFIG|DATABASES|POOLS|CLIENTS|SERVERS|USERS|VERSION",
|
||||
timeout=3,
|
||||
)
|
|
@ -70,4 +70,5 @@ def run_cli(context, run_args=None, prompt_check=True, currentdb=None):
|
|||
|
||||
def wait_prompt(context):
|
||||
"""Make sure prompt is displayed."""
|
||||
expect_exact(context, "{0}> ".format(context.conf["dbname"]), timeout=5)
|
||||
prompt_str = "{0}>".format(context.currentdb)
|
||||
expect_exact(context, [prompt_str + " ", prompt_str, pexpect.EOF], timeout=3)
|
||||
|
|
1
tests/formatter/__init__.py
Normal file
1
tests/formatter/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
# coding=utf-8
|
111
tests/formatter/test_sqlformatter.py
Normal file
111
tests/formatter/test_sqlformatter.py
Normal file
|
@ -0,0 +1,111 @@
|
|||
# coding=utf-8
|
||||
|
||||
from pgcli.packages.formatter.sqlformatter import escape_for_sql_statement
|
||||
|
||||
from cli_helpers.tabular_output import TabularOutputFormatter
|
||||
from pgcli.packages.formatter.sqlformatter import adapter, register_new_formatter
|
||||
|
||||
|
||||
def test_escape_for_sql_statement_bytes():
|
||||
bts = b"837124ab3e8dc0f"
|
||||
escaped_bytes = escape_for_sql_statement(bts)
|
||||
assert escaped_bytes == "X'383337313234616233653864633066'"
|
||||
|
||||
|
||||
def test_escape_for_sql_statement_number():
|
||||
num = 2981
|
||||
escaped_bytes = escape_for_sql_statement(num)
|
||||
assert escaped_bytes == "'2981'"
|
||||
|
||||
|
||||
def test_escape_for_sql_statement_str():
|
||||
example_str = "example str"
|
||||
escaped_bytes = escape_for_sql_statement(example_str)
|
||||
assert escaped_bytes == "'example str'"
|
||||
|
||||
|
||||
def test_output_sql_insert():
|
||||
global formatter
|
||||
formatter = TabularOutputFormatter
|
||||
register_new_formatter(formatter)
|
||||
data = [
|
||||
[
|
||||
1,
|
||||
"Jackson",
|
||||
"jackson_test@gmail.com",
|
||||
"132454789",
|
||||
"",
|
||||
"2022-09-09 19:44:32.712343+08",
|
||||
"2022-09-09 19:44:32.712343+08",
|
||||
]
|
||||
]
|
||||
header = ["id", "name", "email", "phone", "description", "created_at", "updated_at"]
|
||||
table_format = "sql-insert"
|
||||
kwargs = {
|
||||
"column_types": [int, str, str, str, str, str, str],
|
||||
"sep_title": "RECORD {n}",
|
||||
"sep_character": "-",
|
||||
"sep_length": (1, 25),
|
||||
"missing_value": "<null>",
|
||||
"integer_format": "",
|
||||
"float_format": "",
|
||||
"disable_numparse": True,
|
||||
"preserve_whitespace": True,
|
||||
"max_field_width": 500,
|
||||
}
|
||||
formatter.query = 'SELECT * FROM "user";'
|
||||
output = adapter(data, header, table_format=table_format, **kwargs)
|
||||
output_list = [l for l in output]
|
||||
expected = [
|
||||
'INSERT INTO "user" ("id", "name", "email", "phone", "description", "created_at", "updated_at") VALUES',
|
||||
" ('1', 'Jackson', 'jackson_test@gmail.com', '132454789', '', "
|
||||
+ "'2022-09-09 19:44:32.712343+08', '2022-09-09 19:44:32.712343+08')",
|
||||
";",
|
||||
]
|
||||
assert expected == output_list
|
||||
|
||||
|
||||
def test_output_sql_update():
|
||||
global formatter
|
||||
formatter = TabularOutputFormatter
|
||||
register_new_formatter(formatter)
|
||||
data = [
|
||||
[
|
||||
1,
|
||||
"Jackson",
|
||||
"jackson_test@gmail.com",
|
||||
"132454789",
|
||||
"",
|
||||
"2022-09-09 19:44:32.712343+08",
|
||||
"2022-09-09 19:44:32.712343+08",
|
||||
]
|
||||
]
|
||||
header = ["id", "name", "email", "phone", "description", "created_at", "updated_at"]
|
||||
table_format = "sql-update"
|
||||
kwargs = {
|
||||
"column_types": [int, str, str, str, str, str, str],
|
||||
"sep_title": "RECORD {n}",
|
||||
"sep_character": "-",
|
||||
"sep_length": (1, 25),
|
||||
"missing_value": "<null>",
|
||||
"integer_format": "",
|
||||
"float_format": "",
|
||||
"disable_numparse": True,
|
||||
"preserve_whitespace": True,
|
||||
"max_field_width": 500,
|
||||
}
|
||||
formatter.query = 'SELECT * FROM "user";'
|
||||
output = adapter(data, header, table_format=table_format, **kwargs)
|
||||
output_list = [l for l in output]
|
||||
print(output_list)
|
||||
expected = [
|
||||
'UPDATE "user" SET',
|
||||
" \"name\" = 'Jackson'",
|
||||
", \"email\" = 'jackson_test@gmail.com'",
|
||||
", \"phone\" = '132454789'",
|
||||
", \"description\" = ''",
|
||||
", \"created_at\" = '2022-09-09 19:44:32.712343+08'",
|
||||
", \"updated_at\" = '2022-09-09 19:44:32.712343+08'",
|
||||
"WHERE \"id\" = '1';",
|
||||
]
|
||||
assert expected == output_list
|
40
tests/test_auth.py
Normal file
40
tests/test_auth.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
import pytest
|
||||
from unittest import mock
|
||||
from pgcli import auth
|
||||
|
||||
|
||||
@pytest.mark.parametrize("enabled,call_count", [(True, 1), (False, 0)])
|
||||
def test_keyring_initialize(enabled, call_count):
|
||||
logger = mock.MagicMock()
|
||||
|
||||
with mock.patch("importlib.import_module", return_value=True) as import_method:
|
||||
auth.keyring_initialize(enabled, logger=logger)
|
||||
assert import_method.call_count == call_count
|
||||
|
||||
|
||||
def test_keyring_get_password_ok():
|
||||
with mock.patch("pgcli.auth.keyring", return_value=mock.MagicMock()):
|
||||
with mock.patch("pgcli.auth.keyring.get_password", return_value="abc123"):
|
||||
assert auth.keyring_get_password("test") == "abc123"
|
||||
|
||||
|
||||
def test_keyring_get_password_exception():
|
||||
with mock.patch("pgcli.auth.keyring", return_value=mock.MagicMock()):
|
||||
with mock.patch(
|
||||
"pgcli.auth.keyring.get_password", side_effect=Exception("Boom!")
|
||||
):
|
||||
assert auth.keyring_get_password("test") == ""
|
||||
|
||||
|
||||
def test_keyring_set_password_ok():
|
||||
with mock.patch("pgcli.auth.keyring", return_value=mock.MagicMock()):
|
||||
with mock.patch("pgcli.auth.keyring.set_password"):
|
||||
auth.keyring_set_password("test", "abc123")
|
||||
|
||||
|
||||
def test_keyring_set_password_exception():
|
||||
with mock.patch("pgcli.auth.keyring", return_value=mock.MagicMock()):
|
||||
with mock.patch(
|
||||
"pgcli.auth.keyring.set_password", side_effect=Exception("Boom!")
|
||||
):
|
||||
auth.keyring_set_password("test", "abc123")
|
|
@ -1,6 +1,6 @@
|
|||
from textwrap import dedent
|
||||
|
||||
import psycopg2
|
||||
import psycopg
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
from pgspecial.main import PGSpecial, NO_QUERY
|
||||
|
@ -282,6 +282,77 @@ def test_execute_from_file_io_error(os, executor, pgspecial):
|
|||
assert is_special == True
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_execute_from_commented_file_that_executes_another_file(
|
||||
executor, pgspecial, tmpdir
|
||||
):
|
||||
# https://github.com/dbcli/pgcli/issues/1336
|
||||
sqlfile1 = tmpdir.join("test01.sql")
|
||||
sqlfile1.write("-- asdf \n\\h")
|
||||
sqlfile2 = tmpdir.join("test00.sql")
|
||||
sqlfile2.write("--An useless comment;\nselect now();\n-- another useless comment")
|
||||
|
||||
rcfile = str(tmpdir.join("rcfile"))
|
||||
print(rcfile)
|
||||
cli = PGCli(pgexecute=executor, pgclirc_file=rcfile)
|
||||
assert cli != None
|
||||
statement = "--comment\n\\h"
|
||||
result = run(executor, statement, pgspecial=cli.pgspecial)
|
||||
assert result != None
|
||||
assert result[0].find("ALTER TABLE")
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_execute_commented_first_line_and_special(executor, pgspecial, tmpdir):
|
||||
# https://github.com/dbcli/pgcli/issues/1362
|
||||
|
||||
# just some base caes that should work also
|
||||
statement = "--comment\nselect now();"
|
||||
result = run(executor, statement, pgspecial=pgspecial)
|
||||
assert result != None
|
||||
assert result[1].find("now") >= 0
|
||||
|
||||
statement = "/*comment*/\nselect now();"
|
||||
result = run(executor, statement, pgspecial=pgspecial)
|
||||
assert result != None
|
||||
assert result[1].find("now") >= 0
|
||||
|
||||
statement = "/*comment\ncomment line2*/\nselect now();"
|
||||
result = run(executor, statement, pgspecial=pgspecial)
|
||||
assert result != None
|
||||
assert result[1].find("now") >= 0
|
||||
|
||||
statement = "--comment\n\\h"
|
||||
result = run(executor, statement, pgspecial=pgspecial)
|
||||
assert result != None
|
||||
assert result[1].find("ALTER") >= 0
|
||||
assert result[1].find("ABORT") >= 0
|
||||
|
||||
statement = "/*comment*/\n\h;"
|
||||
result = run(executor, statement, pgspecial=pgspecial)
|
||||
assert result != None
|
||||
assert result[1].find("ALTER") >= 0
|
||||
assert result[1].find("ABORT") >= 0
|
||||
|
||||
statement = " /*comment*/\n\h;"
|
||||
result = run(executor, statement, pgspecial=pgspecial)
|
||||
assert result != None
|
||||
assert result[1].find("ALTER") >= 0
|
||||
assert result[1].find("ABORT") >= 0
|
||||
|
||||
statement = "/*comment\ncomment line2*/\n\h;"
|
||||
result = run(executor, statement, pgspecial=pgspecial)
|
||||
assert result != None
|
||||
assert result[1].find("ALTER") >= 0
|
||||
assert result[1].find("ABORT") >= 0
|
||||
|
||||
statement = " /*comment\ncomment line2*/\n\h;"
|
||||
result = run(executor, statement, pgspecial=pgspecial)
|
||||
assert result != None
|
||||
assert result[1].find("ALTER") >= 0
|
||||
assert result[1].find("ABORT") >= 0
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_multiple_queries_same_line(executor):
|
||||
result = run(executor, "select 'foo'; select 'bar'")
|
||||
|
@ -428,7 +499,7 @@ def test_describe_special(executor, command, verbose, pattern, pgspecial):
|
|||
@dbtest
|
||||
@pytest.mark.parametrize("sql", ["invalid sql", "SELECT 1; select error;"])
|
||||
def test_raises_with_no_formatter(executor, sql):
|
||||
with pytest.raises(psycopg2.ProgrammingError):
|
||||
with pytest.raises(psycopg.ProgrammingError):
|
||||
list(executor.run(sql))
|
||||
|
||||
|
||||
|
@ -513,13 +584,6 @@ def test_short_host(executor):
|
|||
assert executor.short_host == "localhost1"
|
||||
|
||||
|
||||
class BrokenConnection:
|
||||
"""Mock a connection that failed."""
|
||||
|
||||
def cursor(self):
|
||||
raise psycopg2.InterfaceError("I'm broken!")
|
||||
|
||||
|
||||
class VirtualCursor:
|
||||
"""Mock a cursor to virtual database like pgbouncer."""
|
||||
|
||||
|
@ -549,13 +613,15 @@ def test_exit_without_active_connection(executor):
|
|||
aliases=(":q",),
|
||||
)
|
||||
|
||||
with patch.object(executor, "conn", BrokenConnection()):
|
||||
with patch.object(
|
||||
executor.conn, "cursor", side_effect=psycopg.InterfaceError("I'm broken!")
|
||||
):
|
||||
# we should be able to quit the app, even without active connection
|
||||
run(executor, "\\q", pgspecial=pgspecial)
|
||||
quit_handler.assert_called_once()
|
||||
|
||||
# an exception should be raised when running a query without active connection
|
||||
with pytest.raises(psycopg2.InterfaceError):
|
||||
with pytest.raises(psycopg.InterfaceError):
|
||||
run(executor, "select 1", pgspecial=pgspecial)
|
||||
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
= Gross Checks =
|
||||
* [ ] Check connecting to a local database.
|
||||
* [ ] Check connecting to a remote database.
|
||||
* [ ] Check connecting to a database with a user/password.
|
||||
* [ ] Check connecting to a non-existent database.
|
||||
* [ ] Test changing the database.
|
||||
|
||||
== PGExecute ==
|
||||
* [ ] Test successful execution given a cursor.
|
||||
* [ ] Test unsuccessful execution with a syntax error.
|
||||
* [ ] Test a series of executions with the same cursor without failure.
|
||||
* [ ] Test a series of executions with the same cursor with failure.
|
||||
* [ ] Test passing in a special command.
|
||||
|
||||
== Naive Autocompletion ==
|
||||
* [ ] Input empty string, ask for completions - Everything.
|
||||
* [ ] Input partial prefix, ask for completions - Stars with prefix.
|
||||
* [ ] Input fully autocompleted string, ask for completions - Only full match
|
||||
* [ ] Input non-existent prefix, ask for completions - nothing
|
||||
* [ ] Input lowercase prefix - case insensitive completions
|
||||
|
||||
== Smart Autocompletion ==
|
||||
* [ ] Input empty string and check if only keywords are returned.
|
||||
* [ ] Input SELECT prefix and check if only columns are returned.
|
||||
* [ ] Input SELECT blah - only keywords are returned.
|
||||
* [ ] Input SELECT * FROM - Table names only
|
||||
|
||||
== PGSpecial ==
|
||||
* [ ] Test \d
|
||||
* [ ] Test \d tablename
|
||||
* [ ] Test \d tablena*
|
||||
* [ ] Test \d non-existent-tablename
|
||||
* [ ] Test \d index
|
||||
* [ ] Test \d sequence
|
||||
* [ ] Test \d view
|
||||
|
||||
== Exceptionals ==
|
||||
* [ ] Test the 'use' command to change db.
|
|
@ -4,7 +4,7 @@ from unittest.mock import Mock
|
|||
from pgcli.main import PGCli
|
||||
|
||||
|
||||
# We need this fixtures beacause we need PGCli object to be created
|
||||
# We need this fixtures because we need PGCli object to be created
|
||||
# after test collection so it has config loaded from temp directory
|
||||
|
||||
|
||||
|
|
|
@ -844,7 +844,7 @@ def test_alter_column_type_suggests_types():
|
|||
"CREATE FUNCTION foo (bar INT, baz ",
|
||||
"SELECT * FROM foo() AS bar (baz ",
|
||||
"SELECT * FROM foo() AS bar (baz INT, qux ",
|
||||
# make sure this doesnt trigger special completion
|
||||
# make sure this doesn't trigger special completion
|
||||
"CREATE TABLE foo (dt d",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import pytest
|
||||
import psycopg2
|
||||
import psycopg2.extras
|
||||
import psycopg
|
||||
from pgcli.main import format_output, OutputSettings
|
||||
from pgcli.pgexecute import register_json_typecasters
|
||||
from os import getenv
|
||||
|
||||
POSTGRES_USER = getenv("PGUSER", "postgres")
|
||||
|
@ -12,12 +10,12 @@ POSTGRES_PASSWORD = getenv("PGPASSWORD", "postgres")
|
|||
|
||||
|
||||
def db_connection(dbname=None):
|
||||
conn = psycopg2.connect(
|
||||
conn = psycopg.connect(
|
||||
user=POSTGRES_USER,
|
||||
host=POSTGRES_HOST,
|
||||
password=POSTGRES_PASSWORD,
|
||||
port=POSTGRES_PORT,
|
||||
database=dbname,
|
||||
dbname=dbname,
|
||||
)
|
||||
conn.autocommit = True
|
||||
return conn
|
||||
|
@ -26,11 +24,10 @@ def db_connection(dbname=None):
|
|||
try:
|
||||
conn = db_connection()
|
||||
CAN_CONNECT_TO_DB = True
|
||||
SERVER_VERSION = conn.server_version
|
||||
json_types = register_json_typecasters(conn, lambda x: x)
|
||||
JSON_AVAILABLE = "json" in json_types
|
||||
JSONB_AVAILABLE = "jsonb" in json_types
|
||||
except:
|
||||
SERVER_VERSION = conn.info.parameter_status("server_version")
|
||||
JSON_AVAILABLE = True
|
||||
JSONB_AVAILABLE = True
|
||||
except Exception as x:
|
||||
CAN_CONNECT_TO_DB = JSON_AVAILABLE = JSONB_AVAILABLE = False
|
||||
SERVER_VERSION = 0
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue