You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gentoo-full-overlay/dev-db/mycli/files/mycli-1.22.2_p20201026.patch

471 lines
17 KiB

diff --git a/.travis.yml b/.travis.yml
index 0afb5cc..182dea7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,7 +12,7 @@ matrix:
install:
- pip install -r requirements-dev.txt
- - pip install -e .
+ - pip install --no-cache-dir -e .
- sudo rm -f /etc/mysql/conf.d/performance-schema.cnf
- sudo service mysql restart
diff --git a/README.md b/README.md
index efe804d..d5a0687 100644
--- a/README.md
+++ b/README.md
@@ -96,6 +96,7 @@ $ sudo apt-get install mycli # Only on debian or ubuntu
--local-infile BOOLEAN Enable/disable LOAD DATA LOCAL INFILE.
--login-path TEXT Read this path from the login file.
-e, --execute TEXT Execute command and quit.
+ --init-command TEXT SQL statement to execute after connecting.
--help Show this message and exit.
Features
diff --git a/changelog.md b/changelog.md
index a4fea35..508c801 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,9 +1,22 @@
+TBD
+===
+
+Features:
+---------
+
+* Add an option `--init-command` to execute SQL after connecting (Thanks: [KITAGAWA Yasutaka]).
+
+Bug Fixes:
+----------
+* Fixed compatibility with sqlparse 0.4 (Thanks: [mtorromeo]).
+
1.22.2
======
Bug Fixes:
----------
-* Make the `pwd` module optional.
+
+* Make the `pwd` module optional.
1.22.1
======
@@ -18,6 +31,11 @@ Features:
* Add an option `--list-ssh-config` to list ssh configurations.
* Add an option `--ssh-config-path` to choose ssh configuration path.
+Bug Fixes:
+----------
+
+* Fix specifying empty password with `--password=''` when config file has a password set (Thanks: [Zach DeCook]).
+
1.21.1
======
@@ -28,6 +46,7 @@ Bug Fixes:
* Fix broken auto-completion for favorite queries (Thanks: [Amjith]).
* Fix undefined variable exception when running with --no-warn (Thanks: [Georgy Frolov])
+* Support setting color for null value (Thanks: [laixintao])
1.21.0
======
@@ -768,3 +787,6 @@ Bug Fixes:
[François Pietka]: https://github.com/fpietka
[Frederic Aoustin]: https://github.com/fraoustin
[Georgy Frolov]: https://github.com/pasenor
+[Zach DeCook]: https://zachdecook.com
+[laixintao]: https://github.com/laixintao
+[mtorromeo]: https://github.com/mtorromeo
diff --git a/mycli/AUTHORS b/mycli/AUTHORS
index b3636d9..a1204b0 100644
--- a/mycli/AUTHORS
+++ b/mycli/AUTHORS
@@ -72,6 +72,10 @@ Contributors:
* Jakub Boukal
* Takeshi D. Itoh
* laixintao
+ * Zach DeCook
+ * kevinhwang91
+ * KITAGAWA Yasutaka
+ * Massimiliano Torromeo
Creator:
--------
diff --git a/mycli/clistyle.py b/mycli/clistyle.py
index c94f793..293f0f4 100644
--- a/mycli/clistyle.py
+++ b/mycli/clistyle.py
@@ -34,6 +34,7 @@ TOKEN_TO_PROMPT_STYLE = {
Token.Output.Header: 'output.header',
Token.Output.OddRow: 'output.odd-row',
Token.Output.EvenRow: 'output.even-row',
+ Token.Output.Null: 'output.null',
Token.Prompt: 'prompt',
Token.Continuation: 'continuation',
}
diff --git a/mycli/main.py b/mycli/main.py
index 03797a0..dffd724 100755
--- a/mycli/main.py
+++ b/mycli/main.py
@@ -98,7 +98,7 @@ class MyCli(object):
xdg_config_home = "~/.config"
system_config_files = [
'/etc/myclirc',
- os.path.join(xdg_config_home, "mycli", "myclirc")
+ os.path.join(os.path.expanduser(xdg_config_home), "mycli", "myclirc")
]
default_config_file = os.path.join(PACKAGE_ROOT, 'myclirc')
@@ -152,7 +152,7 @@ class MyCli(object):
c['main'].as_bool('auto_vertical_output')
# Write user config if system config wasn't the last config loaded.
- if c.filename not in self.system_config_files:
+ if c.filename not in self.system_config_files and not os.path.exists(myclirc):
write_default_config(self.default_config_file, myclirc)
# audit log
@@ -363,7 +363,7 @@ class MyCli(object):
def connect(self, database='', user='', passwd='', host='', port='',
socket='', charset='', local_infile='', ssl='',
ssh_user='', ssh_host='', ssh_port='',
- ssh_password='', ssh_key_filename=''):
+ ssh_password='', ssh_key_filename='', init_command=''):
cnf = {'database': None,
'user': None,
@@ -396,7 +396,7 @@ class MyCli(object):
port = port or cnf['port']
ssl = ssl or {}
- passwd = passwd or cnf['password']
+ passwd = passwd if isinstance(passwd, str) else cnf['password']
charset = charset or cnf['default-character-set'] or 'utf8'
# Favor whichever local_infile option is set.
@@ -420,7 +420,7 @@ class MyCli(object):
self.sqlexecute = SQLExecute(
database, user, passwd, host, port, socket, charset,
local_infile, ssl, ssh_user, ssh_host, ssh_port,
- ssh_password, ssh_key_filename
+ ssh_password, ssh_key_filename, init_command
)
except OperationalError as e:
if ('Access denied for user' in e.args[1]):
@@ -429,7 +429,7 @@ class MyCli(object):
self.sqlexecute = SQLExecute(
database, user, new_passwd, host, port, socket,
charset, local_infile, ssl, ssh_user, ssh_host,
- ssh_port, ssh_password, ssh_key_filename
+ ssh_port, ssh_password, ssh_key_filename, init_command
)
else:
raise e
@@ -1051,6 +1051,8 @@ class MyCli(object):
help='Read this path from the login file.')
@click.option('-e', '--execute', type=str,
help='Execute command and quit.')
+@click.option('--init-command', type=str,
+ help='SQL statement to execute after connecting.')
@click.argument('database', default='', nargs=1)
def cli(database, user, host, port, socket, password, dbname,
version, verbose, prompt, logfile, defaults_group_suffix,
@@ -1058,7 +1060,8 @@ def cli(database, user, host, port, socket, password, dbname,
ssl_ca, ssl_capath, ssl_cert, ssl_key, ssl_cipher,
ssl_verify_server_cert, table, csv, warn, execute, myclirc, dsn,
list_dsn, ssh_user, ssh_host, ssh_port, ssh_password,
- ssh_key_filename, list_ssh_config, ssh_config_path, ssh_config_host):
+ ssh_key_filename, list_ssh_config, ssh_config_path, ssh_config_host,
+ init_command):
"""A MySQL terminal client with auto-completion and syntax highlighting.
\b
@@ -1182,7 +1185,8 @@ def cli(database, user, host, port, socket, password, dbname,
ssh_host=ssh_host,
ssh_port=ssh_port,
ssh_password=ssh_password,
- ssh_key_filename=ssh_key_filename
+ ssh_key_filename=ssh_key_filename,
+ init_command=init_command
)
mycli.logger.debug('Launch Params: \n'
diff --git a/mycli/myclirc b/mycli/myclirc
index 534b201..ba3ea1e 100644
--- a/mycli/myclirc
+++ b/mycli/myclirc
@@ -111,6 +111,7 @@ bottom-toolbar.transaction.failed = 'bg:#222222 #ff005f bold'
output.header = "#00ff5f bold"
output.odd-row = ""
output.even-row = ""
+output.null = "#808080"
# Favorite queries.
[favorite_queries]
diff --git a/mycli/packages/completion_engine.py b/mycli/packages/completion_engine.py
index 2b19c32..3cff2cc 100644
--- a/mycli/packages/completion_engine.py
+++ b/mycli/packages/completion_engine.py
@@ -2,7 +2,6 @@ import os
import sys
import sqlparse
from sqlparse.sql import Comparison, Identifier, Where
-from sqlparse.compat import text_type
from .parseutils import last_word, extract_tables, find_prev_keyword
from .special import parse_special_command
@@ -55,7 +54,7 @@ def suggest_type(full_text, text_before_cursor):
stmt_start, stmt_end = 0, 0
for statement in parsed:
- stmt_len = len(text_type(statement))
+ stmt_len = len(str(statement))
stmt_start, stmt_end = stmt_end, stmt_end + stmt_len
if stmt_end >= current_pos:
diff --git a/mycli/sqlexecute.py b/mycli/sqlexecute.py
index c68af0f..7534982 100644
--- a/mycli/sqlexecute.py
+++ b/mycli/sqlexecute.py
@@ -42,7 +42,7 @@ class SQLExecute(object):
def __init__(self, database, user, password, host, port, socket, charset,
local_infile, ssl, ssh_user, ssh_host, ssh_port, ssh_password,
- ssh_key_filename):
+ ssh_key_filename, init_command=None):
self.dbname = database
self.user = user
self.password = password
@@ -59,12 +59,13 @@ class SQLExecute(object):
self.ssh_port = ssh_port
self.ssh_password = ssh_password
self.ssh_key_filename = ssh_key_filename
+ self.init_command = init_command
self.connect()
def connect(self, database=None, user=None, password=None, host=None,
port=None, socket=None, charset=None, local_infile=None,
ssl=None, ssh_host=None, ssh_port=None, ssh_user=None,
- ssh_password=None, ssh_key_filename=None):
+ ssh_password=None, ssh_key_filename=None, init_command=None):
db = (database or self.dbname)
user = (user or self.user)
password = (password or self.password)
@@ -79,6 +80,7 @@ class SQLExecute(object):
ssh_port = (ssh_port or self.ssh_port)
ssh_password = (ssh_password or self.ssh_password)
ssh_key_filename = (ssh_key_filename or self.ssh_key_filename)
+ init_command = (init_command or self.init_command)
_logger.debug(
'Connection DB Params: \n'
'\tdatabase: %r'
@@ -93,9 +95,11 @@ class SQLExecute(object):
'\tssh_host: %r'
'\tssh_port: %r'
'\tssh_password: %r'
- '\tssh_key_filename: %r',
+ '\tssh_key_filename: %r'
+ '\tinit_command: %r',
db, user, host, port, socket, charset, local_infile, ssl,
- ssh_user, ssh_host, ssh_port, ssh_password, ssh_key_filename
+ ssh_user, ssh_host, ssh_port, ssh_password, ssh_key_filename,
+ init_command
)
conv = conversions.copy()
conv.update({
@@ -110,12 +114,16 @@ class SQLExecute(object):
if ssh_host:
defer_connect = True
+ client_flag = pymysql.constants.CLIENT.INTERACTIVE
+ if init_command and len(list(special.split_queries(init_command))) > 1:
+ client_flag |= pymysql.constants.CLIENT.MULTI_STATEMENTS
+
conn = pymysql.connect(
database=db, user=user, password=password, host=host, port=port,
unix_socket=socket, use_unicode=True, charset=charset,
- autocommit=True, client_flag=pymysql.constants.CLIENT.INTERACTIVE,
+ autocommit=True, client_flag=client_flag,
local_infile=local_infile, conv=conv, ssl=ssl, program_name="mycli",
- defer_connect=defer_connect
+ defer_connect=defer_connect, init_command=init_command
)
if ssh_host:
@@ -146,6 +154,7 @@ class SQLExecute(object):
self.socket = socket
self.charset = charset
self.ssl = ssl
+ self.init_command = init_command
# retrieve connection id
self.reset_connection_id()
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 8e206a5..7a38ed5 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -3,8 +3,8 @@ pytest!=3.3.0
pytest-cov==2.4.0
tox
twine==1.12.1
-behave
-pexpect
+behave>=1.2.4
+pexpect==3.3
coverage==5.0.4
codecov==2.0.9
autopep8==1.3.3
diff --git a/setup.py b/setup.py
index 156cd1a..fbab22e 100755
--- a/setup.py
+++ b/setup.py
@@ -24,7 +24,7 @@ install_requirements = [
'sqlparse>=0.3.0,<0.4.0',
'configobj >= 5.0.5',
'cryptography >= 1.0.0',
- 'cli_helpers[styles] > 1.1.0',
+ 'cli_helpers[styles] >= 2.0.1',
]
@@ -65,7 +65,7 @@ class test(TestCommand):
def initialize_options(self):
TestCommand.initialize_options(self)
self.pytest_args = ''
- self.behave_args = ''
+ self.behave_args = '--no-capture'
def run_tests(self):
unit_test_errno = subprocess.call(
diff --git a/test/features/environment.py b/test/features/environment.py
index 1a49dbe..cb35140 100644
--- a/test/features/environment.py
+++ b/test/features/environment.py
@@ -16,7 +16,7 @@ def before_all(context):
os.environ['LINES'] = "100"
os.environ['COLUMNS'] = "100"
os.environ['EDITOR'] = 'ex'
- os.environ['LC_ALL'] = 'en_US.utf8'
+ os.environ['LC_ALL'] = 'en_US.UTF-8'
os.environ['PROMPT_TOOLKIT_NO_CPR'] = '1'
test_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
@@ -118,11 +118,12 @@ def after_scenario(context, _):
host = context.conf['host']
dbname = context.currentdb
context.cli.expect_exact(
- '{0}@{1}:{2}> '.format(
+ '{0}@{1}:{2}>'.format(
user, host, dbname
),
timeout=5
)
+ context.cli.sendcontrol('c')
context.cli.sendcontrol('d')
context.cli.expect_exact(pexpect.EOF, timeout=5)
diff --git a/test/features/steps/crud_database.py b/test/features/steps/crud_database.py
index a0bfa53..be6dec0 100644
--- a/test/features/steps/crud_database.py
+++ b/test/features/steps/crud_database.py
@@ -64,15 +64,13 @@ def step_see_prompt(context):
user = context.conf['user']
host = context.conf['host']
dbname = context.currentdb
- wrappers.expect_exact(context, '{0}@{1}:{2}> '.format(
- user, host, dbname), timeout=5)
- context.atprompt = True
+ wrappers.wait_prompt(context, '{0}@{1}:{2}> '.format(user, host, dbname))
@then('we see help output')
def step_see_help(context):
for expected_line in context.fixture_data['help_commands.txt']:
- wrappers.expect_exact(context, expected_line + '\r\n', timeout=1)
+ wrappers.expect_exact(context, expected_line, timeout=1)
@then('we see database created')
@@ -96,10 +94,7 @@ def step_see_db_dropped_no_default(context):
context.currentdb = None
wrappers.expect_exact(context, 'Query OK, 0 rows affected', timeout=2)
- wrappers.expect_exact(context, '{0}@{1}:{2}> '.format(
- user, host, database), timeout=5)
-
- context.atprompt = True
+ wrappers.wait_prompt(context, '{0}@{1}:{2}>'.format(user, host, database))
@then('we see database connected')
diff --git a/test/features/steps/wrappers.py b/test/features/steps/wrappers.py
index 565ca59..de833dd 100644
--- a/test/features/steps/wrappers.py
+++ b/test/features/steps/wrappers.py
@@ -88,7 +88,7 @@ def wait_prompt(context, prompt=None):
user = context.conf['user']
host = context.conf['host']
dbname = context.currentdb
- prompt = '{0}@{1}:{2}> '.format(
+ prompt = '{0}@{1}:{2}>'.format(
user, host, dbname),
expect_exact(context, prompt, timeout=5)
context.atprompt = True
diff --git a/test/test_main.py b/test/test_main.py
index 3f92bd1..707c359 100644
--- a/test/test_main.py
+++ b/test/test_main.py
@@ -492,3 +492,37 @@ def test_ssh_config(monkeypatch):
MockMyCli.connect_args["ssh_host"] == "arg_host" and \
MockMyCli.connect_args["ssh_port"] == 3 and \
MockMyCli.connect_args["ssh_key_filename"] == "/path/to/key"
+
+
+@dbtest
+def test_init_command_arg(executor):
+ init_command = "set sql_select_limit=1000"
+ sql = 'show variables like "sql_select_limit";'
+ runner = CliRunner()
+ result = runner.invoke(
+ cli, args=CLI_ARGS + ["--init-command", init_command], input=sql
+ )
+
+ expected = "sql_select_limit\t1000\n"
+ assert result.exit_code == 0
+ assert expected in result.output
+
+
+@dbtest
+def test_init_command_multiple_arg(executor):
+ init_command = 'set sql_select_limit=2000; set max_join_size=20000'
+ sql = (
+ 'show variables like "sql_select_limit";\n'
+ 'show variables like "max_join_size"'
+ )
+ runner = CliRunner()
+ result = runner.invoke(
+ cli, args=CLI_ARGS + ['--init-command', init_command], input=sql
+ )
+
+ expected_sql_select_limit = 'sql_select_limit\t2000\n'
+ expected_max_join_size = 'max_join_size\t20000\n'
+
+ assert result.exit_code == 0
+ assert expected_sql_select_limit in result.output
+ assert expected_max_join_size in result.output
diff --git a/test/test_tabular_output.py b/test/test_tabular_output.py
index 7d7d000..c20c7de 100644
--- a/test/test_tabular_output.py
+++ b/test/test_tabular_output.py
@@ -16,7 +16,7 @@ from pymysql.constants import FIELD_TYPE
@pytest.fixture
def mycli():
cli = MyCli()
- cli.connect(None, USER, PASSWORD, HOST, PORT, None)
+ cli.connect(None, USER, PASSWORD, HOST, PORT, None, init_command=None)
return cli