summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml19
-rw-r--r--.github/workflows/codeql.yml41
-rw-r--r--.gitignore3
-rw-r--r--README.md24
-rw-r--r--changelog.md49
-rw-r--r--mycli/AUTHORS13
-rw-r--r--mycli/__init__.py2
-rw-r--r--mycli/clitoolbar.py5
-rwxr-xr-xmycli/main.py14
-rw-r--r--mycli/sqlexecute.py43
-rw-r--r--requirements-dev.txt1
-rwxr-xr-xsetup.py7
-rw-r--r--test/test_main.py49
-rw-r--r--test/test_special_iocommands.py82
-rw-r--r--test/test_sqlexecute.py14
15 files changed, 248 insertions, 118 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e91d4dd..fb34daa 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,28 +10,31 @@ jobs:
strategy:
matrix:
python-version: [
- '3.7',
'3.8',
'3.9',
'3.10',
+ '3.11',
+ '3.12',
]
include:
- - python-version: '3.7'
- os: ubuntu-18.04 # MySQL 5.7.32
- python-version: '3.8'
- os: ubuntu-18.04 # MySQL 5.7.32
+ os: ubuntu-20.04 # MySQL 8.0.36
- python-version: '3.9'
- os: ubuntu-20.04 # MySQL 8.0.22
+ os: ubuntu-20.04 # MySQL 8.0.36
- python-version: '3.10'
- os: ubuntu-22.04 # MySQL 8.0.28
+ os: ubuntu-22.04 # MySQL 8.0.36
+ - python-version: '3.11'
+ os: ubuntu-22.04 # MySQL 8.0.36
+ - python-version: '3.12'
+ os: ubuntu-22.04 # MySQL 8.0.36
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
deleted file mode 100644
index bd0617b..0000000
--- a/.github/workflows/codeql.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-name: "CodeQL"
-
-on:
- push:
- branches: [ "main" ]
- pull_request:
- branches: [ "main" ]
- schedule:
- - cron: "12 18 * * 1"
-
-jobs:
- analyze:
- name: Analyze
- runs-on: ubuntu-latest
- permissions:
- actions: read
- contents: read
- security-events: write
-
- strategy:
- fail-fast: false
- matrix:
- language: [ python ]
-
- steps:
- - name: Checkout
- uses: actions/checkout@v3
-
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v2
- with:
- languages: ${{ matrix.language }}
- queries: +security-and-quality
-
- - name: Autobuild
- uses: github/codeql-action/autobuild@v2
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
- with:
- category: "/language:${{ matrix.language }}"
diff --git a/.gitignore b/.gitignore
index b13429e..970fcd4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,6 @@
.cache/
.coverage
.coverage.*
+
+.venv/
+venv/
diff --git a/README.md b/README.md
index 9e177b7..e6dcf17 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,6 @@
# mycli
[![Build Status](https://github.com/dbcli/mycli/workflows/mycli/badge.svg)](https://github.com/dbcli/mycli/actions?query=workflow%3Amycli)
-[![PyPI](https://img.shields.io/pypi/v/mycli.svg)](https://pypi.python.org/pypi/mycli)
-[![LGTM](https://img.shields.io/lgtm/grade/python/github/dbcli/mycli.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/dbcli/mycli/context:python)
A command line client for MySQL that can do auto-completion and syntax highlighting.
@@ -76,6 +74,9 @@ $ sudo apt-get install mycli # Only on debian or ubuntu
--ssl-cert PATH X509 cert in PEM format.
--ssl-key PATH X509 key in PEM format.
--ssl-cipher TEXT SSL cipher to use.
+ --tls-version [TLSv1|TLSv1.1|TLSv1.2|TLSv1.3]
+ TLS protocol version for secure connection.
+
--ssl-verify-server-cert Verify server's "Common Name" in its cert
against hostname used when connecting. This
option is disabled by default.
@@ -178,29 +179,10 @@ Fedora has a package available for mycli, install it using dnf:
$ sudo dnf install mycli
```
-### RHEL, Centos
-
-I haven't built an RPM package for mycli for RHEL or Centos yet. So please use `pip` to install `mycli`. You can install pip on your system using:
-
-```
-$ sudo yum install python3-pip
-```
-
-Once that is installed, you can install mycli as follows:
-
-```
-$ sudo pip3 install mycli
-```
-
### Windows
Follow the instructions on this blogpost: https://www.codewall.co.uk/installing-using-mycli-on-windows/
-### Cygwin
-
-1. Make sure the following Cygwin packages are installed:
-`python3`, `python3-pip`.
-2. Install mycli: `pip3 install mycli`
### Thanks:
diff --git a/changelog.md b/changelog.md
index 122012d..fb32e5a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,46 @@
+Upcoming Release (TBD)
+======================
+
+Bug Fixes:
+----------
+
+
+Internal:
+---------
+
+Features:
+---------
+
+
+1.27.2 (2024/04/03)
+===================
+
+Bug Fixes:
+----------
+
+* Don't use default prompt when one is not supplied to the --prompt option.
+
+
+1.27.1 (2024/03/28)
+===================
+
+
+Bug Fixes:
+----------
+
+* Don't install tests.
+* Do not ignore the socket passed with the -S option, even when no port is passed
+* Fix unexpected exception when using dsn without username & password (Thanks: [Will Wang])
+* Let the `--prompt` option act normally with its predefined default value
+
+
+
+Internal:
+---------
+* paramiko is newer than 2.11.0 now, remove version pinning `cryptography`.
+* Drop support for Python 3.7
+
+
1.27.0 (2023/08/11)
===================
@@ -14,6 +57,7 @@ Bug Fixes:
* Remove vi-mode bindings for prettify/unprettify.
* Honor `\G` when executing from commandline with `-e`.
* Correctly report the version of TiDB.
+* Revised `botton` spelling mistakes with `bottom` in `mycli/clitoolbar.py`
1.26.1 (2022/09/01)
@@ -35,6 +79,10 @@ Features:
* Add prettify/unprettify keybindings to format the current statement using `sqlglot`.
+Features:
+---------
+* Add `--tls-version` option to control the tls version used.
+
Internal:
---------
* Pin `cryptography` to suppress `paramiko` warning, helping CI complete and presumably affecting some users.
@@ -950,3 +998,4 @@ Bug Fixes:
[William GARCIA]: https://github.com/willgarcia
[xeron]: https://github.com/xeron
[Zach DeCook]: https://zachdecook.com
+[Will Wang]: https://github.com/willww64
diff --git a/mycli/AUTHORS b/mycli/AUTHORS
index a805465..e9c73aa 100644
--- a/mycli/AUTHORS
+++ b/mycli/AUTHORS
@@ -1,11 +1,7 @@
-Project Lead:
--------------
- * Thomas Roten
-
-
Core Developers:
----------------
+ * Thomas Roten
* Irina Truong
* Matheus Rosa
* Darik Gamble
@@ -35,6 +31,7 @@ Contributors:
* Daniel Black
* Daniel West
* Daniël van Eeden
+ * Fabrizio Gennari
* François Pietka
* Frederic Aoustin
* Georgy Frolov
@@ -94,6 +91,12 @@ Contributors:
* Arvind Mishra
* Kevin Schmeichel
* Mel Dafert
+ * Thomas Copper
+ * Will Wang
+ * Alfred Wingate
+ * Zhanze Wang
+ * Houston Wong
+
Created by:
-----------
diff --git a/mycli/__init__.py b/mycli/__init__.py
index e2ba8ba..b5476c1 100644
--- a/mycli/__init__.py
+++ b/mycli/__init__.py
@@ -1 +1 @@
-__version__ = '1.27.0'
+__version__ = '1.27.2'
diff --git a/mycli/clitoolbar.py b/mycli/clitoolbar.py
index 24d1108..52b6ee4 100644
--- a/mycli/clitoolbar.py
+++ b/mycli/clitoolbar.py
@@ -7,8 +7,7 @@ from .packages import special
def create_toolbar_tokens_func(mycli, show_fish_help):
"""Return a function that generates the toolbar tokens."""
def get_toolbar_tokens():
- result = []
- result.append(('class:bottom-toolbar', ' '))
+ result = [('class:bottom-toolbar', ' ')]
if mycli.multi_line:
delimiter = special.get_current_delimiter()
@@ -26,7 +25,7 @@ def create_toolbar_tokens_func(mycli, show_fish_help):
'[F3] Multiline: OFF '))
if mycli.prompt_app.editing_mode == EditingMode.VI:
result.append((
- 'class:botton-toolbar.on',
+ 'class:bottom-toolbar.on',
'Vi-mode ({})'.format(_get_vi_mode())
))
diff --git a/mycli/main.py b/mycli/main.py
index 02a09cf..ce4dff7 100755
--- a/mycli/main.py
+++ b/mycli/main.py
@@ -93,6 +93,7 @@ SUPPORT_INFO = (
class MyCli(object):
default_prompt = '\\t \\u@\\h:\\d> '
+ default_prompt_splitln = '\\u@\\h\\n(\\t):\\d>'
max_len_prompt = 45
defaults_suffix = None
@@ -427,6 +428,7 @@ class MyCli(object):
port = 3306
if not host or host == 'localhost':
socket = (
+ socket or
cnf['socket'] or
cnf['default_socket'] or
guess_socket_location()
@@ -643,7 +645,7 @@ class MyCli(object):
def get_message():
prompt = self.get_prompt(self.prompt_format)
if self.prompt_format == self.default_prompt and len(prompt) > self.max_len_prompt:
- prompt = self.get_prompt('\\d> ')
+ prompt = self.get_prompt(self.default_prompt_splitln)
prompt = prompt.replace("\\x1b", "\x1b")
return ANSI(prompt)
@@ -1135,6 +1137,9 @@ class MyCli(object):
@click.option('--ssl-key', help='X509 key in PEM format.',
type=click.Path(exists=True))
@click.option('--ssl-cipher', help='SSL cipher to use.')
+@click.option('--tls-version',
+ type=click.Choice(['TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3'], case_sensitive=False),
+ help='TLS protocol version for secure connection.')
@click.option('--ssl-verify-server-cert', is_flag=True,
help=('Verify server\'s "Common Name" in its cert against '
'hostname used when connecting. This option is disabled '
@@ -1186,8 +1191,8 @@ def cli(database, user, host, port, socket, password, dbname,
version, verbose, prompt, logfile, defaults_group_suffix,
defaults_file, login_path, auto_vertical_output, local_infile,
ssl_enable, 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,
+ tls_version, 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,
init_command, charset, password_file):
"""A MySQL terminal client with auto-completion and syntax highlighting.
@@ -1246,6 +1251,7 @@ def cli(database, user, host, port, socket, password, dbname,
'key': ssl_key and os.path.expanduser(ssl_key),
'capath': ssl_capath,
'cipher': ssl_cipher,
+ 'tls_version': tls_version,
'check_hostname': ssl_verify_server_cert,
}
@@ -1278,7 +1284,7 @@ def cli(database, user, host, port, socket, password, dbname,
uri = urlparse(dsn_uri)
if not database:
database = uri.path[1:] # ignore the leading fwd slash
- if not user:
+ if not user and uri.username is not None:
user = unquote(uri.username)
if not password and uri.password is not None:
password = unquote(uri.password)
diff --git a/mycli/sqlexecute.py b/mycli/sqlexecute.py
index fecbefb..bd5f5d9 100644
--- a/mycli/sqlexecute.py
+++ b/mycli/sqlexecute.py
@@ -176,11 +176,15 @@ class SQLExecute(object):
if init_command and len(list(special.split_queries(init_command))) > 1:
client_flag |= pymysql.constants.CLIENT.MULTI_STATEMENTS
+ ssl_context = None
+ if ssl:
+ ssl_context = self._create_ssl_ctx(ssl)
+
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=client_flag,
- local_infile=local_infile, conv=conv, ssl=ssl, program_name="mycli",
+ local_infile=local_infile, conv=conv, ssl=ssl_context, program_name="mycli",
defer_connect=defer_connect, init_command=init_command
)
@@ -354,3 +358,40 @@ class SQLExecute(object):
def change_db(self, db):
self.conn.select_db(db)
self.dbname = db
+
+ def _create_ssl_ctx(self, sslp):
+ import ssl
+
+ ca = sslp.get("ca")
+ capath = sslp.get("capath")
+ hasnoca = ca is None and capath is None
+ ctx = ssl.create_default_context(cafile=ca, capath=capath)
+ ctx.check_hostname = not hasnoca and sslp.get("check_hostname", True)
+ ctx.verify_mode = ssl.CERT_NONE if hasnoca else ssl.CERT_REQUIRED
+ if "cert" in sslp:
+ ctx.load_cert_chain(sslp["cert"], keyfile=sslp.get("key"))
+ if "cipher" in sslp:
+ ctx.set_ciphers(sslp["cipher"])
+
+ # raise this default to v1.1 or v1.2?
+ ctx.minimum_version = ssl.TLSVersion.TLSv1
+
+ if "tls_version" in sslp:
+ tls_version = sslp["tls_version"]
+
+ if tls_version == "TLSv1":
+ ctx.minimum_version = ssl.TLSVersion.TLSv1
+ ctx.maximum_version = ssl.TLSVersion.TLSv1
+ elif tls_version == "TLSv1.1":
+ ctx.minimum_version = ssl.TLSVersion.TLSv1_1
+ ctx.maximum_version = ssl.TLSVersion.TLSv1_1
+ elif tls_version == "TLSv1.2":
+ ctx.minimum_version = ssl.TLSVersion.TLSv1_2
+ ctx.maximum_version = ssl.TLSVersion.TLSv1_2
+ elif tls_version == "TLSv1.3":
+ ctx.minimum_version = ssl.TLSVersion.TLSv1_3
+ ctx.maximum_version = ssl.TLSVersion.TLSv1_3
+ else:
+ _logger.error('Invalid tls version: %s', tls_version)
+
+ return ctx
diff --git a/requirements-dev.txt b/requirements-dev.txt
index c2cd04b..3f5fbdf 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -14,3 +14,4 @@ pyperclip>=1.8.1
importlib_resources>=5.0.0
pyaes>=1.6.1
sqlglot>=5.1.3
+setuptools
diff --git a/setup.py b/setup.py
index 2f69672..2c4f9e1 100755
--- a/setup.py
+++ b/setup.py
@@ -18,9 +18,8 @@ description = 'CLI for MySQL Database. With auto-completion and syntax highlight
install_requirements = [
'click >= 7.0',
- # Temporary to suppress paramiko Blowfish warning which breaks CI.
- # Pinning cryptography should not be needed after paramiko 2.11.0.
- 'cryptography == 36.0.2',
+ # Pinning cryptography is not needed after paramiko 2.11.0. Correct it
+ 'cryptography >= 1.0.0',
# 'Pygments>=1.6,<=2.11.1',
'Pygments>=1.6',
'prompt_toolkit>=3.0.6,<4.0.0',
@@ -95,7 +94,7 @@ setup(
author_email='mycli-dev@googlegroups.com',
version=version,
url='http://mycli.net',
- packages=find_packages(),
+ packages=find_packages(exclude=['test*']),
package_data={'mycli': ['myclirc', 'AUTHORS', 'SPONSORS']},
description=description,
long_description=description,
diff --git a/test/test_main.py b/test/test_main.py
index 64cba0a..589d6cd 100644
--- a/test/test_main.py
+++ b/test/test_main.py
@@ -254,23 +254,21 @@ def test_conditional_pager(monkeypatch):
SPECIAL_COMMANDS['pager'].handler('')
-def test_reserved_space_is_integer():
+def test_reserved_space_is_integer(monkeypatch):
"""Make sure that reserved space is returned as an integer."""
def stub_terminal_size():
return (5, 5)
- old_func = shutil.get_terminal_size
-
- shutil.get_terminal_size = stub_terminal_size
- mycli = MyCli()
- assert isinstance(mycli.get_reserved_space(), int)
-
- shutil.get_terminal_size = old_func
+ with monkeypatch.context() as m:
+ m.setattr(shutil, 'get_terminal_size', stub_terminal_size)
+ mycli = MyCli()
+ assert isinstance(mycli.get_reserved_space(), int)
def test_list_dsn():
runner = CliRunner()
- with NamedTemporaryFile(mode="w") as myclirc:
+ # keep Windows from locking the file with delete=False
+ with NamedTemporaryFile(mode="w",delete=False) as myclirc:
myclirc.write(dedent("""\
[alias_dsn]
test = mysql://test/test
@@ -281,6 +279,15 @@ def test_list_dsn():
assert result.output == "test\n"
result = runner.invoke(cli, args=args + ['--verbose'])
assert result.output == "test : mysql://test/test\n"
+
+ # delete=False means we should try to clean up
+ try:
+ if os.path.exists(myclirc.name):
+ os.remove(myclirc.name)
+ except Exception as e:
+ print(f"An error occurred while attempting to delete the file: {e}")
+
+
def test_prettify_statement():
@@ -299,7 +306,8 @@ def test_unprettify_statement():
def test_list_ssh_config():
runner = CliRunner()
- with NamedTemporaryFile(mode="w") as ssh_config:
+ # keep Windows from locking the file with delete=False
+ with NamedTemporaryFile(mode="w",delete=False) as ssh_config:
ssh_config.write(dedent("""\
Host test
Hostname test.example.com
@@ -313,6 +321,13 @@ def test_list_ssh_config():
assert "test\n" in result.output
result = runner.invoke(cli, args=args + ['--verbose'])
assert "test : test.example.com\n" in result.output
+
+ # delete=False means we should try to clean up
+ try:
+ if os.path.exists(ssh_config.name):
+ os.remove(ssh_config.name)
+ except Exception as e:
+ print(f"An error occurred while attempting to delete the file: {e}")
def test_dsn(monkeypatch):
@@ -466,7 +481,8 @@ def test_ssh_config(monkeypatch):
runner = CliRunner()
# Setup temporary configuration
- with NamedTemporaryFile(mode="w") as ssh_config:
+ # keep Windows from locking the file with delete=False
+ with NamedTemporaryFile(mode="w",delete=False) as ssh_config:
ssh_config.write(dedent("""\
Host test
Hostname test.example.com
@@ -489,8 +505,8 @@ def test_ssh_config(monkeypatch):
MockMyCli.connect_args["ssh_user"] == "joe" and \
MockMyCli.connect_args["ssh_host"] == "test.example.com" and \
MockMyCli.connect_args["ssh_port"] == 22222 and \
- MockMyCli.connect_args["ssh_key_filename"] == os.getenv(
- "HOME") + "/.ssh/gateway"
+ MockMyCli.connect_args["ssh_key_filename"] == os.path.expanduser(
+ "~") + "/.ssh/gateway"
# When a user supplies a ssh config host as argument to mycli,
# and used command line arguments, use the command line
@@ -512,6 +528,13 @@ 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"
+
+ # delete=False means we should try to clean up
+ try:
+ if os.path.exists(ssh_config.name):
+ os.remove(ssh_config.name)
+ except Exception as e:
+ print(f"An error occurred while attempting to delete the file: {e}")
@dbtest
diff --git a/test/test_special_iocommands.py b/test/test_special_iocommands.py
index 8b6be33..d0ca45f 100644
--- a/test/test_special_iocommands.py
+++ b/test/test_special_iocommands.py
@@ -50,25 +50,49 @@ def test_editor_command():
os.environ['EDITOR'] = 'true'
os.environ['VISUAL'] = 'true'
- mycli.packages.special.open_external_editor(sql=r'select 1') == "select 1"
+ # Set the editor to Notepad on Windows
+ if os.name != 'nt':
+ mycli.packages.special.open_external_editor(sql=r'select 1') == "select 1"
+ else:
+ pytest.skip('Skipping on Windows platform.')
+
def test_tee_command():
mycli.packages.special.write_tee(u"hello world") # write without file set
- with tempfile.NamedTemporaryFile() as f:
+ # keep Windows from locking the file with delete=False
+ with tempfile.NamedTemporaryFile(delete=False) as f:
mycli.packages.special.execute(None, u"tee " + f.name)
mycli.packages.special.write_tee(u"hello world")
- assert f.read() == b"hello world\n"
+ if os.name=='nt':
+ assert f.read() == b"hello world\r\n"
+ else:
+ assert f.read() == b"hello world\n"
mycli.packages.special.execute(None, u"tee -o " + f.name)
mycli.packages.special.write_tee(u"hello world")
f.seek(0)
- assert f.read() == b"hello world\n"
+ if os.name=='nt':
+ assert f.read() == b"hello world\r\n"
+ else:
+ assert f.read() == b"hello world\n"
mycli.packages.special.execute(None, u"notee")
mycli.packages.special.write_tee(u"hello world")
f.seek(0)
- assert f.read() == b"hello world\n"
+ if os.name=='nt':
+ assert f.read() == b"hello world\r\n"
+ else:
+ assert f.read() == b"hello world\n"
+
+ # remove temp file
+ # delete=False means we should try to clean up
+ try:
+ if os.path.exists(f.name):
+ os.remove(f.name)
+ except Exception as e:
+ print(f"An error occurred while attempting to delete the file: {e}")
+
def test_tee_command_error():
@@ -82,6 +106,8 @@ def test_tee_command_error():
@dbtest
+
+@pytest.mark.skipif(os.name == "nt", reason="Bug: fails on Windows, needs fixing, singleton of FQ not working right")
def test_favorite_query():
with db_connection().cursor() as cur:
query = u'select "✔"'
@@ -98,16 +124,29 @@ def test_once_command():
mycli.packages.special.execute(None, u"\\once /proc/access-denied")
mycli.packages.special.write_once(u"hello world") # write without file set
- with tempfile.NamedTemporaryFile() as f:
+ # keep Windows from locking the file with delete=False
+ with tempfile.NamedTemporaryFile(delete=False) as f:
mycli.packages.special.execute(None, u"\\once " + f.name)
mycli.packages.special.write_once(u"hello world")
- assert f.read() == b"hello world\n"
+ if os.name=='nt':
+ assert f.read() == b"hello world\r\n"
+ else:
+ assert f.read() == b"hello world\n"
mycli.packages.special.execute(None, u"\\once -o " + f.name)
mycli.packages.special.write_once(u"hello world line 1")
mycli.packages.special.write_once(u"hello world line 2")
f.seek(0)
- assert f.read() == b"hello world line 1\nhello world line 2\n"
+ if os.name=='nt':
+ assert f.read() == b"hello world line 1\r\nhello world line 2\r\n"
+ else:
+ assert f.read() == b"hello world line 1\nhello world line 2\n"
+ # delete=False means we should try to clean up
+ try:
+ if os.path.exists(f.name):
+ os.remove(f.name)
+ except Exception as e:
+ print(f"An error occurred while attempting to delete the file: {e}")
def test_pipe_once_command():
@@ -118,9 +157,14 @@ def test_pipe_once_command():
mycli.packages.special.execute(
None, u"\\pipe_once /proc/access-denied")
- mycli.packages.special.execute(None, u"\\pipe_once wc")
- mycli.packages.special.write_once(u"hello world")
- mycli.packages.special.unset_pipe_once_if_written()
+ if os.name == 'nt':
+ mycli.packages.special.execute(None, u'\\pipe_once python -c "import sys; print(len(sys.stdin.read().strip()))"')
+ mycli.packages.special.write_once(u"hello world")
+ mycli.packages.special.unset_pipe_once_if_written()
+ else:
+ mycli.packages.special.execute(None, u"\\pipe_once wc")
+ mycli.packages.special.write_once(u"hello world")
+ mycli.packages.special.unset_pipe_once_if_written()
# how to assert on wc output?
@@ -128,12 +172,21 @@ def test_parseargfile():
"""Test that parseargfile expands the user directory."""
expected = {'file': os.path.join(os.path.expanduser('~'), 'filename'),
'mode': 'a'}
- assert expected == mycli.packages.special.iocommands.parseargfile(
- '~/filename')
+
+ if os.name=='nt':
+ assert expected == mycli.packages.special.iocommands.parseargfile(
+ '~\\filename')
+ else:
+ assert expected == mycli.packages.special.iocommands.parseargfile(
+ '~/filename')
expected = {'file': os.path.join(os.path.expanduser('~'), 'filename'),
'mode': 'w'}
- assert expected == mycli.packages.special.iocommands.parseargfile(
+ if os.name=='nt':
+ assert expected == mycli.packages.special.iocommands.parseargfile(
+ '-o ~\\filename')
+ else:
+ assert expected == mycli.packages.special.iocommands.parseargfile(
'-o ~/filename')
@@ -162,6 +215,7 @@ def test_watch_query_iteration():
@dbtest
+@pytest.mark.skipif(os.name == "nt", reason="Bug: Win handles this differently. May need to refactor watch_query to work for Win")
def test_watch_query_full():
"""Test that `watch_query`:
diff --git a/test/test_sqlexecute.py b/test/test_sqlexecute.py
index 163c850..ca186bc 100644
--- a/test/test_sqlexecute.py
+++ b/test/test_sqlexecute.py
@@ -117,6 +117,7 @@ def test_multiple_queries_same_line_syntaxerror(executor):
@dbtest
+@pytest.mark.skipif(os.name == "nt", reason="Bug: fails on Windows, needs fixing, singleton of FQ not working right")
def test_favorite_query(executor):
set_expanded_output(False)
run(executor, "create table test(a text)")
@@ -136,6 +137,7 @@ def test_favorite_query(executor):
@dbtest
+@pytest.mark.skipif(os.name == "nt", reason="Bug: fails on Windows, needs fixing, singleton of FQ not working right")
def test_favorite_query_multiple_statement(executor):
set_expanded_output(False)
run(executor, "create table test(a text)")
@@ -159,6 +161,7 @@ def test_favorite_query_multiple_statement(executor):
@dbtest
+@pytest.mark.skipif(os.name == "nt", reason="Bug: fails on Windows, needs fixing, singleton of FQ not working right")
def test_favorite_query_expanded_output(executor):
set_expanded_output(False)
run(executor, '''create table test(a text)''')
@@ -195,16 +198,21 @@ def test_cd_command_without_a_folder_name(executor):
@dbtest
def test_system_command_not_found(executor):
results = run(executor, 'system xyz')
- assert_result_equal(results, status='OSError: No such file or directory',
- assert_contains=True)
+ if os.name=='nt':
+ assert_result_equal(results, status='OSError: The system cannot find the file specified',
+ assert_contains=True)
+ else:
+ assert_result_equal(results, status='OSError: No such file or directory',
+ assert_contains=True)
@dbtest
def test_system_command_output(executor):
+ eol = os.linesep
test_dir = os.path.abspath(os.path.dirname(__file__))
test_file_path = os.path.join(test_dir, 'test.txt')
results = run(executor, 'system cat {0}'.format(test_file_path))
- assert_result_equal(results, status='mycli rocks!\n')
+ assert_result_equal(results, status=f'mycli rocks!{eol}')
@dbtest