Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,45 @@ jobs:
run: |
uv run tox -e py${{ matrix.python-version }}

tests-windows:
name: Tests Windows
runs-on: windows-latest

strategy:
fail-fast: false
matrix:
python-version: ['3.14']

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: 'latest'

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
shell: cmd
run: uv sync --all-extras -p ${{ matrix.python-version }}

- name: Set up MySQL
uses: shogo82148/actions-setup-mysql@c80f44ab210a360ef966c5b9f48a2ae21123b533 # v1.51.0
with:
mysql-version: '9.7'
root-password: root

- name: Pytest / behave
env:
PYTEST_PASSWORD: root
PYTEST_HOST: 127.0.0.1
run: |
uv run -- coverage run -m pytest
uv run -- coverage report -m --sort=Miss --skip-covered --skip-empty

test-no-extras:
name: Tests Without Extras
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Internal
* Factor `main.py` into several files using mixins.
* Update Python versions used in CI.
* Add CI on macOS.
* Add limited CI on Windows.


1.73.1 (2026/05/29)
Expand Down
3 changes: 3 additions & 0 deletions test/pytests/test_filepaths.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def load_filepaths_variant(
return module


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_default_socket_dirs_import_variants(monkeypatch: pytest.MonkeyPatch) -> None:
darwin = load_filepaths_variant(monkeypatch, os_name='posix', system_name='Darwin')
assert darwin.DEFAULT_SOCKET_DIRS == ['/tmp']
Expand Down Expand Up @@ -63,6 +64,7 @@ def test_complete_path_and_parse_path() -> None:
assert filepaths.parse_path('/tmp/dir/') == ('/tmp/dir', '', 0)


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_suggest_path_branches(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.chdir(tmp_path)
(tmp_path / 'query.sql').write_text('select 1\n', encoding='utf-8')
Expand Down Expand Up @@ -98,6 +100,7 @@ def test_dir_path_exists(tmp_path: Path) -> None:
assert filepaths.dir_path_exists(str(tmp_path / 'missing' / 'mycli.log')) is False


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_guess_socket_location_returns_matching_socket(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(filepaths, 'DEFAULT_SOCKET_DIRS', ['/a', '/b'])
monkeypatch.setattr(filepaths.os.path, 'exists', lambda path: path == '/b')
Expand Down
4 changes: 4 additions & 0 deletions test/pytests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@


@dbtest
@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown; try running the test suite under winpty')
def test_binary_display_hex(executor):
m = MyCli()
m.sqlexecute = SQLExecute(
Expand Down Expand Up @@ -122,6 +123,7 @@ def test_binary_display_hex(executor):


@dbtest
@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_binary_display_utf8(executor):
m = MyCli()
m.sqlexecute = SQLExecute(
Expand Down Expand Up @@ -836,6 +838,7 @@ def test_list_dsn(monkeypatch):
print(f"An error occurred while attempting to delete the file: {e}")


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_list_ssh_config():
runner = CliRunner()
# keep Windows from locking the file with delete=False
Expand Down Expand Up @@ -1893,6 +1896,7 @@ def run_query(self, query, new_line=True):
)


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_ssh_config(monkeypatch):
# Setup classes to mock mycli.main.MyCli
class Formatter:
Expand Down
3 changes: 3 additions & 0 deletions test/pytests/test_main_modes_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def test_replay_checkpoint_file_rejects_checkpoint_longer_than_batch(tmp_path: P
batch_mode.replay_checkpoint_file(batch_path, checkpoint, resume=True)


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_replay_checkpoint_file_rejects_batch_read_error(monkeypatch, tmp_path: Path) -> None:
batch_path = write_batch_file(tmp_path, 'select 1;\n')

Expand All @@ -187,6 +188,7 @@ def test_replay_checkpoint_file_rejects_batch_read_error(monkeypatch, tmp_path:
batch_mode.replay_checkpoint_file(batch_path, checkpoint, resume=True)


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_replay_checkpoint_file_rejects_batch_iteration_error(monkeypatch, tmp_path: Path) -> None:
batch_path = write_batch_file(tmp_path, 'select 1;\n')

Expand All @@ -206,6 +208,7 @@ def fake_statements_from_filehandle(handle):
batch_mode.replay_checkpoint_file(batch_path, checkpoint, resume=True)


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_replay_checkpoint_file_rejects_checkpoint_read_error(monkeypatch, tmp_path: Path) -> None:
batch_path = write_batch_file(tmp_path, 'select 1;\n')

Expand Down
3 changes: 3 additions & 0 deletions test/pytests/test_main_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ def fake_prompt(message: str, **kwargs: Any) -> str:
main.MyCli.connect(cli, host='db', port='bad-port')


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_connect_socket_owner_and_tcp_fallback(monkeypatch: pytest.MonkeyPatch) -> None:
cli = make_bare_mycli()
cli.my_cnf = {'client': {}, 'mysqld': {}}
Expand Down Expand Up @@ -565,6 +566,7 @@ class SocketThenTcpSQLExecute(RecordingSQLExecute):
assert len(SocketThenTcpSQLExecute.calls) == 2


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_connect_additional_error_and_config_branches(monkeypatch: pytest.MonkeyPatch) -> None:
cli = make_bare_mycli()
cli.config = {'connection': {'default_ssl_ca_path': '/tmp/ca-path'}, 'main': {}}
Expand Down Expand Up @@ -1153,6 +1155,7 @@ def test_click_entrypoint_branches_with_dummy_mycli(monkeypatch: pytest.MonkeyPa
assert dummy.run_query_calls[-1][0] == 'select 1'


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_click_entrypoint_password_file_and_dsn_early_branches(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
runner = CliRunner()
dummy_class = make_dummy_mycli_class(config={'main': {}, 'alias_dsn': {}, 'connection': {'default_keepalive_ticks': 0}})
Expand Down
1 change: 1 addition & 0 deletions test/pytests/test_smart_completion_public_schema_only.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,7 @@ def dummy_list_path(dir_name):
("source /dir1/subdir1/", [("lastfile.sql", 0)]),
],
)
@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_file_name_completion(completer, complete_event, text, expected):
position = len(text)
special.register_special_command(
Expand Down
4 changes: 2 additions & 2 deletions test/pytests/test_special_iocommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,9 +364,9 @@ def test_watch_query_full():
expected_value = "1"
query = f"SELECT {expected_value}"
expected_preamble = f"> {query}"
# Python 3.14 is skipping ahead to 6 or 7
# Python 3.14 is skipping ahead to 6, 7, or even 8 on Mac and Windows
# Python 3.11 is as slow as 3
expected_results = [3, 4, 5, 6, 7]
expected_results = [3, 4, 5, 6, 7, 8]
ctrl_c_process = send_ctrl_c(wait_interval)
with db_connection().cursor() as cur:
results = list(mycli.packages.special.iocommands.watch_query(arg=f"{watch_seconds} {query}", cur=cur))
Expand Down
1 change: 1 addition & 0 deletions test/pytests/test_special_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def test_handle_cd_command_requires_exactly_one_directory() -> None:
assert message == 'Exactly one directory name must be provided.'


@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_handle_cd_command_changes_directory_and_echoes_cwd(monkeypatch) -> None:
echoed = []

Expand Down
1 change: 1 addition & 0 deletions test/pytests/test_sqlexecute.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ def test_cd_command_without_a_folder_name(executor):


@dbtest
@pytest.mark.skipif(os.name == 'nt', reason='todo: unknown')
def test_cd_command_with_one_nonexistent_folder_name(executor):
results = run(executor, 'system cd nonexistent_folder_name')
assert_result_equal(results, status='No such file or directory', status_plain='No such file or directory')
Expand Down