Skip to content

Commit e7bc88f

Browse files
committed
deprecate connection settings in myclirc [main]
* deprecate main.default_character_set, with a notice to move the setting to the [connection] section * deprecate main.ssl_mode, with a notice to move the setting to connection.default_ssl_mode These deprecation notices will affect a modest number of users who installed mycli for the first time during the periods in which the given connection-level settings were in [main] in the default myclirc file. For default_ssl_mode, that is fresh installs between 2026-01-02 and 2026-02-09. For default_character_set, that is fresh installs between 2026-01-22 and 2026-02-02. Users who ran "mycli --checkup" since then were already advised to migrate the settings to the [connection] section. While the notices are in red, and printed on every execution of mycli, respecting of the deprecated settings in [main] still works, iff the given setting under [main] has a non-blank value. The --checkup instructions for migrating the settings are not removed, though they are somewhat duplicative, to keep the checkup instructions more coherent. Motivation: general simplification; bundling all breaking changes into the 2.0 release. The logic for determining whether the user or package configuration controls is too subtle when there are multiple possible locations for the setting. Preparation for release 2.0
1 parent be011eb commit e7bc88f

8 files changed

Lines changed: 104 additions & 25 deletions

File tree

changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Breaking Changes
1010
* Remove support for deprecated SSH jump functionality.
1111
* Remove support for `my.cnf` vendor MySQL option files.
1212
* Remove support for `.myclirc` files in the current working directory.
13+
* Deprecate `default_character_set` in `[main]` section of `~/.myclirc`.
14+
* Deprecate `ssl_mode` in `[main]` section of `~/.myclirc`.
1315

1416

1517
Documentation

mycli/app_state.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,25 @@
1111
from mycli.client import MyCli
1212

1313

14-
def normalize_ssl_mode(config: ConfigObj) -> tuple[str | None, str | None]:
15-
ssl_mode = config['main'].get('ssl_mode', None) or config['connection'].get('default_ssl_mode', None)
14+
def normalize_ssl_mode(
15+
config: ConfigObj,
16+
config_without_package_defaults: ConfigObj,
17+
) -> tuple[str | None, str | None]:
18+
error_notice: str | None = None
19+
ssl_mode: str | None = None
20+
if 'main' in config_without_package_defaults and 'ssl_mode' in config_without_package_defaults['main']:
21+
# deprecation notice added with mycli 2.0.0 in 2026-07
22+
# todo: entirely remove support for ssl_mode in [main]
23+
error_notice = (
24+
'Mycli 2.0 deprecation notice: please migrate ssl_mode under [main] to default_ssl_mode under [connection] in ~/.myclirc .'
25+
)
26+
ssl_mode = config_without_package_defaults['main']['ssl_mode']
27+
if not ssl_mode and 'default_ssl_mode' in config['connection']:
28+
ssl_mode = config['connection']['default_ssl_mode']
1629
if ssl_mode not in ('auto', 'on', 'off', None):
17-
return None, f'Invalid config option provided for ssl_mode ({ssl_mode}); ignoring.'
18-
return ssl_mode, None
30+
error_notice = f'Invalid config option provided for ssl_mode ({ssl_mode}); ignoring.'
31+
return None, error_notice
32+
return ssl_mode, error_notice
1933

2034

2135
def configure_prompt_state(

mycli/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def __init__(
132132
self.binary_display = c['main'].get('binary_display')
133133
self.llm_prompt_field_truncate, self.llm_prompt_section_truncate = llm_prompt_truncation(c)
134134

135-
self.ssl_mode, ssl_mode_error = normalize_ssl_mode(c)
135+
self.ssl_mode, ssl_mode_error = normalize_ssl_mode(c, self.config_without_package_defaults)
136136
if ssl_mode_error:
137137
self.echo(ssl_mode_error, err=True, fg="red")
138138

mycli/client_connection.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,18 @@ def connect(
7676

7777
passwd = passwd if isinstance(passwd, (str, int)) else mylogin_cnf["password"]
7878

79-
# default_character_set doesn't check in self.config_without_package_defaults, because the
80-
# option already existed before the my.cnf deprecation. For the same reason,
81-
# default_character_set can be in [connection] or [main].
8279
if not character_set:
83-
if 'default_character_set' in self.config['connection']:
80+
if 'main' in self.config_without_package_defaults and 'default_character_set' in self.config_without_package_defaults['main']:
81+
# deprecation notice added with mycli 2.0.0 in 2026-07
82+
# todo: entirely remove support for default_character_set in [main]
83+
click.secho(
84+
'Mycli 2.0 deprecation notice: please migrate default_character_set from [main] to [connection] in ~/.myclirc .',
85+
err=True,
86+
fg='red',
87+
)
88+
character_set = self.config_without_package_defaults['main']['default_character_set']
89+
if not character_set and 'default_character_set' in self.config['connection']:
8490
character_set = self.config['connection']['default_character_set']
85-
elif 'default_character_set' in self.config['main']:
86-
character_set = self.config['main']['default_character_set']
8791
if not character_set:
8892
character_set = DEFAULT_CHARSET
8993

test/pytests/test_app_state.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,44 @@ def __init__(self, login_path: str | None = None) -> None:
1818

1919
@pytest.mark.parametrize('ssl_mode', ['auto', 'on', 'off'])
2020
def test_normalize_ssl_mode_accepts_known_values(ssl_mode: str) -> None:
21-
config = ConfigObj({'main': {'ssl_mode': ssl_mode}, 'connection': {'default_ssl_mode': 'off'}})
21+
config = ConfigObj({'main': {'ssl_mode': ssl_mode}, 'connection': {'default_ssl_mode': ssl_mode}})
22+
config_wo = ConfigObj({'main': {}, 'connection': {}})
2223

23-
assert normalize_ssl_mode(config) == (ssl_mode, None)
24+
assert normalize_ssl_mode(config, config_wo) == (ssl_mode, None)
2425

2526

2627
def test_normalize_ssl_mode_falls_back_to_connection_default() -> None:
2728
config = ConfigObj({'main': {'ssl_mode': ''}, 'connection': {'default_ssl_mode': 'on'}})
29+
config_wo = ConfigObj({'main': {}, 'connection': {}})
2830

29-
assert normalize_ssl_mode(config) == ('on', None)
31+
assert normalize_ssl_mode(config, config_wo) == ('on', None)
32+
33+
34+
def test_normalize_ssl_mode_prefers_deprecated_main_value() -> None:
35+
config = ConfigObj({'main': {}, 'connection': {'default_ssl_mode': 'on'}})
36+
config_wo = ConfigObj({'main': {'ssl_mode': 'auto'}, 'connection': {}})
37+
38+
ssl_mode, warning = normalize_ssl_mode(config, config_wo)
39+
40+
assert ssl_mode == 'auto'
41+
assert (
42+
warning
43+
== 'Mycli 2.0 deprecation notice: please migrate ssl_mode under [main] to default_ssl_mode under [connection] in ~/.myclirc .'
44+
)
45+
46+
47+
def test_normalize_ssl_mode_returns_none_when_not_configured() -> None:
48+
config = ConfigObj({'main': {}, 'connection': {}})
49+
config_wo = ConfigObj({'main': {}, 'connection': {}})
50+
51+
assert normalize_ssl_mode(config, config_wo) == (None, None)
3052

3153

3254
def test_normalize_ssl_mode_reports_invalid_values() -> None:
33-
config = ConfigObj({'main': {'ssl_mode': 'required'}, 'connection': {'default_ssl_mode': 'off'}})
55+
config = ConfigObj({'main': {'ssl_mode': 'required'}, 'connection': {'default_ssl_mode': 'required'}})
56+
config_wo = ConfigObj()
3457

35-
ssl_mode, warning = normalize_ssl_mode(config)
58+
ssl_mode, warning = normalize_ssl_mode(config, config_wo)
3659

3760
assert ssl_mode is None
3861
assert warning == 'Invalid config option provided for ssl_mode (required); ignoring.'

test/pytests/test_checkup.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ def test_configuration_checkup_reports_missing_unsupported_and_deprecated(capsys
133133
'main': {
134134
'present': '',
135135
'unsupported_item': '',
136-
'default_character_set': '',
137136
},
138137
'unsupported_section': {
139138
'anything': '',
@@ -162,9 +161,6 @@ def test_configuration_checkup_reports_missing_unsupported_and_deprecated(capsys
162161
assert '### Unsupported in user ~/.myclirc:' in output
163162
assert 'The entire section:\n\n [unsupported_section]\n' in output
164163
assert 'The item:\n\n [main]\n unsupported_item =' in output
165-
assert '### Deprecated in user ~/.myclirc:' in output
166-
assert ' [main]\n default_character_set' in output
167-
assert ' [connection]\n default_character_set' in output
168164
assert f'{checkup.REPO_URL}/blob/main/mycli/myclirc' in output
169165

170166

@@ -200,10 +196,33 @@ def test_configuration_checkup_skips_transitioned_and_free_entry_items(capsys) -
200196
assert 'The entire section:\n\n [extra_section]\n' in output
201197
assert 'Unsupported in user ~/.myclirc:' in output
202198
assert 'The entire section:\n\n [unsupported_section]\n' in output
203-
assert '[connection]\n default_character_set =' not in output
204199
assert '[favorite_queries]' not in output
205200

206201

202+
def test_configuration_checkup_reports_deprecated_transition(capsys) -> None:
203+
mycli = SimpleNamespace(
204+
config={
205+
'main': {},
206+
},
207+
config_without_package_defaults={
208+
'main': {
209+
'ssl_mode': '',
210+
},
211+
},
212+
config_without_user_options={
213+
'main': {},
214+
},
215+
)
216+
217+
checkup._configuration_checkup(mycli)
218+
output = capsys.readouterr().out
219+
220+
assert '### Deprecated in user ~/.myclirc:' in output
221+
assert 'It is recommended to transition:\n\n [main]\n ssl_mode\n\nto\n\n [connection]\n default_ssl_mode' in output
222+
assert '### Unsupported in user ~/.myclirc:' not in output
223+
assert f'{checkup.REPO_URL}/blob/main/mycli/myclirc' in output
224+
225+
207226
def test_configuration_checkup_up_to_date(capsys) -> None:
208227
mycli = SimpleNamespace(
209228
config={

test/pytests/test_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def test_init_reports_invalid_ssl_mode(monkeypatch: pytest.MonkeyPatch, tmp_path
3131
myclirc = write_myclirc(
3232
tmp_path,
3333
"""
34-
[main]
35-
ssl_mode = invalid
34+
[connection]
35+
default_ssl_mode = invalid
3636
""",
3737
)
3838

test/pytests/test_client_connection.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,29 @@ def test_connect_uses_character_set_from_connection_config() -> None:
148148
assert FakeSQLExecute.calls[-1]['character_set'] == 'utf16'
149149

150150

151-
def test_connect_uses_character_set_from_main_config() -> None:
152-
client = DummyClient(config={'main': {'default_character_set': 'utf32'}, 'connection': {}})
151+
def test_connect_uses_deprecated_character_set_from_main_config(
152+
monkeypatch: pytest.MonkeyPatch,
153+
) -> None:
154+
client = DummyClient(
155+
config={'main': {}, 'connection': {}},
156+
config_without_package_defaults={'main': {'default_character_set': 'utf32'}},
157+
)
158+
secho_calls: list[tuple[str, dict[str, Any]]] = []
159+
monkeypatch.setattr(
160+
client_connection.click,
161+
'secho',
162+
lambda message, **kwargs: secho_calls.append((message, kwargs)),
163+
)
153164

154165
client.connect(host='db', port=3307)
155166

156167
assert FakeSQLExecute.calls[-1]['character_set'] == 'utf32'
168+
assert secho_calls == [
169+
(
170+
'Mycli 2.0 deprecation notice: please migrate default_character_set from [main] to [connection] in ~/.myclirc .',
171+
{'err': True, 'fg': 'red'},
172+
)
173+
]
157174

158175

159176
def test_connect_uses_default_character_set_when_none_configured() -> None:

0 commit comments

Comments
 (0)